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