this begs for hw testing, but I don't have the setup right now...
libretro/pcsx_rearmed#746
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;
#include "externals.h"\r
#include "registers.h"\r
\r
+static void set_dma_end(int iSize, unsigned int cycles)\r
+{\r
+ // this must be > psxdma.c dma irq\r
+ // Road Rash also wants a considerable delay, maybe because of fifo?\r
+ cycles += iSize * 20; // maybe\r
+ cycles |= 1; // indicates dma is active\r
+ spu.cycles_dma_end = cycles;\r
+}\r
+\r
////////////////////////////////////////////////////////////////////////\r
// READ DMA (many values)\r
////////////////////////////////////////////////////////////////////////\r
if (irq && (spu.spuCtrl & CTRL_IRQ))\r
log_unhandled("rdma spu irq: %x/%x+%x\n", irq_addr, spu.spuAddr, iSize * 2);\r
spu.spuAddr = addr;\r
+ set_dma_end(iSize, cycles);\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
if (irq && (spu.spuCtrl & CTRL_IRQ)) // unhandled because need to implement delay\r
log_unhandled("wdma spu irq: %x/%x+%x\n", irq_addr, spu.spuAddr, iSize * 2);\r
spu.spuAddr = addr;\r
+ set_dma_end(iSize, cycles);\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
unsigned char * pSpuIrq;\r
\r
unsigned int cycles_played;\r
+ unsigned int cycles_dma_end;\r
int decode_pos;\r
int decode_dirty_ch;\r
unsigned int bSpuInit:1;\r
int * SB;\r
int * SSumLR;\r
\r
- int pad[29];\r
unsigned short regArea[0x400];\r
} SPUInfo;\r
\r
//-------------------------------------------------//\r
case H_SPUaddr:\r
spu.spuAddr = (unsigned long) val<<3;\r
+ //check_irq_io(spu.spuAddr);\r
break;\r
//-------------------------------------------------//\r
case H_SPUdata:\r
*(unsigned short *)(spu.spuMemC + spu.spuAddr) = HTOLE16(val);\r
spu.spuAddr += 2;\r
spu.spuAddr &= 0x7fffe;\r
+ check_irq_io(spu.spuAddr);\r
break;\r
//-------------------------------------------------//\r
case H_SPUctrl:\r
case H_SPUirqAddr:\r
//if (val & 1)\r
// log_unhandled("w irq with lsb: %08lx %04x\n", reg, val);\r
- spu.pSpuIrq=spu.spuMemC+(((unsigned long) val<<3)&~0xf);\r
+ spu.pSpuIrq = spu.spuMemC + (((int)val << 3) & ~0xf);\r
+ //check_irq_io(spu.spuAddr);\r
goto upd_irq;\r
//-------------------------------------------------//\r
case H_SPUrvolL:\r
case H_SPUaddr:\r
return (unsigned short)(spu.spuAddr>>3);\r
\r
+ // this reportedly doesn't work on real hw\r
case H_SPUdata:\r
{\r
unsigned short s = LE16TOH(*(unsigned short *)(spu.spuMemC + spu.spuAddr));\r
spu.spuAddr += 2;\r
spu.spuAddr &= 0x7fffe;\r
+ //check_irq_io(spu.spuAddr);\r
return s;\r
}\r
\r
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();