]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
rpmodem
authorToni Wilen <twilen@winuae.net>
Wed, 7 Dec 2022 18:24:52 +0000 (20:24 +0200)
committerToni Wilen <twilen@winuae.net>
Wed, 7 Dec 2022 18:24:52 +0000 (20:24 +0200)
cia.cpp
include/serial.h
od-win32/cloanto/RetroPlatformIPC.h
od-win32/rp.cpp
od-win32/rp.h
od-win32/serial_win32.cpp
od-win32/win32.cpp

diff --git a/cia.cpp b/cia.cpp
index 1ed9cb973576855950223c639a40d1c7974dcc57..ec86138211bd2a9c3fb250f6d14a4ef4816b01fe 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -1797,10 +1797,7 @@ static uae_u8 ReadCIAB(uae_u32 addr, uae_u32 *flags)
        case 0:
                tmp = (c->pra & c->dra) | (c->dra ^ 0xff);
 #ifdef SERIAL_PORT
-               if (currprefs.use_serial) {
-                       tmp &= 7;
-                       tmp |= serial_readstatus(c->dra) & 0xf8;
-               }
+               tmp |= serial_readstatus(tmp, c->dra);
 #endif
 #ifdef PARALLEL_PORT
                if (isprinter() > 0) {
@@ -2049,8 +2046,7 @@ static void WriteCIAB(uae_u16 addr, uae_u8 val, uae_u32 *flags)
                write_ciab_serial(val, c->pra, c->dra, c->dra);
                c->pra = val;
 #ifdef SERIAL_PORT
-               if (currprefs.use_serial)
-                       serial_writestatus(c->pra, c->dra);
+               serial_writestatus(c->pra, c->dra);
 #endif
 #ifdef PARALLEL_PORT
                if (isprinter() < 0) {
index a0d782df88bd037836bc2de9209e3eae48b61b49..a9f80c6752b7f769bd99dc3c7f1c0f0b96134e4d 100644 (file)
@@ -18,12 +18,11 @@ extern void serial_dtr_off (void);
 extern void serial_dtr_on (void);
 
 extern uae_u16 SERDATR (void);
-extern int   SERDATS (void);
 extern void  SERPER (uae_u16 w);
 extern void  SERDAT (uae_u16 w);
 
 extern uae_u8 serial_writestatus (uae_u8, uae_u8);
-extern uae_u8 serial_readstatus (uae_u8);
+extern uae_u8 serial_readstatus (uae_u8, uae_u8);
 extern void serial_uartbreak (int);
 extern void serial_rbf_clear (void);
 extern uae_u16 serdat;
@@ -36,7 +35,6 @@ extern void serial_hsynchandler(void);
 extern void serial_rethink(void);
 
 extern int uaeser_getdatalength (void);
-extern int uaeser_getbytespending (void*);
 extern int uaeser_open (void*, void*, int);
 extern void uaeser_close (void*);
 extern int uaeser_read (void*, uae_u8 *data, uae_u32 len);
index a4cbb70d503d788e809859cb336634fe6d64f64c..5634681631a70245c680a1c88f85c98a563c076c 100644 (file)
@@ -9,7 +9,7 @@
          : Software Foundation.
  Authors : os, m
  Created : 2007-08-27 13:55:49
- Updated : 2022-12-03 11:27:12
+ Updated : 2022-12-06 12:23:10
  Comment : RetroPlatform Player interprocess communication include file
  *****************************************************************************/
 
@@ -78,6 +78,7 @@
 #define RP_IPC_TO_HOST_DEVICEWRITEBYTE      (WM_APP + 48) // introduced in RetroPlatform API 10.0
 #define RP_IPC_TO_HOST_PRIVATE_CANTYPECLIPB (WM_APP + 49) // introduced in RetroPlatform API 10.0
 #define RP_IPC_TO_HOST_DEVICEWRITEBYTES     (WM_APP + 50) // introduced in RetroPlatform API 10.1
+#define RP_IPC_TO_HOST_DEVICESETSIGNALS     (WM_APP + 51) // introduced in RetroPlatform API 10.1
 
 // ****************************************************************************
 //  Host-to-Guest Messages
 #define RP_IPC_TO_GUEST_SETCURSORPOSITION       (WM_APP + 246) // introduced in RetroPlatform API 7.9
 #define RP_IPC_TO_GUEST_PRIVATE_TEXTSELMENU  (WM_APP + 247) // introduced in RetroPlatform API 7.10
 #define RP_IPC_TO_GUEST_EXECUTE              (WM_APP + 248) // introduced in RetroPlatform API 10.0
+#define RP_IPC_TO_GUEST_DEVICEWRITEBYTE      (WM_APP + 249) // introduced in RetroPlatform API 10.1
+#define RP_IPC_TO_GUEST_DEVICESETSIGNALS     (WM_APP + 250) // introduced in RetroPlatform API 10.1
 
 // ****************************************************************************
 //  Message Data Structures and Defines
@@ -646,6 +649,16 @@ typedef struct RPExecuteResult
 #define RP_READBYTE_BYTEMASK  0x000000FF // byte mask
 
 
+// RP_IPC_TO_GUEST_DEVICESETSIGNALS flags
+#define RP_SIGNAL_CTS  0x00000001 // Clear To Send
+#define RP_SIGNAL_CD   0x00000002 // Carrier Detect
+#define RP_SIGNAL_DSR  0x00000004 // Data Set Ready
+#define RP_SIGNAL_RI   0x00000008 // Ring Indicator
+// RP_IPC_TO_HOST_DEVICESETSIGNALS flags
+#define RP_SIGNAL_RTS  0x00000010 // Request To Send
+#define RP_SIGNAL_DTR  0x00000020 // Data Terminal Ready
+
+
 // Legacy Compatibility
 #ifndef RP_NO_LEGACY
 // Changed in 7.0
index 66d98f5502b87923ee3d6e1320b31e4cbb14836c..b69e93534e38b966e63600c8ce9deaa82239775e 100644 (file)
@@ -48,9 +48,11 @@ int rp_rpescapeholdtime = 600;
 int rp_screenmode = 0;
 int rp_inputmode = 0;
 int rp_printer = 0;
+int rp_modem = 0;
 int log_rp = 2;
 static int rp_revision, rp_version, rp_build;
 static int rp_printeropen = 0;
+static int rp_modemopen = 0;
 static int max_horiz_dbl = RES_HIRES;
 static int max_vert_dbl = VRES_DOUBLE;
 
@@ -165,6 +167,8 @@ static const TCHAR *getmsg (int msg)
        case RP_IPC_TO_GUEST_SENDMOUSEEVENTS: return _T("RP_IPC_TO_GUEST_SENDMOUSEEVENTS");
        case RP_IPC_TO_GUEST_SHOWDEBUGGER: return _T("RP_IPC_TO_GUEST_SHOWDEBUGGER");
        case RP_IPC_TO_GUEST_EXECUTE: return _T("RP_IPC_TO_GUEST_EXECUTE");
+       case RP_IPC_TO_GUEST_DEVICEWRITEBYTE: return _T("RP_IPC_TO_GUEST_DEVICEWRITEBYTE");
+       case RP_IPC_TO_GUEST_DEVICESETSIGNALS: return _T("RP_IPC_TO_GUEST_DEVICESETSIGNALS");
        default: return _T("UNKNOWN");
        }
 }
