| 301 | // register has no writeback, or if the writeback is handled internally. |
| 302 | template< uint page > |
| 303 | __fi bool dmacWrite32( u32 mem, mem32_t& value ) |
| 304 | { |
| 305 | // DMA Writes are invalid to everything except the STR on CHCR when it is busy |
| 306 | // However this isn't completely confirmed and this might vary depending on if |
| 307 | // using chain or normal modes, DMA's may be handled internally. |
| 308 | // Metal Saga requires the QWC during IPU_FROM to be written but not MADR |
| 309 | // similar happens with Mana Khemia. |
| 310 | // In other cases such as Pilot Down Behind Enemy Lines, it seems to expect the DMA |
| 311 | // to have finished before it writes the new information, otherwise the game breaks. |
| 312 | if (CHECK_DMABUSYHACK && (mem & 0xf0) && mem >= 0x10008000 && mem <= 0x1000E000) |
| 313 | { |
| 314 | if ((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER + 2)) |
| 315 | { |
| 316 | //DevCon.Warning("Gamefix: Write to DMA addr %x while STR is busy!", mem); |
| 317 | while (psHu32(mem & ~0xff) & 0x100) |
| 318 | { |
| 319 | switch ((mem >> 8) & 0xFF) |
| 320 | { |
| 321 | case 0x80: // VIF0 |
| 322 | vif0Interrupt(); |
| 323 | cpuRegs.interrupt &= ~(1 << DMAC_VIF0); |
| 324 | break; |
| 325 | case 0x90: // VIF1 |
| 326 | if (vif1Regs.stat.VEW) |
| 327 | { |
| 328 | vu1Finish(false); |
| 329 | vif1VUFinish(); |
| 330 | } |
| 331 | else |
| 332 | vif1Interrupt(); |
| 333 | cpuRegs.interrupt &= ~(1 << DMAC_VIF1); |
| 334 | break; |
| 335 | case 0xA0: // GIF |
| 336 | gifInterrupt(); |
| 337 | cpuRegs.interrupt &= ~(1 << DMAC_GIF); |
| 338 | break; |
| 339 | case 0xB0: // IPUFROM |
| 340 | [[fallthrough]]; |
| 341 | case 0xB4: // IPUTO |
| 342 | if ((mem & 0xff) == 0x20) |
| 343 | goto allow_write; // I'm so sorry |
| 344 | else |
| 345 | return false; |
| 346 | break; |
| 347 | case 0xD0: // SPRFROM |
| 348 | SPRFROMinterrupt(); |
| 349 | cpuRegs.interrupt &= ~(1 << DMAC_FROM_SPR); |
| 350 | break; |
| 351 | case 0xD4: // SPRTO |
| 352 | SPRTOinterrupt(); |
| 353 | cpuRegs.interrupt &= ~(1 << DMAC_TO_SPR); |
| 354 | break; |
| 355 | default: |
| 356 | return false; |
| 357 | } |
| 358 | } |
| 359 | } |
| 360 | allow_write:; |
nothing calls this directly
no test coverage detected