mirror of
https://github.com/PDP-10/its.git
synced 2026-01-11 23:53:12 +00:00
Some Imlac programs from Tom Uban.
This commit is contained in:
parent
06d581779a
commit
e451cac66f
93
imlac/binldr.i
Normal file
93
imlac/binldr.i
Normal file
@ -0,0 +1,93 @@
|
||||
ABS
|
||||
ORG 17700
|
||||
/
|
||||
/ ASSEMBLE WITH IA AND GET LISTING FILE. RUN LISTING FILE THROUGH
|
||||
/ BINTRN TO STRIP OFF OCTAL (WITH EDIT REMOVE GLITCHES AND INSERT
|
||||
/ LABEL BINLDR). INSERT SOME ZEROS BEFORE 1ST WORD TO KLUDGE 4K
|
||||
/ 1ST CHAR GARBLE (BINLDR 0; 001032 ... ). SEGMENT OLD IA:
|
||||
/ >S BINLDR,ENDLDR THEN >T DK IAA SRC,IAB,IAC _ DK IA (Y)
|
||||
/ THEN >T DK IA SRC _ DK IAA,O,IAC (W) TO PUT TOGETHER WITH NEW
|
||||
/ LOADER. FINALLY PATCH INTO SYSTEM: >READR 17600 IA
|
||||
/
|
||||
LOAD RCF /IOT MUST BE FIRST TO UNLOCK ROM
|
||||
COUNT JMS . /-WC
|
||||
CHECK LAC COUNT /CHECKSUM
|
||||
SAM LCHECK
|
||||
JMP HEAD
|
||||
LWC 17777-DLIST+1 /IF 8K (LV), START LINE
|
||||
DLA
|
||||
DON
|
||||
HEAD CAL
|
||||
DAC CHECK
|
||||
JMS WORD /LOAD OR TRANSFER ADDRESS
|
||||
DAC LOAD
|
||||
ASP
|
||||
JMP DONE
|
||||
JMS WORD /WORD COUNT (COMP)
|
||||
DAC COUNT
|
||||
JMS WORD /CHECKSUM
|
||||
/
|
||||
NEXT JMS WORD /DATA
|
||||
DAC* LOAD
|
||||
LAC LOAD
|
||||
SAR 3
|
||||
AND MASK
|
||||
IOR SETY
|
||||
DAC DLIST
|
||||
LAC* LOAD
|
||||
ISZ LOAD
|
||||
ISZ COUNT
|
||||
JMP NEXT /LOOP TO END OF BLOCK
|
||||
ADD CHECK
|
||||
ASZ
|
||||
JMP . /CHECKSUM ERROR
|
||||
JMP HEAD /NEXT BLOCK
|
||||
/
|
||||
DONE DOF
|
||||
IAC
|
||||
ASN
|
||||
HLT
|
||||
JMS WORD /LAST WORD IS GARBAGE
|
||||
JMP* LOAD
|
||||
/
|
||||
WORD ZRO
|
||||
ADD CHECK
|
||||
DAC CHECK /ACCUMULATE CHECKSUM
|
||||
CAL
|
||||
RSF
|
||||
JMP .-1
|
||||
RRC /READ HIGH ORDER HALF
|
||||
RAL 3
|
||||
RAL 3
|
||||
RAL 2
|
||||
RSF
|
||||
JMP .-1
|
||||
RRC /READ LOW ORDER HALF
|
||||
JMP* WORD
|
||||
/
|
||||
SETY DLYA 0
|
||||
MASK OCT 1777
|
||||
/
|
||||
DLIST DLYA 0
|
||||
DLXA 0
|
||||
DSTS 1
|
||||
046000
|
||||
021777
|
||||
000000
|
||||
DJMP DLIST
|
||||
LCHECK ZRO CHECK
|
||||
/
|
||||
LL=.-LOAD;LL=76-LL
|
||||
.IFNEG LL
|
||||
.ERROR YOU LOSE, LOADER CAN BE AT MOST 76 WRDS (ROM LIMIT)
|
||||
.ENDC
|
||||
.IFPNZ LL
|
||||
.REPT LL
|
||||
0
|
||||
.ENDC
|
||||
/
|
||||
/
|
||||
/
|
||||
/DEL REST
|
||||
END
|
||||
|
||||
96
imlac/binldr.list
Normal file
96
imlac/binldr.list
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
ABS
|
||||
17700 ORG 17700
|
||||
/
|
||||
/ ASSEMBLE WITH IA AND GET LISTING FILE. RUN LISTING FILE THROUGH
|
||||
/ BINTRN TO STRIP OFF OCTAL (WITH EDIT REMOVE GLITCHES AND INSERT
|
||||
/ LABEL BINLDR). INSERT SOME ZEROS BEFORE 1ST WORD TO KLUDGE 4K
|
||||
/ 1ST CHAR GARBLE (BINLDR 0; 001032 ... ). SEGMENT OLD IA:
|
||||
/ >S BINLDR,ENDLDR THEN >T DK IAA SRC,IAB,IAC _ DK IA (Y)
|
||||
/ THEN >T DK IA SRC _ DK IAA,O,IAC (W) TO PUT TOGETHER WITH NEW
|
||||
/ LOADER. FINALLY PATCH INTO SYSTEM: >READR 17600 IA
|
||||
/
|
||||
17700 001032 LOAD RCF /IOT MUST BE FIRST TO UNLOCK ROM
|
||||
17701 037701 COUNT JMS . /-WC
|
||||
17702 063701 CHECK LAC COUNT /CHECKSUM
|
||||
17703 077775 SAM LCHECK
|
||||
17704 013710 JMP HEAD
|
||||
17705 104012 LWC 17777-DLIST+1 /IF 8K (LV), START LINE
|
||||
17706 001003 DLA
|
||||
17707 003100 DON
|
||||
17710 100011 HEAD CAL
|
||||
17711 023702 DAC CHECK
|
||||
17712 037746 JMS WORD /LOAD OR TRANSFER ADDRESS
|
||||
17713 023700 DAC LOAD
|
||||
17714 002002 ASP
|
||||
17715 013740 JMP DONE
|
||||
17716 037746 JMS WORD /WORD COUNT (COMP)
|
||||
17717 023701 DAC COUNT
|
||||
17720 037746 JMS WORD /CHECKSUM
|
||||
/
|
||||
17721 037746 NEXT JMS WORD /DATA
|
||||
17722 123700 DAC* LOAD
|
||||
17723 063700 LAC LOAD
|
||||
17724 003063 SAR 3
|
||||
17725 047765 AND MASK
|
||||
17726 053764 IOR SETY
|
||||
17727 023766 DAC DLIST
|
||||
17730 163700 LAC* LOAD
|
||||
17731 033700 ISZ LOAD
|
||||
17732 033701 ISZ COUNT
|
||||
17733 013721 JMP NEXT /LOOP TO END OF BLOCK
|
||||
17734 067702 ADD CHECK
|
||||
17735 002001 ASZ
|
||||
17736 013736 JMP . /CHECKSUM ERROR
|
||||
17737 013710 JMP HEAD /NEXT BLOCK
|
||||
/
|
||||
17740 001012 DONE DOF
|
||||
17741 100004 IAC
|
||||
17742 102001 ASN
|
||||
17743 000000 HLT
|
||||
17744 037746 JMS WORD /LAST WORD IS GARBAGE
|
||||
17745 113700 JMP* LOAD
|
||||
/
|
||||
17746 000000 WORD ZRO
|
||||
17747 067702 ADD CHECK
|
||||
17750 023702 DAC CHECK /ACCUMULATE CHECKSUM
|
||||
17751 100011 CAL
|
||||
17752 002040 RSF
|
||||
17753 013752 JMP .-1
|
||||
17754 001033 RRC /READ HIGH ORDER HALF
|
||||
17755 003003 RAL 3
|
||||
17756 003003 RAL 3
|
||||
17757 003002 RAL 2
|
||||
17760 002040 RSF
|
||||
17761 013760 JMP .-1
|
||||
17762 001033 RRC /READ LOW ORDER HALF
|
||||
17763 113746 JMP* WORD
|
||||
/
|
||||
17764 020000 SETY DLYA 0
|
||||
17765 001777 MASK OCT 1777
|
||||
/
|
||||
17766 020000 DLIST DLYA 0
|
||||
17767 010000 DLXA 0
|
||||
17770 004005 DSTS 1
|
||||
17771 046000 046000
|
||||
17772 021777 021777
|
||||
17773 000000 000000
|
||||
17774 067766 DJMP DLIST
|
||||
17775 017702 LCHECK ZRO CHECK
|
||||
/
|
||||
000076 LL=.-LOAD;LL=76-LL
|
||||
000000
|
||||
.IFNEG LL
|
||||
.ERROR YOU LOSE, LOADER CAN BE AT MOST 76 WRDS (ROM LIMIT)
|
||||
.ENDC
|
||||
.IFPNZ LL
|
||||
.REPT LL
|
||||
0
|
||||
.ENDC
|
||||
/
|
||||
/
|
||||
/
|
||||
/DEL REST
|
||||
000000 END
|
||||
SIZE=17776 NO ERROR LINES
|
||||
|
||||
113
imlac/bootldr.ia
Normal file
113
imlac/bootldr.ia
Normal file
@ -0,0 +1,113 @@
|
||||
// Imlac Program Loader
|
||||
//
|
||||
// This loader is loaded by the bootstrap program at x7700, where x=0 for
|
||||
// a 4K machine, and x=1 for an 8K machine. The first byte of this loader
|
||||
// is 002, which is used by the bootstrap as a signal to start loading.
|
||||
// This loader checks whether it is running at address 017700 on an 8K machine,
|
||||
// which is assumed to support long vectors, and enables a simple display
|
||||
// during the load if so.
|
||||
//
|
||||
// The load format consists of one or more contiguous blocks, with no
|
||||
// padding bytes between them. Each block begins with three words:
|
||||
//
|
||||
// load address
|
||||
// negative word count
|
||||
// checksum
|
||||
//
|
||||
// Words are always received high-order byte first. The rest of the block
|
||||
// consists of "word count" words, which are loaded starting at "load address".
|
||||
// The sum of all the words in the block, including these first three, must be
|
||||
// zero (16 bit sum), and the checksum is computed to give that result.
|
||||
//
|
||||
// The end of the load is signalled by a block with a negative starting address.
|
||||
// If that address is -1, the loader simply halts. Otherwise it reads one more
|
||||
// word (in the position normally occupied by the negative word count), which
|
||||
// will be the value in the AC at the start of the program just loaded. Then
|
||||
// it starts the program with an indirect jump through the negative starting
|
||||
// address. (For example, to start at 00100, the starting address will be
|
||||
// 100100).
|
||||
//
|
||||
// If a checksum error occurs, the loader goes into a tight loop at
|
||||
// CSERR (x7736).
|
||||
//
|
||||
// As decoded by Howard Palmer (hep@acm.org) from an Imlac wumpus binary.
|
||||
// Oct. 6, 2004
|
||||
//
|
||||
ORG 37700
|
||||
START RCF // This is overwritten by the block start address
|
||||
CNT JMS CNT // This instruction overwrites itself!
|
||||
CKSM LAC CNT // This is overwritten by the checksum
|
||||
SAM LD8K // Are we loaded at 017700?
|
||||
JMP NODSP // Yes, skip display code
|
||||
LWC 12 // Get address of display list (DLIST at 037766)
|
||||
DLA // Start the display processor
|
||||
DON
|
||||
NODSP CAL // Initialize checksum to zero
|
||||
DAC CKSM
|
||||
JMS RWORD // Read the load address of the next block
|
||||
DAC START // Save it
|
||||
ASP // Looking for a negative load address
|
||||
JMP DONE // Finished loading blocks if we find it
|
||||
JMS RWORD // Read the negative word count
|
||||
DAC CNT
|
||||
JMS RWORD // Read the checksum word
|
||||
LOAD JMS RWORD // Read next word to be loaded
|
||||
DAC* START // Store it
|
||||
LAC START // Get the current load address
|
||||
SAR 3 // Extract the top 10 bits
|
||||
AND M1777
|
||||
IOR DLYA // Use as the Y value in a DLYA instruction
|
||||
DAC DLIST // Replace the DLYA in the display list
|
||||
LAC* START // Get the word that was just loaded
|
||||
ISZ START // Bump the load address
|
||||
ISZ CNT // Bump the negative count
|
||||
JMP LOAD // Loop until it goes to zero
|
||||
ADD CKSM // Finish computing the checksum
|
||||
ASZ // Should add up to zero
|
||||
CSERR JMP CSERR // Tight loop if checksum error
|
||||
JMP NODSP // Loop back for the next block
|
||||
|
||||
|
||||
DONE DOF // Turn off the display processor
|
||||
IAC // Increment the negative load address
|
||||
ASN // Just stop if it goes to zero
|
||||
HLT // Load completed successfully
|
||||
JMS RWORD // If not zero, read a starting value for the AC
|
||||
JMP* START // And use the negative load address to start
|
||||
|
||||
|
||||
// This subroutine reads the next word. It is entered with either zero or the
|
||||
// last word read in the AC. It adds that value to CKSM.
|
||||
|
||||
|
||||
RWORD ZZZ // Subroutine to read a word
|
||||
ADD CKSM // Accumulate checksum
|
||||
DAC CKSM
|
||||
CAL
|
||||
WT1 RSF // Wait for high-order byte
|
||||
JMP WT1
|
||||
RRC // Read it
|
||||
RAL 3 // Move it to the high-order AC
|
||||
RAL 3
|
||||
RAL 2
|
||||
WT2 RSF // Wait for low-order byte
|
||||
JMP WT2
|
||||
RRC // Read it, forming a word
|
||||
JMP* RWORD // Return to caller
|
||||
DLYA DLYA 0 // Used to build DLYA instruction
|
||||
M1777 DATA 1777 // 10-bit mask
|
||||
|
||||
|
||||
// Begin display list
|
||||
// This must start at location 037766
|
||||
|
||||
|
||||
DLIST DLYA 0 // This gets dynamically updated
|
||||
DLXA 0
|
||||
DSTS 1 // Set normal scale
|
||||
DATA 046000 // 3-word long vector
|
||||
DATA 021777 // x=1777, y=0, beam on
|
||||
DATA 0
|
||||
DJMP DLIST // Run the display processor continuously
|
||||
LD8K DATA 017702 // Used to check for load at 017700
|
||||
END
|
||||
748
imlac/imload.c
Normal file
748
imlac/imload.c
Normal file
@ -0,0 +1,748 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <Windows32/Base.h>
|
||||
#include <Windows32/Defines.h>
|
||||
#include <Windows32/Structures.h>
|
||||
#include <Windows32/Functions.h>
|
||||
|
||||
typedef enum { False, True } Bool;
|
||||
|
||||
#define RCV_TIMEOUT 200 // in milli-seconds (XXX)
|
||||
#define SERIAL_TIMEOUT -2
|
||||
#define BUF_SIZE 512
|
||||
#define DEFAULT_BAUDRATE 9600
|
||||
#define WIN95_DEFAULT_BAUDRATE CBR_9600
|
||||
|
||||
#define MAX_PORTS 4
|
||||
#define COM_BUF_SZ 1024
|
||||
|
||||
#define WIN95_DEBUG 0
|
||||
|
||||
struct com_info {
|
||||
HANDLE fd;
|
||||
HANDLE mutex;
|
||||
volatile DWORD rxbuf_max;
|
||||
BYTE rxbuf[COM_BUF_SZ];
|
||||
HANDLE th;
|
||||
} com_ports[MAX_PORTS];
|
||||
|
||||
static volatile int waiting = 0;
|
||||
|
||||
static void
|
||||
init_ports()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
com_ports[i].fd = (HANDLE) -1;
|
||||
}
|
||||
|
||||
static int
|
||||
get_port()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
if (com_ports[i].fd == (HANDLE) -1) {
|
||||
com_ports[i].fd = 0;
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
free_port(int port)
|
||||
{
|
||||
if (port >= 0 && port < MAX_PORTS)
|
||||
com_ports[port].fd = (HANDLE) -1;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
com_rx_thread(void *arg)
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
LPBYTE new_bytes_posn;
|
||||
struct com_info *cip;
|
||||
int port;
|
||||
|
||||
port = (int) arg;
|
||||
if (port < 0 || port >= MAX_PORTS) {
|
||||
printf("com_rx_thread: bad port %d\n", port);
|
||||
return (0);
|
||||
}
|
||||
cip = &com_ports[port];
|
||||
while (1) {
|
||||
WaitCommEvent(cip->fd, NULL, NULL);
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
if (waiting && cip->rxbuf_max > 0)
|
||||
printf("com_rx_thread() rxbuf_max %d and waiting\n",
|
||||
cip->rxbuf_max);
|
||||
#endif
|
||||
|
||||
WaitForSingleObject(cip->mutex, INFINITE);
|
||||
new_bytes_posn = cip->rxbuf + cip->rxbuf_max;
|
||||
if (ReadFile(cip->fd, new_bytes_posn, COM_BUF_SZ - cip->rxbuf_max,
|
||||
&bytes_read, NULL) == TRUE) {
|
||||
if (bytes_read)
|
||||
cip->rxbuf_max += bytes_read;
|
||||
} else
|
||||
printf("com_rx_thread() ReadFile failed\n");
|
||||
ReleaseMutex(cip->mutex);
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
if (bytes_read)
|
||||
printf("com_rx_thread() bytes %d\n", bytes_read);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
win95_open (const char *name, long baudrate)
|
||||
{
|
||||
struct com_info *cip;
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS cto;
|
||||
DWORD tid;
|
||||
int fd;
|
||||
static int initialized = 0;
|
||||
|
||||
if (initialized == 0) {
|
||||
initialized = 1;
|
||||
init_ports();
|
||||
}
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_open(%s, %d)\n", name, baudrate);
|
||||
#endif
|
||||
|
||||
if ((fd = get_port()) < 0) {
|
||||
printf("win95_open(%s): all ports in use\n", name);
|
||||
return (-1);
|
||||
}
|
||||
cip = &com_ports[fd];
|
||||
|
||||
/*
|
||||
* Claim the specified port.
|
||||
*/
|
||||
cip->fd = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
SetCommMask(cip->fd, EV_RXCHAR);
|
||||
|
||||
/*
|
||||
* Set the port to 8N1 w/ no timeouts, 9600 baud,
|
||||
* and COM_BUF_SZ bytes input/output buffers.
|
||||
*/
|
||||
GetCommState(cip->fd, &dcb);
|
||||
#if 0
|
||||
DWORD DCBlength;
|
||||
* DWORD BaudRate;
|
||||
DWORD fBinary: 1;
|
||||
DWORD fParity: 1;
|
||||
* DWORD fOutxCtsFlow:1;
|
||||
* DWORD fOutxDsrFlow:1;
|
||||
* DWORD fDtrControl:2;
|
||||
* DWORD fDsrSensitivity:1;
|
||||
DWORD fTXContinueOnXoff:1;
|
||||
* DWORD fOutX: 1;
|
||||
* DWORD fInX: 1;
|
||||
DWORD fErrorChar: 1;
|
||||
DWORD fNull: 1;
|
||||
* DWORD fRtsControl:2;
|
||||
DWORD fAbortOnError:1;
|
||||
DWORD fDummy2:17;
|
||||
WORD wReserved;
|
||||
WORD XonLim;
|
||||
WORD XoffLim;
|
||||
* BYTE ByteSize;
|
||||
* BYTE Parity;
|
||||
* BYTE StopBits;
|
||||
char XonChar;
|
||||
char XoffChar;
|
||||
char ErrorChar;
|
||||
char EofChar;
|
||||
char EvtChar;
|
||||
WORD wReserved1;
|
||||
#endif
|
||||
//XXX dcb.fBinary = TRUE;
|
||||
|
||||
dcb.BaudRate = (DWORD) baudrate;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
// dcb.StopBits = TWOSTOPBITS;
|
||||
dcb.fOutxCtsFlow = FALSE;
|
||||
dcb.fOutxDsrFlow = FALSE;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
SetCommState(cip->fd, &dcb);
|
||||
GetCommTimeouts(cip->fd, &cto);
|
||||
cto.ReadIntervalTimeout = MAXDWORD;
|
||||
cto.ReadTotalTimeoutMultiplier = cto.ReadTotalTimeoutConstant = 0;
|
||||
cto.WriteTotalTimeoutMultiplier = cto.WriteTotalTimeoutConstant = 0;
|
||||
SetCommTimeouts(cip->fd, &cto);
|
||||
SetupComm(cip->fd, COM_BUF_SZ, COM_BUF_SZ);
|
||||
|
||||
/*
|
||||
* Set up the comms receive buffer, create a mutex so we can
|
||||
* receive from the buffer without getting the background thread
|
||||
* bent out of shape and then kick off the background thread that
|
||||
* polls the serial port for us and stuffs the receive buffer.
|
||||
*/
|
||||
cip->rxbuf_max = 0;
|
||||
cip->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
cip->th = CreateThread(NULL, 0, com_rx_thread, (void *) 0, 0, &tid);
|
||||
|
||||
return (fd);
|
||||
}
|
||||
|
||||
void
|
||||
win95_close (int fd)
|
||||
{
|
||||
struct com_info *cip;
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_close(%d)\n", fd);
|
||||
#endif
|
||||
|
||||
if (fd < 0 || fd >= MAX_PORTS)
|
||||
return;
|
||||
|
||||
cip = &com_ports[fd];
|
||||
|
||||
WaitForSingleObject(cip->mutex, INFINITE);
|
||||
TerminateThread(cip->th, 0);
|
||||
ReleaseMutex(cip->mutex);
|
||||
WaitForSingleObject(cip->mutex, INFINITE);
|
||||
CloseHandle(cip->fd);
|
||||
ReleaseMutex(cip->mutex);
|
||||
free_port(fd);
|
||||
}
|
||||
|
||||
int
|
||||
win95_readchar (int fd, BYTE *ch, int timeout)
|
||||
{
|
||||
struct com_info *cip;
|
||||
DWORD i;
|
||||
int timer;
|
||||
|
||||
cip = &com_ports[fd];
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
if (timeout == -1)
|
||||
printf("win95_readchar() timeout %d max %d\n", timeout, cip->rxbuf_max);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The timeout parameter is as follows:
|
||||
* 0 = try once (poll)
|
||||
* >0 = try for timeout milli-seconds
|
||||
* <0 = try forever
|
||||
*/
|
||||
timer = 0;
|
||||
while (1) {
|
||||
if (cip->rxbuf_max == 0) {
|
||||
waiting = 1;
|
||||
if (timeout == 0) {
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_readchar(): SERIAL_TIMEOUT\n");
|
||||
#endif
|
||||
return (SERIAL_TIMEOUT);
|
||||
}
|
||||
|
||||
if (timeout > 0 && timer++ >= timeout) {
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_readchar(): SERIAL_TIMEOUT\n");
|
||||
#endif
|
||||
return (SERIAL_TIMEOUT);
|
||||
}
|
||||
|
||||
Sleep(1); /* Sleep time is in milli-seconds */
|
||||
continue;
|
||||
}
|
||||
|
||||
waiting = 0;
|
||||
WaitForSingleObject(cip->mutex, INFINITE);
|
||||
if (cip->rxbuf_max == 0) {
|
||||
ReleaseMutex(cip->mutex);
|
||||
continue; /* this should not happen */
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - this is ugly, but it came from some working code
|
||||
* XXX - and I don't want to mess with it at the moment.
|
||||
*/
|
||||
*ch = cip->rxbuf[0];
|
||||
for (i = 1; i < cip->rxbuf_max; i++)
|
||||
cip->rxbuf[i - 1] = cip->rxbuf[i];
|
||||
cip->rxbuf_max--;
|
||||
ReleaseMutex(cip->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_readchar(): ch 0x%x\n", ch);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
win95_write (int fd, const char *str, int len)
|
||||
{
|
||||
struct com_info *cip;
|
||||
DWORD chars_written, total_written;
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_write()\n");
|
||||
#endif
|
||||
|
||||
cip = &com_ports[fd];
|
||||
total_written = 0;
|
||||
while (len > 0) {
|
||||
if (WriteFile(cip->fd, str, len, &chars_written, NULL) == TRUE) {
|
||||
if (chars_written < 0)
|
||||
return (total_written);
|
||||
|
||||
len -= chars_written;
|
||||
str += chars_written;
|
||||
total_written += chars_written;
|
||||
} else
|
||||
printf("win95_write() WriteFile failed\n");
|
||||
}
|
||||
|
||||
return (total_written);
|
||||
}
|
||||
|
||||
void
|
||||
win95_flush_input (int fd)
|
||||
{
|
||||
struct com_info *cip;
|
||||
|
||||
#if WIN95_DEBUG > 0
|
||||
printf("win95_flush_input()\n");
|
||||
#endif
|
||||
|
||||
cip = &com_ports[fd];
|
||||
|
||||
WaitForSingleObject(cip->mutex, INFINITE);
|
||||
cip->rxbuf_max = 0;
|
||||
ReleaseMutex(cip->mutex);
|
||||
}
|
||||
|
||||
char *progname;
|
||||
unsigned char buffer[BUF_SIZE];
|
||||
extern char *sys_errlist[];
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-COM2] image\n"
|
||||
" -? this help message\n"
|
||||
" -bBAUD set the transfer baudrate to BAUD where BAUD is\n"
|
||||
" one of: 300, 1200, 2400, 4800, or 9600\n"
|
||||
" (default is 9600 baud)\n"
|
||||
" -COM2 specifiy the COM2 serial port (COM1 is default)\n"
|
||||
" -force8 force an 8bit (binary) load\n"
|
||||
" -info show file info, do not load\n"
|
||||
" -pause pause for CR before each byte\n"
|
||||
" -type4 send a mazewar type 4 message to the serial port\n"
|
||||
" -verify verify each character written\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
static unsigned char type4_msg[] = {
|
||||
0x04, 0x01, 0x54, 0x4f, 0x4d, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40
|
||||
};
|
||||
|
||||
main (int argc, char *argv[], char *env[])
|
||||
{
|
||||
long win95_baudrate;
|
||||
int arg_baudrate, serial_fd, image_fd, rom3_fd, len, i;
|
||||
const char *port;
|
||||
unsigned short sbuf[100], word;
|
||||
unsigned char *image, *cp, c;
|
||||
Bool bit4, force8, info, pause, type4, verify;
|
||||
|
||||
if ((cp = (char *) rindex(argv[0], '/')) ||
|
||||
(cp = (char *) rindex(argv[0], '\\')))
|
||||
progname = cp + 1;
|
||||
else
|
||||
progname = argv[0];
|
||||
|
||||
if ((cp = (char *) rindex(argv[0], '.')))
|
||||
*cp = 0;
|
||||
|
||||
bit4 = False;
|
||||
force8 = False;
|
||||
info = False;
|
||||
pause = False;
|
||||
type4 = False;
|
||||
verify = False;
|
||||
port = "COM1";
|
||||
arg_baudrate = DEFAULT_BAUDRATE;
|
||||
win95_baudrate = WIN95_DEFAULT_BAUDRATE;
|
||||
|
||||
argv++;
|
||||
while (--argc > 0) {
|
||||
if ((*argv)[0] != '-' && (*argv)[0] != '/')
|
||||
break;
|
||||
|
||||
switch (c = (*argv)[1]) {
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
break;
|
||||
case 'b':
|
||||
arg_baudrate = atoi(&(*argv)[2]);
|
||||
switch (arg_baudrate) {
|
||||
case 300:
|
||||
win95_baudrate = CBR_300;
|
||||
break;
|
||||
case 1200:
|
||||
win95_baudrate = CBR_1200;
|
||||
break;
|
||||
case 2400:
|
||||
win95_baudrate = CBR_2400;
|
||||
break;
|
||||
case 4800:
|
||||
win95_baudrate = CBR_4800;
|
||||
break;
|
||||
case 9600:
|
||||
win95_baudrate = CBR_9600;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"%s: baudrate (%d) should be <300 | 1200 | 2400 | "
|
||||
"4800 | 9600>\n", progname, arg_baudrate);
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (strcmp(&(*argv)[2], "om2") == 0 ||
|
||||
strcmp(&(*argv)[2], "OM2") == 0) {
|
||||
port = "COM2";
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (strcmp(&(*argv)[2], "orce8") == 0) {
|
||||
force8 = True;
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (strcmp(&(*argv)[2], "nfo") == 0) {
|
||||
info = True;
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (strcmp(&(*argv)[2], "ause") == 0) {
|
||||
pause = True;
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (strcmp(&(*argv)[2], "ype4") == 0) {
|
||||
type4 = True;
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if (strcmp(&(*argv)[2], "erify") == 0) {
|
||||
verify = True;
|
||||
} else {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid option '%s'\n", progname, *argv);
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
image = *argv;
|
||||
|
||||
/*
|
||||
* Open the image file, read a few bytes, and rewind the fd.
|
||||
*/
|
||||
if ((image_fd = open(image, O_RDONLY | O_BINARY)) < 0) {
|
||||
fprintf(stderr, "%s: unable to open file (%s) - %s\n",
|
||||
progname, image, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
if ((len = read(image_fd, buffer, 10)) <= 0) {
|
||||
fprintf(stderr, "%s: unable to read file (%s) - %s\n",
|
||||
progname, image, sys_errlist[errno]);
|
||||
close(image_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (lseek(image_fd, 0, SEEK_SET) == -1) {
|
||||
fprintf(stderr, "%s: unable to lseek file (%s) - %s\n",
|
||||
progname, image, sys_errlist[errno]);
|
||||
close(image_fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the image is 4 or 8 bit.
|
||||
*/
|
||||
if (buffer[0] & 0140) /* 4 bit file */
|
||||
bit4 = True;
|
||||
|
||||
if (force8 == True)
|
||||
bit4 = False;
|
||||
|
||||
/*
|
||||
* Open the serial port at the specified baudrate.
|
||||
*/
|
||||
if (info == False) {
|
||||
if ((serial_fd = win95_open(port, win95_baudrate)) < 0) {
|
||||
fprintf(stderr, "%s: unable to open serial port (%s)\n",
|
||||
progname, port);
|
||||
close(image_fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Start TTY boot loader and press return when ready...");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
|
||||
if (force8 == False) {
|
||||
buffer[0] = '\1';
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (verify == False) {
|
||||
word = ((unsigned short) buffer[0] << 8) | buffer[0];
|
||||
if ((i & 1) == 0)
|
||||
printf("0%-6.6o 0x%02x 0x%02x\n",
|
||||
word, buffer[0], buffer[0]);
|
||||
}
|
||||
|
||||
if (win95_write(serial_fd, buffer, 1) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (pause == True) {
|
||||
printf("Pausing output, press return when ready...");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
}
|
||||
if (verify == True) {
|
||||
if (win95_readchar(serial_fd, &c, RCV_TIMEOUT) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to read from serial port (%s)\n",
|
||||
progname, port);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (c != buffer[0])
|
||||
printf(">>> sent 0x%02x got 0x%02x\n", buffer[i], c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the image is 4 or 8 bit.
|
||||
*/
|
||||
if (bit4 == True) { /* 4 bit file */
|
||||
printf("4 bit file:\n");
|
||||
if (info == True) {
|
||||
close(image_fd);
|
||||
exit(0);
|
||||
}
|
||||
if ((rom3_fd = open("rom3", O_RDONLY | O_BINARY)) < 0) {
|
||||
fprintf(stderr, "%s: unable to open file (%s) - %s\n",
|
||||
progname, "rom3", sys_errlist[errno]);
|
||||
close(image_fd);
|
||||
if (info == False)
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
printf("Sending rom3\n");
|
||||
while ((len = read(rom3_fd, buffer, BUF_SIZE)) > 0) {
|
||||
putchar('.');
|
||||
|
||||
if (pause == True || verify == True) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (verify == False) {
|
||||
word = ((unsigned short) buffer[i] << 8) |
|
||||
buffer[i + 1];
|
||||
if ((i & 1) == 0)
|
||||
printf("0%-6.6o 0x%02x 0x%02x\n",
|
||||
word, buffer[i], buffer[i + 1]);
|
||||
}
|
||||
|
||||
if (win95_write(serial_fd, &buffer[i], 1) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (pause == True) {
|
||||
printf("Pausing output, press return when ready...");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
}
|
||||
if (verify == True) {
|
||||
if (win95_readchar(serial_fd, &c, RCV_TIMEOUT) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to read from serial "
|
||||
"port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (c != buffer[i])
|
||||
printf(">>> sent 0x%02x got 0x%02x\n",
|
||||
buffer[i], c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (win95_write(serial_fd, buffer, len) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "%s: unable to read file (%s) - %s\n",
|
||||
progname, "rom3", sys_errlist[errno]);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
close(rom3_fd);
|
||||
} else { /* 8 bit file */
|
||||
printf("8 bit file:\n");
|
||||
if (info == True) {
|
||||
close(image_fd);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Sending %s\n", image);
|
||||
while ((len = read(image_fd, buffer, BUF_SIZE)) > 0) {
|
||||
putchar('+');
|
||||
|
||||
if (pause == True || verify == True) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (verify == False) {
|
||||
word = ((unsigned short) buffer[i] << 8) | buffer[i + 1];
|
||||
if ((i & 1) == 0)
|
||||
printf("0%-6.6o 0x%02x 0x%02x\n",
|
||||
word, buffer[i], buffer[i + 1]);
|
||||
}
|
||||
|
||||
if (win95_write(serial_fd, &buffer[i], 1) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (pause == True) {
|
||||
printf("Pausing output, press return when ready...");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
}
|
||||
if (verify == True) {
|
||||
if (win95_readchar(serial_fd, &c, RCV_TIMEOUT) < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: unable to read from serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
if (c != buffer[i])
|
||||
printf(">>> sent 0x%02x got 0x%02x\n", buffer[i], c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (win95_write(serial_fd, buffer, len) < 0) {
|
||||
fprintf(stderr, "%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "%s: unable to read file (%s) - %s\n",
|
||||
progname, image, sys_errlist[errno]);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
|
||||
if (type4) {
|
||||
printf("Press return to send type 4 message...");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
|
||||
if (win95_write(serial_fd, type4_msg, sizeof(type4_msg)) < 0) {
|
||||
fprintf(stderr, "%s: unable to write to serial port (%s)\n",
|
||||
progname, port);
|
||||
close(rom3_fd);
|
||||
close(image_fd);
|
||||
win95_close(serial_fd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
3501
imlac/mazewar.ia
Normal file
3501
imlac/mazewar.ia
Normal file
File diff suppressed because it is too large
Load Diff
7042
imlac/mazewar.out
Normal file
7042
imlac/mazewar.out
Normal file
File diff suppressed because it is too large
Load Diff
BIN
imlac/rom3
Normal file
BIN
imlac/rom3
Normal file
Binary file not shown.
108
imlac/rom3.dis
Normal file
108
imlac/rom3.dis
Normal file
@ -0,0 +1,108 @@
|
||||
Dissassembling: imlac/rom3
|
||||
007700 000000 HLT
|
||||
007701 001032 RCF
|
||||
007702 037701 JMS
|
||||
007703 063701 LAC
|
||||
007704 077775 SAM
|
||||
007705 013710 JMP
|
||||
007706 104012 LWC
|
||||
007707 001003 DLA
|
||||
007710 003100 DON
|
||||
007711 100011 CAL
|
||||
007712 023702 DAC
|
||||
007713 037746 JMS
|
||||
007714 023700 DAC
|
||||
007715 002002 ASP
|
||||
007716 013740 JMP
|
||||
007717 037746 JMS
|
||||
007720 023701 DAC
|
||||
007721 037746 JMS
|
||||
007722 037746 JMS
|
||||
007723 123700 I DAC
|
||||
007724 063700 LAC
|
||||
007725 003063 SAR
|
||||
007726 047765 AND
|
||||
007727 053764 IOR
|
||||
007730 023766 DAC
|
||||
007731 163700 I LAC
|
||||
007732 033700 ISZ
|
||||
007733 033701 ISZ
|
||||
007734 013721 JMP4
|
||||
007735 067702 ADD
|
||||
007736 002001 ASZ
|
||||
007737 013736 JMP5
|
||||
007740 013710 JMP
|
||||
007741 001012 DOF
|
||||
007742 100004 IAC
|
||||
007743 102001 ASN
|
||||
007744 000000 HLT
|
||||
007745 037746 JMS
|
||||
007746 113700 I JMP
|
||||
007747 000000 HLT
|
||||
007750 067702 ADD
|
||||
007751 023702 DAC
|
||||
007752 100011 CAL
|
||||
007753 002040 RSF
|
||||
007754 013752 JMP
|
||||
007755 001033 RRC
|
||||
007756 003003 RAL
|
||||
007757 003003 RAL
|
||||
007760 003002 RAL
|
||||
007761 002040 RSF
|
||||
007762 013760 JMP
|
||||
007763 001033 RRC
|
||||
007764 113746 I JMP
|
||||
007765 020000 DAC
|
||||
007766 001777 ???
|
||||
007767 020000 DAC
|
||||
007770 010000 JMP
|
||||
007771 004005 LAW
|
||||
007772 046000 AND
|
||||
007773 021777 DAC
|
||||
007774 000000 HLT
|
||||
007775 067766 ADD
|
||||
007776 017702 JMP
|
||||
007777 014020 JMP
|
||||
010000 177747 I SAM
|
||||
010001 021356 DAC
|
||||
010002 104101 LWC
|
||||
010003 020010 DAC
|
||||
010004 020056 DAC
|
||||
010005 104004 LWC
|
||||
010006 020054 DAC
|
||||
010007 100011 CAL
|
||||
010010 020057 DAC
|
||||
010011 100011 CAL
|
||||
010012 002040 RSF
|
||||
010013 010030 JMP
|
||||
010014 001033 RRC
|
||||
010015 020055 DAC
|
||||
010016 044060 AND
|
||||
010017 074061 SAM
|
||||
010020 010027 JMP
|
||||
010021 060055 LAC
|
||||
010022 044062 AND
|
||||
010023 024057 XAM
|
||||
010024 003003 RAL
|
||||
010025 003001 RAL
|
||||
010026 050057 IOR
|
||||
010027 020057 DAC
|
||||
010030 030054 ISZ
|
||||
010031 010027 JMP
|
||||
010032 120010 I DAC
|
||||
010033 014051 JMP
|
||||
010034 177775 I SAM
|
||||
010035 013546 JMP
|
||||
010036 030056 ISZ
|
||||
010037 010023 JMP
|
||||
010040 110063 I JMP
|
||||
010041 014060 JMP
|
||||
010042 177774 I SAM
|
||||
010043 163525 I LAC
|
||||
010044 000160 ???
|
||||
010045 000100 ???
|
||||
010046 000017 ???
|
||||
010047 177700 I SAM
|
||||
010050 114020 I JMP
|
||||
010051 000003 ???
|
||||
010052 006412 ???
|
||||
BIN
imlac/rom3.i
Normal file
BIN
imlac/rom3.i
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user