| 485 | } |
| 486 | |
| 487 | static __fi void VSyncStart(u64 sCycle) |
| 488 | { |
| 489 | // End-of-frame tasks. |
| 490 | DoFMVSwitch(); |
| 491 | VMManager::Internal::VSyncOnCPUThread(); |
| 492 | |
| 493 | // Don't bother throttling if we're going to pause. |
| 494 | if (!VMManager::Internal::IsExecutionInterrupted()) |
| 495 | VMManager::Internal::Throttle(); |
| 496 | |
| 497 | gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times! |
| 498 | |
| 499 | // Poll input after MTGS frame push, just in case it has to stall to catch up. |
| 500 | VMManager::Internal::PollInputOnCPUThread(); |
| 501 | |
| 502 | EECNT_LOG(" ================ EE COUNTER VSYNC START (frame: %d) ================", g_FrameCount); |
| 503 | |
| 504 | // Memcard auto ejection - Uses a tick system timed off of real time, decrementing one tick per frame. |
| 505 | AutoEject::CountDownTicks(); |
| 506 | // Memcard IO detection - Uses a tick system to determine when memcards are no longer being written. |
| 507 | MemcardBusy::Decrement(); |
| 508 | |
| 509 | if (!GSSMODE1reg.SINT) |
| 510 | { |
| 511 | hwIntcIrq(INTC_VBLANK_S); |
| 512 | rcntStartGate(true, sCycle); // Counters Start Gate code |
| 513 | psxVBlankStart(); |
| 514 | } |
| 515 | |
| 516 | // INTC - VB Blank Start Hack -- |
| 517 | // Hack fix! This corrects a freezeup in Granda 2 where it decides to spin |
| 518 | // on the INTC_STAT register after the exception handler has already cleared |
| 519 | // it. But be warned! Set the value to larger than 4 and it breaks Dark |
| 520 | // Cloud and other games. -_- |
| 521 | |
| 522 | // How it works: Normally the INTC raises exceptions immediately at the end of the |
| 523 | // current branch test. But in the case of Grandia 2, the game's code is spinning |
| 524 | // on the INTC status, and the exception handler (for some reason?) clears the INTC |
| 525 | // before returning *and* returns to a location other than EPC. So the game never |
| 526 | // gets to the point where it sees the INTC Irq set true. |
| 527 | |
| 528 | // (I haven't investigated why Dark Cloud freezes on larger values) |
| 529 | // (all testing done using the recompiler -- dunno how the ints respond yet) |
| 530 | |
| 531 | //cpuRegs.eCycle[30] = 2; |
| 532 | |
| 533 | // Update 08/2021: The only game I know to require this kind of thing as of 1.7.0 is Penny Racers/Gadget Racers (which has a patch to avoid the problem and others) |
| 534 | // These games have a tight loop checking INTC_STAT waiting for the VBLANK Start, however the game also has a VBLANK Hander which clears it. |
| 535 | // Therefore, there needs to be some delay in order for it to see the interrupt flag before the interrupt is acknowledged, likely helped on real hardware by the pipelines. |
| 536 | // Without the patch and fixing this, the games have other issues, so I'm not going to rush to fix it. |
| 537 | // Refraction |
| 538 | |
| 539 | // Bail out before the next frame starts if we're paused, or the CPU has changed. |
| 540 | // Need to re-check this, because we might've paused during the sleep time. |
| 541 | if (VMManager::Internal::IsExecutionInterrupted()) |
| 542 | Cpu->ExitExecution(); |
| 543 | } |
| 544 |
no test coverage detected