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