From 4aee47a770dddcf74f4564fc25b48adcd7cfe943 Mon Sep 17 00:00:00 2001 From: Marco Maccaferri Date: Sun, 9 Feb 2020 19:41:55 -0800 Subject: [PATCH] Fix handling of escape characters in softmodem When running BBS DOSBox's softmodem does not correctly handle escape characters properly nor does it properly transition to command mode: Characters are swallowed instead of passed-through, this causes issue when transmitting strings with the plus character. Additional characters before and after the escape sequence don't reset the counters causing switch to command mode even if not intended. For example, connect to a remote and type a+++ it switches to command mode, it should not. The attached proposed patch fixes the escape handling: Transmission pause is checked before and after the escape sequence, so +++ is the correct sequence. Extra characters cause the counters to be reset so no unwanted switch is triggered. Use register S12 to set the pause timer in 1/50th of seconds, default is 50 = 1 sec. Plus characters are passed to the remote. With this fix I'm able to run a BBS software and do file transfers with XModem and ZModem without problems. Imported-from: https://sourceforge.net/p/dosbox/patches/287/ --- src/hardware/serialport/softmodem.cpp | 43 ++++++++++++++------------- src/hardware/serialport/softmodem.h | 1 + 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/hardware/serialport/softmodem.cpp b/src/hardware/serialport/softmodem.cpp index bbacd685..2548c771 100644 --- a/src/hardware/serialport/softmodem.cpp +++ b/src/hardware/serialport/softmodem.cpp @@ -258,6 +258,7 @@ void CSerialModem::Reset(){ reg[MREG_CR_CHAR] = '\r'; reg[MREG_LF_CHAR] = '\n'; reg[MREG_BACKSPACE_CHAR] = '\b'; + reg[MREG_GUARD_TIME] = 50; cmdpause = 0; echo = true; @@ -688,14 +689,26 @@ void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) { } void CSerialModem::Timer2(void) { - - bool sendbyte = true; Bitu usesize; Bit8u txval; Bitu txbuffersize =0; // Check for eventual break command - if (!commandmode) cmdpause++; + if (!commandmode) { + cmdpause++; + if (cmdpause > (20 * reg[MREG_GUARD_TIME])) { + if (plusinc == 0) { + plusinc = 1; + } + else if (plusinc == 4) { + LOG_MSG("Modem: Entering command mode(escape sequence)"); + commandmode = true; + SendRes(ResOK); + plusinc = 0; + } + } + } + // Handle incoming data from serial port, read as much as available CSerial::setCTS(true); // buffer will get 'emptier', new data can be received while (tqueue->inuse()) { @@ -716,29 +729,18 @@ void CSerialModem::Timer2(void) { } } else {// + character - // 1000 ticks have passed, can check for pause command - if (cmdpause > 1000) { - if (txval == reg[MREG_ESCAPE_CHAR]) // + - { - plusinc++; - if (plusinc >= 3) { - LOG_MSG("Modem: Entering command mode(escape sequence)"); - commandmode = true; - SendRes(ResOK); - plusinc = 0; - } - sendbyte=false; - } else { - plusinc=0; - } - // If not a special pause command, should go for bigger blocks to send + if (plusinc >= 1 && plusinc <= 3 && txval == reg[MREG_ESCAPE_CHAR]) // + + plusinc++; + else { + plusinc = 0; } + cmdpause = 0; tmpbuf[txbuffersize] = txval; txbuffersize++; } } // while loop - if (clientsocket && sendbyte && txbuffersize) { + if (clientsocket && txbuffersize) { // down here it saves a lot of network traffic if (!clientsocket->SendArray(tmpbuf,txbuffersize)) { SendRes(ResNOCARRIER); @@ -759,7 +761,6 @@ void CSerialModem::Timer2(void) { TelnetEmulation(tmpbuf, usesize); else rqueue->adds(tmpbuf,usesize); - cmdpause = 0; } } // Check for incoming calls diff --git a/src/hardware/serialport/softmodem.h b/src/hardware/serialport/softmodem.h index c3e01d61..22df203b 100644 --- a/src/hardware/serialport/softmodem.h +++ b/src/hardware/serialport/softmodem.h @@ -165,6 +165,7 @@ private: #define MREG_CR_CHAR 3 #define MREG_LF_CHAR 4 #define MREG_BACKSPACE_CHAR 5 +#define MREG_GUARD_TIME 12 class CSerialModem : public CSerial {