@@ -1282,6 +1286,47 @@ static void dos_execute_callback(uae_u32 id, uae_u32 status, uae_u32 flags, cons
        }
 }
 
+extern bool serreceive_external(uae_u16);
+static int rp_readmodemint(WPARAM wp, LPARAM lp)
+{
+       if (wp != MAKEWORD(RP_DEVICECATEGORY_MODEM, 0)) {
+               return 0;
+       }
+       uae_u8 b = (uae_u8)lp;
+       bool v = serreceive_external(b | 0x100);
+       return v ? 1 : -1;
+}
+
+static bool modem_cts, modem_cd, modem_ri, modem_dsr;
+void rp_readmodemstatus(bool *dsr, bool *cd, bool *cts, bool *ri)
+{
+       *dsr = modem_dsr;
+       *cd = modem_cd;
+       *cts = modem_cts;
+       *ri = modem_ri;
+}
+static int rp_readmodemstatusint(WPARAM wp, LPARAM lp)
+{
+       if (wp != MAKEWORD(RP_DEVICECATEGORY_MODEM, 0)) {
+               return 0;
+       }
+       uae_u16 mask = LOWORD(lp);
+       uae_u16 val = HIWORD(lp);
+       if (mask & RP_SIGNAL_CTS) {
+               modem_cts = (val & RP_SIGNAL_CTS) != 0;
+       }
+       if (mask & RP_SIGNAL_RI) {
+               modem_ri = (val & RP_SIGNAL_RI) != 0;
+       }
+       if (mask & RP_SIGNAL_DSR) {
+               modem_dsr = (val & RP_SIGNAL_DSR) != 0;
+       }
+       if (mask & RP_SIGNAL_CD) {
+               modem_cd = (val & RP_SIGNAL_CD) != 0;
+       }
+       return 1;
+}
+
 static int dosexecute(TCHAR *file, TCHAR *currentdir, TCHAR *parms, uae_u32 stack, uae_s32 priority, uae_u32 id, uae_u32 flags, uae_u8 *bin, uae_u32 binsize)
 {
        int ret = filesys_shellexecute2(file, currentdir, parms, stack, priority, id, flags, bin, binsize, dos_execute_callback, NULL);
@@ -1536,6 +1581,10 @@ static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM
                return 1;
        case RP_IPC_TO_GUEST_EXECUTE:
                return execute(pData);
+       case RP_IPC_TO_GUEST_DEVICEWRITEBYTE:
+               return rp_readmodemint(wParam, lParam);
+       case RP_IPC_TO_GUEST_DEVICESETSIGNALS:
+               return rp_readmodemstatusint(wParam, lParam);
        }
        return FALSE;
 }
