mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
iOS
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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) {
|
||||
|
||||
@@ -18,7 +18,9 @@ extern "C" void ARMSX2_SetSDLFullscreen(bool enabled);
|
||||
#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 NSData* ARMSX2ReadSaveStatePreviewPNG(const std::string& path)
|
||||
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 @@ static NSData* ARMSX2ReadSaveStatePreviewPNG(const std::string& path)
|
||||
+ (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 @@ static NSData* ARMSX2ReadSaveStatePreviewPNG(const std::string& path)
|
||||
|
||||
+ (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 @@ static NSData* ARMSX2ReadSaveStatePreviewPNG(const std::string& path)
|
||||
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
|
||||
GSConfig.OsdShowFPS = true;
|
||||
GSConfig.OsdShowCPU = true;
|
||||
break;
|
||||
case 2: // detail: simple + speed + resolution
|
||||
case 1: // simple: Android-style quick readout
|
||||
GSConfig.OsdShowFPS = true;
|
||||
GSConfig.OsdShowSpeed = true;
|
||||
GSConfig.OsdShowCPU = true;
|
||||
GSConfig.OsdShowResolution = true;
|
||||
GSConfig.OsdShowIndicators = true;
|
||||
break;
|
||||
case 3: // full: detail + frame times
|
||||
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: 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 @@ static NSData* ARMSX2ReadSaveStatePreviewPNG(const std::string& path)
|
||||
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 {
|
||||
|
||||
@@ -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,>"
|
||||
)
|
||||
|
||||
|
||||
@@ -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>"
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+131
-19
@@ -22,6 +22,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
@@ -729,6 +730,7 @@ bool PCAPAdapter::ValidateEtherFrame(NetPacket*) { return false; }
|
||||
#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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
|
||||
// --- 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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
}
|
||||
|
||||
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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
}
|
||||
|
||||
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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
}
|
||||
|
||||
- (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 @@ static bool ARMSX2IOSConfigRequestsInterpreter(INISettingsInterface* si)
|
||||
// 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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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)]])
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/// Reset graphics settings to PC PCSX2 defaults
|
||||
/// 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 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
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,30 +15,33 @@ struct OverlaySettingsView: View {
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
|
||||
Picker("Position", selection: $settings.osdPerformancePosition) {
|
||||
Text("Hidden").tag(0)
|
||||
Text("Top Left").tag(1)
|
||||
Text("Top Right").tag(2)
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
} 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")
|
||||
|
||||
Reference in New Issue
Block a user