mirror of
https://git.citron-emu.org/Citron/Citron.git
synced 2025-03-15 03:14:50 +00:00
Compare commits
139 commits
v0.4-canar
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
21594b73aa | ||
|
d869045b77 | ||
|
f2931c7566 | ||
|
12c63997d2 | ||
|
1023125be5 | ||
|
dad8859679 | ||
|
834cc89548 | ||
|
38b259d099 | ||
|
e7e9453667 | ||
|
ae75413cc3 | ||
|
6a31da5905 | ||
|
a5125d008a | ||
|
b24dd921aa | ||
|
9a65205dba | ||
|
af4f08be33 | ||
|
0d0963d32f | ||
|
4491127f52 | ||
|
c304afe2b3 | ||
|
b8240b4214 | ||
|
91487f6d96 | ||
|
031c635095 | ||
|
90a8165f77 | ||
|
6565055865 | ||
|
ee3d858935 | ||
|
31694994f2 | ||
|
4197fa84a0 | ||
|
e4342324fe | ||
|
78b0080b96 | ||
|
644ed69285 | ||
|
3554f55fc9 | ||
|
dc9532b4d1 | ||
|
1308e2b935 | ||
|
5caecd8151 | ||
|
dc9fbcc893 | ||
|
b1d5d4e5be | ||
|
f0d8daf755 | ||
|
cbb9a35166 | ||
|
cfe437aacf | ||
|
9b293c3a98 | ||
|
84e5fbc089 | ||
|
a442078ee4 | ||
|
cc610ad9b6 | ||
|
5a65f9a094 | ||
|
5ca1f0e365 | ||
|
a36baad0f0 | ||
|
ed115d3f72 | ||
|
d9619b7eed | ||
|
dbe5bf1d18 | ||
|
7903415fa4 | ||
|
3bb4d97e9e | ||
|
a41f7b7a56 | ||
|
18f8a0f997 | ||
|
4d50d2ba16 | ||
|
0576d40bf0 | ||
|
6917530ba5 | ||
|
43495b6045 | ||
|
c5e480e55d | ||
|
1c9e17496b | ||
|
7730d14b4a | ||
|
677b8f476a | ||
|
5cbde61d3c | ||
|
33a1996ca4 | ||
|
a7af4d001b | ||
|
ef884ce39c | ||
|
1aad9fd4e3 | ||
|
f45f339ef9 | ||
|
298e797592 | ||
|
8bfafb4755 | ||
|
33d54e595f | ||
|
13ada2d705 | ||
|
8bf4660bac | ||
|
b07751ed43 | ||
|
b3c60b4cbe | ||
|
dcf6f9a071 | ||
|
b42a0fb227 | ||
|
5af4803e42 | ||
|
becaf850ab | ||
|
d4ad55ed21 | ||
|
6e16a8db1c | ||
|
384a18927b | ||
|
76716b5248 | ||
|
6917a22a2c | ||
|
646af3c143 | ||
|
d1b7aebe8c | ||
|
d783806b1e | ||
|
268d322d7f | ||
|
92b70b31e0 | ||
|
4792ba752e | ||
|
b8fe6b6f7c | ||
|
0acfbc5fa1 | ||
|
e3128c6e98 | ||
|
b89a85e228 | ||
|
cc48197448 | ||
|
0010882f36 | ||
|
28350f7af8 | ||
|
7ecb890a16 | ||
|
c31768ec15 | ||
|
227db142e2 | ||
|
3aa9c0d151 | ||
|
7b6495aced | ||
|
d4eca46bba | ||
|
df1ae19742 | ||
|
4cc01f6c71 | ||
|
89ecb641f1 | ||
|
3857e6afe9 | ||
|
42f44a0c09 | ||
|
94c4ef8946 | ||
|
14065ae7cb | ||
|
9eb32d2d85 | ||
|
71e652123b | ||
|
ddd5e7e887 | ||
|
6b9c239fbd | ||
|
cf43fd8038 | ||
|
a1cbcee7ab | ||
|
19ce9d695e | ||
|
44944c4d80 | ||
|
8bda64895f | ||
|
f4b9e54b22 | ||
|
70a9f20ae1 | ||
|
076d0e618d | ||
|
ecc32958ec | ||
|
e8bbdbce42 | ||
|
0216eaa071 | ||
|
137034ca2c | ||
|
8f76ef2579 | ||
|
4e8d00f034 | ||
|
f638922129 | ||
|
a96216ff35 | ||
|
6ab82e8eeb | ||
|
733721f0a1 | ||
|
613099703a | ||
|
9a3d4f0489 | ||
|
8c630a8bea | ||
|
2e4db14bc1 | ||
|
c36151d6e3 | ||
|
33f8cd0c7e | ||
|
c5a2689cef | ||
|
f380744c61 | ||
|
b7e11d3724 |
319 changed files with 5533 additions and 862 deletions
12
.gitmodules
vendored
12
.gitmodules
vendored
|
@ -9,22 +9,22 @@
|
|||
url = https://github.com/mozilla/cubeb.git
|
||||
[submodule "dynarmic"]
|
||||
path = externals/dynarmic
|
||||
url = https://github.com/yuzu-mirror/dynarmic.git
|
||||
url = https://git.citron-emu.org/Citron/dynarmic.git
|
||||
[submodule "libusb"]
|
||||
path = externals/libusb/libusb
|
||||
url = https://github.com/libusb/libusb.git
|
||||
[submodule "discord-rpc"]
|
||||
path = externals/discord-rpc
|
||||
url = https://github.com/yuzu-mirror/discord-rpc.git
|
||||
url = https://git.citron-emu.org/Citron/discord-rpc.git
|
||||
[submodule "Vulkan-Headers"]
|
||||
path = externals/Vulkan-Headers
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
[submodule "sirit"]
|
||||
path = externals/sirit
|
||||
url = https://github.com/yuzu-mirror/sirit.git
|
||||
url = https://git.citron-emu.org/Citron/sirit.git
|
||||
[submodule "mbedtls"]
|
||||
path = externals/mbedtls
|
||||
url = https://github.com/yuzu-mirror/mbedtls.git
|
||||
url = https://git.citron-emu.org/Citron/mbedtls.git
|
||||
[submodule "xbyak"]
|
||||
path = externals/xbyak
|
||||
url = https://github.com/herumi/xbyak.git
|
||||
|
@ -57,13 +57,13 @@
|
|||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||
[submodule "breakpad"]
|
||||
path = externals/breakpad
|
||||
url = https://github.com/yuzu-mirror/breakpad.git
|
||||
url = https://git.citron-emu.org/Citron/breakpad.git
|
||||
[submodule "simpleini"]
|
||||
path = externals/simpleini
|
||||
url = https://github.com/brofield/simpleini.git
|
||||
[submodule "oaknut"]
|
||||
path = externals/oaknut
|
||||
url = https://github.com/yuzu-mirror/oaknut
|
||||
url = https://git.citron-emu.org/Citron/oaknut.git
|
||||
[submodule "Vulkan-Utility-Libraries"]
|
||||
path = externals/Vulkan-Utility-Libraries
|
||||
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
|
||||
|
|
114
CMakeLists.txt
114
CMakeLists.txt
|
@ -17,6 +17,45 @@ if (MSVC)
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-")
|
||||
endif()
|
||||
|
||||
# PGO Configuration
|
||||
option(CITRON_ENABLE_PGO_INSTRUMENT "Enable Profile-Guided Optimization instrumentation build" OFF)
|
||||
option(CITRON_ENABLE_PGO_OPTIMIZE "Enable Profile-Guided Optimization optimization build" OFF)
|
||||
|
||||
if(MSVC)
|
||||
if(CITRON_ENABLE_PGO_INSTRUMENT)
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " /GL /LTCG:PGINSTRUMENT")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG:PGINSTRUMENT")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG:PGINSTRUMENT")
|
||||
elseif(CITRON_ENABLE_PGO_OPTIMIZE)
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " /GL /LTCG:PGOPTIMIZE")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG:PGOPTIMIZE")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG:PGOPTIMIZE")
|
||||
endif()
|
||||
else()
|
||||
# GCC and Clang PGO flags
|
||||
if(CITRON_ENABLE_PGO_INSTRUMENT)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||
else() # GCC
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-generate")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-generate")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-generate")
|
||||
endif()
|
||||
elseif(CITRON_ENABLE_PGO_OPTIMIZE)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||
else() # GCC
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-use")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-use")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-use")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check if SDL2::SDL2 target exists; if not, create an alias
|
||||
if (TARGET SDL2::SDL2-static)
|
||||
add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static)
|
||||
|
@ -98,21 +137,22 @@ endif()
|
|||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||
|
||||
if (ANDROID AND CITRON_DOWNLOAD_ANDROID_VVL)
|
||||
set(vvl_version "sdk-1.3.261.1")
|
||||
set(vvl_version "1.4.304.1")
|
||||
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
|
||||
if (NOT EXISTS "${vvl_zip_file}")
|
||||
# Download and extract validation layer release to externals directory
|
||||
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
|
||||
file(DOWNLOAD "${vvl_base_url}/${vvl_version}/android-binaries-${vvl_version}-android.zip"
|
||||
"${vvl_zip_file}" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||
endif()
|
||||
|
||||
# Copy the arm64 binary to src/android/app/main/jniLibs only if it doesn't exist
|
||||
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")
|
||||
set(vvl_lib_file "${vvl_lib_path}/libVkLayer_khronos_validation.so")
|
||||
if (NOT EXISTS "${vvl_lib_file}")
|
||||
set(vvl_final_lib "${vvl_lib_path}/libVkLayer_khronos_validation.so")
|
||||
|
||||
if (NOT EXISTS "${vvl_final_lib}")
|
||||
# Download and extract validation layer release to externals directory
|
||||
if (NOT EXISTS "${vvl_zip_file}")
|
||||
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
|
||||
file(DOWNLOAD "${vvl_base_url}/vulkan-sdk-${vvl_version}/android-binaries-${vvl_version}.zip"
|
||||
"${vvl_zip_file}" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||
endif()
|
||||
|
||||
# Copy the arm64 binary to src/android/app/main/jniLibs
|
||||
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
|
||||
DESTINATION "${vvl_lib_path}")
|
||||
endif()
|
||||
|
@ -129,22 +169,29 @@ if (CITRON_USE_BUNDLED_VCPKG)
|
|||
|
||||
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
||||
set(VCPKG_TARGET_TRIPLET "arm64-android")
|
||||
set(VCPKG_HOST_TRIPLET "x64-windows")
|
||||
# this is to avoid CMake using the host pkg-config to find the host
|
||||
# libraries when building for Android targets
|
||||
set(PKG_CONFIG_EXECUTABLE "aarch64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
||||
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
|
||||
set(VCPKG_TARGET_TRIPLET "x64-android")
|
||||
set(VCPKG_HOST_TRIPLET "x64-windows")
|
||||
set(PKG_CONFIG_EXECUTABLE "x86_64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported Android architecture ${CMAKE_ANDROID_ARCH_ABI}")
|
||||
endif()
|
||||
|
||||
# Add these lines to ensure proper Android toolchain setup
|
||||
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${ANDROID_NDK}/build/cmake/android.toolchain.cmake")
|
||||
set(VCPKG_CRT_LINKAGE "dynamic")
|
||||
set(VCPKG_LIBRARY_LINKAGE "static")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
|
||||
set(NASM_VERSION "2.16.01")
|
||||
set(NASM_VERSION "2.16.03")
|
||||
set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
|
||||
set(NASM_DOWNLOAD_URL "https://github.com/yuzu-mirror/ext-windows-bin/raw/master/nasm/nasm-${NASM_VERSION}-win64.zip")
|
||||
set(NASM_DOWNLOAD_URL "https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/win64/nasm-${NASM_VERSION}-win64.zip")
|
||||
|
||||
if (NOT EXISTS ${NASM_DESTINATION_PATH})
|
||||
file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
|
||||
|
@ -231,7 +278,7 @@ endif()
|
|||
if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
||||
message(STATUS "Downloading compatibility list for citron...")
|
||||
file(DOWNLOAD
|
||||
https://api.yuzu-mirror.org/gamedb/
|
||||
https://api.citron-emu.org/gamedb/
|
||||
"${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS)
|
||||
endif()
|
||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
||||
|
@ -312,7 +359,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
|||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||
find_package(Boost REQUIRED context)
|
||||
find_package(enet MODULE)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(fmt 11 REQUIRED)
|
||||
if (CITRON_USE_LLVM_DEMANGLE)
|
||||
find_package(LLVM MODULE COMPONENTS Demangle)
|
||||
endif()
|
||||
|
@ -327,7 +374,7 @@ find_package(ZLIB REQUIRED)
|
|||
find_package(zstd REQUIRED)
|
||||
|
||||
if (NOT CITRON_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
find_package(VulkanHeaders 1.4.304 REQUIRED)
|
||||
find_package(VulkanHeaders 1.4.307 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (NOT CITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||
|
@ -335,19 +382,19 @@ if (NOT CITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
|||
endif()
|
||||
|
||||
if (ENABLE_LIBUSB)
|
||||
find_package(libusb 1.0.24 MODULE)
|
||||
find_package(libusb MODULE)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak 6 CONFIG)
|
||||
find_package(xbyak CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64)
|
||||
find_package(oaknut 2.0.1 CONFIG)
|
||||
find_package(oaknut CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
find_package(dynarmic 6.4.0 CONFIG)
|
||||
find_package(dynarmic CONFIG)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CUBEB)
|
||||
|
@ -359,12 +406,12 @@ if (USE_DISCORD_PRESENCE)
|
|||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(cpp-jwt 1.4 CONFIG)
|
||||
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
|
||||
find_package(cpp-jwt CONFIG)
|
||||
find_package(httplib MODULE COMPONENTS OpenSSL)
|
||||
endif()
|
||||
|
||||
if (CITRON_TESTS)
|
||||
find_package(Catch2 3.0.1 REQUIRED)
|
||||
find_package(Catch2 REQUIRED)
|
||||
endif()
|
||||
|
||||
# boost:asio has functions that require AcceptEx et al
|
||||
|
@ -373,11 +420,11 @@ if (MINGW)
|
|||
endif()
|
||||
|
||||
if(ENABLE_OPENSSL)
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(gamemode 1.7 MODULE)
|
||||
find_package(gamemode MODULE)
|
||||
endif()
|
||||
|
||||
# Please consider this as a stub
|
||||
|
@ -390,7 +437,7 @@ if (ENABLE_SDL2)
|
|||
if (CITRON_USE_BUNDLED_SDL2)
|
||||
# Detect toolchain and platform
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1920) AND ARCHITECTURE_x86_64)
|
||||
set(SDL2_VER "SDL2-2.28.2")
|
||||
set(SDL2_VER "SDL2-2.32.0")
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRON_USE_BUNDLED_SDL2 and provide your own.")
|
||||
endif()
|
||||
|
@ -416,10 +463,13 @@ endif()
|
|||
|
||||
add_subdirectory(externals)
|
||||
|
||||
if (USE_DISCORD_PRESENCE)
|
||||
target_compile_options(discord-rpc PRIVATE -fpermissive)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT)
|
||||
if (NOT USE_SYSTEM_QT)
|
||||
download_qt(6.7.3)
|
||||
download_qt(6.8.2)
|
||||
endif()
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent Network)
|
||||
|
@ -484,7 +534,7 @@ list(APPEND CITRON_QT_COMPONENTS2 Multimedia)
|
|||
endif()
|
||||
if (NOT CITRON_USE_BUNDLED_FFMPEG)
|
||||
# Use system installed FFmpeg
|
||||
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
find_package(FFmpeg REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
endif()
|
||||
|
||||
if(ENABLE_QT)
|
||||
|
@ -534,7 +584,7 @@ endif()
|
|||
# against all the src files. This should be used before making a pull request.
|
||||
# =======================================================================
|
||||
|
||||
set(CLANG_FORMAT_POSTFIX "-15")
|
||||
set(CLANG_FORMAT_POSTFIX "-18")
|
||||
find_program(CLANG_FORMAT
|
||||
NAMES clang-format${CLANG_FORMAT_POSTFIX}
|
||||
clang-format
|
||||
|
@ -545,7 +595,7 @@ if (NOT CLANG_FORMAT)
|
|||
message(STATUS "Clang format not found! Downloading...")
|
||||
set(CLANG_FORMAT "${PROJECT_BINARY_DIR}/externals/clang-format${CLANG_FORMAT_POSTFIX}.exe")
|
||||
file(DOWNLOAD
|
||||
https://github.com/yuzu-mirror/ext-windows-bin/raw/master/clang-format${CLANG_FORMAT_POSTFIX}.exe
|
||||
https://git.citron-emu.org/Citron/ext-windows-bin/raw/master/clang-format${CLANG_FORMAT_POSTFIX}.exe
|
||||
"${CLANG_FORMAT}" SHOW_PROGRESS
|
||||
STATUS DOWNLOAD_SUCCESS)
|
||||
if (NOT DOWNLOAD_SUCCESS EQUAL 0)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
set(CURRENT_MODULE_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
function(download_bundled_external remote_path lib_name prefix_var)
|
||||
|
||||
set(package_base_url "https://github.com/yuzu-mirror/")
|
||||
set(package_base_url "https://git.citron-emu.org/Citron/")
|
||||
set(package_repo "no_platform")
|
||||
set(package_extension "no_platform")
|
||||
if (WIN32)
|
||||
|
@ -68,18 +68,18 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out
|
|||
set(arch_path "mingw_64")
|
||||
elseif (MSVC)
|
||||
if ("arm64" IN_LIST ARCHITECTURE)
|
||||
set(arch_path "msvc2019_arm64")
|
||||
set(arch_path "msvc2022_arm64")
|
||||
elseif ("x86_64" IN_LIST ARCHITECTURE)
|
||||
set(arch_path "msvc2019_64")
|
||||
set(arch_path "msvc2022_64")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.")
|
||||
endif()
|
||||
set(arch "win64_${arch_path}")
|
||||
|
||||
if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
|
||||
set(host_arch_path "msvc2019_64")
|
||||
set(host_arch_path "msvc2022_64")
|
||||
elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
set(host_arch_path "msvc2019_64")
|
||||
set(host_arch_path "msvc2022_64")
|
||||
endif()
|
||||
set(host_arch "win64_${host_arch_path}")
|
||||
else()
|
||||
|
@ -134,12 +134,12 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
|
|||
else()
|
||||
set(prefix "${base_path}/${target}/${arch_path}")
|
||||
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch}
|
||||
-m qtmultimedia --archives qttranslations qttools qtsvg qtbase)
|
||||
-m all)
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS "${prefix}")
|
||||
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
|
||||
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.1.18")
|
||||
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.2.0")
|
||||
if (WIN32)
|
||||
set(aqt_path "${base_path}/aqt.exe")
|
||||
if (NOT EXISTS "${aqt_path}")
|
||||
|
|
4
dist/languages/ar.ts
vendored
4
dist/languages/ar.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">موقعنا</span></a>|<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">رماز المصدر</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">المساهمون</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">الرخصة</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">موقعنا</span></a>|<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">رماز المصدر</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">المساهمون</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">الرخصة</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/ca.ts
vendored
4
dist/languages/ca.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Pàgina web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Codi Font</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuïdors</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Llicència</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Pàgina web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Codi Font</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuïdors</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Llicència</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/cs.ts
vendored
4
dist/languages/cs.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webové stránky</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Zdrojový kód</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Přispěvatelé</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webové stránky</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Zdrojový kód</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Přispěvatelé</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/da.ts
vendored
4
dist/languages/da.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/">Netsted<span style=" text-decoration: underline; color:#039be5;"></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsydere</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/">Netsted<span style=" text-decoration: underline; color:#039be5;"></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsydere</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/de.ts
vendored
4
dist/languages/de.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webseite</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Quellcode</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Mitwirkende</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lizenz</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webseite</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Quellcode</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Mitwirkende</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lizenz</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/el.ts
vendored
4
dist/languages/el.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Ιστοσελίδα</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Πηγαίος Κώδικας</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Συνεργάτες</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"></span>Άδεια</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Ιστοσελίδα</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Πηγαίος Κώδικας</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Συνεργάτες</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"></span>Άδεια</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/es.ts
vendored
4
dist/languages/es.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Página web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Código fuente</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencia</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Página web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Código fuente</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencia</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/fi.ts
vendored
4
dist/languages/fi.ts
vendored
|
@ -40,8 +40,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="118"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettisivu</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Lähdekoodi</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Lahjoittajat</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisenssi</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettisivu</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Lähdekoodi</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Lahjoittajat</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisenssi</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="134"/>
|
||||
|
|
4
dist/languages/fr.ts
vendored
4
dist/languages/fr.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Site Web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Code Source</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributeurs</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Site Web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Code Source</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributeurs</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/hu.ts
vendored
4
dist/languages/hu.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Weboldal</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Forráskód</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Közreműködők</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licensz</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Weboldal</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Forráskód</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Közreműködők</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licensz</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/id.ts
vendored
4
dist/languages/id.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Situs web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kode Sumber</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Kontributor</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lisensi</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Situs web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kode Sumber</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Kontributor</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lisensi</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/it.ts
vendored
4
dist/languages/it.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Sito web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Codice sorgente</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributori</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licenza</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Sito web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Codice sorgente</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributori</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licenza</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/ja_JP.ts
vendored
4
dist/languages/ja_JP.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">ウェブサイト</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">ソースコード</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">貢献者</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">ライセンス</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">ウェブサイト</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">ソースコード</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">貢献者</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">ライセンス</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/ko_KR.ts
vendored
4
dist/languages/ko_KR.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">웹사이트</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">소스 코드</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">기여자</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">라이센스</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">웹사이트</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">소스 코드</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">기여자</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">라이센스</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/nb.ts
vendored
4
dist/languages/nb.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettside</span></a>|<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsytere</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisens</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettside</span></a>|<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsytere</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisens</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/nl.ts
vendored
4
dist/languages/nl.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Broncode</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bijdragers</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licentie</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Broncode</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bijdragers</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licentie</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/pl.ts
vendored
4
dist/languages/pl.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Strona</span></a>I<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kod Źródłowy</span></a>I<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Kontrybutorzy</span></a>I<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencja</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Strona</span></a>I<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kod Źródłowy</span></a>I<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Kontrybutorzy</span></a>I<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencja</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/pt_BR.ts
vendored
4
dist/languages/pt_BR.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Site</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Código-fonte</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Colaboradores</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licença</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Site</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Código-fonte</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Colaboradores</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licença</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/pt_PT.ts
vendored
4
dist/languages/pt_PT.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation>Site | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Código fonte | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licença</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation>Site | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Código fonte | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licença</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/ru_RU.ts
vendored
4
dist/languages/ru_RU.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Веб-сайт</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Исходный код</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Контрибьюторы</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Лицензия</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Веб-сайт</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Исходный код</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Контрибьюторы</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Лицензия</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/sv.ts
vendored
4
dist/languages/sv.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Hemsida</span></a>I<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Källkod</span></a>I<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsgivare</span></a>I<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Hemsida</span></a>I<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Källkod</span></a>I<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsgivare</span></a>I<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/tr_TR.ts
vendored
4
dist/languages/tr_TR.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a>|<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kaynak Kodu</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Katkıda Bulunanlar</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lisans</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a>|<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kaynak Kodu</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Katkıda Bulunanlar</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lisans</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/uk.ts
vendored
4
dist/languages/uk.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Веб-сайт</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Першокод</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Вкладники</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Ліцензія</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Веб-сайт</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Першокод</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Вкладники</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Ліцензія</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/vi.ts
vendored
4
dist/languages/vi.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Trang web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Mã nguồn</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Người đóng góp</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Giấy phép</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Trang web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Mã nguồn</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Người đóng góp</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Giấy phép</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/vi_VN.ts
vendored
4
dist/languages/vi_VN.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Trang web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Mã nguồn</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Đóng góp</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Giấy phép</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Trang web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Mã nguồn</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Đóng góp</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Giấy phép</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/zh_CN.ts
vendored
4
dist/languages/zh_CN.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">官方网站</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">源代码</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">贡献者</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">许可证</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">官方网站</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">源代码</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">贡献者</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">许可证</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/languages/zh_TW.ts
vendored
4
dist/languages/zh_TW.ts
vendored
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">官網</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">原始碼</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">貢獻者</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">許可證</span></a></p></body></html></translation>
|
||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">官網</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">原始碼</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">貢獻者</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">許可證</span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||
|
|
4
dist/org.citron_emu.citron.metainfo.xml
vendored
4
dist/org.citron_emu.citron.metainfo.xml
vendored
|
@ -25,13 +25,13 @@ SPDX-License-Identifier: CC0-1.0
|
|||
<keyword>emulator</keyword>
|
||||
</keywords>
|
||||
<url type="homepage">https://citron-emu.org/</url>
|
||||
<url type="bugtracker">https://github.com/citron-emu/citron/issues</url>
|
||||
<url type="bugtracker">https://git.citron-emu.org/Citron/Citron/issues</url>
|
||||
<url type="faq">https://citron-emu.org/wiki/faq/</url>
|
||||
<url type="help">https://citron-emu.org/wiki/home/</url>
|
||||
<url type="donation">https://citron-emu.org/donate/</url>
|
||||
<url type="translate">https://www.transifex.com/projects/p/citron</url>
|
||||
<url type="contact">https://community.citra-emu.org/</url>
|
||||
<url type="vcs-browser">https://github.com/citron-emu/citron</url>
|
||||
<url type="vcs-browser">https://git.citron-emu.org/Citron/Citron</url>
|
||||
<url type="contribute">https://citron-emu.org/wiki/contributing/</url>
|
||||
<launchable type="desktop-id">org.citron_emu.citron.desktop</launchable>
|
||||
<provides>
|
||||
|
|
BIN
dist/qt_themes/default/icons/256x256/citron.png
vendored
BIN
dist/qt_themes/default/icons/256x256/citron.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 12 KiB |
2
externals/Vulkan-Headers
vendored
2
externals/Vulkan-Headers
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a03d2f6d5753b365d704d58161825890baad0755
|
||||
Subproject commit cacef3039d277c448c89336290ec3937270b0996
|
2
externals/Vulkan-Utility-Libraries
vendored
2
externals/Vulkan-Utility-Libraries
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7b23ba7a5f86936a8d783baf64a77c38977d6890
|
||||
Subproject commit bc3a4d9fd9b46729651a3cec4f5226f6272b8684
|
2
externals/VulkanMemoryAllocator
vendored
2
externals/VulkanMemoryAllocator
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7ab8483d10b665ba8d478e1502380c40e2374ac7
|
||||
Subproject commit c788c52156f3ef7bc7ab769cb03c110a53ac8fcb
|
2
externals/cpp-httplib
vendored
2
externals/cpp-httplib
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a609330e4c6374f741d3b369269f7848255e1954
|
||||
Subproject commit 39a64fb4e7e42216f14f0ec51ccc5fa85e651432
|
2
externals/cpp-jwt
vendored
2
externals/cpp-jwt
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 10ef5735d842b31025f1257ae78899f50a40fb14
|
||||
Subproject commit 4a970bc302d671476122cbc6b43cc89fbf4a96ec
|
2
externals/enet
vendored
2
externals/enet
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 39a72ab1990014eb399cee9d538fd529df99c6a0
|
||||
Subproject commit 657eaf97d9d335917c58484a4a4b5e03838ebd8e
|
2
externals/ffmpeg/ffmpeg
vendored
2
externals/ffmpeg/ffmpeg
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 9c1294eaddb88cb0e044c675ccae059a85fc9c6c
|
||||
Subproject commit 99e2af4e7837ca09b97d93a562dc12947179fc48
|
2
externals/libadrenotools
vendored
2
externals/libadrenotools
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5cd3f5c5ceea6d9e9d435ccdd922d9b99e55d10b
|
||||
Subproject commit 8fae8ce254dfc1344527e05301e43f37dea2df80
|
2
externals/libusb/libusb
vendored
2
externals/libusb/libusb
vendored
|
@ -1 +1 @@
|
|||
Subproject commit c060e9ce30ac2e3ffb49d94209c4dae77b6642f7
|
||||
Subproject commit de38189e8014fa393f4d8c1d9d3fdf5e2a95899d
|
2
externals/oaknut
vendored
2
externals/oaknut
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 9d091109deb445bc6e9289c6195a282b7c993d49
|
||||
Subproject commit 94c726ce0338b054eb8cb5ea91de8fe6c19f4392
|
2
externals/opus
vendored
2
externals/opus
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 101a71e03bbf860aaafb7090a0e440675cb27660
|
||||
Subproject commit 734aed05d09af3d2690f8cb5aafa97f052746daf
|
2
externals/simpleini
vendored
2
externals/simpleini
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 382ddbb4b92c0b26aa1b32cefba2002119a5b1f2
|
||||
Subproject commit 6048871ea9ee0ec24be5bd099d161a10567d7dc2
|
2
externals/vcpkg
vendored
2
externals/vcpkg
vendored
|
@ -1 +1 @@
|
|||
Subproject commit cf035d9916a0a23042b41fcae7ee0386d245af08
|
||||
Subproject commit e40d24cb149dd138e7c11d490834fa2c81298b32
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
|
@ -27,20 +28,20 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn
|
|||
android {
|
||||
namespace = "org.citron.citron_emu"
|
||||
|
||||
compileSdkVersion = "android-34"
|
||||
ndkVersion = "27.2.12479018" // "27.2.12479018" // "28.0.12433566 rc1"// "28.0.12674087 rc2" // "26.1.10909125"
|
||||
compileSdkVersion = "android-35"
|
||||
ndkVersion = "29.0.13113456 rc1" // "26.1.10909125"
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
jvmTarget = "21"
|
||||
}
|
||||
|
||||
packaging {
|
||||
|
@ -54,9 +55,10 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// TODO If this is ever modified, change application_id in strings.xml
|
||||
applicationId = "org.citron.citron_emu"
|
||||
applicationId = "com.antutu.ABenchMark"
|
||||
minSdk = 30
|
||||
targetSdk = 34
|
||||
//noinspection EditedTargetSdkVersion
|
||||
targetSdk = 35
|
||||
versionName = getGitVersion()
|
||||
|
||||
versionCode = if (System.getenv("AUTO_VERSIONED") == "true") {
|
||||
|
@ -103,10 +105,10 @@ android {
|
|||
signingConfigs.getByName("default")
|
||||
}
|
||||
|
||||
resValue("string", "app_name_suffixed", "citron")
|
||||
resValue("string", "app_name_suffixed", "Citron")
|
||||
isDefault = true
|
||||
isShrinkResources = true
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
isJniDebuggable = false
|
||||
isDebuggable = false
|
||||
proguardFiles(
|
||||
|
@ -118,9 +120,8 @@ android {
|
|||
// builds a release build that doesn't need signing
|
||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||
register("relWithDebInfo") {
|
||||
resValue("string", "app_name_suffixed", "citron Debug Release")
|
||||
resValue("string", "app_name_suffixed", "Citron Debug Release")
|
||||
signingConfig = signingConfigs.getByName("default")
|
||||
isMinifyEnabled = true
|
||||
isDebuggable = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
|
@ -135,7 +136,7 @@ android {
|
|||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||
debug {
|
||||
signingConfig = signingConfigs.getByName("default")
|
||||
resValue("string", "app_name_suffixed", "citron Debug")
|
||||
resValue("string", "app_name_suffixed", "Citron Debug")
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
versionNameSuffix = "-debug"
|
||||
|
@ -148,7 +149,7 @@ android {
|
|||
create("mainline") {
|
||||
isDefault = true
|
||||
dimension = "version"
|
||||
buildConfigField("Boolean", "PREMIUM", "true") // Spoof EA Version
|
||||
buildConfigField("Boolean", "PREMIUM", "true")
|
||||
}
|
||||
|
||||
create("ea") {
|
||||
|
@ -160,7 +161,7 @@ android {
|
|||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version = "3.22.1"
|
||||
version = "3.31.6"
|
||||
path = file("../../../CMakeLists.txt")
|
||||
}
|
||||
}
|
||||
|
@ -177,23 +178,24 @@ android {
|
|||
"-DCITRON_USE_BUNDLED_VCPKG=ON",
|
||||
"-DCITRON_USE_BUNDLED_FFMPEG=ON",
|
||||
"-DCITRON_ENABLE_LTO=ON",
|
||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
|
||||
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
||||
)
|
||||
|
||||
abiFilters("arm64-v8a")
|
||||
abiFilters("arm64-v8a") // , "x86_64")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create<Delete>("ktlintReset") { // Deprecated, Still Works.
|
||||
tasks.create<Delete>("ktlintReset") {
|
||||
delete(File(buildDir.path + File.separator + "intermediates/ktLint"))
|
||||
}
|
||||
|
||||
val showFormatHelp = {
|
||||
logger.lifecycle(
|
||||
"If this check fails, please try running \"gradlew ktlintFormat\" for automatic " +
|
||||
"codestyle fixes"
|
||||
"codestyle fixes"
|
||||
)
|
||||
}
|
||||
tasks.getByPath("ktlintKotlinScriptCheck").doFirst { showFormatHelp.invoke() }
|
||||
|
@ -204,7 +206,7 @@ ktlint {
|
|||
version.set("0.47.1")
|
||||
android.set(true)
|
||||
ignoreFailures.set(false)
|
||||
disabledRules.set( // Deprecated, Still Works.
|
||||
disabledRules.set(
|
||||
setOf(
|
||||
"no-wildcard-imports",
|
||||
"package-name",
|
||||
|
@ -238,7 +240,6 @@ dependencies {
|
|||
implementation("io.coil-kt:coil:2.2.2")
|
||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||
implementation("androidx.window:window:1.2.0-beta03")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
|
||||
|
|
7
src/android/app/proguard-rules.pro
vendored
7
src/android/app/proguard-rules.pro
vendored
|
@ -22,3 +22,10 @@
|
|||
-dontwarn java.beans.Introspector
|
||||
-dontwarn java.beans.VetoableChangeListener
|
||||
-dontwarn java.beans.VetoableChangeSupport
|
||||
|
||||
# LicenseVerifier protection
|
||||
-keep class org.citron.citron_emu.utils.LicenseVerifier { *; }
|
||||
-keepnames class org.citron.citron_emu.utils.LicenseVerifier
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
|
|
|
@ -14,6 +14,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.citron.citron_emu.utils.Log
|
|||
import org.citron.citron_emu.model.InstallResult
|
||||
import org.citron.citron_emu.model.Patch
|
||||
import org.citron.citron_emu.model.GameVerificationResult
|
||||
import org.citron.citron_emu.network.NetPlayManager
|
||||
import java.net.NetworkInterface
|
||||
|
||||
/**
|
||||
* Class which contains methods that interact
|
||||
|
@ -242,6 +244,27 @@ object NativeLibrary {
|
|||
return coreErrorAlertResult
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun addNetPlayMessage(type: Int, message: String) {
|
||||
val emulationActivity = sEmulationActivity.get()
|
||||
if (emulationActivity != null) {
|
||||
emulationActivity.addNetPlayMessages(type, message)
|
||||
}
|
||||
else {
|
||||
NetPlayManager.addNetPlayMessage(type, message)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun clearChat() {
|
||||
NetPlayManager.clearChat()
|
||||
}
|
||||
|
||||
|
||||
external fun netPlayInit()
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun exitEmulationActivity(resultCode: Int) {
|
||||
|
@ -459,4 +482,29 @@ object NativeLibrary {
|
|||
* Checks if all necessary keys are present for decryption
|
||||
*/
|
||||
external fun areKeysPresent(): Boolean
|
||||
|
||||
fun getNetworkInterfaces(): Array<String> {
|
||||
val interfaceList = mutableListOf<String>()
|
||||
try {
|
||||
NetworkInterface.getNetworkInterfaces()?.toList()?.forEach { iface ->
|
||||
if (iface.isUp && !iface.isLoopback) {
|
||||
iface.inetAddresses.toList()
|
||||
.filterNot { it.isLoopbackAddress }
|
||||
.forEach { addr ->
|
||||
interfaceList.add("${iface.name};${addr.hostAddress}")
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.error("[NativeLibrary] Failed to enumerate network interfaces: ${e.message}")
|
||||
}
|
||||
|
||||
// Always ensure we have at least a loopback interface
|
||||
if (interfaceList.isEmpty()) {
|
||||
Log.warning("[NativeLibrary] No interfaces found, adding loopback fallback")
|
||||
interfaceList.add("lo;127.0.0.1")
|
||||
}
|
||||
|
||||
return interfaceList.toTypedArray()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package org.citron.citron_emu.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.app.PendingIntent
|
||||
import android.app.PictureInPictureParams
|
||||
import android.app.RemoteAction
|
||||
|
@ -39,12 +40,14 @@ import org.citron.citron_emu.NativeLibrary
|
|||
import org.citron.citron_emu.R
|
||||
import org.citron.citron_emu.CitronApplication
|
||||
import org.citron.citron_emu.databinding.ActivityEmulationBinding
|
||||
import org.citron.citron_emu.dialogs.NetPlayDialog
|
||||
import org.citron.citron_emu.features.input.NativeInput
|
||||
import org.citron.citron_emu.features.settings.model.BooleanSetting
|
||||
import org.citron.citron_emu.features.settings.model.IntSetting
|
||||
import org.citron.citron_emu.features.settings.model.Settings
|
||||
import org.citron.citron_emu.model.EmulationViewModel
|
||||
import org.citron.citron_emu.model.Game
|
||||
import org.citron.citron_emu.network.NetPlayManager
|
||||
import org.citron.citron_emu.utils.InputHandler
|
||||
import org.citron.citron_emu.utils.Log
|
||||
import org.citron.citron_emu.utils.MemoryUtil
|
||||
|
@ -52,6 +55,7 @@ import org.citron.citron_emu.utils.NativeConfig
|
|||
import org.citron.citron_emu.utils.NfcReader
|
||||
import org.citron.citron_emu.utils.ParamPackage
|
||||
import org.citron.citron_emu.utils.ThemeHelper
|
||||
import org.citron.citron_emu.utils.LicenseVerifier
|
||||
import java.text.NumberFormat
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
@ -79,6 +83,22 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Check if firmware is available
|
||||
if (!NativeLibrary.isFirmwareAvailable()) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.firmware_missing_title)
|
||||
.setMessage(R.string.firmware_missing_message)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
finish()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
return
|
||||
}
|
||||
|
||||
// Add license verification at the start
|
||||
LicenseVerifier.verifyLicense(this)
|
||||
|
||||
InputHandler.updateControllerData()
|
||||
val players = NativeConfig.getInputSettings(true)
|
||||
var hasConfiguredControllers = false
|
||||
|
@ -405,6 +425,16 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
|
||||
fun displayMultiplayerDialog() {
|
||||
val dialog = NetPlayDialog(this)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun addNetPlayMessages(type: Int, msg: String) {
|
||||
NetPlayManager.addNetPlayMessage(type, msg)
|
||||
}
|
||||
|
||||
|
||||
private var pictureInPictureReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent) {
|
||||
if (intent.action == actionPlay) {
|
||||
|
|
|
@ -31,7 +31,7 @@ class SetupAdapter(val activity: AppCompatActivity, pages: List<SetupPage>) :
|
|||
override fun bind(model: SetupPage) {
|
||||
if (model.stepCompleted.invoke() == StepState.COMPLETE) {
|
||||
binding.buttonAction.setVisible(visible = false, gone = false)
|
||||
binding.textConfirmation.setVisible(true)
|
||||
binding.textConfirmation?.setVisible(true)
|
||||
}
|
||||
|
||||
binding.icon.setImageDrawable(
|
||||
|
@ -68,7 +68,7 @@ class SetupAdapter(val activity: AppCompatActivity, pages: List<SetupPage>) :
|
|||
|
||||
override fun onStepCompleted() {
|
||||
ViewUtils.hideView(binding.buttonAction, 200)
|
||||
ViewUtils.showView(binding.textConfirmation, 200)
|
||||
binding.textConfirmation?.let { ViewUtils.showView(it, 200) }
|
||||
ViewModelProvider(activity)[HomeViewModel::class.java].setShouldPageForward(true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
package org.citron.citron_emu.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import org.citron.citron_emu.R
|
||||
import org.citron.citron_emu.databinding.DialogChatBinding
|
||||
import org.citron.citron_emu.databinding.ItemChatMessageBinding
|
||||
import org.citron.citron_emu.network.NetPlayManager
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class ChatMessage(
|
||||
val nickname: String, // This is the common name youll see on private servers
|
||||
val username: String, // Username is the community/forum username
|
||||
val message: String,
|
||||
val timestamp: String = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date())
|
||||
) {
|
||||
}
|
||||
|
||||
class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||
private lateinit var binding: DialogChatBinding
|
||||
private lateinit var chatAdapter: ChatAdapter
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = DialogChatBinding.inflate(LayoutInflater.from(context))
|
||||
setContentView(binding.root)
|
||||
|
||||
NetPlayManager.setChatOpen(true)
|
||||
setupRecyclerView()
|
||||
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
|
||||
handler.post {
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
binding.chatRecyclerView.post {
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
NetPlayManager.setOnMessageReceivedListener { type, message ->
|
||||
handler.post {
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
binding.sendButton.setOnClickListener {
|
||||
val message = binding.chatInput.text.toString()
|
||||
if (message.isNotBlank()) {
|
||||
sendMessage(message)
|
||||
binding.chatInput.text?.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
NetPlayManager.setChatOpen(false)
|
||||
super.dismiss()
|
||||
}
|
||||
|
||||
private fun sendMessage(message: String) {
|
||||
val username = NetPlayManager.getUsername(context)
|
||||
NetPlayManager.netPlaySendMessage(message)
|
||||
|
||||
val chatMessage = ChatMessage(
|
||||
nickname = username,
|
||||
username = "",
|
||||
message = message,
|
||||
timestamp = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date())
|
||||
)
|
||||
|
||||
NetPlayManager.addChatMessage(chatMessage)
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
scrollToBottom()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
chatAdapter = ChatAdapter(NetPlayManager.getChatMessages())
|
||||
binding.chatRecyclerView.layoutManager = LinearLayoutManager(context).apply {
|
||||
stackFromEnd = true
|
||||
}
|
||||
binding.chatRecyclerView.adapter = chatAdapter
|
||||
}
|
||||
|
||||
private fun scrollToBottom() {
|
||||
binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class ChatAdapter(private val messages: List<ChatMessage>) :
|
||||
RecyclerView.Adapter<ChatAdapter.ChatViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder {
|
||||
val binding = ItemChatMessageBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return ChatViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = messages.size
|
||||
|
||||
override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
|
||||
holder.bind(messages[position])
|
||||
}
|
||||
|
||||
inner class ChatViewHolder(private val binding: ItemChatMessageBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(message: ChatMessage) {
|
||||
binding.usernameText.text = message.nickname
|
||||
binding.messageText.text = message.message
|
||||
binding.userIcon.setImageResource(when (message.nickname) {
|
||||
"System" -> R.drawable.ic_system
|
||||
else -> R.drawable.ic_user
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citron.citron_emu.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import org.citron.citron_emu.R
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citron.citron_emu.CitronApplication
|
||||
import org.citron.citron_emu.databinding.DialogMultiplayerConnectBinding
|
||||
import org.citron.citron_emu.databinding.DialogMultiplayerLobbyBinding
|
||||
import org.citron.citron_emu.databinding.DialogMultiplayerRoomBinding
|
||||
import org.citron.citron_emu.databinding.ItemBanListBinding
|
||||
import org.citron.citron_emu.databinding.ItemButtonNetplayBinding
|
||||
import org.citron.citron_emu.databinding.ItemTextNetplayBinding
|
||||
import org.citron.citron_emu.utils.CompatUtils
|
||||
import org.citron.citron_emu.network.NetPlayManager
|
||||
|
||||
class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||
private lateinit var adapter: NetPlayAdapter
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
when {
|
||||
NetPlayManager.netPlayIsJoined() -> DialogMultiplayerLobbyBinding.inflate(layoutInflater)
|
||||
.apply {
|
||||
setContentView(root)
|
||||
adapter = NetPlayAdapter()
|
||||
listMultiplayer.layoutManager = LinearLayoutManager(context)
|
||||
listMultiplayer.adapter = adapter
|
||||
adapter.loadMultiplayerMenu()
|
||||
btnLeave.setOnClickListener {
|
||||
NetPlayManager.netPlayLeaveRoom()
|
||||
dismiss()
|
||||
}
|
||||
btnChat.setOnClickListener {
|
||||
ChatDialog(context).show()
|
||||
}
|
||||
|
||||
refreshAdapterItems()
|
||||
|
||||
btnModeration.visibility = if (NetPlayManager.netPlayIsModerator()) View.VISIBLE else View.GONE
|
||||
btnModeration.setOnClickListener {
|
||||
showModerationDialog()
|
||||
}
|
||||
|
||||
}
|
||||
else -> {
|
||||
DialogMultiplayerConnectBinding.inflate(layoutInflater).apply {
|
||||
setContentView(root)
|
||||
btnCreate.setOnClickListener {
|
||||
showNetPlayInputDialog(true)
|
||||
dismiss()
|
||||
}
|
||||
btnJoin.setOnClickListener {
|
||||
showNetPlayInputDialog(false)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class NetPlayItems(
|
||||
val option: Int,
|
||||
val name: String,
|
||||
val type: Int,
|
||||
val id: Int = 0
|
||||
) {
|
||||
companion object {
|
||||
const val MULTIPLAYER_ROOM_TEXT = 1
|
||||
const val MULTIPLAYER_ROOM_MEMBER = 2
|
||||
const val MULTIPLAYER_SEPARATOR = 3
|
||||
const val MULTIPLAYER_ROOM_COUNT = 4
|
||||
const val TYPE_BUTTON = 0
|
||||
const val TYPE_TEXT = 1
|
||||
const val TYPE_SEPARATOR = 2
|
||||
}
|
||||
}
|
||||
|
||||
inner class NetPlayAdapter : RecyclerView.Adapter<NetPlayAdapter.NetPlayViewHolder>() {
|
||||
val netPlayItems = mutableListOf<NetPlayItems>()
|
||||
|
||||
abstract inner class NetPlayViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
}
|
||||
abstract fun bind(item: NetPlayItems)
|
||||
}
|
||||
|
||||
inner class TextViewHolder(private val binding: ItemTextNetplayBinding) : NetPlayViewHolder(binding.root) {
|
||||
private lateinit var netPlayItem: NetPlayItems
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
override fun bind(item: NetPlayItems) {
|
||||
netPlayItem = item
|
||||
binding.itemTextNetplayName.text = item.name
|
||||
binding.itemIcon.apply {
|
||||
val iconRes = when (item.option) {
|
||||
NetPlayItems.MULTIPLAYER_ROOM_TEXT -> R.drawable.ic_system
|
||||
NetPlayItems.MULTIPLAYER_ROOM_COUNT -> R.drawable.ic_joined
|
||||
else -> 0
|
||||
}
|
||||
visibility = if (iconRes != 0) {
|
||||
setImageResource(iconRes)
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ButtonViewHolder(private val binding: ItemButtonNetplayBinding) : NetPlayViewHolder(binding.root) {
|
||||
private lateinit var netPlayItems: NetPlayItems
|
||||
private val isModerator = NetPlayManager.netPlayIsModerator()
|
||||
|
||||
init {
|
||||
binding.itemButtonMore.apply {
|
||||
visibility = View.VISIBLE
|
||||
setOnClickListener { showPopupMenu(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
|
||||
private fun showPopupMenu(view: View) {
|
||||
PopupMenu(view.context, view).apply {
|
||||
menuInflater.inflate(R.menu.menu_netplay_member, menu)
|
||||
menu.findItem(R.id.action_kick).isEnabled = isModerator &&
|
||||
netPlayItems.name != NetPlayManager.getUsername(context)
|
||||
menu.findItem(R.id.action_ban).isEnabled = isModerator &&
|
||||
netPlayItems.name != NetPlayManager.getUsername(context)
|
||||
setOnMenuItemClickListener { item ->
|
||||
if (item.itemId == R.id.action_kick) {
|
||||
NetPlayManager.netPlayKickUser(netPlayItems.name)
|
||||
true
|
||||
} else if (item.itemId == R.id.action_ban) {
|
||||
NetPlayManager.netPlayBanUser(netPlayItems.name)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(item: NetPlayItems) {
|
||||
netPlayItems = item
|
||||
binding.itemButtonNetplayName.text = netPlayItems.name
|
||||
}
|
||||
}
|
||||
|
||||
fun loadMultiplayerMenu() {
|
||||
val infos = NetPlayManager.netPlayRoomInfo()
|
||||
if (infos.isNotEmpty()) {
|
||||
val roomInfo = infos[0].split("|")
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_TEXT, roomInfo[0], NetPlayItems.TYPE_TEXT))
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_COUNT, "${infos.size - 1}/${roomInfo[1]}", NetPlayItems.TYPE_TEXT))
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_SEPARATOR, "", NetPlayItems.TYPE_SEPARATOR))
|
||||
for (i in 1 until infos.size) {
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_MEMBER, infos[i], NetPlayItems.TYPE_BUTTON))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int) = netPlayItems[position].type
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NetPlayViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (viewType) {
|
||||
NetPlayItems.TYPE_TEXT -> TextViewHolder(ItemTextNetplayBinding.inflate(inflater, parent, false))
|
||||
NetPlayItems.TYPE_BUTTON -> ButtonViewHolder(ItemButtonNetplayBinding.inflate(inflater, parent, false))
|
||||
NetPlayItems.TYPE_SEPARATOR -> object : NetPlayViewHolder(inflater.inflate(R.layout.item_separator_netplay, parent, false)) {
|
||||
override fun bind(item: NetPlayItems) {}
|
||||
override fun onClick(clicked: View) {}
|
||||
}
|
||||
else -> throw IllegalStateException("Unsupported view type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: NetPlayViewHolder, position: Int) {
|
||||
holder.bind(netPlayItems[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = netPlayItems.size
|
||||
}
|
||||
|
||||
fun refreshAdapterItems() {
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
NetPlayManager.setOnAdapterRefreshListener() { type, msg ->
|
||||
handler.post {
|
||||
adapter.netPlayItems.clear()
|
||||
adapter.loadMultiplayerMenu()
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNetPlayInputDialog(isCreateRoom: Boolean) {
|
||||
val activity = CompatUtils.findActivity(context)
|
||||
val dialog = BottomSheetDialog(activity)
|
||||
|
||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
dialog.behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
|
||||
val binding = DialogMultiplayerRoomBinding.inflate(LayoutInflater.from(activity))
|
||||
dialog.setContentView(binding.root)
|
||||
|
||||
binding.textTitle.text = activity.getString(
|
||||
if (isCreateRoom) R.string.multiplayer_create_room
|
||||
else R.string.multiplayer_join_room
|
||||
)
|
||||
|
||||
binding.ipAddress.setText(
|
||||
if (isCreateRoom) NetPlayManager.getIpAddressByWifi(activity)
|
||||
else NetPlayManager.getRoomAddress(activity)
|
||||
)
|
||||
binding.ipPort.setText(NetPlayManager.getRoomPort(activity))
|
||||
binding.username.setText(NetPlayManager.getUsername(activity))
|
||||
|
||||
binding.roomName.visibility = if (isCreateRoom) View.VISIBLE else View.GONE
|
||||
binding.maxPlayersContainer.visibility = if (isCreateRoom) View.VISIBLE else View.GONE
|
||||
binding.maxPlayersLabel.text = context.getString(R.string.multiplayer_max_players_value, binding.maxPlayers.value.toInt())
|
||||
|
||||
binding.maxPlayers.addOnChangeListener { _, value, _ ->
|
||||
binding.maxPlayersLabel.text = context.getString(R.string.multiplayer_max_players_value, value.toInt())
|
||||
}
|
||||
|
||||
binding.btnConfirm.setOnClickListener {
|
||||
binding.btnConfirm.isEnabled = false
|
||||
binding.btnConfirm.text = activity.getString(R.string.disabled_button_text)
|
||||
|
||||
val ipAddress = binding.ipAddress.text.toString()
|
||||
val username = binding.username.text.toString()
|
||||
val portStr = binding.ipPort.text.toString()
|
||||
val password = binding.password.text.toString()
|
||||
val port = portStr.toIntOrNull() ?: run {
|
||||
Toast.makeText(activity, R.string.multiplayer_port_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
return@setOnClickListener
|
||||
}
|
||||
val roomName = binding.roomName.text.toString()
|
||||
val maxPlayers = binding.maxPlayers.value.toInt()
|
||||
|
||||
if (isCreateRoom && (roomName.length !in 3..20)) {
|
||||
Toast.makeText(activity, R.string.multiplayer_room_name_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (ipAddress.length < 7 || username.length < 5) {
|
||||
Toast.makeText(activity, R.string.multiplayer_input_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
} else {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val result = if (isCreateRoom) {
|
||||
NetPlayManager.netPlayCreateRoom(ipAddress, port, username, password, roomName, maxPlayers)
|
||||
} else {
|
||||
NetPlayManager.netPlayJoinRoom(ipAddress, port, username, password)
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
NetPlayManager.setUsername(activity, username)
|
||||
NetPlayManager.setRoomPort(activity, portStr)
|
||||
if (!isCreateRoom) NetPlayManager.setRoomAddress(activity, ipAddress)
|
||||
Toast.makeText(
|
||||
CitronApplication.appContext,
|
||||
if (isCreateRoom) R.string.multiplayer_create_room_success
|
||||
else R.string.multiplayer_join_room_success,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
dialog.dismiss()
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.multiplayer_could_not_connect, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun showModerationDialog() {
|
||||
val activity = CompatUtils.findActivity(context)
|
||||
val dialog = MaterialAlertDialogBuilder(activity)
|
||||
dialog.setTitle(R.string.multiplayer_moderation_title)
|
||||
|
||||
val banList = NetPlayManager.getBanList()
|
||||
if (banList.isEmpty()) {
|
||||
dialog.setMessage(R.string.multiplayer_no_bans)
|
||||
dialog.setPositiveButton(R.string.ok, null)
|
||||
dialog.show()
|
||||
return
|
||||
}
|
||||
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_ban_list, null)
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.ban_list_recycler)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
lateinit var adapter: BanListAdapter
|
||||
|
||||
val onUnban: (String) -> Unit = { bannedItem ->
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.multiplayer_unban_title)
|
||||
.setMessage(activity.getString(R.string.multiplayer_unban_message, bannedItem))
|
||||
.setPositiveButton(R.string.multiplayer_unban) { _, _ ->
|
||||
NetPlayManager.netPlayUnbanUser(bannedItem)
|
||||
adapter.removeBan(bannedItem)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
adapter = BanListAdapter(banList, onUnban)
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
dialog.setView(view)
|
||||
dialog.setPositiveButton(R.string.ok, null)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private class BanListAdapter(
|
||||
banList: List<String>,
|
||||
private val onUnban: (String) -> Unit
|
||||
) : RecyclerView.Adapter<BanListAdapter.ViewHolder>() {
|
||||
|
||||
private val usernameBans = banList.filter { !it.contains(".") }.toMutableList()
|
||||
private val ipBans = banList.filter { it.contains(".") }.toMutableList()
|
||||
|
||||
class ViewHolder(val binding: ItemBanListBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding = ItemBanListBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val isUsername = position < usernameBans.size
|
||||
val item = if (isUsername) usernameBans[position] else ipBans[position - usernameBans.size]
|
||||
|
||||
holder.binding.apply {
|
||||
banText.text = item
|
||||
icon.setImageResource(if (isUsername) R.drawable.ic_user else R.drawable.ic_ip)
|
||||
btnUnban.setOnClickListener { onUnban(item) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = usernameBans.size + ipBans.size
|
||||
|
||||
fun removeBan(bannedItem: String) {
|
||||
val position = if (bannedItem.contains(".")) {
|
||||
ipBans.indexOf(bannedItem).let { if (it >= 0) it + usernameBans.size else it }
|
||||
} else {
|
||||
usernameBans.indexOf(bannedItem)
|
||||
}
|
||||
|
||||
if (position >= 0) {
|
||||
if (bannedItem.contains(".")) {
|
||||
ipBans.remove(bannedItem)
|
||||
} else {
|
||||
usernameBans.remove(bannedItem)
|
||||
}
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: 2025 Citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.citron.citron_emu.features.settings.model
|
||||
|
@ -27,6 +28,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||
SHOW_INPUT_OVERLAY("show_input_overlay"),
|
||||
TOUCHSCREEN("touchscreen"),
|
||||
SHOW_THERMAL_OVERLAY("show_thermal_overlay"),
|
||||
SHOW_RAM_OVERLAY("show_ram_overlay"),
|
||||
USE_AUTO_STUB("use_auto_stub");
|
||||
|
||||
override fun getBoolean(needsGlobal: Boolean): Boolean =
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: 2025 Citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.citron.citron_emu.fragments
|
||||
|
@ -11,9 +12,11 @@ import android.content.Intent
|
|||
import android.content.IntentFilter
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.BatteryManager
|
||||
import android.os.Bundle
|
||||
import android.os.Debug
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.PowerManager
|
||||
|
@ -68,6 +71,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
private var emulationActivity: EmulationActivity? = null
|
||||
private var perfStatsUpdater: (() -> Unit)? = null
|
||||
private var thermalStatsUpdater: (() -> Unit)? = null
|
||||
private var ramStatsUpdater: (() -> Unit)? = null
|
||||
|
||||
private var _binding: FragmentEmulationBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
@ -83,6 +87,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
|
||||
private lateinit var powerManager: PowerManager
|
||||
|
||||
private val ramStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
if (context is EmulationActivity) {
|
||||
|
@ -265,6 +271,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
true
|
||||
}
|
||||
|
||||
|
||||
R.id.menu_multiplayer -> {
|
||||
emulationActivity?.displayMultiplayerDialog()
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
R.id.menu_controls -> {
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||
null,
|
||||
|
@ -376,6 +389,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
// Setup overlays
|
||||
updateShowFpsOverlay()
|
||||
updateThermalOverlay()
|
||||
updateRamOverlay()
|
||||
}
|
||||
}
|
||||
emulationViewModel.isEmulationStopping.collect(viewLifecycleOwner) {
|
||||
|
@ -470,6 +484,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
if (ramStatsUpdater != null) {
|
||||
ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!)
|
||||
}
|
||||
_binding = null
|
||||
}
|
||||
|
||||
|
@ -552,8 +569,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
emulationViewModel.emulationStarted.value &&
|
||||
!emulationViewModel.isEmulationStopping.value
|
||||
) {
|
||||
// Get thermal status
|
||||
// Get thermal status for color
|
||||
val thermalStatus = when (powerManager.currentThermalStatus) {
|
||||
PowerManager.THERMAL_STATUS_NONE -> 0f
|
||||
PowerManager.THERMAL_STATUS_LIGHT -> 0.25f
|
||||
PowerManager.THERMAL_STATUS_MODERATE -> 0.5f
|
||||
PowerManager.THERMAL_STATUS_SEVERE -> 0.75f
|
||||
|
@ -563,34 +581,57 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
else -> 0f
|
||||
}
|
||||
|
||||
// Convert to Fahrenheit for additional info
|
||||
// Convert to Fahrenheit
|
||||
val fahrenheit = (temperature * 9f / 5f) + 32f
|
||||
|
||||
// Create progress bar using block elements
|
||||
val progressBarLength = 12
|
||||
val filledBars = (thermalStatus * progressBarLength).toInt()
|
||||
val progressBar = buildString {
|
||||
append("│") // Left border
|
||||
repeat(filledBars) { append("█") }
|
||||
repeat(progressBarLength - filledBars) { append("░") }
|
||||
append("│") // Right border
|
||||
append(" ")
|
||||
append(String.format("%3d%%", (thermalStatus * 100).toInt()))
|
||||
}
|
||||
|
||||
// Color interpolation based on temperature (green at 30°C, red at 45°C)
|
||||
val normalizedTemp = ((temperature - 30f) / 15f).coerceIn(0f, 1f)
|
||||
val red = (normalizedTemp * 255).toInt()
|
||||
val green = ((1f - normalizedTemp) * 255).toInt()
|
||||
// Color based on thermal status (green to red)
|
||||
val red = (thermalStatus * 255).toInt()
|
||||
val green = ((1f - thermalStatus) * 255).toInt()
|
||||
val color = android.graphics.Color.rgb(red, green, 0)
|
||||
|
||||
binding.showThermalsText.setTextColor(color)
|
||||
binding.showThermalsText.text = String.format(
|
||||
"%s\n%.1f°C • %.1f°F",
|
||||
progressBar,
|
||||
temperature,
|
||||
fahrenheit
|
||||
)
|
||||
binding.showThermalsText.text = String.format("%.1f°C • %.1f°F", temperature, fahrenheit)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRamOverlay() {
|
||||
val showOverlay = BooleanSetting.SHOW_RAM_OVERLAY.getBoolean()
|
||||
binding.showRamText.setVisible(showOverlay)
|
||||
if (showOverlay) {
|
||||
ramStatsUpdater = {
|
||||
if (emulationViewModel.emulationStarted.value &&
|
||||
!emulationViewModel.isEmulationStopping.value
|
||||
) {
|
||||
val runtime = Runtime.getRuntime()
|
||||
val nativeHeapSize = Debug.getNativeHeapSize()
|
||||
val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
|
||||
val nativeHeapUsed = nativeHeapSize - nativeHeapFreeSize
|
||||
|
||||
val usedMemInMB = nativeHeapUsed / 1048576L
|
||||
val maxMemInMB = nativeHeapSize / 1048576L
|
||||
val percentUsed = (nativeHeapUsed.toFloat() / nativeHeapSize.toFloat() * 100f)
|
||||
|
||||
// Color interpolation from green to red based on usage percentage
|
||||
val normalizedUsage = (percentUsed / 100f).coerceIn(0f, 1f)
|
||||
val red = (normalizedUsage * 255).toInt()
|
||||
val green = ((1f - normalizedUsage) * 255).toInt()
|
||||
val color = Color.rgb(red, green, 0)
|
||||
|
||||
binding.showRamText.setTextColor(color)
|
||||
binding.showRamText.text = String.format(
|
||||
"\nRAM: %d/%d MB (%.1f%%)",
|
||||
usedMemInMB,
|
||||
maxMemInMB,
|
||||
percentUsed
|
||||
)
|
||||
ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1000)
|
||||
}
|
||||
}
|
||||
ramStatsUpdateHandler.post(ramStatsUpdater!!)
|
||||
} else {
|
||||
if (ramStatsUpdater != null) {
|
||||
ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,6 +764,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean()
|
||||
findItem(R.id.thermal_indicator).isChecked =
|
||||
BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean()
|
||||
findItem(R.id.ram_meter).apply {
|
||||
isChecked = BooleanSetting.SHOW_RAM_OVERLAY.getBoolean()
|
||||
isEnabled = false // This grays out the option
|
||||
}
|
||||
findItem(R.id.menu_rel_stick_center).isChecked =
|
||||
BooleanSetting.JOYSTICK_REL_CENTER.getBoolean()
|
||||
findItem(R.id.menu_dpad_slide).isChecked = BooleanSetting.DPAD_SLIDE.getBoolean()
|
||||
|
@ -749,6 +794,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
true
|
||||
}
|
||||
|
||||
R.id.ram_meter -> {
|
||||
// Do nothing since it's disabled
|
||||
true
|
||||
}
|
||||
|
||||
R.id.menu_edit_overlay -> {
|
||||
binding.drawerLayout.close()
|
||||
binding.surfaceInputOverlay.requestFocus()
|
||||
|
|
|
@ -119,6 +119,16 @@ class HomeSettingsFragment : Fragment() {
|
|||
driverViewModel.selectedDriverTitle
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.multiplayer,
|
||||
R.string.multiplayer_description,
|
||||
R.drawable.ic_multiplayer,
|
||||
{
|
||||
val action = mainActivity.displayMultiplayerDialog()
|
||||
},
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.applets,
|
||||
|
|
|
@ -180,6 +180,62 @@ class SetupFragment : Fragment() {
|
|||
}
|
||||
)
|
||||
)
|
||||
|
||||
// Add title.keys installation page
|
||||
add(
|
||||
SetupPage(
|
||||
R.drawable.ic_key,
|
||||
R.string.install_title_keys,
|
||||
R.string.install_title_keys_description,
|
||||
R.drawable.ic_add,
|
||||
true,
|
||||
R.string.select_keys,
|
||||
{
|
||||
titleKeyCallback = it
|
||||
getTitleKey.launch(arrayOf("*/*"))
|
||||
},
|
||||
true,
|
||||
R.string.install_title_keys_warning,
|
||||
R.string.install_title_keys_warning_description,
|
||||
R.string.install_title_keys_warning_help,
|
||||
{
|
||||
val file = File(DirectoryInitialization.userDirectory + "/keys/title.keys")
|
||||
if (file.exists()) {
|
||||
StepState.COMPLETE
|
||||
} else {
|
||||
StepState.INCOMPLETE
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// Add firmware installation page (mandatory)
|
||||
add(
|
||||
SetupPage(
|
||||
R.drawable.ic_key,
|
||||
R.string.install_firmware,
|
||||
R.string.install_firmware_description,
|
||||
R.drawable.ic_add,
|
||||
true,
|
||||
R.string.select_firmware,
|
||||
{
|
||||
firmwareCallback = it
|
||||
getFirmware.launch(arrayOf("application/zip"))
|
||||
},
|
||||
true,
|
||||
R.string.install_firmware_warning,
|
||||
R.string.install_firmware_warning_description,
|
||||
R.string.install_firmware_warning_help,
|
||||
{
|
||||
if (NativeLibrary.isFirmwareAvailable()) {
|
||||
StepState.COMPLETE
|
||||
} else {
|
||||
StepState.INCOMPLETE
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
add(
|
||||
SetupPage(
|
||||
R.drawable.ic_controller,
|
||||
|
@ -268,6 +324,18 @@ class SetupFragment : Fragment() {
|
|||
return@setOnClickListener
|
||||
}
|
||||
|
||||
// Special handling for firmware page - don't allow skipping
|
||||
if (currentPage.titleId == R.string.install_firmware && !NativeLibrary.isFirmwareAvailable()) {
|
||||
SetupWarningDialogFragment.newInstance(
|
||||
currentPage.warningTitleId,
|
||||
currentPage.warningDescriptionId,
|
||||
currentPage.warningHelpLinkId,
|
||||
index,
|
||||
allowSkip = false
|
||||
).show(childFragmentManager, SetupWarningDialogFragment.TAG)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (!hasBeenWarned[index]) {
|
||||
SetupWarningDialogFragment.newInstance(
|
||||
currentPage.warningTitleId,
|
||||
|
@ -346,6 +414,30 @@ class SetupFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private lateinit var titleKeyCallback: SetupCallback
|
||||
|
||||
val getTitleKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result != null) {
|
||||
mainActivity.processTitleKey(result)
|
||||
titleKeyCallback.onStepCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var firmwareCallback: SetupCallback
|
||||
|
||||
val getFirmware =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result != null) {
|
||||
mainActivity.getFirmware.launch(arrayOf("application/zip"))
|
||||
binding.root.postDelayed({
|
||||
if (NativeLibrary.isFirmwareAvailable()) {
|
||||
firmwareCallback.onStepCompleted()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var gamesDirCallback: SetupCallback
|
||||
|
||||
val getGamesDirectory =
|
||||
|
|
|
@ -17,6 +17,7 @@ class SetupWarningDialogFragment : DialogFragment() {
|
|||
private var descriptionId: Int = 0
|
||||
private var helpLinkId: Int = 0
|
||||
private var page: Int = 0
|
||||
private var allowSkip: Boolean = true
|
||||
|
||||
private lateinit var setupFragment: SetupFragment
|
||||
|
||||
|
@ -26,17 +27,24 @@ class SetupWarningDialogFragment : DialogFragment() {
|
|||
descriptionId = requireArguments().getInt(DESCRIPTION)
|
||||
helpLinkId = requireArguments().getInt(HELP_LINK)
|
||||
page = requireArguments().getInt(PAGE)
|
||||
allowSkip = requireArguments().getBoolean(ALLOW_SKIP, true)
|
||||
|
||||
setupFragment = requireParentFragment() as SetupFragment
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setPositiveButton(R.string.warning_skip) { _: DialogInterface?, _: Int ->
|
||||
|
||||
if (allowSkip) {
|
||||
builder.setPositiveButton(R.string.warning_skip) { _: DialogInterface?, _: Int ->
|
||||
setupFragment.pageForward()
|
||||
setupFragment.setPageWarned(page)
|
||||
}
|
||||
.setNegativeButton(R.string.warning_cancel, null)
|
||||
builder.setNegativeButton(R.string.warning_cancel, null)
|
||||
} else {
|
||||
// For mandatory steps, only show an OK button that dismisses the dialog
|
||||
builder.setPositiveButton(R.string.ok, null)
|
||||
}
|
||||
|
||||
if (titleId != 0) {
|
||||
builder.setTitle(titleId)
|
||||
|
@ -48,7 +56,7 @@ class SetupWarningDialogFragment : DialogFragment() {
|
|||
}
|
||||
if (helpLinkId != 0) {
|
||||
builder.setNeutralButton(R.string.warning_help) { _: DialogInterface?, _: Int ->
|
||||
val helpLink = resources.getString(R.string.install_prod_keys_warning_help)
|
||||
val helpLink = resources.getString(helpLinkId)
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(helpLink))
|
||||
startActivity(intent)
|
||||
}
|
||||
|
@ -64,12 +72,14 @@ class SetupWarningDialogFragment : DialogFragment() {
|
|||
private const val DESCRIPTION = "Description"
|
||||
private const val HELP_LINK = "HelpLink"
|
||||
private const val PAGE = "Page"
|
||||
private const val ALLOW_SKIP = "AllowSkip"
|
||||
|
||||
fun newInstance(
|
||||
titleId: Int,
|
||||
descriptionId: Int,
|
||||
helpLinkId: Int,
|
||||
page: Int
|
||||
page: Int,
|
||||
allowSkip: Boolean = true
|
||||
): SetupWarningDialogFragment {
|
||||
val dialog = SetupWarningDialogFragment()
|
||||
val bundle = Bundle()
|
||||
|
@ -78,6 +88,7 @@ class SetupWarningDialogFragment : DialogFragment() {
|
|||
putInt(DESCRIPTION, descriptionId)
|
||||
putInt(HELP_LINK, helpLinkId)
|
||||
putInt(PAGE, page)
|
||||
putBoolean(ALLOW_SKIP, allowSkip)
|
||||
}
|
||||
dialog.arguments = bundle
|
||||
return dialog
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citron.citron_emu.network
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.format.Formatter
|
||||
import android.widget.Toast
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.citron.citron_emu.CitronApplication
|
||||
import org.citron.citron_emu.R
|
||||
import org.citron.citron_emu.dialogs.ChatMessage
|
||||
|
||||
object NetPlayManager {
|
||||
external fun netPlayCreateRoom(ipAddress: String, port: Int, username: String, password: String, roomName: String, maxPlayers: Int): Int
|
||||
external fun netPlayJoinRoom(ipAddress: String, port: Int, username: String, password: String): Int
|
||||
external fun netPlayRoomInfo(): Array<String>
|
||||
external fun netPlayIsJoined(): Boolean
|
||||
external fun netPlayIsHostedRoom(): Boolean
|
||||
external fun netPlaySendMessage(msg: String)
|
||||
external fun netPlayKickUser(username: String)
|
||||
external fun netPlayLeaveRoom()
|
||||
external fun netPlayIsModerator(): Boolean
|
||||
external fun netPlayGetBanList(): Array<String>
|
||||
external fun netPlayBanUser(username: String)
|
||||
external fun netPlayUnbanUser(username: String)
|
||||
|
||||
private var messageListener: ((Int, String) -> Unit)? = null
|
||||
private var adapterRefreshListener: ((Int, String) -> Unit)? = null
|
||||
|
||||
fun setOnMessageReceivedListener(listener: (Int, String) -> Unit) {
|
||||
messageListener = listener
|
||||
}
|
||||
|
||||
fun setOnAdapterRefreshListener(listener: (Int, String) -> Unit) {
|
||||
adapterRefreshListener = listener
|
||||
}
|
||||
|
||||
fun getUsername(activity: Context): String { val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
val name = "Citron${(Math.random() * 100).toInt()}"
|
||||
return prefs.getString("NetPlayUsername", name) ?: name
|
||||
}
|
||||
|
||||
fun setUsername(activity: Activity, name: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayUsername", name).apply()
|
||||
}
|
||||
|
||||
fun getRoomAddress(activity: Activity): String {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
val address = getIpAddressByWifi(activity)
|
||||
return prefs.getString("NetPlayRoomAddress", address) ?: address
|
||||
}
|
||||
|
||||
fun setRoomAddress(activity: Activity, address: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayRoomAddress", address).apply()
|
||||
}
|
||||
|
||||
fun getRoomPort(activity: Activity): String {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
return prefs.getString("NetPlayRoomPort", "24872") ?: "24872"
|
||||
}
|
||||
|
||||
fun setRoomPort(activity: Activity, port: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayRoomPort", port).apply()
|
||||
}
|
||||
|
||||
private val chatMessages = mutableListOf<ChatMessage>()
|
||||
private var isChatOpen = false
|
||||
|
||||
fun addChatMessage(message: ChatMessage) {
|
||||
chatMessages.add(message)
|
||||
}
|
||||
|
||||
fun getChatMessages(): List<ChatMessage> = chatMessages
|
||||
|
||||
fun clearChat() {
|
||||
chatMessages.clear()
|
||||
}
|
||||
|
||||
fun setChatOpen(isOpen: Boolean) {
|
||||
isChatOpen = isOpen
|
||||
}
|
||||
|
||||
fun addNetPlayMessage(type: Int, msg: String) {
|
||||
val context = CitronApplication.appContext
|
||||
val message = formatNetPlayStatus(context, type, msg)
|
||||
|
||||
when (type) {
|
||||
NetPlayStatus.CHAT_MESSAGE -> {
|
||||
val parts = msg.split(":", limit = 2)
|
||||
if (parts.size == 2) {
|
||||
val nickname = parts[0].trim()
|
||||
val chatMessage = parts[1].trim()
|
||||
addChatMessage(ChatMessage(
|
||||
nickname = nickname,
|
||||
username = "",
|
||||
message = chatMessage
|
||||
))
|
||||
}
|
||||
}
|
||||
NetPlayStatus.MEMBER_JOIN,
|
||||
NetPlayStatus.MEMBER_LEAVE,
|
||||
NetPlayStatus.MEMBER_KICKED,
|
||||
NetPlayStatus.MEMBER_BANNED -> {
|
||||
addChatMessage(ChatMessage(
|
||||
nickname = "System",
|
||||
username = "",
|
||||
message = message
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
if (!isChatOpen) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
messageListener?.invoke(type, msg)
|
||||
adapterRefreshListener?.invoke(type, msg)
|
||||
}
|
||||
|
||||
private fun formatNetPlayStatus(context: Context, type: Int, msg: String): String {
|
||||
return when (type) {
|
||||
NetPlayStatus.NETWORK_ERROR -> context.getString(R.string.multiplayer_network_error)
|
||||
NetPlayStatus.LOST_CONNECTION -> context.getString(R.string.multiplayer_lost_connection)
|
||||
NetPlayStatus.NAME_COLLISION -> context.getString(R.string.multiplayer_name_collision)
|
||||
NetPlayStatus.MAC_COLLISION -> context.getString(R.string.multiplayer_mac_collision)
|
||||
NetPlayStatus.CONSOLE_ID_COLLISION -> context.getString(R.string.multiplayer_console_id_collision)
|
||||
NetPlayStatus.WRONG_VERSION -> context.getString(R.string.multiplayer_wrong_version)
|
||||
NetPlayStatus.WRONG_PASSWORD -> context.getString(R.string.multiplayer_wrong_password)
|
||||
NetPlayStatus.COULD_NOT_CONNECT -> context.getString(R.string.multiplayer_could_not_connect)
|
||||
NetPlayStatus.ROOM_IS_FULL -> context.getString(R.string.multiplayer_room_is_full)
|
||||
NetPlayStatus.HOST_BANNED -> context.getString(R.string.multiplayer_host_banned)
|
||||
NetPlayStatus.PERMISSION_DENIED -> context.getString(R.string.multiplayer_permission_denied)
|
||||
NetPlayStatus.NO_SUCH_USER -> context.getString(R.string.multiplayer_no_such_user)
|
||||
NetPlayStatus.ALREADY_IN_ROOM -> context.getString(R.string.multiplayer_already_in_room)
|
||||
NetPlayStatus.CREATE_ROOM_ERROR -> context.getString(R.string.multiplayer_create_room_error)
|
||||
NetPlayStatus.HOST_KICKED -> context.getString(R.string.multiplayer_host_kicked)
|
||||
NetPlayStatus.UNKNOWN_ERROR -> context.getString(R.string.multiplayer_unknown_error)
|
||||
NetPlayStatus.ROOM_UNINITIALIZED -> context.getString(R.string.multiplayer_room_uninitialized)
|
||||
NetPlayStatus.ROOM_IDLE -> context.getString(R.string.multiplayer_room_idle)
|
||||
NetPlayStatus.ROOM_JOINING -> context.getString(R.string.multiplayer_room_joining)
|
||||
NetPlayStatus.ROOM_JOINED -> context.getString(R.string.multiplayer_room_joined)
|
||||
NetPlayStatus.ROOM_MODERATOR -> context.getString(R.string.multiplayer_room_moderator)
|
||||
NetPlayStatus.MEMBER_JOIN -> context.getString(R.string.multiplayer_member_join, msg)
|
||||
NetPlayStatus.MEMBER_LEAVE -> context.getString(R.string.multiplayer_member_leave, msg)
|
||||
NetPlayStatus.MEMBER_KICKED -> context.getString(R.string.multiplayer_member_kicked, msg)
|
||||
NetPlayStatus.MEMBER_BANNED -> context.getString(R.string.multiplayer_member_banned, msg)
|
||||
NetPlayStatus.ADDRESS_UNBANNED -> context.getString(R.string.multiplayer_address_unbanned)
|
||||
NetPlayStatus.CHAT_MESSAGE -> msg
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun getIpAddressByWifi(activity: Activity): String {
|
||||
var ipAddress = 0
|
||||
val wifiManager = activity.getSystemService(WifiManager::class.java)
|
||||
val wifiInfo = wifiManager.connectionInfo
|
||||
if (wifiInfo != null) {
|
||||
ipAddress = wifiInfo.ipAddress
|
||||
}
|
||||
|
||||
if (ipAddress == 0) {
|
||||
val dhcpInfo = wifiManager.dhcpInfo
|
||||
if (dhcpInfo != null) {
|
||||
ipAddress = dhcpInfo.ipAddress
|
||||
}
|
||||
}
|
||||
|
||||
return if (ipAddress == 0) {
|
||||
"192.168.0.1"
|
||||
} else {
|
||||
Formatter.formatIpAddress(ipAddress)
|
||||
}
|
||||
}
|
||||
|
||||
fun getBanList(): List<String> {
|
||||
return netPlayGetBanList().toList()
|
||||
}
|
||||
|
||||
object NetPlayStatus {
|
||||
const val NO_ERROR = 0
|
||||
const val NETWORK_ERROR = 1
|
||||
const val LOST_CONNECTION = 2
|
||||
const val NAME_COLLISION = 3
|
||||
const val MAC_COLLISION = 4
|
||||
const val CONSOLE_ID_COLLISION = 5
|
||||
const val WRONG_VERSION = 6
|
||||
const val WRONG_PASSWORD = 7
|
||||
const val COULD_NOT_CONNECT = 8
|
||||
const val ROOM_IS_FULL = 9
|
||||
const val HOST_BANNED = 10
|
||||
const val PERMISSION_DENIED = 11
|
||||
const val NO_SUCH_USER = 12
|
||||
const val ALREADY_IN_ROOM = 13
|
||||
const val CREATE_ROOM_ERROR = 14
|
||||
const val HOST_KICKED = 15
|
||||
const val UNKNOWN_ERROR = 16
|
||||
const val ROOM_UNINITIALIZED = 17
|
||||
const val ROOM_IDLE = 18
|
||||
const val ROOM_JOINING = 19
|
||||
const val ROOM_JOINED = 20
|
||||
const val ROOM_MODERATOR = 21
|
||||
const val MEMBER_JOIN = 22
|
||||
const val MEMBER_LEAVE = 23
|
||||
const val MEMBER_KICKED = 24
|
||||
const val MEMBER_BANNED = 25
|
||||
const val ADDRESS_UNBANNED = 26
|
||||
const val CHAT_MESSAGE = 27
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ import org.citron.citron_emu.HomeNavigationDirections
|
|||
import org.citron.citron_emu.NativeLibrary
|
||||
import org.citron.citron_emu.R
|
||||
import org.citron.citron_emu.databinding.ActivityMainBinding
|
||||
import org.citron.citron_emu.dialogs.NetPlayDialog
|
||||
import org.citron.citron_emu.features.settings.model.Settings
|
||||
import org.citron.citron_emu.fragments.AddGameFolderDialogFragment
|
||||
import org.citron.citron_emu.fragments.ProgressDialogFragment
|
||||
|
@ -68,6 +69,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
||||
|
||||
ThemeHelper.setTheme(this)
|
||||
NativeLibrary.netPlayInit()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
@ -157,6 +159,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||
setInsets()
|
||||
}
|
||||
|
||||
fun displayMultiplayerDialog() {
|
||||
val dialog = NetPlayDialog(this)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun checkKeys() {
|
||||
if (!NativeLibrary.areKeysPresent()) {
|
||||
MessageDialogFragment.newInstance(
|
||||
|
@ -370,6 +377,57 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||
return false
|
||||
}
|
||||
|
||||
val getTitleKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result != null) {
|
||||
processTitleKey(result)
|
||||
}
|
||||
}
|
||||
|
||||
fun processTitleKey(result: Uri): Boolean {
|
||||
if (FileUtil.getExtension(result) != "keys") {
|
||||
MessageDialogFragment.newInstance(
|
||||
this,
|
||||
titleId = R.string.reading_keys_failure,
|
||||
descriptionId = R.string.install_title_keys_failure_extension_description
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return false
|
||||
}
|
||||
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
|
||||
if (FileUtil.copyUriToInternalStorage(
|
||||
result,
|
||||
dstPath,
|
||||
"title.keys"
|
||||
) != null
|
||||
) {
|
||||
if (NativeLibrary.reloadKeys()) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.install_keys_success,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
homeViewModel.setCheckKeys(true)
|
||||
gamesViewModel.reloadGames(true)
|
||||
return true
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
this,
|
||||
titleId = R.string.invalid_keys_error,
|
||||
descriptionId = R.string.install_keys_failure_description,
|
||||
helpLinkId = R.string.dumping_keys_quickstart_link
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val getFirmware =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citron.citron_emu.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
|
||||
object CompatUtils {
|
||||
fun findActivity(context: Context): Activity {
|
||||
return when (context) {
|
||||
is Activity -> context
|
||||
is ContextWrapper -> findActivity(context.baseContext)
|
||||
else -> throw IllegalArgumentException("Context is not an Activity")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package org.citron.citron_emu.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.Signature
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
object LicenseVerifier {
|
||||
private const val EXPECTED_PACKAGE = "org.citron.citron_emu"
|
||||
private const val ALTERNATE_PACKAGE = "com.miHoYo.Yuanshen"
|
||||
private const val ALTERNATE_PACKAGE_2 = "com.antutu.ABenchMark"
|
||||
private const val OFFICIAL_HASH = "308202e4308201cc020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3231303831383138303335305a180f32303531303831313138303335305a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a0282010100803b4ba8d352ed0475a8442032eadb75ea0a865a0c310c59970bc5f011f162733941a17bac932e060a7f6b00e1d87e640d87951753ee396893769a6e4a60baddc2bf896cd46d5a08c8321879b955eeb6d9f43908029ec6e938433432c5a1ba19da26d8b3dba39f919695626fba5c412b4aba03d85f0246e79af54d6d57347aa6b5095fe916a34262e7060ef4d3f436e7ce03093757fb719b7e72267402289b0fd819673ee44b5aee23237be8e46be08df64b42de09be6090c49d6d0d7d301f0729e25c67eae2d862a87db0aa19db25ba291aae60c7740e0b745af0f1f236dadeb81fe29104a0731eb9091249a94bb56a90239b6496977ebaf1d98b6fa9f679cd0203010001300d06092a864886f70d01010505000382010100784d8e8d28b11bbdb09b5d9e7b8b4fac0d6defd2703d43da63ad4702af76f6ac700f5dcc2f480fbbf6fb664daa64132b36eb7a7880ade5be12919a14c8816b5c1da06870344902680e8ace430705d0a08158d44a3dc710fff6d60b6eb5eff4056bb7d462dafed5b8533c815988805c9f529ef1b70c7c10f1e225eded6db08f847ae805d8b37c174fa0b42cbab1053acb629711e60ce469de383173e714ae2ea76a975169785d1dbe330f803f7f12dd6616703dbaae4d4c327c5174bee83f83635e06f8634cf49d63ba5c3a4f865572740cf9e720e7df1d48fd7a4a2a651d7bb9f40d1cc6b6680b384827a6ea2a44cc1e5168218637fc5da0c3739caca8d21a1d"
|
||||
|
||||
fun verifyLicense(activity: Activity) {
|
||||
val currentPackage = activity.packageName
|
||||
val isDebugBuild = currentPackage.endsWith(".debug")
|
||||
val isEaBuild = currentPackage.endsWith(".ea")
|
||||
|
||||
// Check package name
|
||||
if (!isDebugBuild && !isEaBuild &&
|
||||
currentPackage != EXPECTED_PACKAGE &&
|
||||
currentPackage != ALTERNATE_PACKAGE &&
|
||||
currentPackage != ALTERNATE_PACKAGE_2) {
|
||||
showViolationDialog(activity)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
activity.packageManager.getPackageInfo(
|
||||
currentPackage,
|
||||
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNATURES.toLong())
|
||||
)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
activity.packageManager.getPackageInfo(currentPackage, PackageManager.GET_SIGNATURES)
|
||||
}
|
||||
|
||||
if (!verifySignature(packageInfo.signatures)) {
|
||||
showViolationDialog(activity)
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
showViolationDialog(activity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifySignature(signatures: Array<Signature>?): Boolean {
|
||||
if (signatures == null || signatures.isEmpty()) return false
|
||||
val currentSignature = signatures[0].toCharsString()
|
||||
return currentSignature == OFFICIAL_HASH
|
||||
}
|
||||
|
||||
private fun showViolationDialog(activity: Activity) {
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle("License Violation")
|
||||
.setMessage("This appears to be a modified version of Citron Emulator. " +
|
||||
"Redistributing modified versions without source code violates the GPLv3 License. " +
|
||||
"The application will now close.")
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("Exit") { _, _ ->
|
||||
activity.finish()
|
||||
Process.killProcess(Process.myPid())
|
||||
exitProcess(1)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: 2025 Citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
@ -51,7 +52,7 @@ struct Values {
|
|||
|
||||
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
|
||||
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
||||
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
||||
Settings::Setting<bool> black_backgrounds{linkage, true, "black_backgrounds",
|
||||
Settings::Category::Android};
|
||||
|
||||
// Input/performance overlay settings
|
||||
|
@ -67,8 +68,10 @@ struct Values {
|
|||
Settings::Category::Overlay};
|
||||
Settings::Setting<bool> show_performance_overlay{linkage, true, "show_performance_overlay",
|
||||
Settings::Category::Overlay};
|
||||
Settings::Setting<bool> show_thermal_overlay{linkage, false, "show_thermal_overlay",
|
||||
Settings::Setting<bool> show_thermal_overlay{linkage, true, "show_thermal_overlay",
|
||||
Settings::Category::Overlay};
|
||||
Settings::Setting<bool> show_ram_overlay{linkage, false, "show_ram_overlay",
|
||||
Settings::Category::Overlay};
|
||||
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
|
||||
Settings::Category::Overlay};
|
||||
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <frontend_common/content_manager.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "common/android/multiplayer/multiplayer.h"
|
||||
#include "common/android/android_common.h"
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/detached_tasks.h"
|
||||
|
@ -870,4 +871,83 @@ jboolean Java_org_citron_citron_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, j
|
|||
return ContentManager::AreKeysPresent();
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayCreateRoom(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
||||
jstring username, jstring password, jstring room_name, jint max_players) {
|
||||
return static_cast<jint>(
|
||||
NetPlayCreateRoom(Common::Android::GetJString(env, ipaddress), port,
|
||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password),
|
||||
Common::Android::GetJString(env, room_name), max_players));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayJoinRoom(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
||||
jstring username, jstring password) {
|
||||
return static_cast<jint>(
|
||||
NetPlayJoinRoom(Common::Android::GetJString(env, ipaddress), port,
|
||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password)));
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlayRoomInfo(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return Common::Android::ToJStringArray(env, NetPlayRoomInfo());
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlayIsJoined(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsJoined();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlayIsHostedRoom(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsHostedRoom();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlaySendMessage(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring msg) {
|
||||
NetPlaySendMessage(Common::Android::GetJString(env, msg));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayKickUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayKickUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayLeaveRoom(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
NetPlayLeaveRoom();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlayIsModerator(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsModerator();
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_citron_citron_1emu_network_NetPlayManager_netPlayGetBanList(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return Common::Android::ToJStringArray(env, NetPlayGetBanList());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayBanUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayBanUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_citron_citron_1emu_network_NetPlayManager_netPlayUnbanUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayUnbanUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_citron_citron_1emu_NativeLibrary_netPlayInit(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
NetworkInit(&EmulationSession::GetInstance().System().GetRoomNetwork());
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
31
src/android/app/src/main/jni/native_library.cpp
Normal file
31
src/android/app/src/main/jni/native_library.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "core/crypto/key_manager.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/system.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_org_citron_citron_1emu_NativeLibrary_isFirmwareAvailable(
|
||||
JNIEnv* env, jobject obj) {
|
||||
return Core::Crypto::KeyManager::Instance().IsFirmwareAvailable();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_org_citron_citron_1emu_NativeLibrary_checkFirmwarePresence(
|
||||
JNIEnv* env, jobject obj) {
|
||||
constexpr u64 MiiEditId = 0x0100000000001009; // Mii Edit applet ID
|
||||
constexpr u64 QLaunchId = 0x0100000000001000; // Home Menu applet ID
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto bis_system = system.GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
|
||||
auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
|
||||
|
||||
return (mii_applet_nca != nullptr && qlaunch_nca != nullptr);
|
||||
}
|
||||
|
||||
} // extern "C"
|
10
src/android/app/src/main/res/drawable/ic_chat.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_chat.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||
</vector>
|
9
src/android/app/src/main/res/drawable/ic_ip.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_ip.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/>
|
||||
</vector>
|
10
src/android/app/src/main/res/drawable/ic_joined.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_joined.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
9
src/android/app/src/main/res/drawable/ic_multiplayer.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_multiplayer.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
10
src/android/app/src/main/res/drawable/ic_network.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_network.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorPrimary"
|
||||
android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z"/>
|
||||
</vector>
|
9
src/android/app/src/main/res/drawable/ic_send.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_send.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
10
src/android/app/src/main/res/drawable/ic_system.xml
Normal file
10
src/android/app/src/main/res/drawable/ic_system.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"/>
|
||||
</vector>
|
9
src/android/app/src/main/res/drawable/ic_user.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_user.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
|
@ -34,28 +34,41 @@
|
|||
android:gravity="center"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/text_description"
|
||||
app:layout_constraintBottom_toTopOf="@+id/scroll_description"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
tools:text="@string/welcome" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_description"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="vertical"
|
||||
android:fadeScrollbars="false"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
app:lineHeight="30sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
app:layout_constraintVertical_weight="2">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_description"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="16dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:lineHeight="30sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_confirmation"
|
||||
|
@ -72,7 +85,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/scroll_description"
|
||||
app:layout_constraintVertical_weight="1"
|
||||
app:lineHeight="30sp" />
|
||||
|
||||
|
@ -88,7 +101,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/scroll_description"
|
||||
tools:text="Get started" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
7
src/android/app/src/main/res/layout/dialog_ban_list.xml
Normal file
7
src/android/app/src/main/res/layout/dialog_ban_list.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/ban_list_recycler"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"/>
|
38
src/android/app/src/main/res/layout/dialog_bottom_sheet.xml
Normal file
38
src/android/app/src/main/res/layout/dialog_bottom_sheet.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardCornerRadius="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="?colorSurface">
|
||||
|
||||
<View
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:backgroundTint="?colorSurfaceVariant" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
55
src/android/app/src/main/res/layout/dialog_chat.xml
Normal file
55
src/android/app/src/main/res/layout/dialog_chat.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/chat"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/chat_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:transcriptMode="alwaysScroll" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/type_message">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/chat_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionSend" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/send_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_send"
|
||||
android:contentDescription="@string/send_message" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:text="@string/multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:src="@drawable/ic_network"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_join"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/multiplayer_join_room"
|
||||
app:icon="@drawable/ic_install"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_create"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/multiplayer_create_room"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,75 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:text="@string/multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list_multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_chat"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="true"
|
||||
android:text="@string/multiplayer_chat"
|
||||
app:icon="@drawable/ic_chat"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_moderation"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="true"
|
||||
android:text="@string/multiplayer_moderation"
|
||||
app:cornerRadius="16dp"
|
||||
app:icon="@drawable/ic_user" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_leave"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:text="@string/multiplayer_exit_room"
|
||||
app:icon="@drawable/ic_exit"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
119
src/android/app/src/main/res/layout/dialog_multiplayer_room.xml
Normal file
119
src/android/app/src/main/res/layout/dialog_multiplayer_room.xml
Normal file
|
@ -0,0 +1,119 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"
|
||||
android:elevation="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="8dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_ip_address"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/ip_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_ip_port"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/ip_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_username"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_password"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_room_name"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/room_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/max_players_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/max_players"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:value="8"
|
||||
android:valueFrom="2"
|
||||
android:valueTo="16"
|
||||
android:stepSize="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/max_players_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/multiplayer_max_players_value" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@android:string/ok"
|
||||
android:layout_gravity="center" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -171,6 +171,21 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/show_ram_text"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginTop="24dp"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:textColor="@android:color/white"
|
||||
android:shadowColor="@android:color/black"
|
||||
android:shadowRadius="3"
|
||||
android:layout_below="@id/show_fps_text"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
|
|
28
src/android/app/src/main/res/layout/item_ban_list.xml
Normal file
28
src/android/app/src/main/res/layout/item_ban_list.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_user"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ban_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_unban"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/multiplayer_unban"/>
|
||||
</LinearLayout>
|
25
src/android/app/src/main/res/layout/item_button_netplay.xml
Normal file
25
src/android/app/src/main/res/layout/item_button_netplay.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_button_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/item_button_more"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/multiplayer_more_options"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:padding="12dp" />
|
||||
|
||||
</LinearLayout>
|
36
src/android/app/src/main/res/layout/item_chat_message.xml
Normal file
36
src/android/app/src/main/res/layout/item_chat_message.xml
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/user_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timestamp_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
25
src/android/app/src/main/res/layout/item_netplay_button.xml
Normal file
25
src/android/app/src/main/res/layout/item_netplay_button.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_button_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/item_button_netplay"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/multiplayer_kick_member"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/item_button_more"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_more_vert"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"/>
|
18
src/android/app/src/main/res/layout/item_netplay_text.xml
Normal file
18
src/android/app/src/main/res/layout/item_netplay_text.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text_netplay_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp" />
|
24
src/android/app/src/main/res/layout/item_text_netplay.xml
Normal file
24
src/android/app/src/main/res/layout/item_text_netplay.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||
|
||||
</LinearLayout>
|
|
@ -18,7 +18,7 @@
|
|||
app:layout_constraintHeight_min="110dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="spread"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintWidth_max="220dp"
|
||||
app:layout_constraintWidth_min="110dp"
|
||||
app:layout_constraintVertical_weight="3"
|
||||
|
@ -28,65 +28,56 @@
|
|||
android:id="@+id/text_title"
|
||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/text_description"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/scroll_description"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/icon"
|
||||
app:layout_constraintVertical_weight="1.3"
|
||||
tools:text="@string/welcome" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_description"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="vertical"
|
||||
android:fadeScrollbars="false"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:paddingVertical="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
app:lineHeight="30sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
app:layout_constraintVertical_weight="2">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_confirmation"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="24dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="30sp"
|
||||
android:visibility="invisible"
|
||||
android:text="@string/step_complete"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:layout_constraintVertical_weight="1"
|
||||
app:lineHeight="30sp" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_description"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:lineHeight="30sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconGravity="end"
|
||||
app:iconSize="24sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
tools:text="Get started" />
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
24
src/android/app/src/main/res/menu/item_text_netplay.xml
Normal file
24
src/android/app/src/main/res/menu/item_text_netplay.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
tools:ignore="ExtraText">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_pause_emulation"
|
||||
|
@ -21,6 +23,12 @@
|
|||
android:icon="@drawable/ic_controller"
|
||||
android:title="@string/preferences_controls" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_multiplayer"
|
||||
android:icon="@drawable/ic_multiplayer"
|
||||
android:title="@string/multiplayer" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_overlay_controls"
|
||||
android:icon="@drawable/ic_overlay"
|
||||
|
|
13
src/android/app/src/main/res/menu/menu_netplay_member.xml
Normal file
13
src/android/app/src/main/res/menu/menu_netplay_member.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/action_kick"
|
||||
android:title="@string/multiplayer_kick_member"
|
||||
android:enabled="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_ban"
|
||||
android:title="@string/multiplayer_ban"
|
||||
android:enabled="false" />
|
||||
|
||||
</menu>
|
|
@ -11,6 +11,11 @@
|
|||
android:title="@string/emulation_thermal_indicator"
|
||||
android:checkable="true" />
|
||||
|
||||
<item
|
||||
android:id="@+id/ram_meter"
|
||||
android:title="@string/emulation_ram_meter"
|
||||
android:checkable="true" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_edit_overlay"
|
||||
android:title="@string/emulation_touch_overlay_edit" />
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
<string name="about_app_description">محاكي سويتش مفتوح المصدر</string>
|
||||
<string name="contributors">المساهمين</string>
|
||||
<string name="contributors_description">مصنوع من فريق يوزو</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string>
|
||||
<string name="build">البناء</string>
|
||||
<string name="user_data">بيانات المستخدم</string>
|
||||
|
@ -151,7 +151,7 @@
|
|||
<string name="user_data_export_cancelled">تم إلغاء التصدير</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">الوصول المبكر</string>
|
||||
|
|
|
@ -103,12 +103,12 @@
|
|||
<string name="about_app_description">ئیمۆلیتەرێکی سەرچاوە-کراوەی سویچ</string>
|
||||
<string name="contributors">بەشداربووان</string>
|
||||
<string name="contributors_description">دروستکراوە لەگەڵ \u2764 لەلایەن تیمەکەی یوزو</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="licenses_description">ئەو پڕۆژانەی کە یوزوی بۆ ئەندرۆید ڕەخساند</string>
|
||||
<string name="build">بونیات</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">بەزوویی دەسپێگەشتن</string>
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
<string name="about_app_description">Open-source Switch emulátor</string>
|
||||
<string name="contributors">Přispěvatelé</string>
|
||||
<string name="contributors_description">Vyrobeno s \u2764 od citron týmu</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="build">Číslo sestavení</string>
|
||||
<string name="user_data">Uživatelská data</string>
|
||||
<string name="exporting_user_data">Exportování uživatelských dat...</string>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<string name="user_data_export_cancelled">Export zrušen</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.citron.citron_emu.ea</string>
|
||||
<string name="no_manual_installation">Žádná manuální instalace</string>
|
||||
|
|
|
@ -122,7 +122,7 @@ Wirklich fortfahren?</string>
|
|||
<string name="about_app_description">Ein quelloffener Switch-Emulator</string>
|
||||
<string name="contributors">Beitragende</string>
|
||||
<string name="contributors_description">Gemacht mit \u2764 vom citron Team</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="licenses_description">Projekte, die citron für Android möglich machen </string>
|
||||
<string name="build">Build</string>
|
||||
<string name="user_data">Nutzerdaten</string>
|
||||
|
@ -133,7 +133,7 @@ Wirklich fortfahren?</string>
|
|||
<string name="user_data_export_cancelled">Export abgebrochen</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
<string name="about_app_description">Un emulador de Switch de código abierto</string>
|
||||
<string name="contributors">Contribuidores</string>
|
||||
<string name="contributors_description">Hecho con \u2764 del equipo citron</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="licenses_description">Proyectos que hacen que citron para Android sea una realidad</string>
|
||||
<string name="build">Versión</string>
|
||||
<string name="user_data">Datos de usuario</string>
|
||||
|
@ -182,7 +182,7 @@
|
|||
<string name="user_data_import_failed_description">Asegúrese de que las carpetas de datos de usuario estén en la raíz de la carpeta del zip y contengan un archivo config en config/config.ini e inténtelo de nuevo.</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
<string name="about_app_description">یک شبیهساز سوئیچ منبع باز</string>
|
||||
<string name="contributors">مشارکت کنندگان</string>
|
||||
<string name="contributors_description">Made with \u2764 from the citron team</string>
|
||||
<string name="contributors_link">https://github.com/citron-emu/citron/graphs/contributors</string>
|
||||
<string name="contributors_link">https://git.citron-emu.org/Citron/Citron/graphs/contributors</string>
|
||||
<string name="licenses_description">پروژههایی که citron را برای اندروید ممکن میسازند</string>
|
||||
<string name="build">ساخت</string>
|
||||
<string name="user_data">داده کاربر</string>
|
||||
|
@ -180,7 +180,7 @@
|
|||
<string name="user_data_import_failed_description">مطمئن شوید که پوشههای داده کاربر در ریشه پوشه zip و حاوی یک فایل پیکربندی در config/config.ini هستند سپس دوباره امتحان کنید.</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://citron-emu.org/</string>
|
||||
<string name="github_link">https://github.com/citron-emu</string>
|
||||
<string name="github_link">https://git.citron-emu.org</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">دسترسی زودهنگام</string>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue