shithub: psxe

Download patch

ref: 67df6a218da964b5477cbf3f8038da5a5c2623d5
parent: 155426cb968dab04acb3b85e6346d9e5b368a70a
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Oct 15 10:35:39 EDT 2023

Implement SPU DMA read

Implement correct GTE register accesses for LWC2/SWC2

--- a/frontend/main.c
+++ b/frontend/main.c
@@ -11,7 +11,7 @@
     psx_cdrom_t* cdrom = ((psx_t*)ud)->cdrom;
     psx_spu_t* spu = ((psx_t*)ud)->spu;
 
-    psx_cdrom_get_cdda_samples(cdrom, buf, size);
+    psx_cdrom_get_cdda_samples(cdrom, buf, size, spu);
 
     for (int i = 0; i < (size >> 2); i++) {
         uint32_t sample = psx_spu_get_sample(spu);
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -1301,19 +1301,6 @@
     psx_cpu_exception(cpu, CAUSE_CPU);
 }
 
-void psx_cpu_i_lwc2(psx_cpu_t* cpu) {
-    uint32_t s = cpu->r[S];
-    uint32_t addr = s + IMM16S;
-
-    DO_PENDING_LOAD;
-
-    if (addr & 0x3) {
-        psx_cpu_exception(cpu, CAUSE_ADEL);
-    } else {
-        COP2_DR(T) = psx_bus_read32(cpu->bus, addr);
-    }
-}
-
 void psx_cpu_i_lwc3(psx_cpu_t* cpu) {
     psx_cpu_exception(cpu, CAUSE_CPU);
 }
@@ -1326,26 +1313,6 @@
     psx_cpu_exception(cpu, CAUSE_CPU);
 }
 
-void psx_cpu_i_swc2(psx_cpu_t* cpu) {
-    uint32_t s = cpu->r[S];
-    uint32_t addr = s + IMM16S;
-
-    DO_PENDING_LOAD;
-
-    // Cache isolated
-    if (cpu->cop0_r[COP0_SR] & SR_ISC) {
-        log_debug("Ignoring write while cache is isolated");
-
-        return;
-    }
-
-    if (addr & 0x3) {
-        psx_cpu_exception(cpu, CAUSE_ADES);
-    } else {
-        psx_bus_write32(cpu->bus, addr, COP2_DR(T));
-    }
-}
-
 void psx_cpu_i_swc3(psx_cpu_t* cpu) {
     psx_cpu_exception(cpu, CAUSE_CPU);
 }
@@ -1753,6 +1720,9 @@
 }
 
 uint32_t gte_read_register(psx_cpu_t* cpu, uint32_t r) {
+    if (r == 24) {
+        log_fatal("MAC0 read %08x", cpu->cop2_dr.mac[0]);
+    }
     switch (r) {
         case 0 : return cpu->cop2_dr.v[0].xy;
         case 1 : return (int32_t)cpu->cop2_dr.v[0].z;
@@ -1893,6 +1863,39 @@
     }
 }
 
+void psx_cpu_i_lwc2(psx_cpu_t* cpu) {
+    uint32_t s = cpu->r[S];
+    uint32_t addr = s + IMM16S;
+
+    DO_PENDING_LOAD;
+
+    if (addr & 0x3) {
+        psx_cpu_exception(cpu, CAUSE_ADEL);
+    } else {
+        gte_write_register(cpu, T, psx_bus_read32(cpu->bus, addr));
+    }
+}
+
+void psx_cpu_i_swc2(psx_cpu_t* cpu) {
+    uint32_t s = cpu->r[S];
+    uint32_t addr = s + IMM16S;
+
+    DO_PENDING_LOAD;
+
+    // Cache isolated
+    if (cpu->cop0_r[COP0_SR] & SR_ISC) {
+        log_debug("Ignoring write while cache is isolated");
+
+        return;
+    }
+
+    if (addr & 0x3) {
+        psx_cpu_exception(cpu, CAUSE_ADES);
+    } else {
+        psx_bus_write32(cpu->bus, addr, gte_read_register(cpu, T));
+    }
+}
+
 void psx_cpu_i_mfc2(psx_cpu_t* cpu) {
     TRACE_C2M("mfc2");
 
@@ -2327,8 +2330,6 @@
 
     R_MAC0 = (int)gte_clamp_mac0(cpu, avg);
     R_OTZ = gte_clamp_sz3(cpu, avg >> 12);
-    R_MAC0 = 0xbaadf00d;
-    R_OTZ = 0xdeadbeef;
 }
 
 void psx_gte_i_avsz4(psx_cpu_t* cpu) {
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -1492,7 +1492,7 @@
     }
 }
 
-void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size) {
+void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size, psx_spu_t* spu) {
     if (!cdrom->cdda_playing) {
         memset(buf, 0, size);
     
@@ -1502,8 +1502,6 @@
     if (!cdrom->disc)
         return;
 
-    memcpy(buf, cdrom->cdda_buf, size);
-
     // Convert seek to I
     msf_t msf = cdrom->cdda_msf;
     
@@ -1526,6 +1524,8 @@
     cdrom->cdda_msf = msf;
 
     memcpy(buf, cdrom->cdda_buf, size);
+
+    psx_spu_update_cdda_buffer(spu, cdrom->cdda_buf);
 
     // Handle report IRQ
     if (cdrom->cdda_sectors_played == CD_SECTORS_PS) {
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -9,6 +9,7 @@
 #include "../disc/cue.h"
 #include "../disc/bin.h"
 #include "../msf.h"
+#include "spu.h"
 
 #define DELAY_1MS (PSX_CPU_CPS / 1000)
 #define READ_SINGLE_DELAY (PSX_CPU_CPS / 75)
@@ -217,7 +218,7 @@
 void psx_cdrom_update(psx_cdrom_t*);
 void psx_cdrom_destroy(psx_cdrom_t*);
 void psx_cdrom_open(psx_cdrom_t*, const char*);
-void psx_cdrom_get_cdda_samples(psx_cdrom_t*, void*, int);
+void psx_cdrom_get_cdda_samples(psx_cdrom_t*, void*, int, psx_spu_t*);
 
 /*
   Command          Parameters      Response(s)
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -385,6 +385,20 @@
                 dma->spu.madr += CHCR_STEP(spu) ? -4 : 4;
             }
         }
+    } else {
+        for (int j = 0; j < blocks; j++) {
+            for (int i = 0; i < size; i++) {
+                uint32_t data;
+
+                data  = psx_bus_read16(dma->bus, 0x1f801da8);
+                data |= psx_bus_read16(dma->bus, 0x1f801da8) << 16;
+
+                psx_bus_write32(dma->bus, dma->spu.madr, data);
+
+                dma->spu.madr += CHCR_STEP(spu) ? -4 : 4;
+            }
+        }
+
     }
     
     // Clear BCR and CHCR trigger and busy bits
--- a/psx/dev/spu.c
+++ b/psx/dev/spu.c
@@ -110,6 +110,14 @@
 }
 
 uint16_t psx_spu_read16(psx_spu_t* spu, uint32_t offset) {
+    if (offset == SPUR_TFIFO) {
+        uint16_t data = *(uint16_t*)(&spu->ram[spu->taddr]);
+
+        spu->taddr += 2;
+
+        return data;
+    }
+
     const uint8_t* ptr = (uint8_t*)&spu->voice[0].volumel;
 
     return *((uint16_t*)(ptr + offset));
@@ -622,6 +630,16 @@
     uint16_t clampr = CLAMP(clampsr + spu->lrsr, INT16_MIN, INT16_MAX);
 
     return clampl | (((uint32_t)clampr) << 16);
+}
+
+void psx_spu_update_cdda_buffer(psx_spu_t* spu, void* buf) {
+    int16_t* ptr = buf;
+    int16_t* ram = spu->ram;
+
+    for (int i = 0; i < 0x400;) {
+        ram[i] = ptr[i++];
+        ram[i + 0x400] = ptr[i++];
+    }
 }
 
 #undef CLAMP
--- a/psx/dev/spu.h
+++ b/psx/dev/spu.h
@@ -173,6 +173,7 @@
 void psx_spu_write16(psx_spu_t*, uint32_t, uint16_t);
 void psx_spu_write8(psx_spu_t*, uint32_t, uint8_t);
 void psx_spu_destroy(psx_spu_t*);
+void psx_spu_update_cdda_buffer(psx_spu_t*, void*);
 uint32_t psx_spu_get_sample(psx_spu_t*);
 
 #endif
\ No newline at end of file
--