int _SPR0chain() { tDMA_TAG *pMem; int partialqwc = 0; if (spr0ch.qwc == 0) return 0; pMem = SPRdmaGetAddr(spr0ch.madr, true); if (pMem == NULL) return -1; switch (dmacRegs.ctrl.MFD) { case MFD_VIF1: case MFD_GIF: partialqwc = spr0ch.qwc; if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("SPR MFIFO Write outside MFIFO area"); else mfifotransferred += partialqwc; hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), partialqwc); spr0ch.madr += partialqwc << 4; spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK); spr0ch.sadr += partialqwc << 4; spr0ch.qwc -= partialqwc; break; case NO_MFD: case MFD_RESERVED: //Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of //the cycle delay out of the way before the end. partialqwc = spr0ch.qwc; memcpy_qwc(pMem, &psSu128(spr0ch.sadr), partialqwc); // clear VU mem also! TestClearVUs(spr0ch.madr, partialqwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes) spr0ch.madr += partialqwc << 4; spr0ch.sadr += partialqwc << 4; spr0ch.qwc -= partialqwc; break; } return (partialqwc); // bus is 1/2 the ee speed }
int _SPR0chain() { tDMA_TAG *pMem; int partialqwc = 0; if (spr0ch.qwc == 0) return 0; pMem = SPRdmaGetAddr(spr0ch.madr, true); if (pMem == NULL) return -1; if(spr0ch.madr >= dmacRegs.rbor.ADDR && spr0ch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { partialqwc = spr0ch.qwc; if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("SPR MFIFO Write outside MFIFO area"); else mfifotransferred += partialqwc; hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), partialqwc); spr0ch.madr += partialqwc << 4; spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK); spr0ch.sadr += partialqwc << 4; spr0ch.qwc -= partialqwc; spr0finished = true; } else { //Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of //the cycle delay out of the way before the end. partialqwc = spr0ch.qwc; memcpy_qwc(pMem, &psSu128(spr0ch.sadr), partialqwc); // clear VU mem also! TestClearVUs(spr0ch.madr, partialqwc); spr0ch.madr += partialqwc << 4; spr0ch.sadr += partialqwc << 4; spr0ch.qwc -= partialqwc; } return (partialqwc); // bus is 1/2 the ee speed }
void _SPR0interleave() { int qwc = spr0ch.qwc; int sqwc = dmacRegs.sqwc.SQWC; int tqwc = dmacRegs.sqwc.TQWC; tDMA_TAG *pMem; if (tqwc == 0) tqwc = qwc; //Console.WriteLn("dmaSPR0 interleave"); SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr); CPU_INT(DMAC_FROM_SPR, qwc * BIAS); while (qwc > 0) { spr0ch.qwc = std::min(tqwc, qwc); qwc -= spr0ch.qwc; pMem = SPRdmaGetAddr(spr0ch.madr, true); switch (dmacRegs.ctrl.MFD) { case MFD_VIF1: case MFD_GIF: hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc); mfifotransferred += spr0ch.qwc; break; case NO_MFD: case MFD_RESERVED: // clear VU mem also! TestClearVUs(spr0ch.madr, spr0ch.qwc); memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc); break; } spr0ch.sadr += spr0ch.qwc * 16; spr0ch.madr += (sqwc + spr0ch.qwc) * 16; } spr0ch.qwc = 0; }