shithub: psxe

Download patch

ref: 8aaca5ab81a983338feda1158693e032fce7c888
parent: a6e4400fd09b8489b340b7b300ef2cfa4ef0e689
author: allkern <lisandroaalarcon@gmail.com>
date: Sat Jul 8 08:40:03 EDT 2023

Start working on GTE

Remove some CD logs

--- a/frontend/config.c
+++ b/frontend/config.c
@@ -88,7 +88,7 @@
     cfg->version = 0;
     cfg->log_level = LOG_FATAL;
     cfg->quiet = 0;
-    cfg->cd_path = "";
+    cfg->cd_path = NULL;
 }
 
 void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -19,8 +19,11 @@
     psx_init(psx, cfg->bios);
 
     psx_cdrom_t* cdrom = psx_get_cdrom(psx);
-    psx_cdrom_open(cdrom, cfg->cd_path);
 
+    if (cfg->cd_path) {
+        psx_cdrom_open(cdrom, cfg->cd_path);
+    }
+
     psxe_screen_t* screen = psxe_screen_create();
     psxe_screen_init(screen, psx);
     psxe_screen_set_scale(screen, 2);
@@ -66,7 +69,9 @@
     log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]);
     log_fatal("pc=%08x hi=%08x lo=%08x ep=%08x", cpu->pc, cpu->hi, cpu->lo, cpu->cop0_r[COP0_EPC]);
 
-    psx_cdrom_close(cdrom);
+    if (cfg->cd_path)
+        psx_cdrom_close(cdrom);
+
     psx_input_destroy(input);
     psx_destroy(psx);
     psxi_sda_destroy(controller);
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -44,10 +44,10 @@
 };
 
 psx_cpu_instruction_t g_psx_cpu_cop0_table[] = {
-    psx_cpu_i_mfc0   , psx_cpu_i_invalid, psx_cpu_i_cfc0   , psx_cpu_i_invalid,
-    psx_cpu_i_mtc0   , psx_cpu_i_invalid, psx_cpu_i_ctc0   , psx_cpu_i_invalid,
-    psx_cpu_i_bc0c   , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
+    psx_cpu_i_mfc0   , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
+    psx_cpu_i_mtc0   , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
+    psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_rfe    , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
@@ -54,6 +54,17 @@
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid
 };
 
+psx_cpu_instruction_t g_psx_cpu_cop2_table[] = {
+    psx_cpu_i_mfc2   , psx_cpu_i_invalid, psx_cpu_i_cfc2   , psx_cpu_i_invalid,
+    psx_cpu_i_mtc2   , psx_cpu_i_invalid, psx_cpu_i_ctc2   , psx_cpu_i_invalid,
+    psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
+    psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
+    psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    ,
+    psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    ,
+    psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    ,
+    psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte
+};
+
 psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez   ,
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez   ,
@@ -65,6 +76,63 @@
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez
 };
 
