[Platform] [PC-98] VSync: Retrigger the VSync interrupt after INT 18h

Well, that didn't take long. Unlike *debugging* this issue after you
encounter it on real hardware…

Part of P0232, funded by [Anonymous].
This commit is contained in:
nmlgc 2023-02-28 03:18:18 +01:00
parent df0672762b
commit f1108b5548
1 changed files with 18 additions and 0 deletions

View File

@ -6,6 +6,7 @@
volatile uint16_t vsync_count_16; volatile uint16_t vsync_count_16;
volatile uint32_t vsync_count_32; volatile uint32_t vsync_count_32;
static void interrupt (*vsync_callback_old)(...); static void interrupt (*vsync_callback_old)(...);
static void interrupt (*int18h)(...);
bool vsync_active; bool vsync_active;
static void interrupt vsync_intfunc(...) static void interrupt vsync_intfunc(...)
@ -16,14 +17,30 @@ static void interrupt vsync_intfunc(...)
_outportb_(0x64, _AL); // VSync interrupt trigger _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) void __cdecl vsync_init(void)
{ {
if(vsync_active) { if(vsync_active) {
return; return;
} }
disable(); disable();
vsync_callback_old = getvect(0x0A); vsync_callback_old = getvect(0x0A);
int18h = getvect(0x18);
setvect(0x0A, vsync_intfunc); setvect(0x0A, vsync_intfunc);
setvect(0x18, vsync_retrigger_after_int18h);
// Disable all interrupts from 0x08 to 0x0F except for 0x0A // Disable all interrupts from 0x08 to 0x0F except for 0x0A
_outportb_(0x02, (_inportb_(0x02) & 0xFB)); _outportb_(0x02, (_inportb_(0x02) & 0xFB));
@ -45,6 +62,7 @@ void __cdecl vsync_exit(void)
_outportb_(0x02, (_inportb_(0x02) | 0x04)); _outportb_(0x02, (_inportb_(0x02) | 0x04));
setvect(0x0A, vsync_callback_old); setvect(0x0A, vsync_callback_old);
setvect(0x18, int18h);
enable(); enable();
vsync_active = false; vsync_active = false;
} }