diff --git a/Core/Console.cpp b/Core/Console.cpp index 054e8a45..4e1ee8ac 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -77,6 +77,11 @@ void Console::Init() void Console::Release(bool forShutdown) { + if(_slave) { + _slave->Release(true); + _slave.reset(); + } + if(forShutdown) { _videoDecoder->StopThread(); _videoRenderer->StopThread(); @@ -105,11 +110,6 @@ void Console::Release(bool forShutdown) _systemActionManager.reset(); - if(_slave) { - _slave->Release(true); - _slave.reset(); - } - _master.reset(); _cpu.reset(); _ppu.reset(); @@ -625,6 +625,9 @@ void Console::RunSingleFrame() while(_ppu->GetFrameCount() == lastFrameNumber) { _cpu->Exec(); + if(_slave) { + RunSlaveCpu(); + } } EmulationSettings::DisableOverclocking(_disableOcNextFrame || NsfMapper::GetInstance()); @@ -634,6 +637,20 @@ void Console::RunSingleFrame() _apu->EndFrame(); } +void Console::RunSlaveCpu() +{ + int32_t cycleGap; + while(true) { + //Run the slave until it catches up to the master CPU (and take into account the CPU count overflow that occurs every ~20mins) + cycleGap = _cpu->GetCycleCount() - _slave->_cpu->GetCycleCount(); + if(cycleGap > 5 || cycleGap < -10000 || _ppu->GetFrameCount() > _slave->_ppu->GetFrameCount()) { + _slave->_cpu->Exec(); + } else { + break; + } + } +} + void Console::Run() { Timer clockTimer; @@ -643,8 +660,6 @@ void Console::Run() int timeLagDataIndex = 0; double lastFrameMin = 9999; double lastFrameMax = 0; - int32_t cycleGap = 0; - uint32_t currentFrameNumber = 0; uint32_t lastFrameNumber = -1; @@ -668,21 +683,11 @@ void Console::Run() while(true) { _cpu->Exec(); - currentFrameNumber = _ppu->GetFrameCount(); - if(_slave) { - while(true) { - //Run the slave until it catches up to the master CPU (and take into account the CPU count overflow that occurs every ~20mins) - cycleGap = _cpu->GetCycleCount() - _slave->_cpu->GetCycleCount(); - if(cycleGap > 5 || cycleGap < -10000 || currentFrameNumber > _slave->_ppu->GetFrameCount()) { - _slave->_cpu->Exec(); - } else { - break; - } - } + RunSlaveCpu(); } - if(currentFrameNumber != lastFrameNumber) { + if(_ppu->GetFrameCount() != lastFrameNumber) { _soundMixer->ProcessEndOfFrame(); if(_slave) { _slave->_soundMixer->ProcessEndOfFrame(); diff --git a/Core/Console.h b/Core/Console.h index 53770773..aebe2a8c 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -133,6 +133,7 @@ public: int32_t GetStopCode(); void RunSingleFrame(); + void RunSlaveCpu(); bool UpdateHdPackMode(); shared_ptr GetSystemActionManager(); diff --git a/Libretro/LibretroKeyManager.h b/Libretro/LibretroKeyManager.h index 10036cf9..2b2c0a98 100644 --- a/Libretro/LibretroKeyManager.h +++ b/Libretro/LibretroKeyManager.h @@ -4,10 +4,12 @@ #include "../Core/KeyManager.h" #include "../Core/FdsSystemActionManager.h" #include "../Core/VsSystemActionManager.h" +#include "../Core/Console.h" class LibretroKeyManager : public IKeyManager { private: + shared_ptr _console; retro_input_state_t _getInputState = nullptr; retro_input_poll_t _pollInput = nullptr; bool _mouseButtons[3] = { false, false, false }; @@ -28,8 +30,9 @@ private: } public: - LibretroKeyManager() + LibretroKeyManager(shared_ptr console) { + _console = console; KeyManager::RegisterKeyManager(this); } @@ -72,7 +75,7 @@ public: _mouseButtons[(int)MouseButton::RightButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) != 0; _mouseButtons[(int)MouseButton::MiddleButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE) != 0; - shared_ptr fdsSam = Console::GetInstance()->GetSystemActionManager(); + shared_ptr fdsSam = _console->GetSystemActionManager(); if(fdsSam) { if(ProcessAction(RETRO_DEVICE_ID_JOYPAD_L)) { fdsSam->InsertNextDisk(); @@ -83,7 +86,7 @@ public: } } - shared_ptr vsSam = Console::GetInstance()->GetSystemActionManager(); + shared_ptr vsSam = _console->GetSystemActionManager(); if(vsSam) { if(ProcessAction(RETRO_DEVICE_ID_JOYPAD_L2)) { vsSam->InsertCoin(0); diff --git a/Libretro/LibretroRenderer.h b/Libretro/LibretroRenderer.h index bc0af8f0..4ebf9c32 100644 --- a/Libretro/LibretroRenderer.h +++ b/Libretro/LibretroRenderer.h @@ -10,6 +10,7 @@ class LibretroRenderer : public IRenderingDevice { private: + shared_ptr _console; retro_video_refresh_t _sendFrame = nullptr; retro_environment_t _retroEnv = nullptr; bool _skipMode = false; @@ -17,14 +18,15 @@ private: int32_t _previousWidth = -1; public: - LibretroRenderer() + LibretroRenderer(shared_ptr console) { - VideoRenderer::GetInstance()->RegisterRenderingDevice(this); + _console = console; + _console->GetVideoRenderer()->RegisterRenderingDevice(this); } ~LibretroRenderer() { - VideoRenderer::GetInstance()->UnregisterRenderingDevice(this); + _console->GetVideoRenderer()->UnregisterRenderingDevice(this); } // Inherited via IRenderingDevice @@ -50,10 +52,10 @@ public: void GetSystemAudioVideoInfo(retro_system_av_info &info, int32_t maxWidth = 0, int32_t maxHeight = 0) { - info.timing.fps = Console::GetModel() == NesModel::NTSC ? 60.098811862348404716732985230828 : 50.006977968268290848936010226333; + info.timing.fps = _console->GetModel() == NesModel::NTSC ? 60.098811862348404716732985230828 : 50.006977968268290848936010226333; info.timing.sample_rate = 48000; - float ratio = (float)EmulationSettings::GetAspectRatio(); + float ratio = (float)EmulationSettings::GetAspectRatio(_console); if(ratio == 0.0f) { ratio = 1.0f; } diff --git a/Libretro/LibretroSoundManager.h b/Libretro/LibretroSoundManager.h index 473aec54..157832c9 100644 --- a/Libretro/LibretroSoundManager.h +++ b/Libretro/LibretroSoundManager.h @@ -9,16 +9,18 @@ class LibretroSoundManager : public IAudioDevice private: retro_audio_sample_batch_t _sendAudioBuffer = nullptr; bool _skipMode = false; + shared_ptr _console; public: - LibretroSoundManager() + LibretroSoundManager(shared_ptr console) { - SoundMixer::RegisterAudioDevice(this); + _console = console; + _console->GetSoundMixer()->RegisterAudioDevice(this); } ~LibretroSoundManager() { - SoundMixer::RegisterAudioDevice(nullptr); + _console->GetSoundMixer()->RegisterAudioDevice(nullptr); } // Inherited via IAudioDevice diff --git a/Libretro/Makefile.common b/Libretro/Makefile.common index 220015af..b4a974b1 100644 --- a/Libretro/Makefile.common +++ b/Libretro/Makefile.common @@ -21,12 +21,12 @@ SOURCES_C := $(SEVENZIP_DIR)/7zAlloc.c \ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/APU.cpp \ - $(CORE_DIR)/ApuLengthCounter.cpp \ $(CORE_DIR)/Assembler.cpp \ $(CORE_DIR)/AutomaticRomTest.cpp \ $(CORE_DIR)/AutoSaveManager.cpp \ $(CORE_DIR)/AviRecorder.cpp \ $(CORE_DIR)/BaseControlDevice.cpp \ + $(CORE_DIR)/BaseExpansionAudio.cpp \ $(CORE_DIR)/BaseMapper.cpp \ $(CORE_DIR)/BaseRenderer.cpp \ $(CORE_DIR)/BaseVideoFilter.cpp \ @@ -44,7 +44,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/Debugger.cpp \ $(CORE_DIR)/DebugHud.cpp \ $(CORE_DIR)/DefaultVideoFilter.cpp \ - $(CORE_DIR)/RawVideoFilter.cpp \ + $(CORE_DIR)/RawVideoFilter.cpp \ $(CORE_DIR)/DeltaModulationChannel.cpp \ $(CORE_DIR)/Disassembler.cpp \ $(CORE_DIR)/DisassemblyInfo.cpp \ @@ -52,6 +52,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/ExpressionEvaluator.cpp \ $(CORE_DIR)/FceuxMovie.cpp \ $(CORE_DIR)/FDS.cpp \ + $(CORE_DIR)/FdsLoader.cpp \ $(CORE_DIR)/GameClient.cpp \ $(CORE_DIR)/GameClientConnection.cpp \ $(CORE_DIR)/GameConnection.cpp \ @@ -62,6 +63,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/HdNesPack.cpp \ $(CORE_DIR)/HdPackBuilder.cpp \ $(CORE_DIR)/HdPackLoader.cpp \ + $(CORE_DIR)/HdPpu.cpp \ $(CORE_DIR)/HdVideoFilter.cpp \ $(CORE_DIR)/iNesLoader.cpp \ $(CORE_DIR)/KeyManager.cpp \ @@ -74,11 +76,13 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/MessageManager.cpp \ $(CORE_DIR)/MovieManager.cpp \ $(CORE_DIR)/MovieRecorder.cpp \ + $(CORE_DIR)/NotificationManager.cpp \ + $(CORE_DIR)/NsfLoader.cpp \ $(CORE_DIR)/NsfMapper.cpp \ + $(CORE_DIR)/NsfPpu.cpp \ $(CORE_DIR)/NtscFilter.cpp \ $(CORE_DIR)/OggMixer.cpp \ $(CORE_DIR)/OggReader.cpp \ - $(CORE_DIR)/OpenBusHandler.cpp \ $(CORE_DIR)/PPU.cpp \ $(CORE_DIR)/Profiler.cpp \ $(CORE_DIR)/RecordedRomTest.cpp \ diff --git a/Libretro/libretro.cpp b/Libretro/libretro.cpp index 35e1fde7..2798022c 100644 --- a/Libretro/libretro.cpp +++ b/Libretro/libretro.cpp @@ -14,6 +14,7 @@ #include "../Core/CheatManager.h" #include "../Core/HdData.h" #include "../Core/DebuggerTypes.h" +#include "../Core/GameDatabase.h" #include "../Utilities/FolderUtilities.h" #include "../Utilities/HexUtilities.h" @@ -50,6 +51,7 @@ static vector gameDb = { #include "MesenDB.inc" }; +static std::shared_ptr _console; static std::unique_ptr _renderer; static std::unique_ptr _soundManager; static std::unique_ptr _keyManager; @@ -110,9 +112,12 @@ extern "C" { GameDatabase::LoadGameDb(gameDb); - _renderer.reset(new LibretroRenderer()); - _soundManager.reset(new LibretroSoundManager()); - _keyManager.reset(new LibretroKeyManager()); + _console.reset(new Console()); + _console->Init(); + + _renderer.reset(new LibretroRenderer(_console)); + _soundManager.reset(new LibretroSoundManager(_console)); + _keyManager.reset(new LibretroKeyManager(_console)); _messageManager.reset(new LibretroMessageManager(logCallback, retroEnv)); EmulationSettings::SetFlags(EmulationFlags::FdsAutoLoadDisk); @@ -124,14 +129,14 @@ extern "C" { RETRO_API void retro_deinit() { - Console::GetInstance()->SaveBatteries(); - VideoDecoder::Release(); - VideoRenderer::Release(); - Console::Release(); _renderer.reset(); _soundManager.reset(); _keyManager.reset(); _messageManager.reset(); + + _console->SaveBatteries(); + _console->Release(true); + _console.reset(); } RETRO_API void retro_set_environment(retro_environment_t env) @@ -252,7 +257,7 @@ extern "C" { RETRO_API void retro_reset() { - Console::Reset(true); + _console->Reset(true); } void set_flag(const char* flagName, uint64_t flagValue) @@ -615,7 +620,7 @@ extern "C" { _soundManager->SetSkipMode(true); for(int i = 0; i < 9; i++) { //Attempt to speed up to 1000% speed - Console::GetInstance()->RunSingleFrame(); + _console->RunSingleFrame(); } _renderer->SetSkipMode(false); _soundManager->SetSkipMode(false); @@ -628,12 +633,12 @@ extern "C" { bool hdPacksEnabled = EmulationSettings::CheckFlag(EmulationFlags::UseHdPacks); if(hdPacksEnabled != _hdPacksEnabled) { //Try to load/unload HD pack when the flag is toggled - Console::GetInstance()->UpdateHdPackMode(); + _console->UpdateHdPackMode(); _hdPacksEnabled = hdPacksEnabled; } } - Console::GetInstance()->RunSingleFrame(); + _console->RunSingleFrame(); if(updated) { //Update geometry after running the frame, in case the console's region changed (affects "auto" aspect ratio) @@ -651,7 +656,7 @@ extern "C" { RETRO_API bool retro_serialize(void *data, size_t size) { std::stringstream ss; - Console::SaveState(ss); + _console->SaveState(ss); string saveStateData = ss.str(); memset(data, 0, size); @@ -662,13 +667,13 @@ extern "C" { RETRO_API bool retro_unserialize(const void *data, size_t size) { - Console::LoadState((uint8_t*)data, (uint32_t)size); + _console->LoadState((uint8_t*)data, (uint32_t)size); return true; } RETRO_API void retro_cheat_reset() { - CheatManager::GetInstance()->ClearCodes(); + _console->GetCheatManager()->ClearCodes(); } RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *codeStr) @@ -681,12 +686,12 @@ extern "C" { if(code.size() == 7 && code[4] == ':') { string address = code.substr(0, 4); string value = code.substr(5, 2); - CheatManager::GetInstance()->AddCustomCode(HexUtilities::FromHex(address), HexUtilities::FromHex(value)); + _console->GetCheatManager()->AddCustomCode(HexUtilities::FromHex(address), HexUtilities::FromHex(value)); } else if(code.size() == 10 && code[4] == '?' && code[7] == ':') { string address = code.substr(0, 4); string comparison = code.substr(5, 2); string value = code.substr(8, 2); - CheatManager::GetInstance()->AddCustomCode(HexUtilities::FromHex(address), HexUtilities::FromHex(value), HexUtilities::FromHex(comparison)); + _console->GetCheatManager()->AddCustomCode(HexUtilities::FromHex(address), HexUtilities::FromHex(value), HexUtilities::FromHex(comparison)); } else if(code.size() == 6 || code.size() == 8) { //This is either a GG or PAR code bool isValidGgCode = true; @@ -701,9 +706,9 @@ extern "C" { } if(isValidGgCode) { - CheatManager::GetInstance()->AddGameGenieCode(code); + _console->GetCheatManager()->AddGameGenieCode(code); } else if(isValidParCode) { - CheatManager::GetInstance()->AddProActionRockyCode(HexUtilities::FromHex(code)); + _console->GetCheatManager()->AddProActionRockyCode(HexUtilities::FromHex(code)); } } @@ -830,7 +835,7 @@ extern "C" { void update_core_controllers() { //Setup all "auto" ports - GameDatabase::InitializeInputDevices(Console::GetMapperInfo().Hash.PrgChrCrc32Hash); + GameDatabase::InitializeInputDevices(_console->GetMapperInfo().Hash.PrgChrCrc32Hash); //TODO: Four Score @@ -895,14 +900,14 @@ extern "C" { uint32_t i = 0; uint32_t size = 0; int32_t startAddr = 0; - uint8_t* internalRam = Console::GetInstance()->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); + uint8_t* internalRam = _console->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); _descriptors[i].ptr = internalRam; _descriptors[i].start = startAddr; _descriptors[i].len = size; _descriptors[i].select = 0; i++; - uint8_t* saveRam = Console::GetInstance()->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); + uint8_t* saveRam = _console->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); if(size > 0 && startAddr > 0) { _descriptors[i].ptr = saveRam; _descriptors[i].start = startAddr; @@ -911,7 +916,7 @@ extern "C" { i++; } - uint8_t* workRam = Console::GetInstance()->GetRamBuffer(DebugMemoryType::WorkRam, size, startAddr); + uint8_t* workRam = _console->GetRamBuffer(DebugMemoryType::WorkRam, size, startAddr); if(size > 0 && startAddr > 0) { _descriptors[i].ptr = workRam; _descriptors[i].start = startAddr; @@ -967,7 +972,7 @@ extern "C" { EmulationSettings::SetControllerType(1, ControllerType::StandardController); EmulationSettings::SetControllerType(2, ControllerType::None); EmulationSettings::SetControllerType(3, ControllerType::None); - bool result = Console::LoadROM(string(game->path)); + bool result = _console->Initialize(game->path); if(result) { update_core_controllers(); @@ -977,7 +982,7 @@ extern "C" { //Retroarch doesn't like this for netplay or rewinding - it requires the states to always be the exact same size //So we need to send a large enough size to Retroarch to ensure Mesen's state will always fit within that buffer. std::stringstream ss; - Console::SaveState(ss); + _console->SaveState(ss); //Round up to the next 1kb multiple _saveStateSize = ((ss.str().size() * 2) + 0x400) & ~0x3FF; @@ -994,12 +999,12 @@ extern "C" { RETRO_API void retro_unload_game() { - Console::GetInstance()->Stop(); + _console->Stop(); } RETRO_API unsigned retro_get_region() { - NesModel model = Console::GetModel(); + NesModel model = _console->GetModel(); return model == NesModel::NTSC ? RETRO_REGION_NTSC : RETRO_REGION_PAL; } @@ -1026,8 +1031,8 @@ extern "C" { default: hscale = 1; break; } - HdPackData* hdData = Console::GetHdData(); - if(hdData != nullptr) { + shared_ptr hdData = _console->GetHdData(); + if(hdData) { hscale = hdData->Scale; vscale = hdData->Scale; } @@ -1044,8 +1049,8 @@ extern "C" { uint32_t size; int32_t startAddr; switch(id) { - case RETRO_MEMORY_SAVE_RAM: return Console::GetInstance()->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); - case RETRO_MEMORY_SYSTEM_RAM: return Console::GetInstance()->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); + case RETRO_MEMORY_SAVE_RAM: return _console->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); + case RETRO_MEMORY_SYSTEM_RAM: return _console->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); } return nullptr; } @@ -1055,8 +1060,8 @@ extern "C" { uint32_t size = 0; int32_t startAddr; switch(id) { - case RETRO_MEMORY_SAVE_RAM: Console::GetInstance()->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); break; - case RETRO_MEMORY_SYSTEM_RAM: Console::GetInstance()->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); break; + case RETRO_MEMORY_SAVE_RAM: _console->GetRamBuffer(DebugMemoryType::SaveRam, size, startAddr); break; + case RETRO_MEMORY_SYSTEM_RAM: _console->GetRamBuffer(DebugMemoryType::InternalRam, size, startAddr); break; } return size; }