ref: 854e59a15b1df3aa4525310436d175b6aea58709
parent: c24fbe43df2a63e990814887986b8744e43aab66
author: allkern <lisandroaalarcon@gmail.com>
date: Wed Aug 23 13:11:08 EDT 2023
Improve OTC DMA emulation Passing all OTC DMA tests
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -10,6 +10,18 @@
return (psx_dma_t*)malloc(sizeof(psx_dma_t));
}
+const uint32_t g_psx_dma_ctrl_hw_1_table[] = {+ 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000,
+ 0x00000002
+};
+
+const uint32_t g_psx_dma_ctrl_hw_0_table[] = {+ 0x71770703, 0x71770703, 0x71770703,
+ 0x71770703, 0x71770703, 0x71770703,
+ 0x50000002
+};
+
const psx_dma_do_fn_t g_psx_dma_do_table[] = {psx_dma_do_mdec_in,
psx_dma_do_mdec_out,
@@ -32,7 +44,6 @@
dma->ic = ic;
dma->dpcr = 0x07654321;
- dma->otc.chcr = 0x00000002;
}
uint32_t psx_dma_read32(psx_dma_t* dma, uint32_t offset) {@@ -39,10 +50,16 @@
if (offset < 0x70) {int channel = (offset >> 4) & 0x7;
int reg = (offset >> 2) & 0x3;
+ uint32_t cr = CR(channel, reg);
- log_error("DMA channel %u register %u (%08x) read %08x", channel, reg, PSX_DMAR_BEGIN + offset, (CR(channel, reg)));+ if (reg == 2) {+ cr |= g_psx_dma_ctrl_hw_1_table[channel];
+ cr &= g_psx_dma_ctrl_hw_0_table[channel];
+ }
+
+ log_error("DMA channel %u register %u (%08x) read %08x", channel, reg, PSX_DMAR_BEGIN + offset, cr);- return CR(channel, reg);
+ return cr;
} else { switch (offset) { case 0x70: log_error("DMA control read %08x", dma->dpcr); return dma->dpcr;@@ -92,9 +109,8 @@
log_error("DMA channel %u register %u write (%08x) %08x", channel, reg, PSX_DMAR_BEGIN + offset, value);- if (reg == 2) {+ if (reg == 2)
g_psx_dma_do_table[channel](dma);
- }
} else { switch (offset) { case 0x70: log_error("DMA control write %08x", value); dma->dpcr = value; break;@@ -351,10 +367,22 @@
}
void psx_dma_do_otc(psx_dma_t* dma) {- if (!CHCR_TRIG(otc))
+ if ((!(dma->dpcr & DPCR_DMA6EN)) || (!CHCR_TRIG(otc)) || (!CHCR_BUSY(otc)))
return;
+
+ log_fatal("OTC DMA transfer: madr=%08x, dir=%s, sync=%s, step=%s, size=%x",+ dma->otc.madr,
+ CHCR_TDIR(otc) ? "to device" : "to RAM",
+ CHCR_SYNC(otc) ? "other" : "burst",
+ CHCR_STEP(otc) ? "decrementing" : "incrementing",
+ BCR_SIZE(otc)
+ );
- for (int i = BCR_SIZE(otc); i > 0; i--) {+ uint32_t size = BCR_SIZE(otc);
+
+ if (!size) size = 0x10000;
+
+ for (int i = size; i > 0; i--) {uint32_t addr = (i != 1) ? (dma->otc.madr - 4) : 0xffffff;
psx_bus_write32(dma->bus, dma->otc.madr, addr & 0xffffff);
@@ -387,7 +415,7 @@
if (dma->gpu_irq_delay) {if (dma->dicr & DICR_DMA2EN)
- dma->dicr |= DICR_DMA2FL;
+ dma->dicr |= DICR_DMA2FL;
dma->gpu_irq_delay = 0;
}
--- a/psx/dev/dma.h
+++ b/psx/dev/dma.h
@@ -61,6 +61,33 @@
typedef void (*psx_dma_do_fn_t)(psx_dma_t*);
/*
+ 0-2 DMA0, MDECin Priority (0..7; 0=Highest, 7=Lowest)
+ 3 DMA0, MDECin Master Enable (0=Disable, 1=Enable)
+ 4-6 DMA1, MDECout Priority (0..7; 0=Highest, 7=Lowest)
+ 7 DMA1, MDECout Master Enable (0=Disable, 1=Enable)
+ 8-10 DMA2, GPU Priority (0..7; 0=Highest, 7=Lowest)
+ 11 DMA2, GPU Master Enable (0=Disable, 1=Enable)
+ 12-14 DMA3, CDROM Priority (0..7; 0=Highest, 7=Lowest)
+ 15 DMA3, CDROM Master Enable (0=Disable, 1=Enable)
+ 16-18 DMA4, SPU Priority (0..7; 0=Highest, 7=Lowest)
+ 19 DMA4, SPU Master Enable (0=Disable, 1=Enable)
+ 20-22 DMA5, PIO Priority (0..7; 0=Highest, 7=Lowest)
+ 23 DMA5, PIO Master Enable (0=Disable, 1=Enable)
+ 24-26 DMA6, OTC Priority (0..7; 0=Highest, 7=Lowest)
+ 27 DMA6, OTC Master Enable (0=Disable, 1=Enable)
+ 28-30 Unknown, Priority Offset or so? (R/W)
+ 31 Unknown, no effect? (R/W)
+*/
+
+#define DPCR_DMA0EN 0x00000008
+#define DPCR_DMA1EN 0x00000080
+#define DPCR_DMA2EN 0x00000800
+#define DPCR_DMA3EN 0x00008000
+#define DPCR_DMA4EN 0x00080000
+#define DPCR_DMA5EN 0x00800000
+#define DPCR_DMA6EN 0x08000000
+
+/*
0 Transfer Direction (0=To Main RAM, 1=From Main RAM)
1 Memory Address Step (0=Forward;+4, 1=Backward;-4)
2-7 Not used (always zero)
--
⑨