          NAM HUMBUG / 68K (R)
          OPT PAG
          PAG

********************************************************
* 68K HUMBUG FOR THE PERIPHERAL TECH PT-68K
*
* COPYRIGHT (C) 1986 BY PETER A. STARK
* STAR-K SOFTWARE SYSTEMS CORP.
********************************************************

* MOD 10-26-86 TO INCLUDE WINCHESTER BOOT COMMAND
* MOD 2-5-87 TO FIX ADDRESS OF FORMAT ERROR VECTOR AND
*    PROPERLY SET UP STACK FRAME
* MOD >>A<< 3-27-87 TO SLOW DOWN 1772 STEP RATE, ALLOW
*    LOWER CASE COMMANDS, RETRY WD BOOT IF IT FAILS
* MOD >>B<< 4-15-87 TO CORRECT STACK FRAME ERROR AND ALLOW
*    LOWER CASE HEX LETTERS
* MOD >>C<< 4-19-87 TO ALLOW LOWER CASE ALSO IN RC COMMAND
*    AND ALLOW 19200 BAUD AUTO-SENSE
* MOD >>D<< 5-16-87 TO FIX PROBLEMS WITH PAUSE AND PORT P
* MINOR MOD 6-26-87 TO REDUCE STARTUP TIME
* MOD >>E<< 6-30-87 TO RESTORE INTERRUPTS AFTER SS/BR
* MOD >>F<< 7-12-87 TO ALLOW LOWER CASE AFTER ^S

* EQUATES

ROM       EQU $FFFF0000
SCRPAD    EQU $0400
MSTACK    EQU SCRPAD+$400          EVENTUALLY $0800 MON STACK
USTACK    EQU SCRPAD+$300          EVENTUALLY $0700 USER STACK
SSTACK    EQU SCRPAD+$200          EVENTUALLY $0600 SYSTEM STACK

* DATA STORAGE

          ORG SCRPAD
