Source to src/od-win32/parser.c


Enter a symbol's name here to quickly find it.

/* 
 * UAE - The Un*x Amiga Emulator
 *
 * Not a parser, but parallel and serial emulation for Win32
 *
 * Copyright 1997 Mathias Ortmann
 * Copyright 1998-1999 Brian King - added MIDI output support
 */

#include "sysconfig.h"
#include <windows.h>
#include <winspool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <mmsystem.h>
#include <ddraw.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>

#include "sysdeps.h"
#include "options.h"
#include "gensound.h"
#include "events.h"
#include "uae.h"
#include "memory.h"
#include "custom.h"
#include "osdep/win32gui.h"
#include "osdep/parser.h"
#include "osdep/midi.h"

UINT prttimer;
char prtbuf[PRTBUFSIZE];
int prtbufbytes,wantwrite;
HANDLE hPrt = INVALID_HANDLE_VALUE;
DWORD  dwJob;
extern HWND hAmigaWnd;
 OVERLAPPED ol = { 0 };

void flushprtbuf (void)
{
    DWORD written = 0;

    if (hPrt != INVALID_HANDLE_VALUE)
    {
	if( WritePrinter( hPrt, prtbuf, prtbufbytes, &written ) )
	{
	    if( written != prtbufbytes )
		write_log ( "PRINTER: Only wrote %d of %d bytes!\n", written, prtbufbytes );
	}
	else
	{
	    write_log ( "PRINTER: Couldn't write data!\n" );
	}
    }
    else
    {
	write_log ( "PRINTER: Not open!\n" );
    }
    prtbufbytes = 0;
}

void finishjob (void)
{
    flushprtbuf ();
}

void DoSomeWeirdPrintingStuff( char val )
{
    if (prttimer)
	KillTimer (hAmigaWnd, prttimer);
    if (prtbufbytes < PRTBUFSIZE) {
	prtbuf[prtbufbytes++] = val;
	prttimer = SetTimer (hAmigaWnd, 1, 2000, NULL);
    } else {
	flushprtbuf ();
	*prtbuf = val;
	prtbufbytes = 1;
	prttimer = 0;
    }
}

FILE *openprinter( void )
{
    FILE *result = NULL;
    DOC_INFO_1 DocInfo;

    if( ( hPrt == INVALID_HANDLE_VALUE ) && *currprefs.prtname )
    {
	if( OpenPrinter(currprefs.prtname, &hPrt, NULL ) )
	{
	    // Fill in the structure with info about this "document."
	    DocInfo.pDocName = "My Document";
	    DocInfo.pOutputFile = NULL;
	    DocInfo.pDatatype = "RAW";
	    // Inform the spooler the document is beginning.
	    if( (dwJob = StartDocPrinter( hPrt, 1, (LPSTR)&DocInfo )) == 0 )
	    {
		ClosePrinter( hPrt );
		hPrt = INVALID_HANDLE_VALUE;
	    }
	    else if( StartPagePrinter( hPrt ) )
	    {
		result = 1;
	    }
	}
	else
	{
	    hPrt = INVALID_HANDLE_VALUE; // Stupid bug in Win32, where OpenPrinter fails, but hPrt ends up being zero
	}
    }
    if( hPrt != INVALID_HANDLE_VALUE )
    {
	write_log ( "PRINTER: Opening printer \"%s\" with handle 0x%x.\n", currprefs.prtname, hPrt );
    }
    else if( *currprefs.prtname )
    {
	write_log ( "PRINTER: ERROR - Couldn't open printer \"%s\" for output.\n", currprefs.prtname );
    }

    return result;
}

void closeprinter( void )
{
    if( hPrt != INVALID_HANDLE_VALUE )
    {
	EndPagePrinter( hPrt );
	EndDocPrinter( hPrt );
	ClosePrinter( hPrt );
	hPrt = INVALID_HANDLE_VALUE;
	write_log ( "PRINTER: Closing printer.\n" );
    }
    KillTimer( hAmigaWnd, prttimer );
    prttimer = 0;
}

void putprinter (char val)
{
    DoSomeWeirdPrintingStuff( val );
}

static HANDLE hCom = INVALID_HANDLE_VALUE;
static HANDLE writeevent = NULL;
static DCB dcb;

char inbuf[1024], outbuf[1024];
int inptr, inlast, outlast;

