2019-08-17 13:51:31 -04:00
|
|
|
#include <cstring>
|
2008-12-24 02:03:58 +00:00
|
|
|
#include "PsxBios.h"
|
|
|
|
#include "COP_SCU.h"
|
|
|
|
#include "Log.h"
|
|
|
|
#include "iop/Iop_Intc.h"
|
2018-03-02 11:33:27 +00:00
|
|
|
#include "MIPSAssembler.h"
|
2008-12-24 02:03:58 +00:00
|
|
|
#include "xml/Node.h"
|
|
|
|
#include "xml/Writer.h"
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define LOG_NAME ("psxbios")
|
|
|
|
#define SC_PARAM0 (CMIPS::A0)
|
|
|
|
#define SC_PARAM1 (CMIPS::A1)
|
|
|
|
#define SC_PARAM2 (CMIPS::A2)
|
|
|
|
#define SC_PARAM3 (CMIPS::A3)
|
|
|
|
#define SC_RETURN (CMIPS::V0)
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define PCB_TABLE_ADDRESS (0x0108)
|
|
|
|
#define TCB_TABLE_ADDRESS (0x0110)
|
|
|
|
#define EXITFROMEXCEPTION_STATE_ADDR (0x0200)
|
|
|
|
#define SYSHEAP_POINTER_ADDR (0x0204)
|
|
|
|
#define INTR_HANDLER (0x1000)
|
|
|
|
#define EVENT_CHECKER (0x1200)
|
|
|
|
#define EVENTS_BEGIN (0x3000)
|
|
|
|
#define EVENTS_SIZE (sizeof(CPsxBios::EVENT) * CPsxBios::MAX_EVENT)
|
|
|
|
#define B0TABLE_BEGIN (EVENTS_BEGIN + EVENTS_SIZE)
|
|
|
|
#define B0TABLE_SIZE (0x5D * 4)
|
|
|
|
#define C0TABLE_BEGIN (B0TABLE_BEGIN + B0TABLE_SIZE)
|
|
|
|
#define C0TABLE_SIZE (0x1C * 4)
|
|
|
|
#define C0_EXCEPTIONHANDLER_BEGIN (C0TABLE_BEGIN + C0TABLE_SIZE)
|
|
|
|
#define C0_EXCEPTIONHANDLER_SIZE (0x1000)
|
|
|
|
#define HEAP_START (C0_EXCEPTIONHANDLER_BEGIN + C0_EXCEPTIONHANDLER_SIZE)
|
|
|
|
#define HEAP_SIZE (0x2000)
|
|
|
|
#define BIOS_MEMORY_END (HEAP_START + HEAP_SIZE)
|
2008-12-24 02:03:58 +00:00
|
|
|
|
2018-02-04 10:13:58 -05:00
|
|
|
CPsxBios::CPsxBios(CMIPS& cpu, uint8* ram, uint32 ramSize)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_cpu(cpu)
|
|
|
|
, m_ram(ram)
|
|
|
|
, m_ramSize(ramSize)
|
|
|
|
, m_exitFromExceptionStateAddr(reinterpret_cast<uint32*>(m_ram + EXITFROMEXCEPTION_STATE_ADDR))
|
|
|
|
, m_sysHeapPointerAddr(reinterpret_cast<uint32*>(m_ram + SYSHEAP_POINTER_ADDR))
|
|
|
|
, m_events(reinterpret_cast<EVENT*>(&m_ram[EVENTS_BEGIN]), 1, MAX_EVENT)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2018-02-05 12:47:49 -05:00
|
|
|
static_assert(BIOS_MEMORY_END <= 0x10000, "BIOS memory size must not exceed 64k");
|
2008-12-24 02:03:58 +00:00
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::Reset()
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
uint32 syscallAddress[3] = {0xA0, 0xB0, 0xC0};
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(m_ram + syscallAddress[i]));
|
|
|
|
assembler.SYSCALL();
|
|
|
|
assembler.JR(CMIPS::RA);
|
2011-06-06 00:18:33 +00:00
|
|
|
assembler.NOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Assembly a dummy JR RA at 0 because Vagrant Story jumps at 0
|
|
|
|
{
|
|
|
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(m_ram + 0x0));
|
2018-04-30 21:01:23 +01:00
|
|
|
assembler.LUI(CMIPS::K0, 0x0000); //This is required by Xenogears' SFX PSFs
|
2011-06-06 00:18:33 +00:00
|
|
|
assembler.JR(CMIPS::RA);
|
|
|
|
assembler.NOP();
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
2015-04-18 19:39:59 -04:00
|
|
|
m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] |= CMIPS::STATUS_IE;
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
AssembleEventChecker();
|
|
|
|
AssembleInterruptHandler();
|
|
|
|
|
|
|
|
//Setup B0 table
|
|
|
|
{
|
|
|
|
uint32* table = reinterpret_cast<uint32*>(&m_ram[B0TABLE_BEGIN]);
|
|
|
|
table[0x5B] = C0_EXCEPTIONHANDLER_BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Setup C0 table
|
|
|
|
{
|
|
|
|
uint32* table = reinterpret_cast<uint32*>(&m_ram[C0TABLE_BEGIN]);
|
|
|
|
table[0x06] = C0_EXCEPTIONHANDLER_BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Assemble dummy exception handler
|
|
|
|
{
|
|
|
|
//0x70 = LUI
|
|
|
|
//0x74 = ADDIU
|
|
|
|
//Chrono Cross will overwrite the stuff present at the address that would be computed
|
|
|
|
//by these two instructions and use something else
|
|
|
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(m_ram + C0_EXCEPTIONHANDLER_BEGIN + 0x70));
|
|
|
|
assembler.LI(CMIPS::T0, C0_EXCEPTIONHANDLER_BEGIN);
|
|
|
|
}
|
|
|
|
|
2018-02-04 15:21:24 -05:00
|
|
|
m_exitFromExceptionStateAddr = 0;
|
2018-02-05 12:47:49 -05:00
|
|
|
m_sysHeapPointerAddr = HEAP_START;
|
2018-02-04 15:21:24 -05:00
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
memset(m_events.GetBase(), 0, EVENTS_SIZE);
|
2018-02-05 13:36:53 -05:00
|
|
|
|
|
|
|
//Allocate process control block
|
|
|
|
{
|
|
|
|
auto cbTable = reinterpret_cast<CB_TABLE*>(m_ram + PCB_TABLE_ADDRESS);
|
|
|
|
cbTable->address = AllocateSysMemory(sizeof(PROCESS));
|
|
|
|
cbTable->size = sizeof(PROCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Allocate thread control block
|
|
|
|
{
|
|
|
|
static const uint32 maxTcb = 4;
|
|
|
|
auto cbTable = reinterpret_cast<CB_TABLE*>(m_ram + TCB_TABLE_ADDRESS);
|
|
|
|
cbTable->address = AllocateSysMemory(sizeof(THREAD) * maxTcb);
|
|
|
|
cbTable->size = sizeof(THREAD) * maxTcb;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Setup main thread
|
|
|
|
{
|
|
|
|
auto process = GetProcess();
|
2018-04-30 21:01:23 +01:00
|
|
|
auto threadCbAddr =
|
|
|
|
[&]() {
|
|
|
|
auto cbTable = reinterpret_cast<CB_TABLE*>(m_ram + TCB_TABLE_ADDRESS);
|
|
|
|
auto threadCb = reinterpret_cast<THREAD*>(m_ram + cbTable->address);
|
|
|
|
threadCb->status = THREAD_STATUS_ALLOCATED;
|
|
|
|
return cbTable->address;
|
|
|
|
}();
|
2018-02-05 13:36:53 -05:00
|
|
|
process->currentThreadControlBlockAddr = threadCbAddr;
|
|
|
|
}
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
2016-11-18 09:46:35 -05:00
|
|
|
void CPsxBios::LoadExe(const uint8* exe)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2016-11-18 09:46:35 -05:00
|
|
|
auto exeHeader = reinterpret_cast<const EXEHEADER*>(exe);
|
|
|
|
if(strncmp(reinterpret_cast<const char*>(exeHeader->id), "PS-X EXE", 8))
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2011-06-06 00:18:33 +00:00
|
|
|
throw std::runtime_error("Invalid PSX executable.");
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nPC = exeHeader->pc0 & 0x1FFFFFFF;
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::GP].nD0 = exeHeader->gp0;
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::SP].nD0 = exeHeader->stackAddr;
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
exe += 0x800;
|
|
|
|
if(exeHeader->textAddr != 0)
|
|
|
|
{
|
|
|
|
uint32 realAddr = exeHeader->textAddr & 0x1FFFFFFF;
|
|
|
|
assert(realAddr + exeHeader->textSize <= m_ramSize);
|
|
|
|
memcpy(m_ram + realAddr, exe, exeHeader->textSize);
|
|
|
|
exe += exeHeader->textSize;
|
2012-10-26 06:15:10 +00:00
|
|
|
|
|
|
|
#ifdef DEBUGGER_INCLUDED
|
2018-03-02 11:33:27 +00:00
|
|
|
m_cpu.m_analysis->Analyse(realAddr, realAddr + exeHeader->textSize, m_cpu.m_State.nPC);
|
2012-10-26 06:15:10 +00:00
|
|
|
#endif
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-04 14:32:09 -05:00
|
|
|
void CPsxBios::SaveState(Framework::CZipArchiveWriter& archive)
|
2009-01-26 02:53:10 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-02-04 14:32:09 -05:00
|
|
|
void CPsxBios::LoadState(Framework::CZipArchiveReader& archive)
|
2009-01-26 02:53:10 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-05-05 04:28:11 +00:00
|
|
|
void CPsxBios::NotifyVBlankStart()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::NotifyVBlankEnd()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-01-26 02:53:10 +00:00
|
|
|
bool CPsxBios::IsIdle()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
return false;
|
2009-01-26 02:53:10 +00:00
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
#ifdef DEBUGGER_INCLUDED
|
|
|
|
|
|
|
|
void CPsxBios::LoadDebugTags(Framework::Xml::CNode* root)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::SaveDebugTags(Framework::Xml::CNode* root)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-03-02 11:33:27 +00:00
|
|
|
BiosDebugModuleInfoArray CPsxBios::GetModulesDebugInfo() const
|
|
|
|
{
|
|
|
|
return BiosDebugModuleInfoArray();
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void CPsxBios::CountTicks(uint32 ticks)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::AssembleEventChecker()
|
|
|
|
{
|
|
|
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(m_ram + EVENT_CHECKER));
|
|
|
|
CMIPSAssembler::LABEL checkEventLabel = assembler.CreateLabel();
|
|
|
|
CMIPSAssembler::LABEL doneEventLabel = assembler.CreateLabel();
|
|
|
|
|
|
|
|
unsigned int currentEvent = CMIPS::S0;
|
|
|
|
unsigned int eventMax = CMIPS::S1;
|
|
|
|
unsigned int eventToCheck = CMIPS::S2;
|
|
|
|
unsigned int needClearInt = CMIPS::S3;
|
|
|
|
int stackAlloc = 5 * 4;
|
|
|
|
|
|
|
|
//prolog
|
|
|
|
assembler.ADDIU(CMIPS::SP, CMIPS::SP, -stackAlloc);
|
|
|
|
assembler.SW(CMIPS::RA, 0x00, CMIPS::SP);
|
|
|
|
assembler.SW(CMIPS::S0, 0x04, CMIPS::SP);
|
|
|
|
assembler.SW(CMIPS::S1, 0x08, CMIPS::SP);
|
|
|
|
assembler.SW(CMIPS::S2, 0x0C, CMIPS::SP);
|
|
|
|
assembler.SW(CMIPS::S3, 0x10, CMIPS::SP);
|
|
|
|
|
|
|
|
assembler.LI(currentEvent, EVENTS_BEGIN);
|
|
|
|
assembler.LI(eventMax, EVENTS_BEGIN + EVENTS_SIZE);
|
|
|
|
assembler.MOV(eventToCheck, CMIPS::A0);
|
|
|
|
assembler.ADDU(needClearInt, CMIPS::R0, CMIPS::R0);
|
|
|
|
|
|
|
|
//checkEvent
|
|
|
|
{
|
|
|
|
assembler.MarkLabel(checkEventLabel);
|
2018-04-30 21:01:23 +01:00
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//check if valid
|
|
|
|
assembler.LW(CMIPS::T0, offsetof(EVENT, isValid), currentEvent);
|
|
|
|
assembler.BEQ(CMIPS::T0, CMIPS::R0, doneEventLabel);
|
|
|
|
assembler.NOP();
|
2018-04-30 21:01:23 +01:00
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//check if good event class
|
|
|
|
assembler.LW(CMIPS::T0, offsetof(EVENT, classId), currentEvent);
|
|
|
|
assembler.BNE(CMIPS::T0, eventToCheck, doneEventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
//Tell that we need to clear interrupt later (experimental)
|
|
|
|
assembler.ADDIU(needClearInt, CMIPS::R0, 1);
|
|
|
|
|
|
|
|
//check if enabled
|
|
|
|
assembler.LW(CMIPS::T0, offsetof(EVENT, enabled), currentEvent);
|
|
|
|
assembler.BEQ(CMIPS::T0, CMIPS::R0, doneEventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
//Start handler if present
|
|
|
|
assembler.LW(CMIPS::T0, offsetof(EVENT, func), currentEvent);
|
|
|
|
assembler.BEQ(CMIPS::T0, CMIPS::R0, doneEventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
assembler.JALR(CMIPS::T0);
|
|
|
|
assembler.NOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
//doneEvent
|
|
|
|
assembler.MarkLabel(doneEventLabel);
|
|
|
|
assembler.ADDIU(currentEvent, currentEvent, sizeof(EVENT));
|
|
|
|
assembler.BNE(currentEvent, eventMax, checkEventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
//Result
|
|
|
|
assembler.ADDU(CMIPS::V0, needClearInt, CMIPS::R0);
|
|
|
|
|
|
|
|
//epilog
|
|
|
|
assembler.LW(CMIPS::RA, 0x00, CMIPS::SP);
|
|
|
|
assembler.LW(CMIPS::S0, 0x04, CMIPS::SP);
|
|
|
|
assembler.LW(CMIPS::S1, 0x08, CMIPS::SP);
|
|
|
|
assembler.LW(CMIPS::S2, 0x0C, CMIPS::SP);
|
|
|
|
assembler.LW(CMIPS::S3, 0x10, CMIPS::SP);
|
|
|
|
assembler.ADDIU(CMIPS::SP, CMIPS::SP, stackAlloc);
|
|
|
|
|
|
|
|
assembler.JR(CMIPS::RA);
|
|
|
|
assembler.NOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::AssembleInterruptHandler()
|
|
|
|
{
|
|
|
|
//Assemble interrupt handler
|
|
|
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(m_ram + INTR_HANDLER));
|
|
|
|
CMIPSAssembler::LABEL skipRootCounter2EventLabel = assembler.CreateLabel();
|
2012-10-26 06:15:10 +00:00
|
|
|
CMIPSAssembler::LABEL returnExceptionLabel = assembler.CreateLabel();
|
|
|
|
CMIPSAssembler::LABEL clearIntcCause = assembler.CreateLabel();
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
//Get cause
|
|
|
|
unsigned int cause = CMIPS::S3;
|
|
|
|
assembler.LI(CMIPS::T0, CIntc::STATUS0);
|
|
|
|
assembler.LW(CMIPS::T0, 0, CMIPS::T0);
|
|
|
|
assembler.LI(CMIPS::T1, CIntc::MASK0);
|
|
|
|
assembler.LW(CMIPS::T1, 0, CMIPS::T1);
|
|
|
|
assembler.AND(cause, CMIPS::T0, CMIPS::T1);
|
|
|
|
|
|
|
|
//Check if cause is root counter 2
|
|
|
|
assembler.ANDI(CMIPS::T0, cause, 0x40);
|
|
|
|
assembler.BEQ(CMIPS::T0, CMIPS::R0, skipRootCounter2EventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
assembler.LI(CMIPS::A0, EVENT_ID_RCNT2);
|
|
|
|
assembler.JAL(EVENT_CHECKER);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
assembler.BEQ(CMIPS::V0, CMIPS::R0, skipRootCounter2EventLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
2012-10-26 06:15:10 +00:00
|
|
|
//Clear root counter 2 cause
|
2008-12-24 02:03:58 +00:00
|
|
|
assembler.LI(CMIPS::T0, CIntc::STATUS0);
|
|
|
|
assembler.LI(CMIPS::T1, ~0x40);
|
|
|
|
assembler.SW(CMIPS::T1, 0, CMIPS::T0);
|
|
|
|
|
|
|
|
assembler.MarkLabel(skipRootCounter2EventLabel);
|
|
|
|
|
|
|
|
//checkIntHook
|
2018-02-04 15:21:24 -05:00
|
|
|
assembler.LI(CMIPS::T0, EXITFROMEXCEPTION_STATE_ADDR);
|
2008-12-24 02:03:58 +00:00
|
|
|
assembler.LW(CMIPS::T0, 0, CMIPS::T0);
|
2012-10-26 06:15:10 +00:00
|
|
|
assembler.BEQ(CMIPS::T0, CMIPS::R0, clearIntcCause);
|
2008-12-24 02:03:58 +00:00
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
//callIntHook
|
|
|
|
assembler.ADDIU(CMIPS::A0, CMIPS::T0, CMIPS::R0);
|
|
|
|
assembler.ADDIU(CMIPS::A1, CMIPS::R0, CMIPS::R0);
|
|
|
|
assembler.ADDIU(CMIPS::T0, CMIPS::R0, 0xA0);
|
|
|
|
assembler.ADDIU(CMIPS::T1, CMIPS::R0, 0x14);
|
|
|
|
assembler.JR(CMIPS::T0);
|
|
|
|
assembler.NOP();
|
2018-04-30 21:01:23 +01:00
|
|
|
|
2012-10-26 06:15:10 +00:00
|
|
|
assembler.BEQ(CMIPS::R0, CMIPS::R0, returnExceptionLabel);
|
|
|
|
assembler.NOP();
|
|
|
|
|
|
|
|
//Clear any interrupt that might have triggered this exception handler (to prevent infinite loop)
|
|
|
|
assembler.MarkLabel(clearIntcCause);
|
|
|
|
assembler.LI(CMIPS::T0, CIntc::STATUS0);
|
|
|
|
assembler.NOR(CMIPS::T1, CMIPS::R0, cause);
|
|
|
|
assembler.SW(CMIPS::T1, 0, CMIPS::T0);
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
//ReturnFromException
|
|
|
|
assembler.MarkLabel(returnExceptionLabel);
|
|
|
|
assembler.ADDIU(CMIPS::T0, CMIPS::R0, 0xB0);
|
|
|
|
assembler.ADDIU(CMIPS::T1, CMIPS::R0, 0x17);
|
|
|
|
assembler.JR(CMIPS::T0);
|
|
|
|
assembler.NOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::LongJump(uint32 bufferAddress, uint32 value)
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
bufferAddress = m_cpu.m_pAddrTranslator(&m_cpu, bufferAddress);
|
2008-12-24 02:03:58 +00:00
|
|
|
m_cpu.m_State.nGPR[CMIPS::RA].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x00));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::SP].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x04));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::FP].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x08));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S0].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x0C));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S1].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x10));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S2].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x14));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S3].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x18));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S4].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x1C));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S5].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x20));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S6].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x24));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::S7].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x28));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::GP].nD0 = static_cast<int32>(m_cpu.m_pMemoryMap->GetWord(bufferAddress + 0x2C));
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::V0].nD0 = value == 0 ? 1 : value;
|
|
|
|
}
|
|
|
|
|
2018-02-05 13:36:53 -05:00
|
|
|
CPsxBios::PROCESS* CPsxBios::GetProcess()
|
|
|
|
{
|
|
|
|
auto processCbTable = reinterpret_cast<CB_TABLE*>(m_ram + PCB_TABLE_ADDRESS);
|
|
|
|
assert(processCbTable->address != 0);
|
|
|
|
assert(processCbTable->size != 0);
|
|
|
|
|
|
|
|
return reinterpret_cast<PROCESS*>(m_ram + processCbTable->address);
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
void CPsxBios::SaveCpuState()
|
|
|
|
{
|
2018-02-05 13:36:53 -05:00
|
|
|
auto process = GetProcess();
|
|
|
|
assert(process->currentThreadControlBlockAddr != 0);
|
|
|
|
|
|
|
|
auto thread = reinterpret_cast<THREAD*>(m_ram + process->currentThreadControlBlockAddr);
|
|
|
|
assert(thread->status == THREAD_STATUS_ALLOCATED);
|
|
|
|
thread->pc = m_cpu.m_State.nPC;
|
|
|
|
for(uint32 i = 0; i < 32; i++)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
|
|
|
if(i == CMIPS::R0) continue;
|
|
|
|
if(i == CMIPS::K0) continue;
|
|
|
|
if(i == CMIPS::K1) continue;
|
2018-02-05 13:36:53 -05:00
|
|
|
thread->gpr[i] = m_cpu.m_State.nGPR[i].nV0;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
2018-02-05 13:36:53 -05:00
|
|
|
thread->sr = m_cpu.m_State.nCOP0[CCOP_SCU::STATUS];
|
|
|
|
thread->sr &= ~(CMIPS::STATUS_EXL | CMIPS::STATUS_ERL);
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::LoadCpuState()
|
|
|
|
{
|
2018-02-05 13:36:53 -05:00
|
|
|
auto process = GetProcess();
|
|
|
|
assert(process->currentThreadControlBlockAddr != 0);
|
|
|
|
|
|
|
|
auto thread = reinterpret_cast<THREAD*>(m_ram + process->currentThreadControlBlockAddr);
|
|
|
|
assert(thread->status == THREAD_STATUS_ALLOCATED);
|
|
|
|
m_cpu.m_State.nPC = thread->pc;
|
|
|
|
for(uint32 i = 0; i < 32; i++)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
|
|
|
if(i == CMIPS::R0) continue;
|
|
|
|
if(i == CMIPS::K0) continue;
|
|
|
|
if(i == CMIPS::K1) continue;
|
2018-02-05 13:36:53 -05:00
|
|
|
m_cpu.m_State.nGPR[i].nV0 = thread->gpr[i];
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
2018-02-05 13:36:53 -05:00
|
|
|
m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] = thread->sr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CPsxBios::AllocateSysMemory(uint32 size)
|
|
|
|
{
|
|
|
|
assert((m_sysHeapPointerAddr + size) <= (HEAP_START + HEAP_SIZE));
|
|
|
|
uint32 result = m_sysHeapPointerAddr;
|
|
|
|
m_sysHeapPointerAddr += size;
|
|
|
|
return result;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::HandleInterrupt()
|
|
|
|
{
|
2018-02-05 13:36:53 -05:00
|
|
|
if(m_cpu.GenerateInterrupt(m_cpu.m_State.nPC))
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
|
|
|
SaveCpuState();
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 status = m_cpu.m_pMemoryMap->GetWord(CIntc::STATUS0);
|
|
|
|
uint32 mask = m_cpu.m_pMemoryMap->GetWord(CIntc::MASK0);
|
2008-12-24 02:03:58 +00:00
|
|
|
uint32 cause = status & mask;
|
|
|
|
for(unsigned int i = 1; i <= MAX_EVENT; i++)
|
|
|
|
{
|
|
|
|
EVENT* eventPtr = m_events[i];
|
|
|
|
if(eventPtr == NULL) continue;
|
2018-02-04 11:34:17 -05:00
|
|
|
if((cause & (1 << CIntc::LINE_DMAC)) && eventPtr->classId == 0xF0000009)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2012-10-26 06:15:10 +00:00
|
|
|
eventPtr->fired = 1;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
m_cpu.m_State.nPC = INTR_HANDLER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::HandleException()
|
|
|
|
{
|
|
|
|
assert(m_cpu.m_State.nHasException);
|
2022-10-26 11:31:45 -04:00
|
|
|
uint32 searchAddress = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nCOP0[CCOP_SCU::EPC]);
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 callInstruction = m_cpu.m_pMemoryMap->GetWord(searchAddress);
|
|
|
|
if(callInstruction != 0x0000000C)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Not a SYSCALL.");
|
|
|
|
}
|
2008-12-24 02:03:58 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
DisassembleSyscall(searchAddress);
|
|
|
|
#endif
|
|
|
|
if(searchAddress == 0xA0)
|
|
|
|
{
|
|
|
|
ProcessSubFunction(m_handlerA0, MAX_HANDLER_A0);
|
|
|
|
}
|
|
|
|
else if(searchAddress == 0xB0)
|
|
|
|
{
|
|
|
|
ProcessSubFunction(m_handlerB0, MAX_HANDLER_B0);
|
|
|
|
}
|
|
|
|
else if(searchAddress == 0xC0)
|
|
|
|
{
|
|
|
|
ProcessSubFunction(m_handlerC0, MAX_HANDLER_C0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::A0].nV0;
|
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 0x01:
|
|
|
|
sc_EnterCriticalSection();
|
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
sc_ExitCriticalSection();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sc_Illegal();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_cpu.m_State.nHasException = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::ProcessSubFunction(SyscallHandler* handlerTable, unsigned int handlerTableLength)
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::T1].nV0;
|
|
|
|
if(functionId >= handlerTableLength)
|
|
|
|
{
|
|
|
|
sc_Illegal();
|
|
|
|
}
|
|
|
|
functionId %= handlerTableLength;
|
|
|
|
((this)->*(handlerTable[functionId]))();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::DisassembleSyscall(uint32 searchAddress)
|
|
|
|
{
|
|
|
|
if(searchAddress == 0x00A0)
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::T1].nV0;
|
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 0x13:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "setjmp(buffer = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x14:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "longjmp(buffer = 0x%0.8X, value = %i);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x19:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "strcpy(dst = 0x%0.8X, src = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x28:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "bzero(address = 0x%0.8X, length = 0x%x);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2011-06-06 00:18:33 +00:00
|
|
|
case 0x2A:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "memcpy(dst = 0x%0.8X, src = 0x%0.8X, length = 0x%x);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM2].nV0);
|
2011-06-06 00:18:33 +00:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x2B:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "memset(address = 0x%0.8X, value = 0x%x, length = 0x%x);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM2].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2011-06-06 00:18:33 +00:00
|
|
|
case 0x2F:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "rand();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x30:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "srand(seed = %d);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2011-06-06 00:18:33 +00:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x39:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "InitHeap(block = 0x%0.8X, n = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x3F:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "printf(fmt = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x44:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "FlushCache();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x70:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "_bu_init();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x72:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "_96_remove();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x9F:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SetMem(size = %i);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Unknown system call encountered (0xA0, 0x%X).\r\n", functionId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(searchAddress == 0x00B0)
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::T1].nV0;
|
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 0x00:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SysMalloc(size = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "DeliverEvent(class = 0x%X, event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x08:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "OpenEvent(class = 0x%X, spec = 0x%X, mode = 0x%X, func = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM2].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM3].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2011-06-06 00:18:33 +00:00
|
|
|
case 0x09:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "CloseEvent(event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2011-06-06 00:18:33 +00:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x0A:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "WaitEvent(event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x0B:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "TestEvent(event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x0C:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "EnableEvent(event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x0D:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "DisableEvent(event = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2018-02-06 12:56:46 -05:00
|
|
|
case 0x0E:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "OpenThread(pc = 0x%08X, sp = 0x%08X, gp = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM2].nV0);
|
2018-02-06 12:56:46 -05:00
|
|
|
break;
|
|
|
|
case 0x10:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ChangeThread(threadId = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2018-02-06 12:56:46 -05:00
|
|
|
break;
|
2012-10-26 06:15:10 +00:00
|
|
|
case 0x14:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StopPAD();\r\n");
|
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x16:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "PAD_dr();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x17:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ReturnFromException();\r\n");
|
|
|
|
break;
|
2018-02-06 12:17:42 -05:00
|
|
|
case 0x18:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SetDefaultExitFromException();\r\n");
|
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x19:
|
2018-02-04 15:21:24 -05:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SetCustomExitFromException(stateAddress = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2011-06-06 00:18:33 +00:00
|
|
|
case 0x3F:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "puts(s = 0x%0.8X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2011-06-06 00:18:33 +00:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x4A:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "InitCARD();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x4B:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StartCARD();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x56:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetC0Table();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x57:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetB0Table();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x5B:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ChangeClearPad(param = %i);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Unknown system call encountered (0xB0, 0x%X).\r\n", functionId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(searchAddress == 0x00C0)
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::T1].nV0;
|
|
|
|
switch(functionId)
|
|
|
|
{
|
2018-02-06 18:40:36 -05:00
|
|
|
case 0x00:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "EnqueueTimerAndVblankIrqs(priority = %d);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2018-02-06 18:40:36 -05:00
|
|
|
break;
|
|
|
|
case 0x01:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "EnqueueSyscallHandler(priority = %d);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2018-02-06 18:40:36 -05:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
case 0x03:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SysDeqIntRP(index = %i, queue = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x08:
|
2018-02-05 12:47:49 -05:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SysInitMemory(address = 0x%08X, size = 0x%X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
|
|
|
case 0x0A:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ChangeClearRCnt(param0 = %i, param1 = %i);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0,
|
|
|
|
m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
break;
|
2018-02-06 18:40:36 -05:00
|
|
|
case 0x0C:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "InitDefInt(priority = %d);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2018-02-06 18:40:36 -05:00
|
|
|
break;
|
2008-12-24 02:03:58 +00:00
|
|
|
default:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Unknown system call encountered (0xC0, 0x%X).\r\n", functionId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32 functionId = m_cpu.m_State.nGPR[CMIPS::A0].nV0;
|
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 0x01:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "EnterCriticalSection();\r\n");
|
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ExitCriticalSection();\r\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Unknown system call encountered.\r\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 13
|
|
|
|
void CPsxBios::sc_setjmp()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 bufferAddress = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x00, m_cpu.m_State.nGPR[CMIPS::RA].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x04, m_cpu.m_State.nGPR[CMIPS::SP].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x08, m_cpu.m_State.nGPR[CMIPS::FP].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x0C, m_cpu.m_State.nGPR[CMIPS::S0].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x10, m_cpu.m_State.nGPR[CMIPS::S1].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x14, m_cpu.m_State.nGPR[CMIPS::S2].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x18, m_cpu.m_State.nGPR[CMIPS::S3].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x1C, m_cpu.m_State.nGPR[CMIPS::S4].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x20, m_cpu.m_State.nGPR[CMIPS::S5].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x24, m_cpu.m_State.nGPR[CMIPS::S6].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x28, m_cpu.m_State.nGPR[CMIPS::S7].nV0);
|
|
|
|
m_cpu.m_pMemoryMap->SetWord(bufferAddress + 0x2C, m_cpu.m_State.nGPR[CMIPS::GP].nV0);
|
|
|
|
m_cpu.m_State.nGPR[CMIPS::V0].nD0 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 14
|
|
|
|
void CPsxBios::sc_longjmp()
|
|
|
|
{
|
|
|
|
uint32 buffer = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 value = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
LongJump(buffer, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 19
|
|
|
|
void CPsxBios::sc_strcpy()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 dst = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
|
|
|
uint32 src = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
strcpy(
|
2018-04-30 21:01:23 +01:00
|
|
|
reinterpret_cast<char*>(m_ram + dst),
|
|
|
|
reinterpret_cast<char*>(m_ram + src));
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nV0 = dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 28
|
|
|
|
void CPsxBios::sc_bzero()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 address = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
uint32 length = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
if((address + length) > m_ramSize)
|
|
|
|
{
|
2011-06-06 00:18:33 +00:00
|
|
|
throw std::exception();
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
memset(m_ram + address, 0, length);
|
|
|
|
}
|
|
|
|
|
2011-06-06 00:18:33 +00:00
|
|
|
//A0 - 2A
|
|
|
|
void CPsxBios::sc_memcpy()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 dst = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
|
|
|
uint32 src = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
2011-06-06 00:18:33 +00:00
|
|
|
uint32 length = m_cpu.m_State.nGPR[SC_PARAM2].nV0;
|
|
|
|
|
|
|
|
memcpy(m_ram + dst, m_ram + src, length);
|
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nV0 = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//A0 - 2B
|
|
|
|
void CPsxBios::sc_memset()
|
|
|
|
{
|
2012-05-26 18:31:31 +00:00
|
|
|
uint32 address = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nGPR[SC_PARAM0].nV0);
|
2008-12-24 02:03:58 +00:00
|
|
|
uint8 value = static_cast<uint8>(m_cpu.m_State.nGPR[SC_PARAM1].nV0);
|
|
|
|
uint32 length = m_cpu.m_State.nGPR[SC_PARAM2].nV0;
|
|
|
|
if((address + length) > m_ramSize)
|
|
|
|
{
|
2011-06-06 00:18:33 +00:00
|
|
|
throw std::exception();
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
memset(m_ram + address, value, length);
|
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nV0 = address;
|
|
|
|
}
|
|
|
|
|
2011-06-06 00:18:33 +00:00
|
|
|
//A0 - 2F
|
|
|
|
void CPsxBios::sc_rand()
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nV0 = rand();
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 30
|
|
|
|
void CPsxBios::sc_srand()
|
|
|
|
{
|
|
|
|
uint32 seed = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
srand(seed);
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//A0 - 39
|
|
|
|
void CPsxBios::sc_InitHeap()
|
|
|
|
{
|
|
|
|
uint32 block = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 n = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 3F
|
|
|
|
void CPsxBios::sc_printf()
|
|
|
|
{
|
|
|
|
uint32 formatAddress = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 44
|
|
|
|
void CPsxBios::sc_FlushCache()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 70
|
|
|
|
void CPsxBios::sc_bu_init()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 72
|
|
|
|
void CPsxBios::sc_96_remove()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//A0 - 9F
|
|
|
|
void CPsxBios::sc_SetMem()
|
|
|
|
{
|
|
|
|
uint32 n = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 00
|
|
|
|
void CPsxBios::sc_SysMalloc()
|
|
|
|
{
|
2018-02-05 13:36:53 -05:00
|
|
|
uint32 size = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 result = AllocateSysMemory(size);
|
2018-02-05 12:47:49 -05:00
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nV0 = result;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 07
|
|
|
|
void CPsxBios::sc_DeliverEvent()
|
|
|
|
{
|
|
|
|
uint32 classId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 08
|
|
|
|
void CPsxBios::sc_OpenEvent()
|
|
|
|
{
|
|
|
|
uint32 classId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 spec = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
uint32 mode = m_cpu.m_State.nGPR[SC_PARAM2].nV0;
|
|
|
|
uint32 func = m_cpu.m_State.nGPR[SC_PARAM3].nV0;
|
|
|
|
|
|
|
|
uint32 eventId = m_events.Allocate();
|
|
|
|
if(eventId == -1)
|
|
|
|
{
|
2011-06-06 00:18:33 +00:00
|
|
|
throw std::exception();
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
EVENT* eventPtr = m_events[eventId];
|
2018-04-30 21:01:23 +01:00
|
|
|
eventPtr->classId = classId;
|
|
|
|
eventPtr->spec = spec;
|
|
|
|
eventPtr->mode = mode;
|
|
|
|
eventPtr->func = func;
|
|
|
|
eventPtr->fired = 0;
|
2008-12-24 02:03:58 +00:00
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = static_cast<int32>(eventId);
|
|
|
|
}
|
|
|
|
|
2011-06-06 00:18:33 +00:00
|
|
|
//B0 - 09
|
|
|
|
void CPsxBios::sc_CloseEvent()
|
|
|
|
{
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
EVENT* eventPtr = m_events[eventId];
|
|
|
|
if(eventPtr != NULL)
|
|
|
|
{
|
|
|
|
m_events.Free(eventId);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//B0 - 0A
|
|
|
|
void CPsxBios::sc_WaitEvent()
|
|
|
|
{
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
2018-02-06 18:49:30 -05:00
|
|
|
auto event = m_events[eventId];
|
|
|
|
if(!event)
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(event->fired);
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 0B
|
|
|
|
void CPsxBios::sc_TestEvent()
|
|
|
|
{
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
2018-04-07 09:53:25 -04:00
|
|
|
auto eventPtr = m_events[eventId];
|
|
|
|
|
|
|
|
assert(eventPtr);
|
|
|
|
if(!eventPtr)
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2018-04-07 09:53:25 -04:00
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = 0;
|
|
|
|
return;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
2018-04-07 09:53:25 -04:00
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = eventPtr->fired;
|
|
|
|
eventPtr->fired = 0;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 0C
|
|
|
|
void CPsxBios::sc_EnableEvent()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
EVENT* eventPtr = m_events[eventId];
|
|
|
|
if(eventPtr != NULL)
|
|
|
|
{
|
|
|
|
eventPtr->enabled = true;
|
|
|
|
eventPtr->fired = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 0D
|
|
|
|
void CPsxBios::sc_DisableEvent()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
uint32 eventId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
EVENT* eventPtr = m_events[eventId];
|
|
|
|
if(eventPtr != NULL)
|
|
|
|
{
|
|
|
|
eventPtr->enabled = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 12:56:46 -05:00
|
|
|
//B0 - 0E
|
|
|
|
void CPsxBios::sc_OpenThread()
|
|
|
|
{
|
|
|
|
uint32 threadPc = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 threadSp = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
uint32 threadGp = m_cpu.m_State.nGPR[SC_PARAM2].nV0;
|
|
|
|
|
|
|
|
auto threadCbTable = reinterpret_cast<CB_TABLE*>(m_ram + TCB_TABLE_ADDRESS);
|
|
|
|
assert(threadCbTable->address != 0);
|
|
|
|
assert(threadCbTable->size != 0);
|
|
|
|
assert((threadCbTable->size % sizeof(THREAD)) == 0);
|
|
|
|
|
|
|
|
auto threads = reinterpret_cast<THREAD*>(m_ram + threadCbTable->address);
|
|
|
|
auto threadCount = threadCbTable->size / sizeof(THREAD);
|
|
|
|
|
|
|
|
uint32 threadId = -1;
|
|
|
|
for(uint32 i = 0; i < threadCount; i++)
|
|
|
|
{
|
|
|
|
auto thread = &threads[i];
|
|
|
|
if(thread->status == THREAD_STATUS_ALLOCATED) continue;
|
|
|
|
assert(thread->status == THREAD_STATUS_FREE);
|
|
|
|
threadId = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(threadId == -1)
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto thread = &threads[threadId];
|
|
|
|
thread->status = THREAD_STATUS_ALLOCATED;
|
|
|
|
thread->pc = threadPc;
|
|
|
|
thread->gpr[CMIPS::SP] = threadSp;
|
|
|
|
thread->gpr[CMIPS::FP] = threadSp;
|
|
|
|
thread->gpr[CMIPS::GP] = threadGp;
|
|
|
|
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = threadId;
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 10
|
|
|
|
void CPsxBios::sc_ChangeThread()
|
|
|
|
{
|
|
|
|
uint32 threadId = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = 1;
|
|
|
|
|
|
|
|
SaveCpuState();
|
|
|
|
|
|
|
|
//Update current thread id
|
|
|
|
{
|
|
|
|
auto process = GetProcess();
|
|
|
|
|
|
|
|
auto threadCbTable = reinterpret_cast<CB_TABLE*>(m_ram + TCB_TABLE_ADDRESS);
|
|
|
|
assert(threadCbTable->address != 0);
|
|
|
|
assert(threadCbTable->size != 0);
|
|
|
|
assert((threadCbTable->size % sizeof(THREAD)) == 0);
|
|
|
|
|
|
|
|
auto threadCount = threadCbTable->size / sizeof(THREAD);
|
|
|
|
assert(threadId < threadCount);
|
|
|
|
|
|
|
|
process->currentThreadControlBlockAddr = threadCbTable->address + threadId * sizeof(THREAD);
|
|
|
|
}
|
|
|
|
|
|
|
|
LoadCpuState();
|
|
|
|
}
|
|
|
|
|
2012-10-26 06:15:10 +00:00
|
|
|
//B0 - 14
|
|
|
|
void CPsxBios::sc_StopPAD()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//B0 - 16
|
|
|
|
void CPsxBios::sc_PAD_dr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 17
|
|
|
|
void CPsxBios::sc_ReturnFromException()
|
|
|
|
{
|
|
|
|
uint32& status = m_cpu.m_State.nCOP0[CCOP_SCU::STATUS];
|
|
|
|
assert(status & (CMIPS::STATUS_ERL | CMIPS::STATUS_EXL));
|
|
|
|
if(status & CMIPS::STATUS_ERL)
|
|
|
|
{
|
|
|
|
status &= ~CMIPS::STATUS_ERL;
|
|
|
|
}
|
|
|
|
else if(status & CMIPS::STATUS_EXL)
|
|
|
|
{
|
|
|
|
status &= ~CMIPS::STATUS_EXL;
|
|
|
|
}
|
|
|
|
LoadCpuState();
|
|
|
|
}
|
|
|
|
|
2018-02-06 12:17:42 -05:00
|
|
|
//B0 - 18
|
|
|
|
void CPsxBios::sc_SetDefaultExitFromException()
|
|
|
|
{
|
|
|
|
m_exitFromExceptionStateAddr = 0;
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//B0 - 19
|
2018-02-04 15:21:24 -05:00
|
|
|
void CPsxBios::sc_SetCustomExitFromException()
|
2008-12-24 02:03:58 +00:00
|
|
|
{
|
2018-02-04 15:21:24 -05:00
|
|
|
uint32 stateAddr = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
m_exitFromExceptionStateAddr = stateAddr;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
2011-06-06 00:18:33 +00:00
|
|
|
//B0 - 3F
|
|
|
|
void CPsxBios::sc_puts()
|
|
|
|
{
|
|
|
|
uint32 stringAddress = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//B0 - 4A
|
|
|
|
void CPsxBios::sc_InitCARD()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 4B
|
|
|
|
void CPsxBios::sc_StartCARD()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 56
|
|
|
|
void CPsxBios::sc_GetC0Table()
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = static_cast<int32>(C0TABLE_BEGIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 57
|
|
|
|
void CPsxBios::sc_GetB0Table()
|
|
|
|
{
|
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = static_cast<int32>(B0TABLE_BEGIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
//B0 - 5B
|
|
|
|
void CPsxBios::sc_ChangeClearPad()
|
|
|
|
{
|
|
|
|
uint32 param = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
}
|
|
|
|
|
2018-02-06 18:40:36 -05:00
|
|
|
//C0 - 00
|
|
|
|
void CPsxBios::sc_EnqueueTimerAndVblankIrqs()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//C0 - 01
|
|
|
|
void CPsxBios::sc_EnqueueSyscallHandler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
//C0 - 03
|
|
|
|
void CPsxBios::sc_SysDeqIntRP()
|
|
|
|
{
|
|
|
|
uint32 index = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 queue = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//C0 - 08
|
|
|
|
void CPsxBios::sc_SysInitMemory()
|
|
|
|
{
|
2018-02-05 12:47:49 -05:00
|
|
|
//Two parameters are passed, but don't seem to be used somehow?
|
|
|
|
//TODO: Reset PCB and TCB addresses
|
|
|
|
m_sysHeapPointerAddr = HEAP_START;
|
|
|
|
memset(m_ram + HEAP_START, 0, HEAP_SIZE);
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//C0 - 0A
|
|
|
|
void CPsxBios::sc_ChangeClearRCnt()
|
|
|
|
{
|
|
|
|
uint32 param0 = m_cpu.m_State.nGPR[SC_PARAM0].nV0;
|
|
|
|
uint32 param1 = m_cpu.m_State.nGPR[SC_PARAM1].nV0;
|
|
|
|
}
|
|
|
|
|
2018-02-06 18:40:36 -05:00
|
|
|
//C0 - 0C
|
|
|
|
void CPsxBios::sc_InitDefInt()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-12-24 02:03:58 +00:00
|
|
|
void CPsxBios::sc_EnterCriticalSection()
|
|
|
|
{
|
2018-02-06 18:34:31 -05:00
|
|
|
bool isIntEnabled = (m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] & CMIPS::STATUS_IE) != 0;
|
|
|
|
m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] &= ~CMIPS::STATUS_IE;
|
2018-04-30 21:01:23 +01:00
|
|
|
|
2018-02-06 18:34:31 -05:00
|
|
|
m_cpu.m_State.nGPR[SC_RETURN].nD0 = static_cast<int32>(isIntEnabled ? 1 : 0);
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::sc_ExitCriticalSection()
|
|
|
|
{
|
2018-02-06 18:34:31 -05:00
|
|
|
m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] |= CMIPS::STATUS_IE;
|
2008-12-24 02:03:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPsxBios::sc_Illegal()
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
2011-06-06 00:18:33 +00:00
|
|
|
throw std::runtime_error("Illegal system call.");
|
2008-12-24 02:03:58 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-04-30 11:19:06 -04:00
|
|
|
// clang-format off
|
2008-12-24 02:03:58 +00:00
|
|
|
CPsxBios::SyscallHandler CPsxBios::m_handlerA0[MAX_HANDLER_A0] =
|
|
|
|
{
|
|
|
|
//0x00
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x08
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x10
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_setjmp, &CPsxBios::sc_longjmp, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x18
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_strcpy, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x20
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x28
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_bzero, &CPsxBios::sc_Illegal, &CPsxBios::sc_memcpy, &CPsxBios::sc_memset, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_rand,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x30
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_srand, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x38
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_InitHeap, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_printf,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x40
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_FlushCache, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x48
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x50
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x58
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x60
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x68
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x70
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_bu_init, &CPsxBios::sc_Illegal, &CPsxBios::sc_96_remove, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x78
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x80
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x88
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x90
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x98
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_SetMem,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xA0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xA8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xB0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xB8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xC0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xC8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xD0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xD8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xE0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xE8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xF0
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0xF8
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal
|
2008-12-24 02:03:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
CPsxBios::SyscallHandler CPsxBios::m_handlerB0[MAX_HANDLER_B0] =
|
|
|
|
{
|
|
|
|
//0x00
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_SysMalloc, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_DeliverEvent,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x08
|
2018-02-06 12:56:46 -05:00
|
|
|
&CPsxBios::sc_OpenEvent, &CPsxBios::sc_CloseEvent, &CPsxBios::sc_WaitEvent, &CPsxBios::sc_TestEvent, &CPsxBios::sc_EnableEvent, &CPsxBios::sc_DisableEvent, &CPsxBios::sc_OpenThread, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x10
|
2018-02-06 12:56:46 -05:00
|
|
|
&CPsxBios::sc_ChangeThread, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_StopPAD, &CPsxBios::sc_Illegal, &CPsxBios::sc_PAD_dr, &CPsxBios::sc_ReturnFromException,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x18
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_SetDefaultExitFromException, &CPsxBios::sc_SetCustomExitFromException, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x20
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x28
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x30
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x38
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_puts,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x40
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x48
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_InitCARD, &CPsxBios::sc_StartCARD, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x50
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_GetC0Table, &CPsxBios::sc_GetB0Table,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x58
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_ChangeClearPad, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x60
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x68
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x70
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x78
|
2018-02-06 12:40:23 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal
|
2008-12-24 02:03:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
CPsxBios::SyscallHandler CPsxBios::m_handlerC0[MAX_HANDLER_C0] =
|
|
|
|
{
|
|
|
|
//0x00
|
2018-02-06 18:40:36 -05:00
|
|
|
&CPsxBios::sc_EnqueueTimerAndVblankIrqs, &CPsxBios::sc_EnqueueSyscallHandler, &CPsxBios::sc_Illegal, &CPsxBios::sc_SysDeqIntRP, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x08
|
2018-02-06 18:40:36 -05:00
|
|
|
&CPsxBios::sc_SysInitMemory, &CPsxBios::sc_Illegal, &CPsxBios::sc_ChangeClearRCnt, &CPsxBios::sc_Illegal, &CPsxBios::sc_InitDefInt, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x10
|
2018-02-06 18:40:36 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal,
|
2008-12-24 02:03:58 +00:00
|
|
|
//0x18
|
2018-02-06 18:40:36 -05:00
|
|
|
&CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal, &CPsxBios::sc_Illegal
|
2008-12-24 02:03:58 +00:00
|
|
|
};
|
2018-04-30 11:19:06 -04:00
|
|
|
// clang-format on
|