shithub: psxe

Download patch

ref: 567cb9cb4ed3855b637bee999b04aee683d50bff
parent: b856b80b7349eba3853fcde0f2f1956419e4cfeb
author: allkern <lisandroaalarcon@gmail.com>
date: Wed Oct 25 17:25:43 EDT 2023

Reimplement DMA IRQ delays

--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -177,7 +177,7 @@
         dma->mdec_in.madr += CHCR_STEP(mdec_in) ? -4 : 4;
     }
 
-    dma->mdec_in_irq_delay = 1;
+    dma->mdec_in_irq_delay = size;
 
     dma->mdec_in.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
     dma->mdec_in.bcr = 0;
@@ -197,7 +197,7 @@
         dma->mdec_out.madr += CHCR_STEP(mdec_out) ? -4 : 4;
     }
 
-    dma->mdec_out_irq_delay = 1;
+    dma->mdec_out_irq_delay = size;
 
     dma->mdec_out.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
     dma->mdec_out.bcr = 0;
@@ -372,7 +372,7 @@
         // exit(1);
     }
 
-    dma->spu_irq_delay = 1;
+    dma->spu_irq_delay = BCR_SIZE(spu) * BCR_BCNT(spu);
 
     if (CHCR_TDIR(spu)) {
         for (int j = 0; j < blocks; j++) {
@@ -434,7 +434,7 @@
         dma->otc.madr -= 4;
     }
 
-    dma->otc_irq_delay = BCR_SIZE(otc);
+    dma->otc_irq_delay = size;
 
     // Clear BCR and CHCR trigger and busy bits
     dma->otc.chcr = 0;
@@ -444,45 +444,50 @@
 
 void psx_dma_update(psx_dma_t* dma, int cyc) {
     if (dma->cdrom_irq_delay) {
-        if (dma->dicr & DICR_DMA3EN)
-            dma->dicr |= DICR_DMA3FL;
+        dma->cdrom_irq_delay--;
 
-        dma->cdrom_irq_delay = 0;
+        if ((dma->dicr & DICR_DMA3EN) && !dma->cdrom_irq_delay)
+            dma->dicr |= DICR_DMA3FL;
     }
 
     if (dma->spu_irq_delay) {
-        if (dma->dicr & DICR_DMA4EN)
-            dma->dicr |= DICR_DMA4FL;
-        
-        dma->spu_irq_delay = 0;
+        dma->spu_irq_delay--;
+
+        if (!dma->spu_irq_delay)
+            if (dma->dicr & DICR_DMA4EN)
+                dma->dicr |= DICR_DMA4FL;
     }
 
     if (dma->gpu_irq_delay) {
-        if (dma->dicr & DICR_DMA2EN)
-            dma->dicr |= DICR_DMA2FL;
+        dma->gpu_irq_delay--;
 
-        dma->gpu_irq_delay = 0;
+        if (!dma->gpu_irq_delay)
+            if (dma->dicr & DICR_DMA2EN)
+                dma->dicr |= DICR_DMA2FL;
     }
 
     if (dma->otc_irq_delay) {
-        if (dma->dicr & DICR_DMA6EN)
-            dma->dicr |= DICR_DMA6FL;
+        dma->otc_irq_delay--;
 
-        dma->otc_irq_delay = 0;
+        if (!dma->otc_irq_delay)
+            if (dma->dicr & DICR_DMA6EN)
+                dma->dicr |= DICR_DMA6FL;
     }
 
     if (dma->mdec_in_irq_delay) {
-        if (dma->dicr & DICR_DMA0EN)
-            dma->dicr |= DICR_DMA0FL;
-        
-        dma->mdec_in_irq_delay = 0;
+        dma->mdec_in_irq_delay--;
+
+        if (!dma->mdec_in_irq_delay)
+            if (dma->dicr & DICR_DMA0EN)
+                dma->dicr |= DICR_DMA0FL;
     }
 
     if (dma->mdec_out_irq_delay) {
-        if (dma->dicr & DICR_DMA1EN)
-            dma->dicr |= DICR_DMA1FL;
-        
-        dma->mdec_out_irq_delay = 0;
+        dma->mdec_out_irq_delay--;
+
+        if (!dma->mdec_out_irq_delay)
+            if (dma->dicr & DICR_DMA1EN)
+                dma->dicr |= DICR_DMA1FL;
     }
 
     int prev_irq_signal = (dma->dicr & DICR_IRQSI) != 0;
--