mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-09-06 08:54:32 +00:00
302 lines
8.9 KiB
C++
302 lines
8.9 KiB
C++
/*
|
|
AppleWin : An Apple //e emulator for Windows
|
|
|
|
Copyright (C) 1994-1996, Michael O'Brien
|
|
Copyright (C) 1999-2001, Oliver Schmidt
|
|
Copyright (C) 2002-2005, Tom Charlesworth
|
|
Copyright (C) 2006, Tom Charlesworth, Michael Pohoreski
|
|
|
|
AppleWin is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
AppleWin is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with AppleWin; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/* Description: Serial port emulation: not SSC, but similar (same?) regs
|
|
*
|
|
* Author: Various
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#pragma hdrstop
|
|
|
|
static DWORD baudrate = CBR_19200;
|
|
static BYTE bytesize = 8;
|
|
static BYTE commandbyte = 0x00;
|
|
static HANDLE commhandle = INVALID_HANDLE_VALUE;
|
|
static DWORD comminactivity = 0;
|
|
static BYTE controlbyte = 0x1F;
|
|
static BYTE parity = NOPARITY;
|
|
static BYTE recvbuffer[9];
|
|
static DWORD recvbytes = 0;
|
|
DWORD serialport = 0;
|
|
static BYTE stopbits = ONESTOPBIT;
|
|
|
|
static void UpdateCommState ();
|
|
|
|
//===========================================================================
|
|
static BOOL CheckComm () {
|
|
comminactivity = 0;
|
|
if ((commhandle == INVALID_HANDLE_VALUE) && serialport) {
|
|
TCHAR portname[8];
|
|
wsprintf(portname,
|
|
TEXT("COM%u"),
|
|
serialport);
|
|
commhandle = CreateFile(portname,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
(LPSECURITY_ATTRIBUTES)NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (commhandle != INVALID_HANDLE_VALUE) {
|
|
UpdateCommState();
|
|
COMMTIMEOUTS ct;
|
|
ZeroMemory(&ct,sizeof(COMMTIMEOUTS));
|
|
ct.ReadIntervalTimeout = MAXDWORD;
|
|
SetCommTimeouts(commhandle,&ct);
|
|
}
|
|
}
|
|
return (commhandle != INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
//===========================================================================
|
|
static void CheckReceive () {
|
|
if (recvbytes || (commhandle == INVALID_HANDLE_VALUE))
|
|
return;
|
|
ReadFile(commhandle,recvbuffer,8,&recvbytes,NULL);
|
|
}
|
|
|
|
//===========================================================================
|
|
static void CloseComm () {
|
|
if (commhandle != INVALID_HANDLE_VALUE)
|
|
CloseHandle(commhandle);
|
|
commhandle = INVALID_HANDLE_VALUE;
|
|
comminactivity = 0;
|
|
}
|
|
|
|
//===========================================================================
|
|
static void UpdateCommState () {
|
|
if (commhandle == INVALID_HANDLE_VALUE)
|
|
return;
|
|
DCB dcb;
|
|
ZeroMemory(&dcb,sizeof(DCB));
|
|
dcb.DCBlength = sizeof(DCB);
|
|
GetCommState(commhandle,&dcb);
|
|
dcb.BaudRate = baudrate;
|
|
dcb.ByteSize = bytesize;
|
|
dcb.Parity = parity;
|
|
dcb.StopBits = stopbits;
|
|
SetCommState(commhandle,&dcb);
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommCommand (WORD, BYTE, BYTE write, BYTE value, ULONG) {
|
|
if (!CheckComm())
|
|
return 0;
|
|
if (write && (value != commandbyte)) {
|
|
commandbyte = value;
|
|
|
|
// UPDATE THE PARITY
|
|
if (commandbyte & 0x20)
|
|
switch (commandbyte & 0xC0) {
|
|
case 0x00 : parity = ODDPARITY; break;
|
|
case 0x40 : parity = EVENPARITY; break;
|
|
case 0x80 : parity = MARKPARITY; break;
|
|
case 0xC0 : parity = SPACEPARITY; break;
|
|
}
|
|
else
|
|
parity = NOPARITY;
|
|
|
|
UpdateCommState();
|
|
}
|
|
return commandbyte;
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommControl (WORD, BYTE, BYTE write, BYTE value, ULONG) {
|
|
if (!CheckComm())
|
|
return 0;
|
|
if (write && (value != controlbyte)) {
|
|
controlbyte = value;
|
|
|
|
// UPDATE THE BAUD RATE
|
|
switch (controlbyte & 0x0F) {
|
|
case 0x00: // fall through
|
|
case 0x01: // fall through
|
|
case 0x02: // fall through
|
|
case 0x03: // fall through
|
|
case 0x04: // fall through
|
|
case 0x05: baudrate = CBR_110; break;
|
|
case 0x06: baudrate = CBR_300; break;
|
|
case 0x07: baudrate = CBR_600; break;
|
|
case 0x08: baudrate = CBR_1200; break;
|
|
case 0x09: // fall through
|
|
case 0x0A: baudrate = CBR_2400; break;
|
|
case 0x0B: // fall through
|
|
case 0x0C: baudrate = CBR_4800; break;
|
|
case 0x0D: // fall through
|
|
case 0x0E: baudrate = CBR_9600; break;
|
|
case 0x0F: baudrate = CBR_19200; break;
|
|
}
|
|
|
|
// UPDATE THE BYTE SIZE
|
|
switch (controlbyte & 0x60) {
|
|
case 0x00: bytesize = 8; break;
|
|
case 0x20: bytesize = 7; break;
|
|
case 0x40: bytesize = 6; break;
|
|
case 0x60: bytesize = 5; break;
|
|
}
|
|
|
|
// UPDATE THE NUMBER OF STOP BITS
|
|
if (controlbyte & 0x80) {
|
|
if ((bytesize == 8) && (parity == NOPARITY))
|
|
stopbits = ONESTOPBIT;
|
|
else if ((bytesize == 5) && (parity == NOPARITY))
|
|
stopbits = ONE5STOPBITS;
|
|
else
|
|
stopbits = TWOSTOPBITS;
|
|
}
|
|
else
|
|
stopbits = ONESTOPBIT;
|
|
|
|
UpdateCommState();
|
|
}
|
|
return controlbyte;
|
|
}
|
|
|
|
//===========================================================================
|
|
void CommDestroy () {
|
|
if ((baudrate != CBR_19200) ||
|
|
(bytesize != 8) ||
|
|
(parity != NOPARITY) ||
|
|
(stopbits != ONESTOPBIT)) {
|
|
CommReset();
|
|
CheckComm();
|
|
}
|
|
CloseComm();
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommDipSw (WORD, BYTE, BYTE, BYTE, ULONG) {
|
|
// note: determine what values a real SSC returns
|
|
return 0;
|
|
}
|
|
|
|
//===========================================================================
|
|
void CommSetSerialPort (HWND window, DWORD newserialport) {
|
|
if (commhandle == INVALID_HANDLE_VALUE)
|
|
serialport = newserialport;
|
|
else
|
|
MessageBox(window,
|
|
TEXT("You cannot change the serial port while it is ")
|
|
TEXT("in use."),
|
|
TEXT("Configuration"),
|
|
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
}
|
|
|
|
//===========================================================================
|
|
void CommUpdate (DWORD totalcycles) {
|
|
if (commhandle == INVALID_HANDLE_VALUE)
|
|
return;
|
|
if ((comminactivity += totalcycles) > 1000000) {
|
|
static DWORD lastcheck = 0;
|
|
if ((comminactivity > 2000000) || (comminactivity-lastcheck > 99950)) {
|
|
DWORD modemstatus = 0;
|
|
GetCommModemStatus(commhandle,&modemstatus);
|
|
if ((modemstatus & MS_RLSD_ON) || DiskIsSpinning())
|
|
comminactivity = 0;
|
|
}
|
|
if (comminactivity > 2000000)
|
|
CloseComm();
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommReceive (WORD, BYTE, BYTE, BYTE, ULONG) {
|
|
if (!CheckComm())
|
|
return 0;
|
|
if (!recvbytes)
|
|
CheckReceive();
|
|
BYTE result = 0;
|
|
if (recvbytes) {
|
|
result = recvbuffer[0];
|
|
if (--recvbytes)
|
|
MoveMemory(recvbuffer,recvbuffer+1,recvbytes);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//===========================================================================
|
|
void CommReset () {
|
|
CloseComm();
|
|
baudrate = CBR_19200;
|
|
bytesize = 8;
|
|
commandbyte = 0x00;
|
|
controlbyte = 0x1F;
|
|
parity = NOPARITY;
|
|
recvbytes = 0;
|
|
stopbits = ONESTOPBIT;
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommStatus (WORD, BYTE, BYTE, BYTE, ULONG) {
|
|
if (!CheckComm())
|
|
return 0x70;
|
|
if (!recvbytes)
|
|
CheckReceive();
|
|
DWORD modemstatus = 0;
|
|
GetCommModemStatus(commhandle,&modemstatus);
|
|
return 0x10 | (recvbytes ? 0x08 : 0x00)
|
|
| ((modemstatus & MS_RLSD_ON) ? 0x00 : 0x20)
|
|
| ((modemstatus & MS_DSR_ON) ? 0x00 : 0x40);
|
|
}
|
|
|
|
//===========================================================================
|
|
BYTE __stdcall CommTransmit (WORD, BYTE, BYTE, BYTE value, ULONG) {
|
|
if (!CheckComm())
|
|
return 0;
|
|
DWORD byteswritten;
|
|
WriteFile(commhandle,&value,1,&byteswritten,NULL);
|
|
return 0;
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
DWORD CommGetSnapshot(SS_IO_Comms* pSS)
|
|
{
|
|
pSS->baudrate = baudrate;
|
|
pSS->bytesize = bytesize;
|
|
pSS->commandbyte = commandbyte;
|
|
pSS->comminactivity = comminactivity;
|
|
pSS->controlbyte = controlbyte;
|
|
pSS->parity = parity;
|
|
memcpy(pSS->recvbuffer, recvbuffer, 9);
|
|
pSS->recvbytes = recvbytes;
|
|
pSS->stopbits = stopbits;
|
|
return 0;
|
|
}
|
|
|
|
DWORD CommSetSnapshot(SS_IO_Comms* pSS)
|
|
{
|
|
baudrate = pSS->baudrate;
|
|
bytesize = pSS->bytesize;
|
|
commandbyte = pSS->commandbyte;
|
|
comminactivity = pSS->comminactivity;
|
|
controlbyte = pSS->controlbyte;
|
|
parity = pSS->parity;
|
|
memcpy(recvbuffer, pSS->recvbuffer, 9);
|
|
recvbytes = pSS->recvbytes;
|
|
stopbits = pSS->stopbits;
|
|
return 0;
|
|
}
|