Added SeekL (might be broken atm) and sideloading of executables

This commit is contained in:
liuk7071 2023-09-19 18:47:23 +02:00
parent fc2155a208
commit ee070d73d4
12 changed files with 130 additions and 41 deletions

View file

@ -35,6 +35,25 @@ void CDROM::executeCommand(u8 data) {
break;
}
case CDROMCommands::SeekL: {
// TODO: SeekL/P should stop ongoing reads
// First response doesn't have seeking bit set
response.push(statusCode.raw);
statusCode.seeking = true;
secondResponse.push(statusCode.raw);
scheduler->push(&int3, scheduler->time + int3Delay, this);
scheduler->push(&int2, scheduler->time + int3Delay + int2Delay, this);
// Seek time is currently stubbed to 150k cycles
scheduler->push(&stopSeeking, scheduler->time + seekTime, this);
log("SeekL\n");
break;
}
case CDROMCommands::Test: {
u8 subFunc = getParamByte();
switch (subFunc) {
@ -46,12 +65,12 @@ void CDROM::executeCommand(u8 data) {
break;
}
default:
Helpers::panic("[FATAL] Unimplemented CDROM test subfunc 0x%02x\n", subFunc);
Helpers::panic("[ FATAL ] Unimplemented CDROM test subfunc 0x%02x\n", subFunc);
}
scheduler->push(&int3, scheduler->time + int3Delay, this);
log("Test\n", statusCode.raw);
log("Test\n");
break;
}
@ -83,15 +102,15 @@ void CDROM::executeCommand(u8 data) {
scheduler->push(&int3, scheduler->time + int3Delay, this);
scheduler->push(&int2, scheduler->time + int3Delay + getIDDelay, this);
log("GetID\n", statusCode.raw);
log("GetID\n");
break;
}
default:
Helpers::panic("[FATAL] Unimplemented CDROM command 0x%02x\n", data);
Helpers::panic("[ FATAL ] Unimplemented CDROM command 0x%02x\n", data);
}
Helpers::debugAssert(params.size() == 0, "[FATAL] CDROM command did not use all parameters");
Helpers::debugAssert(params.size() == 0, "[ FATAL ] CDROM command did not use all parameters");
statusReg.rslrrdy = 1; // Response fifo not empty
statusReg.prmempt = 1; // Parameter fifo empty
@ -104,43 +123,57 @@ bool CDROM::shouldFireIRQ() {
void CDROM::int2(void* classptr) {
CDROM* cdrom = (CDROM*)classptr;
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[FATAL] CDROM INT2 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[ FATAL ] CDROM INT2 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
cdrom->intFlag |= 2;
// Second response
if (cdrom->secondResponse.size()) {
Helpers::debugAssert(!cdrom->response.size(), "[FATAL] CDROM INT2 before first response was read (probably not supposed to happen...?");
Helpers::debugAssert(!cdrom->response.size(), "[ FATAL ] CDROM INT2 before first response was read (probably not supposed to happen...?");
cdrom->response = cdrom->secondResponse;
cdrom->statusReg.rslrrdy = 1; // Response fifo not empty
while (cdrom->secondResponse.size()) cdrom->secondResponse.pop();
log("---INT2\n");
}
else
log("INT2\n");
}
void CDROM::int3(void* classptr) {
CDROM* cdrom = (CDROM*)classptr;
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[FATAL] CDROM INT3 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[ FATAL ] CDROM INT3 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
cdrom->intFlag |= 3;
log("-INT3\n");
}
void CDROM::int5(void* classptr) {
CDROM* cdrom = (CDROM*)classptr;
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[FATAL] CDROM INT5 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[ FATAL ] CDROM INT5 was fired before previous INT%d was acknowledged in interrupt flag\n", cdrom->intFlag & 3);
cdrom->intFlag |= 5;
// Second response
if (cdrom->secondResponse.size()) {
Helpers::debugAssert(!cdrom->response.size(), "[FATAL] CDROM INT5 before first response was read (probably not supposed to happen...?");
Helpers::debugAssert(!cdrom->response.size(), "[ FATAL ] CDROM INT5 before first response was read (probably not supposed to happen...?");
cdrom->response = cdrom->secondResponse;
cdrom->statusReg.rslrrdy = 1; // Response fifo not empty
while (cdrom->secondResponse.size()) cdrom->secondResponse.pop();
log("---INT5\n");
}
else
log("INT5\n");
}
void CDROM::stopSeeking(void* classptr) {
CDROM* cdrom = (CDROM*)classptr;
cdrom->statusCode.seeking = false;
log("Seek ended\n");
}
void CDROM::pushParam(u8 data) {
params.push(data);
Helpers::debugAssert(params.size() <= 16, "[FATAL] Wrote more than 16 bytes to CDROM parameter fifo");
Helpers::debugAssert(params.size() <= 16, "[ FATAL ] Wrote more than 16 bytes to CDROM parameter fifo");
if (params.size() == 16) {
statusReg.prmwrdy = 0; // Parameter fifo full
}

View file

@ -13,8 +13,10 @@ constexpr u64 readDelayDoubleSpeed = readDelay / 2;
// I don't know if these are ok?????
constexpr u64 int3Delay = cpuSpeed / 1000;
constexpr u64 int2Delay = int3Delay * 2;
constexpr u64 getIDDelay = 33868;
constexpr u64 seekTime = 150000; // Currently stubbed seeking time to this for all seeks
class CDROM {
public:
@ -30,6 +32,8 @@ public:
static void int3(void* classptr);
static void int5(void* classptr);
static void stopSeeking(void* classptr);
void pushParam(u8 data);
u8 readStatus();
@ -83,6 +87,7 @@ namespace CDROMCommands {
enum {
GetStat = 0x01,
SetLoc = 0x02,
SeekL = 0x15,
Test = 0x19,
GetID = 0x1A
};

View file

@ -188,7 +188,7 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
break;
}
default:
Helpers::panic("[FATAL] Unimplemented secondary instruction 0x%02x (raw: 0x%08x)\n", instr.secondaryOpc.Value(), instr.raw);
Helpers::panic("[ FATAL ] Unimplemented secondary instruction 0x%02x (raw: 0x%08x)\n", instr.secondaryOpc.Value(), instr.raw);
}
break;
}
@ -225,7 +225,7 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
break;
}
default:
Helpers::panic("[FATAL] Invalid REGIMM instruction 0x%02x (raw: 0x%08x)\n", instr.regimmOpc.Value(), instr.raw);
Helpers::panic("[ FATAL ] Invalid REGIMM instruction 0x%02x (raw: 0x%08x)\n", instr.regimmOpc.Value(), instr.raw);
}
break;
}
@ -318,12 +318,12 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
break;
}
default:
Helpers::panic("[FATAL] Invalid cop0 instruction 0x%02 (raw:0x%08x)\n", instr.func.Value(), instr.raw);
Helpers::panic("[ FATAL ] Invalid cop0 instruction 0x%02 (raw:0x%08x)\n", instr.func.Value(), instr.raw);
}
break;
}
default:
Helpers::panic("[FATAL] Unimplemented cop instruction 0x%02x (raw: 0x%08x)\n", instr.cop0Opc.Value(), instr.raw);
Helpers::panic("[ FATAL ] Unimplemented cop instruction 0x%02x (raw: 0x%08x)\n", instr.cop0Opc.Value(), instr.raw);
}
break;
}
@ -426,7 +426,7 @@ void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
break;
}
default:
Helpers::panic("[FATAL] Unimplemented primary instruction 0x%02x (raw: 0x%08x)\n", instr.primaryOpc.Value(), instr.raw);
Helpers::panic("[ FATAL ] Unimplemented primary instruction 0x%02x (raw: 0x%08x)\n", instr.primaryOpc.Value(), instr.raw);
}
core->isDelaySlot = false;