@@ -2379,6 +2428,49 @@ void rp_reset(void)
        device_add_vsync_pre(rp_vsync);
 }
 
+bool rp_ismodem(void)
+{
+       return rp_modem != 0;
+}
+void rp_writemodem(uae_u8 v)
+{
+       if (!initialized) {
+               return;
+       }
+       if (!rp_modemopen) {
+               rp_modemstate(1);
+       }
+       WPARAM unit = MAKEWORD(RP_DEVICECATEGORY_MODEM, 0);
+       RPSendMessagex(RP_IPC_TO_HOST_DEVICEWRITEBYTE, unit, v, NULL, 0, &guestinfo, NULL);
+}
+void rp_modemstate(int state)
+{
+       if (!initialized) {
+               return;
+       }
+       if (state == rp_modemopen) {
+               return;
+       }
+       WPARAM unit = MAKEWORD(RP_DEVICECATEGORY_MODEM, 0);
+       if (state) {
+               write_log(_T("RP: modem open\n"));
+               RPSendMessagex(RP_IPC_TO_HOST_DEVICEOPEN, unit, 0, NULL, 0, &guestinfo, NULL);
+       } else {
+               write_log(_T("RP: modem close\n"));
+               RPSendMessagex(RP_IPC_TO_HOST_DEVICECLOSE, unit, 0, NULL, 0, &guestinfo, NULL);
+       }
+       rp_modemopen = state;
+}
+void rp_writemodemstatus(bool rts, bool rtschanged, bool dtr, bool dtrchanged)
+{
+       if (!initialized) {
+               return;
+       }
+       WPARAM unit = MAKEWORD(RP_DEVICECATEGORY_MODEM, 0);
+       LPARAM l = MAKELONG((rtschanged ? RP_SIGNAL_RTS :0) | (dtrchanged ? RP_SIGNAL_DTR : 0), (rts ? RP_SIGNAL_RTS : 0) | (dtr ? RP_SIGNAL_DTR : 0));
+       RPSendMessagex(RP_IPC_TO_HOST_DEVICESETSIGNALS, unit, l, NULL, 0, &guestinfo, NULL);
+
+}
 
 bool rp_isprinter(void)
 {
@@ -2390,8 +2482,9 @@ bool rp_isprinteropen(void)
 }
 void rp_writeprinter(uae_char *b, int len)
 {
-       if (!initialized)
+       if (!initialized) {
                return;
+       }
        WPARAM unit = MAKEWORD(RP_DEVICECATEGORY_PRINTER, 0);
        if (!b) {
                if (rp_printeropen) {
index efff017748c394851c5384cac599e215127ca0c4..be86d77bd4e3eb21cb6d7b20977cb60584e61a55 100644 (file)
@@ -27,6 +27,11 @@ extern void rp_test(void);
 extern bool rp_isprinter(void);
 extern bool rp_isprinteropen(void);
 extern void rp_writeprinter(uae_char*, int);
+extern bool rp_ismodem(void);
+extern void rp_writemodem(uae_u8);
+extern void rp_modemstate(int);
+extern void rp_writemodemstatus(bool, bool, bool, bool);
+extern void rp_readmodemstatus(bool*,bool*,bool*,bool*);
 
 extern TCHAR *rp_param;
 extern int rp_rpescapekey;
@@ -34,6 +39,7 @@ extern int rp_rpescapeholdtime;
 extern int rp_screenmode;
 extern int rp_inputmode;
 extern int rp_printer;
+extern int rp_modem;
 extern int log_rp;
 
 extern void rp_input_change (int num);
index c757b5c87e5ca31cbbf661f5dda5dcf438fa986b..8c871f0b2671fead10e36d59b1dbc12e6ce9e77e 100644 (file)
 #include "serial.h"
 #include "enforcer.h"
 #include "arcadia.h"
+#include "parallel.h"
+#ifdef RETROPLATFORM
+#include "rp.h"
+#endif
 
 #include "parser.h"
 
@@ -57,6 +61,8 @@ static bool serempty_enabled;
 static bool serxdevice_enabled;
 static uae_u8 serstatus;
 static bool ser_accurate;
+static uae_u16 *receive_buf;
+static int receive_buf_size, receive_buf_count;
 
 #define SER_MEMORY_MAPPING _T("WinUAE_Serial")
 
@@ -312,6 +318,39 @@ static void serial_rx_irq(void)
        }
 }
 
+bool serreceive_external(uae_u16 v)
+{
+       if (data_in_serdatr) {
+               if (!receive_buf) {
+                       receive_buf_size = 200;
+                       receive_buf = xcalloc(uae_u16, receive_buf_size);
+                       if (!receive_buf) {
+                               return false;
+                       }
+               }
+               if (receive_buf_count >= receive_buf_size) {
+                       return false;
+               }
+               receive_buf[receive_buf_count++] = v;
+               return true;
+       }
+       serdatr = v;
+       serial_rx_irq();
+       return true;
+}
+
+static void receive_next_buffered(void)
+{
+       if (receive_buf && receive_buf_count > 0 && !(intreq & (1 << 11))) {
+               uae_u16 v = receive_buf[0];
+               receive_buf_count--;
+               if (receive_buf_count > 0) {
+                       memmove(receive_buf, receive_buf + 1, receive_buf_count * sizeof(uae_u16));
+               }
+               serreceive_external(v);
+       }
+}
+
 void serial_rethink(void)
 {
        if (data_in_serdatr) {
@@ -331,6 +370,7 @@ void serial_rethink(void)
                        INTREQ_INT(11, 0);
                }
        }
+       receive_next_buffered();
 }
 
 static TCHAR docharlog(int v)
