mirror of
https://github.com/liuk7071/ChonkyStation.git
synced 2024-05-20 12:57:52 -04:00
[CDROM] Add test command
This commit is contained in:
parent
e79b771a61
commit
1ff9d8ca6c
|
@ -1,19 +1,53 @@
|
|||
#include <cdrom.hpp>
|
||||
|
||||
|
||||
CDROM::CDROM() {
|
||||
CDROM::CDROM(Scheduler* scheduler) : scheduler(scheduler) {
|
||||
status.prmempt = 1; // Parameter fifo empty
|
||||
status.prmwrdy = 1; // Parameter fifo not full
|
||||
}
|
||||
|
||||
void CDROM::executeCommand(u8 data) {
|
||||
Helpers::panic("[FATAL] Unimplemented CDROM command 0x%02x\n", data);
|
||||
switch (data) {
|
||||
|
||||
case CDROMCommands::Test: {
|
||||
u8 subFunc = getParamByte();
|
||||
switch (subFunc) {
|
||||
case 0x20: {
|
||||
response.push(0x94);
|
||||
response.push(0x09);
|
||||
response.push(0x19);
|
||||
response.push(0xC0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Helpers::panic("[FATAL] Unimplemented CDROM test subfunc 0x%02x\n", subFunc);
|
||||
}
|
||||
|
||||
scheduler->push(&int3, scheduler->time + int3Delay, this);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Helpers::panic("[FATAL] Unimplemented CDROM command 0x%02x\n", data);
|
||||
}
|
||||
|
||||
Helpers::debugAssert(params.size() == 0, "[FATAL] CDROM command did not use all parameters");
|
||||
|
||||
status.rslrrdy = 1; // Response fifo not empty
|
||||
status.prmempt = 1; // Parameter fifo empty
|
||||
status.prmwrdy = 1; // Parameter fifo not full
|
||||
}
|
||||
|
||||
bool CDROM::shouldFireIRQ() {
|
||||
return intFlag & intEnable;
|
||||
}
|
||||
|
||||
void CDROM::int3(void* classptr) {
|
||||
CDROM* cdrom = (CDROM*)classptr;
|
||||
Helpers::debugAssert((cdrom->intFlag & 7) == 0, "[FATAL] CDROM INT3 was fired before previous INT was acknowledged in interrupt flag (INT%d)\n", cdrom->intFlag & 3);
|
||||
cdrom->intFlag |= 3;
|
||||
}
|
||||
|
||||
void CDROM::pushParam(u8 data) {
|
||||
Helpers::debugAssert(params.size() <= 16, "[FATAL] Wrote more than 16 bytes to CDROM parameter fifo");
|
||||
params.push(data);
|
||||
|
@ -31,13 +65,45 @@ void CDROM::writeStatus(u8 data) {
|
|||
}
|
||||
|
||||
void CDROM::writeIE(u8 data) {
|
||||
// TODO: stubbed
|
||||
intEnable = data;
|
||||
}
|
||||
|
||||
u8 CDROM::readIF() {
|
||||
return intFlag | (7 << 5); // bits 5-7 are always 1
|
||||
}
|
||||
|
||||
void CDROM::writeIF(u8 data) {
|
||||
// TODO: stubbed
|
||||
intEnable &= ~(data & 0x1f);
|
||||
if (data & (1 << 6)) { // "CLRPRM" clear parameter fifo
|
||||
while (params.size()) params.pop();
|
||||
status.prmempt = 1; // Parameter fifo empty
|
||||
status.prmwrdy = 1; // Parameter fifo not full
|
||||
}
|
||||
// Upon acknowledge, the response fifo is cleared
|
||||
while (response.size()) response.pop();
|
||||
}
|
||||
|
||||
u8 CDROM::getIndex() {
|
||||
return status.index;
|
||||
}
|
||||
|
||||
u8 CDROM::getParamByte() {
|
||||
u8 byte = params.front();
|
||||
params.pop();
|
||||
return byte;
|
||||
}
|
||||
|
||||
u8 CDROM::getResponseByte() {
|
||||
if (!response.size()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 byte = response.front();
|
||||
response.pop();
|
||||
|
||||
if (!response.size()) {
|
||||
status.rslrrdy = 0; // Response fifo empty
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
|
@ -3,24 +3,46 @@
|
|||
#include <helpers.hpp>
|
||||
#include <BitField.hpp>
|
||||
#include <queue>
|
||||
#include <scheduler.hpp>
|
||||
|
||||
|
||||
constexpr u64 cpuSpeed = 33868800;
|
||||
constexpr u64 readDelay = cpuSpeed / 75;
|
||||
constexpr u64 readDelayDoubleSpeed = readDelay / 2;
|
||||
constexpr u64 int3Delay = cpuSpeed / 1000; // I don't know if this is ok???
|
||||
|
||||
|
||||
class CDROM {
|
||||
public:
|
||||
CDROM();
|
||||
CDROM(Scheduler* scheduler);
|
||||
Scheduler* scheduler;
|
||||
|
||||
void executeCommand(u8 data);
|
||||
|
||||
// INTs
|
||||
bool shouldFireIRQ();
|
||||
static void int3(void* classptr);
|
||||
|
||||
void pushParam(u8 data);
|
||||
|
||||
u8 readStatus();
|
||||
void writeStatus(u8 data);
|
||||
|
||||
void writeIE(u8 data);
|
||||
u8 readIF();
|
||||
void writeIF(u8 data);
|
||||
|
||||
u8 getIndex();
|
||||
|
||||
u8 getResponseByte(); // This one is public so it can be called from the memory read handlers
|
||||
private:
|
||||
u8 intEnable = 0;
|
||||
u8 intFlag = 0;
|
||||
|
||||
std::queue<u8> params;
|
||||
u8 getParamByte();
|
||||
|
||||
std::queue<u8> response;
|
||||
|
||||
union {
|
||||
u8 raw = 0;
|
||||
|
@ -32,4 +54,10 @@ private:
|
|||
BitField<6, 1, u8> drqsts;
|
||||
BitField<7, 1, u8> busysts;
|
||||
} status;
|
||||
};
|
||||
};
|
||||
|
||||
namespace CDROMCommands {
|
||||
enum {
|
||||
Test = 0x19
|
||||
};
|
||||
} // End namespace CDROMCommands
|
|
@ -66,6 +66,20 @@ u8 Memory::read(u32 vaddr) {
|
|||
|
||||
// CDROM
|
||||
if (paddr == 0x1f801800) return cdrom->readStatus();
|
||||
else if (paddr == 0x1f801801) {
|
||||
switch (cdrom->getIndex()) {
|
||||
case 1: return cdrom->getResponseByte();
|
||||
default:
|
||||
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());
|
||||
}
|
||||
}
|
||||
else if (Helpers::inRangeSized<u32>(paddr, 0x1f000000, 0x400)) return 0xff;
|
||||
else
|
||||
Helpers::panic("[FATAL] Unhandled read8 0x%08x (virtual 0x%08x)\n", paddr, vaddr);
|
||||
|
@ -169,7 +183,6 @@ void Memory::write(u32 vaddr, u8 data) {
|
|||
default:
|
||||
Helpers::panic("[FATAL] Unhandled CDROM write8 0x1f801802.%d <- 0x%02x\n", cdrom->getIndex(), data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (paddr == 0x1f801803) {
|
||||
switch (cdrom->getIndex()) {
|
||||
|
@ -180,7 +193,6 @@ void Memory::write(u32 vaddr, u8 data) {
|
|||
default:
|
||||
Helpers::panic("[FATAL] Unhandled CDROM write8 0x1f801803.%d <- 0x%02x\n", cdrom->getIndex(), data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (paddr == 0x1f802041) return; // POST - External 7-segment Display (W)
|
||||
else
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
class PlayStation {
|
||||
public:
|
||||
PlayStation(const fs::path& biosPath) : cdrom(), interrupt(), gpu(&scheduler), dma(), mem(&interrupt, &dma, &gpu, &cdrom), cpu(&mem) {
|
||||
PlayStation(const fs::path& biosPath) : cdrom(&scheduler), interrupt(), gpu(&scheduler), dma(), mem(&interrupt, &dma, &gpu, &cdrom), cpu(&mem) {
|
||||
mem.loadBios(biosPath);
|
||||
cpu.switchBackend(Cpu::Backend::Interpreter);
|
||||
|
||||
|
@ -27,6 +27,11 @@ public:
|
|||
auto cyclesToAdd = isInBIOS() ? 20 : 2;
|
||||
scheduler.tick(cyclesToAdd);
|
||||
cycles += cyclesToAdd;
|
||||
|
||||
// CDROM IRQ
|
||||
if (cdrom.shouldFireIRQ()) {
|
||||
interrupt.raiseInterrupt(Interrupt::InterruptType::CDROM);
|
||||
}
|
||||
}
|
||||
|
||||
u32 getPC() { return cpu.core.pc; }
|
||||
|
|
Loading…
Reference in a new issue