+/*
+  Opc  Name      Clk Expl.
+  00h  -             N/A (modifies similar registers than RTPS...)
+  01h  RTPS      15  Perspective Transformation single
+  0xh  -             N/A
+  06h  NCLIP     8   Normal clipping
+  0xh  -             N/A
+  0Ch  OP(sf)    6   Outer product of 2 vectors
+  0xh  -             N/A
+  10h  DPCS      8   Depth Cueing single
+  11h  INTPL     8   Interpolation of a vector and far color vector
+  12h  MVMVA(..) 8   Multiply vector by matrix and add vector (see below)
+  13h  NCDS      19  Normal color depth cue single vector
+  14h  CDP       13  Color Depth Que
+  15h  -             N/A
+  16h  NCDT      44  Normal color depth cue triple vectors
+  1xh  -             N/A
+  1Bh  NCCS      17  Normal Color Color single vector
+  1Ch  CC        11  Color Color
+  1Dh  -             N/A
+  1Eh  NCS       14  Normal color single
+  1Fh  -             N/A
+  20h  NCT       30  Normal color triple
+  2xh  -             N/A
+  28h  SQR(sf)   5   Square of vector IR
+  29h  DCPL      8   Depth Cue Color light
+  2Ah  DPCT      17  Depth Cueing triple (should be fake=08h, but isn't)
+  2xh  -             N/A
+  2Dh  AVSZ3     5   Average of three Z values
+  2Eh  AVSZ4     6   Average of four Z values
+  2Fh  -             N/A
+  30h  RTPT      23  Perspective Transformation triple
+  3xh  -             N/A
+  3Dh  GPF(sf)   5   General purpose interpolation
+  3Eh  GPL(sf)   5   General purpose interpolation with base
+  3Fh  NCCT      39  Normal Color Color triple vector
+*/
+
+psx_cpu_instruction_t g_psx_gte_table[] = {
+    psx_gte_i_invalid, psx_gte_i_rtps   , psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_nclip  , psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_op     , psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_dpcs   , psx_gte_i_intpl  , psx_gte_i_mvmva  , psx_gte_i_ncds   ,
+    psx_gte_i_cdp    , psx_gte_i_invalid, psx_gte_i_ncdt   , psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_nccs   ,
+    psx_gte_i_cc     , psx_gte_i_invalid, psx_gte_i_ncs    , psx_gte_i_invalid,
+    psx_gte_i_nct    , psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_sqr    , psx_gte_i_dcpl   , psx_gte_i_dpct   , psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_avsz3  , psx_gte_i_avsz4  , psx_gte_i_invalid,
+    psx_gte_i_rtpt   , psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
+    psx_gte_i_invalid, psx_gte_i_gpf    , psx_gte_i_gpl    , psx_gte_i_ncct
+};
+
 uint32_t g_psx_cpu_cop0_write_mask_table[] = {
     0x00000000, // cop0r0-r2   - N/A
     0x00000000, // cop0r0-r2   - N/A
@@ -656,9 +724,7 @@
 }
 
 void psx_cpu_i_cop2(psx_cpu_t* cpu) {
-    log_fatal("%08x: GTE instruction (GTE unimplemented)", cpu->pc - 8);
-
-    DO_PENDING_LOAD;
+    g_psx_cpu_cop2_table[S](cpu);
 }
 
 void psx_cpu_i_cop3(psx_cpu_t* cpu) {
@@ -1271,18 +1337,6 @@
     cpu->cop0_r[D] = t & g_psx_cpu_cop0_write_mask_table[D];
 }
 
