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