From f1108b5548e21a9c53e71a82a788a01ffb2143af Mon Sep 17 00:00:00 2001 From: nmlgc Date: Tue, 28 Feb 2023 03:18:18 +0100 Subject: [PATCH] [Platform] [PC-98] VSync: Retrigger the VSync interrupt after INT 18h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Well, that didn't take long. Unlike *debugging* this issue after you encounter it on real hardware… Part of P0232, funded by [Anonymous]. --- platform/x86real/pc98/vsync.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/platform/x86real/pc98/vsync.cpp b/platform/x86real/pc98/vsync.cpp index b8fded2c..2a255d4e 100644 --- a/platform/x86real/pc98/vsync.cpp +++ b/platform/x86real/pc98/vsync.cpp @@ -6,6 +6,7 @@ volatile uint16_t vsync_count_16; volatile uint32_t vsync_count_32; static void interrupt (*vsync_callback_old)(...); +static void interrupt (*int18h)(...); bool vsync_active; static void interrupt vsync_intfunc(...) @@ -16,14 +17,30 @@ static void interrupt vsync_intfunc(...) _outportb_(0x64, _AL); // VSync interrupt trigger } +// Some real-hardware BIOS implementations of certain INT 18h functions (in +// particular the gaiji upload function, AH=14h) seem to return with the VSync +// interrupt trigger disabled, causing any successive delay loop based on our +// VSync counters to deadlock. This is quite awful to debug, especially because +// no emulator replicates this nuisance, as of February 2023... +// This workaround of retriggering INT 0Ah ourselves, was taken from +// master.lib's VSYNC.ASM, and the CRTBIOS_COOK handler in particular. +static void interrupt vsync_retrigger_after_int18h(...) +{ + int18h(); + _outportb_(0x64, _AL); // VSync interrupt trigger +} + void __cdecl vsync_init(void) { if(vsync_active) { return; } disable(); + vsync_callback_old = getvect(0x0A); + int18h = getvect(0x18); setvect(0x0A, vsync_intfunc); + setvect(0x18, vsync_retrigger_after_int18h); // Disable all interrupts from 0x08 to 0x0F except for 0x0A _outportb_(0x02, (_inportb_(0x02) & 0xFB)); @@ -45,6 +62,7 @@ void __cdecl vsync_exit(void) _outportb_(0x02, (_inportb_(0x02) | 0x04)); setvect(0x0A, vsync_callback_old); + setvect(0x18, int18h); enable(); vsync_active = false; }