@@ -555,6 +595,11 @@ static void checksend(void)
        if (cubo_enabled) {
                touch_serial_read(serdatshift);
        }
+#ifdef RETROPLATFORM
+       if (rp_ismodem()) {
+               rp_writemodem(serdatshift & 0xff);
+       }
+#endif
        if (serempty_enabled && !serxdevice_enabled) {
                return;
        }
@@ -631,7 +676,6 @@ static void sersend_serloop(uae_u32 v)
        event2_newevent_xx(-1, v * CYCLE_UNIT, 0, sersend_end);
 }
 
-
 static void sersend_ce(uae_u32 v)
 {
        if (checkshiftempty()) {
@@ -886,6 +930,7 @@ uae_u16 SERDATR(void)
        write_log (_T("SERIAL: read 0x%04x (%c) %x\n"), serdatr, dochar (serdatr), M68K_GETPC);
 #endif
        data_in_serdatr = 0;
+       receive_next_buffered();
        return serdatr;
 }
 
@@ -903,28 +948,38 @@ void serial_rbf_clear(void)
        ovrun = 0;
 }
 
-void serial_dtr_on (void)
+void serial_dtr_on(void)
 {
 #if SERIALHSDEBUG > 0
        write_log ( "SERIAL: DTR on\n" );
+#endif
+#ifdef RETROPLATFORM
+       if (rp_ismodem()) {
+               rp_modemstate(1);
+       }
 #endif
        dtr = 1;
        if (currprefs.serial_demand)
-               serial_open ();
+               serial_open();
 #ifdef SERIAL_PORT
        setserstat(TIOCM_DTR, dtr);
 #endif
 }
 
