shithub: psxe

Download patch

ref: 2e6491c20b71356eb4450b1180a6a11fb1df13bb
parent: dd6976f79391a1d98690efa28a77d8674c2d746b
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Jul 23 10:08:32 EDT 2023

Stub SPU space and SPU DMA IRQ

--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -225,18 +225,6 @@
 
     g_psx_dma_gpu_table[CHCR_SYNC(gpu)](dma);
 
-    // if (dma->dicr & 0x00040000) {
-    //     dma->dicr |= 0x04000000;
-
-    //     if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {
-    //         dma->dicr |= 0x80000000;
-
-    //         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);
     dma->gpu.bcr = 0;
@@ -295,11 +283,59 @@
 }
 
 void psx_dma_do_spu(psx_dma_t* dma) {
-    log_error("SPU DMA channel unimplemented"); exit(1);
+    if (!CHCR_BUSY(spu))
+        return;
+    
+    log_fatal("SPU DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
+        dma->spu.madr,
+        CHCR_TDIR(spu) ? "to device" : "to RAM",
+        g_psx_dma_sync_type_name_table[CHCR_SYNC(spu)], CHCR_SYNC(spu),
+        CHCR_STEP(spu) ? "decrementing" : "incrementing",
+        BCR_SIZE(spu)
+    );
+
+    log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",
+        (dma->dicr >> 15) & 1,
+        (dma->dicr >> 16) & 0x7f,
+        (dma->dicr >> 23) & 1,
+        (dma->dicr >> 24) & 0x7f
+    );
+
+    uint32_t size = BCR_SIZE(spu) * BCR_BCNT(spu);
+
+    if (!size) {
+        log_fatal("0 sized SPU DMA");
+
+        exit(1);
+    }
+
+    dma->spu_irq_delay = size * 4;
+
+    if (!CHCR_TDIR(spu)) {
+        for (int i = 0; i < size; i++) {
+            uint32_t data = 0;
+            
+            data |= psx_bus_read8(dma->bus, 0x1f801802) << 0;
+            data |= psx_bus_read8(dma->bus, 0x1f801802) << 8;
+            data |= psx_bus_read8(dma->bus, 0x1f801802) << 16;
+            data |= psx_bus_read8(dma->bus, 0x1f801802) << 24;
+
+            psx_bus_write32(dma->bus, dma->spu.madr, data);
+
+            dma->spu.madr += CHCR_STEP(spu) ? -4 : 4;
+        }
+    } else {
+        log_fatal("Invalid SPU DMA transfer direction");
+    }
+    
+    // Clear BCR and CHCR trigger and busy bits
+    dma->spu.chcr = 0;
+    //dma->otc.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
+    dma->spu.bcr = 0;
 }
 
 void psx_dma_do_pio(psx_dma_t* dma) {
-    log_error("PIO DMA channel unimplemented"); exit(1);
+    log_fatal("PIO DMA channel unimplemented"); exit(1);
 }
 
 void psx_dma_do_otc(psx_dma_t* dma) {
@@ -337,6 +373,17 @@
                 dma->dicr |= DICR_DMA3FL;
 
             dma->cdrom_irq_delay = 0;
+        }
+    }
+
+    if (dma->spu_irq_delay) {
+        dma->spu_irq_delay -= cyc;
+
+        if (dma->spu_irq_delay <= 0) {
+            if (dma->dicr & DICR_DMA4EN)
+                dma->dicr |= DICR_DMA4FL;
+
+            dma->spu_irq_delay = 0;
         }
     }
 
--- a/psx/dev/dma.h
+++ b/psx/dev/dma.h
@@ -31,6 +31,7 @@
     dma_channel_t otc;
 
     int cdrom_irq_delay;
+    int spu_irq_delay;
 
     uint32_t dpcr;
     uint32_t dicr;
--- a/psx/dev/spu.c
+++ b/psx/dev/spu.c
@@ -14,38 +14,37 @@
 
     spu->io_base = PSX_SPU_BEGIN;
     spu->io_size = PSX_SPU_SIZE;
+
+    spu->ram = (uint8_t*)malloc(PSX_SPU_RAM_SIZE);
 }
 
 uint32_t psx_spu_read32(psx_spu_t* spu, uint32_t offset) {
-    //log_warn("Unhandled 32-bit SPU read at offset %08x", offset);
-
-    return 0x0;
+    return *(uint32_t*)(&spu->r[offset]);
 }
 
 uint16_t psx_spu_read16(psx_spu_t* spu, uint32_t offset) {
-    //log_warn("Unhandled 16-bit SPU read at offset %08x", offset);
-
-    return 0x0;
+    return *(uint16_t*)(&spu->r[offset]);
 }
 
 uint8_t psx_spu_read8(psx_spu_t* spu, uint32_t offset) {
-    //log_warn("Unhandled 8-bit SPU read at offset %08x", offset);
+    log_fatal("Unhandled 8-bit SPU read at offset %08x", offset);
 
     return 0x0;
 }
 
 void psx_spu_write32(psx_spu_t* spu, uint32_t offset, uint32_t value) {
-    //log_warn("Unhandled 32-bit SPU write at offset %08x (%08x)", offset, value);
+    *(uint32_t*)(&spu->r[offset]) = value;
 }
 
 void psx_spu_write16(psx_spu_t* spu, uint32_t offset, uint16_t value) {
-    //log_warn("Unhandled 16-bit SPU write at offset %08x (%04x)", offset, value);
+    *(uint16_t*)(&spu->r[offset]) = value;
 }
 
 void psx_spu_write8(psx_spu_t* spu, uint32_t offset, uint8_t value) {
-    //log_warn("Unhandled 8-bit SPU write at offset %08x (%02x)", offset, value);
+    log_fatal("Unhandled 8-bit SPU write at offset %08x (%02x)", offset, value);
 }
 
 void psx_spu_destroy(psx_spu_t* spu) {
+    free(spu->ram);
     free(spu);
 }
\ No newline at end of file
--- a/psx/dev/spu.h
+++ b/psx/dev/spu.h
@@ -7,8 +7,31 @@
 #define PSX_SPU_SIZE  0x400
 #define PSX_SPU_END   0x1f801fff
 
+#define PSX_SPU_RAM_SIZE 0x80000
+
 typedef struct {
     uint32_t io_base, io_size;
+
+    uint8_t* ram;
+
+    uint8_t r[0x400];
+
+    uint32_t current_addr;
+
+    // struct {
+    //     uint16_t volumel;
+    //     uint16_t volumer;
+    //     uint16_t adsampr;
+    //     uint16_t adsaddr;
+    //     uint16_t envctl1;
+    //     uint16_t envctl2;
+    //     uint16_t envcvol;
+    //     uint16_t adraddr;
+    // } voice[24];
+
+    // uint16_t mainvol[2];
+    // uint16_t echovol[2];
+    // uint32_t flags[3];
 } psx_spu_t;
 
 psx_spu_t* psx_spu_create();
--