Files
ARMSX2/ARMSX2-iOS-f0bccd9.patch
T
2026-05-29 13:29:06 -04:00

1345 lines
69 KiB
Diff

diff --git a/app/src/main/cpp/ARMSX2Bridge.h b/app/src/main/cpp/ARMSX2Bridge.h
index 10d02ab9a..2b8edaf5e 100644
--- a/app/src/main/cpp/ARMSX2Bridge.h
+++ b/app/src/main/cpp/ARMSX2Bridge.h
@@ -13,8 +13,10 @@ typedef NS_ENUM(NSInteger, ARMSX2EmulatorState) {
};
typedef NS_ENUM(NSInteger, ARMSX2CoreType) {
- ARMSX2CoreTypeJIT = 0,
+ ARMSX2CoreTypeLegacyRecompiler = 0,
ARMSX2CoreTypeInterpreter = 1,
+ ARMSX2CoreTypeARM64JIT = 2,
+ ARMSX2CoreTypeJIT = ARMSX2CoreTypeARM64JIT,
};
typedef NS_ENUM(NSInteger, ARMSX2PadButton) {
diff --git a/app/src/main/cpp/ARMSX2Bridge.mm b/app/src/main/cpp/ARMSX2Bridge.mm
index 4001e2531..ad35fd478 100644
--- a/app/src/main/cpp/ARMSX2Bridge.mm
+++ b/app/src/main/cpp/ARMSX2Bridge.mm
@@ -18,7 +18,9 @@
#include "common/Path.h"
#include "common/ZipHelpers.h"
+#include <algorithm>
#include <cstdio>
+#include <cstring>
#include <future>
#include <optional>
#include <string_view>
@@ -89,6 +91,49 @@ static BOOL ARMSX2GetCurrentSaveStateIdentity(std::string* serial, u32* crc)
return [NSData dataWithBytes:data->data() length:data->size()];
}
+static void ARMSX2ApplyLiveGSBoolSetting(const char* section, const char* key, bool value)
+{
+ if (std::strcmp(section, "EmuCore/GS") != 0)
+ return;
+
+#define APPLY_OSD_BOOL(name) \
+ do { \
+ if (std::strcmp(key, #name) == 0) { \
+ EmuConfig.GS.name = value; \
+ GSConfig.name = value; \
+ return; \
+ } \
+ } while (0)
+
+ APPLY_OSD_BOOL(OsdShowFPS);
+ APPLY_OSD_BOOL(OsdShowVPS);
+ APPLY_OSD_BOOL(OsdShowSpeed);
+ APPLY_OSD_BOOL(OsdShowCPU);
+ APPLY_OSD_BOOL(OsdShowGPU);
+ APPLY_OSD_BOOL(OsdShowResolution);
+ APPLY_OSD_BOOL(OsdShowGSStats);
+ APPLY_OSD_BOOL(OsdShowIndicators);
+ APPLY_OSD_BOOL(OsdShowSettings);
+ APPLY_OSD_BOOL(OsdShowInputs);
+ APPLY_OSD_BOOL(OsdShowFrameTimes);
+ APPLY_OSD_BOOL(OsdShowVersion);
+ APPLY_OSD_BOOL(OsdShowHardwareInfo);
+ APPLY_OSD_BOOL(OsdShowVideoCapture);
+ APPLY_OSD_BOOL(OsdShowInputRec);
+
+#undef APPLY_OSD_BOOL
+}
+
+static void ARMSX2ApplyLiveGSIntSetting(const char* section, const char* key, int value)
+{
+ if (std::strcmp(section, "EmuCore/GS") != 0 || std::strcmp(key, "OsdPerformancePos") != 0)
+ return;
+
+ const int clamped = std::clamp(value, static_cast<int>(OsdOverlayPos::None), static_cast<int>(OsdOverlayPos::TopRight));
+ EmuConfig.GS.OsdPerformancePos = static_cast<OsdOverlayPos>(clamped);
+ GSConfig.OsdPerformancePos = static_cast<OsdOverlayPos>(clamped);
+}
+
@implementation ARMSX2Bridge
+ (UIView *)gameRenderView {
@@ -195,7 +240,7 @@ + (nonnull NSString *)biosName {
+ (void)requestVMStop {
extern std::atomic<bool> s_requestVMStop;
s_requestVMStop.store(true);
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ARMSX2iOSVMDidShutdown" object:nil];
+ NSLog(@"[ARMSX2Bridge] VM stop requested");
}
+ (void)setFullScreen:(BOOL)enabled {
@@ -209,7 +254,9 @@ + (nonnull NSString *)buildVersion {
+ (nullable NSString *)currentISOPath {
NSString *docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
- NSString *iniPath = [docsPath stringByAppendingPathComponent:@"PCSX2-iOS.ini"];
+ NSString *iniPath = [docsPath stringByAppendingPathComponent:@"ARMSX2-iOS.ini"];
+ if (![[NSFileManager defaultManager] fileExistsAtPath:iniPath])
+ iniPath = [docsPath stringByAppendingPathComponent:@"PCSX2-iOS.ini"];
// Read BootISO from INI
FILE *f = fopen(iniPath.UTF8String, "r");
if (!f) return nil;
@@ -310,28 +357,60 @@ + (void)applyOsdPreset:(int)preset {
GSConfig.OsdShowFrameTimes = false;
GSConfig.OsdShowVersion = false;
GSConfig.OsdShowHardwareInfo = false;
+ GSConfig.OsdShowIndicators = false;
+ GSConfig.OsdShowSettings = false;
+ GSConfig.OsdShowInputs = false;
+ GSConfig.OsdShowVideoCapture = false;
+ GSConfig.OsdShowInputRec = false;
switch (preset) {
- case 1: // simple: FPS + CPU usage
+ case 1: // simple: Android-style quick readout
GSConfig.OsdShowFPS = true;
+ GSConfig.OsdShowSpeed = true;
GSConfig.OsdShowCPU = true;
+ GSConfig.OsdShowIndicators = true;
break;
- case 2: // detail: simple + speed + resolution
+ case 2: // detail: performance and renderer diagnostics
GSConfig.OsdShowFPS = true;
+ GSConfig.OsdShowVPS = true;
GSConfig.OsdShowSpeed = true;
GSConfig.OsdShowCPU = true;
+ GSConfig.OsdShowGPU = true;
GSConfig.OsdShowResolution = true;
+ GSConfig.OsdShowIndicators = true;
break;
- case 3: // full: detail + frame times
+ case 3: // full: closest to Android's full stats section
GSConfig.OsdShowFPS = true;
+ GSConfig.OsdShowVPS = true;
GSConfig.OsdShowSpeed = true;
GSConfig.OsdShowCPU = true;
+ GSConfig.OsdShowGPU = true;
GSConfig.OsdShowResolution = true;
+ GSConfig.OsdShowGSStats = true;
GSConfig.OsdShowFrameTimes = true;
+ GSConfig.OsdShowVersion = true;
+ GSConfig.OsdShowHardwareInfo = true;
+ GSConfig.OsdShowIndicators = true;
+ GSConfig.OsdShowSettings = true;
+ GSConfig.OsdShowInputs = true;
break;
default: // 0 = off
break;
}
+
+ EmuConfig.GS.OsdShowFPS = GSConfig.OsdShowFPS;
+ EmuConfig.GS.OsdShowVPS = GSConfig.OsdShowVPS;
+ EmuConfig.GS.OsdShowSpeed = GSConfig.OsdShowSpeed;
+ EmuConfig.GS.OsdShowCPU = GSConfig.OsdShowCPU;
+ EmuConfig.GS.OsdShowGPU = GSConfig.OsdShowGPU;
+ EmuConfig.GS.OsdShowResolution = GSConfig.OsdShowResolution;
+ EmuConfig.GS.OsdShowGSStats = GSConfig.OsdShowGSStats;
+ EmuConfig.GS.OsdShowFrameTimes = GSConfig.OsdShowFrameTimes;
+ EmuConfig.GS.OsdShowVersion = GSConfig.OsdShowVersion;
+ EmuConfig.GS.OsdShowHardwareInfo = GSConfig.OsdShowHardwareInfo;
+ EmuConfig.GS.OsdShowIndicators = GSConfig.OsdShowIndicators;
+ EmuConfig.GS.OsdShowSettings = GSConfig.OsdShowSettings;
+ EmuConfig.GS.OsdShowInputs = GSConfig.OsdShowInputs;
}
// ============================================================
@@ -438,12 +517,14 @@ + (void)setINIInt:(nonnull NSString *)section key:(nonnull NSString *)key value:
if (!g_p44_settings_interface) return;
g_p44_settings_interface->SetIntValue(section.UTF8String, key.UTF8String, value);
g_p44_settings_interface->Save();
+ ARMSX2ApplyLiveGSIntSetting(section.UTF8String, key.UTF8String, value);
}
+ (void)setINIBool:(nonnull NSString *)section key:(nonnull NSString *)key value:(BOOL)value {
if (!g_p44_settings_interface) return;
g_p44_settings_interface->SetBoolValue(section.UTF8String, key.UTF8String, value);
g_p44_settings_interface->Save();
+ ARMSX2ApplyLiveGSBoolSetting(section.UTF8String, key.UTF8String, value);
}
+ (void)setINIFloat:(nonnull NSString *)section key:(nonnull NSString *)key value:(float)value {
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index 8e72c0431..76e8ab8c5 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -228,7 +228,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks /usr/lib/swift"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) /usr/lib/swift"
XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS ""
- XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/pcsx2/GS/Renderers/Metal ${CMAKE_SOURCE_DIR}/../assets"
+ XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/pcsx2/GS/Renderers/Metal ${CMAKE_SOURCE_DIR}/3rdparty/include ${CMAKE_SOURCE_DIR}/../assets ${CMAKE_SOURCE_DIR}/../assets/resources"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO "$<IF:$<CONFIG:Debug>,INCLUDE_SOURCE,>"
)
diff --git a/app/src/main/cpp/cmake/BuildParameters.cmake b/app/src/main/cpp/cmake/BuildParameters.cmake
index 88bacfb79..7420144b2 100644
--- a/app/src/main/cpp/cmake/BuildParameters.cmake
+++ b/app/src/main/cpp/cmake/BuildParameters.cmake
@@ -119,7 +119,7 @@ elseif("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64" OR "${CMAKE_HOST_SYSTEM
# add_compile_options("-march=armv8.4-a" "-mcpu=apple-m1")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
- add_definitions("-march=armv8-a+crc")
+ add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-march=armv8-a+crc>")
# If we're running on Linux, we need to detect the page/cache line size.
# It could be a virtual machine with 4K pages, or 16K with Asahi.
@@ -159,7 +159,11 @@ if(MSVC)
# Disable Exceptions
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
else()
- add_compile_options(-pipe -fvisibility=hidden -pthread)
+ add_compile_options(
+ "$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-pipe>"
+ "$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fvisibility=hidden>"
+ "$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-pthread>"
+ )
add_compile_options(
"$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>"
)
diff --git a/app/src/main/cpp/common/Darwin/DarwinMisc.cpp b/app/src/main/cpp/common/Darwin/DarwinMisc.cpp
index 624bf70f5..3c2fd9056 100644
--- a/app/src/main/cpp/common/Darwin/DarwinMisc.cpp
+++ b/app/src/main/cpp/common/Darwin/DarwinMisc.cpp
@@ -832,6 +832,10 @@ void DarwinMisc::MunmapCodeDualMap(void* rx_ptr, size_t size)
bool DarwinMisc::IsJITAvailable()
{
+ static std::optional<bool> s_cached_jit_available;
+ if (s_cached_jit_available.has_value())
+ return *s_cached_jit_available;
+
#if ARMSX2_APPLE_IOS_DEVICE
uint32_t cs_flags = 0;
int rv = csops(getpid(), 0, &cs_flags, sizeof(cs_flags));
@@ -844,11 +848,13 @@ bool DarwinMisc::IsJITAvailable()
fprintf(stderr, "@@JIT_DETECT@@ result=UNAVAILABLE (no CS_DEBUGGED — launch via StikDebug)\n");
s_jit_mode = JitMode::Legacy;
s_jit_mode_detected = true;
- return false;
+ s_cached_jit_available = false;
+ return *s_cached_jit_available;
}
fprintf(stderr, "@@JIT_DETECT@@ result=AVAILABLE (CS_DEBUGGED set)\n");
- return true;
+ s_cached_jit_available = true;
+ return *s_cached_jit_available;
#else
const size_t probe_size = static_cast<size_t>(getpagesize());
void* probe = mmap(nullptr, probe_size, PROT_READ | PROT_WRITE | PROT_EXEC,
@@ -856,12 +862,14 @@ bool DarwinMisc::IsJITAvailable()
if (probe == MAP_FAILED)
{
fprintf(stderr, "@@JIT_DETECT@@ MAP_JIT probe failed errno=%d\n", errno);
- return false;
+ s_cached_jit_available = false;
+ return *s_cached_jit_available;
}
munmap(probe, probe_size);
fprintf(stderr, "@@JIT_DETECT@@ MAP_JIT probe result=AVAILABLE\n");
- return true;
+ s_cached_jit_available = true;
+ return *s_cached_jit_available;
#endif
}
@@ -1088,8 +1096,21 @@ void HostSys::BeginCodeWrite()
}
} else {
static auto func = reinterpret_cast<void(*)(int)>(dlsym(RTLD_DEFAULT, "pthread_jit_write_protect_np"));
+ static bool s_logged_pthread_jit_begin = false;
if (func)
+ {
+ if (!s_logged_pthread_jit_begin)
+ {
+ fprintf(stderr, "@@JIT_WRITE_PROTECT@@ pthread_jit_write_protect_np available=1 action=begin_write protect=0\n");
+ s_logged_pthread_jit_begin = true;
+ }
func(0);
+ }
+ else if (!s_logged_pthread_jit_begin)
+ {
+ fprintf(stderr, "@@JIT_WRITE_PROTECT@@ pthread_jit_write_protect_np available=0 action=begin_write\n");
+ s_logged_pthread_jit_begin = true;
+ }
}
}
}
@@ -1120,8 +1141,21 @@ void HostSys::EndCodeWrite()
}
} else {
static auto func = reinterpret_cast<void(*)(int)>(dlsym(RTLD_DEFAULT, "pthread_jit_write_protect_np"));
+ static bool s_logged_pthread_jit_end = false;
if (func)
+ {
+ if (!s_logged_pthread_jit_end)
+ {
+ fprintf(stderr, "@@JIT_WRITE_PROTECT@@ pthread_jit_write_protect_np available=1 action=end_write protect=1\n");
+ s_logged_pthread_jit_end = true;
+ }
func(1);
+ }
+ else if (!s_logged_pthread_jit_end)
+ {
+ fprintf(stderr, "@@JIT_WRITE_PROTECT@@ pthread_jit_write_protect_np available=0 action=end_write\n");
+ s_logged_pthread_jit_end = true;
+ }
}
}
}
diff --git a/app/src/main/cpp/ios_main.mm b/app/src/main/cpp/ios_main.mm
index e688872dc..431562f55 100644
--- a/app/src/main/cpp/ios_main.mm
+++ b/app/src/main/cpp/ios_main.mm
@@ -22,6 +22,7 @@
#include <cstdio>
#include <cstring>
#include <string>
+#include <string_view>
#include <iostream>
#include <algorithm>
#include <deque>
@@ -729,6 +730,7 @@ void DestroyMetalLayer(WindowInfo* wi) {
#include "pcsx2/INISettingsInterface.h"
static INISettingsInterface* s_settings_interface = nullptr;
+static std::string s_iosSettingsPath;
// Expose to ARMSX2Bridge.mm via extern
INISettingsInterface* g_p44_settings_interface = nullptr;
@@ -826,22 +828,36 @@ static void ARMSX2LogIOSSettingsSnapshot(const char* tag, INISettingsInterface*
const bool recVU0 = si->GetBoolValue("EmuCore/CPU/Recompiler", "EnableVU0", false);
const bool recVU1 = si->GetBoolValue("EmuCore/CPU/Recompiler", "EnableVU1", false);
const bool extraMemory = si->GetBoolValue("EmuCore/CPU", "ExtraMemory", false);
+ const bool fastmem = si->GetBoolValue("EmuCore/CPU/Recompiler", "EnableFastmem", false);
const int gsRenderer = si->GetIntValue("EmuCore/GS", "Renderer", -999);
const int vsyncQueue = si->GetIntValue("EmuCore/GS", "VsyncQueueSize", -999);
const bool mtvu = si->GetBoolValue("EmuCore/Speedhacks", "MTVU", false);
const bool vuThread = si->GetBoolValue("EmuCore/Speedhacks", "vuThread", false);
+ const std::string bootISO = si->GetStringValue("GameISO", "BootISO", "");
+ const std::string biosName = si->GetStringValue("Filenames", "BIOS", "");
+#if ARMSX2_APPLE_MAC_RUNTIME
+ const bool jitAvailable = true;
+ const bool noJitActive = false;
+#else
+ const bool forceEEInterp = (DarwinMisc::ARMSX2_FORCE_EE_INTERP != 0);
+ const bool forceJit = (DarwinMisc::ARMSX2_FORCE_JIT != 0);
+ const bool jitAvailable = forceJit || (!forceEEInterp && DarwinMisc::IsJITAvailable());
+ const bool noJitActive = forceEEInterp || (!forceJit && !jitAvailable) || cpuCore == 1;
+#endif
fprintf(stderr,
- "@@IOS_SETTINGS@@ tag=%s si=%p spu2_backend=%s cpu_core=%d arm64_dynarec=%d rec_ee=%d rec_iop=%d rec_vu0=%d rec_vu1=%d extra_memory=%d gs_renderer=%d vsync_queue=%d mtvu=%d vu_thread=%d\n",
- tag, si, spu2Backend.c_str(), cpuCore, arm64Dynarec ? 1 : 0, recEE ? 1 : 0, recIOP ? 1 : 0,
- recVU0 ? 1 : 0, recVU1 ? 1 : 0, extraMemory ? 1 : 0, gsRenderer, vsyncQueue, mtvu ? 1 : 0,
- vuThread ? 1 : 0);
+ "@@IOS_SETTINGS@@ tag=%s si=%p config_path=%s data_root=%s bios_dir=%s boot_iso=\"%s\" bios_name=\"%s\" spu2_backend=%s cpu_core=%d arm64_dynarec=%d rec_ee=%d rec_iop=%d rec_vu0=%d rec_vu1=%d fastmem=%d extra_memory=%d gs_renderer=%d vsync_queue=%d mtvu=%d vu_thread=%d jit_available=%d no_jit_active=%d\n",
+ tag, si, s_iosSettingsPath.c_str(), EmuFolders::DataRoot.c_str(), EmuFolders::Bios.c_str(), bootISO.c_str(),
+ biosName.c_str(), spu2Backend.c_str(), cpuCore, arm64Dynarec ? 1 : 0, recEE ? 1 : 0, recIOP ? 1 : 0,
+ recVU0 ? 1 : 0, recVU1 ? 1 : 0, fastmem ? 1 : 0, extraMemory ? 1 : 0, gsRenderer, vsyncQueue,
+ mtvu ? 1 : 0, vuThread ? 1 : 0, jitAvailable ? 1 : 0, noJitActive ? 1 : 0);
fflush(stderr);
Console.WriteLn(
- "@@IOS_SETTINGS@@ tag=%s si=%p spu2_backend=%s cpu_core=%d arm64_dynarec=%d rec_ee=%d rec_iop=%d rec_vu0=%d rec_vu1=%d extra_memory=%d gs_renderer=%d vsync_queue=%d mtvu=%d vu_thread=%d",
- tag, si, spu2Backend.c_str(), cpuCore, arm64Dynarec ? 1 : 0, recEE ? 1 : 0, recIOP ? 1 : 0,
- recVU0 ? 1 : 0, recVU1 ? 1 : 0, extraMemory ? 1 : 0, gsRenderer, vsyncQueue, mtvu ? 1 : 0,
- vuThread ? 1 : 0);
+ "@@IOS_SETTINGS@@ tag=%s si=%p config_path=%s data_root=%s bios_dir=%s boot_iso=\"%s\" bios_name=\"%s\" spu2_backend=%s cpu_core=%d arm64_dynarec=%d rec_ee=%d rec_iop=%d rec_vu0=%d rec_vu1=%d fastmem=%d extra_memory=%d gs_renderer=%d vsync_queue=%d mtvu=%d vu_thread=%d jit_available=%d no_jit_active=%d",
+ tag, si, s_iosSettingsPath.c_str(), EmuFolders::DataRoot.c_str(), EmuFolders::Bios.c_str(), bootISO.c_str(),
+ biosName.c_str(), spu2Backend.c_str(), cpuCore, arm64Dynarec ? 1 : 0, recEE ? 1 : 0, recIOP ? 1 : 0,
+ recVU0 ? 1 : 0, recVU1 ? 1 : 0, fastmem ? 1 : 0, extraMemory ? 1 : 0, gsRenderer, vsyncQueue,
+ mtvu ? 1 : 0, vuThread ? 1 : 0, jitAvailable ? 1 : 0, noJitActive ? 1 : 0);
}
static constexpr const char* ARMSX2_IOS_JIT_SECTION = "ARMSX2iOS/JIT";
@@ -894,6 +910,36 @@ static void ARMSX2RestoreIOSJitDefaults(INISettingsInterface* si)
si->SetBoolValue("EmuCore/CPU/Recompiler", "EnableFastmem", true);
}
+static const char* ARMSX2NormalizeGSAspectRatio(std::string_view value)
+{
+ if (value == "Stretch" || value == "0")
+ return "Stretch";
+ if (value == "Auto 4:3/3:2" || value == "1")
+ return "Auto 4:3/3:2";
+ if (value == "4:3" || value == "2")
+ return "4:3";
+ if (value == "16:9" || value == "3")
+ return "16:9";
+ if (value == "10:7" || value == "4")
+ return "10:7";
+ return nullptr;
+}
+
+static const char* ARMSX2NormalizeGSFMVAspectRatioSwitch(std::string_view value)
+{
+ if (value == "Off" || value == "0")
+ return "Off";
+ if (value == "Auto 4:3/3:2" || value == "1")
+ return "Auto 4:3/3:2";
+ if (value == "4:3" || value == "2")
+ return "4:3";
+ if (value == "16:9" || value == "3")
+ return "16:9";
+ if (value == "10:7" || value == "4")
+ return "10:7";
+ return nullptr;
+}
+
static void ARMSX2ApplyIOSRuntimeDefaults(INISettingsInterface* si)
{
if (!si)
@@ -948,9 +994,10 @@ static void ARMSX2ApplyIOSRuntimeDefaults(INISettingsInterface* si)
si->SetBoolValue("EmuCore/CPU/Recompiler", "EnableVU1", true);
si->SetBoolValue("EmuCore/CPU/Recompiler", "EnableFastmem", true);
#else
+ const int configured_core_type = si->GetIntValue("EmuCore/CPU", "CoreType", 2);
if (!si->ContainsValue("EmuCore/CPU", "CoreType"))
si->SetIntValue("EmuCore/CPU", "CoreType", 2);
- if (!si->ContainsValue("EmuCore/CPU", "UseArm64Dynarec"))
+ if (configured_core_type == 2 || !si->ContainsValue("EmuCore/CPU", "UseArm64Dynarec"))
si->SetBoolValue("EmuCore/CPU", "UseArm64Dynarec", true);
if (!si->ContainsValue("EmuCore/CPU/Recompiler", "EnableEE"))
si->SetBoolValue("EmuCore/CPU/Recompiler", "EnableEE", true);
@@ -984,8 +1031,25 @@ static void ARMSX2ApplyIOSRuntimeDefaults(INISettingsInterface* si)
break;
}
#endif
- si->SetStringValue("EmuCore/GS", "AspectRatio", "Auto 4:3/3:2");
- si->SetStringValue("EmuCore/GS", "FMVAspectRatioSwitch", "Off");
+ const std::string configured_aspect_ratio = si->GetStringValue("EmuCore/GS", "AspectRatio", "");
+ const char* normalized_aspect_ratio = ARMSX2NormalizeGSAspectRatio(configured_aspect_ratio);
+ if (!normalized_aspect_ratio) {
+ Console.Warning("@@IOS_SETTINGS@@ invalid AspectRatio=\"%s\" fallback=\"Auto 4:3/3:2\"",
+ configured_aspect_ratio.c_str());
+ normalized_aspect_ratio = "Auto 4:3/3:2";
+ }
+ if (configured_aspect_ratio != normalized_aspect_ratio)
+ si->SetStringValue("EmuCore/GS", "AspectRatio", normalized_aspect_ratio);
+
+ const std::string configured_fmv_aspect = si->GetStringValue("EmuCore/GS", "FMVAspectRatioSwitch", "");
+ const char* normalized_fmv_aspect = ARMSX2NormalizeGSFMVAspectRatioSwitch(configured_fmv_aspect);
+ if (!normalized_fmv_aspect) {
+ Console.Warning("@@IOS_SETTINGS@@ invalid FMVAspectRatioSwitch=\"%s\" fallback=\"Off\"",
+ configured_fmv_aspect.c_str());
+ normalized_fmv_aspect = "Off";
+ }
+ if (configured_fmv_aspect != normalized_fmv_aspect)
+ si->SetStringValue("EmuCore/GS", "FMVAspectRatioSwitch", normalized_fmv_aspect);
ARMSX2ClampINIInt(si, "EmuCore/GS", "VsyncQueueSize", 2, 0, 8);
ARMSX2ClampINIInt(si, "EmuCore/GS", "deinterlace_mode", static_cast<int>(GSInterlaceMode::Automatic), 0, static_cast<int>(GSInterlaceMode::Count) - 1);
ARMSX2ClampINIInt(si, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic), 0, static_cast<int>(AccBlendLevel::Maximum));
@@ -1026,12 +1090,12 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session op
// --- SDL Initialization ---
static bool s_initialized = false;
- if (!s_initialized) {
- SDL_SetMainReady();
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD) < 0) {
- NSLog(@"SDL_Init failed: %s", SDL_GetError());
- return;
- }
+ if (!s_initialized) {
+ SDL_SetMainReady();
+ if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) {
+ NSLog(@"SDL_Init failed: %s", SDL_GetError());
+ return;
+ }
s_initialized = true;
}
@@ -1059,6 +1123,7 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session op
}
std::string iniPath = [iniPathString UTF8String];
+ s_iosSettingsPath = iniPath;
s_settings_interface = new INISettingsInterface(iniPath);
if (!static_cast<INISettingsInterface*>(s_settings_interface)->Load()) {
Console.WriteLn("Creating new config at %s", iniPath.c_str());
@@ -1509,8 +1574,17 @@ - (void)checkJITAndStartVM {
const bool force_jit = (DarwinMisc::ARMSX2_FORCE_JIT != 0);
const bool jit_available = force_jit || (!force_ee_interp && DarwinMisc::IsJITAvailable());
const bool jit_unavailable = !force_ee_interp && !force_jit && !jit_available;
+ const bool config_interpreter = ARMSX2IOSConfigRequestsInterpreter(s_settings_interface);
+ const char* fallback_reason =
+ force_ee_interp ? "env_force_ee_interp" :
+ (config_interpreter ? "config_interpreter" :
+ (jit_unavailable ? "jit_unavailable" : "none"));
- if (!jit_available || force_ee_interp || ARMSX2IOSConfigRequestsInterpreter(s_settings_interface)) {
+ Console.WriteLn("@@JIT_GATE@@ force_ee_interp=%d force_jit=%d jit_available=%d config_interpreter=%d fallback_reason=%s",
+ force_ee_interp ? 1 : 0, force_jit ? 1 : 0, jit_available ? 1 : 0, config_interpreter ? 1 : 0,
+ fallback_reason);
+
+ if (!jit_available || force_ee_interp || config_interpreter) {
if (s_settings_interface) {
if (jit_unavailable)
ARMSX2SetAutoNoJitFallback(s_settings_interface);
@@ -1727,6 +1801,35 @@ - (void)startVMThread {
}
const std::string bios_path = Path::Combine(EmuFolders::Bios, EmuConfig.BaseFilenames.Bios);
+ const std::string selected_game_path =
+ !boot_params.elf_override.empty() ? boot_params.elf_override :
+ (!boot_params.filename.empty() ? boot_params.filename : std::string());
+ const bool boot_arm64_dynarec =
+ s_settings_interface ? s_settings_interface->GetBoolValue("EmuCore/CPU", "UseArm64Dynarec", EmuConfig.Cpu.CoreType == 2) :
+ (EmuConfig.Cpu.CoreType == 2);
+#if ARMSX2_APPLE_MAC_RUNTIME
+ const bool boot_jit_available = true;
+ const bool boot_no_jit_active = false;
+ const char* boot_fallback_reason = "none";
+#else
+ const bool boot_force_ee_interp = (DarwinMisc::ARMSX2_FORCE_EE_INTERP != 0);
+ const bool boot_force_jit = (DarwinMisc::ARMSX2_FORCE_JIT != 0);
+ const bool boot_jit_available = boot_force_jit || (!boot_force_ee_interp && DarwinMisc::IsJITAvailable());
+ const bool boot_no_jit_active = boot_force_ee_interp || (!boot_force_jit && !boot_jit_available) || EmuConfig.Cpu.CoreType == 1;
+ const char* boot_fallback_reason =
+ boot_force_ee_interp ? "env_force_ee_interp" :
+ (EmuConfig.Cpu.CoreType == 1 ? "config_interpreter" :
+ (!boot_jit_available ? "jit_unavailable" : "none"));
+#endif
+ Console.WriteLn(
+ "@@IOS_BOOT_DIAG@@ config_path=%s data_root=%s bios_dir=%s bios_name=\"%s\" bios_path=%s bios_exists=%d game_path=%s renderer=%d core_type=%d arm64_dynarec=%d ee_rec=%d iop_rec=%d vu0_rec=%d vu1_rec=%d fastmem=%d jit_available=%d no_jit_active=%d fallback_reason=%s",
+ s_iosSettingsPath.c_str(), EmuFolders::DataRoot.c_str(), EmuFolders::Bios.c_str(),
+ EmuConfig.BaseFilenames.Bios.c_str(), bios_path.c_str(), FileSystem::FileExists(bios_path.c_str()) ? 1 : 0,
+ selected_game_path.c_str(), static_cast<int>(EmuConfig.GS.Renderer), EmuConfig.Cpu.CoreType,
+ boot_arm64_dynarec ? 1 : 0, EmuConfig.Cpu.Recompiler.EnableEE ? 1 : 0,
+ EmuConfig.Cpu.Recompiler.EnableIOP ? 1 : 0, EmuConfig.Cpu.Recompiler.EnableVU0 ? 1 : 0,
+ EmuConfig.Cpu.Recompiler.EnableVU1 ? 1 : 0, EmuConfig.Cpu.Recompiler.EnableFastmem ? 1 : 0,
+ boot_jit_available ? 1 : 0, boot_no_jit_active ? 1 : 0, boot_fallback_reason);
#if ARMSX2_APPLE_MAC_RUNTIME
const bool mac_fast_boot_value = boot_params.fast_boot.value_or(false);
LogUnified("@@MAC_VM_BOOT_PARAMS@@ filename=%s elf=%s source_type=%d fast_boot=%d bios_name=%s bios_path=%s bios_exists=%d renderer=%d cpu_core=%d rec_ee=%d rec_iop=%d rec_vu0=%d rec_vu1=%d\n",
@@ -1842,18 +1945,26 @@ - (void)startVMThread {
}
- (void)sceneDidDisconnect:(UIScene *)scene {
+ Console.WriteLn("@@IOS_LIFECYCLE@@ sceneDidDisconnect vm_state=%d active=%d",
+ static_cast<int>(VMManager::GetState()), s_vmThreadActive.load() ? 1 : 0);
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
+ Console.WriteLn("@@IOS_LIFECYCLE@@ sceneDidBecomeActive vm_state=%d active=%d",
+ static_cast<int>(VMManager::GetState()), s_vmThreadActive.load() ? 1 : 0);
}
- (void)sceneWillResignActive:(UIScene *)scene {
// NVM save when app loses focus
extern void cdvdSaveNVRAM();
cdvdSaveNVRAM();
+ Console.WriteLn("@@IOS_LIFECYCLE@@ sceneWillResignActive vm_state=%d active=%d saved_nvram=1",
+ static_cast<int>(VMManager::GetState()), s_vmThreadActive.load() ? 1 : 0);
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
+ Console.WriteLn("@@IOS_LIFECYCLE@@ sceneWillEnterForeground vm_state=%d active=%d",
+ static_cast<int>(VMManager::GetState()), s_vmThreadActive.load() ? 1 : 0);
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
@@ -1863,7 +1974,8 @@ - (void)sceneDidEnterBackground:(UIScene *)scene {
// happens when iOS terminates the app via SIGTERM.
extern void cdvdSaveNVRAM();
cdvdSaveNVRAM();
- Console.WriteLn("[NVM] NVM saved on sceneDidEnterBackground");
+ Console.WriteLn("@@IOS_LIFECYCLE@@ sceneDidEnterBackground vm_state=%d active=%d saved_nvram=1",
+ static_cast<int>(VMManager::GetState()), s_vmThreadActive.load() ? 1 : 0);
}
@end
diff --git a/app/src/main/cpp/pcsx2/GS/Renderers/Metal/cas.metal b/app/src/main/cpp/pcsx2/GS/Renderers/Metal/cas.metal
index 523ba1194..56cf3094a 100644
--- a/app/src/main/cpp/pcsx2/GS/Renderers/Metal/cas.metal
+++ b/app/src/main/cpp/pcsx2/GS/Renderers/Metal/cas.metal
@@ -5,7 +5,7 @@
#define A_MSL 1
#define A_HALF 1
-#include "../../../../bin/resources/shaders/common/ffx_a.h"
+#include "shaders/common/ffx_a.h"
struct CASTextureF
{
@@ -35,7 +35,7 @@ A_STATIC AH3 CasLoadH(CASTextureH tex, ASW2 coord)
A_STATIC void CasInputH(inoutAH2 r, inoutAH2 g, inoutAH2 b){}
-#include "../../../../bin/resources/shaders/common/ffx_cas.h"
+#include "shaders/common/ffx_cas.h"
#include "GSMTLShaderCommon.h"
diff --git a/app/src/main/cpp/pcsx2/GS/Renderers/Metal/fxaa.metal b/app/src/main/cpp/pcsx2/GS/Renderers/Metal/fxaa.metal
index 68c9a249f..bf09eef48 100644
--- a/app/src/main/cpp/pcsx2/GS/Renderers/Metal/fxaa.metal
+++ b/app/src/main/cpp/pcsx2/GS/Renderers/Metal/fxaa.metal
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0+
#include "GSMTLShaderCommon.h"
-#include "../../../../bin/resources/shaders/common/fxaa.fx"
+#include "shaders/common/fxaa.fx"
fragment float4 ps_fxaa(ConvertShaderData data [[stage_in]], texture2d<float> tex [[texture(GSMTLTextureIndexNonHW)]])
{
diff --git a/app/src/main/cpp/pcsx2/ImGui/FullscreenUI.cpp b/app/src/main/cpp/pcsx2/ImGui/FullscreenUI.cpp
index 83e3f6387..704fb2c17 100644
--- a/app/src/main/cpp/pcsx2/ImGui/FullscreenUI.cpp
+++ b/app/src/main/cpp/pcsx2/ImGui/FullscreenUI.cpp
@@ -1404,7 +1404,7 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
logo_pos, logo_pos + logo_size);
dl->AddText(heading_font, heading_font->FontSize,
ImVec2(logo_pos.x + logo_size.x + LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), logo_pos.y),
- ImGui::GetColorU32(ImGuiCol_Text), "PCSX2");
+ ImGui::GetColorU32(ImGuiCol_Text), "ARMSX2");
}
// draw time
@@ -1620,7 +1620,7 @@ void FullscreenUI::DrawExitWindow()
QueueResetFocus(FocusResetType::WindowChanged);
}
- if (HorizontalMenuItem(GetCachedTexture("fullscreenui/exit.png"), FSUI_CSTR("Exit PCSX2"),
+ if (HorizontalMenuItem(GetCachedTexture("fullscreenui/exit.png"), FSUI_CSTR("Exit ARMSX2"),
FSUI_CSTR("Completely exits the application, returning you to your desktop.")))
{
DoRequestExit();
@@ -3430,7 +3430,7 @@ void FullscreenUI::DrawInterfaceSettingsPage()
FSUI_NSTR("Untouched Lagoon"),
FSUI_NSTR("Baby Pastel"),
FSUI_NSTR("Pizza Time!"),
- FSUI_NSTR("PCSX2 Blue"),
+ FSUI_NSTR("ARMSX2 Blue"),
FSUI_NSTR("Scarlet Devil"),
FSUI_NSTR("Violet Angel"),
FSUI_NSTR("Cobalt Sky"),
@@ -3585,8 +3585,8 @@ void FullscreenUI::DrawInterfaceSettingsPage()
FSUI_CSTR(
"Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc."),
"EmuCore/GS", "OsdShowMessages", true);
- DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_INFO, "Show PCSX2 Version"),
- FSUI_CSTR("Shows the current PCSX2 version on the top-right corner of the display."), "EmuCore/GS",
+ DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_INFO, "Show ARMSX2 Version"),
+ FSUI_CSTR("Shows the current ARMSX2 version on the top-right corner of the display."), "EmuCore/GS",
"OsdShowVersion", false);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TACHOMETER_ALT, "Show Speed"),
FSUI_CSTR("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."), "EmuCore/GS",
@@ -3817,7 +3817,7 @@ void FullscreenUI::DrawEmulationSettingsPage()
FSUI_CSTR("Speeds up emulation so that the guest refresh rate matches the host."), "EmuCore/GS", "SyncToHostRefreshRate", false);
DrawToggleSetting(bsi, FSUI_CSTR("Use Host VSync Timing"),
- FSUI_CSTR("Disables PCSX2's internal frame timing, and uses host vsync instead."), "EmuCore/GS", "UseVSyncForTiming", false,
+ FSUI_CSTR("Disables the emulator's internal frame timing, and uses host vsync instead."), "EmuCore/GS", "UseVSyncForTiming", false,
GetEffectiveBoolSetting(bsi, "EmuCore/GS", "VsyncEnable", false) && GetEffectiveBoolSetting(bsi, "EmuCore/GS", "SyncToHostRefreshRate", false));
EndMenuButtons();
@@ -5148,8 +5148,8 @@ void FullscreenUI::DrawAdvancedSettingsPage()
if (!IsEditingGameSettings(bsi))
{
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BIOHAZARD, "Show Advanced Settings"),
- FSUI_CSTR("Changing these options may cause games to become non-functional. Modify at your own risk, the PCSX2 team will not "
- "provide support for configurations with these settings changed."),
+ FSUI_CSTR("Changing these options may cause games to become non-functional. Modify at your own risk; support is not "
+ "guaranteed for configurations with these settings changed."),
"UI", "ShowAdvancedSettings", false);
}
@@ -5337,7 +5337,7 @@ void FullscreenUI::DrawPatchesOrCheatsSettingsPage(bool cheats)
FSUI_CSTR("Activating game patches can cause unpredictable behavior, crashing, soft-locks, or broken saved games."),
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ActiveButton(
- FSUI_CSTR("Use patches at your own risk, the PCSX2 team will provide no support for users who have enabled game patches."),
+ FSUI_CSTR("Use patches at your own risk; support is not guaranteed for users who have enabled game patches."),
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
}
@@ -7223,7 +7223,7 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& se
MenuHeading(FSUI_CSTR("Settings"));
check_challenge_state = DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TROPHY, "Enable Achievements"),
- FSUI_CSTR("When enabled and logged in, PCSX2 will scan for achievements on startup."), "Achievements", "Enabled", false);
+ FSUI_CSTR("When enabled and logged in, ARMSX2 will scan for achievements on startup."), "Achievements", "Enabled", false);
const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false);
@@ -7247,11 +7247,11 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& se
FSUI_CSTR("When enabled, each session will behave as if no achievements have been unlocked."), "Achievements", "EncoreMode", false,
enabled);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_EYE, "Spectator Mode"),
- FSUI_CSTR("When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server."),
+ FSUI_CSTR("When enabled, ARMSX2 will assume all achievements are locked and not send any unlock notifications to the server."),
"Achievements", "SpectatorMode", false, enabled);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MEDAL, "Test Unofficial Achievements"),
FSUI_CSTR(
- "When enabled, PCSX2 will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements."),
+ "When enabled, ARMSX2 will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements."),
"Achievements", "UnofficialTestMode", false, enabled);
// Check for challenge mode just being enabled.
@@ -7426,7 +7426,7 @@ TRANSLATE_NOOP("FullscreenUI", "Start BIOS");
TRANSLATE_NOOP("FullscreenUI", "Start the console without any disc inserted.");
TRANSLATE_NOOP("FullscreenUI", "Back");
TRANSLATE_NOOP("FullscreenUI", "Return to the previous menu.");
-TRANSLATE_NOOP("FullscreenUI", "Exit PCSX2");
+ TRANSLATE_NOOP("FullscreenUI", "Exit ARMSX2");
TRANSLATE_NOOP("FullscreenUI", "Completely exits the application, returning you to your desktop.");
TRANSLATE_NOOP("FullscreenUI", "Desktop Mode");
TRANSLATE_NOOP("FullscreenUI", "Exits Big Picture mode, returning to the desktop interface.");
@@ -7467,7 +7467,7 @@ TRANSLATE_NOOP("FullscreenUI", "On-Screen Display");
TRANSLATE_NOOP("FullscreenUI", "Determines how large the on-screen messages and monitor are.");
TRANSLATE_NOOP("FullscreenUI", "%d%%");
TRANSLATE_NOOP("FullscreenUI", "Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc.");
-TRANSLATE_NOOP("FullscreenUI", "Shows the current PCSX2 version on the top-right corner of the display.");
+TRANSLATE_NOOP("FullscreenUI", "Shows the current ARMSX2 version on the top-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the current emulation speed of the system in the top-right corner of the display as a percentage.");
TRANSLATE_NOOP("FullscreenUI", "Shows the number of video frames (or v-syncs) displayed per second by the system in the top-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the CPU usage based on threads in the top-right corner of the display.");
@@ -7520,7 +7520,7 @@ TRANSLATE_NOOP("FullscreenUI", "Synchronizes frame presentation with host refres
TRANSLATE_NOOP("FullscreenUI", "Sync to Host Refresh Rate");
TRANSLATE_NOOP("FullscreenUI", "Speeds up emulation so that the guest refresh rate matches the host.");
TRANSLATE_NOOP("FullscreenUI", "Use Host VSync Timing");
-TRANSLATE_NOOP("FullscreenUI", "Disables PCSX2's internal frame timing, and uses host vsync instead.");
+TRANSLATE_NOOP("FullscreenUI", "Disables the emulator's internal frame timing, and uses host vsync instead.");
TRANSLATE_NOOP("FullscreenUI", "Renderer");
TRANSLATE_NOOP("FullscreenUI", "Selects the API used to render the emulated GS.");
TRANSLATE_NOOP("FullscreenUI", "Display");
@@ -7727,7 +7727,7 @@ TRANSLATE_NOOP("FullscreenUI", "Determines the pressure required to activate the
TRANSLATE_NOOP("FullscreenUI", "Toggle every %d frames");
TRANSLATE_NOOP("FullscreenUI", "Clears all bindings for this USB controller.");
TRANSLATE_NOOP("FullscreenUI", "Data Save Locations");
-TRANSLATE_NOOP("FullscreenUI", "Changing these options may cause games to become non-functional. Modify at your own risk, the PCSX2 team will not provide support for configurations with these settings changed.");
+TRANSLATE_NOOP("FullscreenUI", "Changing these options may cause games to become non-functional. Modify at your own risk; support is not guaranteed for configurations with these settings changed.");
TRANSLATE_NOOP("FullscreenUI", "Logging");
TRANSLATE_NOOP("FullscreenUI", "Writes log messages to the system console (console window/standard output).");
TRANSLATE_NOOP("FullscreenUI", "Writes log messages to emulog.txt.");
@@ -7782,7 +7782,7 @@ TRANSLATE_NOOP("FullscreenUI", "No patches are available for this game.");
TRANSLATE_NOOP("FullscreenUI", "Game Patches");
TRANSLATE_NOOP("FullscreenUI", "Activating cheats can cause unpredictable behavior, crashing, soft-locks, or broken saved games.");
TRANSLATE_NOOP("FullscreenUI", "Activating game patches can cause unpredictable behavior, crashing, soft-locks, or broken saved games.");
-TRANSLATE_NOOP("FullscreenUI", "Use patches at your own risk, the PCSX2 team will provide no support for users who have enabled game patches.");
+TRANSLATE_NOOP("FullscreenUI", "Use patches at your own risk; support is not guaranteed for users who have enabled game patches.");
TRANSLATE_NOOP("FullscreenUI", "Game Fixes");
TRANSLATE_NOOP("FullscreenUI", "Game fixes should not be modified unless you are aware of what each option does and the implications of doing so.");
TRANSLATE_NOOP("FullscreenUI", "FPU Multiply Hack");
@@ -7845,15 +7845,15 @@ TRANSLATE_NOOP("FullscreenUI", "About PCSX2");
TRANSLATE_NOOP("FullscreenUI", "PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.");
TRANSLATE_NOOP("FullscreenUI", "PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.");
TRANSLATE_NOOP("FullscreenUI", "Version: %s");
-TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, PCSX2 will scan for achievements on startup.");
+TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, ARMSX2 will scan for achievements on startup.");
TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.");
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages when starting, submitting, or failing a leaderboard challenge.");
TRANSLATE_NOOP("FullscreenUI", "Plays sound effects for events such as achievement unlocks and leaderboard submissions.");
TRANSLATE_NOOP("FullscreenUI", "Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, each session will behave as if no achievements have been unlocked.");
-TRANSLATE_NOOP("FullscreenUI", "When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server.");
-TRANSLATE_NOOP("FullscreenUI", "When enabled, PCSX2 will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements.");
+TRANSLATE_NOOP("FullscreenUI", "When enabled, ARMSX2 will assume all achievements are locked and not send any unlock notifications to the server.");
+TRANSLATE_NOOP("FullscreenUI", "When enabled, ARMSX2 will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements.");
TRANSLATE_NOOP("FullscreenUI", "Sound Effects");
TRANSLATE_NOOP("FullscreenUI", "Account");
TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements.");
@@ -7921,7 +7921,7 @@ TRANSLATE_NOOP("FullscreenUI", "Grey Matter");
TRANSLATE_NOOP("FullscreenUI", "Untouched Lagoon");
TRANSLATE_NOOP("FullscreenUI", "Baby Pastel");
TRANSLATE_NOOP("FullscreenUI", "Pizza Time!");
-TRANSLATE_NOOP("FullscreenUI", "PCSX2 Blue");
+TRANSLATE_NOOP("FullscreenUI", "ARMSX2 Blue");
TRANSLATE_NOOP("FullscreenUI", "Scarlet Devil");
TRANSLATE_NOOP("FullscreenUI", "Violet Angel");
TRANSLATE_NOOP("FullscreenUI", "Cobalt Sky");
@@ -8145,7 +8145,7 @@ TRANSLATE_NOOP("FullscreenUI", "Double-Click Toggles Fullscreen");
TRANSLATE_NOOP("FullscreenUI", "Hide Cursor In Fullscreen");
TRANSLATE_NOOP("FullscreenUI", "OSD Scale");
TRANSLATE_NOOP("FullscreenUI", "Show Messages");
-TRANSLATE_NOOP("FullscreenUI", "Show PCSX2 Version");
+TRANSLATE_NOOP("FullscreenUI", "Show ARMSX2 Version");
TRANSLATE_NOOP("FullscreenUI", "Show Speed");
TRANSLATE_NOOP("FullscreenUI", "Show FPS");
TRANSLATE_NOOP("FullscreenUI", "Show CPU Usage");
diff --git a/app/src/main/cpp/pcsx2/ImGui/ImGuiOverlays.cpp b/app/src/main/cpp/pcsx2/ImGui/ImGuiOverlays.cpp
index 39d091c67..2bef10643 100644
--- a/app/src/main/cpp/pcsx2/ImGui/ImGuiOverlays.cpp
+++ b/app/src/main/cpp/pcsx2/ImGui/ImGuiOverlays.cpp
@@ -37,6 +37,10 @@
#include "fmt/format.h"
#include "imgui.h"
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
#include <array>
#include <chrono>
#include <cmath>
@@ -137,13 +141,11 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
switch (PerformanceMetrics::GetInternalFPSMethod())
{
case PerformanceMetrics::InternalFPSMethod::GSPrivilegedRegister:
- text.append_format("FPS: {:.2f} [P]", PerformanceMetrics::GetInternalFPS(),
- PerformanceMetrics::GetFPS());
+ text.append_format("FPS: {:.2f} [P]", PerformanceMetrics::GetInternalFPS());
break;
case PerformanceMetrics::InternalFPSMethod::DISPFBBlit:
- text.append_format("FPS: {:.2f} [B]", PerformanceMetrics::GetInternalFPS(),
- PerformanceMetrics::GetFPS());
+ text.append_format("FPS: {:.2f} [B]", PerformanceMetrics::GetInternalFPS());
break;
case PerformanceMetrics::InternalFPSMethod::None:
@@ -156,8 +158,7 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
if (GSConfig.OsdShowVPS)
{
- text.append_format("{}VPS: {:.2f}", first ? "" : " | ", PerformanceMetrics::GetFPS(),
- PerformanceMetrics::GetFPS());
+ text.append_format("{}VPS: {:.2f}", first ? "" : " | ", PerformanceMetrics::GetFPS());
first = false;
}
@@ -175,8 +176,11 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
if (GSConfig.OsdShowVersion)
{
-// text.append_format("{}PCSX2 {}", first ? "" : " | ", BuildVersion::GitRev);
- text.append_format("{}ARMSX2 {}", first ? "" : " | ", "v2.3.430");
+#if defined(__APPLE__) && TARGET_OS_IPHONE
+ text.append_format("{}ARMSX2 iOS", first ? "" : " | ");
+#else
+ text.append_format("{}ARMSX2 {}", first ? "" : " | ", BuildVersion::GitRev);
+#endif
}
if (!text.empty())
diff --git a/app/src/main/swift/Models/FileImportHandler.swift b/app/src/main/swift/Models/FileImportHandler.swift
index 26480f32e..8af61a734 100644
--- a/app/src/main/swift/Models/FileImportHandler.swift
+++ b/app/src/main/swift/Models/FileImportHandler.swift
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0+
import SwiftUI
+import Foundation
import UniformTypeIdentifiers
@Observable
@@ -83,12 +84,14 @@ final class FileImportHandler: @unchecked Sendable {
if preferredDestination == .game {
guard Self.gameExtensions.contains(ext) else {
+ NSLog("[ARMSX2 iOS Import] unsupported game file: %@", fileName)
return .unsupported(fileName)
}
destDir = (docsPath as NSString).appendingPathComponent("iso")
category = "Game"
} else if preferredDestination == .bios {
guard Self.biosExtensions.contains(ext) else {
+ NSLog("[ARMSX2 iOS Import] unsupported BIOS file: %@", fileName)
return .unsupported(fileName)
}
destDir = (docsPath as NSString).appendingPathComponent("bios")
@@ -108,6 +111,7 @@ final class FileImportHandler: @unchecked Sendable {
category = "BIOS"
}
} else {
+ NSLog("[ARMSX2 iOS Import] unsupported file: %@", fileName)
return .unsupported(fileName)
}
@@ -122,8 +126,10 @@ final class FileImportHandler: @unchecked Sendable {
try FileManager.default.removeItem(atPath: destPath)
}
try FileManager.default.copyItem(at: url, to: URL(fileURLWithPath: destPath))
+ NSLog("[ARMSX2 iOS Import] %@ imported: %@ -> %@", category, fileName, destPath)
return .success("\(category) imported: \(fileName)")
} catch {
+ NSLog("[ARMSX2 iOS Import] failed: %@ -> %@ error=%@", fileName, destPath, error.localizedDescription)
return .failure("\(fileName): \(error.localizedDescription)")
}
}
diff --git a/app/src/main/swift/Models/SettingsStore.swift b/app/src/main/swift/Models/SettingsStore.swift
index d76d21c35..c98e94796 100644
--- a/app/src/main/swift/Models/SettingsStore.swift
+++ b/app/src/main/swift/Models/SettingsStore.swift
@@ -26,7 +26,10 @@ final class SettingsStore: @unchecked Sendable {
// ── Emulator / CPU ──
var eeCoreType: Int {
- didSet { ARMSX2Bridge.setINIInt("EmuCore/CPU", key: "CoreType", value: Int32(eeCoreType)) }
+ didSet {
+ ARMSX2Bridge.setINIInt("EmuCore/CPU", key: "CoreType", value: Int32(eeCoreType))
+ ARMSX2Bridge.setINIBool("EmuCore/CPU", key: "UseArm64Dynarec", value: eeCoreType == 2)
+ }
}
var iopRecompiler: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/CPU/Recompiler", key: "EnableIOP", value: iopRecompiler) }
@@ -89,7 +92,7 @@ final class SettingsStore: @unchecked Sendable {
didSet { ARMSX2Bridge.setINIInt("EmuCore/GS", key: "deinterlace_mode", value: Int32(interlaceMode)) }
}
var aspectRatio: Int {
- didSet { ARMSX2Bridge.setINIInt("EmuCore/GS", key: "AspectRatio", value: Int32(aspectRatio)) }
+ didSet { ARMSX2Bridge.setINIString("EmuCore/GS", key: "AspectRatio", value: Self.aspectRatioName(for: aspectRatio)) }
}
var blendingAccuracy: Int {
didSet { ARMSX2Bridge.setINIInt("EmuCore/GS", key: "accurate_blending_unit", value: Int32(blendingAccuracy)) }
@@ -105,21 +108,48 @@ final class SettingsStore: @unchecked Sendable {
applyOsdPreset(osdPreset)
}
}
+ var osdPerformancePosition: Int {
+ didSet { ARMSX2Bridge.setINIInt("EmuCore/GS", key: "OsdPerformancePos", value: Int32(osdPerformancePosition)) }
+ }
var osdShowFPS: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowFPS", value: osdShowFPS) }
}
+ var osdShowVPS: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowVPS", value: osdShowVPS) }
+ }
var osdShowSpeed: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowSpeed", value: osdShowSpeed) }
}
var osdShowCPU: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowCPU", value: osdShowCPU) }
}
+ var osdShowGPU: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowGPU", value: osdShowGPU) }
+ }
var osdShowResolution: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowResolution", value: osdShowResolution) }
}
+ var osdShowGSStats: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowGSStats", value: osdShowGSStats) }
+ }
+ var osdShowIndicators: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowIndicators", value: osdShowIndicators) }
+ }
+ var osdShowSettings: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowSettings", value: osdShowSettings) }
+ }
+ var osdShowInputs: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowInputs", value: osdShowInputs) }
+ }
var osdShowFrameTimes: Bool {
didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowFrameTimes", value: osdShowFrameTimes) }
}
+ var osdShowVersion: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowVersion", value: osdShowVersion) }
+ }
+ var osdShowHardwareInfo: Bool {
+ didSet { ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowHardwareInfo", value: osdShowHardwareInfo) }
+ }
// ── Gamepad / UI ──
var padOpacity: Float {
@@ -129,6 +159,28 @@ final class SettingsStore: @unchecked Sendable {
didSet { ARMSX2Bridge.setINIBool("ARMSX2iOS/UI", key: "HapticFeedback", value: hapticFeedback) }
}
+ private static func aspectRatioName(for value: Int) -> String {
+ switch value {
+ case 0: return "Stretch"
+ case 1: return "Auto 4:3/3:2"
+ case 2: return "4:3"
+ case 3: return "16:9"
+ case 4: return "10:7"
+ default: return "Auto 4:3/3:2"
+ }
+ }
+
+ private static func aspectRatioValue(from name: String) -> Int {
+ switch name {
+ case "Stretch", "0": return 0
+ case "Auto 4:3/3:2", "1": return 1
+ case "4:3", "2": return 2
+ case "16:9", "3": return 3
+ case "10:7", "4": return 4
+ default: return 1
+ }
+ }
+
// ── Init from INI ──
private init() {
// CPU
@@ -159,19 +211,29 @@ final class SettingsStore: @unchecked Sendable {
casMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASMode", defaultValue: 0))
casSharpness = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASSharpness", defaultValue: 50))
interlaceMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "deinterlace_mode", defaultValue: 7))
- aspectRatio = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "AspectRatio", defaultValue: 0))
+ aspectRatio = Self.aspectRatioValue(from: ARMSX2Bridge.getINIString("EmuCore/GS", key: "AspectRatio", defaultValue: "Auto 4:3/3:2"))
blendingAccuracy = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "accurate_blending_unit", defaultValue: 1))
dithering = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "dithering_ps2", defaultValue: 2))
// OSD
osdPreset = OsdPreset(rawValue: Int(ARMSX2Bridge.getINIInt("ARMSX2iOS/UI", key: "OsdPreset", defaultValue: 0))) ?? .off
+ osdPerformancePosition = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "OsdPerformancePos", defaultValue: 2))
osdShowFPS = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowFPS", defaultValue: false)
+ osdShowVPS = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowVPS", defaultValue: false)
osdShowSpeed = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowSpeed", defaultValue: false)
osdShowCPU = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowCPU", defaultValue: false)
+ osdShowGPU = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowGPU", defaultValue: false)
osdShowResolution = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowResolution", defaultValue: false)
+ osdShowGSStats = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowGSStats", defaultValue: false)
+ osdShowIndicators = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowIndicators", defaultValue: false)
+ osdShowSettings = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowSettings", defaultValue: false)
+ osdShowInputs = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowInputs", defaultValue: false)
osdShowFrameTimes = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowFrameTimes", defaultValue: false)
+ osdShowVersion = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowVersion", defaultValue: false)
+ osdShowHardwareInfo = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowHardwareInfo", defaultValue: false)
// UI
padOpacity = ARMSX2Bridge.getINIFloat("ARMSX2iOS/UI", key: "PadOpacity", defaultValue: 0.6)
hapticFeedback = ARMSX2Bridge.getINIBool("ARMSX2iOS/UI", key: "HapticFeedback", defaultValue: true)
+ ARMSX2Bridge.setINIString("EmuCore/GS", key: "AspectRatio", value: Self.aspectRatioName(for: aspectRatio))
// [P60] Force MTVU off (known buggy)
ARMSX2Bridge.setINIBool("EmuCore/Speedhacks", key: "vuThread", value: false)
// Apply OSD preset
@@ -204,15 +266,24 @@ final class SettingsStore: @unchecked Sendable {
casMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASMode", defaultValue: 0))
casSharpness = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASSharpness", defaultValue: 50))
interlaceMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "deinterlace_mode", defaultValue: 7))
- aspectRatio = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "AspectRatio", defaultValue: 0))
+ aspectRatio = Self.aspectRatioValue(from: ARMSX2Bridge.getINIString("EmuCore/GS", key: "AspectRatio", defaultValue: "Auto 4:3/3:2"))
blendingAccuracy = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "accurate_blending_unit", defaultValue: 1))
dithering = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "dithering_ps2", defaultValue: 2))
osdPreset = OsdPreset(rawValue: Int(ARMSX2Bridge.getINIInt("ARMSX2iOS/UI", key: "OsdPreset", defaultValue: 0))) ?? .off
+ osdPerformancePosition = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "OsdPerformancePos", defaultValue: 2))
osdShowFPS = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowFPS", defaultValue: false)
+ osdShowVPS = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowVPS", defaultValue: false)
osdShowSpeed = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowSpeed", defaultValue: false)
osdShowCPU = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowCPU", defaultValue: false)
+ osdShowGPU = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowGPU", defaultValue: false)
osdShowResolution = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowResolution", defaultValue: false)
+ osdShowGSStats = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowGSStats", defaultValue: false)
+ osdShowIndicators = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowIndicators", defaultValue: false)
+ osdShowSettings = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowSettings", defaultValue: false)
+ osdShowInputs = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowInputs", defaultValue: false)
osdShowFrameTimes = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowFrameTimes", defaultValue: false)
+ osdShowVersion = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowVersion", defaultValue: false)
+ osdShowHardwareInfo = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "OsdShowHardwareInfo", defaultValue: false)
padOpacity = ARMSX2Bridge.getINIFloat("ARMSX2iOS/UI", key: "PadOpacity", defaultValue: 0.6)
hapticFeedback = ARMSX2Bridge.getINIBool("ARMSX2iOS/UI", key: "HapticFeedback", defaultValue: true)
}
@@ -220,37 +291,65 @@ final class SettingsStore: @unchecked Sendable {
/// Apply OSD preset — writes ALL OSD flags to INI + GSConfig
private func applyOsdPreset(_ preset: OsdPreset) {
ARMSX2Bridge.applyOsdPreset(Int32(preset.rawValue))
+ if preset == .off {
+ osdPerformancePosition = 0
+ } else if osdPerformancePosition == 0 {
+ osdPerformancePosition = 2
+ }
let isSimple = preset == .simple
let isDetail = preset == .detail
let isFull = preset == .full
osdShowFPS = isSimple || isDetail || isFull
- osdShowSpeed = isDetail || isFull
+ osdShowVPS = isDetail || isFull
+ osdShowSpeed = isSimple || isDetail || isFull
osdShowCPU = isSimple || isDetail || isFull
+ osdShowGPU = isDetail || isFull
osdShowResolution = isDetail || isFull
+ osdShowGSStats = isFull
+ osdShowIndicators = isSimple || isDetail || isFull
+ osdShowSettings = isFull
+ osdShowInputs = isFull
osdShowFrameTimes = isFull
- ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowVPS", value: false)
- ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowVersion", value: false)
- ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowHardwareInfo", value: false)
- ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowGPU", value: false)
- ARMSX2Bridge.setINIBool("EmuCore/GS", key: "OsdShowGSStats", value: false)
+ osdShowVersion = isFull
+ osdShowHardwareInfo = isFull
}
- /// Reset emulator settings to PC PCSX2 defaults
+ /// Reset emulator settings to ARMSX2 iOS defaults
func resetEmulatorDefaults() {
eeCoreType = 2 // ARM64 JIT
iopRecompiler = true
- vu0Recompiler = true // PC PCSX2 default: microVU JIT
- vu1Recompiler = true // PC PCSX2 default: microVU JIT
+ vu0Recompiler = true
+ vu1Recompiler = true
fastBoot = false
fastmem = true
fastCDVD = false
eeCycleRate = 0
- vu1Instant = true // PC PCSX2 recommended default
- waitLoop = true // PC PCSX2 recommended default
- intcStat = true // PC PCSX2 recommended default
+ vu1Instant = true
+ waitLoop = true
+ intcStat = true
+ }
+
+ /// Keep EE/IOP/VU0 fast while isolating suspected VU1 JIT regressions.
+ func applyVU1CompatibilityPreset() {
+ eeCoreType = 2
+ iopRecompiler = true
+ vu0Recompiler = true
+ vu1Recompiler = false
+ vu1Instant = false
+ fastmem = false
+ }
+
+ /// Slow diagnostic preset for crash isolation when dynarec state is suspect.
+ func applyFullInterpreterPreset() {
+ eeCoreType = 1
+ iopRecompiler = false
+ vu0Recompiler = false
+ vu1Recompiler = false
+ vu1Instant = false
+ fastmem = false
}
- /// Reset graphics settings to PC PCSX2 defaults
+ /// Reset graphics settings to ARMSX2 iOS defaults
func resetGraphicsDefaults() {
renderer = 17 // Metal
upscaleMultiplier = 1.0 // Native PS2
@@ -260,7 +359,7 @@ final class SettingsStore: @unchecked Sendable {
casMode = 0 // Disabled
casSharpness = 50
interlaceMode = 7 // Adaptive
- aspectRatio = 0 // Auto 4:3/3:2
+ aspectRatio = 1 // Auto 4:3/3:2
blendingAccuracy = 1 // Basic
dithering = 2 // Scaled
}
diff --git a/app/src/main/swift/Views/BootSplashView.swift b/app/src/main/swift/Views/BootSplashView.swift
index bee9674f2..4991612f1 100644
--- a/app/src/main/swift/Views/BootSplashView.swift
+++ b/app/src/main/swift/Views/BootSplashView.swift
@@ -25,7 +25,7 @@ struct BootSplashView: View {
}
.task {
try? await Task.sleep(nanoseconds: Self.hardTimeout)
- await finish()
+ finish()
}
}
@@ -79,7 +79,7 @@ private struct BootSplashPlayerView: UIViewRepresentable {
coordinator.stopObserving()
}
- final class Coordinator {
+ final class Coordinator: @unchecked Sendable {
var player: AVPlayer?
private let onFinished: () -> Void
private var endToken: NSObjectProtocol?
diff --git a/app/src/main/swift/Views/GameScreenView.swift b/app/src/main/swift/Views/GameScreenView.swift
index bfb9fc229..1159c8a78 100644
--- a/app/src/main/swift/Views/GameScreenView.swift
+++ b/app/src/main/swift/Views/GameScreenView.swift
@@ -205,22 +205,28 @@ private struct SaveStatesPanel: View {
}
private func save(_ slot: ARMSX2SaveStateSlotInfo) {
- busySlot = slot.slot
- ARMSX2Bridge.saveState(toSlot: slot.slot) { success in
- busySlot = nil
- refresh()
- statusHandler(success ? "State saved to slot \(slot.slot)" : "Failed to save slot \(slot.slot)")
+ let slotNumber = slot.slot
+ busySlot = slotNumber
+ ARMSX2Bridge.saveState(toSlot: slotNumber) { success in
+ Task { @MainActor in
+ busySlot = nil
+ refresh()
+ statusHandler(success ? "State saved to slot \(slotNumber)" : "Failed to save slot \(slotNumber)")
+ }
}
}
private func load(_ slot: ARMSX2SaveStateSlotInfo) {
- busySlot = slot.slot
- ARMSX2Bridge.loadState(fromSlot: slot.slot) { success in
- busySlot = nil
- refresh()
- statusHandler(success ? "State loaded from slot \(slot.slot)" : "Failed to load slot \(slot.slot)")
- if success {
- dismiss()
+ let slotNumber = slot.slot
+ busySlot = slotNumber
+ ARMSX2Bridge.loadState(fromSlot: slotNumber) { success in
+ Task { @MainActor in
+ busySlot = nil
+ refresh()
+ statusHandler(success ? "State loaded from slot \(slotNumber)" : "Failed to load slot \(slotNumber)")
+ if success {
+ dismiss()
+ }
}
}
}
diff --git a/app/src/main/swift/Views/HelpView.swift b/app/src/main/swift/Views/HelpView.swift
index 8193b2fc1..19c6d78b0 100644
--- a/app/src/main/swift/Views/HelpView.swift
+++ b/app/src/main/swift/Views/HelpView.swift
@@ -60,7 +60,7 @@ private let helpData: [HelpSection] = [
HelpSection(title: "Overlay", icon: "speedometer", items: [
HelpItem(
question: "Overlay presets",
- answer: "OFF: No overlay. Simple: FPS + CPU usage. Detail: FPS, Speed, CPU, Resolution. Full: Everything including Frame Times graph. Configure in Settings > Overlay."
+ answer: "OFF hides the overlay. Simple shows FPS, speed, CPU, and indicators. Detail adds VPS, GPU, and resolution. Full enables the Android-style diagnostic set including GS stats, settings, inputs, frame times, version, and hardware info."
),
HelpItem(
question: "In-game toggle",
diff --git a/app/src/main/swift/Views/Settings/EmulatorSettingsView.swift b/app/src/main/swift/Views/Settings/EmulatorSettingsView.swift
index d96a8deb4..6196f08c1 100644
--- a/app/src/main/swift/Views/Settings/EmulatorSettingsView.swift
+++ b/app/src/main/swift/Views/Settings/EmulatorSettingsView.swift
@@ -69,6 +69,22 @@ struct EmulatorSettingsView: View {
.foregroundStyle(.secondary)
}
+ Section {
+ Button("Use VU1 Interpreter Preset") {
+ settings.applyVU1CompatibilityPreset()
+ }
+ Button("Use Full Interpreter Preset") {
+ settings.applyFullInterpreterPreset()
+ }
+ Text("Use the VU1 preset first for boot crashes or VU1-related texture/rendering glitches. Full Interpreter is much slower, but helps isolate dynarec/JIT issues.")
+ .font(.caption)
+ .foregroundStyle(.secondary)
+ } header: {
+ Text("Compatibility")
+ } footer: {
+ Text("Changes take effect on next VM boot.")
+ }
+
Section {
Stepper("EE Cycle Rate: \(settings.eeCycleRate)", value: $settings.eeCycleRate, in: -3...3)
Text("0 = Default. Negative = underclock (stable). Positive = overclock (fast but risky).")
@@ -80,7 +96,7 @@ struct EmulatorSettingsView: View {
Toggle("Wait Loop Detection", isOn: $settings.waitLoop)
Toggle("INTC Stat Hack", isOn: $settings.intcStat)
- Text("These are recommended defaults from PCSX2. Disable only if a specific game has issues.")
+ Text("These are recommended compatibility defaults. Disable only if a specific game has issues.")
.font(.caption)
.foregroundStyle(.secondary)
} header: {
diff --git a/app/src/main/swift/Views/Settings/GamepadSettingsView.swift b/app/src/main/swift/Views/Settings/GamepadSettingsView.swift
index 4cac1494f..481811906 100644
--- a/app/src/main/swift/Views/Settings/GamepadSettingsView.swift
+++ b/app/src/main/swift/Views/Settings/GamepadSettingsView.swift
@@ -126,8 +126,10 @@ struct GamepadSettingsView: View {
let captured = ARMSX2Bridge.capturedButton()
if captured >= 0 {
ARMSX2Bridge.setButtonMapping(Int32(ps2Index), toSDLButton: captured)
- stopCapture()
- mappingVersion += 1
+ Task { @MainActor in
+ stopCapture()
+ mappingVersion += 1
+ }
}
}
}
diff --git a/app/src/main/swift/Views/Settings/GraphicsSettingsView.swift b/app/src/main/swift/Views/Settings/GraphicsSettingsView.swift
index 58c3380d6..e292b7cfb 100644
--- a/app/src/main/swift/Views/Settings/GraphicsSettingsView.swift
+++ b/app/src/main/swift/Views/Settings/GraphicsSettingsView.swift
@@ -90,10 +90,11 @@ struct GraphicsSettingsView: View {
}
Picker("Aspect Ratio", selection: $settings.aspectRatio) {
- Text("Auto 4:3 / 3:2 (Default)").tag(0)
- Text("4:3").tag(1)
- Text("16:9 (Widescreen)").tag(2)
- Text("Stretch to Window").tag(3)
+ Text("Auto 4:3 / 3:2 (Default)").tag(1)
+ Text("4:3").tag(2)
+ Text("16:9 (Widescreen)").tag(3)
+ Text("10:7").tag(4)
+ Text("Stretch to Window").tag(0)
}
}
diff --git a/app/src/main/swift/Views/Settings/OverlaySettingsView.swift b/app/src/main/swift/Views/Settings/OverlaySettingsView.swift
index 7e4bc8189..ae9970687 100644
--- a/app/src/main/swift/Views/Settings/OverlaySettingsView.swift
+++ b/app/src/main/swift/Views/Settings/OverlaySettingsView.swift
@@ -15,30 +15,33 @@ struct OverlaySettingsView: View {
}
}
.pickerStyle(.segmented)
- }
- Section {
- switch settings.osdPreset {
- case .off:
- Text("Overlay is hidden.")
- .foregroundStyle(.secondary)
- case .simple:
- Label("FPS", systemImage: "checkmark")
- Label("CPU Usage (EE/GS)", systemImage: "checkmark")
- case .detail:
- Label("FPS", systemImage: "checkmark")
- Label("Speed %", systemImage: "checkmark")
- Label("CPU Usage (EE/GS)", systemImage: "checkmark")
- Label("Resolution", systemImage: "checkmark")
- case .full:
- Label("FPS", systemImage: "checkmark")
- Label("Speed %", systemImage: "checkmark")
- Label("CPU Usage (EE/GS)", systemImage: "checkmark")
- Label("Resolution", systemImage: "checkmark")
- Label("Frame Times Graph", systemImage: "checkmark")
+ Picker("Position", selection: $settings.osdPerformancePosition) {
+ Text("Hidden").tag(0)
+ Text("Top Left").tag(1)
+ Text("Top Right").tag(2)
}
- } header: {
- Text("Displayed Items")
+ }
+
+ Section("Displayed Items") {
+ Toggle("Show FPS", isOn: $settings.osdShowFPS)
+ Toggle("Show VPS", isOn: $settings.osdShowVPS)
+ Toggle("Show Speed", isOn: $settings.osdShowSpeed)
+ Toggle("Show CPU", isOn: $settings.osdShowCPU)
+ Toggle("Show GPU", isOn: $settings.osdShowGPU)
+ Toggle("Show Resolution", isOn: $settings.osdShowResolution)
+ Toggle("Show GS Stats", isOn: $settings.osdShowGSStats)
+ Toggle("Show Indicators", isOn: $settings.osdShowIndicators)
+ Toggle("Show Settings", isOn: $settings.osdShowSettings)
+ Toggle("Show Inputs", isOn: $settings.osdShowInputs)
+ Toggle("Show Frame Times", isOn: $settings.osdShowFrameTimes)
+ Toggle("Show Version", isOn: $settings.osdShowVersion)
+ Toggle("Show Hardware Info", isOn: $settings.osdShowHardwareInfo)
+ }
+
+ Section("Notes") {
+ Text("These match ARMSX2 Android's OSD/stat controls where practical. When Show Version is enabled, the overlay label displays ARMSX2 iOS.")
+ .foregroundStyle(.secondary)
}
}
.navigationTitle("Overlay")