-void serial_dtr_off (void)
+void serial_dtr_off(void)
 {
 #if SERIALHSDEBUG > 0
        write_log ( "SERIAL: DTR off\n" );
+#endif
+#ifdef RETROPLATFORM
+       if (rp_ismodem()) {
+               rp_modemstate(0);
+       }
 #endif
        dtr = 0;
 #ifdef SERIAL_PORT
        if (currprefs.serial_demand)
-               serial_close ();
+               serial_close();
        setserstat(TIOCM_DTR, dtr);
 #endif
 }
@@ -944,7 +999,7 @@ static void serial_status_debug(const TCHAR *s)
 #endif
 }
 
-uae_u8 serial_readstatus (uae_u8 dir)
+uae_u8 serial_readstatus(uae_u8 v, uae_u8 dir)
 {
        int status = 0;
        uae_u8 serbits = oldserbits;
@@ -956,10 +1011,27 @@ uae_u8 serial_readstatus (uae_u8 dir)
                if (serstatus & 0x10) { // RTS -> CTS
                        status |= TIOCM_CTS;
                }
-       } else {
+       } else if (rp_ismodem()) {
+               bool dsr, cd, cts, ri;
+               rp_readmodemstatus(&dsr, &cd, &cts, &ri);
+               if (dsr) {
+                       status |= TIOCM_DSR;
+               }
+               if (cd) {
+                       status |= TIOCM_CAR;
+               }
+               if (cts) {
+                       status |= TIOCM_CTS;
+               }
+               if (ri) {
+                       status |= TIOCM_RI;
+               }
+       } else if (currprefs.use_serial) {
 #ifdef SERIAL_PORT
                getserstat(&status);
 #endif
+       } else {
+               return v;
        }
 
        if (!(status & TIOCM_CAR)) {
@@ -1010,13 +1082,31 @@ uae_u8 serial_readstatus (uae_u8 dir)
                }
        }
 
-       serbits &= 0x08 | 0x10 | 0x20;
-       oldserbits &= ~(0x08 | 0x10 | 0x20);
+       if (!isprinter()) {
+               // SEL == RI
+               v |= 4;
+               serbits |= 0x04;
+       } else {
+               serbits &= ~0x04;
+               serbits |= v & 0x04;
+       }
+
+       if (status & TIOCM_RI) {
+               if (serbits & 0x04) {
+                       serbits &= ~0x04;
+#if SERIALHSDEBUG > 0
+                       write_log("SERIAL: RI on\n");
+#endif
+               }
+       }
+
+       serbits &= 0x04 | 0x08 | 0x10 | 0x20;
+       oldserbits &= ~(0x04 | 0x08 | 0x10 | 0x20);
        oldserbits |= serbits;
 
        serial_status_debug (_T("read"));
 
-       return oldserbits;
+       return (v & (0x80 | 0x40 | 0x02 | 0x01)) | serbits;
 }
 
 uae_u8 serial_writestatus (uae_u8 newstate, uae_u8 dir)
@@ -1026,28 +1116,30 @@ uae_u8 serial_writestatus (uae_u8 newstate, uae_u8 dir)
        serstatus = newstate & dir;
 
 #ifdef SERIAL_PORT
