mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 13:47:57 +03:00

Some checks are pending
Build Android / build_android (apk) (push) Waiting to run
Build Android / build_android (libretro) (push) Waiting to run
Build iOS / build_ios (push) Waiting to run
Build JavaScript / build_js (push) Waiting to run
Build Linux / build_linux (push) Waiting to run
Build Linux ARM32 / build_linux_arm32 (push) Waiting to run
Build Linux ARM64 / build_linux_arm64 (push) Waiting to run
Build macOS / build_macos (push) Waiting to run
Build Windows / build_windows (x86_32, Visual Studio 16 2019, installer32.nsi, win32_msvc2019, Win32) (push) Waiting to run
Build Windows / build_windows (x86_64, Visual Studio 16 2019, installer64.nsi, win64_msvc2019_64, x64) (push) Waiting to run
Build Windows Psf / build_windows_psf (off, x86_64, Visual Studio 16 2019, installer64.nsi, x64) (push) Waiting to run
Build Windows Psf / build_windows_psf (on, x86_64, Visual Studio 16 2019, installer64.nsi, x64) (push) Waiting to run
Check Format / run_clangformat (push) Waiting to run
483 lines
10 KiB
C++
483 lines
10 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <memory>
|
|
#include "filesystem_def.h"
|
|
#include "signal/Signal.h"
|
|
#include "../ELF.h"
|
|
#include "../MIPS.h"
|
|
#include "../BiosDebugInfoProvider.h"
|
|
#include "../OsStructManager.h"
|
|
#include "../OsVariableWrapper.h"
|
|
#include "../OsStructQueue.h"
|
|
#include "../gs/GSHandler.h"
|
|
#include "SIF.h"
|
|
#include "Ee_IdleEvaluator.h"
|
|
#include "Ee_LibMc2.h"
|
|
|
|
#define INTERRUPTS_ENABLED_MASK (CMIPS::STATUS_IE | CMIPS::STATUS_EIE)
|
|
|
|
class CIopBios;
|
|
|
|
class CPS2OS : public CBiosDebugInfoProvider
|
|
{
|
|
public:
|
|
typedef std::vector<std::string> ArgumentList;
|
|
|
|
typedef Framework::CSignal<void(const char*, const ArgumentList&)> RequestLoadExecutableEvent;
|
|
|
|
CPS2OS(CMIPS&, uint8*, uint8*, uint8*, CGSHandler*&, CSIF&, CIopBios&);
|
|
virtual ~CPS2OS();
|
|
|
|
void Initialize(uint32);
|
|
void Release();
|
|
|
|
bool IsIdle() const;
|
|
|
|
void BootFromFile(const fs::path&);
|
|
void BootFromVirtualPath(const char*, const ArgumentList&);
|
|
void BootFromCDROM();
|
|
CELF32* GetELF();
|
|
const char* GetExecutableName() const;
|
|
std::pair<uint32, uint32> GetExecutableRange() const;
|
|
uint32 LoadExecutable(const char*, const char*);
|
|
|
|
Ee::CLibMc2& GetLibMc2();
|
|
|
|
void HandleInterrupt(int32);
|
|
void HandleSyscall();
|
|
void HandleReturnFromException();
|
|
void HandleTLBException();
|
|
bool CheckVBlankFlag();
|
|
|
|
uint32 SuspendCurrentThread();
|
|
void ResumeThread(uint32);
|
|
|
|
uint8* GetStructPtr(uint32) const;
|
|
|
|
void UpdateTLBEnabledState();
|
|
|
|
static uint32 TranslateAddress(CMIPS*, uint32);
|
|
static uint32 TranslateAddressTLB(CMIPS*, uint32);
|
|
static uint32 CheckTLBExceptions(CMIPS*, uint32, uint32);
|
|
|
|
#ifdef DEBUGGER_INCLUDED
|
|
BiosDebugModuleInfoArray GetModulesDebugInfo() const override;
|
|
BiosDebugObjectInfoMap GetBiosObjectsDebugInfo() const override;
|
|
BiosDebugObjectArray GetBiosObjects(uint32) const override;
|
|
#endif
|
|
|
|
Framework::CSignal<void()> OnExecutableChange;
|
|
Framework::CSignal<void()> OnExecutableUnloading;
|
|
Framework::CSignal<void()> OnRequestInstructionCacheFlush;
|
|
RequestLoadExecutableEvent OnRequestLoadExecutable;
|
|
Framework::CSignal<void()> OnRequestExit;
|
|
Framework::CSignal<void()> OnCrtModeChange;
|
|
|
|
private:
|
|
enum
|
|
{
|
|
BIOS_SIFDMA_COUNT = 0x20,
|
|
};
|
|
|
|
struct BIOS_STATE
|
|
{
|
|
uint32 padding[4];
|
|
uint32 idleThreadId;
|
|
uint32 currentThreadId;
|
|
uint32 vsyncFlagValue1Ptr;
|
|
uint32 vsyncFlagValue2Ptr;
|
|
uint32 threadScheduleBase;
|
|
uint32 intcHandlerQueueBase;
|
|
uint32 dmacHandlerQueueBase;
|
|
uint32 tlblExceptionHandler;
|
|
uint32 tlbsExceptionHandler;
|
|
uint32 trapExceptionHandler;
|
|
uint32 allocateThreadNextId;
|
|
uint32 sifDmaNextIdx;
|
|
uint32 sifDmaTimes[BIOS_SIFDMA_COUNT];
|
|
};
|
|
static_assert((sizeof(BIOS_STATE) & 0xF) == 0, "Size of BIOS_STATE must be a multiple of 16.");
|
|
|
|
struct SEMAPHOREPARAM
|
|
{
|
|
uint32 count;
|
|
uint32 maxCount;
|
|
uint32 initCount;
|
|
uint32 waitThreads;
|
|
uint32 attributes;
|
|
uint32 option;
|
|
};
|
|
|
|
struct THREADPARAM
|
|
{
|
|
uint32 status;
|
|
uint32 threadProc;
|
|
uint32 stackBase;
|
|
uint32 stackSize;
|
|
uint32 gp;
|
|
uint32 initPriority;
|
|
uint32 currPriority;
|
|
uint32 attr;
|
|
uint32 option;
|
|
};
|
|
|
|
struct THREADSTATUS : public THREADPARAM
|
|
{
|
|
uint32 waitType;
|
|
uint32 waitId;
|
|
uint32 wakeupCount;
|
|
};
|
|
static_assert(sizeof(THREADSTATUS) == 0x30, "Thread status must be 48 bytes long.");
|
|
|
|
struct SEMAPHORE
|
|
{
|
|
uint32 isValid;
|
|
uint32 count;
|
|
uint32 maxCount;
|
|
uint32 waitCount;
|
|
uint32 waitNextId;
|
|
uint32 option;
|
|
};
|
|
|
|
struct THREAD
|
|
{
|
|
uint32 isValid;
|
|
uint32 nextId;
|
|
uint32 status;
|
|
uint32 contextPtr;
|
|
uint32 stackBase;
|
|
uint32 heapBase;
|
|
uint32 threadProc;
|
|
uint32 epc;
|
|
uint32 gp;
|
|
uint32 initPriority;
|
|
uint32 currPriority;
|
|
uint32 semaWait;
|
|
uint32 wakeUpCount;
|
|
uint32 stackSize;
|
|
};
|
|
|
|
enum STACKRES
|
|
{
|
|
STACKRES = 0x2A0,
|
|
STACK_FRAME_RESERVE_SIZE = 0x20
|
|
};
|
|
|
|
//Castlevania: CoD relies on the fact that the GPRs are stored
|
|
//in order starting from R0 all the way up to RA because it read/writes
|
|
//values directly in the thread context
|
|
struct THREADCONTEXT
|
|
{
|
|
uint128 gpr[0x20];
|
|
uint32 cop1[0x20];
|
|
uint32 fcsr;
|
|
uint32 cop1a;
|
|
uint32 unknown[6];
|
|
};
|
|
static_assert(sizeof(THREADCONTEXT) == STACKRES, "Size of THREADCONTEXT must be STACKRES");
|
|
|
|
struct DMACHANDLER
|
|
{
|
|
uint32 isValid;
|
|
uint32 nextId;
|
|
uint32 channel;
|
|
uint32 address;
|
|
uint32 arg;
|
|
uint32 gp;
|
|
};
|
|
|
|
struct INTCHANDLER
|
|
{
|
|
uint32 isValid;
|
|
uint32 nextId;
|
|
uint32 cause;
|
|
uint32 address;
|
|
uint32 arg;
|
|
uint32 gp;
|
|
};
|
|
|
|
struct DECI2HANDLER
|
|
{
|
|
uint32 isValid;
|
|
uint32 device;
|
|
uint32 bufferAddr;
|
|
};
|
|
|
|
//I have no idea about this, purely speculative
|
|
struct DECI2BUFFER
|
|
{
|
|
uint32 unknown0;
|
|
int32 status0;
|
|
int32 unknown1;
|
|
uint32 status1;
|
|
uint32 dataAddr;
|
|
};
|
|
static_assert(sizeof(DECI2BUFFER) == 0x14);
|
|
|
|
struct DECI2SEND
|
|
{
|
|
uint32 size;
|
|
uint32 unknown[2];
|
|
uint8 data[];
|
|
};
|
|
static_assert(offsetof(DECI2SEND, data) == 0x0C);
|
|
|
|
struct ALARM
|
|
{
|
|
uint32 isValid;
|
|
uint32 delay;
|
|
uint32 compare;
|
|
uint32 callback;
|
|
uint32 callbackParam;
|
|
uint32 gp;
|
|
};
|
|
|
|
enum class OSD_VERSION
|
|
{
|
|
V1,
|
|
V2,
|
|
V2_EXT,
|
|
};
|
|
|
|
enum class OSD_LANGUAGE
|
|
{
|
|
JAPANESE,
|
|
ENGLISH,
|
|
FRENCH,
|
|
SPANISH,
|
|
GERMAN,
|
|
ITALIAN,
|
|
DUTCH,
|
|
PORTUGUESE,
|
|
RUSSIAN,
|
|
KOREAN,
|
|
CHINESE_TRADITIONAL,
|
|
CHINESE_SIMPLIFIED
|
|
};
|
|
|
|
enum class OSD_SCREENTYPE
|
|
{
|
|
RATIO_4_3,
|
|
FULLSCREEN,
|
|
RATIO_16_9,
|
|
};
|
|
|
|
struct OSDCONFIGPARAM : public convertible<uint32>
|
|
{
|
|
uint32 spdifMode : 1;
|
|
uint32 screenType : 2;
|
|
uint32 videoOutput : 1;
|
|
uint32 jpLanguage : 1;
|
|
uint32 ps1drvConfig : 8;
|
|
uint32 version : 3;
|
|
uint32 language : 5;
|
|
uint32 timezoneOffset : 11;
|
|
};
|
|
|
|
#ifdef DEBUGGER_INCLUDED
|
|
struct SYSCALL_NAME
|
|
{
|
|
uint32 id;
|
|
const char* name;
|
|
};
|
|
#endif
|
|
|
|
enum SYSCALL_REGS
|
|
{
|
|
SC_RETURN = 2,
|
|
SC_PARAM0 = 4,
|
|
SC_PARAM1 = 5,
|
|
SC_PARAM2 = 6,
|
|
SC_PARAM3 = 7,
|
|
SC_PARAM4 = 8
|
|
};
|
|
|
|
enum MAX
|
|
{
|
|
MAX_THREAD = 256,
|
|
MAX_SEMAPHORE = 256,
|
|
MAX_DMACHANDLER = 128,
|
|
MAX_INTCHANDLER = 128,
|
|
MAX_DECI2HANDLER = 32,
|
|
MAX_ALARM = 4,
|
|
};
|
|
|
|
//TODO: Use "refer" status enum values
|
|
enum THREAD_STATUS
|
|
{
|
|
THREAD_RUNNING = 0x01,
|
|
THREAD_SLEEPING = 0x02,
|
|
THREAD_WAITING = 0x03,
|
|
THREAD_SUSPENDED = 0x04,
|
|
THREAD_SUSPENDED_WAITING = 0x05,
|
|
THREAD_SUSPENDED_SLEEPING = 0x06,
|
|
THREAD_ZOMBIE = 0x07,
|
|
};
|
|
|
|
enum THREAD_STATUS_REFER
|
|
{
|
|
THS_RUN = 0x01,
|
|
THS_READY = 0x02,
|
|
THS_WAIT = 0x04,
|
|
THS_SUSPEND = 0x08,
|
|
THS_DORMANT = 0x10,
|
|
};
|
|
|
|
typedef COsStructManager<DECI2HANDLER> Deci2HandlerList;
|
|
typedef COsStructManager<THREAD> ThreadList;
|
|
typedef COsStructManager<SEMAPHORE> SemaphoreList;
|
|
typedef COsStructManager<INTCHANDLER> IntcHandlerList;
|
|
typedef COsStructManager<DMACHANDLER> DmacHandlerList;
|
|
typedef COsStructManager<ALARM> AlarmList;
|
|
|
|
typedef COsStructQueue<THREAD> ThreadQueue;
|
|
typedef COsStructQueue<INTCHANDLER> IntcHandlerQueue;
|
|
typedef COsStructQueue<DMACHANDLER> DmacHandlerQueue;
|
|
|
|
typedef void (CPS2OS::*SystemCallHandler)();
|
|
|
|
void LoadELF(Framework::CStream*, const char*, const ArgumentList&);
|
|
|
|
void LoadExecutableInternal();
|
|
void UnloadExecutable();
|
|
|
|
void ApplyGameConfig();
|
|
|
|
void DisassembleSysCall(uint8);
|
|
std::string GetSysCallDescription(uint8);
|
|
|
|
static SystemCallHandler m_sysCall[0x80];
|
|
|
|
void AssembleCustomSyscallHandler();
|
|
void AssembleInterruptHandler();
|
|
void AssembleDmacHandler();
|
|
void AssembleIntcHandler();
|
|
void AssembleAlarmHandler();
|
|
void AssembleThreadEpilog();
|
|
void AssembleIdleThreadProc();
|
|
|
|
uint32* GetCustomSyscallTable();
|
|
|
|
void CreateIdleThread();
|
|
void LinkThread(uint32);
|
|
void UnlinkThread(uint32);
|
|
void ThreadShakeAndBake();
|
|
void ThreadSwitchContext(uint32);
|
|
void ThreadSaveContext(THREAD*, bool);
|
|
void ThreadLoadContext(THREAD*, bool);
|
|
void ThreadReset(uint32);
|
|
void CheckLivingThreads();
|
|
|
|
void SemaLinkThread(uint32, uint32);
|
|
void SemaUnlinkThread(uint32, uint32);
|
|
void SemaReleaseSingleThread(uint32, bool);
|
|
|
|
void AlarmUpdateCompare();
|
|
|
|
std::pair<uint32, uint32> GetVsyncFlagPtrs() const;
|
|
void SetVsyncFlagPtrs(uint32, uint32);
|
|
|
|
//Various system calls
|
|
void sc_GsSetCrt();
|
|
void sc_Exit();
|
|
void sc_LoadExecPS2();
|
|
void sc_ExecPS2();
|
|
void sc_SetVTLBRefillHandler();
|
|
void sc_SetVCommonHandler();
|
|
void sc_AddIntcHandler();
|
|
void sc_RemoveIntcHandler();
|
|
void sc_AddDmacHandler();
|
|
void sc_RemoveDmacHandler();
|
|
void sc_EnableIntc();
|
|
void sc_DisableIntc();
|
|
void sc_EnableDmac();
|
|
void sc_DisableDmac();
|
|
void sc_SetAlarm();
|
|
void sc_ReleaseAlarm();
|
|
void sc_CreateThread();
|
|
void sc_DeleteThread();
|
|
void sc_StartThread();
|
|
void sc_ExitThread();
|
|
void sc_ExitDeleteThread();
|
|
void sc_TerminateThread();
|
|
void sc_ChangeThreadPriority();
|
|
void sc_RotateThreadReadyQueue();
|
|
void sc_ReleaseWaitThread();
|
|
void sc_GetThreadId();
|
|
void sc_ReferThreadStatus();
|
|
void sc_SleepThread();
|
|
void sc_WakeupThread();
|
|
void sc_CancelWakeupThread();
|
|
void sc_SuspendThread();
|
|
void sc_ResumeThread();
|
|
void sc_SetupThread();
|
|
void sc_SetupHeap();
|
|
void sc_EndOfHeap();
|
|
void sc_CreateSema();
|
|
void sc_DeleteSema();
|
|
void sc_SignalSema();
|
|
void sc_WaitSema();
|
|
void sc_PollSema();
|
|
void sc_ReferSemaStatus();
|
|
void sc_GetOsdConfigParam();
|
|
void sc_GetCop0();
|
|
void sc_FlushCache();
|
|
void sc_GsGetIMR();
|
|
void sc_GsPutIMR();
|
|
void sc_SetVSyncFlag();
|
|
void sc_SetSyscall();
|
|
void sc_SifDmaStat();
|
|
void sc_SifSetDma();
|
|
void sc_SifSetDChain();
|
|
void sc_SifSetReg();
|
|
void sc_SifGetReg();
|
|
void sc_Deci2Call();
|
|
void sc_MachineType();
|
|
void sc_GetMemorySize();
|
|
void sc_Unhandled();
|
|
|
|
CMIPS& m_ee;
|
|
CGSHandler*& m_gs;
|
|
|
|
uint8* m_ram = nullptr;
|
|
uint32 m_ramSize = 0;
|
|
uint8* m_bios = nullptr;
|
|
uint8* m_spr = nullptr;
|
|
|
|
CSIF& m_sif;
|
|
Ee::CLibMc2 m_libMc2;
|
|
CIopBios& m_iopBios;
|
|
|
|
std::unique_ptr<CELF32> m_elf;
|
|
Deci2HandlerList m_deci2Handlers;
|
|
ThreadList m_threads;
|
|
SemaphoreList m_semaphores;
|
|
IntcHandlerList m_intcHandlers;
|
|
DmacHandlerList m_dmacHandlers;
|
|
AlarmList m_alarms;
|
|
|
|
BIOS_STATE* m_state = nullptr;
|
|
OsVariableWrapper<uint32> m_currentThreadId;
|
|
OsVariableWrapper<uint32> m_idleThreadId;
|
|
OsVariableWrapper<uint32> m_tlblExceptionHandler;
|
|
OsVariableWrapper<uint32> m_tlbsExceptionHandler;
|
|
OsVariableWrapper<uint32> m_trapExceptionHandler;
|
|
OsVariableWrapper<uint32> m_sifDmaNextIdx;
|
|
uint32* m_sifDmaTimes = nullptr;
|
|
|
|
ThreadQueue m_threadSchedule;
|
|
IntcHandlerQueue m_intcHandlerQueue;
|
|
DmacHandlerQueue m_dmacHandlerQueue;
|
|
|
|
ArgumentList m_currentArguments;
|
|
|
|
//For display purposes only
|
|
std::string m_executableName;
|
|
|
|
Ee::CIdleEvaluator m_idleEvaluator;
|
|
|
|
#ifdef DEBUGGER_INCLUDED
|
|
static const SYSCALL_NAME g_syscallNames[];
|
|
#endif
|
|
};
|