|
|
1.1.1.2 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Not a parser, but parallel and serial emulation for Win32
5: *
6: * Copyright 1997 Mathias Ortmann
1.1.1.3 ! root 7: * Copyright 1998-1999 Brian King - added MIDI output support
1.1.1.2 root 8: */
9:
10: #include "config.h"
11: #include "sysconfig.h"
12: #include <windows.h>
1.1.1.3 ! root 13: #include <winspool.h>
1.1.1.2 root 14: #include <stdlib.h>
15: #include <stdarg.h>
1.1.1.3 ! root 16: #include <mmsystem.h>
! 17: #include <ddraw.h>
1.1.1.2 root 18: #include <commctrl.h>
19: #include <commdlg.h>
20: #include <stdio.h>
21: #include <fcntl.h>
22: #include <sys/stat.h>
23: #include <io.h>
24:
25: #include "sysdeps.h"
26: #include "options.h"
27: #include "gensound.h"
28: #include "events.h"
29: #include "uae.h"
1.1.1.3 ! root 30: #include "memory.h"
1.1.1.2 root 31: #include "custom.h"
32: #include "osdep/win32gui.h"
1.1.1.3 ! root 33: #include "osdep/parser.h"
! 34: #include "osdep/midi.h"
1.1.1.2 root 35:
36: UINT prttimer;
37: char prtbuf[PRTBUFSIZE];
1.1.1.3 ! root 38: int prtbufbytes,wantwrite;
1.1.1.2 root 39: HANDLE hPrt = INVALID_HANDLE_VALUE;
1.1.1.3 ! root 40: DWORD dwJob;
1.1.1.2 root 41: extern HWND hAmigaWnd;
1.1.1.3 ! root 42: OVERLAPPED ol = { 0 };
1.1.1.2 root 43:
44: void flushprtbuf (void)
45: {
1.1.1.3 ! root 46: DWORD written = 0;
1.1.1.2 root 47:
48: if (hPrt != INVALID_HANDLE_VALUE)
1.1.1.3 ! root 49: {
! 50: if( WritePrinter( hPrt, prtbuf, prtbufbytes, &written ) )
! 51: {
! 52: if( written != prtbufbytes )
! 53: write_log( "PRINTER: Only wrote %d of %d bytes!\n", written, prtbufbytes );
! 54: }
! 55: else
! 56: {
! 57: write_log( "PRINTER: Couldn't write data!\n" );
! 58: }
! 59: }
! 60: else
! 61: {
! 62: write_log( "PRINTER: Not open!\n" );
! 63: }
1.1.1.2 root 64: prtbufbytes = 0;
65: }
66:
67: void finishjob (void)
68: {
69: flushprtbuf ();
70: }
71:
1.1.1.3 ! root 72: void DoSomeWeirdPrintingStuff( char val )
1.1.1.2 root 73: {
74: if (prttimer)
75: KillTimer (hAmigaWnd, prttimer);
76: if (prtbufbytes < PRTBUFSIZE) {
1.1.1.3 ! root 77: prtbuf[prtbufbytes++] = val;
1.1.1.2 root 78: prttimer = SetTimer (hAmigaWnd, 1, 2000, NULL);
79: } else {
80: flushprtbuf ();
1.1.1.3 ! root 81: *prtbuf = val;
1.1.1.2 root 82: prtbufbytes = 1;
83: prttimer = 0;
84: }
85: }
86:
1.1.1.3 ! root 87: FILE *openprinter( void )
! 88: {
! 89: FILE *result = NULL;
! 90: DOC_INFO_1 DocInfo;
! 91:
! 92: if( ( hPrt == INVALID_HANDLE_VALUE ) && *currprefs.prtname )
! 93: {
! 94: if( OpenPrinter(currprefs.prtname, &hPrt, NULL ) )
! 95: {
! 96: // Fill in the structure with info about this "document."
! 97: DocInfo.pDocName = "My Document";
! 98: DocInfo.pOutputFile = NULL;
! 99: DocInfo.pDatatype = "RAW";
! 100: // Inform the spooler the document is beginning.
! 101: if( (dwJob = StartDocPrinter( hPrt, 1, (LPSTR)&DocInfo )) == 0 )
! 102: {
! 103: ClosePrinter( hPrt );
! 104: hPrt = INVALID_HANDLE_VALUE;
! 105: }
! 106: else if( StartPagePrinter( hPrt ) )
! 107: {
! 108: result = 1;
! 109: }
! 110: }
! 111: else
! 112: {
! 113: hPrt = INVALID_HANDLE_VALUE; // Stupid bug in Win32, where OpenPrinter fails, but hPrt ends up being zero
! 114: }
! 115: }
! 116: if( hPrt != INVALID_HANDLE_VALUE )
! 117: {
! 118: write_log( "PRINTER: Opening printer \"%s\" with handle 0x%x.\n", currprefs.prtname, hPrt );
! 119: }
! 120: else if( *currprefs.prtname )
! 121: {
! 122: write_log( "PRINTER: ERROR - Couldn't open printer \"%s\" for output.\n", currprefs.prtname );
! 123: }
! 124:
! 125: return result;
! 126: }
! 127:
! 128: void closeprinter( void )
! 129: {
! 130: if( hPrt != INVALID_HANDLE_VALUE )
! 131: {
! 132: EndPagePrinter( hPrt );
! 133: EndDocPrinter( hPrt );
! 134: ClosePrinter( hPrt );
! 135: hPrt = INVALID_HANDLE_VALUE;
! 136: write_log( "PRINTER: Closing printer.\n" );
! 137: }
! 138: KillTimer( hAmigaWnd, prttimer );
! 139: prttimer = 0;
! 140: }
! 141:
! 142: void putprinter (char val)
! 143: {
! 144: DoSomeWeirdPrintingStuff( val );
! 145: }
! 146:
1.1.1.2 root 147: static HANDLE hCom = INVALID_HANDLE_VALUE;
1.1.1.3 ! root 148: static HANDLE writeevent = NULL;
1.1.1.2 root 149: static DCB dcb;
150:
151: char inbuf[1024], outbuf[1024];
152: int inptr, inlast, outlast;
153:
154: int openser (char *sername)
155: {
156: char buf[32];
157: COMMTIMEOUTS CommTimeOuts;
158:
159: sprintf (buf, "\\.\\\\%s", sername);
160:
161: if (!(writeevent = CreateEvent (NULL, TRUE, FALSE, NULL))) {
1.1.1.3 ! root 162: write_log ("SERIAL: Failed to create event!\n");
1.1.1.2 root 163: return 0;
164: }
165: if ((hCom = CreateFile (buf, GENERIC_READ | GENERIC_WRITE,
166: 0,
167: NULL,
168: OPEN_EXISTING,
169: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
170: NULL)) != INVALID_HANDLE_VALUE) {
171: SetCommMask (hCom, EV_RXFLAG);
1.1.1.3 ! root 172: SetupComm (hCom, 65536,128);
1.1.1.2 root 173: PurgeComm (hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
174: CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
175: CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
176: CommTimeOuts.ReadTotalTimeoutConstant = 0;
177: CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
178: CommTimeOuts.WriteTotalTimeoutConstant = 0;
179: SetCommTimeouts (hCom, &CommTimeOuts);
180:
181: GetCommState (hCom, &dcb);
182:
183: dcb.BaudRate = 9600;
1.1.1.3 ! root 184: //dcb.ByteSize = 8;
! 185: //dcb.Parity = 0;
! 186: //dcb.StopBits = NOPARITY;
! 187:
! 188: //dcb.fOutxCtsFlow = TRUE;
! 189: //dcb.fOutxDsrFlow = FALSE;
! 190: //dcb.fDtrControl = DTR_CONTROL_ENABLE;
! 191: //dcb.fTXContinueOnXoff = FALSE;
! 192: //dcb.fOutX = FALSE;
! 193: //dcb.fInX = FALSE;
! 194: //dcb.fNull = FALSE;
! 195: //dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
! 196: //dcb.fAbortOnError = FALSE;
1.1.1.2 root 197:
198: if (SetCommState (hCom, &dcb)) {
1.1.1.3 ! root 199: write_log ("SERIAL: Using %s\n", sername);
1.1.1.2 root 200: return 1;
201: }
202: CloseHandle (hCom);
203: hCom = INVALID_HANDLE_VALUE;
204: }
205: return 0;
206: }
207:
208: void closeser (void)
209: {
1.1.1.3 ! root 210: if (hCom != INVALID_HANDLE_VALUE)
! 211: {
! 212: CloseHandle (hCom);
! 213: hCom = INVALID_HANDLE_VALUE;
1.1.1.2 root 214: }
1.1.1.3 ! root 215: if( writeevent )
! 216: CloseHandle( writeevent );
1.1.1.2 root 217: }
218:
1.1.1.3 ! root 219: void doserout( void )
1.1.1.2 root 220: {
221: DWORD dwErrorFlags;
222: unsigned long actual;
223:
1.1.1.3 ! root 224: if (hCom != INVALID_HANDLE_VALUE)
! 225: {
! 226: if (outlast)
! 227: {
! 228: ResetEvent (ol.hEvent = writeevent);
! 229: actual = 0;
! 230:
! 231: if (!WriteFile (hCom, outbuf, outlast, &actual, &ol))
! 232: {
! 233: //GetOverlappedResult (hCom, &ol, &actual, FALSE);
! 234:
! 235: /* while (outlast -= actual)
! 236: {
! 237: if ((dwErrorFlags = GetLastError ()) == ERROR_IO_INCOMPLETE || dwErrorFlags == ERROR_IO_PENDING)
! 238: {
1.1.1.2 root 239: actual = 0;
240: GetOverlappedResult (hCom, &ol, &actual, FALSE);
241:
1.1.1.3 ! root 242: if ((dwErrorFlags = GetLastError ()) != ERROR_IO_INCOMPLETE && dwErrorFlags != ERROR_IO_PENDING)
! 243: {
1.1.1.2 root 244: write_log ("writeser: error %d, lost %d chars!\n", GetLastError (), outlast - actual);
245: outlast = 0;
246: break;
247: }
1.1.1.3 ! root 248: if (WaitForSingleObject (writeevent, 100) == WAIT_TIMEOUT)
! 249: {
1.1.1.2 root 250: write_log ("writeser: timeout, lost %d chars!\n", outlast - actual);
251: outlast = 0;
252: break;
253: }
1.1.1.3 ! root 254: }
! 255: else
! 256: {
! 257: if (dwErrorFlags)
! 258: {
1.1.1.2 root 259: write_log ("writeser: error %d while writing, lost %d chars!\n", dwErrorFlags, outlast - actual);
260: ClearCommError (hCom, &dwErrorFlags, NULL);
261: }
1.1.1.3 ! root 262:
1.1.1.2 root 263: outlast = 0;
264: break;
265: }
1.1.1.3 ! root 266:
1.1.1.2 root 267: }
1.1.1.3 ! root 268: */
! 269: outlast=0;
1.1.1.2 root 270: }
271: }
1.1.1.3 ! root 272: }
! 273: else
! 274: {
1.1.1.2 root 275: outlast = 0;
276: inptr = inlast = 0;
277: }
278: }
279:
280: void writeser (char c)
281: {
1.1.1.3 ! root 282: COMSTAT ComStat;
! 283: DWORD dwErrorFlags;
! 284: extern uae_u16 serdat;
! 285: {
! 286: outbuf[ outlast++ ] = c;
! 287: //serial
! 288: if (outlast == 100/*sizeof outbuf*/)
! 289: {
! 290: doserout();
! 291: wantwrite=2000;
! 292: return;
! 293: }
! 294: }
! 295: serdat|=0x2000; /* Set TBE in the SERDATR ... */
! 296: intreq|=1; /* ... and in INTREQ register */
! 297: INTREQ( 0x8000 | 0x01 );
! 298: }
! 299: int state,oldstatelw,oldstaterw;
! 300:
! 301: void hsyncstuff( void ) //only generate Interrupts when
! 302: //writebuffer is complete flushed
! 303: //check state of lwin rwin
! 304:
! 305: {
! 306: static int keycheck=0;
! 307: extern uae_u16 serdat;
! 308: extern int serdev;
! 309:
! 310: keycheck++;
! 311: if(keycheck==1000)
! 312: {
! 313: state=GetAsyncKeyState(VK_LWIN);
! 314:
! 315: if (state!=oldstatelw){my_kbd_handler(VK_LWIN,0,state);
! 316: oldstatelw=state;
! 317: }
! 318: state=GetAsyncKeyState(VK_RWIN);
! 319:
! 320: if (state!=oldstaterw){my_kbd_handler(VK_RWIN,0,state);
! 321: oldstaterw=state;
! 322: }
! 323: keycheck=0;
! 324: }
! 325:
! 326: if (!serdev) /* || (serdat&0x4000)) */
! 327: return;
! 328:
! 329: if(wantwrite)
! 330: {
! 331: int actual=0;
! 332: if(wantwrite==1)
! 333: {
! 334: serdat|=0x2000;
! 335: intreq|=0x1;
! 336: INTREQ(0x8000 | (0x01));
! 337: wantwrite=0;
! 338: }
! 339: wantwrite--;
! 340: GetOverlappedResult (hCom, &ol, &actual, FALSE);
! 341: if (actual==100)
! 342: { serdat|=0x2000;
! 343: intreq|=0x1;
! 344: INTREQ(0x8000 | (0x01));
! 345: wantwrite=0;
! 346: }
! 347: }
1.1.1.2 root 348: }
349:
350: int readser (char *buffer)
351: {
352: COMSTAT ComStat;
353: DWORD dwErrorFlags;
354: DWORD result;
355: unsigned long actual;
1.1.1.3 ! root 356:
! 357:
! 358: {
! 359:
! 360:
! 361: //
! 362: //if(intreq&&1);
! 363: //else
! 364: /*if (WaitForSingleObject (writeevent,0) != WAIT_TIMEOUT)
! 365: {
! 366: serdat|=0x2000;
! 367: intreq|=0x1;
! 368: INTREQ(0x8000 | (0x01));
! 369: ResetEvent (ol.hEvent = writeevent);
1.1.1.2 root 370:
371: }
1.1.1.3 ! root 372: else {INTREQ(0x1);
! 373: serdat &=0xdfff;
! 374: }*/
! 375: if (inptr < inlast)
! 376: {
1.1.1.2 root 377: *buffer = inbuf[inptr++];
378: return 1;
379: }
1.1.1.3 ! root 380: if (hCom != INVALID_HANDLE_VALUE)
! 381: {
! 382: inptr = inlast = 0;
! 383:
! 384: /* only try to read number of bytes in queue */
! 385: ClearCommError (hCom, &dwErrorFlags, &ComStat);
! 386: if (ComStat.cbInQue)
! 387: {
! 388:
! 389: if (!ReadFile (hCom, inbuf, min (ComStat.cbInQue, sizeof inbuf), &inlast, &ol))
! 390: {
! 391: if (GetLastError () == ERROR_IO_PENDING)
! 392: {
! 393: write_log ("readser: INTERNAL ERROR - intermittent loss of serial data!\n");
! 394: for (;;)
! 395: {
! 396: actual = 0;
! 397: result = GetOverlappedResult (hCom, &ol, &actual, TRUE);
! 398: inlast += actual;
! 399:
! 400: if (result)
! 401: break;
! 402:
! 403: if (GetLastError () != ERROR_IO_INCOMPLETE)
! 404: {
! 405: ClearCommError (hCom, &dwErrorFlags, &ComStat);
! 406: break;
! 407: }
! 408: }
! 409: }
! 410: else
! 411: {
! 412: ClearCommError (hCom, &dwErrorFlags, &ComStat);
! 413: }
! 414: }
! 415: }
! 416: if (inptr < inlast)
! 417: {
! 418: *buffer = inbuf[inptr++];
! 419: return 1;
! 420: }
! 421: }
1.1.1.2 root 422: }
423: return 0;
424: }
425:
426: void getserstat (int *status)
427: {
428: DWORD stat;
429:
430: *status = 0;
431: if (hCom != INVALID_HANDLE_VALUE) {
1.1.1.3 ! root 432: //GetCommModemStatus (hCom, &stat);
1.1.1.2 root 433: /* @@@ This "ouch" section was #ifdef 0 before - BDK */
434: #if 0
435: #define TIOCM_CAR 1
436: #define TIOCM_DSR 2
437: /* ouch */
1.1.1.3 ! root 438: if (stat & MS_CTS_ON)
! 439: *status |= TIOCM_CAR;
1.1.1.2 root 440: if (stat & MS_RLSD_ON)
441: *status |= TIOCM_CAR;
442: if (stat & MS_DSR_ON)
443: *status |= TIOCM_DSR;
444: #endif
445: }
446: }
447:
448: int setbaud (long baud)
449: {
1.1.1.3 ! root 450: write_log( "Baud-rate is %d\n", baud );
! 451: {
! 452: if (hCom != INVALID_HANDLE_VALUE)
! 453: {
! 454: if (GetCommState (hCom, &dcb))
! 455: {
! 456: dcb.BaudRate = baud;
! 457: if (!SetCommState (hCom, &dcb))
! 458: write_log ("SERIAL: Error setting baud rate %d!\n", baud);
! 459: }
! 460: else
! 461: {
! 462: write_log ("SERIAL: setbaud internal error!\n");
! 463: }
! 464: }
1.1.1.2 root 465: }
466: return 0;
467: }
468:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.