diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp index 1a3095421..a7f98548b 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.cpp +++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp @@ -91,8 +91,10 @@ void ClientDisplayView::__InstanceInit(const ClientDisplayViewProperties &props) _showCPULoadAverage = false; _showRTC = false; + _clientFrameInfo.videoFPS = 0; + _ndsFrameInfo.clear(); + memset(&_emuDisplayInfo, 0, sizeof(_emuDisplayInfo)); - memset(&_emuFrameInfo, 0, sizeof(_emuFrameInfo)); _hudString = "\x01"; // Char value 0x01 will represent the "text box" character, which will always be first in the string. _hudNeedsUpdate = true; _allowViewUpdates = true; @@ -133,36 +135,36 @@ void ClientDisplayView::_UpdateHUDString() if (this->_showVideoFPS) { - ss << "Video FPS: " << this->_emuFrameInfo.videoFPS << "\n"; + ss << "Video FPS: " << this->_clientFrameInfo.videoFPS << "\n"; } if (this->_showRender3DFPS) { - ss << "3D Rendering FPS: " << this->_emuFrameInfo.render3DFPS << "\n"; + ss << "3D Rendering FPS: " << this->_ndsFrameInfo.render3DFPS << "\n"; } if (this->_showFrameIndex) { - ss << "Frame Index: " << this->_emuFrameInfo.frameIndex << "\n"; + ss << "Frame Index: " << this->_ndsFrameInfo.frameIndex << "\n"; } if (this->_showLagFrameCount) { - ss << "Lag Frame Count: " << this->_emuFrameInfo.lagFrameCount << "\n"; + ss << "Lag Frame Count: " << this->_ndsFrameInfo.lagFrameCount << "\n"; } if (this->_showCPULoadAverage) { static char buffer[32]; memset(buffer, 0, sizeof(buffer)); - snprintf(buffer, 25, "CPU Load Avg: %02d%% / %02d%%\n", this->_emuFrameInfo.cpuLoadAvgARM9, this->_emuFrameInfo.cpuLoadAvgARM7); + snprintf(buffer, 25, "CPU Load Avg: %02d%% / %02d%%\n", this->_ndsFrameInfo.cpuLoadAvgARM9, this->_ndsFrameInfo.cpuLoadAvgARM7); ss << buffer; } if (this->_showRTC) { - ss << "RTC: " << this->_emuFrameInfo.rtcString << "\n"; + ss << "RTC: " << this->_ndsFrameInfo.rtcString << "\n"; } this->_hudString = ss.str(); @@ -445,9 +447,11 @@ void ClientDisplayView::CopyHUDFont(const FT_Face &fontFace, const size_t glyphS // Do nothing. This is implementation dependent. } -void ClientDisplayView::SetHUDInfo(const NDSFrameInfo &frameInfo) +void ClientDisplayView::SetHUDInfo(const ClientFrameInfo &clientFrameInfo, const NDSFrameInfo &ndsFrameInfo) { - this->_emuFrameInfo = frameInfo; + this->_clientFrameInfo.videoFPS = clientFrameInfo.videoFPS; + this->_ndsFrameInfo.copyFrom(ndsFrameInfo); + this->_UpdateHUDString(); } @@ -756,9 +760,8 @@ void ClientDisplayView::SetEmuDisplayInfo(const NDSDisplayInfo &ndsDisplayInfo) this->_emuDisplayInfo = ndsDisplayInfo; } -void ClientDisplayView::HandleEmulatorFrameEndEvent(const NDSFrameInfo &frameInfo) +void ClientDisplayView::HandleEmulatorFrameEndEvent() { - this->SetHUDInfo(frameInfo); this->UpdateView(); } diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.h b/desmume/src/frontend/cocoa/ClientDisplayView.h index 5ef045e8f..48bfe43f7 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.h +++ b/desmume/src/frontend/cocoa/ClientDisplayView.h @@ -23,6 +23,8 @@ #include "../../filter/videofilter.h" #include "../../GPU.h" +#include "ClientExecutionControl.h" + #include #include FT_FREETYPE_H @@ -97,17 +99,11 @@ struct LUTValues }; typedef struct LUTValues LUTValues; -struct NDSFrameInfo +struct ClientFrameInfo { uint32_t videoFPS; - uint32_t render3DFPS; - uint32_t frameIndex; - uint32_t lagFrameCount; - uint32_t cpuLoadAvgARM9; - uint32_t cpuLoadAvgARM7; - char rtcString[25]; }; -typedef struct NDSFrameInfo NDSFrameInfo; +typedef struct ClientFrameInfo ClientFrameInfo; struct ClientDisplayViewProperties { @@ -163,8 +159,10 @@ protected: bool _showCPULoadAverage; bool _showRTC; + ClientFrameInfo _clientFrameInfo; + NDSFrameInfo _ndsFrameInfo; + NDSDisplayInfo _emuDisplayInfo; - NDSFrameInfo _emuFrameInfo; std::string _hudString; bool _hudNeedsUpdate; bool _allowViewUpdates; @@ -237,7 +235,7 @@ public: void SetHUDFontPath(const char *filePath); virtual void LoadHUDFont(); virtual void CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, const size_t glyphTileSize, GlyphInfo *glyphInfo); - virtual void SetHUDInfo(const NDSFrameInfo &frameInfo); + virtual void SetHUDInfo(const ClientFrameInfo &clientFrameInfo, const NDSFrameInfo &ndsFrameInfo); const std::string& GetHUDString() const; float GetHUDObjectScale() const; @@ -275,7 +273,7 @@ public: // Emulator interface const NDSDisplayInfo& GetEmuDisplayInfo() const; void SetEmuDisplayInfo(const NDSDisplayInfo &ndsDisplayInfo); - virtual void HandleEmulatorFrameEndEvent(const NDSFrameInfo &frameInfo); + virtual void HandleEmulatorFrameEndEvent(); // Touch screen input handling void GetNDSPoint(const int inputID, const bool isInitialTouchPress, diff --git a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp index dbdccea36..6ba59a479 100644 --- a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp +++ b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp @@ -19,6 +19,9 @@ #include #include "NDSSystem.h" +#include "GPU.h" +#include "movie.h" +#include "rtc.h" #include "ClientExecutionControl.h" @@ -35,40 +38,55 @@ ClientExecutionControl::ClientExecutionControl() _framesToSkip = 0; _prevExecBehavior = ExecutionBehavior_Pause; - _settingsPending.cpuEngineID = CPUEmulationEngineID_Interpreter; - _settingsPending.JITMaxBlockSize = 12; - _settingsPending.filePathARM9BIOS = std::string(); - _settingsPending.filePathARM7BIOS = std::string(); - _settingsPending.filePathFirmware = std::string(); + _settingsPending.cpuEngineID = CPUEmulationEngineID_Interpreter; + _settingsPending.JITMaxBlockSize = 12; + _settingsPending.slot1DeviceType = NDS_SLOT1_RETAIL_AUTO; + _settingsPending.filePathARM9BIOS = std::string(); + _settingsPending.filePathARM7BIOS = std::string(); + _settingsPending.filePathFirmware = std::string(); + _settingsPending.filePathSlot1R4 = std::string(); + _settingsPending.cpuEmulationEngineName = "Interpreter"; + _settingsPending.slot1DeviceName = "Uninitialized"; - _settingsPending.enableAdvancedBusLevelTiming = true; - _settingsPending.enableRigorous3DRenderingTiming = false; - _settingsPending.enableGameSpecificHacks = true; - _settingsPending.enableExternalBIOS = false; - _settingsPending.enableBIOSInterrupts = false; - _settingsPending.enableBIOSPatchDelayLoop = false; - _settingsPending.enableExternalFirmware = false; - _settingsPending.enableFirmwareBoot = false; - _settingsPending.enableDebugConsole = false; - _settingsPending.enableEnsataEmulation = false; + _settingsPending.enableAdvancedBusLevelTiming = true; + _settingsPending.enableRigorous3DRenderingTiming = false; + _settingsPending.enableGameSpecificHacks = true; + _settingsPending.enableExternalBIOS = false; + _settingsPending.enableBIOSInterrupts = false; + _settingsPending.enableBIOSPatchDelayLoop = false; + _settingsPending.enableExternalFirmware = false; + _settingsPending.enableFirmwareBoot = false; + _settingsPending.enableDebugConsole = false; + _settingsPending.enableEnsataEmulation = false; - _settingsPending.enableExecutionSpeedLimiter = true; - _settingsPending.executionSpeed = SPEED_SCALAR_NORMAL; + _settingsPending.enableExecutionSpeedLimiter = true; + _settingsPending.executionSpeed = SPEED_SCALAR_NORMAL; - _settingsPending.enableFrameSkip = true; - _settingsPending.frameJumpTarget = 0; + _settingsPending.enableFrameSkip = true; + _settingsPending.frameJumpTarget = 0; - _settingsPending.execBehavior = ExecutionBehavior_Pause; - _settingsPending.jumpBehavior = FrameJumpBehavior_Forward; + _settingsPending.execBehavior = ExecutionBehavior_Pause; + _settingsPending.jumpBehavior = FrameJumpBehavior_Forward; _settingsApplied = _settingsPending; - _settingsApplied.filePathARM9BIOS = std::string(); - _settingsApplied.filePathARM7BIOS = std::string(); - _settingsApplied.filePathFirmware = std::string(); + _settingsApplied.filePathARM9BIOS = _settingsPending.filePathARM9BIOS; + _settingsApplied.filePathARM7BIOS = _settingsPending.filePathARM7BIOS; + _settingsApplied.filePathFirmware = _settingsPending.filePathFirmware; + _settingsApplied.filePathSlot1R4 = _settingsPending.filePathSlot1R4; + _settingsApplied.cpuEmulationEngineName = _settingsPending.cpuEmulationEngineName; + _settingsApplied.slot1DeviceName = _settingsPending.slot1DeviceName; + + _ndsFrameInfo.clear(); + _ndsFrameInfo.cpuEmulationEngineName = _settingsPending.cpuEmulationEngineName; + _ndsFrameInfo.slot1DeviceName = _settingsPending.slot1DeviceName; + + _cpuEmulationEngineNameOut = _ndsFrameInfo.cpuEmulationEngineName; + _slot1DeviceNameOut = _ndsFrameInfo.slot1DeviceName; pthread_mutex_init(&_mutexSettingsPendingOnReset, NULL); pthread_mutex_init(&_mutexSettingsPendingOnExecutionLoopStart, NULL); pthread_mutex_init(&_mutexSettingsPendingOnNDSExec, NULL); + pthread_mutex_init(&_mutexOutputPostNDSExec, NULL); } ClientExecutionControl::~ClientExecutionControl() @@ -76,6 +94,7 @@ ClientExecutionControl::~ClientExecutionControl() pthread_mutex_destroy(&this->_mutexSettingsPendingOnReset); pthread_mutex_destroy(&this->_mutexSettingsPendingOnExecutionLoopStart); pthread_mutex_destroy(&this->_mutexSettingsPendingOnNDSExec); + pthread_mutex_destroy(&this->_mutexOutputPostNDSExec); } CPUEmulationEngineID ClientExecutionControl::GetCPUEmulationEngineID() @@ -87,7 +106,16 @@ CPUEmulationEngineID ClientExecutionControl::GetCPUEmulationEngineID() return engineID; } -void ClientExecutionControl::SetCPUEmulationEngineID(CPUEmulationEngineID engineID) +const char* ClientExecutionControl::GetCPUEmulationEngineName() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_cpuEmulationEngineNameOut = this->_settingsPending.cpuEmulationEngineName; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return this->_cpuEmulationEngineNameOut.c_str(); +} + +void ClientExecutionControl::SetCPUEmulationEngineByID(CPUEmulationEngineID engineID) { #if !defined(__i386__) && !defined(__x86_64__) engineID = CPUEmulationEngine_Interpreter; @@ -96,6 +124,21 @@ void ClientExecutionControl::SetCPUEmulationEngineID(CPUEmulationEngineID engine pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); this->_settingsPending.cpuEngineID = engineID; + switch (engineID) + { + case CPUEmulationEngineID_Interpreter: + this->_settingsPending.cpuEmulationEngineName = "Interpreter"; + break; + + case CPUEmulationEngineID_DynamicRecompiler: + this->_settingsPending.cpuEmulationEngineName = "Dynamic Recompiler"; + break; + + default: + this->_settingsPending.cpuEmulationEngineName = "Unknown Engine"; + break; + } + this->_newSettingsPendingOnReset = true; pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } @@ -127,6 +170,42 @@ void ClientExecutionControl::SetJITMaxBlockSize(uint8_t blockSize) pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } +NDS_SLOT1_TYPE ClientExecutionControl::GetSlot1DeviceType() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + const NDS_SLOT1_TYPE type = this->_settingsPending.slot1DeviceType; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return type; +} + +const char* ClientExecutionControl::GetSlot1DeviceName() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_slot1DeviceNameOut = this->_settingsPending.slot1DeviceName; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return this->_slot1DeviceNameOut.c_str(); +} + +void ClientExecutionControl::SetSlot1DeviceByType(NDS_SLOT1_TYPE type) +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_settingsPending.slot1DeviceType = type; + + if ( (type < 0) || type >= (NDS_SLOT1_COUNT) ) + { + this->_settingsPending.slot1DeviceName = "Uninitialized"; + } + else + { + this->_settingsPending.slot1DeviceName = slot1_List[type]->info()->name(); + } + + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); +} + const char* ClientExecutionControl::GetARM9ImagePath() { pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); @@ -205,6 +284,32 @@ void ClientExecutionControl::SetFirmwareImagePath(const char *filePath) pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); } +const char* ClientExecutionControl::GetSlot1R4Path() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + const char *filePath = this->_settingsPending.filePathSlot1R4.c_str(); + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return filePath; +} + +void ClientExecutionControl::SetSlot1R4Path(const char *filePath) +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + + if (filePath == NULL) + { + this->_settingsPending.filePathSlot1R4.clear(); + } + else + { + this->_settingsPending.filePathSlot1R4 = std::string(filePath); + } + + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); +} + bool ClientExecutionControl::GetEnableAdvancedBusLevelTiming() { pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); @@ -558,12 +663,24 @@ 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.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; + + const bool didChangeSlot1Type = (this->_settingsApplied.slot1DeviceType != this->_settingsPending.slot1DeviceType); + if (didChangeSlot1Type) + { + this->_settingsApplied.slot1DeviceType = this->_settingsPending.slot1DeviceType; + } this->_newSettingsPendingOnReset = false; pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); @@ -597,6 +714,16 @@ void ClientExecutionControl::ApplySettingsOnReset() { strlcpy(CommonSettings.Firmware, this->_settingsApplied.filePathFirmware.c_str(), sizeof(CommonSettings.Firmware)); } + + if (this->_settingsApplied.filePathSlot1R4.length() > 0) + { + slot1_SetFatDir(this->_settingsApplied.filePathSlot1R4); + } + + if (didChangeSlot1Type) + { + slot1_Change(this->_settingsApplied.slot1DeviceType); + } } else { @@ -705,6 +832,32 @@ void ClientExecutionControl::ApplySettingsOnNDSExec() } } +void ClientExecutionControl::FetchOutputPostNDSExec() +{ + pthread_mutex_lock(&this->_mutexOutputPostNDSExec); + + this->_ndsFrameInfo.frameIndex = currFrameCounter; + this->_ndsFrameInfo.render3DFPS = GPU->GetFPSRender3D(); + this->_ndsFrameInfo.lagFrameCount = TotalLagFrames; + + if ((this->_ndsFrameInfo.frameIndex & 0xF) == 0xF) + { + NDS_GetCPULoadAverage(this->_ndsFrameInfo.cpuLoadAvgARM9, this->_ndsFrameInfo.cpuLoadAvgARM7); + } + + char *tempBuffer = (char *)calloc(25, sizeof(char)); + rtcGetTimeAsString(tempBuffer); + this->_ndsFrameInfo.rtcString = tempBuffer; + free(tempBuffer); + + pthread_mutex_unlock(&this->_mutexOutputPostNDSExec); +} + +const NDSFrameInfo& ClientExecutionControl::GetNDSFrameInfo() +{ + return this->_ndsFrameInfo; +} + double ClientExecutionControl::GetFrameTime() { return this->_frameTime; diff --git a/desmume/src/frontend/cocoa/ClientExecutionControl.h b/desmume/src/frontend/cocoa/ClientExecutionControl.h index 894a6146d..08d905df3 100644 --- a/desmume/src/frontend/cocoa/ClientExecutionControl.h +++ b/desmume/src/frontend/cocoa/ClientExecutionControl.h @@ -21,6 +21,9 @@ #include #include +#include "../../slot1.h" +#undef BOOL + #define SPEED_SCALAR_QUARTER 0.25 // Speed scalar for quarter execution speed. #define SPEED_SCALAR_HALF 0.5 // Speed scalar for half execution speed. #define SPEED_SCALAR_THREE_QUARTER 0.75 // Speed scalar for three quarters execution speed. @@ -61,9 +64,14 @@ typedef struct ClientExecutionControlSettings { CPUEmulationEngineID cpuEngineID; uint8_t JITMaxBlockSize; + NDS_SLOT1_TYPE slot1DeviceType; std::string filePathARM9BIOS; std::string filePathARM7BIOS; std::string filePathFirmware; + std::string filePathSlot1R4; + + std::string cpuEmulationEngineName; + std::string slot1DeviceName; bool enableAdvancedBusLevelTiming; bool enableRigorous3DRenderingTiming; @@ -89,12 +97,51 @@ typedef struct ClientExecutionControlSettings } ClientExecutionControlSettings; +struct NDSFrameInfo +{ + std::string cpuEmulationEngineName; + std::string slot1DeviceName; + std::string rtcString; + + uint64_t frameIndex; + uint32_t render3DFPS; + uint32_t lagFrameCount; + uint32_t cpuLoadAvgARM9; + uint32_t cpuLoadAvgARM7; + + void clear() + { + this->cpuEmulationEngineName = std::string(); + this->slot1DeviceName = std::string(); + this->rtcString = std::string(); + this->frameIndex = 0; + this->render3DFPS = 0; + this->lagFrameCount = 0; + this->cpuLoadAvgARM9 = 0; + this->cpuLoadAvgARM7 = 0; + } + + void copyFrom(const NDSFrameInfo &fromObject) + { + this->cpuEmulationEngineName = fromObject.cpuEmulationEngineName; + this->slot1DeviceName = fromObject.slot1DeviceName; + this->rtcString = fromObject.rtcString; + this->frameIndex = fromObject.frameIndex; + this->render3DFPS = fromObject.render3DFPS; + this->lagFrameCount = fromObject.lagFrameCount; + this->cpuLoadAvgARM9 = fromObject.cpuLoadAvgARM9; + this->cpuLoadAvgARM7 = fromObject.cpuLoadAvgARM7; + } +}; + class ClientExecutionControl { private: ClientExecutionControlSettings _settingsPending; ClientExecutionControlSettings _settingsApplied; + NDSFrameInfo _ndsFrameInfo; + bool _newSettingsPendingOnReset; bool _newSettingsPendingOnExecutionLoopStart; bool _newSettingsPendingOnNDSExec; @@ -105,20 +152,30 @@ private: uint8_t _framesToSkip; ExecutionBehavior _prevExecBehavior; + std::string _cpuEmulationEngineNameOut; + std::string _slot1DeviceNameOut; + std::string _rtcStringOut; + pthread_mutex_t _mutexSettingsPendingOnReset; pthread_mutex_t _mutexSettingsPendingOnExecutionLoopStart; pthread_mutex_t _mutexSettingsPendingOnNDSExec; + pthread_mutex_t _mutexOutputPostNDSExec; public: ClientExecutionControl(); ~ClientExecutionControl(); CPUEmulationEngineID GetCPUEmulationEngineID(); - void SetCPUEmulationEngineID(CPUEmulationEngineID engineID); + const char* GetCPUEmulationEngineName(); + void SetCPUEmulationEngineByID(CPUEmulationEngineID engineID); uint8_t GetJITMaxBlockSize(); void SetJITMaxBlockSize(uint8_t blockSize); + NDS_SLOT1_TYPE GetSlot1DeviceType(); + const char* GetSlot1DeviceName(); + void SetSlot1DeviceByType(NDS_SLOT1_TYPE type); + const char* GetARM9ImagePath(); void SetARM9ImagePath(const char *filePath); @@ -128,6 +185,9 @@ public: const char* GetFirmwareImagePath(); void SetFirmwareImagePath(const char *filePath); + const char* GetSlot1R4Path(); + void SetSlot1R4Path(const char *filePath); + bool GetEnableAdvancedBusLevelTiming(); void SetEnableAdvancedBusLevelTiming(bool enable); @@ -191,6 +251,9 @@ public: void ApplySettingsOnExecutionLoopStart(); void ApplySettingsOnNDSExec(); + void FetchOutputPostNDSExec(); + const NDSFrameInfo& GetNDSFrameInfo(); + double GetFrameTime(); uint8_t CalculateFrameSkip(double startAbsoluteTime, double frameAbsoluteTime); diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index b9438a78b..291e60c55 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -37,7 +37,6 @@ class OGLVideoOutput; -struct NDSFrameInfo; enum ShaderSupportTier { diff --git a/desmume/src/frontend/cocoa/cocoa_core.h b/desmume/src/frontend/cocoa/cocoa_core.h index d7fae3e61..d7f20007a 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.h +++ b/desmume/src/frontend/cocoa/cocoa_core.h @@ -53,8 +53,6 @@ typedef struct pthread_t coreThread; CoreThreadParam threadParam; - std::string _slot1R4Path; - NSTimer *_fpsTimer; BOOL _isTimerAtSecond; @@ -67,13 +65,10 @@ typedef struct volatile gdbstub_handle_t gdbStubHandleARM9; volatile gdbstub_handle_t gdbStubHandleARM7; - NSInteger slot1DeviceType; NSString *slot1StatusText; NSString *frameStatus; NSString *executionSpeedStatus; - NSURL *slot1R4URL; - OSSpinLock spinlockCdsController; OSSpinLock spinlockMasterExecute; } @@ -120,7 +115,7 @@ typedef struct @property (copy) NSURL *arm9ImageURL; @property (copy) NSURL *arm7ImageURL; @property (copy) NSURL *firmwareImageURL; -@property (retain) NSURL *slot1R4URL; +@property (copy) NSURL *slot1R4URL; @property (readonly) pthread_rwlock_t *rwlockCoreExecute; @@ -129,7 +124,7 @@ typedef struct - (void) changeRomSaveType:(NSInteger)saveTypeID; - (void) updateExecutionSpeedStatus; -- (BOOL) applySlot1Device; +- (void) updateSlot1DeviceStatus; - (void) restoreCoreState; - (void) reset; diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index e1c805052..9ab74db30 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -108,7 +108,7 @@ volatile bool execute = true; @dynamic emuFlagEmulateEnsata; @dynamic cpuEmulationEngine; @dynamic maxJITBlockSize; -@synthesize slot1DeviceType; +@dynamic slot1DeviceType; @synthesize slot1StatusText; @synthesize frameStatus; @synthesize executionSpeedStatus; @@ -116,7 +116,7 @@ volatile bool execute = true; @dynamic arm9ImageURL; @dynamic arm7ImageURL; @dynamic firmwareImageURL; -@synthesize slot1R4URL; +@dynamic slot1R4URL; @dynamic rwlockCoreExecute; @@ -155,15 +155,11 @@ volatile bool execute = true; cdsGPU = [[[[CocoaDSGPU alloc] init] autorelease] retain]; cdsOutputList = [[[[NSMutableArray alloc] initWithCapacity:32] autorelease] retain]; - slot1DeviceType = NDS_SLOT1_RETAIL_AUTO; slot1StatusText = NSSTRING_STATUS_EMULATION_NOT_RUNNING; spinlockMasterExecute = OS_SPINLOCK_INIT; spinlockCdsController = OS_SPINLOCK_INIT; - slot1R4URL = nil; - _slot1R4Path = ""; - threadParam.cdsCore = self; pthread_mutex_init(&threadParam.mutexOutputList, NULL); @@ -531,7 +527,7 @@ volatile bool execute = true; - (void) setCpuEmulationEngine:(NSInteger)engineID { - execControl->SetCPUEmulationEngineID((CPUEmulationEngineID)engineID); + execControl->SetCPUEmulationEngineByID((CPUEmulationEngineID)engineID); } - (NSInteger) cpuEmulationEngine @@ -549,6 +545,16 @@ volatile bool execute = true; return (NSInteger)execControl->GetJITMaxBlockSize(); } +- (void) setSlot1DeviceType:(NSInteger)theType +{ + execControl->SetSlot1DeviceByType((NDS_SLOT1_TYPE)theType); +} + +- (NSInteger) slot1DeviceType +{ + return (NSInteger)execControl->GetSlot1DeviceType(); +} + - (void) setCoreState:(NSInteger)coreState { pthread_mutex_lock(&threadParam.mutexThreadExecute); @@ -680,6 +686,18 @@ volatile bool execute = true; return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]]; } +- (void) setSlot1R4URL:(NSURL *)fileURL +{ + const char *filePath = (fileURL != NULL) ? [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding] : NULL; + execControl->SetSlot1R4Path(filePath); +} + +- (NSURL *) slot1R4URL +{ + const char *filePath = execControl->GetSlot1R4Path(); + return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]]; +} + - (pthread_rwlock_t *) rwlockCoreExecute { return &threadParam.rwlockCoreExecute; @@ -719,19 +737,9 @@ volatile bool execute = true; } } -- (BOOL) applySlot1Device +- (void) updateSlot1DeviceStatus { - const NSInteger deviceTypeID = [self slot1DeviceType]; - NSString *r4Path = [[self slot1R4URL] path]; - - pthread_mutex_lock(&threadParam.mutexThreadExecute); - - _slot1R4Path = (r4Path != nil) ? std::string([r4Path cStringUsingEncoding:NSUTF8StringEncoding]) : ""; - slot1_SetFatDir(_slot1R4Path); - - BOOL result = slot1_Change((NDS_SLOT1_TYPE)deviceTypeID); - - pthread_mutex_unlock(&threadParam.mutexThreadExecute); + const NDS_SLOT1_TYPE deviceTypeID = execControl->GetSlot1DeviceType(); switch (deviceTypeID) { @@ -759,8 +767,6 @@ volatile bool execute = true; [self setSlot1StatusText:NSSTRING_STATUS_SLOT1_UNKNOWN_STATE]; break; } - - return result; } - (void) restoreCoreState @@ -771,13 +777,13 @@ volatile bool execute = true; - (void) reset { [self setCoreState:ExecutionBehavior_Pause]; - [self applySlot1Device]; pthread_mutex_lock(&threadParam.mutexThreadExecute); execControl->ApplySettingsOnReset(); NDS_Reset(); pthread_mutex_unlock(&threadParam.mutexThreadExecute); + [self updateSlot1DeviceStatus]; [self restoreCoreState]; [self setMasterExecute:YES]; [[self cdsController] reset]; @@ -786,13 +792,6 @@ volatile bool execute = true; - (void) getTimedEmulatorStatistics:(NSTimer *)timer { - uint32_t loadAvgARM9; - uint32_t loadAvgARM7; - - pthread_rwlock_rdlock(&threadParam.rwlockCoreExecute); - NDS_GetCPULoadAverage(loadAvgARM9, loadAvgARM7); - pthread_rwlock_unlock(&threadParam.rwlockCoreExecute); - // The timer should fire every 0.5 seconds, so only take the frame // count every other instance the timer fires. _isTimerAtSecond = !_isTimerAtSecond; @@ -805,8 +804,6 @@ volatile bool execute = true; { [(CocoaDSDisplay *)cdsOutput takeFrameCount]; } - - [(CocoaDSDisplay *)cdsOutput setCPULoadAvgARM9:loadAvgARM9 ARM7:loadAvgARM7]; } } } @@ -868,43 +865,12 @@ volatile bool execute = true; - (NSString *) cpuEmulationEngineString { - NSString *theString = @"Uninitialized"; - - switch ([self cpuEmulationEngine]) - { - case CPUEmulationEngineID_Interpreter: - theString = @"Interpreter"; - break; - - case CPUEmulationEngineID_DynamicRecompiler: - theString = @"Dynamic Recompiler"; - break; - - default: - break; - } - - return theString; + return [NSString stringWithCString:execControl->GetCPUEmulationEngineName() encoding:NSUTF8StringEncoding]; } - (NSString *) slot1DeviceTypeString { - NSString *theString = @"Uninitialized"; - - pthread_mutex_lock(&threadParam.mutexThreadExecute); - - if(slot1_device == NULL) - { - pthread_mutex_unlock(&threadParam.mutexThreadExecute); - return theString; - } - - const Slot1Info *info = slot1_device->info(); - theString = [NSString stringWithCString:info->name() encoding:NSUTF8StringEncoding]; - - pthread_mutex_unlock(&threadParam.mutexThreadExecute); - - return theString; + return [NSString stringWithCString:execControl->GetSlot1DeviceName() encoding:NSUTF8StringEncoding]; } - (NSString *) slot2DeviceTypeString @@ -913,7 +879,7 @@ volatile bool execute = true; pthread_mutex_lock(&threadParam.mutexThreadExecute); - if(slot2_device == NULL) + if (slot2_device == NULL) { pthread_mutex_unlock(&threadParam.mutexThreadExecute); return theString; @@ -978,7 +944,8 @@ static void* RunCoreThread(void *arg) CocoaDSCore *cdsCore = (CocoaDSCore *)param->cdsCore; ClientExecutionControl *execControl = [cdsCore execControl]; NSMutableArray *cdsOutputList = [cdsCore cdsOutputList]; - uint64_t frameNum = 0; + const NDSFrameInfo &ndsFrameInfo = execControl->GetNDSFrameInfo(); + double startTime = 0; double frameTime = 0; // The amount of time that is expected for the frame to run. @@ -1025,7 +992,7 @@ static void* RunCoreThread(void *arg) // Execute the frame and increment the frame counter. pthread_rwlock_wrlock(¶m->rwlockCoreExecute); NDS_exec(); - frameNum = (uint64_t)currFrameCounter; + execControl->FetchOutputPostNDSExec(); pthread_rwlock_unlock(¶m->rwlockCoreExecute); // Check if an internal execution error occurred that halted the emulation. @@ -1054,6 +1021,11 @@ static void* RunCoreThread(void *arg) { for (CocoaDSOutput *cdsOutput in cdsOutputList) { + if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + [(CocoaDSDisplay *)cdsOutput setNDSFrameInfo:ndsFrameInfo]; + } + if ( ![cdsOutput isKindOfClass:[CocoaDSDisplay class]] || (framesToSkip == 0) ) { [cdsOutput doCoreEmuFrame]; @@ -1115,11 +1087,11 @@ static void* RunCoreThread(void *arg) } else if (behavior == ExecutionBehavior_FrameJump) { - if (frameNum == (frameJumpTarget - 1)) + if (ndsFrameInfo.frameIndex == (frameJumpTarget - 1)) { execControl->ResetFramesToSkip(); } - else if (frameNum >= frameJumpTarget) + else if (ndsFrameInfo.frameIndex >= frameJumpTarget) { [cdsCore restoreCoreState]; } diff --git a/desmume/src/frontend/cocoa/cocoa_output.h b/desmume/src/frontend/cocoa/cocoa_output.h index b528b6536..4a65b4d7a 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.h +++ b/desmume/src/frontend/cocoa/cocoa_output.h @@ -22,13 +22,12 @@ #import "cocoa_util.h" #include "ClientDisplayView.h" +#include "ClientExecutionControl.h" #undef BOOL @class NSImage; @class NSBitmapImageRep; -struct NDSFrameInfo; - @interface CocoaDSOutput : CocoaDSThread { NSMutableDictionary *property; @@ -105,11 +104,10 @@ struct NDSFrameInfo; uint32_t _currentReceivedFrameIndex; uint32_t _receivedFrameCount; - uint32_t _cpuLoadAvgARM9; - uint32_t _cpuLoadAvgARM7; + NDSFrameInfo _ndsFrameInfo; OSSpinLock spinlockReceivedFrameIndex; - OSSpinLock spinlockCPULoadAverage; + OSSpinLock spinlockNDSFrameInfo; OSSpinLock spinlockViewProperties; } @@ -124,7 +122,7 @@ struct NDSFrameInfo; - (void) handleCopyToPasteboard; - (void) takeFrameCount; -- (void) setCPULoadAvgARM9:(uint32_t)loadAvgARM9 ARM7:(uint32_t)loadAvgARM7; +- (void) setNDSFrameInfo:(const NDSFrameInfo &)ndsFrameInfo; - (NSImage *) image; - (NSBitmapImageRep *) bitmapImageRep; diff --git a/desmume/src/frontend/cocoa/cocoa_output.mm b/desmume/src/frontend/cocoa/cocoa_output.mm index ee21b2928..648affa24 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.mm +++ b/desmume/src/frontend/cocoa/cocoa_output.mm @@ -513,17 +513,15 @@ } spinlockReceivedFrameIndex = OS_SPINLOCK_INIT; - spinlockCPULoadAverage = OS_SPINLOCK_INIT; + spinlockNDSFrameInfo = OS_SPINLOCK_INIT; spinlockViewProperties = OS_SPINLOCK_INIT; _cdv = NULL; + _ndsFrameInfo.clear(); _receivedFrameIndex = 0; _currentReceivedFrameIndex = 0; _receivedFrameCount = 0; - - _cpuLoadAvgARM9 = 0; - _cpuLoadAvgARM7 = 0; return self; } @@ -645,12 +643,11 @@ OSSpinLockUnlock(&spinlockReceivedFrameIndex); } -- (void) setCPULoadAvgARM9:(uint32_t)loadAvgARM9 ARM7:(uint32_t)loadAvgARM7 +- (void) setNDSFrameInfo:(const NDSFrameInfo &)ndsFrameInfo { - OSSpinLockLock(&spinlockCPULoadAverage); - _cpuLoadAvgARM9 = loadAvgARM9; - _cpuLoadAvgARM7 = loadAvgARM7; - OSSpinLockUnlock(&spinlockCPULoadAverage); + OSSpinLockLock(&spinlockNDSFrameInfo); + _ndsFrameInfo.copyFrom(ndsFrameInfo); + OSSpinLockUnlock(&spinlockNDSFrameInfo); } - (NSImage *) image @@ -1038,23 +1035,16 @@ { [super handleEmuFrameProcessed]; - NDSFrameInfo frameInfo; - frameInfo.render3DFPS = GPU->GetFPSRender3D(); - frameInfo.frameIndex = currFrameCounter; - frameInfo.lagFrameCount = TotalLagFrames; - OSSpinLockLock(&spinlockReceivedFrameIndex); - frameInfo.videoFPS = _receivedFrameCount; + ClientFrameInfo clientFrameInfo; + clientFrameInfo.videoFPS = _receivedFrameCount; OSSpinLockUnlock(&spinlockReceivedFrameIndex); - OSSpinLockLock(&spinlockCPULoadAverage); - frameInfo.cpuLoadAvgARM9 = _cpuLoadAvgARM9; - frameInfo.cpuLoadAvgARM7 = _cpuLoadAvgARM7; - OSSpinLockUnlock(&spinlockCPULoadAverage); + OSSpinLockLock(&spinlockNDSFrameInfo); + _cdv->SetHUDInfo(clientFrameInfo, _ndsFrameInfo); + OSSpinLockUnlock(&spinlockNDSFrameInfo); - rtcGetTimeAsString(frameInfo.rtcString); - - _cdv->HandleEmulatorFrameEndEvent(frameInfo); + _cdv->HandleEmulatorFrameEndEvent(); } - (void) handleReceiveGPUFrame diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index 963c5ab59..202565085 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -1683,7 +1683,7 @@ CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; [cdsCore execControl]->ApplySettingsOnReset(); - [cdsCore applySlot1Device]; + [cdsCore updateSlot1DeviceStatus]; [self writeDefaultsSlot1Settings:nil]; CocoaDSRom *newRom = [[CocoaDSRom alloc] init]; diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index 48700be81..30d2be2c2 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -152,17 +152,22 @@ void slot1_Reset() bool slot1_Change(NDS_SLOT1_TYPE changeToType) { - if((changeToType == slot1_device_type) || (changeToType == slot1_GetSelectedType())) - return FALSE; //nothing to do - if (changeToType > NDS_SLOT1_COUNT || changeToType < 0) return FALSE; - if(slot1_device != NULL) + if ( (changeToType == slot1_device_type) || (changeToType == slot1_GetSelectedType()) ) + return false; //nothing to do + + if ( (changeToType >= NDS_SLOT1_COUNT) || (changeToType < 0) ) + return false; + + if (slot1_device != NULL) slot1_device->disconnect(); + slot1_device_type = changeToType; slot1_device = slot1_List[slot1_device_type]; printf("Slot 1: %s\n", slot1_device->info()->name()); printf("sending eject signal to SLOT-1\n"); NDS_TriggerCardEjectIRQ(); slot1_device->connect(); + return true; }