-void psx_cpu_i_ctc0(psx_cpu_t* cpu) {
-    log_error("%08x: ctc0 (unimplemented)", cpu->pc - 8);
-
-    exit(1);
-}
-
-void psx_cpu_i_bc0c(psx_cpu_t* cpu) {
-    log_error("%08x: bc0c (unimplemented)", cpu->pc - 8);
-
-    exit(1);
-}
-
 // COP0-specific
 void psx_cpu_i_rfe(psx_cpu_t* cpu) {
     TRACE_N("rfe");
@@ -1293,6 +1347,134 @@
 
     cpu->cop0_r[COP0_SR] &= 0xfffffff0;
     cpu->cop0_r[COP0_SR] |= mode >> 2;
+}
+
+// COP2
+void psx_cpu_i_mfc2(psx_cpu_t* cpu) {
+    DO_PENDING_LOAD;
+
+    cpu->load_v = ((uint32_t*)(&cpu->cop2_dr))[D];
+    cpu->load_d = T;
+}
+
+void psx_cpu_i_cfc2(psx_cpu_t* cpu) {
+    DO_PENDING_LOAD;
+
+    cpu->load_v = ((uint32_t*)(&cpu->cop2_cr))[D];
+    cpu->load_d = T;
+}
+
+void psx_cpu_i_mtc2(psx_cpu_t* cpu) {
+    uint32_t t = cpu->r[T];
+
+    DO_PENDING_LOAD;
+
+    ((uint32_t*)(&cpu->cop2_dr))[D] = t & g_psx_cpu_cop0_write_mask_table[D];
+}
+
+void psx_cpu_i_ctc2(psx_cpu_t* cpu) {
+    uint32_t t = cpu->r[T];
+
+    DO_PENDING_LOAD;
+
+    ((uint32_t*)(&cpu->cop2_cr))[D] = t & g_psx_cpu_cop0_write_mask_table[D];
+}
+
+void psx_cpu_i_gte(psx_cpu_t* cpu) {
+    g_psx_gte_table[cpu->opcode & 0x3f](cpu);
+}
+
+
+void psx_gte_i_invalid(psx_cpu_t* cpu) {
+    log_fatal("invalid: Unimplemented GTE instruction %02x, %02x", cpu->opcode & 0x3f, cpu->opcode >> 25);
+}
+
+void psx_gte_i_rtps(psx_cpu_t* cpu) {
+    log_fatal("rtps: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_nclip(psx_cpu_t* cpu) {
+    log_fatal("nclip: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_op(psx_cpu_t* cpu) {
+    log_fatal("op: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_dpcs(psx_cpu_t* cpu) {
+    log_fatal("dpcs: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_intpl(psx_cpu_t* cpu) {
+    log_fatal("intpl: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_mvmva(psx_cpu_t* cpu) {
+    log_fatal("mvmva: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_ncds(psx_cpu_t* cpu) {
+    log_fatal("ncds: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_cdp(psx_cpu_t* cpu) {
+    log_fatal("cdp: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_ncdt(psx_cpu_t* cpu) {
+    log_fatal("ncdt: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_nccs(psx_cpu_t* cpu) {
+    log_fatal("nccs: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_cc(psx_cpu_t* cpu) {
+    log_fatal("cc: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_ncs(psx_cpu_t* cpu) {
+    log_fatal("ncs: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_nct(psx_cpu_t* cpu) {
+    log_fatal("nct: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_sqr(psx_cpu_t* cpu) {
+    log_fatal("sqr: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_dcpl(psx_cpu_t* cpu) {
+    log_fatal("dcpl: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_dpct(psx_cpu_t* cpu) {
+    log_fatal("dpct: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_avsz3(psx_cpu_t* cpu) {
+    log_fatal("avsz3: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_avsz4(psx_cpu_t* cpu) {
+    log_fatal("avsz4: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_rtpt(psx_cpu_t* cpu) {
+    log_fatal("rtpt: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_gpf(psx_cpu_t* cpu) {
+    log_fatal("gpf: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_gpl(psx_cpu_t* cpu) {
+    log_fatal("gpl: Unimplemented GTE instruction");
+}
+
+void psx_gte_i_ncct(psx_cpu_t* cpu) {
+    log_fatal("ncct: Unimplemented GTE instruction");
 }
 
 #undef R_R0
--- a/psx/cpu.h
+++ b/psx/cpu.h
@@ -76,6 +76,34 @@
 
     uint32_t cop0_r[16];
 
+    struct {
+        int16_t v0[4], v1[4], v2[4];
+        uint32_t rgbc;
+        uint32_t otz;
+        uint32_t ir0, ir1, ir2, ir3;
+        int16_t sxy0[2], sxy1[2], sxy2[2], sxyp[2];
+        uint32_t sz0, sz1, sz2, sz3;
+        uint32_t rgb0, rgb1, rgb2;
+        uint32_t res1;
+        int32_t mac0, mac1, mac2, mac3;
+        uint32_t irgb, orgb;
+        int32_t lzcs, lzcr;
+    } cop2_dr;
+
+    struct {
+        int16_t rt[3 * 3];
+        uint32_t trx, try, trz;
+        int16_t l[3 * 3];
+        uint32_t rbk, gbk, bbk;
+        int16_t lr[3 * 3];
+        uint32_t rfc, gfc, bfc;
+        uint32_t ofx, ofy;
+        uint32_t h;
+        uint32_t dqa, dqb;
+        uint32_t zsf3, zsf4;
+        uint32_t flag;
+    } cop2_cr;
+
     psx_bus_t* bus;
 
     psx_cpu_kcall_hook_t a_function_hook;
@@ -272,17 +300,8 @@
 
 // COP0
 void psx_cpu_i_mfc0(psx_cpu_t*);
-void psx_cpu_i_cfc0(psx_cpu_t*);
 void psx_cpu_i_mtc0(psx_cpu_t*);
-void psx_cpu_i_ctc0(psx_cpu_t*);
-void psx_cpu_i_bc0c(psx_cpu_t*);
 
-// Unimplemented
-// void psx_cpu_i_cop0_tlbr(psx_cpu_t*);
-// void psx_cpu_i_cop0_tlbwi(psx_cpu_t*);
-// void psx_cpu_i_cop0_tlbwr(psx_cpu_t*);
-// void psx_cpu_i_cop0_tlbp(psx_cpu_t*);
-
 // COP0-specific
 void psx_cpu_i_rfe(psx_cpu_t*);
 
@@ -291,6 +310,38 @@
 void psx_cpu_i_bgez(psx_cpu_t*);
 void psx_cpu_i_bltzal(psx_cpu_t*);
 void psx_cpu_i_bgezal(psx_cpu_t*);
+
+// COP2
+void psx_cpu_i_mfc2(psx_cpu_t*);
+void psx_cpu_i_cfc2(psx_cpu_t*);
+void psx_cpu_i_mtc2(psx_cpu_t*);
+void psx_cpu_i_ctc2(psx_cpu_t*);
+void psx_cpu_i_gte(psx_cpu_t*);
+
+// GTE instructions
+void psx_gte_i_invalid(psx_cpu_t*);
+void psx_gte_i_rtps(psx_cpu_t*);
+void psx_gte_i_nclip(psx_cpu_t*);
+void psx_gte_i_op(psx_cpu_t*);
+void psx_gte_i_dpcs(psx_cpu_t*);
+void psx_gte_i_intpl(psx_cpu_t*);
+void psx_gte_i_mvmva(psx_cpu_t*);
+void psx_gte_i_ncds(psx_cpu_t*);
+void psx_gte_i_cdp(psx_cpu_t*);
+void psx_gte_i_ncdt(psx_cpu_t*);
+void psx_gte_i_nccs(psx_cpu_t*);
+void psx_gte_i_cc(psx_cpu_t*);
+void psx_gte_i_ncs(psx_cpu_t*);
+void psx_gte_i_nct(psx_cpu_t*);
+void psx_gte_i_sqr(psx_cpu_t*);
+void psx_gte_i_dcpl(psx_cpu_t*);
+void psx_gte_i_dpct(psx_cpu_t*);
+void psx_gte_i_avsz3(psx_cpu_t*);
+void psx_gte_i_avsz4(psx_cpu_t*);
+void psx_gte_i_rtpt(psx_cpu_t*);
+void psx_gte_i_gpf(psx_cpu_t*);
+void psx_gte_i_gpl(psx_cpu_t*);
+void psx_gte_i_ncct(psx_cpu_t*);
 
 typedef void (*psx_cpu_instruction_t)(psx_cpu_t*);
 
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -31,6 +31,8 @@
         RESP_PUSH(cdrom->stat);
         SEND_INT3(COMMAND_DELAY);
 
+        cdrom->stat |= GETSTAT_READ;
+
         cdrom->delayed_response_command = cdrom->command;
     } else {
         log_fatal("Reading data from disc. offset=%02x:%02x:%02x (%08x)",
@@ -47,6 +49,8 @@
 
         cdrom->dfifo_full = 1;
 
+        cdrom->stat &= ~GETSTAT_READ;
+
         // Repeat until pause
         cdrom->delayed_response_command = cdrom->command;
     }
@@ -72,15 +76,28 @@
 }
 
 void cdrom_cmd_init(psx_cdrom_t* cdrom) {
-    log_fatal("init: Unimplemented CD command");
+    if (!cdrom->delayed_response_command) {
+        RESP_PUSH(cdrom->stat);
+        SEND_INT3(COMMAND_DELAY);
+
+        cdrom->delayed_response_command = cdrom->command;
+    } else {
+        RESP_PUSH(cdrom->stat);
+        SEND_INT2(COMMAND_DELAY);
+
+        cdrom->delayed_response_command = 0;
+    }
 }
 
 void cdrom_cmd_unmute(psx_cdrom_t* cdrom) {
-    log_fatal("unmute: Unimplemented CD command");
+    RESP_PUSH(cdrom->stat);
+    SEND_INT3(COMMAND_DELAY);
 }
 
 void cdrom_cmd_setfilter(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("setfilter: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_setmode(psx_cdrom_t* cdrom) {
@@ -97,19 +114,27 @@
 }
 
 void cdrom_cmd_getlocl(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("getlocl: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_getlocp(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("getlocp: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_gettn(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("gettn: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_gettd(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("gettd: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_seekl(psx_cdrom_t* cdrom) {
@@ -131,19 +156,27 @@
 }
 
 void cdrom_cmd_seekp(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("seekp: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_reads(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("reads: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("readtoc: Unimplemented CD command");
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_unimplemented(psx_cdrom_t* cdrom) {
+    log_set_quiet(0);
     log_fatal("Unimplemented CD command %02x", cdrom->command);
+    log_set_quiet(1);
 }
 
 void cdrom_cmd_getstat(psx_cdrom_t* cdrom) {
@@ -157,7 +190,7 @@
 
 void cdrom_cmd_setloc(psx_cdrom_t* cdrom) {
     if (cdrom->pfifo_index != 3) {
-        log_fatal("setloc: Expected exactly 3 parameters");
+        log_fatal("setloc: Expected exactly 3 parameters, got %u instead", cdrom->pfifo_index);
 
         return;
     }
@@ -185,19 +218,31 @@
 
 void cdrom_cmd_getid(psx_cdrom_t* cdrom) {
     if (!cdrom->delayed_response_command) {
-        RESP_PUSH(cdrom->stat);
+        // RESP_PUSH(cdrom->stat);
         SEND_INT3(COMMAND_DELAY);
 
         cdrom->delayed_response_command = cdrom->command;
     } else {
-        RESP_PUSH(0x02);
-        RESP_PUSH(0x00);
-        RESP_PUSH(0x20);
-        RESP_PUSH(0x00);
-        RESP_PUSH(0x53);
-        RESP_PUSH(0x43);
-        RESP_PUSH(0x45);
-        RESP_PUSH(0x41);
+        if (!cdrom->disc) {
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x40);
+            RESP_PUSH(0x08);
+        } else {
+            RESP_PUSH(0x41);
+            RESP_PUSH(0x45);
+            RESP_PUSH(0x43);
+            RESP_PUSH(0x53);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x20);
+            RESP_PUSH(0x00);
+            RESP_PUSH(0x02);
+        }
+
         SEND_INT2(COMMAND_DELAY);
 
         cdrom->delayed_response_command = 0;
@@ -205,7 +250,11 @@
 }
 
 void cdrom_cmd_test(psx_cdrom_t* cdrom) {
-    switch (cdrom->pfifo[0]) {
+    if (cdrom->pfifo_index != 1) {
+        log_fatal("test: Expected exactly 1 parameter");
+    }
+
+    switch (cdrom->pfifo[--cdrom->pfifo_index]) {
         case 0x20: {
             RESP_PUSH(0x01);
             RESP_PUSH(0x95);
@@ -304,7 +353,7 @@
 typedef void (*psx_cdrom_write_function_t)(psx_cdrom_t*, uint8_t);
 
 uint8_t cdrom_read_status(psx_cdrom_t* cdrom) {
-    log_fatal("    Status read %02x", cdrom->status);
+    //log_fatal("    Status read %02x, pfifo_index=%u", cdrom->status, cdrom->pfifo_index);
 
     return cdrom->status;
 }
@@ -315,13 +364,13 @@
         
         SET_BITS(status, STAT_RSLRRDY_MASK, 0);
 
-        log_fatal("    RFIFO read (%02x)", data);
+        //log_fatal("    RFIFO read (%02x)", data);
 
         return data;
     } else {
         uint8_t data = cdrom->rfifo[--cdrom->rfifo_index];
     
-        log_fatal("    RFIFO read (%02x)", data);
+        //log_fatal("    RFIFO read (%02x)", data);
     
         return data;
     }
@@ -346,44 +395,43 @@
 }
 
 uint8_t cdrom_read_ier(psx_cdrom_t* cdrom) {
-    log_fatal("    IER read %02x", cdrom->ier);
+    //log_fatal("    IER read %02x", cdrom->ier);
 
     return cdrom->ier;
 }
 
 uint8_t cdrom_read_ifr(psx_cdrom_t* cdrom) {
-    log_fatal("    IFR read %02x", cdrom->ifr);
+    //log_fatal("    IFR read %02x", cdrom->ifr);
 
     return cdrom->ifr;
 }
 
 void cdrom_write_status(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("    Status write %02x", value);
+    //log_fatal("    Status write %02x, pfifo_index=%u", value, cdrom->pfifo_index);
 
     SET_BITS(status, STAT_INDEX_MASK, value);
 }
 
 void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("    Command %02x (pfifo=%02x, %02x, %02x, %02x)",
+    cdrom->delayed_response_command = 0;
+    cdrom->command = value;
+
+    g_psx_cdrom_command_table[value](cdrom);
+
+    log_fatal("    Command %02x (pfifo=%02x, %02x, %02x, %02x), pfifo_index=%u",
         value,
         cdrom->pfifo[0],
         cdrom->pfifo[1],
         cdrom->pfifo[2],
-        cdrom->pfifo[3]
+        cdrom->pfifo[3],
+        cdrom->pfifo_index
     );
-
-    cdrom->delayed_response_command = 0;
-    cdrom->command = value;
-
-    g_psx_cdrom_command_table[value](cdrom);
 }
 
 void cdrom_write_pfifo(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("    PFIFO write %02x", value);
-
     cdrom->pfifo[(cdrom->pfifo_index++) & 0xf] = value;
 
-    SET_BITS(status, STAT_PRMWRDY_MASK, (cdrom->pfifo_index & 0x10) ? 0xff : 0);
+    SET_BITS(status, STAT_PRMWRDY_MASK, (cdrom->pfifo_index & 0x10) ? 0x0 : 0xff);
 
     cdrom->pfifo_index &= 0x1f;
 }
@@ -406,13 +454,13 @@
 }
 
 void cdrom_write_ier(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("    IER write %02x", value);
+    //log_fatal("    IER write %02x", value);
 
     cdrom->ier = value;
 }
 
 void cdrom_write_ifr(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("    IFR write %02x", value);
+    //log_fatal("    IFR write %02x", value);
 
     cdrom->ifr &= ~(value & 0x7);
 
@@ -516,8 +564,11 @@
 
             cdrom->irq_delay = 0;
 
+            log_fatal("delayed_command=%02x", cdrom->delayed_response_command);
+
             if (cdrom->delayed_response_command) {
                 g_psx_cdrom_command_table[cdrom->delayed_response_command](cdrom);
+                log_fatal("Delayed execution delay=%08x cmd=%02x", cdrom->irq_delay, cdrom->delayed_response_command);
             }
         }
     }
@@ -528,6 +579,8 @@
 
     if (!cdrom->disc) {
         log_fatal("Couldn't open disc image \"%s\"", path);
+
+        cdrom->stat |= GETSTAT_TRAYOPEN;
 
         return;
     }
--