PORADM    DS.L 1 CONTROL PORT
PORADP    DS.L 1 PRINTER PORT
DVECTR    DS.L 1 USER PORT X VECTOR
PORECH    DS.B 1 ECHO IS <> 0
REGERS    DS.L 15 A AND D REGISTER STORAGE
REGA7     DS.L 1 REGISTER A7
USERPC    DS.L 1 USER PROGRAM COUNTER
USERSR    DS.W 1 USER STATUS REGISTER
SYSTSR    DS.W 1 SYSTEM SR DURING TRACING/BREAKPOINTS >>E<<
USERSP    DS.L 1 USER STACK POINTER
SYSTSP    DS.L 1 SYSTEM STACK POINTER
TRAVEC    DS.L 1 TRACE VECTOR TEMPORARY
BKTAB     DS.L 6 BP TABLE (LOC1, OP1,...
STATUS    DS.B 1 STATUS: P0,P1,VID,PD,PA,X,X,X
INZFLG    DS.L 1 PREVIOUSLY INITIALIZED FLAG
PAUCTR    DS.B 1 PAUSE FEATURE LINE COUNTER
BEGA      DS.L 1 BEGINNING ADDRESS
ENDA      DS.L 1 ENDING ADDRESS
SP        DS.L 1 STACK PTR
FINDNO    DS.B 1 NUMBER OF BYTES IN FI
WHAT      DS.B 5 WHAT TO FIND IN FI
NEWLOC    DS.L 1 USED IN MO
*         EVEN                     FOLLOWING USED IN HARD BOOT
OURWIN    DS.B 14                  OUR COPY OF WIN TABLE
BUFFER    DS.B 256                 SECTOR BUFFER


* PROGRAM BEGINNING

          ORG.L ROM

********************************************************
* VECTORS TO GO AT THE BEGINNING OF MEMORY
********************************************************

VECTRS DC.L MSTACK-6             0 INITIAL SUPERVISOR STACK POINTER
       DC.L COLDST               4 RESET VECTOR
       DC.L BUSERR               8 BUS ERROR
       DC.L ADDERR               C ADDRESS ERROR
       DC.L ILLINS              10 ILLEGAL INSTRUCTION
       DC.L ZERDIV              14 ZERO DIVIDE
       DC.L CHKINS              18 CHK INSTRUCTION
       DC.L TRAPVI              1C TRAPV INSTR
       DC.L PRIVIO              20 PRIVILEGE VIOLATION
       DC.L TRARET              24 TRACE
       DC.L LN1010              28 LINE 1010
       DC.L LN1111              2C LINE 1111
       DC.L UNASSI              30 UNASSIGNED
       DC.L UNASSI              34 "
       DC.L FORERR              38 FORMAT ERROR ON 68010/20
       DC.L UNASSI              3C UNASSIGNED
       DC.L UNASSI              40 "
       DC.L UNASSI              44 "
       DC.L UNASSI              48 "
       DC.L UNASSI              4C "
       DC.L UNASSI              50 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L SPURIO              60 SPURIOUS INTERRUPT
       DC.L LVL1IA                 LEVEL 1 INTERRUPT AUTOVECTOR
       DC.L LVL2IA                 LEVEL 2 "
       DC.L LVL3IA                 LEVEL 3 "
       DC.L LVL4IA              70 LEVEL 4 "
       DC.L LVL5IA                 LEVEL 5 "
       DC.L LVL6IA                 LEVEL 6 "
       DC.L LVL7IA                 LEVEL 7 "
       DC.L TRAP0V              80 TRAP 0
       DC.L TRAP1V                 TRAP 1
       DC.L TRAP2V                 TRAP 2
       DC.L TRAP3V                 TRAP 3
       DC.L TRAP4V              90 TRAP 4
       DC.L TRAP5V                 TRAP 5
       DC.L TRAP6V                 TRAP 6
       DC.L TRAP7V                 TRAP 7
       DC.L TRAP8V              A0 TRAP 8
       DC.L TRAP9V                 TRAP 9
       DC.L TRAPAV                 TRAP 10
       DC.L TRAPBV                 TRAP 11
       DC.L TRAPCV              B0 TRAP 12
       DC.L TRAPDV                 TRAP 13
       DC.L TRAPEV                 TRAP 14
       DC.L WARMST                 TRAP 15 GO TO MONITOR
VECTEN EQU *

*******************************************************
* ENTRY POINT JUMP TABLE
*******************************************************
          JMP.L COLDST
          JMP.L WARMST
          JMP.L INEEE
          JMP.L INCH7
          JMP.L INCH8
          JMP.L OUTEEE
          JMP.L OUTCHM
          JMP.L OUTCHP
          JMP.L PSTRNG
          JMP.L OUT4HS
          JMP.L OUT8HS

*******************************************************
* INITIAL COLD START ROUTINE.
*******************************************************

* FIRST CHECK WHETHER THIS IS INITIAL POWER UP

COLDST    MOVEM.L D0-D0,-(A7)      TEMP SAVE D0
          MOVE.L INZFLG,D0         IS IT INITIALIZED?
          CMP.L #$AA5555AA,D0
          MOVEM.L (A7)+,D0-D0      RESTORE D0
          MOVEM.L D0-D7/A0-A6,REGERS PUSH ALL REGISTERS
          BNE.S COLD1              IF NO, DO EVERYTHING
          BSR.L INIPOR             ELSE INITIALIZE PORTS
          BRA.L MOVCTR             AND JUST RESTART HUMBUG

* ON A REAL COLD START, INITIALIZE PORTS, PARITY MEMORY,
* SET USER STACK POINTER AND USER REGISTERS

COLD1     BSR.L INIPOR             INITIALIZE PORTS
          BSR.L MEMRD              READ ALL OF MEMORY
          MOVE.L #USTACK-4,A0
          MOVE.L A0,USP            INITIALIZE USER STACK POINTER
          MOVE.L #REGERS,A0        POINT TO REGISTER STORAGE
          MOVE.B #8,D1             COUNTER
          MOVE.L #$D0,D0
DLOOP     MOVE.L D0,(A0)+          SET DATA REGISTERS
          ADD.B #1,D0
          SUB.B #1,D1              DECR COUNTER
          BNE.S DLOOP
          MOVE.B #7,D1             COUNTER AGAIN
          MOVE.L #$A0,D0
ALOOP     MOVE.L D0,(A0)+          SET ADDRESS REGISTERS
          ADD.B #1,D0
          SUB.B #1,D1              DECR COUNTER
          BNE.S ALOOP
          MOVE.L #USTACK-4,(A0)+   A7=USER STACK POINTER
          MOVE.L #WARMST,(A0)+     PS=DEFAULT TO WARMSTART
          MOVE.W #$0000,(A0)+      SR=USER STATUS REGISTER
          MOVE.L #USTACK-4,(A0)+   US=USER STACK POINTER
          MOVE.L #USTACK-4,(A0)    SS=SYST STACK POINTER

* ERASE BREAKPOINT TABLE

RESTRT    LEA BKTAB,A0             NOW ERASE BRK TABLE
          MOVE.B #$FF,D0           FILL WITH FF'S
          MOVE.B #24,D1            24 BYTES IN TABLE
BKERAS    MOVE.B D0,(A0)+          ERASE BREAKPOINT TABLE
          SUB.B #01,D1
          BNE.S BKERAS             REPEAT IF NOT FINISHED

* MOVE VECTORS FROM ROM INTO RAM

MOVCTR    LEA VECTRS,A0            POINT TO VECTORS
          MOVE.L #0,A1             WHERE TO PUT THEM
          LEA VECTEN,A2            LAST ONE
VECMOV    MOVE.L (A0)+,(A1)+       MOVE ONE
          CMP.L A0,A2              DONE?
          BNE.S VECMOV             NO, DO MORE

RESET     MOVE.L #RTSAD,DVECTR     POINT D VECTOR TO AN RTS
          TRAP #15                 GO TO SUPERVISOR AND WARMST
RTSAD     RTS

*******************************************************
* WARMSTART INITIALIZATION
*******************************************************

WARMST    MOVE.L #MSTACK-6,A7      SET STACK PTR TO MON AREA
          EOR.W #$1000,SR          FLIP TO OTHER SSR
          MOVE.L #MSTACK-6,A7      SET OTHER STACK POINTER TOO
          EOR.W #$1000,SR          RETURN TO ORIG SSR
          BSR.L PARON              TURN ON PARITY MEMORY
          MOVE.L $00BC,A0          TEMP SAVE TRAP 15 VECTOR
          LEA WARMS1(PC),A1
          MOVE.L A1,$00BC          PUT IN NEW VECTOR
          TRAP #15                 FORCE SUPERVISOR STATE
WARMS1    OR.W #$0700,SR           DISABLE INTERRUPTS
          MOVE.W SR,SYSTSR         AND SAVE IT
          MOVE.L A0,$00BC          RESTORE TRAP 15 VECTOR
          MOVE.L #MSTACK-6,A7      SET STACK PTR TO MON AREA
          MOVE.B #$40,STATUS       PORT P, D, PAUSE OFF; 1 ON
          MOVE.B #$0F,PAUCTR       INIT PAUSE LINE COUNTER
          MOVE.B #$FF,PORECH       CTRL PORT ECHO ON
          CLR.L D0
          MOVE.L #$AA5555AA,INZFLG SET INITIALIZED FLAG
          BSR.L CRLF
          MOVE.L #H68MSG,A4
          BSR.L PDATA              PRINT SIGN-ON

*******************************************************
* NXTCMD - INITIALIZATION COMPLETE. READY FOR COMMAND
*******************************************************

NXTCMD    MOVE.L #MSTACK-6,A7      RESET STACK PTR TO MON AREA
NXTCM1    JSR CRLF                 PRINT CR/LF
          MOVE.B #$2A,D4           PRINT PROMPT
          JSR OUTEEE
          JSR INEEE                GET FIRST COMMAND CHARACTER
          LSL.W #8,D5              MOVE INTO SECOND BYTE
          JSR INEEE                GET SECOND COMMAND CHARACTER
          AND.W #$DFDF,D5          CVT TO UPPER CASE >>A<<
          JSR OUTS

* CHECK COMMAND

COMAND    LEA COMTAB-6,A0          GET ADDR OF COMMAND TABLE-6
          LEA TABEND,A1            AND END OF TABLE
LOOKUP    ADD.L #6,A0              POINT TO NEXT ENTRY
          CMP.L A0,A1              END OF TABLE?
          BEQ.S COMEND             YES
          CMP.W (A0),D5            CHECK THE COMMAND AGAINST TABLE
          BNE.S LOOKUP             WRONG
          MOVE.L 2(A0),A0          GET ADDRESS IF OK
          JSR OUTS                 PRINT A SPACE
          JSR (A0)                 JUMP TO APPROP COMMAND ROUTINE
          BRA.S NXTCMD
COMEND    MOVE.B #$3F,D4           PRINT ? IF NOT FOUND
          BSR.L OUTEEE
          BRA.S NXTCMD

*******************************************************
* COMMAND TABLE
*******************************************************

COMTAB    FCC 'AD' FORMATTED ASCII DUMP
          DC.L ASCDMP
          FCC 'AI' ASCII INPUT
          DC.L ASCIN
          FCC 'AO' ASCII OUT
          DC.L ASCOUT
          FCC 'BP' PRINT BP LOCATIONS
          DC.L BPRINT
          FCC 'BR' SET/RESET BPS
          DC.L BREAK
          FCC 'CO' CONTINUE AFTER BP
          DC.L CONT
          FCC 'CS' FOUR-BYTE CHECKSUM
          DC.L SUM
          FCC 'FD' REGULAR DISK BOOT
          DC.L FLBOOT
          FCC 'FI' FIND BYTES COMMAND
          DC.L FIND
          FCC 'FM' FILL MEMORY
          DC.L FILL
          FCC 'HA' COMBINED HEX AND ASCII DUMP
          DC.L HEXASC
          FCC 'HD' HEX DUMP ROUTINE
          DC.L HEXDMP
          FCC 'HE' HELP
          DC.L HELP
          FCC 'JS' JUMP TO SYSTEM PROGRAM
          DC.L JUMPS
          FCC 'JU' JUMP TO USER PROGRAM
          DC.L JUMPU
          FCC 'LO' LOAD S1S9 FORMAT TAPE
          DC.L LOAD
          FCC 'MC' MEMORY COMPARE
          DC.L COMPAR
          FCC 'ME' MEMORY EXAMINE
          DC.L CHANGE
          FCC 'MO' MOVE MEMORY CONTENTS
          DC.L MOVE
          FCC 'MS' MEMORY STORE W/O READING
          DC.L MSTORE
          FCC 'MT' MEMORY TEST
          DC.L MTEST
          FCC 'RC' REGISTER CHANGE
          DC.L REGCHG
          FCC 'RD' RETURN TO DOS
          DC.L RETDOS
          FCC 'RE' REGISTER EXAMINE
          DC.L REGIST
          FCC 'SS' SINGLE-STEP
          DC.L STEP
          FCC 'ST' START SINGLE-STEPPING
          DC.L STRTSS
          FCC 'WD' WINCHESTER DISK
          DC.L WDBOOT
          DC.W $0101 !!=FORCE POWERUP INITIALIZATION
          DC.L RESTRT
TABEND    DC.W 0 MARKS END OF TABLE

*******************************************************
* 'MS' - MEMORY STORE WITHOUT READING
*******************************************************

MSTORE    LEA ADMSG,A4
          JSR PDATA                PRINT "ADDRESS: "
          BSR.L BADDR              GET ADDRESS
          MOVE.L D5,A0
          SUB.L #1,A0              BACKUP 1
          MOVE.L $0008,A2          TEMP SAVE BUS ERROR VECTOR
          MOVE.L #MSBERR,$0008     REPLACE WITH NEW VECTOR
MSTOR1    ADD.L #1,A0              THEN GO FORWARD
MSTOR2    MOVE.L A0,D4             PREPARE TO PRINT
          JSR CRLF
          JSR OUT8HS               PRINT ADDRESS
MSTOR3    JSR INEEE                INPUT COMMAND CHAR
          CMP.B #$0D,D5
          BEQ.S MSEXIT             QUIT ON CR
          CMP.B #$5E,D5            UP ARROW?
          BNE.S MSTOR4             NO
          SUB.L #1,A0              YES, STEP BACK
          BRA.S MSTOR2             AND REPEAT
MSTOR4    JSR CVTHEX               PROCESS THE DIGIT
          BEQ.S MSTOR1             ON SPACE GO TO NEXT
          MOVE.B D5,D0             SAVE FIRST DIGIT
          LSL.B #4,D0              IN LEFT NYBBLE
          BSR.L IN1HEX             GET SECOND DIGIT
          BEQ.S MSTOR1             ON SPACE GO TO NEXT
          ADD.B D5,D0              COMBINE THE TWO DIGITS
          MOVE.B D0,(A0)           STORE NEW NUMBER
          BRA.S MSTOR1             AND THEN DO THE NEXT
MSBERR    LEA MEBMSG(PC),A4
          JSR PDATA                PRINT "BUSS ERROR"
          BRA.S MSTOR1
MSEXIT    MOVE.L A2,$0008          RESTORE BUS ERROR VECTOR
          JMP NXTCMD               THEN DO NEXT COMMAND

*******************************************************
* 'ME' - MEMORY EXAMINE AND CHANGE FUNCTION
*******************************************************

CHANGE    LEA ADMSG,A4
          JSR PDATA                PRINT "ADDRESS: "
          BSR.L BADDR              GET ADDRESS
          MOVE.L D5,A0
          SUB.L #1,A0              BACKUP 1
CHANG0    MOVE.L $0008,A2          TEMP SAVE BUS ERROR VECTOR
          MOVE.L #MEBERR,$0008     REPLACE WITH NEW VECTOR
CHANG1    ADD.L #1,A0              THEN GO FORWARD
CHANG2    MOVE.L A0,D4             PREPARE TO PRINT
          JSR CRLF
          JSR OUT8HS               PRINT ADDRESS
          MOVE.B (A0),D4           GET THE OLD DATA
          JSR OUT2HS               PRINT IT
          JSR OUTS                 SPACE
CHANG3    JSR INEEE                INPUT COMMAND CHAR
          CMP.B #$0D,D5
          BEQ.S MEEXIT             QUIT ON CR
          CMP.B #$5E,D5            UP ARROW?
          BNE.S CHANG4             NO
          SUB.L #1,A0              YES, STEP BACK
          BRA.S CHANG2             AND REPEAT
CHANG4    JSR CVTHEX               PROCESS THE DIGIT
          BEQ.S CHANG1             ON SPACE GO TO NEXT
          MOVE.B D5,D0             SAVE FIRST DIGIT
          LSL.B #4,D0              IN LEFT NYBBLE
          BSR.S IN1HEX             GET SECOND DIGIT
          BEQ.S CHANG1             ON SPACE GO TO NEXT
          ADD.B D5,D0              COMBINE THE TWO DIGITS
          MOVE.B D0,(A0)           STORE NEW NUMBER
          CMP.B (A0),D0            CMPA -1,X CHECK IT
          BEQ.S CHANG1             STORED OK, DO NEXT
          LEA NOCMSG(PC),A4        ERROR IF NOT STORED OK
          JSR PDATA                PRINT "DID NOT STORE"
          BRA.S CHANG2             DO SAME ONE AGAIN
MEBERR    LEA MEBMSG(PC),A4
          JSR PDATA                PRINT "BUSS ERROR"
MEEXIT    MOVE.L A2,$0008          RESTORE BUS ERROR VECTOR
          JMP NXTCMD               THEN DO NEXT COMMAND

*******************************************************
* VARIOUS ROUTINES NEEDED TO SUPPORT ABOVE ETC.
*******************************************************

* BUILD ADDRESS. BUILDS AN ADDRESS IN D5; UNLIMITED NUMBER OF
* DIGITS ACCEPTED UNTIL A SPACE IS ENTERED.
* ANY OTHER NON-HEX CHARACTER ABORTS AND RETURNS TO NXTCMD

BADDR     CLR.L D6
BADDR1    BSR.S IN1HEX             GET 1 HEX DIGIT
          BEQ.S BADEXI             EXIT IF A SPACE
          LSL.L #4,D6              MOVE PREVIOUS NUMBER LEFT
          ADD.B D5,D6              COMBINE WITH LATEST DIGIT
          BRA.S BADDR1             AND REPEAT
BADEXI    MOVE.L D6,D5             ANSWER INTO D5
          RTS

* INPUT BYTE (TWO HEX DIGITS)
* ANY NON-HEX CHARACTER EXCEPT SPACE ABORTS AND RETURNS TO COMEND

BYTE      BSR.S IN1HEX             GET ONE HEX DIGIT
          BEQ.S BYTE               SKIP SPACE
BYTE1     LSL.B #4,D5
          MOVE.B D5,D6             TEMP SAVE IT
BYTE2     BSR.S IN1HEX             GET SECOND HEX DIGIT
          BEQ.S BYTE2              SKIP SPACE
          ADD.B D6,D5              COMBINE
          ADD.B D5,D1              ADD TO CHECKSUM (IN LOAD S1)
          RTS

* INPUT 1 HEX DIGIT
* ANY NON-HEX CHARACTER ABORTS AND RETURNS TO COMEND

IN1HEX    BSR.L INEEE
CVTHEX    CMP.B #$20,D5            IS IT A SPACE?
          BEQ.S IHEXIT             YES, EXIT WITH EQUALS
          SUB.B #$30,D5            CVT FROM ASCII
          CMP.B #$A,D5             CHECK IF 0-9
          BCS.S IHEXIT             YES, EXIT
          AND.B #$DF,D5            CVT TO UPPER >>B<<
          CMP.B #$11,D5            CHECK IF <A
          BCS.L COMEND             YES, ERROR
          SUB.B #7,D5              TAKE A CHANCE THAT IT'S A-F
          CMP.B #$10,D5            CHECK IF IT'S VALID
          BCC.L COMEND             ERROR IF 10 OR ABOVE
IHEXIT    RTS                      RTS

* OUTHL AND R - OUTPUT ONE HEX DIGIT

OUTHL     LSR.B #4,D4              OUTPUT LEFT DIGIT ENTRY
OUTHR     AND.B #$F,D4             OUTPUT HEX RIGHT DIGIT ENTRY
          ADD.B #$30,D4
          CMP.B #$39,D4            0-9?
          BLS.L OUTEEE             YES, OUTPUT IT
          ADD.B #$7,D4             ELSE CONVERT FOR A - F
          BRA.L OUTEEE             AND OUTPUT

* OUT2, 4, AND 8 HEX ROUTINES

OUT2H     MOVE.B D4,D5             SAVE BYTE IN D5
          BSR.S OUTHL              OUTPUT LEFT HEX CHAR
          MOVE.B D5,D4             RESTORE BYTE
          BRA.S OUTHR              OUTPUT RIGHT HEX CHAR

OUT8HS    SWAP D4
          BSR.S OUT4H              LEFT 4 DIGITS FIRST
          SWAP D4
          BSR.S OUT4H              RIGHT 4 DIGITS NEXT
          BRA.S OUTS               FOLLOW WITH SPACE

OUT4H     MOVE.W D4,D6             SAVE WORD IN D6
          LSR.W #8,D4
          BSR.S OUT2H              LEFT BYTE FIRST
          MOVE.W D6,D4             RESTORE WORD
          BRA.S OUT2H              RIGHT BYTE NEXT
          RTS

OUT4HS    BSR.S OUT4H
          BRA.S OUTS

OUT2HS    BSR.S OUT2H
OUTS      MOVE.B #$20,D4           SPACE
          BSR.L OUTEEE
          RTS                      AND RETURN

*******************************************************
* JUMP TO USER PROGRAM COMMAND; PUT RETURN ADDRESS ON HIS STACK
* SO HE'LL RETURN TO WARM START IF HE DOES RTS
*******************************************************

JUMPU     LEA STMSG,A4
          JSR PDATA                PRINT "FROM ADDRESS"
* USE -8 IN FOLLOWING INSTRUCTION FOR 68010/68020
          MOVE.L #MSTACK-6,A7      RESET STACK
          BSR.L BADDR              GET ADDRESS TO JUMP TO
          BTST #0,D5
          BNE.L ODDADD             IF NOT EVEN
          MOVE.L D5,2(A7)          PUT ON STACK
          BEQ.L COMEND             NG IF ZERO
          MOVE.W #$0700,(A7)       SET SR
* INCLUDE FOLLOWING INSTRUCTION FOR 68010/68020
*         CLR.W 6(A7)              CLEAR 68010/20 FORMAT CODE
          MOVE.L #USTACK-4,A6
          MOVE.L A6,USP            SET USER STACK REGISTER
          LEA WARMST(PC),A6        POINT TO WARMSTART
          MOVE.L A6,USTACK-4       PUT IT ON USER STACK
          MOVEM.L REGERS,D0-D7/A0-A6 RESET A&D REGISTERS
          RTE                      GO TO USER


*******************************************************
* JUMP TO SYSTEM PROGRAM COMMAND; PUT RETURN ADDRESS ON STACK
* SO HE'LL RETURN TO WARM START IF HE DOES RTS
*******************************************************

JUMPS     LEA STMSG,A4
          JSR PDATA                PRINT "FROM ADDRESS"
          BSR.L BADDR              GET ADDRESS TO JUMP TO
          BTST #0,D5
          BNE.L ODDADD             IF NOT EVEN
          MOVE.L #SSTACK,A7        INITIALIZE STACK TO SYST AREA
          LEA WARMST,A0
          MOVE.L A0,-(A7)          WARMST ADDR ON STACK
          MOVE.L D5,-(A7)          AND GO TO ADDRESS ON STACK
          BEQ.L COMEND             NG IF ZERO
          MOVEM.L REGERS,D0-D7/A0-A6 RESET A&D REGISTERS
          RTS                      GO TO SYST PROGRAM

*******************************************************
* PSTRNG AND PCRLF
*******************************************************

* CRLF - PRINT CR/LF
CRLF      MOVEM.L A4-A4,-(A7)
          MOVE.L #CRLFST,A4        POINT TO CRLF STRING
          BSR.S PDATA              PRINT AND RETURN
          MOVEM.L (A7)+,A4-A4
          RTS
CRLFST    FCB $0D,$0A,4

* PSTRNG - CRLF FOLLOWED BY PDATA
PSTRNG    BSR.S CRLF

* PDATA - PRINT DATA STRING
PDATA     MOVEM.L D4-D4,-(A7)
PDATA1    MOVE.B (A4)+,D4          GET CHARACTER
          CMP.B #4,D4              END?
          BEQ.S PDEXIT
          BSR.L OUTEEE
          BRA.S PDATA1             AND REPEAT
PDEXIT    MOVEM.L (A7)+,D4-D4
          RTS

*******************************************************
* CONSOLE I/O ROUTINES
*******************************************************

* INEEE - CHARACTER INPUT ROUTINE
INEEE
INRPT     BSR.L INCH7              GET INPUT CHARACTER
          CMP.B #$13,D5            IS IT CONTROL-S?
          BEQ.S GOTCS              YES
          TST.B PORECH             ECHO?
          BEQ.S NOECHO             NO
          MOVEM.L D4-D4,-(A7)      YES
          MOVE.B D5,D4
          BSR.L OUTEEE
          MOVEM.L (A7)+,D4-D4
NOECHO    RTS

* CONTROL-S DETECTED. GET AND INTERPRET COMMAND
GOTCS     BSR.S GETCMD             DO COMMAND
          BRA.S INRPT

* SUBR TO GET AND DO COMMAND
GETCMD    MOVE.B D4,D5             SAVE CHARACTER BEING OUTPUT
          MOVE.B #$07,D4
          JSR OUTCHM               ECHO CONTROL-G (BELL) ON CTL PORT
          MOVE.B D5,D4             RESTORE CHARACTER
          BSR.S INCH7              GET SECOND CHARACTER OF CMD
          CMP.B #$60,D5            CHECK FOR LOWER CASE >>F<<
          BCS.S NOTLCS             NOT LOWER >>F<<
          SUB.B #$20,D5            ELSE CHANGE TO UPPER CASE >>F<<
NOTLCS    CMP.B #$50,D5            P - PORT P COMMAND? >>F<<
          BNE.S NOT0               NO
          EOR.B #$80,STATUS        FLIP PORT P
          RTS                      AND RETURN
NOT0      CMP.B #$43,D5            C - PORT C COMMAND?
          BNE.S NOT1               NO
          EOR.B #$40,STATUS        FLIP PORT C
          RTS
NOT1      CMP.B #$58,D5            X - PORT X COMMAND?
          BNE.S NOTD               NO
          EOR.B #$10,STATUS        FLIP PORT X
          RTS
NOTD      CMP.B #$57,D5            W - PAUSE COMMAND?
          BNE.S NOTP               NO
          EOR.B #$08,STATUS        FLIP PAUSE
          MOVE.B #$F,PAUCTR        RESET PAUSE LINE CNTR
          RTS
NOTP      CMP.B #$0D,D5            CR COMMAND TO QUIT?
          BEQ.L WARMST             YES, QUIT
          CMP.B #$08,D5            ^X COMMAND TO QUIT?
          BEQ.L WARMST             YES, QUIT
NOTCR     RTS                      RETURN W/O DOING ANYTHING

* ACTUAL CONTROL PORT INPUT ROUTINES
INCH7     BSR.L INCH8              GET 7-BIT CHARACTER
          AND.B #$7F,D5            MASK OUT PARITY
          RTS

* OUTEEE - CHARACTER OUTPUT ROUTINE

OUTEEE    MOVEM.L A6-A6,-(A7)
OUTEE1    BSR.L INCHEK             CHECK FOR INPUT CHARACTER
          BEQ.S NOTEST             NO CHARACTER
          BSR.S INCH7              GET CHARACTER
          CMP.B #$13,D5            IS IT CONTROL-S?
          BNE.S NOTEST             NO
          BSR.L GETCMD             YES; GET COMMAND AND DO IT
* CHECK FOR PAUSE
NOTEST    BTST #3,STATUS           PAUSE ON?
          BEQ.S NOPAUS             NO
          CMP.B #$0D,D4            CR? >>D<<
          BNE.S NOPAUS             ONLY PAUSE AT END OF LINE
          SUB.B #1,PAUCTR          DECR PAUSE LINE CNTR
          BNE.S NOPAUS             AND CHECK IT
* LINE DELETED HERE BY >>D<<
          MOVE.B #$0F,PAUCTR       MUST PAUSE. RESET CNTR
          BSR.S INCH7              WAIT FOR RESTART CHAR
          CMP.B #$0D,D5            QUIT IF IT'S A CR
          BEQ.L NXTCMD
NOPAUS    TST.B STATUS             PRINT ON PORT P?
          BPL.S NOTPT0             NO
          BSR.L OUTCHP             YES
NOTPT0    BTST #6,STATUS           PRINT ON CTL PORT?
          BEQ.S NOTPTM             NO
          BSR.L OUTCHM             YES
NOTPTM    BTST #4,STATUS           OUTPUT ON D?
          BEQ.S NOTPTD             NO
          MOVEM.L D4-D4,-(A7)         SAVE CHAR
          MOVE.L DVECTR,A6
          JSR (A6)                 YES
          MOVEM.L (A7)+,D4-D4      RESTORE CHAR
NOTPTD    MOVEM.L (A7)+,A6-A6
          RTS

* ALTERNATE OUTEEE ENTRY W/O CTRL-S TEST

OUTNOT    MOVEM.L A6-A6,-(A7)      SAVE REGISTER
          BRA.S NOTEST

*******************************************************
* 'RC' - REGISTER CHANGE
*******************************************************

REGCHG    MOVE.L #WHMESG,A4
          JSR PDATA                ASK WHICH REGISTER
          JSR INEEE                GET FIRST LETTER
          MOVE.B D5,D0             MOVE INTO D0
          LSL.W #8,D0              MOVE LEFT 1 BYTE
          JSR INEEE                GET SECOND
          MOVE.B D5,D0             COMBINE WITH FIRST
          OR.W #$2020,D0           UPPER TO LOWER CASE >>C<<
          CMP.W #$7573,D0          IS IT 'US'? >>C<<
          BEQ.S RCUS               YES
          CMP.W #$7373,D0          IS IT 'SS'? >>C<<
          BEQ.S RCSS               YES
          MOVE.B #18,D1            COUNT 18 REG NAMES
          LEA REGERS-1,A0          POINT TO REGISTERS
          LEA RNAMES(PC),A1        POINT TO NAME TABLE
RCLOOP    CMP.W (A1)+,D0           COMPARE NAME
          BEQ.S RCOK               IF LETTER FOUND
          ADD.L #4,A0              POINT TO NEXT REGISTER
          SUB.B #1,D1              CHECK COUNTER
          BNE.S RCLOOP             LOOP TIL DONE
          JMP COMEND               QUIT WITH '?' IF NG
RCSS      LEA SYSTSP-1,A0
          JMP CHANG0               GO TO 'ME' IF OK
RCUS      LEA USERSP-1,A0
RCOK      JMP CHANG0               GO TO 'ME' IF OK
RNAMES    FCC 'd0d1d2d3d4d5d6d7a0a1a2a3a4a5a6a7'    >>C<<
          FCC 'pcsr'               REGISTER NAMES   >>C<<
********************************************************
* "LO" COMMAND - LOAD S1S9 FORMAT FORMAT TAPE
********************************************************

LOAD      JSR INEEE                GET THE FIRST CHAR
          CMP.B #$53,D5            S?
          BNE.S LOAD               1ST CHAR NOT S
          JSR INEEE                GET NEXT CHAR
          CMP.B #$39,D5            S9?
          BEQ.L LOAD21             YES, FINISH LOADING
          CMP.B #$38,D5            S8?
          BEQ.L LOAD21             YES, FINISH LOADING
          CMP.B #$37,D5            S7?
          BEQ.S LOAD21             YES, FINISH LOADING
          CMP.B #$31,D5            S1?
          BEQ.S LOADS1             YES
          CMP.B #$32,D5            S2?
          BEQ.S LOADS2             YES
          CMP.B #$33,D5            S3?
          BEQ.L LOADS3             YES
          BRA.S LOAD               2ND CHAR NOT VALID

* LOAD S1 ROUTINE - 2-BYTE ADDRESS
LOADS1    CLR.L D1                 ZERO CHECKSUM
          JSR BYTE                 READ BYTE (D5) & CSUM
          SUB.B #2,D5
          CLR.L D2                 ZERO COUNTER (D2)
          MOVE.B D5,D2             SET COUNTER
          CLR.L D5
LOADR2    JSR BYTE                 GET ADDRESS BYTE & CSUM
          LSL.L #8,D5              MOVE INTO NEXT BYTE
          JSR BYTE                 SECOND ADDRESS BYTE & CSUM
          MOVE.L D5,A0             FORM ADDRESS
* STORE DATA
LOAD11    JSR BYTE                 GET BYTE TO LOAD & CSUM
          SUB.L #1,D2              DECR COUNT
          BEQ.S LOAD15             ZERO BYTE COUNT?
          MOVE.B D5,(A0)           STORE DATA
          CMP.B (A0),D5            DATA STORED?
          BNE.S LOAD19
          ADD.L #1,A0              NEXT ADDRESS
          BRA.S LOAD11
LOAD15    EOR.B #$FF,D1            COMPLEMENT CHECKSUM
          BEQ.L LOAD               OK IF ZERO
LOAD19    MOVE.B #$3F,D4           PRINT ? IF ERROR
          JSR OUTEEE

LOAD21    JMP NXTCMD               QUIT WHEN DONE

* LOAD S2 ROUTINE - 3-BYTE ADDRESS
LOADS2    CLR.L D1                 ZERO CHECKSUM
          JSR BYTE                 READ BYTE (D5) (CSUM)
          SUB.B #3,D5
          CLR.L D2                 ZERO COUNTER (D2)
          MOVE.B D5,D2             SET COUNTER
          CLR.L D5
LOADR3    JSR BYTE                 GET ADDRESS BYTE & CSUM
          LSL.W #8,D5              MOVE INTO NEXT BYTE
          BRA.S LOADR2             READ 2 MORE BYTES, CONTINUE

* LOAD S3 ROUTINE - 4-BYTE ADDRESS
LOADS3    CLR.L D1                 ZERO CHECKSUM
          JSR BYTE                 READ BYTE (D5) (CSUM)
          SUB.B #4,D5
          CLR.L D2                 ZERO COUNTER (D2)
          MOVE.B D5,D2             SET COUNTER
          CLR.L D5
          JSR BYTE                 GET ADDRESS BYTE & CSUM
          LSL.W #8,D5              MOVE INTO NEXT BYTE
          BRA.S LOADR3             READ 3 MORE BYTES, CONTINUE

********************************************************
* 'HD' HEX DUMP COMMAND
* 'AD' ASCII DUMP COMMAND
* 'HA' COMBINED HEX AND ASCII DUMP
********************************************************

HEXDMP    MOVE.B #$FF,D0           HD IS <0 FLAG
          BRA.S HDADHA
ASCDMP    CLR.B D0                 AD IS =0 FLAG
          BRA.S HDADHA
HEXASC    MOVE.B #$1,D0            HA IS >0 FLAG

HDADHA    JSR FROMTO
          MOVE.L BEGA,D4           GET STARTING ADDRESS
          MOVE.L D4,A0             STORE IT
          MOVE.L D4,A1             WORKING COPY
DUMP      JSR CRLF                 JSR CRLF
          MOVE.L A1,D4
          CMP.L #$10000,D4         NEED 4 OR 8 DIGITS?
          BCS.S DUMP0              4 IF <10000
          JSR OUT8HS               ELSE USE 8
          BRA.S DUMP1
DUMP0     JSR OUT4HS               PRINT ADDRESS
DUMP1     JSR OUTS                 EXTRA SPACE
          TST.B D0                 CHECK FLAG
          BEQ.S ONLYAS             ONLY ASCII IF FLAG=0
          MOVE.B #16,D1            SET COUNTER TO 16
DUMP2     MOVE.W A1,D4
          AND.B #$07,D4            ON 0 OR 8 BOUNDARY?
          BNE.S DUMP2A             NO
          JSR OUTS                 YES, SKIP SPACE
DUMP2A    MOVE.B (A1)+,D4          GET THE BYTE
          JSR OUT2HS               PRINT NEXT BYTE
          SUB.B #1,D1              DECREMENT COUNTER
          BNE.S DUMP2              CONTINUE LINE IF NOT FINISHED
          TST.B D0                 SHOULD WE DO ASCII?
          BMI.S NOASCI             DON'T DO IF MINUS
          MOVE.L A0,A1             RESTORE WORKING ADDRESS
          JSR OUTS                 PRINT ANOTHER SPACE
ONLYAS    MOVE.B #16,D1            SET COUNTER TO 16 AGAIN
DUMP3     MOVE.W A1,D4
          AND.B #$07,D4            ON 0 OR 8 BOUNDARY?
          BNE.S DUMP3A             NO
          JSR OUTS                 YES, SKIP SPACE
DUMP3A    MOVE.B (A1)+,D4          GET THE BYTE
          AND.B #$7F,D4            MASK OFF PARITY BIT
          CMP.B #$7E,D4
          BCC.S DUMP4              SUBSTITUTE . FOR 7E,7F
          CMP.B #$20,D4
          BCC.S DUMP5              PRINT SPACE AND ABOVE
DUMP4     MOVE.B #$2E,D4           SUBSTITUTE . FOR ALL ELSE
DUMP5     JSR OUTEEE               PRINT IT
          SUB.B #1,D1              DECREMENT COUNTER
          BNE.S DUMP3              CONTINUE LINE IF NOT FINISHED
NOASCI    MOVE.L A1,A0             SAVE CURRENT
          CMP.L ENDA,A1            ARE WE DONE?
          BCS.L DUMP               NO, DO NEXT LINE
          RTS


********************************************************
* FROMTO SUBR - INITIALIZE BEGA AND ENDA ADDRESSES
********************************************************

FROMTO    LEA FROMST,A4
          JSR PDATA                PRINT "FROM "
          JSR INEEE                GET CHARACTER
          CMP.B #$0D,D5            IS IT A CR?
          BEQ.L CRLF               ON CR, DO CRLF AND RETURN
          JSR CVTHEX               CONVERT TO HEX
          BEQ.L NXTCMD             ABORT IF SPACE
          CLR.L D6
          MOVE.B D5,D6             READY TO FINISH WITH BADDR
          JSR BADDR1               GET REST OF NUMBER
          MOVE.L D5,BEGA           BEGINNING ADDRESS
          LEA TOSTR(PC),A4
          JSR PDATA                PRINT "TO "
          JSR BADDR                GET TO ADDRESS
          MOVE.L D5,ENDA           STORE IT
          JMP OUTS                 AND EXIT

********************************************************
* "FI" COMMAND - FIND 1 TO 5 BYTES IN MEMORY
********************************************************

FIND      LEA MANYST,A4
          JSR PDATA                ASK "HOW MANY BYTES"
          JSR INEEE                GET NUMBER
          SUB.B #$30,D5            CONVERT FROM ASCII
          BEQ.L CRLF               IF = 0
          CMP.B #$5,D5
          BHI.L CRLF               IF GREATER THAN 3
          MOVE.B D5,D3             STORE NUMBER OF BYTES
          MOVE.B D5,D2             BACKUP COPY
          JSR OUTS
          LEA WHATST(PC),A4
          JSR PDATA                ASK "WHAT BYTES"
          LEA WHAT,A0              WHERE TO PUT DESIRED BYTES
FIENTR    JSR BYTE                 ENTER A BYTE
          MOVE.B D5,(A0)+          STORE IT
          SUB.B #1,D3
          BNE.S FIENTR             ENTER MORE, IF NEEDED
          JSR FROMTO               GET BEGA AND ENDA
          MOVE.L BEGA,A0           GET READY TO LOOK
FIND1     MOVE.B D2,D1             RESET NUMBER OF BYTES
          MOVE.B (A0),D0           GET FIRST BYTE
          CMP.B WHAT,D0
          BNE.S FIND4              WRONG BYTE
          SUB.B #1,D1
          BEQ.S FIND2              FOUND ONE CORRECT BYTE
          MOVE.B 1(A0),D0          GET SECOND BYTE
          CMP.B WHAT+1,D0
          BNE.S FIND4              WRONG
          SUB.B #1,D1
          BEQ.S FIND2              FOUND TWO CORRECT BYTES
          MOVE.B 2(A0),D0          GET THIRD BYTE
          CMP.B WHAT+2,D0
          BNE.S FIND4              WRONG
          SUB.B #1,D1
          BEQ.S FIND2              FOUND THREE CORRECT BYTES
          MOVE.B 3(A0),D0          GET FOURTH BYTE
          CMP.B WHAT+3,D0
          BNE.S FIND4              WRONG
          SUB.B #1,D1
          BEQ.S FIND2              FOUND FOUR CORRECT BYTES
          MOVE.B 4(A0),D0          GET FIFTH BYTE
          CMP.B WHAT+4,D0
          BNE.S FIND4              WRONG BYTE
FIND2     BSR.L CRLF               PRINT CRLF
          MOVE.L A0,D4
          BSR.L OUT8HS             PRINT ADDRESS
          JSR OUTS                 ONE MORE SPACE
          LEA -1(A0),A1            BACKUP ONE BYTE
          MOVE.B #7,D1             READY TO PRINT SEVEN BYTES
FIND3     MOVE.B (A1)+,D4
          JSR OUT2HS               PRINT BYTE
          CMP.B #7,D1              BEFORE SECOND BYTE?
          BNE.S FIND3A             NO
          MOVE.B #$3E,D4           POINT TO IT
          JSR OUTEEE
FIND3A    SUB.B #01,D1
          BNE.S FIND3              PRINT FOUR BYTES
FIND4     CMP.L ENDA,A0            SEE IF DONE
          BEQ.L CRLF               YES
          ADD.L #1,A0              NO
          BRA.L FIND1              KEEP LOOKING

********************************************************
* "FM" COMMAND - FILL MEMORY WITH CONSTANT
********************************************************

FILL      JSR FROMTO               GET FROM-TO ADDRESSES
          LEA WITHST,A4
          JSR PDATA                ASK FOR DATA
          JSR BYTE                 INPUT
          MOVE.L BEGA,A0           GET STARTING ADDRESS
          MOVE.L ENDA,A1           ENDING ADDRESS
          ADD.L #1,A1              SIMPLIFY COMPARISON
FILOOP    MOVE.B D5,(A0)+          STORE THE BYTE
          CMP.L A1,A0              SEE IF DONE
          BNE.S FILOOP             CONTINUE OF NO
          RTS                      QUIT WHEN DONE

********************************************************
* SUM - MEMORY CHECKSUM
********************************************************

SUM       JSR FROMTO               GET ADDRESS LIMITS
          MOVE.L BEGA,A0           GET STARTING ADDRESS
          MOVE.L ENDA,A1           GET ENDING ADDRESS
          CLR.L D0
          CLR.L D1
SUMLP     MOVE.B (A0)+,D1          GET BYTE
          ADD.L D1,D0              ADD INTO CHECKSUM
          CMP.L ENDA,A0            LAST ADDRESS?
          BLS.S SUMLP              NO, REPEAT
SUMDON    MOVE.L D0,D4
          JSR OUT8HS               OUTPUT CHECKSUM
          RTS

********************************************************
* 'MT' - MEMORY TEST
********************************************************

MTEST     JSR FROMTO               GET ADDRESS LIMITS
          MOVE.L BEGA,A0
          MOVE.L ENDA,A2
LODREG    MOVE.B (A0),D2           SAVE OLD CONTENTS
          MOVE.B #1,D0             STORE 1 IN MEMORY
          MOVE.B D0,(A0)
          CMP.B (A0),D0            WAS IT WRITTEN?
          BNE.S ERRPNT             NO
ROLP1     ASL.B #1,D0
          BEQ.S INCR1              DONE WHEN ALL ZEROES
          MOVE.B D0,(A0)           STORE NEXT BIT
          CMP.B (A0),D0            CHECK IT
          BEQ.S ROLP1              OK, DO NEXT BIT
ERRPNT    JSR CRLF                 ON ERROR
          MOVE.L A0,D4             ADDRESS OF WRONG BYTE
          BSR.L OUT8HS             PRINT IT
          MOVE.B D0,D4             INCORRECT BIT
          JSR OUT2HS               OUTPUT WHAT SHOULD BE STORED
          MOVE.B (A0),D4           WRONG BIT
          JSR OUT2HS               OUTPUT WHAT WAS STORED
INCR1     MOVE.B D2,(A0)           RESTORE PREVIOUS CONTENTS
          CMP.L A2,A0              COMPARE WITH END ADDRESS
          BEQ.S FINISH
          ADD.L #1,A0
          BRA.S LODREG             DO NEXT BYTE IF NOT DONE
FINISH    MOVE.B #$2B,D4
          JSR OUTEEE               PRINT "+"
          RTS

********************************************************
* 'AI' COMMAND - ASCII INPUT ROUTINE
********************************************************

ASCIN     JSR FROMTO               GET ADDRESS RANGE
          JSR CRLF
          MOVE.L ENDA,A1           GET LAST EMPTY ADDRESS
          MOVE.L BEGA,A0           GET STARTING ADDRESS
          SUB.L #1,A0
ASCI2     ADD.L #1,A0
          JSR INEEE                GET NEXT CHARACTER
          MOVE.B D5,(A0)           STORE IT
          CMP.B (A0),D5            SEE IF IT STORED OK
          BNE.S ASCI3              NO, ERROR
          MOVE.L A0,ENDA           STORE ENDING ADDRESS
          CMP.L A0,A1              CHECK IF RUN OUT OF MEMORY
          BNE.S ASCI2              NO, SO GET MORE
ASCI3     LEA ESTR,A4              MEM FULL OR BAD, SO..
          JSR PDATA                PRINT ERROR
          BRA.L NXTCMD             QUIT

********************************************************
* 'AO' COMMAND - ASCII OUTPUT ROUTINE
********************************************************

ASCOUT    JSR FROMTO               GET ADDRESS RANGE
          JSR CRLF
          MOVE.L BEGA,A0           GET STARTING ADDRESS
          MOVE.L ENDA,A1           GET ENDING ADDRESS
ASCO2     MOVE.B (A0),D4           GET NEXT CHARACTER
          JSR OUTEEE               OUTPUT IT
          CMP.L A0,A1              SEE IF DONE
          BEQ.S ASCO3              YES
          ADD.L #1,A0
          BRA.S ASCO2              REPEAT IF NOT
ASCO3     RTS                      RETURN WHEN DONE

********************************************************
* 'MO' COMMAND - MOVE MEMORY ROUTINE
********************************************************

MOVE      LEA OLDSTR,A4
          JSR PDATA                ASK FOR OLD ADDRESSES
          JSR FROMTO
          JSR CRLF
          LEA NEWSTR,A4
          JSR PDATA                ASK FOR NEW ADDRESS
          JSR BADDR
          MOVE.L D5,A2             SAVE NEW ADDRESS
          MOVE.L BEGA,A0           BEGINNING ADDRESS
          MOVE.L ENDA,A1           ENDING ADDRESS
* NOW CHECK FOR FORWARD MOVE OR BACKWARD MOVE
          MOVE.L A0,D0             BEGINNING
          SUB.L A2,D0              SUBTRACT NEW
          BCS.S BACK               BACKWARD IF BEGINNING<NEW
          BNE.S FWD1
MEXIT     RTS                      NO MOVE IF NEW=OLD
* FORWARD MOVE
FWD1      MOVE.B (A0)+,(A2)+       MOVE AND INCREMENT
          CMP.L A0,A1              END?
          BNE.S FWD1               NO
          MOVE.B (A0),(A2)         MOVE LAST BYTE
          RTS                      RTS
* BACKWARD MOVE
BACK      MOVE.L A1,D0
          SUB.L A0,D0              COMPUTE NEW END
          ADD.L A2,D0
          MOVE.L D0,A3             TFR D,Y
          MOVE.B (A1),(A3)         MOVE LAST
BACK1     CMP.L A0,A1              DONE?
          BEQ.S MEXIT              YES
          MOVE.B -(A1),-(A3)       DECREMENT AND MOVE
          BRA.S BACK1              AND REPEAT

********************************************************
* 'BR' COMMAND - SET/RESET UP TO FOUR BPS
********************************************************

BREAK     BSR.S BKNUM              POINT A0 TO BP IN TABLE
          BSR.S BERASE             GO ERASE OLD ONE
          LEA NEWSTR(PC),A4        PRINT "ENTER NEW ADDRESS: "
          JSR PDATA
          JSR BADDR                GET ADDRESS
          BTST #0,D5               CHECK WHETHER EVEN
          BNE.S ODDADD             NO
          TST.L D5
          BEQ.L COMEND             NG IF ZERO
          MOVE.L D5,A1             POINT TO DESIRED BP
          MOVE.L D5,(A0)           STORE ADDRESS IN TABLE
          MOVE.W (A1),4(A0)        STORE PRESENT OP CODE
          MOVE.W #$4AFC,(A1)       SUBST INVALID INSTRUCTION CODE
          RTS                      AND RETURN
ODDADD    LEA ANEMSG(PC),A4
          JSR PSTRNG               PRINT "ADDRESS NOT EVEN"
          JMP NXTCMD

* ERASE PREVIOUS BP, IF ANY, AND RESTORE OP CODE
BERASE    MOVE.W 4(A0),D1          GET OP CODE
          MOVE.L (A0),A1           GET ADDRESS
          CMP.L #$FFFFFFFF,A1      WAS THERE A BP?
          BEQ.S BEEXIT             NO, EXIT
          MOVE.W D1,(A1)           YES, RESTORE OP CODE
          MOVE.L #$FFFFFFFF,(A0)   ERASE BP TABLE ENTRY
BEEXIT    RTS                      AND RETURN

********************************************************
* BKNUM ROUTINE - GET NO OF DESIRED BP & POINT
* TO ITS LOCATION IN BKTAB TABLE
********************************************************

BKNUM     LEA BNSTR,A4
          JSR PDATA
          JSR INEEE                GET BP NUMBER
          SUB.B #$30,D5            CONVERT FROM ASCII
          BEQ.L NXTCMD             IF ZERO
          CMP.B #$4,D5
          BHI.L NXTCMD             IF GREATER THAN 4
          CLR.L D0
          MOVE.B D5,D0
          JSR OUTS
          MOVE.W #6,D1
          MULU D0,D1               OFFSET INTO TABLE
          LEA BKTAB-6,A0           POINT TO BREAKPOINT TABLE
          LEA 0(A0,D1.L),A0         POINT TO ENTRY IN TABLE
          RTS                      RETURN WHEN DONE

********************************************************
* 'BP' COMMAND - PRINT BP LOCATIONS
********************************************************

BPRINT    MOVE.B #$30,D1           BP NUMBER IN ASCII
          LEA BKTAB,A0             POINT TO TABLE
BPR1      ADD.B #01,D1             NEXT BP NUMBER
          CMP.B #$35,D1            STOP AT 5 BPS
          BNE.S BPR2
          RTS                      RETURN WHEN DONE
BPR2      JSR CRLF                 PRINT CR
          MOVE.L D1,D4             GET BP NUMBER
          JSR OUTEEE               PRINT BP NUMBER
          JSR OUTS                 PRINT SPACE
          MOVE.L (A0)+,D4          GET BP ADDRESS
          CMP.L #$FFFFFFFF,D4      IS THERE ONE?
          BNE.S BPR3               YES, GO PRINT IT
          ADD.L #2,A0              POINT TO NEXT
          BRA.S BPR1               AND REPEAT
BPR3      JSR OUT8HS               PRINT ADDRESS OF BP
          MOVE.W (A0)+,D4          GET OP CODE
          JSR OUT4HS               PRINT OP CODE
          BRA.S BPR1               AND REPEAT

********************************************************
* 'RE' COMMAND - PRINT USER REGISTERS FROM STACK
********************************************************

REGIST    JSR CRLF                 JSR CRLF
          MOVE.W USERSR,D7         CHECK USER STATUS
          BTST.W #13,D7            CHECK S BIT
          BEQ.S A7ISUS             ZERO MEANS A7 IS USP
          MOVE.L SYSTSP,D7         ELSE A7 IS SYSTEM SP
          BRA.S OKONA7
A7ISUS    MOVE.L USERSP,D7         A7 IS USER SP
OKONA7    MOVE.L D7,REGA7
          LEA REMSG,A4             POINT TO COLUMN HEADER
          JSR PDATA                PRINT HEADER
          JSR CRLF
          LEA REGERS,A0            POINT TO REGISTER TABLE
          LEA DMSG,A4
          JSR PDATA                PRINT "D: "
          MOVE.B #8,D0             COUNT D REGISTERS
DPLOOP    MOVE.L (A0)+,D4          GET NEXT
          JSR OUT8HS               OUTPUT D REGISTER
          SUB.B #1,D0              DECREMENT COUNTER
          BNE.S DPLOOP             REPEAT UNTIL DONE
          JSR CRLF                 NEXT LINE
          LEA AMSG,A4
          JSR PDATA                PRINT "A: "
          MOVE.B #8,D0             COUNT A REGISTERS
APLOOP    MOVE.L (A0)+,D4          GET NEXT
          JSR OUT8HS               OUTPUT A REGISTER
          SUB.B #1,D0              DECREMENT COUNTER
          BNE.S APLOOP             REPEAT UNTIL DONE
          JSR CRLF                 NEXT LINE
          LEA PCMSG,A4
          JSR PDATA                PRINT "PC="
          MOVE.L (A0)+,D4          GET IT
          JSR OUT8HS               PRINT REGISTER
          LEA SRMSG,A4
          JSR PDATA                PRINT "SR="
          MOVE.W (A0)+,D4          GET IT
          MOVE.W D4,D0             SAVE IT
          MOVE.W D4,D2             SAVE IT
          JSR OUT4HS               PRINT REGISTER
          MOVE.B #$3D,D4
          JSR OUTEEE               PRINT EQUALS
          LEA SRLETR,A0            POINT TO LETTER TABLE
          MOVE.B #5,D1             DO FIRST FIVE LETTERS
          BSR.S SRLOOP             PRINT LETTERS
          MOVE.W D2,D4             GET INTERRUPT MASK
          LSR.W #8,D4              INTO RIGHT BYTE
          AND.B #$07,D4            INTERRUPT ONLY
          ADD.B #$30,D4            CVT TO ASCII
          JSR OUTEEE               PRINT IT
          LSL.W #3,D0              SKIP THE INTERRUPT BITS
          MOVE.B #8,D1             DO LAST 8 BITS
          BSR.S SRLOOP             PRINT LETTERS
          LEA USMSG,A4
          JSR PDATA                PRINT "US="
          MOVE.L USERSP,D4         GET IT
          JSR OUT8HS               PRINT REGISTER
          LEA SSMSG,A4
          JSR PDATA                PRINT "SS="
          MOVE.L SYSTSP,D4         GET IT
          JSR OUT8HS               PRINT REGISTER
          JSR CRLF                 FINISH UP
          RTS
* LOOP TO PRINT LETTERS FOR SR
SRLOOP    MOVE.B (A0)+,D4          GET NEXT LETTER
          LSL.W #1,D0              NEXT BIT INTO C
          BCS.S SRLUSE             IS 1 SO USE LETTER
          MOVE.B #$2E,D4           IS 0 SO SUBSTITUTE PERIOD
SRLUSE    JSR OUTEEE               PRINT IT
          SUB.B #1,D1              DECREMENT COUNTER
          BNE.S SRLOOP
          RTS
SRLETR    FCC 'TTSM????XNZVC'

********************************************************
* 'ST' - START SINGLE-STEP COMMAND
********************************************************

STRTSS    LEA FROMST,A4
          JSR PDATA                PRINT "FROM "
          JSR BADDR                GET ADDRESS
          TST.L D5
          BEQ.L COMEND             NG IF ZERO
          BTST #0,D5
          BNE.L ODDADD             NG IF ODD ADDRESS
          LEA WARMST,A0
          MOVE.L A0,USTACK-4       PUT RETURN ADDRESS ON STACK
          MOVE.L A0,SSTACK-4       PUT RETURN ADDRESS ON STACK
          LEA USTACK-4,A0
          MOVE.L A0,USERSP         INITIALIZE USER SP MEMORY
          LEA SSTACK-4,A0
          MOVE.L A0,SYSTSP         INITIALIZE SYST SP MEMORY
STEPCO    MOVE.W USERSR,D0         OLD STATUS REGISTER
          MOVE.L SYSTSP,A7         USE HIS SYSTEM SP
* USE 8 IN FOLLOWING INSTRUCTION FOR 68010/68020 >>B<<
          SUB.L #6,A7              BUT STEP BACK 6 TO MAKE ROOM
          MOVE.W D0,(A7)           PUT USER SR ON STACK
          MOVE.L D5,2(A7)          PUT GOTO ADDRESS ON STACK
* USE FOLLOWING INSTRUCTION FOR 68010/68020 >>B<<
*         CLR.W 6(A7)              CLEAR 68010/20 FORMAT
          MOVE.L USERSP,A0
          MOVE.L A0,USP            SET USER STACK POINTER
          MOVE.L $0024,A5
          MOVE.L A5,TRAVEC         SAVE OLD TRACE VECTOR
          LEA TRARET(PC),A5
          MOVE.L A5,$0024          PUT IN NEW TRACE VECTOR
          MOVE.L D5,A0             SAVE GOTO ADDRESS
          BSR.L PRTINS             PRINT OUT ADDRESS AND INSTR
          MOVEM.W (A0),D5-D5       LOOK AT THE NEXT INSTRUCTION
          CMP.W #$4E73,D5          IS IT AN RTE???
          BEQ.S ISRTE              YES, IT IS AN RTE
* SIMPLE IF IT'S NOT AN RTE
          MOVE.W (A7),D5           GET USER SR
          OR.W #$8000,D5           TURN ON TRACE BIT
          MOVE.W D5,(A7)           AND BACK ON STACK
          MOVEM.L REGERS,D0-D7/A0-A6 RESTORE REGISTERS
          RTE                      AND GO TO USER

* THEN COME BACK TO HERE
TRARET    MOVEM.L D0-D7/A0-A7,REGERS SAVE REGISTERS
          MOVE.W (A7),D0
          AND.W #$7FFF,D0          TURN OFF TRACE BIT
          MOVE.W D0,USERSR         SAVE USER STATUS REGISTER
          MOVE.L 2(A7),USERPC      AND USER PC
          MOVE.L USP,A0
          MOVE.L A0,USERSP         AND USER STACK POINTER
          BTST.W #13,D0            CHECK S BIT IN SR
          BEQ.S TRARUS             S=0 WAS USER MODE
          MOVE.L REGA7,D0          S=1 WAS SYSTEM, SO SAVE SYST SP
          ADD.L #6,D0              REMOVE SR AND PC
          MOVE.L D0,SYSTSP
TRARUS    MOVE.L TRAVEC,A5
          MOVE.L A5,$0024          RESTORE OLD TRACE VECTOR
          MOVE.W SYSTSR,SR         RESTORE INTERRUPT LEVEL
          JSR REGIST               PRINT REGISTERS
          JMP NXTCMD

* IF NEXT INSTRUCTION IS AN RTE, WE HAVE TO CARRY TRACE ACROSS
* CHANGE OF STATE

ISRTE     MOVE.L USERSP,A5         USER'S STACK POINTER
          MOVE.W (A5),D0           GET SR HE'S RETURNING
          OR.W #$8000,D0           SET THAT TRACE BIT
          MOVE.W D0,(A5)           RETURN IT
          MOVEM.L REGERS,D0-D7/A0-A6 RESTORE REGISTERS
          RTE                      AND FINALLY GO TO USER

* ROUTINE TO PRINT OUT INSTRUCTION POINTED TO BY A0

PRTINS    JSR CRLF                 NEXT LINE
          MOVE.L A0,D4             GOTO ADDRESS
          SWAP D4
          BSR.L OUT4H              PRINT IT W/O TRAILING SPACE
          SWAP D4
          BSR.L OUT4H
          MOVE.B #$3A,D4
          JSR OUTEEE               PRINT :
          MOVE.B #$20,D4
          JSR OUTEEE               PRINT SPACE
          MOVE.W (A0),D4
          JSR OUT4HS               PRINT OP CODE
          RTS

********************************************************
* 'SS' COMMAND - SINGLE STEP AFTER BREAKPOINT
********************************************************

STEP      MOVE.L USERPC,D5         WHERE TO GO
          BRA.L STEPCO             AND CONTINUE AS IN ST

********************************************************
* 'CO' COMMAND - CONTINUE AFTER A BREAKPOINT
********************************************************

CONT      MOVE.L USERPC,D5         WHERE TO GO
          MOVE.W USERSR,D0         OLD STATUS REGISTER
          MOVE.L SYSTSP,A7         USE HIS SYSTEM SP
* USE 8 IN FOLLOWING INSTRUCTION FOR 68010/68020 >>B<<
          SUB.L #6,A7              BUT STEP BACK 6 TO MAKE ROOM
          MOVE.W D0,(A7)           PUT USER SR ON STACK
          MOVE.L D5,2(A7)          PUT GOTO ADDRESS ON STACK
* USE FOLLOWING INSTRUCTION FOR 68010/68020 >>B<<
*         CLR.W 6(A7)              CLEAR 68010/20 FORMAT
          MOVE.L USERSP,A0
          MOVE.L A0,USP            SET USER STACK POINTER
          MOVEM.L REGERS,D0-D7/A0-A6 RESTORE REGISTERS
          RTE                      AND GO TO USER

********************************************************
* 'MC' - MEMORY COMPARISON ROUTINE
********************************************************

COMPAR    LEA P1MSG,A4
          JSR PDATA                PRINT 'PROGRAM 1: '
          JSR FROMTO               GET PROGRAM 1 START AND END ADDR.
          JSR CRLF
          LEA P2MSG,A4
          JSR PDATA                PRINT 'PROGRAM 2: FROM '
          JSR BADDR                GET PROGRAM 2 START ADDR.
          MOVE.L BEGA,A0           PROG 1 START
          MOVE.L ENDA,A1           PROG 1 END
          ADD.L #1,A1              POINT PAST IT
          MOVE.L D5,A2             PROG 2 START
          JSR CRLF                 JSR CRLF
          MOVE.B #3,D0             INITIALIZE LINE COUNTER
MCLOOP    MOVE.B (A0)+,D7          GET NEXT BYTE FROM PGM 1
          CMP.B (A2)+,D7           COMPARE WITH PGM 2
          BEQ.S INCR               IF SAME, SEE IF DONE
* DIFFERENT BYTES, SO PRINT
          SUB.B #1,D0              DECREMENT LINE COUNTER
          BNE.S MCCONT             IF ROOM ON LINE, CONTINUE
          MOVE.B #2,D0             OTHERWISE RESET
          JSR CRLF
MCCONT    JSR OUTS
          JSR OUTS                 PRINT TWO SPACES
          MOVE.L A0,D4
          SUB.L #1,D4
          JSR OUT8HS               PRINT ADDRESS 1
          MOVE.B -1(A0),D4
          JSR OUT2HS               PRINT DATA 1
          MOVE.L A2,D4
          SUB.L #1,D4
          JSR OUT8HS               PRINT ADDRESS 2
          MOVE.B -1(A2),D4
          JSR OUT2HS               PRINT DATA 2
INCR      CMP.L A0,A1              DONE?
          BNE.S MCLOOP
          RTS                      FINISH UP

********************************************************
* 'HE' - HELP COMMAND
********************************************************

HELP      JSR CRLF
          LEA HLPMSG,A4
          JSR PSTRNG               PRINT HELP TEXT
          RTS
******************************************************
* TRAP PROCESSING
******************************************************

* BUSERR - BUS ERROR

BUSERR    LEA BUSMSG(PC),A4
          JSR PSTRNG
          JMP REPORS

* ADDERR - ADDRESS ERROR

ADDERR    LEA ADDMSG(PC),A4
          JSR PSTRNG
          JMP REPORS

* ILLINS - ILLEGAL INSTRUCTION

ILLINS    MOVEM.L D0-D7/A0-A7,REGERS SAVE REGISTERS
          MOVE.W (A7),D0
          MOVE.W D0,USERSR         SAVE SR
          MOVE.L USP,A0
          MOVE.L A0,USERSP         SAVE SP
          MOVE.L 2(A7),A0          GET USER'S PC
          MOVE.L A0,USERPC         SAVE PC
          BTST.W #13,D0            CHECK S BIT IN SR
          BEQ.S ILLIUS             S=0 WAS USER MODE
          MOVE.L REGA7,D0          S=1 WAS SYSTEM, SO SAVE SYST SP
          ADD.L #6,D0              SKIP PAST SR AND PC
          MOVE.L D0,SYSTSP
ILLIUS    MOVE.W (A0),D0           GET OFFENDING INSTRUCTION
          CMP.W #$4AFC,D0          CHECK IF A BREAK
          BEQ.S CHKILL             MAY BE LEGAL, GO CHECK
REALIL    LEA ILLMSG(PC),A4
          JSR PSTRNG
PRTILL    MOVE.L 2(A7),D4
          JSR OUT8HS               PRINT ADDRESS
          JSR REGIST               PRINT REGISTERS
          JMP NXTCMD
CHKILL    CMP.L BKTAB,A0           CHECK ADDRESS 1
          BEQ.S ISBRK              IT'S A BREAK
          CMP.L BKTAB+6,A0         CHECK ADDRESS 2
          BEQ.S ISBRK              IT'S A BREAK
          CMP.L BKTAB+12,A0        CHECK ADDRESS 3
          BEQ.S ISBRK              IT'S A BREAK
          CMP.L BKTAB+18,A0        CHECK ADDRESS 4
          BNE.S REALIL             DEFINITELY ILLEGAL
ISBRK     LEA BRKMSG,A4
          JSR PSTRNG               PRINT "BREAKPOINT AT "
          BRA.S PRTILL

* ZERDIV - ZERO DIVIDE

ZERDIV    LEA ZERMSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* CHKINS - CHK INSTRUCTION

CHKINS    LEA CHKMSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPVI - TRAPV INSTR

TRAPVI    LEA TVIMSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* PRIVIO - PRIVILEGE VIOLATION

PRIVIO    LEA PRIMSG(PC),A4
          JSR PSTRNG
          JMP REPORS

* LN1010 - LINE 1010

LN1010    LEA L10MSG(PC),A4
          JSR PSTRNG
          JMP REPORS

* LN1111 - LINE 1111

LN1111    LEA L11MSG(PC),A4
          JSR PSTRNG
          JMP REPORS

* UNASSI - UNASSIGNED

UNASSI    LEA UNAMSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* FORERR - FORMAT ERROR ON 68010

FORERR    LEA FORMSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* SPURIO - SPURIOUS INTERRUPT

SPURIO    LEA SPUMSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL1IA - LEVEL 1 INTERRUPT AUTOVECTOR

LVL1IA    LEA LV1MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL2IA - LEVEL 2 INTERRUPT AUTOVECTOR

LVL2IA    LEA LV2MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL3IA - LEVEL 3 INTERRUPT AUTOVECTOR

LVL3IA    LEA LV3MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL4IA - LEVEL 4 INTERRUPT AUTOVECTOR

LVL4IA    LEA LV4MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL5IA - LEVEL 5 INTERRUPT AUTOVECTOR

LVL5IA    LEA LV5MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL6IA - LEVEL 6 INTERRUPT AUTOVECTOR

LVL6IA    LEA LV6MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* LVL7IA - LEVEL 7 INTERRUPT AUTOVECTOR

LVL7IA    LEA LV7MSG(PC),A4
          JSR PSTRNG
          JMP WARMST

* TRAP0V - TRAP 0

TRAP0V    LEA TR0MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP1V - TRAP 1

TRAP1V    LEA TR1MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP2V - TRAP 2

TRAP2V    LEA TR2MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP3V - TRAP 3

TRAP3V    LEA TR3MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP4V - TRAP 4

TRAP4V    LEA TR4MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP5V - TRAP 5

TRAP5V    LEA TR5MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP6V - TRAP 6

TRAP6V    LEA TR6MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP7V - TRAP 7

TRAP7V    LEA TR7MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP8V - TRAP 8

TRAP8V    LEA TR8MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAP9V - TRAP 9

TRAP9V    LEA TR9MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPAV - TRAP 10

TRAPAV    LEA T10MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPBV - TRAP 11

TRAPBV    LEA T11MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPCV - TRAP 12

TRAPCV    LEA T12MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPDV - TRAP 13

TRAPDV    LEA T13MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* TRAPEV - TRAP 14

TRAPEV    LEA T14MSG(PC),A4
          JSR PSTRNG
          JMP REPORN

* REPORT ADDRESS OF EXCEPTION OCCURRENCE. REPORS ASSUMES
* PUSHED ADDRESS IS THAT OF TRAP, REPORN ASSUMES ADDRESS
* IS THAT OF NEXT INSTRUCTION

REPORS    MOVE.L 2(A7),D4          GET EXCEPTION'S PC
REPORT    JSR OUT8HS               REPORT IT
          JMP WARMST

REPORN    MOVE.L 2(A7),D4          GET EXCEPTION'S PC
          SUB.L #2,D4              FIX IT
          BRA.S REPORT

*******************************************************
* TEXT STRINGS
*******************************************************

BUSMSG    FCC 'BUS ERROR AT ',4
ADDMSG    FCC 'ADDRESS ERROR AT ',4
ILLMSG    FCC 'ILLEGAL INSTRUCTION AT ',4
ZERMSG    FCC 'ZERO DIVIDE AT ',4
CHKMSG    FCC 'CHK INSTRUCTION AT ',4
TVIMSG    FCC 'TRAPV INSTR AT ',4
PRIMSG    FCC 'PRIVILEGE VIOLATION AT ',4
L10MSG    FCC 'LINE 1010 AT ',4
L11MSG    FCC 'LINE 1111 AT ',4
UNAMSG    FCC 'UNASSIGNED',4
FORMSG    FCC 'FORMAT ERROR ON 68010',4
SPUMSG    FCC 'SPURIOUS INTERRUPT',4
LV1MSG    FCC 'LEVEL 1 INTERRUPT AUTOVECTOR',4
LV2MSG    FCC 'LEVEL 2 INTERRUPT AUTOVECTOR',4
LV3MSG    FCC 'LEVEL 3 INTERRUPT AUTOVECTOR',4
LV4MSG    FCC 'LEVEL 4 INTERRUPT AUTOVECTOR',4
LV5MSG    FCC 'LEVEL 5 INTERRUPT AUTOVECTOR',4
LV6MSG    FCC 'LEVEL 6 INTERRUPT AUTOVECTOR',4
LV7MSG    FCC 'LEVEL 7 INTERRUPT AUTOVECTOR',4
TR0MSG    FCC 'TRAP 0 AT ',4
TR1MSG    FCC 'TRAP 1 AT ',4
TR2MSG    FCC 'TRAP 2 AT ',4
TR3MSG    FCC 'TRAP 3 AT ',4
TR4MSG    FCC 'TRAP 4 AT ',4
TR5MSG    FCC 'TRAP 5 AT ',4
TR6MSG    FCC 'TRAP 6 AT ',4
TR7MSG    FCC 'TRAP 7 AT ',4
TR8MSG    FCC 'TRAP 8 AT ',4
TR9MSG    FCC 'TRAP 9 AT ',4
T10MSG    FCC 'TRAP 10 AT ',4
T11MSG    FCC 'TRAP 11 AT ',4
T12MSG    FCC 'TRAP 12 AT ',4
T13MSG    FCC 'TRAP 13 AT ',4
T14MSG    FCC 'TRAP 14 AT ',4
H68MSG    FCC 'HUMBUG / 68K '
          FCC 'Copyright (C) 1986, 1987 by Peter A. Stark',4
NOCMSG    FCC ' DATA DID NOT STORE',4
MEBMSG    FCC ' BUS ERROR',4
WHMESG    FCC 'REGISTER: ',4
FROMST    FCC ' FROM ',4
TOSTR     FCC ' TO ',4
MANYST    FCC 'HOW MANY BYTES? ',4
WITHST    FCC ' WITH? ',4
WHATST    FCC 'FIND WHAT? ',4
ESTR      FCC ' MEMORY FULL OR DEFECTIVE ',4
ANEMSG    FCC 'ADDRESS ERROR - NOT EVEN',4
BRKMSG    FCC 'BREAKPOINT ENCOUNTERED AT ',4
OLDSTR    FCC 'ENTER OLD ADDRESSES:',4
NEWSTR    FCC 'ENTER NEW ADDRESS: ',4
BNSTR     FCC ' NUMBER: ',4
REMSG     FCC '       0        1        2        3        4'
          FCC '        5        6        7',4
DMSG      FCC 'D: ',4
AMSG      FCC 'A: ',4
PCMSG     FCC 'PC=',4
SRMSG     FCC '   SR=',4
USMSG     FCC '   US=',4
SSMSG     FCC '   SS=',4
STMSG     FCC 'START FROM '
ADMSG     FCC 'ADDRESS: ',4
P1MSG     FCC 'REGION 1: ',4
P2MSG     FCC '     REGION 2:  FROM ',4
HLPMSG    FCC 'AD - ASCII Dump               JU - Jump to User program'
          DC.B $D,$A
          FCC 'AI - ASCII Input              LO - Load S1-S9 format'
          DC.B $D,$A
          FCC 'AO - ASCII Output             MC - Memory Compare'
          DC.B $D,$A
          FCC 'BP - Breakpoint Print         ME - Memory Examine'
          DC.B $D,$A
          FCC 'BR - BReakpoint set/reset     MO - MOve memory'
          DC.B $D,$A
          FCC 'CO - COntinue                 MS - Memory Store'
          DC.B $D,$A
          FCC 'CS - CheckSum                 MT - Memory Test'
          DC.B $D,$A
          FCC 'FD - Floppy Disk boot         RC - Register Change'
          DC.B $D,$A
          FCC 'FI - FInd 1-5 bytes           RD - Return to DOS'
          DC.B $D,$A
          FCC 'FM - Fill Memory              RE - Register Examine'
          DC.B $D,$A
          FCC 'HA - Hex and ASCII dump       SS - Single Step'
          DC.B $D,$A
          FCC 'HD - Hex memory Dump          ST - STart single-step'
          DC.B $D,$A
          FCC 'HE - HElp                     WD - Winchester Disk boot'
          DC.B $D,$A
          FCC 'JS - Jump to System program   !! - Force reset'
          DC.B $D,$A,4

**********************************************************
* SYSTEM - DEPENDENT ROUTINES
**********************************************************

**********************************************************
* JUMP TABLE WHICH LEADS US TO ALL OF THE FOLLOWING
* ROUTINES IN HUMBUG
**********************************************************

MEMRD     JMP MEMRD0             CHECK ALL OF MEMORY
PARON     JMP PARON0             TURN ON PARITY CIRCUITRY
INIPOR    JMP INIPO0             INITIALIZE PORTS
INCHEK    JMP INCHE0             CHECK INPUT PORT
INCH8     JMP INCH80             INPUT 8-BIT CHAR
OUTCHP    JMP OUTPCH             OUTPUT PRINTER CHARACTER
OUTCHM    JMP OUTMCH             OUTPUT CONSOLE CHARACTER
FLBOOT    JMP FLBOOO             SK*DOS FLOPPY BOOT
RETDOS    JMP DOSRET             RETURN TO DOS
WDBOOT    JMP HDBOOT             SK*DOS HARD DISK BOOT

**********************************************************
* PARITY MEMORY ROUTINES
* NEEDED ONLY IF MEMORY CONTAINS PARITY CIRCUITRY
**********************************************************

MEMRD0    RTS                      READ AND WRITE ALL OF MEMORY

PARON0    RTS                      THEN TURN ON PARITY CIRCUITRY

************************
* CONSOLE I/O ROUTINES *
************************

***********************************************************
* EQUATES. THESE ROUTINES USE A 68681 DUART AT $E0000
* FOR THE PT-68K COMPUTER
***********************************************************

DUART     EQU $E0000               DUART ADDRESS
DMODEA    EQU 1                    PORT A MODE REG
DCLOCA    EQU 3                    PORT A CLOCK REG
DSTATA    EQU 3                    PORT A STATUS REG
DCOMMA    EQU 5                    PORT A COMMAND REGISTER
DDATAA    EQU 7                    PORT A DATA REGISTERS
DAUXA     EQU 9                    PORT A AUXILIARY CONTROL REG
DMODEB    EQU 17                   PORT B MODE REG
DCLOCB    EQU 19                   PORT B CLOCK REG
DSTATB    EQU 19                   PORT B STATUS REG
DCOMMB    EQU 21                   PORT B COMMAND REGISTER
DDATAB    EQU 23                   PORT B DATA REGISTERS
DAUXB     EQU 25                   PORT B AUXILIARY CONTROL REG


***********************************************************
* INITIALIZE CONSOLE AND PRINTER PORTS, AND SET BAUD RATES
***********************************************************

INIPO0    MOVE.L #DUART,A0         POINT TO DUART
          MOVE.L A0,PORADM         SET CONTROL PORT ADDRESS
          MOVE.L A0,A1
          ADD.L #16,A1
          MOVE.L A1,PORADP         SET PRINTER PORT ADDRESS
          MOVE.B #$15,DCOMMB(A0)   CRB: MODE=1, ENABLE RX&TX
          MOVE.B #$5,DCOMMB(A0)    CRB: ENABLE RX & TX
          MOVE.B #$13,DMODEB(A0)   MRB1: NO RTS, NO PARITY, 8 BITS
          MOVE.B #$27,DMODEB(A0)   MRB2: RTS,1 STOP BIT
          MOVE.B #$BB,DCLOCB(A0)   CSRB: 9600 BAUD
          MOVE.B #$80,DAUXB(A0)    AUX CONTROL REG = SET 1
          MOVE.B DDATAB(A0),D0
          MOVE.B DDATAB(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAB(A0),D0
* INITIALIZE SERIAL PORT A, FIND CORRECT BAUD RATE
BAUDAG    CLR.W D0
BAUWAI    SUB.W #1,D0              WAIT 1/2 SECOND OR SO
          BNE.S BAUWAI
          MOVE.B #$20,DCOMMA(A0)   RESET RECEIVER
          MOVE.B #$15,DCOMMA(A0)   CRA: MODE=1, ENABLE RX&TX
          MOVE.B #$5,DCOMMA(A0)    CRA: ENABLE RX & TX
          MOVE.B #$13,DMODEA(A0)   MRA1: NO RTS, NO PARITY, 8 BITS
          MOVE.B #$07,DMODEA(A0)   MRA2: NO RTS,1 STOP BIT
          MOVE.B #$88,DCLOCA(A0)   SET CSRA TO 2400 BAUD
          MOVE.B #$80,DAUXA(A0)    AUX CONTROL REG = SET 2 >>C<<
          MOVE.B DDATAA(A0),D0
          MOVE.B DDATAA(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAA(A0),D0
BAUDWA    BTST.B #0,DSTATA(A0)     CHECK RX RDY BIT
          BEQ.S BAUDWA             WAIT FOR A CHARACTER
          MOVE.B DDATAA(A0),D0     GET CHARACTER
          AND.B #$7F,D0            REMOVE PARITY BIT
          LEA BAUTAB(PC),A1        POINT TO BAUD TABLE
BAULOO    MOVE.W (A1)+,D1          GET NEXT ENTRY
          CMP.B D0,D1              DOES IT MATCH?
          BEQ.S BAUDOK             YES, GOT RIGHT BAUD RATE
          CMP.B #$FF,D1            ARE WE AT END OF TABLE?
          BEQ.S BAUDAG             YES, TRY IT AGAIN
          BRA.S BAULOO             NO, CHECK NEXT BAUD RATE

BAUTAB    DC.W $BB7F               9600 BAUD
          DC.W $BB7E               ALSO 9600 BAUD
          DC.W $880D               2400 BAUD
          DC.W $6666               1200 BAUD
          DC.W $5578               600 BAUD
          DC.W $4400               300 BAUD
          DC.W $00FF               END OF TABLE

BAUDOK    LSR.W #8,D1              GET BAUD RATE CODE
          MOVE.B D1,DCLOCA(A0)     GIVE IT TO DUART
          MOVE.B DDATAA(A0),D0
          MOVE.B DDATAA(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAA(A0),D0
          CMP.B #$BB,D1            WAS IT 9600 BAUD? >>C<<
          BNE.S BAURTS             NO, SO LEAVE AS IS >>C<<
* IF 9600 BAUD, IT COULD ALSO BE 19200; CHECK >>C<<
BAUDW2    BTST.B #0,DSTATA(A0)     CHECK RX RDY BIT >>C<<
          BEQ.S BAUDW2             WAIT FOR ANOTHER CHARACTER >>C<<
          MOVE.B DDATAA(A0),D0     GET CHARACTER >>C<<
          AND.B #$7F,D0            REMOVE PARITY BIT >>C<<
          CMP.B #$0D,D0            CR? >>C<<
          BEQ.S BAURTS             YES, USE 9600 >>C<<
          MOVE.B #$CC,DCLOCA(A0)   NO, SWITCH TO 19200 >>C<<
          MOVE.B DDATAA(A0),D0     >>C<<
          MOVE.B DDATAA(A0),D0     EMPTY RCVR BUFFER 3 TIMES >>C<<
          MOVE.B DDATAA(A0),D0     >>C<<
BAURTS    RTS                      >>C<<

***********************************************************
* INCHEK - CHECK FOR CHAR IN SERIAL PORT
***********************************************************

INCHE0    MOVEM.L A6,-(A7)
          MOVE.L PORADM,A6         POINT TO PORT
          BTST #0,DSTATA(A6)       CHECK RDRF FLAG
          MOVEM.L (A7)+,A6
          RTS                      AND RETURN WITH IT

***********************************************************
* GET 8-BIT CHARACTER FROM SERIAL PORT
***********************************************************

INCH80    MOVEM.L A6,-(A7)
          MOVE.L PORADM,A6         POINT TO PORT
INCH8A    BTST #0,DSTATA(A6)       CHECK STATUS OF PORT
          BEQ.S INCH8A             WAIT IF NOTHING
          MOVE.B DDATAA(A6),D5     ELSE GET CHARACTER
          MOVEM.L (A7)+,A6
          RTS

***********************************************************
* OUTPUT ON PRINTER (PORT P)
***********************************************************

OUTPCH    MOVEM.L A6,-(A7)
          MOVE.L PORADP,A6
* LINE DELETED HERE BY >>D<<
          BRA.S OUTCHE

***********************************************************
* OUTPUT ON CONTROL PORT (MAIN CONSOLE)
***********************************************************

OUTMCH    MOVEM.L A6,-(A7)
          MOVE.L PORADM,A6         POINT TO MAIN PORT
OUTCHE    BTST #2,DSTATA(A6)       CHECK TDRE
          BEQ.S OUTCHE             WAIT UNTIL READY
          MOVE.B D4,DDATAA(A6)     PRINT IT
          MOVEM.L (A7)+,A6
          RTS


*******************************************************
* 'FD - BOOT SK*DOS FROM FLOPPY DISK
*******************************************************

DLATCH    EQU $E0061
* EXPLANATION OF DLATCH OPERATION:
*           BITS 0 & 1 SELECT DRIVE 0 OR 1, RESP
*           BITS 2 - 4 - NOT USED
*           BIT 5 SELECTS DENSITY (0 = DD)
*           BIT 6 - SELECTS SIDE (O = SIDE A)
*           BIT 7 - NOT USED
*
COMREG    EQU $E0081
STAREG    EQU COMREG
TRKREG    EQU $E0083
SECREG    EQU $E0085
DATREG    EQU $E0087

FLBOOO    MOVE.B #4,D3             RETRY COUNTER
          MOVE.B #$21,D4           DD, DRIVE 0
PRLOOP    MOVE.B D4,DLATCH         SELECT DRIVE, MOTOR, DENSITY
          EOR.B #$20,D4            CHANGE DENSITY FOR NEXT TRY
          BSR.L WAIT
* FOLLOWING LINE IS 01 FOR 1772, 03 FOR OTHER WESTERN DIGITAL FDC'S
          MOVE.B #$01,COMREG       RESTORE, LOAD, SLOW STEP >>A<<
          BSR.L WNBUSY             WAIT UNTIL NOT BUSY
          MOVE.B #1,SECREG         SECTOR 1
          BSR.L WAIT

          MOVE.L #$0800,A5         WHERE TO LOAD THE SECTOR
* ASSUME INTERRUPTS ARE ALREADY OFF
          OR.W #$0700,SR
          LEA STAREG,A6            POINT A6 TO STATUS REG
          LEA DATREG,A4            POINT A4 TO DATA REG
          MOVE.B #$84,COMREG       READ COMMAND
          BSR WAIT                 WAIT FOR FDC TO SETTLE
          BRA.S RDLOOP             REPEAT UNTIL DONE

RDBYTE    MOVE.B (A4),(A5)+        GET DATA BYTE
RDLOOP    MOVE.B (A6),D6           CHECK STATUS
          BTST.B #1,D6             DRQ?
          BNE.S RDBYTE             YES
          BTST.B #0,D6             BUSY?
          BNE.S RDLOOP             YES, SO WAIT

          AND.B #$1C,D6            NR, RNF, CRC, OR LOST DATA?
          BEQ.S FDEXIT             EXIT NORMALLY IF NO ERROR
          SUB.B #1,D3              DECR RETRY COUNTER
          BNE.S PRLOOP             ELSE TRY AGAIN WHEN NOT DONE
          LEA EBDMSG,A4
          JSR PSTRNG               THEN PRINT ERROR MESSAGE
          JMP WARMST               AND QUIT
FDEXIT    JMP $0800                GO TO SUPER-BOOT
EBDMSG    FCC 'ERROR BOOTING DOS.',4

* WAIT - WAIT ROUTINE TO WAIT A WHILE

WAIT      BSR.S WAIT4
          NOP
WAIT4     BSR.S WAIT2
          NOP
WAIT2     BSR.S WAIT1
          NOP
WAIT1     RTS                      RTS

* WNBUSY

WNBUSY    BSR.S WAIT               WAIT FOR COMMAND TO SETTLE
          MOVE.B STAREG,D6         GET STATUS
          BTST.B #0,D6             CHECK BUSY FLAG
          BNE.S WNBUSY             WAIT IF STILL BUSY
          RTS                      ELSE RETURN WITH B=STATUS

********************************************************
* 'WD' COMMAND - BOOT SK*DOS FROM HARD DISK
********************************************************

* SK*DOS EQUATES

DRUSED    EQU $113C                DRIVE USED TABLE

WDREAD    EQU $E0020               READ DATA REGISTER
WDWRIT    EQU WDREAD               WRITE DATA REGISTER
WDERRO    EQU $E0024               ERROR REGISTER
WDWPRE    EQU WDERRO               WRITE PRECOMP REGISTER
WDSCNT    EQU $E0028               SECTOR COUNT REGISTER
WDSNUM    EQU $E002C               SECTOR NUMBER
WDCYLO    EQU $E0030               CYLINDER NUMBER - LOW ORDER BYTE
WDCYHI    EQU $E0034               CYLINDER NUMBER - HIGH ORDER BYTE
WDSDHR    EQU $E0038               SIZE,DRIVE,HEAD REGISTER
WDSTAT    EQU $E003C               STATUS REG - READ ONLY
WDCOMA    EQU WDSTAT               COMMAND REG - WRITE ONLY

* FIRST, TEST WHETHER THERE IS A WD1002

HDBOOT    MOVE.B #$A5,WDSNUM       TRY STORING INTO WD1002
          MOVE.L WDSNUM,D5         READ BACK
          CMP.L #$A5A5A5A5,D5      CHECK IT
          BNE.L BERROR             NO WD1002 THERE
          MOVE.B #$5A,WDSNUM       THEN TRY THE COMPLEMENT
          MOVE.L WDSNUM,D5         READ BACK
          CMP.L #$5A5A5A5A,D5      CHECK IT
          BNE.L BERROR             NO WD1002 THERE

* INITIALIZE THE WINCHESTER

          MOVE.B #$88,WDSDHR       ECC,SEC=256,DRIVE 1,HEAD 0
          MOVE.B #32,WDWPRE        SET PRECOMP TO TRACK 128
          MOVE.B #$1F,WDCOMA       DO A SLOW RESTORE
          BSR.L CHBUSY             WAIT FOR WD1002 NOT BUSY
          BNE.L BERROR             EXIT IF ERROR

* READ TRACK 0 SECTOR 0 TO DETERMINE PARTITION 0 LAYOUT

          MOVE.B #0,WDSNUM         SECTOR 0
          MOVE.B #0,WDCYHI
          MOVE.B #0,WDCYLO         CYLINDER 0
          MOVE.B #1,WDSCNT         SECTOR COUNT = 1
          MOVE.B #$20,WDCOMA       SEND READ COMMAND
          BSR.L CHBUSY             WAIT FOR COMPLETION
          BNE.L BERROR             EXIT IF ERROR
          LEA OURWIN,A1            POINT TO OUR WINTAB
          MOVE.L WDREAD,(A1)+
          MOVE.L WDREAD,(A1)+      READ 14 BYTES OF CONFIG DATA
          MOVE.L WDREAD,(A1)+
          MOVE.W WDREAD,(A1)+
          MOVE.B WDSTAT,D7         GET WD STATUS BYTE
          BTST.B #0,D7             CHECK ERROR BIT
          BNE.L BERROR             EXIT IF ERROR

* NOW SEARCH DISK DIRECTORY FOR SK*DOS.SYS

          MOVE.L #$0005,D0         DIRECTORY START DISK ADDRESS
          LEA OURWIN,A1            POINT TO OUR WINTAB
DIREAD    LEA BUFFER,A0            DIRECTORY SECTOR BUFFER
          BSR.L HREAD              READ DIRECTORY SECTOR
          BNE.L BERROR
          LEA BUFFER,A0            BACK TO DIRECTORY BUFFER
          LEA 256(A0),A6           END OF BUFFER
          LEA 16(A0),A0            FIRST DIR ENTRY
DIRLOO    TST.B (A0)               CHECK FIRST BYTE OF ENTRY
          BMI.S NXTDIR             DELETED ENTRY
          BEQ.L BERROR             END OF DIRECTORY
          MOVE.L (A0),D7           FIRST FOUR LETTERS
          CMP.L #$534B2A44,D7      "SK*D" ?
          BNE.S NXTDIR             NO
          MOVE.L 4(A0),D7          NEXT FOUR LETTERS
          CMP.L #$4F530000,D7      "OS.." ?
          BNE.S NXTDIR
          MOVE.L 8(A0),D7          NEXT THREE
          AND.L #$FFFFFF00,D7      BLANK OUT LAST
          CMP.L #$53595300,D7      "SYS" ?
          BEQ.S GOTIT              GOT IT?

NXTDIR    ADD.L #24,A0             POINT TO NEXT ENTRY
          CMP.L A0,A6              AT END OF SECTOR?
          BNE.S DIRLOO             NO, CONTINUE

          MOVE.W BUFFER,D0         AT END, GET POINTER TO NEXT
          BEQ.L BERROR             SK*DOS.SYS NOT FOUND IF AT END
          BRA.S DIREAD             ELSE LOOK AT NEXT SCTR

* WE HAVE FOUND 'SK*DOS.SYS'

GOTIT     MOVE.B 13(A0),D0
          LSL.W #8,D0
          MOVE.B 14(A0),D0         GET STARTING DISK ADDRESS
          LEA BUFFER,A0            POINT BACK TO BUFFER
          MOVE.W D0,(A0)           PUT FIRST ADDRESS INTO IT

* NOW READ THE FILE INTO MEMORY WITHOUT AN OFFSET

          MOVE.L #0,A3             ERASE EXECUTION ADDRESS
          CLR.L D1                 DATA POINTER =0
GET2      BSR.L GETNEW             GET FLAG BYTE
          CMP.B #$02,D5            IS IT 02?
          BEQ.S GETD2O             2-BYTE ADDRESS DATA
          CMP.B #$03,D5            IS IT 03?
          BEQ.S GETD4O             4-BYTE ADDRESS DATA
          CMP.B #$16,D5            IS IT 16?
          BEQ.L GETT2O             2-BYTE TRANSFER
          CMP.B #$17,D5            IS IT 17?
          BEQ.L GETT4O             4-BYTE TRANSFER
          BRA.S GET2               ANYTHING ELSE JUST SKIP

GETD2O    BSR.L GETWRD             GET 2-BYTE LOAD ADDRESS
          MOVE.L D4,A2             PUT INTO A2
          BSR.L GETNEW             GET LENGTH
          MOVE.L D5,D2             SET UP AS COUNTER
          BRA.S GETLOO             THEN CONTINUE

GETD4O    BSR.L GETWRD             GET LEFT WORD OF LOAD ADDRESS
          SWAP D4
          MOVE.L D4,A2             MOVE INTO A2
          BSR.L GETWRD             GET RIGHT WORD OF LOAD ADDRESS
          ADD.L D4,A2              COMBINE TWO WORDS
          BSR.L GETWRD             GET LENGTH
          MOVE.L D4,D2             SET UP AS COUNTER

GETLOO    BSR.L GETNEW             ELSE GET ONE BYTE
          MOVE.B D5,(A2)+          STORE IN MEMORY
          SUB.W #01,D2             DECREMENT COUNTER
          BNE.S GETLOO
          BRA.L GET2               AT END, LOOK FOR NEXT FLAG

GETT4O    BSR.S GETWRD             GET LEFT WORD OF TRANSFER ADDRESS
          SWAP D4                  MOVE INTO LEFT HALF
          MOVE.L D4,A3             SAVE IN A3
          BSR.S GETWRD             GET RIGHT HALF OF ADDR
          ADD.L A3,D4              ADD BACK TOGETHER
          MOVE.L D4,A3             SAVE EXECUTION ADDRESS
          BRA.S GET2

GETT2O    BSR.S GETWRD             GET TRANSFER ADDRESS FROM FILE
          MOVE.L D4,A3             STORE EXECUTION ADDRESS
          BRA.L GET2               AND REPEAT

* GETWRD - GET TWO-BYTE WORD FROM FILE

GETWRD    BSR.S GETNEW             GET MSB BYTE
          MOVE.L D5,D4             SAVE IN D4
          LSL.W #8,D4              MOVE INTO SECOND BYTE
          BSR.S GETNEW             GET LSB
          ADD.W D5,D4              ADD THE TWO BYTES TOGETHER IN D4
GETEXI    RTS

* GETNEW - GET BYTE FROM FILE

GETNEW    TST.B D1                 CHECK POINTER TO DATA
          BEQ.S READIT             ZERO MEANS HAVE TO READ SCTR
GETNW1    CLR.L D5
          MOVE.B (A0,D1.W),D5      READ A BYTE
          ADD.B #1,D1              POINT TO NEXT
          RTS

* READIT - READ A NEW SECTOR FROM HARD DISK INTO BUFFER

READIT    LEA BUFFER,A0            POINT TO BUFFER
          MOVE.W (A0),D0           POINTER TO NEXT
          BEQ.S HDFINI             FINISHED IF 00 POINTER
          BSR.S HREAD              READ NEXT SECTOR
          MOVE.W #4,D1             POINT TO ITS FIRST BYTE
          BRA.S GETNW1             THEN CONTINUE AS ABOVE

* HDFINI - WHEN FINISHED READING, REASSIGN DRIVE NUMBERS,
* AND JUMP TO PROGRAM IF THERE IS A TRANSFER ADDRESS

HDFINI    MOVE.L A3,D7             TRANSFER ADDRESS, IF ANY
          BEQ.L BERROR             ERROR IF NONE
          MOVE.B #$20,DRUSED       HARD DISK BECOMES DRIVE 0
          MOVE.B #$10,DRUSED+1     FLOPPY DISK BECOMES DRIVE 1
          JMP.L (A3)               THEN JUMP TO SK*DOS

* HREAD - READ SECTOR INTO MEMORY. ENTER WITH D0=LOGICAL TR/SEC,
* AND A0 = ADDRESS OF BUFFER TO READ INTO

HREAD     BSR.S LPCONV             CONVERT LOG TO PHYS ADDRESS
          MOVE.B #1,WDSCNT         SECTOR COUNT = 1
          MOVE.B #$20,WDCOMA       SEND READ COMMAND
          BSR.S CHBUSY             WAIT FOR COMPLETION
          BEQ.S HREDOK             CONTINUE IF NO ERROR >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
HREDOK    MOVE.L A0,A5             POINT TO BUFFER >>A<<
          MOVE.W #63,D6            COUNTER = 256/4-1
HRDLOO    MOVE.L WDREAD,(A5)+      READ 4 BYTES
          DBRA D6,HRDLOO           REPEAT FOR 256 BYTES
          BSR.S CHBUSY             WAIT FOR COMPLETION
          BNE.L BERROR             IF ERROR
          RTS

* CHBUSY - WAIT IF BUSY, BUT ABORT IF IT TAKES TOO LONG

CHBUSY    MOVE.L #$100000,D6       TIMEOUT COUNTER
CHBUS1    SUB.L #1,D6              DROP TIMEOUT COUNT
          BEQ.L BERROR             SOMETHING WRONG?
          TST.B WDSTAT             CHECK WD1002 STATUS
          BMI.S CHBUS1             WAIT UNTIL NOT BUSY
          MOVE.B WDSTAT,D7         GET WD STATUS BYTE
          BTST.B #0,D7             CHECK ERROR BIT
          RTS

* LPCONV - CONVERT A LOGICAL TRACK AND SECTOR NUMBER (IN D0
* AS 0000TRSE) INTO PHYSICAL TRACK, HEAD, AND SECTOR NUMBERS AND
* PUT INTO WD REGS, USING INFO IN OURWIN ENTRY POINTED TO BY A1

LPCONV    MOVE.W D0,D6
          LSR.W #8,D6              LOGICAL TRACK
          CLR.L D7
          MOVE.B 11(A1),D7         LOG SECT/TRACK
          ADD.W #1,D7              NUMBER PER TRACK
          MULU D7,D6               SECT BEFORE THIS TRACK
          CLR.L D7
          MOVE.B D0,D7             LOG SECTOR
          ADD.W D7,D6              BLOCK NUMBER
          MOVE.W 4(A1),D7          SECT/CYL ON HARD DISK
          DIVU D7,D6               REMAINDER | TRACK NUMBER
          ADD.W 8(A1),D6           PLUS START OF PARTITION
          MOVE.B D6,WDCYLO
          LSR.L #8,D6
          MOVE.B D6,WDCYHI         CYLINDER NUMBER TO WD1002
          LSR.L #8,D6              REMAINDER IN RIGHT HALF
          CLR.L D7
          MOVE.B 2(A1),D7          SECTORS PER TRACK
          DIVU D7,D6               SECTOR | HEAD
          ADD.B #$88,D6            COMBINE WITH OTHER SDH BITS
          MOVE.B D6,WDSDHR         PUT INTO SDH REGISTER
          SWAP D6                  MOVE SECTOR RIGHT
          MOVE.B D6,WDSNUM         SECTOR NUMBER TO WD1002
          RTS

* BERROR - WHAT TO DO IN CASE OF ERROR

BERROR    LEA HBEMSG,A4
          JSR PSTRNG               THEN PRINT ERROR MESSAGE
          JMP WARMST               AND QUIT
HBEMSG    FCC 'HARD DISK BOOT ERROR.',4

********************************************************
* 'RD' COMMAND - RETURN TO SK*DOS
********************************************************

SKCOLD    EQU $1000                SK*DOS COLD-START
SKWARM    EQU $1006                SK*DOS WARM-START

DOSRET    MOVE.W SKCOLD,D0         CHECK IF DOS LOADED
          CMP.W #$4EF9,D0          IS IT A JUMP?
          BNE.L COMEND             IGNORE IF NOT
          JMP SKWARM               RETURN TO DOS IF OK

********************************************************

          END
