| 100 | } |
| 101 | |
| 102 | int _SPR0chain() |
| 103 | { |
| 104 | tDMA_TAG *pMem; |
| 105 | int partialqwc = 0; |
| 106 | if (spr0ch.qwc == 0) return 0; |
| 107 | pMem = SPRdmaGetAddr(spr0ch.madr, true); |
| 108 | if (pMem == NULL) return -1; |
| 109 | |
| 110 | if(spr0ch.madr >= dmacRegs.rbor.ADDR && spr0ch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) |
| 111 | { |
| 112 | if (dmacRegs.rbsr.RMSK == 0) // Shortcut when MFIFO isn't set up with a size (Hitman series) |
| 113 | { |
| 114 | spr0ch.madr += spr0ch.qwc << 4; |
| 115 | spr0ch.sadr += spr0ch.qwc << 4; |
| 116 | spr0ch.sadr &= 0x3FFF; // Limited to 16K |
| 117 | spr0ch.qwc = 0; |
| 118 | } |
| 119 | else |
| 120 | { |
| 121 | partialqwc = std::min(spr0ch.qwc, 0x400 - ((spr0ch.sadr & 0x3fff) >> 4)); |
| 122 | |
| 123 | if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) |
| 124 | Console.WriteLn("SPR MFIFO Write outside MFIFO area"); |
| 125 | |
| 126 | hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), partialqwc); |
| 127 | spr0ch.madr += partialqwc << 4; |
| 128 | spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK); |
| 129 | spr0ch.sadr += partialqwc << 4; |
| 130 | spr0ch.sadr &= 0x3FFF; // Limited to 16K |
| 131 | spr0ch.qwc -= partialqwc; |
| 132 | } |
| 133 | spr0finished = true; |
| 134 | } |
| 135 | else |
| 136 | { |
| 137 | |
| 138 | // Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of |
| 139 | // the cycle delay out of the way before the end. |
| 140 | partialqwc = std::min(spr0ch.qwc, 0x400 - ((spr0ch.sadr & 0x3fff) >> 4)); |
| 141 | memcpy_from_spr((u8*)pMem, spr0ch.sadr, partialqwc*16); |
| 142 | |
| 143 | // Clear VU mem also! |
| 144 | TestClearVUs(spr0ch.madr, partialqwc, true); |
| 145 | |
| 146 | spr0ch.madr += partialqwc << 4; |
| 147 | spr0ch.sadr += partialqwc << 4; |
| 148 | spr0ch.sadr &= 0x3FFF; // Limited to 16K |
| 149 | spr0ch.qwc -= partialqwc; |
| 150 | |
| 151 | } |
| 152 | |
| 153 | if (spr0ch.qwc == 0 && dmacRegs.ctrl.STS == STS_fromSPR) |
| 154 | { |
| 155 | if (spr0ch.chcr.MOD == NORMAL_MODE || ((spr0ch.chcr.TAG >> 28) & 0x7) == TAG_CNTS) |
| 156 | { |
| 157 | //DevCon.Warning("SPR0 %s Stall Control", spr0ch.chcr.MOD == NORMAL_MODE ? "Normal" : "Chain"); |
| 158 | dmacRegs.stadr.ADDR = spr0ch.madr; // Copy MADR to DMAC_STADR stall addr register |
| 159 | } |
no test coverage detected