shithub: psxe

Download patch

ref: 9fc807ccb8c9aacbe22e81fbde9b052e1a9ebcee
parent: d5d7cc24b593fd59b130bed528f7f0e16517dd07
author: allkern <lisandroaalarcon@gmail.com>
date: Fri Jul 21 19:26:19 EDT 2023

Implement delayed DMA IRQs

--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -231,17 +231,17 @@
 
     g_psx_dma_gpu_table[CHCR_SYNC(gpu)](dma);
 
-    if (dma->dicr & 0x00040000) {
-        dma->dicr |= 0x04000000;
+    // if (dma->dicr & 0x00040000) {
+    //     dma->dicr |= 0x04000000;
 
-        if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
-            dma->dicr |= 0x80000000;
+    //     if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
+    //         dma->dicr |= 0x80000000;
 
-            psx_ic_irq(dma->ic, IC_DMA);
-        } else {
-            dma->dicr &= 0x7fffffff;
-        }
-    }
+    //         psx_ic_irq(dma->ic, IC_DMA);
+    //     } else {
+    //         dma->dicr &= 0x7fffffff;
+    //     }
+    // }
 
     // Clear BCR and CHCR trigger and busy bits
     dma->gpu.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
@@ -262,6 +262,14 @@
 
     uint32_t size = BCR_SIZE(cdrom) * BCR_BCNT(cdrom);
 
+    if (!size) {
+        log_fatal("0 sized CDROM DMA");
+
+        exit(1);
+    }
+
+    dma->cdrom_irq_delay = size * 24;
+
     if (!CHCR_TDIR(cdrom)) {
         for (int i = 0; i < size; i++) {
             uint32_t data = 0;
@@ -283,18 +291,6 @@
     dma->cdrom.chcr = 0;
     //dma->otc.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
     dma->cdrom.bcr = 0;
-
-    if (dma->dicr & 0x00400000) {
-        dma->dicr |= 0x40000000;
-
-        if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
-            dma->dicr |= 0x80000000;
-
-            psx_ic_irq(dma->ic, IC_DMA);
-        } else {
-            dma->dicr &= 0x7fffffff;
-        }
-    }
 }
 
 void psx_dma_do_spu(psx_dma_t* dma) {
@@ -330,15 +326,39 @@
     //dma->otc.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
     dma->otc.bcr = 0;
 
-    if (dma->dicr & 0x00400000) {
-        dma->dicr |= 0x40000000;
+    // if (dma->dicr & 0x00400000) {
+    //     dma->dicr |= 0x40000000;
 
-        if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
-            dma->dicr |= 0x80000000;
+    //     if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
+    //         dma->dicr |= 0x80000000;
 
-            psx_ic_irq(dma->ic, IC_DMA);
-        } else {
-            dma->dicr &= 0x7fffffff;
+    //         psx_ic_irq(dma->ic, IC_DMA);
+    //     } else {
+    //         dma->dicr &= 0x7fffffff;
+    //     }
+    // }
+}
+
+void psx_dma_update(psx_dma_t* dma, int cyc) {
+    if (dma->cdrom_irq_delay) {
+        dma->cdrom_irq_delay -= cyc;
+
+        if (dma->cdrom_irq_delay <= 0) {
+            if (dma->dicr & 0x00400000) {
+                dma->dicr |= 0x40000000;
+
+                if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
+                    dma->dicr |= 0x80000000;
+
+                    log_fatal("DMA IRQ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+
+                    psx_ic_irq(dma->ic, IC_DMA);
+                } else {
+                    dma->dicr &= 0x7fffffff;
+                }
+            }
+
+            dma->cdrom_irq_delay = 0;
         }
     }
 }
--- a/psx/dev/dma.h
+++ b/psx/dev/dma.h
@@ -30,6 +30,8 @@
     dma_channel_t pio;
     dma_channel_t otc;
 
+    int cdrom_irq_delay;
+
     uint32_t dpcr;
     uint32_t dicr;
 } psx_dma_t;
@@ -51,6 +53,7 @@
 void psx_dma_write16(psx_dma_t*, uint32_t, uint16_t);
 void psx_dma_write8(psx_dma_t*, uint32_t, uint8_t);
 void psx_dma_destroy(psx_dma_t*);
+void psx_dma_update(psx_dma_t*, int);
 
 typedef void (*psx_dma_do_fn_t)(psx_dma_t*);
 
--- a/psx/psx.c
+++ b/psx/psx.c
@@ -30,6 +30,7 @@
     psx_gpu_update(psx->gpu, psx->cpu->last_cycles);
     psx_pad_update(psx->pad, psx->cpu->last_cycles);
     psx_timer_update(psx->timer, psx->cpu->last_cycles);
+    psx_dma_update(psx->dma, psx->cpu->last_cycles);
 }
 
 void psx_run_frame(psx_t* psx) {
--