Commits (1)
  • Rob Swindell's avatar
    Fix (loss of) carrier detect reporting in Virtual UART driver · 5f2881f2
    Rob Swindell authored
    So Hobo and I have noticed that Global War was leaving game lock (*.LOK) files behind when he disconnected while in the game (e.g. due to the game not responding or something). 
    This was happening because GWAR was not recognizing the loss of connection ("carrier detect" or DCD) and SBBS would ungracefully terminate the process after 5 seconds of being disconnected, thus the game lock files would remain and requiring manual clean-up.
    
    I discovered that if I changed the WAR.CFG file to use FOSSIL instead of UART, Global War would then correctly recognize the loss of carrier and exit gracefully (and not leave any .LOK files behind). So... I suspected an issue with the Virtual UART driver. It turns out, that a program that relies on the modem status register change interrupt (and doesn't "poll" the UART MSR register) might never know that the "carrier" was lost. This is fixed by waiting on the hungup_event in the interrupt_thread and deasserting DCD in the "virtual" MSR register and asserting the MSR change interrupt to notify the program that it has in fact changed. Good thing for WaitForMultipleObjects(). Uh huh.
    5f2881f2
......@@ -192,8 +192,17 @@ void set_interrupt_pending(BYTE intr, BOOL assert)
void _cdecl interrupt_thread(void *arg)
{
HANDLE handles[] = {interrupt_event, hungup_event};
while(1) {
if(WaitForSingleObject(interrupt_event,INFINITE)!=WAIT_OBJECT_0)
DWORD handle_count = (uart_msr_reg & UART_MSR_DCD) ? 2 : 1;
DWORD result = WaitForMultipleObjects(handle_count, handles, /* waitAll */FALSE, INFINITE);
if(result == WAIT_OBJECT_0 + 1) {
lprintf(LOG_DEBUG, "Hangup detected in " __FUNCTION__);
uart_msr_reg &=~ UART_MSR_DCD;
assert_interrupt(UART_IER_MODEM_STATUS);
continue;
}
if(result != WAIT_OBJECT_0)
break;
if((uart_ier_reg&pending_interrupts) != 0) {
lprintf(LOG_DEBUG,"VDDSimulateInterrupt (pending: %02X) - IER: %02X"
......