mirror of
https://github.com/JaCzekanski/Avocado.git
synced 2024-05-20 12:57:38 -04:00
cdrom: fixed interrupt/response queue
This commit is contained in:
parent
1cdf1b349f
commit
ff674d52db
|
@ -19,7 +19,7 @@ CDROM::CDROM(System* sys) : sys(sys) {
|
|||
void CDROM::step() {
|
||||
status.transmissionBusy = 0;
|
||||
if (!interruptQueue.is_empty()) {
|
||||
if ((interruptEnable & 7) & (interruptQueue.peek() & 7)) {
|
||||
if ((interruptEnable & 7) & (interruptQueue.peek().irq & 7)) {
|
||||
sys->interrupt->trigger(interrupt::CDROM);
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ void CDROM::step() {
|
|||
writeResponse(bcd::toBcd(0)); // peakhi
|
||||
|
||||
if (verbose) {
|
||||
fmt::print("CDROM: CDDA report -> ({})\n", dumpFifo(CDROM_response));
|
||||
fmt::print("CDROM:CDDA report -> ({})\n", dumpFifo(interruptQueue.peek().response));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,23 +144,44 @@ void CDROM::step() {
|
|||
}
|
||||
}
|
||||
|
||||
void CDROM::writeResponse(uint8_t byte) {
|
||||
if (interruptQueue.is_empty()) {
|
||||
fmt::print("CDROM: Fatal: Trying to write response to empty interruptQueue\n");
|
||||
return;
|
||||
}
|
||||
auto& entry = interruptQueue.ref(interruptQueue.size() - 1);
|
||||
if (entry.response.is_full()) {
|
||||
return;
|
||||
}
|
||||
entry.response.add(byte);
|
||||
}
|
||||
|
||||
uint8_t CDROM::read(uint32_t address) {
|
||||
if (address == 0) { // CD Status
|
||||
// status.transmissionBusy = !interruptQueue.empty();
|
||||
if (verbose == 2) fmt::print("CDROM: R STATUS: 0x{:02x}\n", status._reg);
|
||||
bool responseFifoEmpty = interruptQueue.is_empty() || interruptQueue.peek().response.is_empty();
|
||||
|
||||
status.parameterFifoEmpty = CDROM_params.is_empty();
|
||||
status.parameterFifoFull = !CDROM_params.is_full(); // Inverse logic
|
||||
status.responseFifoEmpty = !responseFifoEmpty; // Inverse logic
|
||||
return status._reg;
|
||||
}
|
||||
if (address == 1) { // CD Response
|
||||
uint8_t response = 0;
|
||||
if (!CDROM_response.is_empty()) {
|
||||
response = CDROM_response.get();
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (CDROM_response.is_empty()) {
|
||||
status.responseFifoEmpty = 0;
|
||||
if (!interruptQueue.is_empty()) {
|
||||
auto& response = interruptQueue.ref();
|
||||
if (!response.response.is_empty()) {
|
||||
ret = response.response.get();
|
||||
|
||||
if (response.response.is_empty() && response.ack == true) {
|
||||
interruptQueue.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (verbose == 2) fmt::print("CDROM: R RESPONSE: 0x{:02x}\n", response);
|
||||
return response;
|
||||
if (verbose == 2) fmt::print("CDROM: R RESPONSE: 0x{:02x}\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (address == 2) { // CD Data
|
||||
uint8_t byte = readByte();
|
||||
|
@ -175,7 +196,7 @@ uint8_t CDROM::read(uint32_t address) {
|
|||
if (status.index == 1 || status.index == 3) { // Interrupt flags
|
||||
uint8_t _status = 0b11100000;
|
||||
if (!interruptQueue.is_empty()) {
|
||||
_status |= interruptQueue.peek() & 7;
|
||||
_status |= interruptQueue.peek().irq & 7;
|
||||
}
|
||||
if (verbose == 2) fmt::print("CDROM: R INTF: 0x{:02x}\n", _status);
|
||||
return _status;
|
||||
|
@ -234,7 +255,6 @@ std::string CDROM::dumpFifo(const FIFO& f) {
|
|||
|
||||
void CDROM::handleCommand(uint8_t cmd) {
|
||||
interruptQueue.clear();
|
||||
CDROM_response.clear();
|
||||
switch (cmd) {
|
||||
case 0x01: cmdGetstat(); break;
|
||||
case 0x02: cmdSetloc(); break;
|
||||
|
@ -282,8 +302,6 @@ void CDROM::handleCommand(uint8_t cmd) {
|
|||
}
|
||||
|
||||
CDROM_params.clear();
|
||||
status.parameterFifoEmpty = 1;
|
||||
status.parameterFifoFull = 1;
|
||||
status.transmissionBusy = 1;
|
||||
status.xaFifoEmpty = 0;
|
||||
}
|
||||
|
@ -299,10 +317,7 @@ void CDROM::write(uint32_t address, uint8_t data) {
|
|||
return handleCommand(data);
|
||||
}
|
||||
if (address == 2 && status.index == 0) { // Parameter fifo
|
||||
assert(CDROM_params.size() < 16);
|
||||
CDROM_params.add(data);
|
||||
status.parameterFifoEmpty = 0;
|
||||
status.parameterFifoFull = !(CDROM_params.size() >= 16);
|
||||
if (verbose == 3) fmt::print("CDROM: W PARAMFIFO: 0x{:02x}\n", data);
|
||||
return;
|
||||
}
|
||||
|
@ -332,12 +347,13 @@ void CDROM::write(uint32_t address, uint8_t data) {
|
|||
if (data & 0x40) // reset parameter fifo
|
||||
{
|
||||
CDROM_params.clear();
|
||||
status.parameterFifoEmpty = 1;
|
||||
status.parameterFifoFull = 1;
|
||||
}
|
||||
|
||||
if (!interruptQueue.is_empty()) {
|
||||
interruptQueue.get();
|
||||
interruptQueue.ref().ack = true;
|
||||
if (interruptQueue.ref().response.is_empty()) {
|
||||
interruptQueue.get();
|
||||
}
|
||||
}
|
||||
if (verbose == 2) fmt::print("CDROM: W INTF: 0x{:02x}\n", data);
|
||||
return;
|
||||
|
|
|
@ -62,11 +62,11 @@ class CDROM {
|
|||
union CDROM_Status {
|
||||
struct {
|
||||
uint8_t index : 2;
|
||||
uint8_t xaFifoEmpty : 1;
|
||||
uint8_t parameterFifoEmpty : 1; // triggered before writing first byte
|
||||
uint8_t parameterFifoFull : 1; // triggered after writing 16 bytes
|
||||
uint8_t responseFifoEmpty : 1; // triggered after reading last byte
|
||||
uint8_t dataFifoEmpty : 1; // triggered after reading last byte
|
||||
uint8_t xaFifoEmpty : 1; // 1 - NOT empty, 0 - empty, INVERSE LOGIC
|
||||
uint8_t parameterFifoEmpty : 1; // 1 - empty, 0 - not empty
|
||||
uint8_t parameterFifoFull : 1; // 1 - NOT full, 0 - full, INVERSE LOGIC
|
||||
uint8_t responseFifoEmpty : 1; // 1 - NOT empty, 0 - empty, INVERSE LOGIC
|
||||
uint8_t dataFifoEmpty : 1; // 1 - NOT empty, 0 - empty, INVERSE LOGIC
|
||||
uint8_t transmissionBusy : 1;
|
||||
};
|
||||
uint8_t _reg;
|
||||
|
@ -102,6 +102,18 @@ class CDROM {
|
|||
}
|
||||
};
|
||||
|
||||
// Hack
|
||||
struct irq_response_t {
|
||||
uint8_t irq;
|
||||
fifo<uint8_t, 16> response;
|
||||
bool ack;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar) {
|
||||
ar(irq, response, ack);
|
||||
}
|
||||
};
|
||||
|
||||
using FIFO = fifo<uint8_t, 16>;
|
||||
|
||||
int verbose = 1;
|
||||
|
@ -109,8 +121,7 @@ class CDROM {
|
|||
CDROM_Status status;
|
||||
uint8_t interruptEnable = 0;
|
||||
FIFO CDROM_params;
|
||||
FIFO CDROM_response;
|
||||
FIFO interruptQueue;
|
||||
fifo<irq_response_t, 16> interruptQueue;
|
||||
|
||||
Mode mode;
|
||||
Filter filter;
|
||||
|
@ -154,28 +165,14 @@ class CDROM {
|
|||
void cmdSeekP();
|
||||
void handleCommand(uint8_t cmd);
|
||||
|
||||
void writeResponse(uint8_t byte) {
|
||||
if (CDROM_response.is_full()) {
|
||||
return;
|
||||
}
|
||||
CDROM_response.add(byte);
|
||||
status.responseFifoEmpty = 1;
|
||||
}
|
||||
void writeResponse(uint8_t byte);
|
||||
|
||||
uint8_t readParam() {
|
||||
uint8_t param = CDROM_params.get();
|
||||
|
||||
status.parameterFifoEmpty = CDROM_params.is_empty();
|
||||
status.parameterFifoFull = 1;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
void postInterrupt(int irq) {
|
||||
assert(irq <= 7);
|
||||
|
||||
interruptQueue.add(irq);
|
||||
}
|
||||
void postInterrupt(int irq) { interruptQueue.add(irq_response_t{.irq = (uint8_t)irq, .response = {}}); }
|
||||
|
||||
std::string dumpFifo(const FIFO& f);
|
||||
std::pair<int16_t, int16_t> mixSample(std::pair<int16_t, int16_t> sample);
|
||||
|
@ -213,7 +210,7 @@ class CDROM {
|
|||
void serialize(Archive& ar) {
|
||||
ar(status._reg, interruptEnable);
|
||||
ar(CDROM_params);
|
||||
ar(CDROM_response);
|
||||
// ar(CDROM_response);
|
||||
ar(interruptQueue);
|
||||
ar(mode._reg);
|
||||
ar(filter);
|
||||
|
|
|
@ -8,7 +8,7 @@ void CDROM::cmdGetstat() {
|
|||
postInterrupt(3);
|
||||
writeResponse(stat._reg);
|
||||
|
||||
if (verbose) fmt::print("CDROM: cmdGetstat -> 0x{:02x}\n", CDROM_response[0]);
|
||||
if (verbose) fmt::print("CDROM: cmdGetstat -> 0x{:02x}\n", interruptQueue.peek().response[0]);
|
||||
}
|
||||
|
||||
void CDROM::cmdSetloc() {
|
||||
|
@ -156,7 +156,7 @@ void CDROM::cmdGetparam() {
|
|||
writeResponse(filter.file);
|
||||
writeResponse(filter.channel);
|
||||
|
||||
if (verbose) fmt::print("CDROM: cmdGetparam({})\n", dumpFifo(CDROM_response));
|
||||
if (verbose) fmt::print("CDROM: cmdGetparam({})\n", dumpFifo(interruptQueue.peek().response));
|
||||
}
|
||||
|
||||
void CDROM::cmdSetSession() {
|
||||
|
@ -205,6 +205,7 @@ void CDROM::cmdGetlocL() {
|
|||
writeResponse(rawSector[19]); // ci
|
||||
|
||||
if (verbose) {
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print(
|
||||
"CDROM: cmdGetlocL -> ("
|
||||
"pos = (0x{:02x}:0x{:02x}:0x{:02x}), "
|
||||
|
@ -232,6 +233,7 @@ void CDROM::cmdGetlocP() {
|
|||
writeResponse(lastQ.data[8]); // sector (disc)
|
||||
|
||||
if (verbose) {
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print("CDROM: cmdGetlocP -> ({})\n", dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +245,7 @@ void CDROM::cmdGetTN() {
|
|||
writeResponse(bcd::toBcd(disc->getTrackCount()));
|
||||
|
||||
if (verbose) {
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print("CDROM: cmdGetTN -> ({})\n", dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
|
@ -275,6 +278,7 @@ void CDROM::cmdGetTD() {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print("CDROM: cmdGetTD(0x{:02x}) -> ({})\n", track, dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +335,8 @@ void CDROM::cmdTest() {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
fmt::print("CDROM: cmdTest(0x{:02x}) -> ({})\n", opcode, dumpFifo(CDROM_response));
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print("//CDROM: cmdTest(0x{:02x}) -> ({})\n", opcode, dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,6 +352,10 @@ void CDROM::cmdGetId() {
|
|||
postInterrupt(3);
|
||||
writeResponse(stat._reg);
|
||||
|
||||
if (disc->getTrackCount() == 0) {
|
||||
stat.idError = 1;
|
||||
}
|
||||
|
||||
// No CD
|
||||
if (disc->getTrackCount() == 0) {
|
||||
postInterrupt(5);
|
||||
|
@ -356,7 +365,7 @@ void CDROM::cmdGetId() {
|
|||
}
|
||||
// Audio CD
|
||||
else if (disc->read(disc::Position(0, 2, 0)).second == disc::TrackType::AUDIO) {
|
||||
postInterrupt(5);
|
||||
postInterrupt(2);
|
||||
writeResponse(0x0a);
|
||||
writeResponse(0x90);
|
||||
for (int i = 0; i < 6; i++) writeResponse(0);
|
||||
|
@ -374,7 +383,10 @@ void CDROM::cmdGetId() {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
fmt::print("CDROM: cmdGetId -> ({})\n", dumpFifo(CDROM_response));
|
||||
for (int i = 0; i < interruptQueue.size(); i++) {
|
||||
auto CDROM_response = interruptQueue.peek(i).response;
|
||||
fmt::print("CDROM: cmdGetId -> INT{} ({})\n", interruptQueue.peek(i).irq, dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,6 +419,7 @@ void CDROM::cmdUnlock() {
|
|||
writeResponse(0x40);
|
||||
|
||||
if (verbose) {
|
||||
auto CDROM_response = interruptQueue.peek().response;
|
||||
fmt::print("CDROM: cmdUnlock -> ({})\n", dumpFifo(CDROM_response));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue