shithub: psxe

Download patch

ref: 2989bb6ea366123012f68b7d0ba4fed482999d46
parent: 2c6a5a42ab52db675388ed9171015ff1497b8b66
author: allkern <lisandroaalarcon@gmail.com>
date: Mon Jul 22 19:41:29 EDT 2024

Implement IER IRQ blocking

Fixes a lot of games (Strider 2, Crash Bash, Tokimeki Memorial 2, Rockman games, and many more)

--- a/frontend/main.c
+++ b/frontend/main.c
@@ -42,6 +42,9 @@
 
     psx_cdrom_t* cdrom = psx_get_cdrom(psx);
 
+    // To-do: Set CDROM firmware version and region based
+    //        on CLI options
+
     if (cfg->cd_path)
         psx_cdrom_open(cdrom, cfg->cd_path);
 
--- a/psx/dev/cdrom/cdrom.c
+++ b/psx/dev/cdrom/cdrom.c
@@ -503,55 +503,54 @@
         return;
     }
 
-    psx_ic_irq(cdrom->ic, IC_CDROM);
+    switch (cdrom->state) {
+        case CD_STATE_TX_RESP1: {
+            cdrom_handle_resp1(cdrom);
 
-    if (cdrom->state == CD_STATE_TX_RESP1) {
-        cdrom_handle_resp1(cdrom);
+            switch (cdrom->pending_command) {
+                case CDL_READN:
+                case CDL_READS:
+                    break;
+            }
 
-        switch (cdrom->pending_command) {
-            case CDL_READN:
-            case CDL_READS:
-                return;
-        }
+            // Switching to read mode after executing a command
+            // has a 500ms penalty
+            if (cdrom->state == CD_STATE_READ) {
+                cdrom_process_setloc(cdrom);
 
-        // Switching to read mode after executing a command
-        // has a 500ms penalty
-        if (cdrom->state == CD_STATE_READ) {
-            cdrom_process_setloc(cdrom);
-
-            int ts = psx_disc_query(cdrom->disc, cdrom->lba);
-            
-            cdrom->state = CD_STATE_READ;
-            cdrom->prev_state = CD_STATE_READ;
-            cdrom->delay = CD_DELAY_ONGOING_READ;
-        }
+                int ts = psx_disc_query(cdrom->disc, cdrom->lba);
+                
+                cdrom->state = CD_STATE_READ;
+                cdrom->prev_state = CD_STATE_READ;
+                cdrom->delay = CD_DELAY_ONGOING_READ;
+            }
+        } break;
 
-        return;
-    }
+        case CD_STATE_TX_RESP2: {
+            cdrom_cmd_table[cdrom->pending_command](cdrom);
 
-    if (cdrom->state == CD_STATE_TX_RESP2) {
-        cdrom_cmd_table[cdrom->pending_command](cdrom);
+            // Switching to read mode after executing a command
+            // has a 500ms penalty
+            if (cdrom->state == CD_STATE_READ) {
+                cdrom_process_setloc(cdrom);
 
-        // Switching to read mode after executing a command
-        // has a 500ms penalty
-        if (cdrom->state == CD_STATE_READ) {
-            cdrom_process_setloc(cdrom);
-
-            int ts = psx_disc_query(cdrom->disc, cdrom->lba);
-            
-            cdrom->state = CD_STATE_READ;
-            cdrom->prev_state = CD_STATE_READ;
-            cdrom->delay = CD_DELAY_ONGOING_READ;
-        }
+                int ts = psx_disc_query(cdrom->disc, cdrom->lba);
+                
+                cdrom->state = CD_STATE_READ;
+                cdrom->prev_state = CD_STATE_READ;
+                cdrom->delay = CD_DELAY_ONGOING_READ;
+            }
+        } break;
 
-        return;
+        case CD_STATE_READ: {
+            cdrom_handle_read(cdrom);
+        } break;
     }
 
-    if (cdrom->state == CD_STATE_READ) {
-        cdrom_handle_read(cdrom);
-
+    if ((cdrom->ifr & cdrom->ier) == 0)
         return;
-    }
+
+    psx_ic_irq(cdrom->ic, IC_CDROM);
 }
 
 uint8_t cdrom_read_status(psx_cdrom_t* cdrom) {
--- a/psx/dev/cdrom/impl.c
+++ b/psx/dev/cdrom/impl.c
@@ -480,13 +480,11 @@
 
     int tn = psx_disc_get_track_count(cdrom->disc);
 
-    printf("getstat=%02x\n", cdrom_get_stat(cdrom));
-
     queue_push(cdrom->response, cdrom_get_stat(cdrom));
     queue_push(cdrom->response, 1);
     queue_push(cdrom->response, ITOB(tn));
 
-    cdrom_restore_state(cdrom);
+    cdrom_pause(cdrom);
 }
 
 void cdrom_cmd_gettd(psx_cdrom_t* cdrom) {
@@ -721,15 +719,17 @@
 void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) {
     if (cdrom->state == CD_STATE_TX_RESP1) {
         cdrom_set_int(cdrom, 3);
+
         queue_push(cdrom->response, cdrom_get_stat(cdrom));
 
-        cdrom->delay = PSX_CPU_CPS / 2;
+        cdrom->delay = CD_DELAY_1MS * 500;
         cdrom->state = CD_STATE_TX_RESP2;
     } else {
         cdrom_set_int(cdrom, 2);
-        queue_push(cdrom->response, cdrom_get_stat(cdrom));
 
-        cdrom_restore_state(cdrom);
+        queue_push(cdrom->response, CD_STAT_SPINDLE);
+
+        cdrom_pause(cdrom);
     }
 }
 
--