From 830dd0d78cbcfbc952a4b67b359e7491d7145f56 Mon Sep 17 00:00:00 2001 From: rogerman Date: Tue, 19 Sep 2017 12:59:44 -0700 Subject: [PATCH] Cocoa Port: Give user feedback for when the emulation gets halted internally. - Also be more consistent when recovering from an internal emulation halt. - Also apply enabling the external BIOS, external firmware and firmware boot settings at load/reset time instead of at frame time. --- desmume/src/MMU.cpp | 2 +- desmume/src/NDSSystem.cpp | 64 ++- desmume/src/NDSSystem.h | 50 ++- desmume/src/armcpu.cpp | 4 +- .../frontend/cocoa/ClientExecutionControl.cpp | 69 +-- .../project.pbxproj | 11 + desmume/src/frontend/cocoa/cocoa_core.h | 7 + desmume/src/frontend/cocoa/cocoa_core.mm | 128 +++++- .../English.lproj/MainMenu.strings | Bin 382146 -> 383606 bytes .../translations/English.lproj/MainMenu.xib | 406 +++++++++++++++++- .../userinterface/EmuControllerDelegate.h | 6 + .../userinterface/EmuControllerDelegate.mm | 78 ++++ desmume/src/frontend/posix/gtk/main.cpp | 2 +- desmume/src/frontend/windows/main.cpp | 6 +- 14 files changed, 760 insertions(+), 73 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index abc8354e9..382e2715b 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1490,7 +1490,7 @@ void FASTCALL MMU_writeToSPIData(u16 val) { printf("SYSTEM POWERED OFF VIA ARM7 SPI POWER DEVICE\n"); printf("Did your main() return?\n"); - emu_halt(); + emu_halt(EMUHALT_REASON_SYSTEM_POWERED_OFF, NDSErrorTag_None); } } diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index c9772d072..ca703a584 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -83,11 +83,12 @@ BaseDriver* driver = &_stub_driver; std::string InputDisplayString; static BOOL LidClosed = FALSE; -static u8 countLid = 0; +static u8 countLid = 0; +static NDSError _lastNDSError; GameInfo gameInfo; NDSSystem nds; -CFIRMWARE *firmware = NULL; +CFIRMWARE *firmware = NULL; using std::min; using std::max; @@ -2663,6 +2664,10 @@ void NDS_Reset() //this needs to happen last, pretty much, since it establishes the correct scheduling state based on all of the above initialization initSchedule(); + + _lastNDSError.code = NDSError_NoError; + _lastNDSError.tag = NDSErrorTag_None; + NDS_CurrentCPUInfoToNDSError(_lastNDSError); } static std::string MakeInputDisplayString(u16 pad, const std::string* Buttons, int count) { @@ -3019,12 +3024,59 @@ void NDS_swapScreen() } } - -void emu_halt() +NDSError NDS_GetLastError() { - //printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr); - execute = false; + return _lastNDSError; +} + +static void NDS_CurrentCPUInfoToNDSError(NDSError &ndsError) +{ + ndsError.programCounterARM9 = NDS_ARM9.R[15]; + ndsError.instructionARM9 = NDS_ARM9.instruction; + ndsError.instructionAddrARM9 = NDS_ARM9.instruct_adr; + ndsError.programCounterARM7 = NDS_ARM7.R[15]; + ndsError.instructionARM7 = NDS_ARM7.instruction; + ndsError.instructionAddrARM7 = NDS_ARM7.instruct_adr; +} + +void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag) +{ + switch (reasonCode) + { + case EMUHALT_REASON_USER_REQUESTED_HALT: + _lastNDSError.code = NDSError_NoError; + _lastNDSError.tag = NDSErrorTag_None; + break; + + case EMUHALT_REASON_SYSTEM_POWERED_OFF: + _lastNDSError.code = NDSError_SystemPoweredOff; + _lastNDSError.tag = NDSErrorTag_None; + break; + + case EMUHALT_REASON_JIT_UNMAPPED_ADDRESS_EXCEPTION: + _lastNDSError.code = NDSError_JITUnmappedAddressException; + _lastNDSError.tag = errorTag; + break; + + case EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION: + case EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION: + _lastNDSError.code = NDSError_ARMUndefinedInstructionException; + _lastNDSError.tag = errorTag; + break; + + case EMUHALT_REASON_UNKNOWN: + default: + _lastNDSError.code = NDSError_UnknownError; + _lastNDSError.tag = errorTag; + break; + } + + NDS_CurrentCPUInfoToNDSError(_lastNDSError); + GPU->ForceFrameStop(); + execute = false; + + //printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr); #ifdef LOG_ARM9 if (fp_dis9) diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index c182c7338..2b729c3f7 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -82,6 +82,52 @@ enum ROM_DSGBA }; +enum EmuHaltReasonCode +{ + EMUHALT_REASON_USER_REQUESTED_HALT = 0, + + EMUHALT_REASON_SYSTEM_POWERED_OFF = 1000, + + EMUHALT_REASON_JIT_UNMAPPED_ADDRESS_EXCEPTION = 2000, + EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION, + EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION, + + EMUHALT_REASON_UNKNOWN = 10000 +}; + +enum NDSErrorCode +{ + NDSError_NoError = 0, + + NDSError_SystemPoweredOff = 1000, + + NDSError_JITUnmappedAddressException = 2000, + NDSError_ARMUndefinedInstructionException, + + NDSError_UnknownError = 10000 +}; + +enum NDSErrorTag +{ + NDSErrorTag_None = 0, + NDSErrorTag_ARM9 = 1, + NDSErrorTag_ARM7 = 2, + NDSErrorTag_BothCPUs = 3, +}; + +struct NDSError +{ + NDSErrorCode code; + NDSErrorTag tag; + u32 programCounterARM9; + u32 instructionARM9; + u32 instructionAddrARM9; + u32 programCounterARM7; + u32 instructionARM7; + u32 instructionAddrARM7; +}; +typedef struct NDSError NDSError; + //#define LOG_ARM9 //#define LOG_ARM7 @@ -143,7 +189,9 @@ struct NDS_header #include "PACKED_END.h" extern void debug(); -void emu_halt(); +NDSError NDS_GetLastError(); +static void NDS_CurrentCPUInfoToNDSError(NDSError &ndsError); +void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag); extern u64 nds_timer; void NDS_Reschedule(); diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index 38d93b502..9595ede53 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -498,7 +498,7 @@ void armcpu_exception(armcpu_t *cpu, u32 number) case EXCEPTION_SWI: cpumode = SVC; break; case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break; case EXCEPTION_DATA_ABORT: cpumode = ABT; break; - case EXCEPTION_RESERVED_0x14: emu_halt(); break; + case EXCEPTION_RESERVED_0x14: emu_halt(EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7); break; case EXCEPTION_IRQ: cpumode = IRQ; break; case EXCEPTION_FAST_IRQ: cpumode = FIQ; break; } @@ -576,7 +576,7 @@ u32 TRAPUNDEF(armcpu_t* cpu) } else { - emu_halt(); + emu_halt(EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7); return 4; } } diff --git a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp index f28102049..fb2e96276 100644 --- a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp +++ b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp @@ -379,20 +379,20 @@ void ClientExecutionControl::SetEnableGameSpecificHacks(bool enable) bool ClientExecutionControl::GetEnableExternalBIOS() { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); const bool enable = this->_settingsPending.enableExternalBIOS; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); return enable; } void ClientExecutionControl::SetEnableExternalBIOS(bool enable) { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); this->_settingsPending.enableExternalBIOS = enable; - this->_newSettingsPendingOnNDSExec = true; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } bool ClientExecutionControl::GetEnableBIOSInterrupts() @@ -433,38 +433,38 @@ void ClientExecutionControl::SetEnableBIOSPatchDelayLoop(bool enable) bool ClientExecutionControl::GetEnableExternalFirmware() { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); const bool enable = this->_settingsPending.enableExternalFirmware; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); return enable; } void ClientExecutionControl::SetEnableExternalFirmware(bool enable) { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); this->_settingsPending.enableExternalFirmware = enable; - this->_newSettingsPendingOnNDSExec = true; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } bool ClientExecutionControl::GetEnableFirmwareBoot() { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); const bool enable = this->_settingsPending.enableFirmwareBoot; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); return enable; } void ClientExecutionControl::SetEnableFirmwareBoot(bool enable) { - pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); this->_settingsPending.enableFirmwareBoot = enable; - this->_newSettingsPendingOnNDSExec = true; - pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } bool ClientExecutionControl::GetEnableDebugConsole() @@ -702,18 +702,22 @@ void ClientExecutionControl::ApplySettingsOnReset() if (this->_newSettingsPendingOnReset) { - this->_settingsApplied.cpuEngineID = this->_settingsPending.cpuEngineID; - this->_settingsApplied.JITMaxBlockSize = this->_settingsPending.JITMaxBlockSize; + this->_settingsApplied.cpuEngineID = this->_settingsPending.cpuEngineID; + this->_settingsApplied.JITMaxBlockSize = this->_settingsPending.JITMaxBlockSize; - this->_settingsApplied.filePathARM9BIOS = this->_settingsPending.filePathARM9BIOS; - this->_settingsApplied.filePathARM7BIOS = this->_settingsPending.filePathARM7BIOS; - this->_settingsApplied.filePathFirmware = this->_settingsPending.filePathFirmware; - this->_settingsApplied.filePathSlot1R4 = this->_settingsPending.filePathSlot1R4; + this->_settingsApplied.filePathARM9BIOS = this->_settingsPending.filePathARM9BIOS; + this->_settingsApplied.filePathARM7BIOS = this->_settingsPending.filePathARM7BIOS; + this->_settingsApplied.filePathFirmware = this->_settingsPending.filePathFirmware; + this->_settingsApplied.filePathSlot1R4 = this->_settingsPending.filePathSlot1R4; - this->_settingsApplied.cpuEmulationEngineName = this->_settingsPending.cpuEmulationEngineName; - this->_settingsApplied.slot1DeviceName = this->_settingsPending.slot1DeviceName; - this->_ndsFrameInfo.cpuEmulationEngineName = this->_settingsApplied.cpuEmulationEngineName; - this->_ndsFrameInfo.slot1DeviceName = this->_settingsApplied.slot1DeviceName; + this->_settingsApplied.enableExternalBIOS = this->_settingsPending.enableExternalBIOS; + this->_settingsApplied.enableExternalFirmware = this->_settingsPending.enableExternalFirmware; + this->_settingsApplied.enableFirmwareBoot = this->_settingsPending.enableFirmwareBoot; + + this->_settingsApplied.cpuEmulationEngineName = this->_settingsPending.cpuEmulationEngineName; + this->_settingsApplied.slot1DeviceName = this->_settingsPending.slot1DeviceName; + this->_ndsFrameInfo.cpuEmulationEngineName = this->_settingsApplied.cpuEmulationEngineName; + this->_ndsFrameInfo.slot1DeviceName = this->_settingsApplied.slot1DeviceName; const bool didChangeSlot1Type = (this->_settingsApplied.slot1DeviceType != this->_settingsPending.slot1DeviceType); if (didChangeSlot1Type) @@ -724,8 +728,12 @@ void ClientExecutionControl::ApplySettingsOnReset() this->_newSettingsPendingOnReset = false; pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); - CommonSettings.use_jit = (this->_settingsApplied.cpuEngineID == CPUEmulationEngineID_DynamicRecompiler); - CommonSettings.jit_max_block_size = this->_settingsApplied.JITMaxBlockSize; + CommonSettings.use_jit = (this->_settingsApplied.cpuEngineID == CPUEmulationEngineID_DynamicRecompiler); + CommonSettings.jit_max_block_size = this->_settingsApplied.JITMaxBlockSize; + CommonSettings.UseExtBIOS = this->_settingsApplied.enableExternalBIOS; + CommonSettings.UseExtFirmware = this->_settingsApplied.enableExternalFirmware; + CommonSettings.UseExtFirmwareSettings = this->_settingsApplied.enableExternalFirmware; + CommonSettings.BootFromFirmware = this->_settingsApplied.enableFirmwareBoot; if (this->_settingsApplied.filePathARM9BIOS.length() == 0) { @@ -842,11 +850,8 @@ void ClientExecutionControl::ApplySettingsOnNDSExec() this->_settingsApplied.enableAdvancedBusLevelTiming = this->_settingsPending.enableAdvancedBusLevelTiming; this->_settingsApplied.enableRigorous3DRenderingTiming = this->_settingsPending.enableRigorous3DRenderingTiming; this->_settingsApplied.enableGameSpecificHacks = this->_settingsPending.enableGameSpecificHacks; - this->_settingsApplied.enableExternalBIOS = this->_settingsPending.enableExternalBIOS; this->_settingsApplied.enableBIOSInterrupts = this->_settingsPending.enableBIOSInterrupts; this->_settingsApplied.enableBIOSPatchDelayLoop = this->_settingsPending.enableBIOSPatchDelayLoop; - this->_settingsApplied.enableExternalFirmware = this->_settingsPending.enableExternalFirmware; - this->_settingsApplied.enableFirmwareBoot = this->_settingsPending.enableFirmwareBoot; this->_settingsApplied.enableDebugConsole = this->_settingsPending.enableDebugConsole; this->_settingsApplied.enableEnsataEmulation = this->_settingsPending.enableEnsataEmulation; @@ -862,12 +867,8 @@ void ClientExecutionControl::ApplySettingsOnNDSExec() CommonSettings.advanced_timing = this->_settingsApplied.enableAdvancedBusLevelTiming; CommonSettings.rigorous_timing = this->_settingsApplied.enableRigorous3DRenderingTiming; - CommonSettings.UseExtBIOS = this->_settingsApplied.enableExternalBIOS; CommonSettings.SWIFromBIOS = this->_settingsApplied.enableBIOSInterrupts; CommonSettings.PatchSWI3 = this->_settingsApplied.enableBIOSPatchDelayLoop; - CommonSettings.UseExtFirmware = this->_settingsApplied.enableExternalFirmware; - CommonSettings.UseExtFirmwareSettings = this->_settingsApplied.enableExternalFirmware; - CommonSettings.BootFromFirmware = this->_settingsApplied.enableFirmwareBoot; CommonSettings.DebugConsole = this->_settingsApplied.enableDebugConsole; CommonSettings.EnsataEmulation = this->_settingsApplied.enableEnsataEmulation; diff --git a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj index e23d372a4..f217d304f 100644 --- a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj @@ -1422,6 +1422,11 @@ ABAE30BD1869484F00C92F4F /* Image_Piano.png in Resources */ = {isa = PBXBuildFile; fileRef = ABAE30BA1869484F00C92F4F /* Image_Piano.png */; }; ABAE30BE1869484F00C92F4F /* Image_Piano.png in Resources */ = {isa = PBXBuildFile; fileRef = ABAE30BA1869484F00C92F4F /* Image_Piano.png */; }; ABAE30BF1869484F00C92F4F /* Image_Piano.png in Resources */ = {isa = PBXBuildFile; fileRef = ABAE30BA1869484F00C92F4F /* Image_Piano.png */; }; + ABAFD2751F7110E4007705BD /* gdbstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF171345ACA900AF11D1 /* gdbstub.cpp */; }; + ABAFD2761F7110E4007705BD /* gdbstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF171345ACA900AF11D1 /* gdbstub.cpp */; }; + ABAFD2771F7110E5007705BD /* gdbstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF171345ACA900AF11D1 /* gdbstub.cpp */; }; + ABAFD2781F7110E5007705BD /* gdbstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF171345ACA900AF11D1 /* gdbstub.cpp */; }; + ABAFD2791F7110E6007705BD /* gdbstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF171345ACA900AF11D1 /* gdbstub.cpp */; }; ABB6AD5D173A3F2B00EC2E8D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABB6AD5C173A3F2B00EC2E8D /* Carbon.framework */; }; ABB9212117CEB4110049D4C5 /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABB9212017CEB4110049D4C5 /* slot1comp_protocol.cpp */; }; ABB9212217CEB4110049D4C5 /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABB9212017CEB4110049D4C5 /* slot1comp_protocol.cpp */; }; @@ -4611,6 +4616,7 @@ ABD4F2741F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */, ABC04DA41F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */, ABC04DCB1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */, + ABAFD2791F7110E6007705BD /* gdbstub.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4798,6 +4804,7 @@ ABD4F2751F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */, ABC04DA51F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */, ABC04DCC1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */, + ABAFD2781F7110E5007705BD /* gdbstub.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5015,6 +5022,7 @@ ABD4F2731F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */, ABC04DA31F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */, ABC04DCA1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */, + ABAFD2751F7110E4007705BD /* gdbstub.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5232,6 +5240,7 @@ ABD4F2771F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */, ABC04DA71F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */, ABC04DCE1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */, + ABAFD2761F7110E4007705BD /* gdbstub.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5419,6 +5428,7 @@ ABD4F2761F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */, ABC04DA61F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */, ABC04DCD1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */, + ABAFD2771F7110E5007705BD /* gdbstub.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5625,6 +5635,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( _DEBUG, "DEBUG=1", + GDB_STUB, ); GCC_STRICT_ALIASING = YES; GCC_SYMBOLS_PRIVATE_EXTERN = NO; diff --git a/desmume/src/frontend/cocoa/cocoa_core.h b/desmume/src/frontend/cocoa/cocoa_core.h index 4bffde476..8e4841390 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.h +++ b/desmume/src/frontend/cocoa/cocoa_core.h @@ -22,6 +22,9 @@ #include #import "cocoa_util.h" +#include "../../NDSSystem.h" +#undef BOOL + class ClientExecutionControl; @class CocoaDSCore; @@ -68,6 +71,7 @@ typedef struct NSString *slot1StatusText; NSString *frameStatus; NSString *executionSpeedStatus; + NSString *errorStatus; OSSpinLock spinlockCdsController; OSSpinLock spinlockMasterExecute; @@ -115,6 +119,7 @@ typedef struct @property (assign) NSString *slot1StatusText; @property (assign) NSString *frameStatus; @property (assign) NSString *executionSpeedStatus; +@property (retain) NSString *errorStatus; @property (copy) NSURL *arm9ImageURL; @property (copy) NSURL *arm7ImageURL; @@ -146,6 +151,8 @@ typedef struct - (BOOL) startReplayRecording:(NSURL *)fileURL sramURL:(NSURL *)sramURL; - (void) stopReplay; +- (void) postNDSError:(const NDSError &)ndsError; + @end static void* RunCoreThread(void *arg); diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index 973fda2ad..7cd74f0ce 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -118,6 +118,7 @@ volatile bool execute = true; @synthesize slot1StatusText; @synthesize frameStatus; @synthesize executionSpeedStatus; +@synthesize errorStatus; @dynamic arm9ImageURL; @dynamic arm7ImageURL; @@ -207,6 +208,7 @@ volatile bool execute = true; frameStatus = @"---"; executionSpeedStatus = @"1.00x"; + errorStatus = @""; return self; } @@ -221,6 +223,7 @@ volatile bool execute = true; [self setCdsFirmware:nil]; [self setCdsGPU:nil]; [self setCdsOutputList:nil]; + [self setErrorStatus:nil]; pthread_cancel(coreThread); pthread_join(coreThread, NULL); @@ -242,14 +245,23 @@ volatile bool execute = true; - (void) setMasterExecute:(BOOL)theState { OSSpinLockLock(&spinlockMasterExecute); - execute = theState ? true : false; + + if (theState) + { + execute = true; + } + else + { + emu_halt(EMUHALT_REASON_UNKNOWN, NDSErrorTag_BothCPUs); + } + OSSpinLockUnlock(&spinlockMasterExecute); } - (BOOL) masterExecute { OSSpinLockLock(&spinlockMasterExecute); - const BOOL theState = execute ? YES : NO; + const BOOL theState = (execute) ? YES : NO; OSSpinLockUnlock(&spinlockMasterExecute); return theState; @@ -855,8 +867,8 @@ volatile bool execute = true; pthread_mutex_unlock(&threadParam.mutexThreadExecute); [self updateSlot1DeviceStatus]; - [self restoreCoreState]; [self setMasterExecute:YES]; + [self restoreCoreState]; [[self cdsController] reset]; [[self cdsController] updateMicLevel]; } @@ -988,6 +1000,111 @@ volatile bool execute = true; FCEUI_StopMovie(); } +- (void) postNDSError:(const NDSError &)ndsError +{ + NSString *newErrorString = nil; + + switch (ndsError.code) + { + case NDSError_NoError: + // Do nothing if there is no error. + return; + + case NDSError_SystemPoweredOff: + newErrorString = @"The system powered off using the ARM7 SPI device."; + break; + + case NDSError_JITUnmappedAddressException: + { + if (ndsError.tag == NDSErrorTag_ARM9) + { + newErrorString = [NSString stringWithFormat: +@"JIT UNMAPPED ADDRESS EXCEPTION - ARM9:\n\ +\tARM9 Program Counter: 0x%08X\n\ +\tARM9 Instruction: 0x%08X\n\ +\tARM9 Instruction Address: 0x%08X", + ndsError.programCounterARM9, ndsError.instructionARM9, ndsError.instructionAddrARM9]; + } + else if (ndsError.tag == NDSErrorTag_ARM7) + { + newErrorString = [NSString stringWithFormat: +@"JIT UNMAPPED ADDRESS EXCEPTION - ARM7:\n\ +\tARM7 Program Counter: 0x%08X\n\ +\tARM7 Instruction: 0x%08X\n\ +\tARM7 Instruction Address: 0x%08X", + ndsError.programCounterARM7, ndsError.instructionARM7, ndsError.instructionAddrARM7]; + } + else + { + newErrorString = [NSString stringWithFormat: +@"JIT UNMAPPED ADDRESS EXCEPTION - UNKNOWN CPU:\n\ +\tARM9 Program Counter: 0x%08X\n\ +\tARM9 Instruction: 0x%08X\n\ +\tARM9 Instruction Address: 0x%08X\n\ +\tARM7 Program Counter: 0x%08X\n\ +\tARM7 Instruction: 0x%08X\n\ +\tARM7 Instruction Address: 0x%08X", + ndsError.programCounterARM9, ndsError.instructionARM9, ndsError.instructionAddrARM9, + ndsError.programCounterARM7, ndsError.instructionARM7, ndsError.instructionAddrARM7]; + } + break; + } + + case NDSError_ARMUndefinedInstructionException: + { + if (ndsError.tag == NDSErrorTag_ARM9) + { + newErrorString = [NSString stringWithFormat: +@"ARM9 UNDEFINED INSTRUCTION EXCEPTION:\n\ +\tARM9 Program Counter: 0x%08X\n\ +\tARM9 Instruction: 0x%08X\n\ +\tARM9 Instruction Address: 0x%08X", + ndsError.programCounterARM9, ndsError.instructionARM9, ndsError.instructionAddrARM9]; + } + else if (ndsError.tag == NDSErrorTag_ARM7) + { + newErrorString = [NSString stringWithFormat: +@"ARM7 UNDEFINED INSTRUCTION EXCEPTION:\n\ +\tARM7 Program Counter: 0x%08X\n\ +\tARM7 Instruction: 0x%08X\n\ +\tARM7 Instruction Address: 0x%08X", + ndsError.programCounterARM7, ndsError.instructionARM7, ndsError.instructionAddrARM7]; + } + else + { + newErrorString = [NSString stringWithFormat: +@"UNKNOWN ARM CPU UNDEFINED INSTRUCTION EXCEPTION:\n\ +\tARM9 Program Counter: 0x%08X\n\ +\tARM9 Instruction: 0x%08X\n\ +\tARM9 Instruction Address: 0x%08X\n\ +\tARM7 Program Counter: 0x%08X\n\ +\tARM7 Instruction: 0x%08X\n\ +\tARM7 Instruction Address: 0x%08X", + ndsError.programCounterARM9, ndsError.instructionARM9, ndsError.instructionAddrARM9, + ndsError.programCounterARM7, ndsError.instructionARM7, ndsError.instructionAddrARM7]; + } + break; + } + + case NDSError_UnknownError: + default: + newErrorString = [NSString stringWithFormat: +@"UNKNOWN ERROR:\n\ +\tARM9 Program Counter: 0x%08X\n\ +\tARM9 Instruction: 0x%08X\n\ +\tARM9 Instruction Address: 0x%08X\n\ +\tARM7 Program Counter: 0x%08X\n\ +\tARM7 Instruction: 0x%08X\n\ +\tARM7 Instruction Address: 0x%08X", + ndsError.programCounterARM9, ndsError.instructionARM9, ndsError.instructionAddrARM9, + ndsError.programCounterARM7, ndsError.instructionARM7, ndsError.instructionAddrARM7]; + break; + } + + [self setErrorStatus:newErrorString]; + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.handleNDSError" object:self userInfo:nil]; +} + @end static void* RunCoreThread(void *arg) @@ -1039,9 +1156,10 @@ static void* RunCoreThread(void *arg) // Check if an internal execution error occurred that halted the emulation. if (!execute) { + NDSError ndsError = NDS_GetLastError(); pthread_mutex_unlock(¶m->mutexThreadExecute); - // TODO: Message the core that emulation halted. - NSLog(@"The emulator halted during execution. Was it an internal error that caused this?"); + + [cdsCore postNDSError:ndsError]; continue; } diff --git a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.strings index 7525a3a6a81521ed4f47d01f7ef9a2ce56c5d758..c6c55143fe5ea60427f6133b3a40e2753602a50a 100644 GIT binary patch delta 447 zcmX@KQvBN%@rD-07N!>F7M3lnhptTjmBr-6oy$HA(H`zHb!P9&FKzYj4J$o3@!}832eb6_b?;d?*rAH1f0So&pZ?)ClgMr_){T403;QFE-aaTK8sNuq+xPHnixp=3;_6~c2NKT delta 19 bcmeyiMf}i8@rD-07N!>F7M3lnhpqqsR$2%x diff --git a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib index ae978c1f5..ee6f5f11b 100644 --- a/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib +++ b/desmume/src/frontend/cocoa/translations/English.lproj/MainMenu.xib @@ -12,6 +12,7 @@ YES + YES @@ -1944,6 +1945,14 @@ + + + Show GDB Stub Control... + + 2147483647 + + + YES @@ -1954,9 +1963,9 @@ - + - Show GDB Stub Control... + Disable Metal (requires app restart) 2147483647 @@ -1972,9 +1981,9 @@ - + - Disable Metal (requires app restart) + Simulate Emulation Crash 2147483647 @@ -13636,7 +13645,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {1.7976931348623157e+308, 1.7976931348623157e+308} {700, 250} - + 256 YES @@ -13645,6 +13654,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{17, 351}, {666, 34}} + YES 67108864 @@ -13663,6 +13673,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{17, 351}, {666, 34}} + YES 67108864 @@ -13681,6 +13692,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 289 {{362, 12}, {162, 32}} + 2 YES @@ -13703,6 +13715,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 289 {{200, 12}, {162, 32}} + YES 67108864 @@ -13724,6 +13737,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{17, 315}, {666, 28}} + YES 67108864 @@ -13742,6 +13756,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{17, 315}, {666, 28}} + YES 67108864 @@ -13760,6 +13775,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 292 {{18, 21}, {182, 18}} + YES 67108864 @@ -13783,6 +13799,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 289 {{524, 12}, {162, 32}} + 1 YES @@ -13815,6 +13832,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 256 {700, 229} + _NS:1718 YES NO @@ -13824,14 +13842,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 256 {700, 17} + _NS:1720 - - + + -2147483392 {{224, 0}, {16, 17}} - _NS:1724 @@ -13944,6 +13962,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {{1, 17}, {700, 229}} + _NS:1716 @@ -13955,6 +13974,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2147483392 {{224, 17}, {15, 102}} + _NS:1741 NO @@ -13966,6 +13986,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2147483392 {{1, 197}, {700, 15}} + _NS:1743 NO 1 @@ -13982,14 +14003,15 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {{1, 0}, {700, 17}} + _NS:1721 - {{-1, 60}, {702, 247}} + _NS:1714 133682 @@ -14004,6 +14026,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {700, 405} + + {{0, 0}, {1920, 1177}} {700, 272} @@ -14237,6 +14261,125 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {1.7976931348623157e+308, 1.7976931348623157e+308} YES + + 1 + 2 + {{157, 347}, {400, 114}} + 1685586944 + NDS Error + NSWindow + + + + + 256 + + YES + + + 268 + {{17, 77}, {366, 17}} + + _NS:3939 + YES + + 67108864 + 272891904 + The emulation has halted due to an internal issue. + + LucidaGrande-Bold + 13 + 16 + + _NS:3939 + + + + + NO + 1 + + + + 289 + {{290, 12}, {96, 32}} + + _NS:610 + YES + + 67108864 + 134217728 + Stop + + _NS:610 + + -2038284288 + 129 + + DQ + 200 + 25 + + NO + + + + 289 + {{194, 12}, {96, 32}} + + _NS:610 + 2 + YES + + 67108864 + 134217728 + Reset + + _NS:610 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 292 + {{17, 53}, {366, 16}} + + _NS:3939 + YES + + 69206017 + 272760832 + + + Monaco + 11 + 16 + + error string + _NS:3939 + + + + + NO + 1 + + + {400, 114} + + _NS:122 + + {{0, 0}, {1440, 878}} + {1.7976931348623157e+308, 1.7976931348623157e+308} + NO + 7 2 @@ -15131,11 +15274,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 69206081 137216 Text Cell - - Monaco - 11 - 16 - + @@ -30838,6 +30977,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 frameJumpBehavior frameJumpNumberFramesForward frameJumpToFrameIndex + errorStatus CocoaDSCore @@ -44538,6 +44678,82 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 10520 + + + ndsErrorSheet + + + + 10532 + + + + closeSheet: + + + + 10533 + + + + closeSheet: + + + + 10534 + + + + value: selection.errorStatus + + + + + + value: selection.errorStatus + value + selection.errorStatus + 2 + + + 10535 + + + + ndsErrorStatusTextField + + + + 10536 + + + + simulateEmulationCrash: + + + + 10537 + + + + hidden: isDeveloperPlusBuild + + + + + + hidden: isDeveloperPlusBuild + hidden + isDeveloperPlusBuild + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 10539 + @@ -46043,9 +46259,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + - + @@ -56727,6 +56944,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + Window (Game Data Migration Assistant) 9706 @@ -60510,6 +60728,89 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 + + 10521 + + + + + 10522 + + + YES + + + + Window (NDS Error) + + + 10523 + + + YES + + + + + + + + + 10524 + + + YES + + + + + + 10525 + + + + + 10526 + + + YES + + + + + + 10527 + + + + + 10528 + + + YES + + + + + + 10529 + + + + + 10530 + + + YES + + + + + + 10531 + + + @@ -60886,6 +61187,23 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 10505.IBPluginDependency 10508.IBPluginDependency 10509.IBPluginDependency + 10521.IBPluginDependency + 10522.IBEditorWindowLastContentRect + 10522.IBPluginDependency + 10522.IBWindowTemplateEditedContentRect + 10522.NSWindowTemplate.visibleAtLaunch + 10523.IBPluginDependency + 10524.IBPluginDependency + 10524.IBViewBoundsToFrameTransform + 10525.IBPluginDependency + 10526.IBPluginDependency + 10526.IBViewBoundsToFrameTransform + 10527.IBPluginDependency + 10528.IBPluginDependency + 10528.IBViewBoundsToFrameTransform + 10529.IBPluginDependency + 10530.IBPluginDependency + 10531.IBPluginDependency 1113.IBPluginDependency 1114.IBPluginDependency 1115.IBPluginDependency @@ -61210,6 +61528,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 3211.IBPluginDependency 3213.IBPluginDependency 3214.IBPluginDependency + 3456.IBEditorWindowLastContentRect 3456.IBPluginDependency 3456.IBWindowTemplateEditedContentRect 3456.NSWindowTemplate.visibleAtLaunch @@ -63066,6 +63385,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 968.IBPluginDependency 969.IBPluginDependency 970.IBPluginDependency + 9705.IBEditorWindowLastContentRect 9705.IBPluginDependency 9705.IBWindowTemplateEditedContentRect 9705.NSWindowTemplate.visibleAtLaunch @@ -63879,6 +64199,29 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + {{617, 513}, {400, 114}} + com.apple.InterfaceBuilder.CocoaPlugin + {{617, 513}, {400, 114}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBiAAAw3gAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDXQAAwpwAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDGAAAww4AAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -64369,7 +64712,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{380, 836}, {512, 20}} + {{463, 836}, {512, 20}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -64398,8 +64741,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + {{741, 693}, {335, 163}} com.apple.InterfaceBuilder.CocoaPlugin - {{1241, 208}, {335, 163}} + {{741, 693}, {335, 163}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -65509,7 +65853,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{598, 723}, {292, 113}} + {{787, 703}, {292, 133}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -67105,8 +67449,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + {{0, 429}, {700, 405}} com.apple.InterfaceBuilder.CocoaPlugin - {{189, 422}, {700, 405}} + {{0, 429}, {700, 405}} {700, 250} @@ -67290,7 +67635,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - 10520 + 10539 @@ -68186,6 +68531,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 saveEmuSaveStateAs: saveEmuSaveStateSlot: setVerticalSyncForNonLayerBackedViews: + simulateEmulationCrash: slot1Eject: stopReplay: toggleAllDisplays: @@ -68254,6 +68600,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 id id id + id @@ -68297,6 +68644,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 saveEmuSaveStateAs: saveEmuSaveStateSlot: setVerticalSyncForNonLayerBackedViews: + simulateEmulationCrash: slot1Eject: stopReplay: toggleAllDisplays: @@ -68462,6 +68810,10 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 setVerticalSyncForNonLayerBackedViews: id + + simulateEmulationCrash: + id + slot1Eject: id @@ -68537,6 +68889,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 exportRomSavePanelAccessoryView firmwarePanelController inputManager + ndsErrorSheet + ndsErrorStatusTextField romInfoPanelController saveFileMigrationSheet saveStatePrecloseSheet @@ -68558,6 +68912,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 NSView NSObjectController InputManager + NSWindow + NSTextField NSObjectController NSWindow NSWindow @@ -68582,6 +68938,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 exportRomSavePanelAccessoryView firmwarePanelController inputManager + ndsErrorSheet + ndsErrorStatusTextField romInfoPanelController saveFileMigrationSheet saveStatePrecloseSheet @@ -68642,6 +69000,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 inputManager InputManager + + ndsErrorSheet + NSWindow + + + ndsErrorStatusTextField + NSTextField + romInfoPanelController NSObjectController diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.h b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.h index 65aef5bc2..1c78969f4 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.h +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.h @@ -61,6 +61,8 @@ class AudioSampleBlockGenerator; NSWindow *slot1ManagerWindow; NSWindow *saveFileMigrationSheet; NSWindow *saveStatePrecloseSheet; + NSWindow *ndsErrorSheet; + NSTextField *ndsErrorStatusTextField; NSView *exportRomSavePanelAccessoryView; BOOL isSaveStateEdited; @@ -74,6 +76,7 @@ class AudioSampleBlockGenerator; BOOL isShowingSaveStateDialog; BOOL isShowingFileMigrationDialog; BOOL isUserInterfaceBlockingExecution; + BOOL _isNDSErrorSheetAlreadyShown; NSURL *currentSaveStateURL; NSInteger selectedExportRomSaveID; NSInteger selectedRomSaveTypeID; @@ -130,6 +133,8 @@ class AudioSampleBlockGenerator; @property (readonly) IBOutlet NSWindow *slot1ManagerWindow; @property (readonly) IBOutlet NSWindow *saveFileMigrationSheet; @property (readonly) IBOutlet NSWindow *saveStatePrecloseSheet; +@property (readonly) IBOutlet NSWindow *ndsErrorSheet; +@property (readonly) IBOutlet NSTextField *ndsErrorStatusTextField; @property (readonly) IBOutlet NSView *exportRomSavePanelAccessoryView; @property (readonly) NSImage *iconExecute; @@ -213,6 +218,7 @@ class AudioSampleBlockGenerator; // Misc IBActions - (IBAction) chooseSlot1R4Directory:(id)sender; - (IBAction) slot1Eject:(id)sender; +- (IBAction) simulateEmulationCrash:(id)sender; - (IBAction) writeDefaults3DRenderingSettings:(id)sender; - (IBAction) writeDefaultsEmulationSettings:(id)sender; diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index c655804ce..f2648b5ba 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -59,6 +59,8 @@ @synthesize slot1ManagerWindow; @synthesize saveFileMigrationSheet; @synthesize saveStatePrecloseSheet; +@synthesize ndsErrorSheet; +@synthesize ndsErrorStatusTextField; @synthesize exportRomSavePanelAccessoryView; @synthesize iconExecute; @@ -116,6 +118,7 @@ isShowingSaveStateDialog = NO; isShowingFileMigrationDialog = NO; isUserInterfaceBlockingExecution = NO; + _isNDSErrorSheetAlreadyShown = NO; currentSaveStateURL = nil; selectedRomSaveTypeID = ROMSAVETYPE_AUTOMATIC; @@ -155,6 +158,11 @@ name:@"org.desmume.DeSmuME.loadRomDidFinish" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleNDSError:) + name:@"org.desmume.DeSmuME.handleNDSError" + object:nil]; + return self; } @@ -900,6 +908,12 @@ [cdsCore slot1Eject]; } +- (IBAction) simulateEmulationCrash:(id)sender +{ + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + [cdsCore setMasterExecute:NO]; +} + - (IBAction) writeDefaults3DRenderingSettings:(id)sender { CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; @@ -1814,6 +1828,9 @@ [[windowController window] displayIfNeeded]; } + [cdsCore execControl]->ApplySettingsOnReset(); + [cdsCore setMasterExecute:YES]; + // After the ROM loading is complete, send an execute message to the Cocoa DS per // user preferences. if ([[NSUserDefaults standardUserDefaults] boolForKey:@"General_ExecuteROMOnLoad"]) @@ -1901,6 +1918,50 @@ return result; } +- (void) handleNDSError:(NSNotification *)aNotification +{ + [self setIsUserInterfaceBlockingExecution:YES]; + + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + NSString *ndsErrorString = [cdsCore errorStatus]; + const char *ndsErrorCString = [ndsErrorString cStringUsingEncoding:NSUTF8StringEncoding]; + size_t lineCount = 1; + + for (size_t i = 0; i < [ndsErrorString length]; i++) + { + if (ndsErrorCString[i] == '\n') + { + lineCount++; + } + } + + NSRect newSheetFrameRect = [ndsErrorSheet frame]; + newSheetFrameRect.size.height = 98.0f + (16.0f * lineCount); + + // For some reason, when the sheet is shown for the very first time, + // the sheet doesn't drop down as low as it should. However, upon + // subsequent showings, the sheet drops down to the intended distance. + // To compensate for this difference, the first sheet showing will + // have a little added height to it. + if (!_isNDSErrorSheetAlreadyShown) + { + _isNDSErrorSheetAlreadyShown = YES; + newSheetFrameRect.size.height += 22.0f; + } + + [ndsErrorSheet setFrame:newSheetFrameRect display:NO]; + + NSRect newTextFieldRect = [ndsErrorStatusTextField frame]; + newTextFieldRect.size.height = 16.0f * lineCount; + [ndsErrorStatusTextField setFrame:newTextFieldRect]; + + [NSApp beginSheet:ndsErrorSheet + modalForWindow:(NSWindow *)[[windowList objectAtIndex:0] window] + modalDelegate:self + didEndSelector:@selector(didEndErrorSheet:returnCode:contextInfo:) + contextInfo:nil]; +} + - (void) addOutputToCore:(CocoaDSOutput *)theOutput { CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; @@ -2097,6 +2158,23 @@ [cdsCore setSlot1R4URL:selectedDirURL]; } +- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + [sheet orderOut:self]; + [self setIsUserInterfaceBlockingExecution:NO]; + + switch (returnCode) + { + case COCOA_DIALOG_OPTION: // Reset + [self reset:self]; + break; + + case NSCancelButton: // Stop + default: + break; + } +} + - (void) updateAllWindowTitles { if ([windowList count] < 1) diff --git a/desmume/src/frontend/posix/gtk/main.cpp b/desmume/src/frontend/posix/gtk/main.cpp index 8e994aa33..e167ffac1 100644 --- a/desmume/src/frontend/posix/gtk/main.cpp +++ b/desmume/src/frontend/posix/gtk/main.cpp @@ -2599,7 +2599,7 @@ public: static void DoQuit() { - emu_halt(); + emu_halt(EMUHALT_REASON_USER_REQUESTED_HALT, NDSErrorTag_None); gtk_main_quit(); } diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp index 16ea02198..250a41f03 100644 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -2326,7 +2326,7 @@ static void StepRunLoop_Throttle(bool allowSleep = true, int forceFrameSkip = -1 if (frameAdvance && allowSleep) { frameAdvance = false; - emu_halt(); + emu_halt(EMUHALT_REASON_USER_REQUESTED_HALT, NDSErrorTag_None); SPU_Pause(1); } if(execute && emu_paused && !frameAdvance) @@ -2386,7 +2386,7 @@ bool NDS_Pause(bool showMsg) { if(paused) return false; - emu_halt(); + emu_halt(EMUHALT_REASON_USER_REQUESTED_HALT, NDSErrorTag_None); paused = TRUE; SPU_Pause(1); while (!paused) {} @@ -2620,7 +2620,7 @@ void MenuDeinit() static void ExitRunLoop() { finished = TRUE; - emu_halt(); + emu_halt(EMUHALT_REASON_USER_REQUESTED_HALT, NDSErrorTag_None); } class WinWifiHandler : public WifiHandler