mirror of
https://git.citron-emu.org/Citron/Citron.git
synced 2025-02-07 16:56:21 +01:00
Update Android build configuration, add new CPU and memory options, and enhance patch manager handling for CTGP
- Updated the NDK version to 28.0.13004108. - Changed Java source and target compatibility to version 23. - Enabled resource shrinking and updated ProGuard files. - Added a new CPU accuracy option ("Safe") and a new memory layout option ("Software"). - Implemented special handling for CTGP patches, ensuring they are processed even if disabled. - Added logging for better traceability of patch processing. - Updated memory layout handling in various places to accommodate the new "Software" mode.
This commit is contained in:
parent
d4eca46bba
commit
1d379a30dc
9 changed files with 123 additions and 39 deletions
|
@ -28,7 +28,7 @@ android {
|
|||
namespace = "org.citron.citron_emu"
|
||||
compileSdk = 35
|
||||
|
||||
ndkVersion = "26.3.11579264"
|
||||
ndkVersion = "28.0.13004108" // "26.3.11579264"
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
|
@ -36,8 +36,8 @@ android {
|
|||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_23
|
||||
targetCompatibility = JavaVersion.VERSION_23
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
|
@ -107,9 +107,11 @@ android {
|
|||
resValue("string", "app_name_suffixed", "Citron")
|
||||
isDefault = true
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
isJniDebuggable = false
|
||||
isDebuggable = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android.txt"),
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
|
@ -122,7 +124,7 @@ android {
|
|||
isMinifyEnabled = true
|
||||
isDebuggable = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android.txt"),
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
versionNameSuffix = "-relWithDebInfo"
|
||||
|
@ -181,7 +183,7 @@ android {
|
|||
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
||||
)
|
||||
|
||||
abiFilters("arm64-v8a", "x86_64")
|
||||
abiFilters("arm64-v8a") //, "x86_64")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,8 +252,6 @@ dependencies {
|
|||
// Third Party Libraries
|
||||
implementation("io.coil-kt:coil:2.2.2")
|
||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||
|
||||
]]
|
||||
}
|
||||
|
||||
fun runGitCommand(command: List<String>): String {
|
||||
|
|
|
@ -352,6 +352,7 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
|
|||
PAIR(CpuAccuracy, Auto, tr("Auto")),
|
||||
PAIR(CpuAccuracy, Accurate, tr("Accurate")),
|
||||
PAIR(CpuAccuracy, Unsafe, tr("Unsafe")),
|
||||
PAIR(CpuAccuracy, Safe, tr("Safe (recommended for CTGP)")),
|
||||
PAIR(CpuAccuracy, Paranoid, tr("Paranoid (disables most optimizations)")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::CpuBackend>::Index(),
|
||||
|
@ -513,10 +514,11 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
|
|||
translations->insert({Settings::EnumMetadata<Settings::MemoryLayout>::Index(),
|
||||
{
|
||||
PAIR(MemoryLayout, Memory_4Gb, tr("4GB DRAM (Default)")),
|
||||
PAIR(MemoryLayout, Memory_6Gb, tr("6GB DRAM (Unsafe)")),
|
||||
PAIR(MemoryLayout, Memory_8Gb, tr("8GB DRAM (Unsafe)")),
|
||||
PAIR(MemoryLayout, Memory_10Gb, tr("10GB DRAM (Unsafe)")),
|
||||
PAIR(MemoryLayout, Memory_12Gb, tr("12GB DRAM (Unsafe)")),
|
||||
PAIR(MemoryLayout, Memory_6Gb, tr("6GB DRAM")),
|
||||
PAIR(MemoryLayout, Memory_8Gb, tr("8GB DRAM")),
|
||||
PAIR(MemoryLayout, Memory_10Gb, tr("10GB DRAM")),
|
||||
PAIR(MemoryLayout, Memory_12Gb, tr("12GB DRAM")),
|
||||
PAIR(MemoryLayout, Software, tr("Software (Maximum compatibility)")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::ConsoleMode>::Index(),
|
||||
{
|
||||
|
|
|
@ -132,9 +132,9 @@ ENUM(GpuAccuracy, Normal, High, Extreme);
|
|||
|
||||
ENUM(CpuBackend, Dynarmic, Nce);
|
||||
|
||||
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
|
||||
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid, Safe);
|
||||
|
||||
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb);
|
||||
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb, Software);
|
||||
|
||||
ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);
|
||||
|
||||
|
|
|
@ -195,12 +195,58 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
|
|||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
||||
const auto nso_build_id = fmt::format("{:0<64}", build_id);
|
||||
|
||||
// Special handling for CTGP patches
|
||||
const bool is_ctgp = patch_dirs.size() == 1 &&
|
||||
Common::ToLower(patch_dirs[0]->GetName()).find("ctgp") != std::string::npos;
|
||||
|
||||
std::vector<VirtualFile> out;
|
||||
out.reserve(patch_dirs.size());
|
||||
for (const auto& subdir : patch_dirs) {
|
||||
if (std::find(disabled.cbegin(), disabled.cend(), subdir->GetName()) != disabled.cend())
|
||||
// For CTGP patches, ensure we load them even if disabled
|
||||
if (!is_ctgp && std::find(disabled.cbegin(), disabled.cend(), subdir->GetName()) != disabled.cend())
|
||||
continue;
|
||||
|
||||
if (is_ctgp) {
|
||||
LOG_INFO(Loader, "Processing CTGP patch directory: {}", subdir->GetName());
|
||||
|
||||
auto exefs_dir = FindSubdirectoryCaseless(subdir, "exefs");
|
||||
if (exefs_dir != nullptr) {
|
||||
bool main_npdm_found = false;
|
||||
bool subsdk1_found = false;
|
||||
for (const auto& file : exefs_dir->GetFiles()) {
|
||||
if (file->GetName() == "main.npdm") {
|
||||
main_npdm_found = true;
|
||||
LOG_INFO(Loader, "Found main.npdm in CTGP patch directory.");
|
||||
}
|
||||
if (file->GetName() == "subsdk1") {
|
||||
subsdk1_found = true;
|
||||
LOG_INFO(Loader, "Found subsdk1 in CTGP patch directory.");
|
||||
}
|
||||
if (file->GetExtension() == "ips") {
|
||||
auto name = file->GetName();
|
||||
|
||||
const auto this_build_id =
|
||||
fmt::format("{:0<64}", name.substr(0, name.find('.')));
|
||||
if (nso_build_id == this_build_id)
|
||||
out.push_back(file);
|
||||
} else if (file->GetExtension() == "pchtxt") {
|
||||
IPSwitchCompiler compiler{file};
|
||||
if (!compiler.IsValid())
|
||||
continue;
|
||||
|
||||
const auto this_build_id = Common::HexToString(compiler.GetBuildID());
|
||||
if (nso_build_id == this_build_id)
|
||||
out.push_back(file);
|
||||
}
|
||||
}
|
||||
if (!main_npdm_found) {
|
||||
LOG_ERROR(Loader, "main.npdm not found in CTGP patch directory.");
|
||||
}
|
||||
if (!subsdk1_found) {
|
||||
LOG_ERROR(Loader, "subsdk1 not found in CTGP patch directory.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto exefs_dir = FindSubdirectoryCaseless(subdir, "exefs");
|
||||
if (exefs_dir != nullptr) {
|
||||
for (const auto& file : exefs_dir->GetFiles()) {
|
||||
|
@ -223,6 +269,7 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -263,10 +310,27 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
|
|||
return nso;
|
||||
}
|
||||
|
||||
// Special handling for CTGP
|
||||
if (name == "main" || name == "subsdk0") {
|
||||
LOG_INFO(Loader, "Applying CTGP-specific patch handling for {}", name);
|
||||
}
|
||||
|
||||
auto patch_dirs = load_dir->GetSubdirectories();
|
||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
||||
const auto patches = CollectPatches(patch_dirs, build_id);
|
||||
|
||||
// Prioritize CTGP patches if present
|
||||
const auto ctgp_dir = FindSubdirectoryCaseless(load_dir, "CTGP");
|
||||
std::vector<VirtualFile> patches;
|
||||
if (ctgp_dir != nullptr && (name == "main" || name == "subsdk0")) {
|
||||
patches = CollectPatches({ctgp_dir}, build_id);
|
||||
if (!patches.empty()) {
|
||||
LOG_INFO(Loader, "Found CTGP-specific patches for {}", name);
|
||||
}
|
||||
}
|
||||
if (patches.empty()) {
|
||||
patches = CollectPatches(patch_dirs, build_id);
|
||||
}
|
||||
|
||||
auto out = nso;
|
||||
for (const auto& patch_file : patches) {
|
||||
|
|
|
@ -52,6 +52,8 @@ u32 GetMemorySizeForInit() {
|
|||
return Smc::MemorySize_10GB;
|
||||
case Settings::MemoryLayout::Memory_12Gb:
|
||||
return Smc::MemorySize_12GB;
|
||||
case Settings::MemoryLayout::Software:
|
||||
return Smc::MemorySize_12GB; // Use maximum size for software mode
|
||||
}
|
||||
return Smc::MemorySize_4GB;
|
||||
}
|
||||
|
@ -68,6 +70,8 @@ Smc::MemoryArrangement GetMemoryArrangeForInit() {
|
|||
return Smc::MemoryArrangement_10GB;
|
||||
case Settings::MemoryLayout::Memory_12Gb:
|
||||
return Smc::MemoryArrangement_12GB;
|
||||
case Settings::MemoryLayout::Software:
|
||||
return Smc::MemoryArrangement_12GB; // Use maximum arrangement for software mode
|
||||
}
|
||||
return Smc::MemoryArrangement_4GB;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ constexpr std::size_t GetMaximumOverheadSize(std::size_t size) {
|
|||
|
||||
constexpr std::size_t MainMemorySize = 4_GiB;
|
||||
constexpr std::size_t MainMemorySizeMax = 12_GiB;
|
||||
constexpr std::size_t SoftwareMemorySize = 4_GiB; // Fixed size for software memory management mode
|
||||
|
||||
constexpr std::size_t ReservedEarlyDramSize = 384_KiB;
|
||||
constexpr std::size_t DramPhysicalAddress = 0x80000000;
|
||||
|
|
|
@ -36,13 +36,14 @@ constexpr KMemoryManager::Pool GetPoolFromMemoryRegionType(u32 type) {
|
|||
} // namespace
|
||||
|
||||
KMemoryManager::KMemoryManager(Core::System& system)
|
||||
: m_system{system}, m_memory_layout{system.Kernel().MemoryLayout()},
|
||||
m_pool_locks{
|
||||
KLightLock{system.Kernel()},
|
||||
KLightLock{system.Kernel()},
|
||||
KLightLock{system.Kernel()},
|
||||
KLightLock{system.Kernel()},
|
||||
} {}
|
||||
: m_system{system},
|
||||
m_memory_layout{system.Kernel().MemoryLayout()},
|
||||
m_pool_locks{KLightLock{system.Kernel()}, // Application
|
||||
KLightLock{system.Kernel()}, // Applet
|
||||
KLightLock{system.Kernel()}, // System
|
||||
KLightLock{system.Kernel()}, // SystemNonSecure
|
||||
KLightLock{system.Kernel()}} { // Software
|
||||
}
|
||||
|
||||
void KMemoryManager::Initialize(KVirtualAddress management_region, size_t management_region_size) {
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
Applet = 1,
|
||||
System = 2,
|
||||
SystemNonSecure = 3,
|
||||
Software = 4, // Software memory management mode
|
||||
|
||||
Count,
|
||||
|
||||
|
@ -37,6 +38,7 @@ public:
|
|||
// Aliases.
|
||||
Unsafe = Application,
|
||||
Secure = System,
|
||||
Safe = Software, // Alias for software mode
|
||||
};
|
||||
|
||||
enum class Direction : u32 {
|
||||
|
|
|
@ -182,6 +182,11 @@ struct Memory::Impl {
|
|||
}
|
||||
|
||||
void Write8(const Common::ProcessAddress addr, const u8 data) {
|
||||
// Check for null pointer write
|
||||
if (addr == 0 || addr < 0x1000) {
|
||||
LOG_ERROR(HW_Memory, "Null pointer Write8 @ 0x{:016X} = 0x{:02X}", addr, data);
|
||||
return;
|
||||
}
|
||||
Write<u8>(addr, data);
|
||||
}
|
||||
|
||||
|
@ -992,6 +997,11 @@ u64 Memory::Read64(const Common::ProcessAddress addr) {
|
|||
}
|
||||
|
||||
void Memory::Write8(Common::ProcessAddress addr, u8 data) {
|
||||
// Check for null pointer write
|
||||
if (addr == 0 || addr < 0x1000) {
|
||||
LOG_ERROR(HW_Memory, "Null pointer Write8 @ 0x{:016X} = 0x{:02X}", addr, data);
|
||||
return;
|
||||
}
|
||||
impl->Write8(addr, data);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue