1 #pragma once 2 3 #include <thread> 4 #include <future> 5 #include "filesystem_def.h" 6 #include "Types.h" 7 #include "MIPS.h" 8 #include "MailBox.h" 9 #include "PadHandler.h" 10 #include "OpticalMedia.h" 11 #include "VirtualMachine.h" 12 #include "ee/Ee_SubSystem.h" 13 #include "iop/Iop_SubSystem.h" 14 #include "../tools/PsfPlayer/Source/SoundHandler.h" 15 #include "FrameDump.h" 16 #include "FrameLimiter.h" 17 #include "Profiler.h" 18 19 class CPS2VM : public CVirtualMachine 20 { 21 public: 22 struct CPU_UTILISATION_INFO 23 { 24 int32 eeTotalTicks = 0; 25 int32 eeIdleTicks = 0; 26 27 int32 iopTotalTicks = 0; 28 int32 iopIdleTicks = 0; 29 }; 30 31 typedef std::unique_ptr<Ee::CSubSystem> EeSubSystemPtr; 32 typedef std::unique_ptr<Iop::CSubSystem> IopSubSystemPtr; 33 typedef std::function<void(const CFrameDump&)> FrameDumpCallback; 34 typedef Framework::CSignal<void(const CProfiler::ZoneArray&)> ProfileFrameDoneSignal; 35 36 CPS2VM(); 37 virtual ~CPS2VM() = default; 38 39 void Initialize(); 40 void Destroy(); 41 42 void StepEe(); 43 void StepIop(); 44 void StepVu0(); 45 void StepVu1(); 46 47 void Resume() override; 48 void Pause() override; 49 void PauseAsync(); 50 void Reset(); 51 52 STATUS GetStatus() const override; 53 54 void DumpEEIntcHandlers(); 55 void DumpEEDmacHandlers(); 56 57 void CreateGSHandler(const CGSHandler::FactoryFunction&); 58 CGSHandler* GetGSHandler(); 59 void DestroyGSHandler(); 60 61 void CreatePadHandler(const CPadHandler::FactoryFunction&); 62 CPadHandler* GetPadHandler(); 63 void DestroyPadHandler(); 64 65 void CreateSoundHandler(const CSoundHandler::FactoryFunction&); 66 CSoundHandler* GetSoundHandler(); 67 void DestroySoundHandler(); 68 void ReloadSpuBlockCount(); 69 70 void ReloadFrameRateLimit(); 71 72 static fs::path GetStateDirectoryPath(); 73 fs::path GenerateStatePath(unsigned int) const; 74 75 std::future<bool> SaveState(const fs::path&); 76 std::future<bool> LoadState(const fs::path&); 77 78 void TriggerFrameDump(const FrameDumpCallback&); 79 80 CPU_UTILISATION_INFO GetCpuUtilisationInfo() const; 81 82 #ifdef DEBUGGER_INCLUDED 83 std::string MakeDebugTagsPackagePath(const char*); 84 void LoadDebugTags(const char*); 85 void SaveDebugTags(const char*); 86 #endif 87 88 CPadHandler* m_pad; 89 90 EeSubSystemPtr m_ee; 91 IopSubSystemPtr m_iop; 92 93 ProfileFrameDoneSignal ProfileFrameDone; 94 95 private: 96 typedef std::unique_ptr<COpticalMedia> OpticalMediaPtr; 97 98 void CreateVM(); 99 void ResetVM(); 100 void DestroyVM(); 101 bool SaveVMState(const fs::path&); 102 bool LoadVMState(const fs::path&); 103 104 void ReloadExecutable(const char*, const CPS2OS::ArgumentList&); 105 void OnCrtModeChange(); 106 107 void ResumeImpl(); 108 void PauseImpl(); 109 void DestroyImpl(); 110 111 void CreateGsHandlerImpl(const CGSHandler::FactoryFunction&); 112 void DestroyGsHandlerImpl(); 113 114 void CreatePadHandlerImpl(const CPadHandler::FactoryFunction&); 115 void DestroyPadHandlerImpl(); 116 117 void CreateSoundHandlerImpl(const CSoundHandler::FactoryFunction&); 118 void DestroySoundHandlerImpl(); 119 120 void UpdateEe(); 121 void UpdateIop(); 122 void UpdateSpu(); 123 124 void OnGsNewFrame(); 125 126 void CDROM0_SyncPath(); 127 void CDROM0_Reset(); 128 void SetIopOpticalMedia(COpticalMedia*); 129 130 void RegisterModulesInPadHandler(); 131 132 void EmuThread(); 133 134 std::thread m_thread; 135 CMailBox m_mailBox; 136 STATUS m_nStatus; 137 bool m_nEnd; 138 139 uint32 m_onScreenTicksTotal = 0; 140 uint32 m_vblankTicksTotal = 0; 141 int m_vblankTicks = 0; 142 bool m_inVblank = 0; 143 int m_spuUpdateTicks = 0; 144 int m_eeExecutionTicks = 0; 145 int m_iopExecutionTicks = 0; 146 CFrameLimiter m_frameLimiter; 147 148 CPU_UTILISATION_INFO m_cpuUtilisation; 149 150 bool m_singleStepEe; 151 bool m_singleStepIop; 152 bool m_singleStepVu0; 153 bool m_singleStepVu1; 154 155 CFrameDump m_frameDump; 156 FrameDumpCallback m_frameDumpCallback; 157 std::mutex m_frameDumpCallbackMutex; 158 bool m_dumpingFrame = false; 159 160 OpticalMediaPtr m_cdrom0; 161 162 //SPU update parameters 163 enum 164 { 165 DST_SAMPLE_RATE = 44100, 166 UPDATE_RATE = 1000, //Number of SPU updates per second (on PS2 time scale) 167 SPU_UPDATE_TICKS = PS2::IOP_CLOCK_OVER_FREQ / UPDATE_RATE, 168 SAMPLE_COUNT = DST_SAMPLE_RATE / UPDATE_RATE, 169 BLOCK_SIZE = SAMPLE_COUNT * 2, 170 BLOCK_COUNT = 400, 171 }; 172 173 int16 m_samples[BLOCK_SIZE * BLOCK_COUNT]; 174 int m_currentSpuBlock = 0; 175 int m_spuBlockCount; 176 CSoundHandler* m_soundHandler = nullptr; 177 178 CProfiler::ZoneHandle m_eeProfilerZone = 0; 179 CProfiler::ZoneHandle m_iopProfilerZone = 0; 180 CProfiler::ZoneHandle m_spuProfilerZone = 0; 181 CProfiler::ZoneHandle m_gsSyncProfilerZone = 0; 182 CProfiler::ZoneHandle m_otherProfilerZone = 0; 183 184 CPS2OS::RequestLoadExecutableEvent::Connection m_OnRequestLoadExecutableConnection; 185 Framework::CSignal<void()>::Connection m_OnCrtModeChangeConnection; 186 Framework::CSignal<void(uint32)>::Connection m_OnNewFrameConnection; 187 }; 188