#pragma once #include "stdafx.h" #include "Core/Debugger/DebugTypes.h" #include "Core/Debugger/Debugger.h" #include "Core/Shared/EmulatorLock.h" #include "Core/Shared/Interfaces/IConsole.h" #include "Core/Shared/Audio/AudioPlayerTypes.h" #include "Utilities/Timer.h" #include "Utilities/safe_ptr.h" #include "Utilities/SimpleLock.h" #include "Utilities/VirtualFile.h" class Debugger; class DebugHud; class SoundMixer; class VideoRenderer; class VideoDecoder; class NotificationManager; class EmuSettings; class SaveStateManager; class RewindManager; class BatteryManager; class CheatManager; class MovieManager; class HistoryViewer; class FrameLimiter; class DebugStats; class BaseControlManager; class VirtualFile; class BaseVideoFilter; class ShortcutKeyHandler; class SystemActionManager; class AudioPlayerHud; class GameServer; class GameClient; class IInputRecorder; class IInputProvider; struct RomInfo; struct TimingInfo; enum class MemoryOperationType; enum class MemoryType; enum class EventType; enum class ConsoleRegion; enum class ConsoleType; enum class HashType; enum class TapeRecorderAction; struct ConsoleMemoryInfo { void* Memory; uint32_t Size; }; class Emulator { private: unique_ptr _emuThread; unique_ptr _audioPlayerHud; safe_ptr _console; shared_ptr _shortcutKeyHandler; shared_ptr _rewindManager; safe_ptr _debugger; shared_ptr _systemActionManager; const unique_ptr _settings; const unique_ptr _debugHud; const unique_ptr _scriptHud; const unique_ptr _notificationManager; const unique_ptr _batteryManager; const unique_ptr _soundMixer; const unique_ptr _videoRenderer; const unique_ptr _videoDecoder; const unique_ptr _saveStateManager; const unique_ptr _cheatManager; const unique_ptr _movieManager; const unique_ptr _historyViewer; const shared_ptr _gameServer; const shared_ptr _gameClient; thread::id _emulationThreadId; atomic _lockCounter; SimpleLock _runLock; SimpleLock _loadLock; SimpleLock _debuggerLock; atomic _stopFlag; atomic _paused; atomic _pauseOnNextFrame; atomic _threadPaused; atomic _debugRequestCount; atomic _allowDebuggerRequest; atomic _isRunAheadFrame; bool _frameRunning = false; RomInfo _rom; ConsoleMemoryInfo _consoleMemory[(int)MemoryType::Register + 1] = {}; unique_ptr _stats; unique_ptr _frameLimiter; Timer _lastFrameTimer; double _frameDelay = 0; uint32_t _autoSaveStateFrameCounter = 0; void WaitForLock(); void WaitForPauseEnd(); void ProcessAutoSaveState(); bool ProcessSystemActions(); void RunFrameWithRunAhead(); void BlockDebuggerRequests(); void ResetDebugger(bool startDebugger = false); double GetFrameDelay(); template void TryLoadRom(VirtualFile& romFile, LoadRomResult& result, unique_ptr& console); public: class DebuggerRequest { private: shared_ptr _debugger; Emulator* _emu = nullptr; public: DebuggerRequest(Emulator* emu) { if(emu) { _emu = emu; _debugger = _emu->_debugger.lock(); _emu->_debugRequestCount++; } } ~DebuggerRequest() { if(_emu) { _emu->_debugRequestCount--; } } Debugger* GetDebugger() { return _debugger.get(); } }; Emulator(); ~Emulator(); void Initialize(bool enableShortcuts = true); void Release(); void Run(); void Stop(bool sendNotification, bool preventRecentGameSave = false, bool saveBattery = true); void OnBeforeSendFrame(); void ProcessEndOfFrame(); void Reset(); void ReloadRom(bool forPowerCycle); void PowerCycle(); void PauseOnNextFrame(); void Pause(); void Resume(); bool IsPaused(); bool LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom = true, bool forPowerCycle = false); RomInfo& GetRomInfo(); string GetHash(HashType type); uint32_t GetCrc32(); PpuFrameInfo GetPpuFrame(); ConsoleRegion GetRegion(); shared_ptr GetConsole(); IConsole* GetConsoleUnsafe(); ConsoleType GetConsoleType(); vector GetCpuTypes(); uint64_t GetMasterClock(); uint32_t GetMasterClockRate(); EmulatorLock AcquireLock(); void Lock(); void Unlock(); bool IsThreadPaused(); void SuspendDebugger(bool release); void Serialize(ostream& out, bool includeSettings, int compressionLevel = 1); bool Deserialize(istream& in, uint32_t fileFormatVersion, bool includeSettings); SoundMixer* GetSoundMixer(); VideoRenderer* GetVideoRenderer(); VideoDecoder* GetVideoDecoder(); ShortcutKeyHandler* GetShortcutKeyHandler(); NotificationManager* GetNotificationManager(); EmuSettings* GetSettings(); SaveStateManager* GetSaveStateManager(); RewindManager* GetRewindManager(); DebugHud* GetDebugHud(); DebugHud* GetScriptHud(); BatteryManager* GetBatteryManager(); CheatManager* GetCheatManager(); MovieManager* GetMovieManager(); HistoryViewer* GetHistoryViewer(); GameServer* GetGameServer(); GameClient* GetGameClient(); shared_ptr GetSystemActionManager(); BaseVideoFilter* GetVideoFilter(); void InputBarcode(uint64_t barcode, uint32_t digitCount); void ProcessTapeRecorderAction(TapeRecorderAction action, string filename); ShortcutState IsShortcutAllowed(EmulatorShortcut shortcut, uint32_t shortcutParam); bool IsKeyboardConnected(); void InitDebugger(); void StopDebugger(); DebuggerRequest GetDebugger(bool autoInit = false); bool IsDebugging(); Debugger* InternalGetDebugger() { return _debugger.get(); } thread::id GetEmulationThreadId(); bool IsEmulationThread(); void RegisterMemory(MemoryType type, void* memory, uint32_t size); ConsoleMemoryInfo GetMemory(MemoryType type); AudioTrackInfo GetAudioTrackInfo(); void ProcessAudioPlayerAction(AudioPlayerActionParams p); AudioPlayerHud* GetAudioPlayerHud(); bool IsRunning(); bool IsRunAheadFrame(); TimingInfo GetTimingInfo(CpuType cpuType); uint32_t GetFrameCount(); uint32_t GetLagCounter(); void ResetLagCounter(); bool HasControlDevice(ControllerType type); void RegisterInputRecorder(IInputRecorder* recorder); void UnregisterInputRecorder(IInputRecorder* recorder); void RegisterInputProvider(IInputProvider* provider); void UnregisterInputProvider(IInputProvider* provider); double GetFps(); template __forceinline void ProcessInstruction() { if(_debugger) { _debugger->ProcessInstruction(); } } template __forceinline void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType) { if(_debugger) { _debugger->ProcessMemoryRead(addr, value, opType); } } template __forceinline void ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType) { if(_debugger) { _debugger->ProcessMemoryWrite(addr, value, opType); } } template __forceinline void ProcessIdleCycle() { if(_debugger) { _debugger->ProcessIdleCycle(); } } template __forceinline void ProcessPpuRead(uint32_t addr, T& value, MemoryType memoryType, MemoryOperationType opType = MemoryOperationType::Read) { if(_debugger) { _debugger->ProcessPpuRead(addr, value, memoryType, opType); } } template __forceinline void ProcessPpuWrite(uint32_t addr, T& value, MemoryType memoryType) { if(_debugger) { _debugger->ProcessPpuWrite(addr, value, memoryType); } } template __forceinline void ProcessPpuCycle() { if(_debugger) { _debugger->ProcessPpuCycle(); } } __forceinline void DebugLog(string log) { if(_debugger) { _debugger->Log(log); } } template void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi); void ProcessEvent(EventType type); template void AddDebugEvent(DebugEventType evtType); void BreakIfDebugging(CpuType sourceCpu, BreakSource source); }; enum class HashType { Crc32, Sha1 };