spu: adjust irqs again
authornotaz <notasas@gmail.com>
Fri, 25 Aug 2023 20:32:14 +0000 (23:32 +0300)
committernotaz <notasas@gmail.com>
Fri, 25 Aug 2023 23:11:58 +0000 (02:11 +0300)
this begs for hw testing, but I don't have the setup right now...

libretro/pcsx_rearmed#746

libpcsxcore/psxdma.c
plugins/dfsound/dma.c
plugins/dfsound/externals.h
plugins/dfsound/registers.c
plugins/dfsound/spu.c

index 42fb3ba..c0aee7e 100644 (file)
@@ -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;
 
index 533d95e..ada007f 100644 (file)
 #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
@@ -44,6 +53,7 @@ void CALLBACK SPUreadDMAMem(unsigned short *pusPSXMem, int iSize,
  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
@@ -78,6 +88,7 @@ void CALLBACK SPUwriteDMAMem(unsigned short *pusPSXMem, int iSize,
  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
index dd05a5a..f638b94 100644 (file)
@@ -197,6 +197,7 @@ typedef struct
  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
@@ -240,7 +241,6 @@ typedef struct
  int           * SB;\r
  int           * SSumLR;\r
 \r
- int             pad[29];\r
  unsigned short  regArea[0x400];\r
 } SPUInfo;\r
 \r
index ae7ed24..bcac4d9 100644 (file)
@@ -133,12 +133,14 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,
     //-------------------------------------------------//\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
@@ -160,7 +162,8 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,
     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
@@ -350,11 +353,13 @@ unsigned short CALLBACK SPUreadRegister(unsigned long reg)
     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
index 0c4e4f8..fead03c 100644 (file)
@@ -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();