-       if (((oldserbits ^ newstate) & 0x80) && (dir & 0x80)) {
-               if (newstate & 0x80)
-                       serial_dtr_off();
-               else
-                       serial_dtr_on();
-       }
-
-       if (!currprefs.serial_hwctsrts && (dir & 0x40)) {
-               if ((oldserbits ^ newstate) & 0x40) {
-                       if (newstate & 0x40) {
-                               setserstat (TIOCM_RTS, 0);
+       if (currprefs.use_serial) {
+               if (((oldserbits ^ newstate) & 0x80) && (dir & 0x80)) {
+                       if (newstate & 0x80)
+                               serial_dtr_off();
+                       else
+                               serial_dtr_on();
+               }
+               if (!currprefs.serial_hwctsrts && (dir & 0x40)) {
+                       if ((oldserbits ^ newstate) & 0x40) {
+                               if (newstate & 0x40) {
+                                       setserstat(TIOCM_RTS, 0);
 #if SERIALHSDEBUG > 0
-                               write_log (_T("SERIAL: RTS cleared\n"));
+                                       write_log(_T("SERIAL: RTS cleared\n"));
 #endif
-                       } else {
-                               setserstat (TIOCM_RTS, 1);
+                               } else {
+                                       setserstat(TIOCM_RTS, 1);
 #if SERIALHSDEBUG > 0
-                               write_log (_T("SERIAL: RTS set\n"));
+                                       write_log(_T("SERIAL: RTS set\n"));
 #endif
+                               }
                        }
                }
        }
+#endif
 
 #if 0 /* CIA io-pins can be read even when set to output.. */
        if ((newstate & 0x20) != (oldserbits & 0x20) && (dir & 0x20))
@@ -1060,21 +1152,28 @@ uae_u8 serial_writestatus (uae_u8 newstate, uae_u8 dir)
 
        if (logcnt > 0) {
                if (((newstate ^ oldserbits) & 0x40) && !(dir & 0x40)) {
-                       write_log (_T("SERIAL: warning, program tries to use RTS as an input! PC=%x\n"), M68K_GETPC);
+                       write_log(_T("SERIAL: warning, program tries to use RTS as an input! PC=%x\n"), M68K_GETPC);
                        logcnt--;
                }
                if (((newstate ^ oldserbits) & 0x80) && !(dir & 0x80)) {
-                       write_log (_T("SERIAL: warning, program tries to use DTR as an input! PC=%x\n"), M68K_GETPC);
+                       write_log(_T("SERIAL: warning, program tries to use DTR as an input! PC=%x\n"), M68K_GETPC);
                        logcnt--;
                }
        }
 
-#endif
+       if (rp_ismodem()) {
+               if ((oldserbits & (0x80 | 0x40)) != (newstate & (0x80 | 0x40))) {
+                       rp_writemodemstatus(
+                               (newstate & 0x40) != 0, (oldserbits & 0x40) != (newstate & 0x40),
+                               (newstate & 0x80) != 0, (oldserbits & 0x80) != (newstate & 0x80));
+               }
+       }
 
        oldserbits &= ~(0x80 | 0x40);
        newstate &= 0x80 | 0x40;
        oldserbits |= newstate;
-       serial_status_debug (_T("write"));
+
+       serial_status_debug(_T("write"));
 
        return oldserbits;
 }
@@ -1129,6 +1228,18 @@ void serial_close(void)
        sermap_deactivate();
 #endif
 #endif
+#ifdef RETROPLATFORM
+       if (rp_ismodem()) {
+               rp_modemstate(0);
+       }
+#endif
+       if (receive_buf) {
+               xfree(receive_buf);
+               receive_buf = NULL;
+       }
+       receive_buf_size = 0;
+       receive_buf_count = 0;
+
        serloop_enabled = false;
        serempty_enabled = false;
        serxdevice_enabled = false;
index 8307de5c6cc79ed38eee42f1f7111eb66d0bf51a..1f964760222e78efdd5ca0a61f0e9ad47c7f0318 100644 (file)
@@ -6658,6 +6658,10 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2)
                rp_printer = 1;
                return 1;
        }
+       if (!_tcscmp(arg, _T("rpmodem"))) {
+               rp_modem = 1;
+               return 1;
+       }
 
        if (!np)
                return 0;