void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
u32 *ptr, madr_next, *madr_next_p;
u32 words, words_left, words_max, words_copy;
- int cycles_sum, cycles_last_cmd = 0, do_walking;
+ s32 cycles_last_cmd = 0;
+ int do_walking;
+ long cycles_sum;
madr &= ~3;
switch (chcr) {
case 0x01000200: // vram2mem
- PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+ PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %x addr = %x size = %x\n", chcr, madr, bcr);
ptr = getDmaRam(madr, &words_max);
if (ptr == INVALID_PTR) {
log_unhandled("bad dma2 madr %x\n", madr);
return;
case 0x01000201: // mem2vram
- PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+ PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %x addr = %x size = %x\n", chcr, madr, bcr);
words = words_left = (bcr >> 16) * (bcr & 0xffff);
while (words_left > 0) {
ptr = getDmaRam(madr, &words_max);
return;
case 0x01000401: // dma chain
- PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+ PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %x addr = %x size = %x\n", chcr, madr, bcr);
// when not emulating walking progress, end immediately
+ // (some games abort the dma and read madr so break out of that logic)
madr_next = 0xffffff;
do_walking = Config.GpuListWalking;
- if (do_walking < 0 || Config.hacks.gpu_timing1024)
+ if (do_walking < 0)
do_walking = Config.hacks.gpu_slow_list_walking;
madr_next_p = do_walking ? &madr_next : NULL;
HW_DMA2_MADR = SWAPu32(madr_next);
- // a hack for Judge Dredd which is annoyingly sensitive to timing
- if (Config.hacks.gpu_timing1024)
- cycles_sum = 1024;
+ // timing hack with some lame heuristics
+ if (Config.gpu_timing_override && (do_walking || cycles_sum > 64)
+ && !(HW_GPU_STATUS & SWAP32(PSXGPU_DHEIGHT | PSXGPU_RGB24)))
+ cycles_sum = Config.gpu_timing_override;
psxRegs.gpuIdleAfter = psxRegs.cycle + cycles_sum + cycles_last_cmd;
set_event(PSXINT_GPUDMA, cycles_sum);
- //printf("%u dma2cf: %d,%d %08x\n", psxRegs.cycle, cycles_sum,
- // cycles_last_cmd, HW_DMA2_MADR);
+ //printf("%u dma2cf: %6ld,%4d %08x %08x %08x %08x\n", psxRegs.cycle,
+ // cycles_sum, cycles_last_cmd, madr, bcr, chcr, HW_DMA2_MADR);
return;
default:
void gpuInterrupt() {
if (HW_DMA2_CHCR == SWAP32(0x01000401) && !(HW_DMA2_MADR & SWAP32(0x800000)))
{
- u32 madr_next = 0xffffff, madr = SWAPu32(HW_DMA2_MADR);
- int cycles_sum, cycles_last_cmd = 0;
- cycles_sum = GPU_dmaChain((u32 *)psxM, madr & 0x1fffff,
- &madr_next, &cycles_last_cmd);
+ u32 madr_next = SWAPu32(HW_DMA2_MADR);
+ s32 cycles_sum = psxRegs.gpuIdleAfter - psxRegs.cycle;
+ s32 cycles_last_cmd = 0;
+
+ do {
+ cycles_sum += cycles_last_cmd;
+ cycles_sum += GPU_dmaChain((u32 *)psxM, madr_next & 0x1fffff,
+ &madr_next, &cycles_last_cmd);
+ }
+ while (cycles_sum <= 0 && !(madr_next & 0x800000));
HW_DMA2_MADR = SWAPu32(madr_next);
- if ((s32)(psxRegs.gpuIdleAfter - psxRegs.cycle) > 0)
- cycles_sum += psxRegs.gpuIdleAfter - psxRegs.cycle;
psxRegs.gpuIdleAfter = psxRegs.cycle + cycles_sum + cycles_last_cmd;
set_event(PSXINT_GPUDMA, cycles_sum);
- //printf("%u dma2cn: %d,%d %08x\n", psxRegs.cycle, cycles_sum,
- // cycles_last_cmd, HW_DMA2_MADR);
+ //printf("%u dma2cn: %6d,%4d %08x\n", psxRegs.cycle, cycles_sum,
+ // cycles_last_cmd, HW_DMA2_MADR);
return;
}
if (HW_DMA2_CHCR & SWAP32(0x01000000))
}
}
+void psxAbortDma2() {
+ psxRegs.gpuIdleAfter = psxRegs.cycle + 32;
+}
+
void psxDma6(u32 madr, u32 bcr, u32 chcr) {
u32 words, words_max;
u32 *mem;