From 77735c3ff0772609e9c8d29e3ce2ab42ff54d20b Mon Sep 17 00:00:00 2001 From: Travis Bradshaw Date: Tue, 31 Jan 2012 15:57:38 -0600 Subject: [PATCH] The source for the DOOM serial / model driver. --- sersrc/DOOMNET.C | 126 +++++++++ sersrc/DOOMNET.H | 60 ++++ sersrc/PORT.C | 428 +++++++++++++++++++++++++++++ sersrc/README.TXT | 1 + sersrc/SERSETUP.C | 680 ++++++++++++++++++++++++++++++++++++++++++++++ sersrc/SERSETUP.H | 102 +++++++ sersrc/SERSTR.H | 21 ++ sersrc/SER_FRCH.H | 25 ++ 8 files changed, 1443 insertions(+) create mode 100644 sersrc/DOOMNET.C create mode 100644 sersrc/DOOMNET.H create mode 100644 sersrc/PORT.C create mode 100644 sersrc/README.TXT create mode 100644 sersrc/SERSETUP.C create mode 100644 sersrc/SERSETUP.H create mode 100644 sersrc/SERSTR.H create mode 100644 sersrc/SER_FRCH.H diff --git a/sersrc/DOOMNET.C b/sersrc/DOOMNET.C new file mode 100644 index 000000000..c027ec7c7 --- /dev/null +++ b/sersrc/DOOMNET.C @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include "doomnet.h" + +//#include "serstr.h" +#include "ser_frch.h" // FRENCH VERSION + +#define DOOM2 + +extern int myargc; +extern char **myargv; + +doomcom_t doomcom; +int vectorishooked; +void interrupt (*olddoomvect) (void); + + + +/* +================= += += CheckParm += += Checks for the given parameter in the program's command line arguments += += Returns the argument number (1 to argc-1) or 0 if not present += +================= +*/ + +int CheckParm (char *check) +{ + int i; + + for (i = 1;i= inque.head) + return -1; + c = inque.data[inque.tail&(QUESIZE-1)]; + inque.tail++; + return c; +} + + +void write_byte( int c ) +{ + outque.data[outque.head&(QUESIZE-1)] = c; + outque.head++; +} + + + +//========================================================================== + + +/* +============== += += isr_8250 += +============== +*/ + +void interrupt isr_8250(void) +{ + int c; + + while (1) + { + switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 ) + { +// not enabled + case IIR_MODEM_STATUS_INTERRUPT : + modem_status = INPUT( uart + MODEM_STATUS_REGISTER ); + break; + +// not enabled + case IIR_LINE_STATUS_INTERRUPT : + line_status = INPUT( uart + LINE_STATUS_REGISTER ); + break; + +// +// transmit +// + case IIR_TX_HOLDING_REGISTER_INTERRUPT : +//I_ColorBlack (63,0,0); + if (outque.tail < outque.head) + { + c = outque.data[outque.tail&(QUESIZE-1)]; + outque.tail++; + OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c ); + } + break; + +// +// receive +// + case IIR_RX_DATA_READY_INTERRUPT : +//I_ColorBlack (0,63,0); + c = INPUT( uart + RECEIVE_BUFFER_REGISTER ); + inque.data[inque.head&(QUESIZE-1)] = c; + inque.head++; + break; + +// +// done +// + default : +//I_ColorBlack (0,0,0); + OUTPUT( 0x20, 0x20 ); + return; + } + } +} + + +/* +============== += += isr_16550 += +============== +*/ + +void interrupt isr_16550(void) +{ + int c; + int count; + + while (1) + { + switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 ) + { +// not enabled + case IIR_MODEM_STATUS_INTERRUPT : + modem_status = INPUT( uart + MODEM_STATUS_REGISTER ); + break; + +// not enabled + case IIR_LINE_STATUS_INTERRUPT : + line_status = INPUT( uart + LINE_STATUS_REGISTER ); + break; + +// +// transmit +// + case IIR_TX_HOLDING_REGISTER_INTERRUPT : +//I_ColorBlack (63,0,0); + count = 16; + while (outque.tail < outque.head && count--) + { + c = outque.data[outque.tail&(QUESIZE-1)]; + outque.tail++; + OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c ); + } + break; + +// +// receive +// + case IIR_RX_DATA_READY_INTERRUPT : +//I_ColorBlack (0,63,0); + do + { + c = INPUT( uart + RECEIVE_BUFFER_REGISTER ); + inque.data[inque.head&(QUESIZE-1)] = c; + inque.head++; + } while (INPUT( uart + LINE_STATUS_REGISTER ) & LSR_DATA_READY ); + + break; + +// +// done +// + default : +//I_ColorBlack (0,0,0); + OUTPUT( 0x20, 0x20 ); + return; + } + } +} + + +/* +=============== += += jump_start += += Start up the transmition interrupts by sending the first char +=============== +*/ + +void jump_start( void ) +{ + int c; + + if (outque.tail < outque.head) + { + c = outque.data [outque.tail&(QUESIZE-1)]; + outque.tail++; + OUTPUT( uart, c ); + } +} + + diff --git a/sersrc/README.TXT b/sersrc/README.TXT new file mode 100644 index 000000000..94ce05338 --- /dev/null +++ b/sersrc/README.TXT @@ -0,0 +1 @@ +This is the source for the DOOM serial / modem driver. diff --git a/sersrc/SERSETUP.C b/sersrc/SERSETUP.C new file mode 100644 index 000000000..eeee0060d --- /dev/null +++ b/sersrc/SERSETUP.C @@ -0,0 +1,680 @@ +// sersetup.c +#define DOOM2 +#include "sersetup.h" +//#include "serstr.h" +#include "ser_frch.h" // FRENCH VERSION +#include "DoomNet.h" + +extern que_t inque, outque; + +void jump_start( void ); +extern int uart; + +int usemodem; +char startup[256], shutdown[256], baudrate[256]; + +extern int baudbits; + +void ModemCommand (char *str); + +int myargc; +char **myargv; + +//====================================== +// +// I_Error +// +//====================================== +void I_Error(char *string) +{ + printf("%s\n",string); + exit(1); +} + +/* +================ += += write_buffer += +================ +*/ + +void write_buffer( char *buffer, unsigned int count ) +{ + int i; + +// if this would overrun the buffer, throw everything else out + if (outque.head-outque.tail+count > QUESIZE) + outque.tail = outque.head; + + while (count--) + write_byte (*buffer++); + + if ( INPUT( uart + LINE_STATUS_REGISTER ) & 0x40) + jump_start(); +} + + +/* +================= += += Error += += For abnormal program terminations += +================= +*/ + +void Error (char *error, ...) +{ + va_list argptr; + + if (usemodem) + { + printf ("\n"); + printf ("\n"STR_DROPDTR"\n"); + + OUTPUT(uart+MODEM_CONTROL_REGISTER, INPUT(uart+MODEM_CONTROL_REGISTER)&~MCR_DTR); + delay (1250); + OUTPUT( uart + MODEM_CONTROL_REGISTER, INPUT( uart + MODEM_CONTROL_REGISTER ) | MCR_DTR ); + ModemCommand("+++"); + delay (1250); + ModemCommand(shutdown); + delay (1250); + + } + + ShutdownPort (); + + if (vectorishooked) + setvect (doomcom.intnum,olddoomvect); + + if (error) + { + va_start (argptr,error); + vprintf (error,argptr); + va_end (argptr); + printf ("\n"); + exit (1); + } + + printf (STR_CLEANEXIT"\n"); + exit (0); +} + + +/* +================ += += ReadPacket += +================ +*/ + +#define MAXPACKET 512 +#define FRAMECHAR 0x70 + +char packet[MAXPACKET]; +int packetlen; +int inescape; +int newpacket; + +boolean ReadPacket (void) +{ + int c; + +// if the buffer has overflowed, throw everything out + + if (inque.head-inque.tail > QUESIZE - 4) // check for buffer overflow + { + inque.tail = inque.head; + newpacket = true; + return false; + } + + if (newpacket) + { + packetlen = 0; + newpacket = 0; + } + + do + { + c = read_byte (); + if (c < 0) + return false; // haven't read a complete packet +//printf ("%c",c); + if (inescape) + { + inescape = false; + if (c!=FRAMECHAR) + { + newpacket = 1; + return true; // got a good packet + } + } + else if (c==FRAMECHAR) + { + inescape = true; + continue; // don't know yet if it is a terminator + } // or a literal FRAMECHAR + + if (packetlen >= MAXPACKET) + continue; // oversize packet + packet[packetlen] = c; + packetlen++; + } while (1); + +} + + +/* +============= += += WritePacket += +============= +*/ + + + +void WritePacket (char *buffer, int len) +{ + int b; + char static localbuffer[MAXPACKET*2+2]; + + b = 0; + if (len > MAXPACKET) + return; + + while (len--) + { + if (*buffer == FRAMECHAR) + localbuffer[b++] = FRAMECHAR; // escape it for literal + localbuffer[b++] = *buffer++; + } + + localbuffer[b++] = FRAMECHAR; + localbuffer[b++] = 0; + + write_buffer (localbuffer, b); +} + + +/* +============= += += NetISR += +============= +*/ + +void interrupt NetISR (void) +{ + if (doomcom.command == CMD_SEND) + { +//I_ColorBlack (0,0,63); + WritePacket ((char *)&doomcom.data, doomcom.datalength); + } + else if (doomcom.command == CMD_GET) + { +//I_ColorBlack (63,63,0); + + if (ReadPacket () && packetlen <= sizeof(doomcom.data) ) + { + doomcom.remotenode = 1; + doomcom.datalength = packetlen; + memcpy (&doomcom.data, &packet, packetlen); + } + else + doomcom.remotenode = -1; + + } +//I_ColorBlack (0,0,0); +} + + + + +/* +================= += += Connect += += Figures out who is player 0 and 1 +================= +*/ + +void Connect (void) +{ + struct time time; + int oldsec; + int localstage, remotestage; + char str[20]; + char idstr[7]; + char remoteidstr[7]; + unsigned long idnum; + int i; + +// +// wait for a good packet +// + printf (STR_ATTEMPT"\n"); + +// +// build a (hopefully) unique id string by hashing up the current milliseconds +// and the interrupt table +// + if (CheckParm ("-player1")) + idnum = 0; + else if (CheckParm ("-player2")) + idnum = 999999; + else + { + gettime (&time); + idnum = time.ti_sec*100+time.ti_hund; + for (i=0 ; i<512 ; i++) + idnum += ((unsigned far *)0)[i]; + idnum %= 1000000; + } + + idstr[0] = '0' + idnum/ 100000l; + idnum -= (idstr[0]-'0')*100000l; + idstr[1] = '0' + idnum/ 10000l; + idnum -= (idstr[1]-'0')*10000l; + idstr[2] = '0' + idnum/ 1000l; + idnum -= (idstr[2]-'0')*1000l; + idstr[3] = '0' + idnum/ 100l; + idnum -= (idstr[3]-'0')*100l; + idstr[4] = '0' + idnum/ 10l; + idnum -= (idstr[4]-'0')*10l; + idstr[5] = '0' + idnum; + idstr[6] = 0; + +// +// sit in a loop until things are worked out +// +// the packet is: ID000000_0 +// the first field is the idnum, the second is the acknowledge stage +// ack stage starts out 0, is bumped to 1 after the other computer's id +// is known, and is bumped to 2 after the other computer has raised to 1 +// + oldsec = -1; + localstage = remotestage = 0; + + do + { + while ( bioskey(1) ) + { + if ( (bioskey (0) & 0xff) == 27) + Error ("\n\n"STR_NETABORT); + } + + if (ReadPacket ()) + { + packet[packetlen] = 0; + printf ("read : %s\n",packet); + if (packetlen != 10) + continue; + if (strncmp(packet,"ID",2) ) + continue; + if (!strncmp (packet+2,idstr,6)) + Error ("\n\n"STR_DUPLICATE); + strncpy (remoteidstr,packet+2,6); + + remotestage = packet[9] - '0'; + localstage = remotestage+1; + oldsec = -1; + } + + gettime (&time); + if (time.ti_sec != oldsec) + { + oldsec = time.ti_sec; + sprintf (str,"ID%s_%i",idstr,localstage); + WritePacket (str,strlen(str)); + printf ("wrote: %s\n",str); + } + + } while (localstage < 2); + +// +// decide who is who +// + if (strcmp(remoteidstr,idstr) > 0) + doomcom.consoleplayer = 0; + else + doomcom.consoleplayer = 1; + + +// +// flush out any extras +// + while (ReadPacket ()) + ; +} + + + +/* +============== += += ModemCommand += +============== +*/ + +void ModemCommand (char *str) +{ + int i,l; + + printf (STR_MODEMCMD,str); + l = strlen(str); + for (i=0 ; i=' ') + { + response[respptr] = c; + respptr++; + } + } while (1); + + } while (strncmp(response,resp,strlen(resp))); +} + + +/* +============= += += ReadLine += +============= +*/ + +void ReadLine (FILE *f, char *dest) +{ + int c; + + do + { + c = fgetc (f); + if (c == EOF || c == '\r' || c == '\n') + break; + *dest++ = c; + } while (1); + *dest = 0; +} + + +/* +============= += += ReadModemCfg += +============= +*/ + +void ReadModemCfg (void) +{ + int mcr; + FILE *f; + unsigned baud; + + f = fopen ("modem.cfg","r"); + if (!f) + Error (STR_CANTREAD); + ReadLine (f, startup); + ReadLine (f, shutdown); + ReadLine (f, baudrate); + fclose (f); + + baud = atol(baudrate); + if (baud) + baudbits = 115200l/baud; + + usemodem = true; +} + + +/* +============= += += Dial += +============= +*/ + +void Dial (void) +{ + char cmd[80]; + int p; + + ModemCommand(startup); + ModemResponse ("OK"); + + printf ("\n"STR_DIALING"\n\n"); + p = CheckParm ("-dial"); + sprintf (cmd,"ATDT%s",myargv[p+1]); + + ModemCommand(cmd); + ModemResponse (STR_CONNECT); + doomcom.consoleplayer = 1; +} + + +/* +============= += += Answer += +============= +*/ + +void Answer (void) +{ + ModemCommand(startup); + ModemResponse ("OK"); + printf ("\n"STR_WAITRING"\n\n"); + + ModemResponse (STR_RING); + ModemCommand ("ATA"); + ModemResponse (STR_CONNECT); + + doomcom.consoleplayer = 0; +} + +//======================================================== +// +// Find a Response File +// +//======================================================== +void FindResponseFile (void) +{ + int i; + #define MAXARGVS 100 + + for (i = 1;i < myargc;i++) + if (myargv[i][0] == '@') + { + FILE * handle; + int size; + int k; + int index; + int indexinfile; + char *infile; + char *file; + char *moreargs[20]; + char *firstargv; + + // READ THE RESPONSE FILE INTO MEMORY + handle = fopen (&myargv[i][1],"rb"); + if (!handle) + I_Error (STR_NORESP); + printf("Found response file \"%s\"!\n",strupr(&myargv[i][1])); + fseek (handle,0,SEEK_END); + size = ftell(handle); + fseek (handle,0,SEEK_SET); + file = malloc (size); + fread (file,size,1,handle); + fclose (handle); + + // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG + for (index = 0,k = i+1; k < myargc; k++) + moreargs[index++] = myargv[k]; + + firstargv = myargv[0]; + myargv = malloc(sizeof(char *)*MAXARGVS); + memset(myargv,0,sizeof(char *)*MAXARGVS); + myargv[0] = firstargv; + + infile = file; + indexinfile = k = 0; + indexinfile++; // SKIP PAST ARGV[0] (KEEP IT) + do + { + myargv[indexinfile++] = infile+k; + while(k < size && + ((*(infile+k)>= ' '+1) && (*(infile+k)<='z'))) + k++; + *(infile+k) = 0; + while(k < size && + ((*(infile+k)<= ' ') || (*(infile+k)>'z'))) + k++; + } while(k < size); + + for (k = 0;k < index;k++) + myargv[indexinfile++] = moreargs[k]; + myargc = indexinfile; + + // DISPLAY ARGS +// printf("%d command-line args:\n",myargc); +// for (k=1;k +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define INPUT(port) inportb(port) +#define OUTPUT(port,data) outportb(port,data) +#define CLI() disable() +#define STI() enable() + + +typedef enum {false, true} boolean; +typedef unsigned char byte; + + +#define TRANSMIT_HOLDING_REGISTER 0x00 +#define RECEIVE_BUFFER_REGISTER 0x00 +#define INTERRUPT_ENABLE_REGISTER 0x01 +#define IER_RX_DATA_READY 0x01 +#define IER_TX_HOLDING_REGISTER_EMPTY 0x02 +#define IER_LINE_STATUS 0x04 +#define IER_MODEM_STATUS 0x08 +#define INTERRUPT_ID_REGISTER 0x02 +#define IIR_MODEM_STATUS_INTERRUPT 0x00 +#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02 +#define IIR_RX_DATA_READY_INTERRUPT 0x04 +#define IIR_LINE_STATUS_INTERRUPT 0x06 +#define FIFO_CONTROL_REGISTER 0x02 +#define FCR_FIFO_ENABLE 0x01 +#define FCR_RCVR_FIFO_RESET 0x02 +#define FCR_XMIT_FIFO_RESET 0x04 +#define FCR_RCVR_TRIGGER_LSB 0x40 +#define FCR_RCVR_TRIGGER_MSB 0x80 +#define FCR_TRIGGER_01 0x00 +#define FCR_TRIGGER_04 0x40 +#define FCR_TRIGGER_08 0x80 +#define FCR_TRIGGER_14 0xc0 +#define LINE_CONTROL_REGISTER 0x03 +#define LCR_WORD_LENGTH_MASK 0x03 +#define LCR_WORD_LENGTH_SELECT_0 0x01 +#define LCR_WORD_LENGTH_SELECT_1 0x02 +#define LCR_STOP_BITS 0x04 +#define LCR_PARITY_MASK 0x38 +#define LCR_PARITY_ENABLE 0x08 +#define LCR_EVEN_PARITY_SELECT 0x10 +#define LCR_STICK_PARITY 0x20 +#define LCR_SET_BREAK 0x40 +#define LCR_DLAB 0x80 +#define MODEM_CONTROL_REGISTER 0x04 +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_OUT1 0x04 +#define MCR_OUT2 0x08 +#define MCR_LOOPBACK 0x10 +#define LINE_STATUS_REGISTER 0x05 +#define LSR_DATA_READY 0x01 +#define LSR_OVERRUN_ERROR 0x02 +#define LSR_PARITY_ERROR 0x04 +#define LSR_FRAMING_ERROR 0x08 +#define LSR_BREAK_DETECT 0x10 +#define LSR_THRE 0x20 +#define MODEM_STATUS_REGISTER 0x06 +#define MSR_DELTA_CTS 0x01 +#define MSR_DELTA_DSR 0x02 +#define MSR_TERI 0x04 +#define MSR_DELTA_CD 0x08 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_CD 0x80 +#define DIVISOR_LATCH_LOW 0x00 +#define DIVISOR_LATCH_HIGH 0x01 + + + +#define QUESIZE 2048 + +typedef struct +{ + long head, tail; // bytes are put on head and pulled from tail + unsigned char data[QUESIZE]; +} que_t; + +void InitPort (void); +void ShutdownPort (void); + +int read_byte( void ); +void write_byte( int c ); + + +void Error (char *error, ...); + +extern int argc; +extern char **argv; diff --git a/sersrc/SERSTR.H b/sersrc/SERSTR.H new file mode 100644 index 000000000..39ce5dc5c --- /dev/null +++ b/sersrc/SERSTR.H @@ -0,0 +1,21 @@ +#define STR_DROPDTR "Dropping DTR" +#define STR_CLEANEXIT "Clean exit from SERSETUP" +#define STR_ATTEMPT "Attempting to connect across serial link, press escape to abort." +#define STR_NETABORT "Network game synchronization aborted." +#define STR_DUPLICATE "Duplicate id string, try again or check modem init string." +#define STR_MODEMCMD "Modem command : " +#define STR_MODEMRESP "Modem response: " +#define STR_RESPABORT "Modem response aborted." +#define STR_CANTREAD "Couldn't read MODEM.CFG" +#define STR_DIALING "Dialing..." +#define STR_CONNECT "CONNECT" +#define STR_WAITRING "Waiting for ring..." +#define STR_RING "RING" +#define STR_NORESP "No such response file!" +#define STR_DOOMSERIAL "DOOM II SERIAL DEVICE DRIVER v1.4" +#define STR_WARNING \ +"Warning: no NULL or iret interrupt vectors were found in the 0x60 to 0x66\n"\ +"range. You can specify a vector with the -vector 0x parameter.\n" +#define STR_COMM "Communicating with interrupt vector 0x%x" +#define STR_RETURNED "Returned from DOOM II" +#define STR_PORTSET "Setting port to %lu baud" diff --git a/sersrc/SER_FRCH.H b/sersrc/SER_FRCH.H new file mode 100644 index 000000000..f265058df --- /dev/null +++ b/sersrc/SER_FRCH.H @@ -0,0 +1,25 @@ +#define STR_DROPDTR "Abandon de DTR" +#define STR_CLEANEXIT "Sortie normale de SERSETUP" +#define STR_ATTEMPT "Tentative de connexion en s‚rie, appuyez sur ESC pour annuler." +#define STR_NETABORT "Synchronisation de jeu sur r‚seau annul‚e." +#define STR_DUPLICATE "ChaŒne id en double. R‚essayez ou v‚rifiez la chaŒne d'initialistion du modem." +#define STR_MODEMCMD "Commande du modem: " +#define STR_MODEMRESP "R‚ponse du modem: " +#define STR_RESPABORT "R‚ponse du modem annul‚e." +#define STR_CANTREAD "Lecture de MODEM.CFG impossible" +#define STR_DIALING "Composition du num‚ro..." +#define STR_CONNECT "CONNECTION" +#define STR_WAITRING "Attente d'appel..." +#define STR_RING "APPEL" +#define STR_NORESP "Ce fichier de r‚ponse n'existe pas!" +#define STR_DOOMSERIAL "GESTIONNAIRE DE LIAISON SERIE DOOM II v1.4" +#define STR_WARNING \ +"Attention: pas de vecteurs d'interruption NULL ou iret trouv‚s entre 0x60 et 0x66.\n"\ +"Vous pouvez sp‚cifier un vecteur avec le paramŠtre -vector 0x." +#define STR_COMM "Communication avec le vecteur d'interruption 0x%x" +#define STR_RETURNED "Retour de DOOM II" +#define STR_PORTLOOK "Recherche de l'UART sur le port" +#define STR_UART8250 "UART = 8250" +#define STR_UART16550 "UART = 16550" +#define STR_CLEARPEND "Riinitilisation des interruptions en attente.\n" +#define STR_PORTSET "Réglage du port à %lu baud"