From 3c7a8977ddbdbfb4a8840a487fadade29bd939d6 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 25 Aug 2023 23:32:14 +0300 Subject: [PATCH] spu: adjust irqs again this begs for hw testing, but I don't have the setup right now... libretro/pcsx_rearmed#746 --- libpcsxcore/psxdma.c | 3 +++ plugins/dfsound/dma.c | 11 +++++++++++ plugins/dfsound/externals.h | 2 +- plugins/dfsound/registers.c | 7 ++++++- plugins/dfsound/spu.c | 5 ++++- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libpcsxcore/psxdma.c b/libpcsxcore/psxdma.c index 42fb3bab..c0aee7ed 100644 --- a/libpcsxcore/psxdma.c +++ b/libpcsxcore/psxdma.c @@ -64,6 +64,9 @@ void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU break; SPU_writeDMAMem(ptr, words_copy * 2, psxRegs.cycle); HW_DMA4_MADR = SWAPu32(madr + words_copy * 2); + // This should be much slower, like 12+ cycles/byte, it's like + // that because the CPU runs too fast and fifo is not emulated. + // See also set_dma_end(). SPUDMA_INT(words * 4); return; diff --git a/plugins/dfsound/dma.c b/plugins/dfsound/dma.c index 533d95e9..ada007f0 100644 --- a/plugins/dfsound/dma.c +++ b/plugins/dfsound/dma.c @@ -22,6 +22,15 @@ #include "externals.h" #include "registers.h" +static void set_dma_end(int iSize, unsigned int cycles) +{ + // this must be > psxdma.c dma irq + // Road Rash also wants a considerable delay, maybe because of fifo? + cycles += iSize * 20; // maybe + cycles |= 1; // indicates dma is active + spu.cycles_dma_end = cycles; +} + //////////////////////////////////////////////////////////////////////// // READ DMA (many values) //////////////////////////////////////////////////////////////////////// @@ -44,6 +53,7 @@ void CALLBACK SPUreadDMAMem(unsigned short *pusPSXMem, int iSize, if (irq && (spu.spuCtrl & CTRL_IRQ)) log_unhandled("rdma spu irq: %x/%x+%x\n", irq_addr, spu.spuAddr, iSize * 2); spu.spuAddr = addr; + set_dma_end(iSize, cycles); } //////////////////////////////////////////////////////////////////////// @@ -78,6 +88,7 @@ void CALLBACK SPUwriteDMAMem(unsigned short *pusPSXMem, int iSize, if (irq && (spu.spuCtrl & CTRL_IRQ)) // unhandled because need to implement delay log_unhandled("wdma spu irq: %x/%x+%x\n", irq_addr, spu.spuAddr, iSize * 2); spu.spuAddr = addr; + set_dma_end(iSize, cycles); } //////////////////////////////////////////////////////////////////////// diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index dd05a5ab..f638b94f 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -197,6 +197,7 @@ typedef struct unsigned char * pSpuIrq; unsigned int cycles_played; + unsigned int cycles_dma_end; int decode_pos; int decode_dirty_ch; unsigned int bSpuInit:1; @@ -240,7 +241,6 @@ typedef struct int * SB; int * SSumLR; - int pad[29]; unsigned short regArea[0x400]; } SPUInfo; diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c index ae7ed24e..bcac4d9a 100644 --- a/plugins/dfsound/registers.c +++ b/plugins/dfsound/registers.c @@ -133,12 +133,14 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, //-------------------------------------------------// case H_SPUaddr: spu.spuAddr = (unsigned long) val<<3; + //check_irq_io(spu.spuAddr); break; //-------------------------------------------------// case H_SPUdata: *(unsigned short *)(spu.spuMemC + spu.spuAddr) = HTOLE16(val); spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + check_irq_io(spu.spuAddr); break; //-------------------------------------------------// case H_SPUctrl: @@ -160,7 +162,8 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, case H_SPUirqAddr: //if (val & 1) // log_unhandled("w irq with lsb: %08lx %04x\n", reg, val); - spu.pSpuIrq=spu.spuMemC+(((unsigned long) val<<3)&~0xf); + spu.pSpuIrq = spu.spuMemC + (((int)val << 3) & ~0xf); + //check_irq_io(spu.spuAddr); goto upd_irq; //-------------------------------------------------// case H_SPUrvolL: @@ -350,11 +353,13 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg) case H_SPUaddr: return (unsigned short)(spu.spuAddr>>3); + // this reportedly doesn't work on real hw case H_SPUdata: { unsigned short s = LE16TOH(*(unsigned short *)(spu.spuMemC + spu.spuAddr)); spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + //check_irq_io(spu.spuAddr); return s; } diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 0c4e4f86..fead03c0 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -1154,7 +1154,10 @@ void do_samples(unsigned int cycles_to, int do_direct) do_irq(); } } - check_irq_io(spu.spuAddr); + if (!spu.cycles_dma_end || (int)(spu.cycles_dma_end - cycles_to) < 0) { + spu.cycles_dma_end = 0; + check_irq_io(spu.spuAddr); + } if (unlikely(spu.rvb->dirty)) REVERBPrep(); -- 2.39.2