View file

@ -34,6 +34,9 @@ bool delay = false;
#define log_kernel_tty
void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
// Handle interrupts
core->checkInterrupt(mem->interrupt);
const auto instr = mem->read<u32>(core->pc);
disassembler->disassemble({ .raw = instr }, core);

View file

@ -82,6 +82,7 @@ struct COP0 {
case (u32)COP0Reg::Status: return status.raw;
case (u32)COP0Reg::Cause: return cause.raw;
case (u32)COP0Reg::EPC: return epc;
case (u32)COP0Reg::PRId: return 2;
default:
Helpers::panic("Unimplemented cop0 register read cop0r%d\n", cop0r);
}

View file

@ -62,7 +62,7 @@ void DMA::gpuDMA(Memory* memory) {
break;
}
case (u32)SyncMode::LinkedList: {
Helpers::debugAssert(ch.chcr.dir == (u32)Direction::ToDevice, "[FATAL] GPU LinkedList with direction ToRam");
Helpers::debugAssert(ch.chcr.dir == (u32)Direction::ToDevice, "[ FATAL ] GPU LinkedList with direction ToRam");
u32 header = 0;
u32 words = 0;

View file

@ -10,17 +10,17 @@ class GPU;
class GPUBackend {
public:
GPUBackend(GPU* gpu) : gpu(gpu) {}
virtual void reset() { Helpers::panic("[FATAL] GPU Backend did not define reset function\n"); };
virtual u8* getVRAM() { Helpers::panic("[FATAL] GPU Backend did not define getVRAM function\n"); };
virtual void reset() { Helpers::panic("[ FATAL ] GPU Backend did not define reset function\n"); };
virtual u8* getVRAM() { Helpers::panic("[ FATAL ] GPU Backend did not define getVRAM function\n"); };
// Drawing
virtual void drawTriUntextured(Vertex v0, Vertex v1, Vertex v2) { Helpers::panic("[FATAL] GPU Backend did not define drawTriUntextured function\n"); }
virtual void drawTriTextured(Vertex v0, Vertex v1, Vertex v2, u16 clut, u16 texpage) { Helpers::panic("[FATAL] GPU Backend did not define drawTriTextured function\n"); }
virtual void drawTriUntextured(Vertex v0, Vertex v1, Vertex v2) { Helpers::panic("[ FATAL ] GPU Backend did not define drawTriUntextured function\n"); }
virtual void drawTriTextured(Vertex v0, Vertex v1, Vertex v2, u16 clut, u16 texpage) { Helpers::panic("[ FATAL ] GPU Backend did not define drawTriTextured function\n"); }
// Textures
virtual void beginTextureUpload(u16 x, u16 y, u16 width) { Helpers::panic("[FATAL] GPU Backend did not define beginTextureUpload function\n"); };
virtual void textureUploadData(u16 data) { Helpers::panic("[FATAL] GPU Backend did not define textureUploadData function\n"); };
virtual void endTextureUpload() { Helpers::panic("[FATAL] GPU Backend did not define endTextureUpload function\n"); }
virtual void beginTextureUpload(u16 x, u16 y, u16 width) { Helpers::panic("[ FATAL ] GPU Backend did not define beginTextureUpload function\n"); };
virtual void textureUploadData(u16 data) { Helpers::panic("[ FATAL ] GPU Backend did not define textureUploadData function\n"); };
virtual void endTextureUpload() { Helpers::panic("[ FATAL ] GPU Backend did not define endTextureUpload function\n"); }
protected:
GPU* gpu;

View file

@ -11,7 +11,7 @@ u8* GPUSoftware::getVRAM() {
}
void GPUSoftware::beginTextureUpload(u16 x, u16 y, u16 width) {
if (uploadingTexture) Helpers::panic("[FATAL] Attempted to start a GPU texture transfer before another transfer ended\n");
if (uploadingTexture) Helpers::panic("[ FATAL ] Attempted to start a GPU texture transfer before another transfer ended\n");
textureUpload = { x, y, width };
curX = x;
@ -20,7 +20,7 @@ void GPUSoftware::beginTextureUpload(u16 x, u16 y, u16 width) {
}
void GPUSoftware::textureUploadData(u16 data) {
if (!uploadingTexture) Helpers::panic("[FATAL] Attempted to upload texture data before starting a texture transfer\n");
if (!uploadingTexture) Helpers::panic("[ FATAL ] Attempted to upload texture data before starting a texture transfer\n");
writePixel(curX, curY, data);

View file

@ -10,6 +10,10 @@ int main(int argc, char** argv) {
PlayStation playstation = PlayStation(argv[1]);
if (argc >= 3) {
playstation.sideloadExecutable(argv[2]);
}
// SDL Window
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("ChonkyStation", 100, 100, 1024, 512, 0);

View file

@ -70,21 +70,21 @@ u8 Memory::read(u32 vaddr) {
switch (cdrom->getIndex()) {
case 1: return cdrom->getResponseByte();
default:
Helpers::panic("[FATAL] Unhandled CDROM read8 0x1f801801.%d", cdrom->getIndex());
Helpers::panic("[ FATAL ] Unhandled CDROM read8 0x1f801801.%d", cdrom->getIndex());
}
}
else if (paddr == 0x1f801803) {
switch (cdrom->getIndex()) {
case 1: return cdrom->readIF();
default:
Helpers::panic("[FATAL] Unhandled CDROM read8 0x1f801803.%d", cdrom->getIndex());
Helpers::panic("[ FATAL ] Unhandled CDROM read8 0x1f801803.%d", cdrom->getIndex());
}
}
// SIO
else if (Helpers::inRangeSized<u32>(paddr, (u32)MemoryBase::SIO, (u32)MemorySize::SIO)) return 0;
else if (Helpers::inRangeSized<u32>(paddr, 0x1f000000, 0x400)) return 0xff;
else
Helpers::panic("[FATAL] Unhandled read8 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
Helpers::panic("[ FATAL ] Unhandled read8 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
}
template<>
@ -107,7 +107,7 @@ u16 Memory::read(u32 vaddr) {
// SPU
else if (Helpers::inRangeSized<u32>(paddr, (u32)MemoryBase::SPU, (u32)MemorySize::SPU)) return 0;
else
Helpers::panic("[FATAL] Unhandled read16 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
Helpers::panic("[ FATAL ] Unhandled read16 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
}
template<>
@ -122,8 +122,14 @@ u32 Memory::read(u32 vaddr) {
u32 paddr = maskAddress(vaddr);
// Scratchpad
if (Helpers::inRangeSized<u32>(paddr, 0x1f800000, 1_KB)) {
u32 data = 0;
std::memcpy(&data, &scratchpad[paddr - 0x1f800000], sizeof(u32));
return data;
}
// GPU
if (paddr == 0x1f801810) return gpu->gpuRead();
else if (paddr == 0x1f801810) return gpu->gpuRead();
else if (paddr == 0x1f801814) return gpu->getStat();
// Interrupt
else if (paddr == 0x1f801070) return interrupt->readIstat();
@ -137,7 +143,7 @@ u32 Memory::read(u32 vaddr) {
case 0x0: return dma->channels[channel].madr;
case 0x4: return dma->channels[channel].bcr.raw;
case 0x8: return dma->channels[channel].chcr.raw;
default: Helpers::panic("[FATAL] Unhandled DMA read32 0x%08x\n", paddr);
default: Helpers::panic("[ FATAL ] Unhandled DMA read32 0x%08x\n", paddr);
}
}
else if (paddr == 0x1f8010f0) return dma->dpcr;
@ -145,7 +151,7 @@ u32 Memory::read(u32 vaddr) {
// Timers
else if (Helpers::inRangeSized<u32>(paddr, (u32)MemoryBase::Timer, (u32)MemorySize::Timer)) return 0;
else
Helpers::panic("[FATAL] Unhandled read32 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
Helpers::panic("[ FATAL ] Unhandled read32 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
}
@ -171,7 +177,7 @@ void Memory::write(u32 vaddr, u8 data) {
break;
}
default:
Helpers::panic("[FATAL] Unhandled CDROM write8 0x1f801801.%d <- 0x%02x\n", cdrom->getIndex(), data);
Helpers::panic("[ FATAL ] Unhandled CDROM write8 0x1f801801.%d <- 0x%02x\n", cdrom->getIndex(), data);
}
}
else if (paddr == 0x1f801802) {
@ -185,7 +191,7 @@ void Memory::write(u32 vaddr, u8 data) {
break;
}
default:
Helpers::panic("[FATAL] Unhandled CDROM write8 0x1f801802.%d <- 0x%02x\n", cdrom->getIndex(), data);
Helpers::panic("[ FATAL ] Unhandled CDROM write8 0x1f801802.%d <- 0x%02x\n", cdrom->getIndex(), data);
}
}
else if (paddr == 0x1f801803) {
@ -195,12 +201,12 @@ void Memory::write(u32 vaddr, u8 data) {
break;
}
default:
Helpers::panic("[FATAL] Unhandled CDROM write8 0x1f801803.%d <- 0x%02x\n", cdrom->getIndex(), data);
Helpers::panic("[ FATAL ] Unhandled CDROM write8 0x1f801803.%d <- 0x%02x\n", cdrom->getIndex(), data);
}
}
else if (paddr == 0x1f802041) return; // POST - External 7-segment Display (W)
else
Helpers::panic("[FATAL] Unhandled write8 0x%08x (virtual 0x%08x) <- 0x%02x\n", paddr, vaddr, data);
Helpers::panic("[ FATAL ] Unhandled write8 0x%08x (virtual 0x%08x) <- 0x%02x\n", paddr, vaddr, data);
}
template<>
@ -226,7 +232,7 @@ void Memory::write(u32 vaddr, u16 data) {
// Timers
else if (Helpers::inRangeSized<u32>(paddr, (u32)MemoryBase::Timer, (u32)MemorySize::Timer)) return;
else
Helpers::panic("[FATAL] Unhandled write16 0x%08x (virtual 0x%08x) <- 0x%04x\n", paddr, vaddr, data);
Helpers::panic("[ FATAL ] Unhandled write16 0x%08x (virtual 0x%08x) <- 0x%04x\n", paddr, vaddr, data);
}
template<>
@ -263,7 +269,7 @@ void Memory::write(u32 vaddr, u32 data) {
}
break;
}
default: Helpers::panic("[FATAL] Unhandled DMA write32 0x%08x <- 0x%08x\n", paddr, data);
default: Helpers::panic("[ FATAL ] Unhandled DMA write32 0x%08x <- 0x%08x\n", paddr, data);
}
}
else if (paddr == 0x1f8010f0) dma->dpcr = data;
@ -283,5 +289,5 @@ void Memory::write(u32 vaddr, u32 data) {
else if (paddr == 0x1f801060) return; // RAM_SIZE (R/W) (usually 00000B88h) (or 00000888h)
else if (paddr == 0xfffe0130) return; // Cache Control (R/W)
else
Helpers::panic("[FATAL] Unhandled write32 0x%08x (virtual 0x%08x) <- 0x%08x\n", paddr, vaddr, data);
Helpers::panic("[ FATAL ] Unhandled write32 0x%08x (virtual 0x%08x) <- 0x%08x\n", paddr, vaddr, data);
}

View file

@ -32,6 +32,14 @@ public:
if (cdrom.shouldFireIRQ()) {
interrupt.raiseInterrupt(Interrupt::InterruptType::CDROM);
}
if (cpu.core.pc == 0x80030000) {
isKernelSetupDone = true;
if (hasToLoadExecutable) {
loadExecutable(executablePath);
hasToLoadExecutable = false;
}
}
}
u32 getPC() { return cpu.core.pc; }
@ -44,6 +52,30 @@ public:
}
void VBLANK() { interrupt.raiseInterrupt(Interrupt::InterruptType::VBLANK); }
bool isInBIOS() { return Helpers::inRangeSized<u32>(cpu.core.pc, (u32)Memory::MemoryBase::BIOS, (u32)Memory::MemorySize::BIOS); }
void loadExecutable(const fs::path path) {
auto binary = Helpers::readBinary(path);
u32 entryPc = 0;
u32 entryAddr = 0;
u32 fileSize = 0;
memcpy(&entryPc, &binary[0x10], sizeof(u32));
memcpy(&entryAddr, &binary[0x18], sizeof(u32));
memcpy(&fileSize, &binary[0x1c], sizeof(u32));
for (int i = 0; i < (binary.size() - 2048); i++) {
mem.write(entryAddr + i, binary[0x800 + i]);
}
cpu.core.pc = entryPc;
cpu.core.nextPc = cpu.core.pc + 4;
}
void sideloadExecutable(const fs::path path) {
hasToLoadExecutable = true;
executablePath = path;
}
private:
Cpu cpu;
@ -53,4 +85,9 @@ private:
Interrupt interrupt;
GPU gpu;
CDROM cdrom;
bool hasToLoadExecutable = false;
fs::path executablePath;
bool isKernelSetupDone = false;
};

View file

@ -14,7 +14,7 @@ void Scheduler::tick(u64 cycles) {
}
void Scheduler::push(void (*functionPtr)(void*), u64 time, void* data) {
Helpers::debugAssert(events.size() < schedulerMaxEntries, "[FATAL] Queued more than %d scheduler events\n", schedulerMaxEntries);
Helpers::debugAssert(events.size() < schedulerMaxEntries, "[ FATAL ] Queued more than %d scheduler events\n", schedulerMaxEntries);
events.push({ .functionPtr = functionPtr, .data = data, .time = time });
}