int openser (char *sername)
{
    char buf[32];
    COMMTIMEOUTS CommTimeOuts;

    sprintf (buf, "\\.\\\\%s", sername);

    if (!(writeevent = CreateEvent (NULL, TRUE, FALSE, NULL))) {
	write_log ("SERIAL: Failed to create event!\n");
	return 0;
    }
    if ((hCom = CreateFile (buf, GENERIC_READ | GENERIC_WRITE,
			    0,
			    NULL,
			    OPEN_EXISTING,
			    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
			    NULL)) != INVALID_HANDLE_VALUE) {
	SetCommMask (hCom, EV_RXFLAG);
	SetupComm (hCom, 65536,128);
	PurgeComm (hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 0;
	SetCommTimeouts (hCom, &CommTimeOuts);

	GetCommState (hCom, &dcb);

	dcb.BaudRate = 9600;
	//dcb.ByteSize = 8;
	//dcb.Parity = 0;
	//dcb.StopBits = NOPARITY;

	//dcb.fOutxCtsFlow = TRUE;
	//dcb.fOutxDsrFlow = FALSE;
	//dcb.fDtrControl = DTR_CONTROL_ENABLE;
	//dcb.fTXContinueOnXoff = FALSE;
	//dcb.fOutX = FALSE;
	//dcb.fInX = FALSE;
	//dcb.fNull = FALSE;
	//dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
	//dcb.fAbortOnError = FALSE;

	if (SetCommState (hCom, &dcb)) {
	    write_log ("SERIAL: Using %s\n", sername);
	    return 1;
	}
	CloseHandle (hCom);
	hCom = INVALID_HANDLE_VALUE;
    }
    return 0;
}

void closeser (void)
{
    if (hCom != INVALID_HANDLE_VALUE) 
    {
	    CloseHandle (hCom);
	    hCom = INVALID_HANDLE_VALUE;
    }
    if( writeevent )
	CloseHandle( writeevent );
}

void doserout( void )
{
    DWORD dwErrorFlags;
    unsigned long actual;

    if (hCom != INVALID_HANDLE_VALUE) 
    {
	if (outlast) 
	{
	    ResetEvent (ol.hEvent = writeevent);
	    actual = 0;
				    
	    if (!WriteFile (hCom, outbuf, outlast, &actual, &ol)) 
	    {
			 //GetOverlappedResult (hCom, &ol, &actual, FALSE);

	     /*   while (outlast -= actual) 
		{
		    if ((dwErrorFlags = GetLastError ()) == ERROR_IO_INCOMPLETE || dwErrorFlags == ERROR_IO_PENDING) 
		    {
			actual = 0;
			GetOverlappedResult (hCom, &ol, &actual, FALSE);

			if ((dwErrorFlags = GetLastError ()) != ERROR_IO_INCOMPLETE && dwErrorFlags != ERROR_IO_PENDING) 
			{
			    write_log ("writeser: error %d, lost %d chars!\n", GetLastError (), outlast - actual);
			    outlast = 0;
			    break;
			}
			if (WaitForSingleObject (writeevent, 100) == WAIT_TIMEOUT) 
			{
			    write_log ("writeser: timeout, lost %d chars!\n", outlast - actual);
			    outlast = 0;
			    break;
			}
		    }
		    else
		    {
			if (dwErrorFlags) 
			{
			    write_log ("writeser: error %d while writing, lost %d chars!\n", dwErrorFlags, outlast - actual);
			    ClearCommError (hCom, &dwErrorFlags, NULL);
			}
			
			outlast = 0;
			break;
		    }
			
		}
		*/
	outlast=0;
	    }
	}
    }
    else 
    {
	outlast = 0;
	inptr = inlast = 0;
    }
}

void writeser (char c)
{
	COMSTAT ComStat;
    DWORD dwErrorFlags;
	extern 	uae_u16 serdat;
    {
	outbuf[ outlast++ ] = c;
//serial
	if (outlast == 100/*sizeof outbuf*/)
	{
	    doserout();
	wantwrite=2000;
		return;
	}
    }
    serdat|=0x2000; /* Set TBE in the SERDATR ... */
    intreq|=1;      /* ... and in INTREQ register */
    INTREQ( 0x8000 | 0x01 );
}
int state,oldstatelw,oldstaterw;

void hsyncstuff( void )   //only generate Interrupts when 
//writebuffer is complete flushed
//check state of lwin rwin

{
    static int keycheck=0;
    extern 	uae_u16 serdat;
    extern int serdev;
    
    keycheck++;
    if(keycheck==1000)
    {
	state=GetAsyncKeyState(VK_LWIN);
	
	if (state!=oldstatelw){my_kbd_handler(VK_LWIN,0,state);
	oldstatelw=state;
	}
	state=GetAsyncKeyState(VK_RWIN);
	
	if (state!=oldstaterw){my_kbd_handler(VK_RWIN,0,state);
	oldstaterw=state;
	}
	keycheck=0;
    }
    
    if (!serdev)           /* || (serdat&0x4000)) */
	return;

    if(wantwrite)
    {
	int actual=0;
	if(wantwrite==1)
	{
	    serdat|=0x2000;
	    intreq|=0x1;
	    INTREQ(0x8000 | (0x01));
	    wantwrite=0;
	}
	wantwrite--;
	GetOverlappedResult (hCom, &ol, &actual, FALSE);           	
	if (actual==100)
	{		 serdat|=0x2000;
	intreq|=0x1;
	INTREQ(0x8000 | (0x01));
	wantwrite=0;
	}
    }
}

int readser (char *buffer)
{
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    DWORD result;
    unsigned long actual;
    
    
    {
	
	
	//	
		//if(intreq&&1);
		//else
	/*if (WaitForSingleObject (writeevent,0) != WAIT_TIMEOUT) 
			{
			 serdat|=0x2000;
		intreq|=0x1;
		INTREQ(0x8000 | (0x01));
		 ResetEvent (ol.hEvent = writeevent);

			}
	else {INTREQ(0x1);
	serdat &=0xdfff;
	}*/
	if (inptr < inlast) 
	{
	    *buffer = inbuf[inptr++];
	    return 1;
	}
	if (hCom != INVALID_HANDLE_VALUE) 
	{
	    inptr = inlast = 0;
	    
	    /* only try to read number of bytes in queue */
	    ClearCommError (hCom, &dwErrorFlags, &ComStat);
	    if (ComStat.cbInQue) 
	    {
		
		if (!ReadFile (hCom, inbuf, min (ComStat.cbInQue, sizeof inbuf), &inlast, &ol)) 
		{
		    if (GetLastError () == ERROR_IO_PENDING) 
		    {
			write_log ("readser: INTERNAL ERROR - intermittent loss of serial data!\n");
			for (;;) 
			{
			    actual = 0;
			    result = GetOverlappedResult (hCom, &ol, &actual, TRUE);
			    inlast += actual;
			    
			    if (result)
				break;
			    
			    if (GetLastError () != ERROR_IO_INCOMPLETE) 
			    {
				ClearCommError (hCom, &dwErrorFlags, &ComStat);
				break;
			    }
			}
		    }
		    else
		    {
			ClearCommError (hCom, &dwErrorFlags, &ComStat);
		    }
		}
	    }
	    if (inptr < inlast) 
	    {
		*buffer = inbuf[inptr++];
		return 1;
	    }
	}
    }
    return 0;
}

void getserstat (int *status)
{
    DWORD stat;

    *status = 0;
    if (hCom != INVALID_HANDLE_VALUE) {
	//GetCommModemStatus (hCom, &stat);
/* @@@ This "ouch" section was #ifdef 0 before - BDK */
#if 0
#define TIOCM_CAR 1
#define TIOCM_DSR 2
    /* ouch */
    if (stat & MS_CTS_ON)
	    *status |= TIOCM_CAR;
	if (stat & MS_RLSD_ON)
	    *status |= TIOCM_CAR;
	if (stat & MS_DSR_ON)
	    *status |= TIOCM_DSR;
#endif
    }
}

int setbaud (long baud)
{
    write_log ( "Baud-rate is %d\n", baud );
    {
	if (hCom != INVALID_HANDLE_VALUE) 
	{
		if (GetCommState (hCom, &dcb)) 
	    {
		    dcb.BaudRate = baud;
		    if (!SetCommState (hCom, &dcb))
			write_log ("SERIAL: Error setting baud rate %d!\n", baud);
		} 
	    else
	    {
		    write_log ("SERIAL: setbaud internal error!\n");
	    }
	}
    }
    return 0;
}