From: Toni Wilen Date: Mon, 11 May 2026 14:02:09 +0000 (+0300) Subject: Serial port fix X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=3c3a44b5ef46b85d258e5381f019d6a34c52c632;p=francis%2Fwinuae.git Serial port fix --- diff --git a/custom.cpp b/custom.cpp index 3292b2fc..778ce4b3 100644 --- a/custom.cpp +++ b/custom.cpp @@ -3179,9 +3179,13 @@ static void rethink_intreq(void) devices_rethink(); } -static void intreq_checks(uae_u16 oldreq, uae_u16 newreq) +static void intreq_checks(uae_u16 req) { - serial_rbf_change((newreq & 0x0800) ? 1 : 0); +#ifdef SERIAL_PORT + if (req & 0x0800) { + serial_rbf_change((req & 0x8000) != 0); + } +#endif } static void event_doint_delay_do_ext_old(uae_u32 v) @@ -3290,7 +3294,7 @@ static void INTREQ_nodelay(uae_u16 v) uae_u16 old = intreq; setclr(&intreq, v); intreq2 = intreq; - intreq_checks(old, intreq); + intreq_checks(v); doint(); } @@ -3299,17 +3303,17 @@ void INTREQ_f(uae_u16 v) uae_u16 old = intreq; setclr(&intreq, v); intreq2 = intreq; - intreq_checks(old, intreq); + intreq_checks(v); } bool INTREQ_0(uae_u16 v) { uae_u16 old = intreq; setclr(&intreq, v); + intreq_checks(v); if (old != intreq) { doint_delay_intreq(v); - intreq_checks(old, intreq); } return true; } diff --git a/od-win32/parser.cpp b/od-win32/parser.cpp index cb167703..24a3366c 100644 --- a/od-win32/parser.cpp +++ b/od-win32/parser.cpp @@ -907,7 +907,8 @@ static uae_u8 inputbuffer[SERIAL_READ_BUFFER]; static int datainoutput; static int dataininput, dataininputcnt; static OVERLAPPED writeol, readol; -static int writepending; +static bool writepending; +static int writepending_size; static bool breakpending; static WSADATA wsadata; @@ -1087,7 +1088,7 @@ int openser (const TCHAR *sername) } SetCommMask (hCom, EV_RXFLAG | EV_BREAK); - SetupComm (hCom, 65536, 128); + SetupComm (hCom, 128, 128); PurgeComm (hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF; CommTimeOuts.ReadTotalTimeoutMultiplier = 0; @@ -1168,22 +1169,67 @@ void closeser (void) uartbreak = 0; } -static void outser (void) +static void outser(void) { - if (datainoutput <= 0) - return; - DWORD v = WaitForSingleObject (writeevent, 0); - if (v == WAIT_OBJECT_0) { + if (writepending) { + DWORD actual; + writepending = false; + if (GetOverlappedResult(hCom, &writeol, &actual, FALSE)) { + if (actual < writepending_size) { + if (actual) { + memmove(outputbufferout, outputbufferout + actual, writepending_size - actual); + writepending_size -= actual; + } + if (!WriteFile(hCom, outputbufferout, writepending_size, NULL, &writeol)) { + if (GetLastError() == ERROR_IO_PENDING) { + writepending = true; + } + } else { + DWORD err = GetLastError(); + write_log(_T("SERIAL: WriteFile failed (remaining write), err=%d\n"), err); + writepending_size = 0; + } + } + } else { + writepending = false; + writepending_size = 0; + } + } + if (!writepending && datainoutput > 0) { + writepending_size = 0; + memcpy(outputbufferout, outputbuffer, datainoutput); + if (!WriteFile(hCom, outputbufferout, datainoutput, NULL, &writeol)) { + DWORD err = GetLastError(); + if (err == ERROR_IO_PENDING) { + writepending_size = datainoutput; + writepending = true; + datainoutput = 0; + } else { + write_log(_T("SERIAL: WriteFile failed, err=%d\n"), err); + datainoutput = 0; + } + } else { + datainoutput = 0; + } + } +} + +static void writeser_waitpending(void) +{ + if (writepending) { DWORD actual; - memcpy (outputbufferout, outputbuffer, datainoutput); - WriteFile (hCom, outputbufferout, datainoutput, &actual, &writeol); + GetOverlappedResult(hCom, &writeol, &actual, TRUE); + writepending_size = 0; datainoutput = 0; + writepending = false; } } void writeser_flush(void) { + writeser_waitpending(); outser(); + writeser_waitpending(); } void writeser (int c) diff --git a/od-win32/serial_win32.cpp b/od-win32/serial_win32.cpp index e1efa80e..a0e3ff05 100644 --- a/od-win32/serial_win32.cpp +++ b/od-win32/serial_win32.cpp @@ -284,7 +284,7 @@ void SERPER (uae_u16 w) serial_period_receive_ccks = maxhpos; safe_receive = true; } - if (sermap_enabled || serxdevice_enabled) { + if (sermap_enabled || serxdevice_enabled || currprefs.m68k_speed < 0) { safe_receive = true; } @@ -477,8 +477,9 @@ static void checkreceive_serial (void) static int ninebitdata; int recdata; - if (!canreceive()) + if (!canreceive()) { return; + } if (ninebit) { bool breakcond; @@ -1047,8 +1048,9 @@ uae_u16 SERDATR(void) if (!data_in_serdatr) { // interrupt was previously cleared but SERDATR was not read. // Clear it now when SERDATR was read. - INTREQ_f(1 << 11); + INTREQ_INT(11, 0); } + serdatr_last_got = 0; return serdatr; }