mkweb
PDP-8 Emulator written in Javascipt with HTML5 Canvas based frontend.
/ This program attempts to mimic the functionality of wozmon on the Apple I
BUFINIT=6777
*10
HEAD, BUFINIT
TAIL, BUFINIT
MSGPTR, WELMSG-1
*20
ADDR, 0
STADDR, 0
STDATA, 0
LSTADR, 0
BUFRST, BUFINIT
MSGRST, WELMSG-1
NL, 12 / ASCII New Line
BSLSH, 134 / ASCII Back Slash
COLON, 72 / ASCII Colon
SPACE, 40 / ASCII Space
DOT, 56 / ASCII Period
R, 122 / ASCII 'R'
CA8, 7710 / -(ASCII 8)
CA0, 7720 / 000 000 110 000 > 111 111 001 111 > 111 111 010 000 > 7720
PUTNM, 0 / Put number stub. Allows calling from any page
JMP I PUTNMA / Jump indirectly to put number address
PUTNMA, PUTNMR
GETNM, 0 / Get number stub. Allows calling from any page
JMP I GETNMA / Jump indirectly to get number routine address
GETNMA, GETNMR
PUTCH, 0
TSF / Skip if teleprinter flag set
JMP .-1 / Else jump back and loop
TLS / Transfer char in AC, print, clear flag
JMP I PUTCH / Return from subroutine
GETCH, 0
KSF / Skip if reader flag is set (meaning there is a char available)
JMP .-1 / Else jumpback and wait
KRB / Clear AC, load char, clear flag
JMP I GETCH / Return from subroutine
RESET, 0 / Reset subroutine
CLA / Clear AC
TAD BUFRST / Load starting address of buffer
DCA HEAD / Store it in HEAD
TAD BUFRST / Load starting address of buffer
DCA TAIL / Store it in TAIL
JMP I RESET / Return from subroutine
CMD, 0 / Command subroutine dispatches the correct subcommand routine based on the command character
TAD TAIL / Load TAIL location into AC
CMA IAC / Complement and increment to form two's complement
TAD HEAD / Add HEAD location to AC
SMA / Skip on -AC, meaning we have more characters in buffer
JMP READ / Read is the default action
CLA
TAD I HEAD / Load command char into AC
DCA CDAT / Save it temporarily
TAD DOT / Load value of ascii period
CMA IAC / Complement and increment AC to form two's complement
TAD CDAT / Add character value
SNA / Skip if AC != 0 (not a '.')
JMP RANGE / Jump to range command routine
CLA / Clear AC
TAD COLON / Load value of ascii colon
CMA IAC / Complement and increment to form two's complement
TAD CDAT / Add character value
SNA / Skip if AC != 0 (not a ':')
JMP WRITE / Jump to write command routine
CLA / Clear AC
TAD R / Load value of ascii 'R'
CMA IAC / Complement and increment to form two's complement
TAD CDAT / Add character value
SNA / Skip if AC != 0 (not a 'R')
JMP RUN / Jump to run command routine
JMP ERROR / Jump to error routine if command not found
/ JMP I CMD / Return from subroutine
CDAT, 0
READ, CLA
TAD STADDR
JMS PUTNM
CLA
TAD COLON
JMS PUTCH
CLA
TAD SPACE
JMS PUTCH
CLA
TAD STDATA
JMS PUTNM
JMP I CMD
RANGE, JMP I RANGEA
RANGEA, RANGER
WRITE, CLA / Clear AC
TAD TAIL / Load TAIL location into AC
CMA IAC / Complement and increment to form two's complement
TAD HEAD / Add HEAD location to AC
SMA / Skip on -AC, meaning we have more characters in buffer
JMP ENDWR / Jump to end of write
JMS GETNM / Get write data from command
DCA I ADDR / Store new data at address
TAD SPACE / Add ascii space value
CMA IAC / Complement and increment to form two's complement
TAD I HEAD / Add HEAD
SZA / Skip if char is space
JMP ENDWR / Jump to end of write
TAD ADDR / Load address
IAC / Increment it
DCA ADDR / Store incremented address
JMP WRITE+1 / Jump back to write next address
ENDWR, CLA CMA / Form a -1 in AC
TAD HEAD / Decrement HEAD
DCA HEAD / Store it
JMP READ / Return from command routine
RUN, CLA CLL / Clear AC and Link
JMP I LSTADR / Jump to last address
ERROR, CLA / Clear AC
TAD NL / load value of ascii newline
JMS PUTCH / Print character
CLA
JMP I RESTRT / Restart program
RESTRT, START
*200
INIT, CLA / Clear AC
TAD MSGRST / Load start of string
DCA MSGPTR / Store in pointer
TAD I MSGPTR / Get next character
SNA / Skip if not null
JMP START / Return from subroutine
JMS PUTCH / Print character
CLA / Clear AC
JMP .-5 / Loop until null is reached
START, TAD BSLSH / Add the ASCII value of '\'
JMS PUTCH / Print '\'
LOOP, JMS RESET / Reset HEAD and TAIL
TAD NL / Load the ASCII value of '\n'
JMS PUTCH / Print '\n'
CLA / Clear AC
JMS RDLN / Read command line
JMS GETNM / Get the starting address
DCA ADDR / Store it for use
TAD ADDR / Load it back
DCA STADDR / Store it for keeping
TAD I STADDR / Get data at address
DCA STDATA / Store it for keeping
TAD NL / Load an ascii NL
JMS PUTCH / Print it
JMS PUTCH / Print it
CLA / Clear AC
JMS CMD / Run command
CLA / Clear AC
TAD STADDR / Load starting address
DCA LSTADR / Save it as last address
JMP LOOP / Jump to beginng of loop
RDLN, 0
JMS GETCH
DCA CHAR / Store char
TAD CHAR / And load it back
TAD CCR / Add the two's complement of '\r' (ascii 13 or 015)
SNA / Skip if input not a newline
JMP I RDLN / If it is, return from readline subroutine
CLA / Clear AC
TAD CHAR / And load it back
TAD CBS / Add the two's complement of '\b' (ascii 8 or 010)
SNA / Skip if input not a backspace
JMP BSPACE / If it is, jump to BSPACE subroutine
CLA / Clear AC
TAD CHAR / And load it back
JMS PUTCH / Echo character back
DCA I TAIL / Store input char at tail
JMP RDLN+1 / Read next char
CHAR, 0
CCR, 7763 / Complement of 015 - ASCII Carrige Return
CBS, 7770 / Complement of 010 - ASCII Backspace
BSPACE, CLA CMA / Set AC to -1
TAD TAIL / Remove last char from tail
DCA TAIL / Store new value
TAD BSLSH / Load backslash
JMS PUTCH / Print it
JMP RDLN+1 / Read next character
*400
/ Put number routine - prints the ascii repr of AC
PUTNMR, RTL / Rotate left twice, twice
RTL / Should put the top octal digit in the lower 3 bits
DCA PTMPNM / Store shifted value
TAD PTMPNM / Load it back
AND BOTDIG / And the lower 3 bits to extract a single digit
TAD ASCII0 / Add offset to get ASCII char value
JMS PUTCH / Print digit
CLA / Clear AC
TAD PTMPNM / Load temp num into AC
RAL / Rotate left once
RTL / Rotate left two more times to get the next digit
DCA PTMPNM / Store shifted value
TAD PTMPNM / Load it back
AND BOTDIG / And the lower 3 bits to extract a single digit
TAD ASCII0 / Add offset to get ASCII char value
JMS PUTCH / Print digit
CLA / Clear AC
TAD PTMPNM / Load temp num into AC
RAL / Rotate left once
RTL / Rotate left two more times to get the next digit
DCA PTMPNM / Store shifted value
TAD PTMPNM / Load it back
AND BOTDIG / And the lower 3 bits to extract a single digit
TAD ASCII0 / Add offset to get ASCII char value
JMS PUTCH / Print digit
CLA / Clear AC
TAD PTMPNM / Load temp num into AC
RAL / Rotate left once
RTL / Rotate left two more times to get the next digit
DCA PTMPNM / Store shifted value
TAD PTMPNM / Load it back
AND BOTDIG / And the lower 3 bits to extract a single digit
TAD ASCII0 / Add offset to get ASCII char value
JMS PUTCH / Print digit
JMP I PUTNM / Return from subroutine via zero page stub
ASCII0, 60
BOTDIG, 7
PTMPNM, 0
/ *400
RANGER, CLA / Clear AC
TAD ADDR / Load address
JMS PUTNM / Print number
CLA / Clear AC
TAD COLON / Load ascii colon value
JMS PUTCH / Print it
CLA / Clear AC
JMS GETNM / Get ending address of range
CMA / Form one's complement of it
DCA ENDADR / Store ending address
JMP RDATA / Print first data
RLOOP, TAD ADDR / Load address
TAD ENDADR / Subtract ending address
SNA / Skip if not equal
JMP I CMD / Return from routine
CLA / Clear AC
TAD ADDR / Load address
AND BOTDIG / And with three low bits
SZA / Skip if AC == 0 (beginning of row)
JMP RDATA / Jump to print data
TAD NL / Load ascii NL
JMS PUTCH / Print it
CLA / Clear AC
TAD ADDR / Load address
JMS PUTNM / Print number
CLA / Clear AC
TAD COLON / Load ascii colon value
JMS PUTCH / Print it
RDATA, CLA / Clear AC
TAD SPACE / Load ascii space value
JMS PUTCH / Print it
CLA / Clear AC
TAD I ADDR / Get address contents
JMS PUTNM / Print number in AC
CLA IAC / Set AC to 1
TAD ADDR / Increment address
DCA ADDR / Store new address
JMP RLOOP / Jump for next address
ENDADR, 0
GETNMR, CLA / Clear AC
DCA TNUM / Clear temp num
DCA NNUM / Clear number count
CLA CLL / Clear AC and L
TAD TAIL / Load TAIL location into AC
CMA IAC / Complement and increment to form two's complement
TAD HEAD / Add HEAD location to AC
SMA / Skip on -AC, meaning we have more characters in buffer
JMP ENDNM / Else return from subroutine1
CLA / Clear AC
TAD I HEAD / Load HEAD into AC
DCA THEAD / Store char in THEAD
TAD THEAD / Load value back into AC
TAD CA0 / Load two's complement of ascii 0
SPA / Skip on positive ac (AC >= 0) (might be a 0-7)
JMP ENDCH / Not a number char - put it back
CLA / Clear AC
TAD THEAD / Load value of char into AC
TAD CA8 / Add two's complement of ascii 8
SMA / Skip on minus AC (definitely 0-7)
JMP ENDCH / Not a number (or out of range) - put it back
CLA / Clear AC
TAD THEAD / Load value into AC
TAD CA0 / Add two's complement of ascii 0 to get number value
DCA THEAD / Store value
TAD TNUM / Load temp number
CLL RAL / Clear L and rotate left (shift)
CLL RAL / Shift left
CLL RAL / Shift left
TAD THEAD / Combine new number with working number
DCA TNUM / Save new number
TAD NNUM / Load number count
IAC / Increment count
DCA NNUM / Save it
JMP GETNMR+3 / Jump back for next number
/ Oops! we consumed a char we didn't use
ENDCH, CLA CMA / Set AC to -1
TAD HEAD / Decrement HEAD
DCA HEAD / Store new value
/ Return the current number
ENDNM, CLA / Clear AC
TAD NNUM / Load number count into AC
SNA / Skip if we found at least one number
JMP ENDLA / Jump to end - last address subroutine
CLA / Clear AC
TAD TNUM / Load number into AC
JMP I GETNM / Return from subroutine
/ Return the previous address
ENDLA, CLA / Clear AC
TAD LSTADR / Load last address
JMP I GETNM / Return from subroutine
THEAD, 0
TNUM, 0
NNUM, 0
WELMSG, "macmon v0.1.0\n"
$