#include "stdafx.h" #include "Console.h" #include "Cpu.h" #include "Ppu.h" #include "Spc.h" #include "InternalRegisters.h" #include "ControlManager.h" #include "MemoryManager.h" #include "DmaController.h" #include "Debugger.h" #include "NotificationManager.h" #include "SoundMixer.h" #include "VideoDecoder.h" #include "VideoRenderer.h" #include "DebugHud.h" #include "FrameLimiter.h" #include "MessageManager.h" #include "KeyManager.h" #include "../Utilities/Timer.h" #include "../Utilities/VirtualFile.h" #include "../Utilities/PlatformUtilities.h" #include "../Utilities/FolderUtilities.h" void Console::Initialize() { _notificationManager.reset(new NotificationManager()); _videoDecoder.reset(new VideoDecoder(shared_from_this())); _videoRenderer.reset(new VideoRenderer(shared_from_this())); _soundMixer.reset(new SoundMixer()); _debugHud.reset(new DebugHud()); _videoDecoder->StartThread(); _videoRenderer->StartThread(); } void Console::Release() { Stop(); _videoDecoder->StopThread(); _videoRenderer->StopThread(); _videoDecoder.reset(); _videoRenderer.reset(); _debugHud.reset(); _notificationManager.reset(); } void Console::Run() { if(!_cpu) { return; } _stopFlag = false; uint32_t previousFrameCount = 0; FrameLimiter frameLimiter(16.63926405550947); PlatformUtilities::EnableHighResolutionTimer(); uint32_t keyCode = KeyManager::GetKeyCode("Tab"); auto lock = _runLock.AcquireSafe(); while(!_stopFlag) { _cpu->Exec(); if(previousFrameCount != _ppu->GetFrameCount()) { if(!KeyManager::IsKeyPressed(keyCode)) { frameLimiter.ProcessFrame(); frameLimiter.WaitForNextFrame(); } previousFrameCount = _ppu->GetFrameCount(); } } PlatformUtilities::RestoreTimerResolution(); } void Console::Stop() { _stopFlag = true; shared_ptr debugger = _debugger; if(debugger) { debugger->Run(); } _debugger.reset(); _runLock.WaitForRelease(); _cpu.reset(); _ppu.reset(); _spc.reset(); _cart.reset(); _internalRegisters.reset(); _controlManager.reset(); _memoryManager.reset(); _dmaController.reset(); _soundMixer->StopAudio(); } void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile) { Stop(); shared_ptr cart = BaseCartridge::CreateCartridge(romFile, patchFile); if(cart) { MessageManager::ClearLog(); vector spcRomData; VirtualFile spcBios(FolderUtilities::CombinePath(FolderUtilities::GetHomeFolder(), "spc700.rom")); if(spcBios.IsValid()) { spcBios.ReadFile(spcRomData); } else { MessageManager::Log("[SPC] spc700.rom not found, cannot launch game."); return; } _internalRegisters.reset(new InternalRegisters(shared_from_this())); _ppu.reset(new Ppu(shared_from_this())); _spc.reset(new Spc(shared_from_this(), spcRomData)); _cart = cart; _controlManager.reset(new ControlManager(shared_from_this())); _memoryManager.reset(new MemoryManager()); _dmaController.reset(new DmaController(_memoryManager.get())); _memoryManager->Initialize(shared_from_this()); _cpu.reset(new Cpu(_memoryManager)); _memoryManager->IncrementMasterClockValue<160>(); //if(_debugger) { //Reset debugger if it was running before //auto lock = _debuggerLock.AcquireSafe(); //_debugger.reset(); //GetDebugger(); //} } } shared_ptr Console::GetSoundMixer() { return _soundMixer; } shared_ptr Console::GetVideoRenderer() { return _videoRenderer; } shared_ptr Console::GetVideoDecoder() { return _videoDecoder; } shared_ptr Console::GetNotificationManager() { return _notificationManager; } shared_ptr Console::GetDebugHud() { return _debugHud; } shared_ptr Console::GetCpu() { return _cpu; } shared_ptr Console::GetPpu() { return _ppu; } shared_ptr Console::GetSpc() { return _spc; } shared_ptr Console::GetCartridge() { return _cart; } shared_ptr Console::GetMemoryManager() { return _memoryManager; } shared_ptr Console::GetInternalRegisters() { return _internalRegisters; } shared_ptr Console::GetControlManager() { return _controlManager; } shared_ptr Console::GetDmaController() { return _dmaController; } shared_ptr Console::GetDebugger(bool autoStart) { shared_ptr debugger = _debugger; if(!debugger && autoStart) { //Lock to make sure we don't try to start debuggers in 2 separate threads at once auto lock = _debuggerLock.AcquireSafe(); debugger = _debugger; if(!debugger) { debugger.reset(new Debugger(shared_from_this())); _debugger = debugger; } } return debugger; } bool Console::IsRunning() { return _cpu != nullptr; } void Console::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType type) { if(_debugger) { _debugger->ProcessCpuRead(addr, value, type); } } void Console::ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType type) { if(_debugger) { _debugger->ProcessCpuWrite(addr, value, type); } }