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) {--
⑨