;
; Title:  Machine Language Manager
; Author: Andy Guevara
; 
; For the Bally Astrocade
; 
; Made ready to assemble by Adam Trionfo
; 
;         .03 - Jan. 3, 2004
;                  - Finished cleanup of code
;                  - First assemble with no errors
;                  - Matches EXACTLY with MLM cart
;         .02 - May  27, 2003
;                  - Cleaned up a bit - needs LOTS of work
;         .01 - Mar. 27, 2002
;                  - Scanned
;                  - Noticed it's not identical to cart
;
; Assemble using Zmac
;
; zmac -i -m -o mlmsourc.bin -x mlmsourc.lst mlmsourc.asm 
;
;
; ********************************************************
; *                                                      *
; *           BALLY ARCADE UTILITY PACKAGE               *
; *                      OR                              *
; *  "HOW TO GET STUFF IN AND OUT IN MACHINE LANGUAGE"   *
; *                                                      *
; * (C) 1981 ANDY GUEVARA                  JULY 29, 1981 *
; ********************************************************
;
;
;
SKYD    EQU    0013H
DISP    EQU    0D7H       ; RST 10
STRING  EQU    0DFH       ; RST 18
SYSSUK  EQU    0FFH
SYSTEM  EQU    0FFH
UPRAM   EQU    4F50H      ; BEGINNING OF U.P. RAM
                          ; ROOM FOR STACK:
;
UPSTK   EQU    4FACH      ; U.P. STACK-GROWS DOWNWARD
MODE    EQU    4FADH      ; MODE REGISTER
IOB     EQU    4FAEH      ; I/0 INFORMATION BYTE
KEYN    EQU    4FAFH      ; KEY INPUT NUMBER
LPINT   EQU    4FB0H      ; LIGHT PEN INTERRUPT VECTOR
SCINT   EQU    4FB2H      ; SCREEN INTERRUPT VECTOR
IN1     EQU    4FB4H      ; INPUT REGISTERS
IN2     EQU    4FB5H  
ADRG1   EQU    4FB6H      ; ADDRESS REGISTERS
ADRG2   EQU    4FB7H  
SCRN    EQU    4FB8H      ; SCREEN SIZE-BYTES
SCRLN   EQU    4FBAH      ; SCRATCH AT THIS LINE AND BELOW
HRZCB   EQU    4FBBH      ; HORIZONTAL COLOR BOUNDARY
LFLG    EQU    4FBCH      ; LIST FLAG
RFG     EQU    4FBDH      ; REGISTER FLAG
PWRUP   EQU    4FBEH      ; POWER UP SIGNATURE
PW2     EQU    4FC0H      ; 3RD BYTE
END_    EQU    4FC1H      ; END OF FILE MARKER
COORD   EQU    4FC3H      ; XY COORDS FOR SCREEN
                          ; D IS Y COORDINATE
POPT    EQU    4FC5H      ; PRINT OPTIONS BYTE
COLORS  EQU    4FC6H      ; COLOR 3
CD      EQU    4FC7H      ; COLOR 2
FCOL    EQU    4FC8H      ; FOREGROUND COLOR (1)
BCOL    EQU    4FC9H      ; BACKGROUND COLOR (0)
M4BA    EQU    4FCAH      ; ENTRY ADDRESS FOR MODE 4
;
        ORG    2000H
START   JP     INIT
        DB     44H,42H,32H ; * NOW MATCHES MLM CART
;        DEFS   3          ; EMPTY SPACE
         DEFB   23        ; BUP REVISION LEVEL 2.3
BPE     JP     BRKPT      ; BREAKPOINT ENTRY
DEP     JP     DISPLAY    ; DISPLAY ENTRY POINT
SEP     JP     STRDIS     ; STRING DISPLAY
INIT    DI                ; DISABLE INTERRUPTS
        LD     SP,UPSTK   ; RESET STACK
        LD     HL,(PWRUP) ; CHECK IF BEEN AWAKE
        LD     DE,0AA00H  ; SIGNATURE VALUE
        OR     A          ; CLEAR CARRY
        SBC    HL,DE
        JR     NZ,STSPC   ; BEEN ASLEEP, SET VALUES
; OK SO FAR
        LD      A,(PW2)   ; 3RD BYTE
        CP      0FAH
        JR      Z,CONT    ; JUMP IF OK
STSPC   DEFB    SYSSUK    ; ASLEEP, SET DEFAULT SPECS
        DEFB    00H       ; START INTERPRETER
        DEFB    1BH       ; DO FILL
        DEFW    MODE      ; SYSTEM RAM START
        DEFW    23H       ; HOW MANY
        DEFB    00H       ; WITH WHAT
        DEFB    17H       ; DO SETOUT
        DEFB    90 SHL 1  ; BLANK LINE 90 DECIM. AND BELOW
                          ; THIS ALLOWS 360 BYTES OF RAM
        DEFB    2CH       ; 44 DECIMAL--MOVE R/L BOUNDARY
                          ; TO FAR RIGHT
        DEFB   8H         ; INTERRUPT MODE 8
        DEFB   5FH        ; MOVE BYTES
        DEFW   COLORS     ; TO WHERE
        DEFW   04H        ; HOW MANY
        DEFW   COLIST     ; FROM WHERE
        DEFB   19H        ; COLSET--SET COLORS
        DEFW   COLORS     ; ADDR OF COLOR LIST
        DEFB   03H        ; EXIT INTERPRETER
        LD     HL,0E10H   ; DEFAULT VALUE OF SCREEN SIZE
        LD     (SCRN),HL
        LD     A,90       ; 90 DEC.
        LD     (SCRLN),A  ; VERT BLANK. LINE
        CALL   CLEAR      ; WIPE SCREEN CLEAN
        CALL   READY
CONT    DEFB   SYSSUK
        DEFB   15H        ; DO EMUSIC--STOP MUSIC
        CALL   ININT      ; SET UP INTERRUPTS
        LD     HL,0AA00H  ; WRITE POWER UP SIGNATURE
        LD     (PWRUP),HL
        LD     A,0FAH
        LD     (PW2),A
        LD     HL,SCRSP   ; SET UP CALL TO
        LD     (IN1),HL   ; SCREEN SPEC PROGRAM
        CALL   INAD       ; KEEPS LIST FROM RUNNING AWAY
        XOR    A          ; CLEAR FLAGS AND MODE
        LD     (IOB),A    ; CLEAR I/0 BYTE
        LD     (MODE),A
        LD     (POPT),A
        LD     (LFLG),A
        LD     (RFG),A
        CALL   CRLF
        DEFB   STRING
        DEFW   OKM        ; SYSTEM PROMPT
;
MAIN    LD     HL,MAIN    ; MAIN LOOP
        PUSH   HL         ; THIS CAUSES RETURNS FROM
                          ; MAIN ROUTINES TO RETURN HERE
        CALL   KEYGET     ; RETURNS WITH KEY N0. IN A
                          ; USED AS A
                          ; DISPLACEMENT IN JUMP TABLE
        DEFB   SYSSUK     ; INTERPRETER CALL'
        DEFB   5DH        ; INDEXB--BYTE TABLE LOOKUP
        DEFW   TTT-1      ; RETURNS WITH KEY TYPE IN
                          ; HI NIBBLE
                          ; TRANSLATION IN LOW NIBBLE
                          ; TYPE=0 MEANS NUMBER,
                          ; =1 MEANS COMMAND
; NOTE: THE -1 IS FOR THE ZERO ENTRY THAT DOESN'T EXIST
        AND    0FH        ; ISOLATE TRANSLATION
        LD     C,A        ; COPY DIGIT TO C
        XOR    (HL)       ; PICK OUT TYPE
        JP     Z,NUMBER   ; IF TYPE 0, SKIP AHEAD
        LD     A,(MODE)   ; IF NOT THEN MUST BE TYPE 1
                          ; FIND MODE
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW--WORD TABLE LOOKUP
        DEFW   MDTBL      ; MODE TABLE
        PUSH   DE
        RET               ; SNEAKY WAY TO JUMP TO COMMAND
;
; ******** TYPE-TRANSLATE TABLE ***************************
;
;
TTT     DEFB   0DH        ; 1  D
        DEFB   0EH        ; 2  E
        DEFB   0FH        ; 3  F
        DEFB   12H        ; 4 CALL
        DEFB   0AH        ; 5  A
        DEFB   0BH        ; 6  B
        DEFB   0CH        ; 7  C
        DEFB   15H        ; 8 REG (*TAPE DISPLAY)
        DEFB   07H        ; 9  7
        DEFB   08H        ; 10  8
        DEFB   09H        ; 11  9
        DEFB   13H        ; 12 LIST (*PRINT)
        DEFB   04H        ; 13  4
        DEFB   05H        ; 14  5
        DEFB   06H        ; 15  6
        DEFB   17H        ; 16 INS (*DELETE)
        DEFB   01H        ; 17  1
        DEFB   02H        ; 18  2
        DEFB   03H        ; 19  3
        DEFB   11H        ; 20 READ (:*TAPE INPUT)
        DEFB   16H        ; 21  *
        DEFB   00H        ; 22  0
        DEFB   14H        ; 23 WRITE (*TAPE OUTPUT)
        DEFB   10H        ; 24 ADDR
;
;
; ********* MODE JUMP TABLE ****************
MDTBL   DEFW   MODE0      ; NORMAL COMMANDS
        DEFW   MODE1      ; REGISTER COMMANDS
        DEFW   MODE2      ; STAR (2ND SET) COMMANDS
        DEFW   MODE3      ; SCREEN SPECIFICATIONS
        DEFW   MODE4      ; EXTERNAL (USER) COMMANDS
;
;
; *********** JUMP TABLE FOR MODE 0 **********************
;
;              ROUTINE KEY VAL.
M0JT    DEFW   ADDR       ; 0, ADDRESS
        DEFW   READ_      ; 1, READ AND INCREMENT
        DEFW   ACALL      ; 2, CALL
        DEFW   LIST_      ; 3, LIST
        DEFW   WRITE      ; 4, WRITE TO MEMORY
        DEFW   REG        ; 5, LOAD REGISTERS
        DEFW   STAR0      ; 6, SET OPTIONS FLAG
        DEFW   INS        ; 7, INSERT IN MEMORY
;
; ************ MODE 1 JUMP TABLE **************************
;
;               ROUTINE KEY VAL.
M1JT    DEFW   M1RT       ; 0, IGNORE 'ADDR' KEYPUSH
        DEFW   RPLUS      ; 1, SKIP TO NEXT REGISTER
        DEFW   M1RT       ; 2, IGNORE 'CALL'
        DEFW   RLIST      ; 3, LIST REGISTERS
        DEFW   RWRT       ; 4, CHANGE REGISTER CONTENTS
        DEFW   M1RT       ; 5, IGNORE 2ND 'REG'
        DEFW   M1RT       ; 6, IGNORE '*'
        DEFW   M1RT       ; 7, IGNORE 'INS'
;
; ************ MODE 2 JUMP TABLE ****************
;
M2JT    DEFW   ADDR       ; 0
        DEFW   TAPIN      ; 1
        DEFW   ACALL      ; 2
        DEFW   PRINT      ; 3
        DEFW   TAPOUT     ; 4
        DEFW   TADIS      ; 5
        DEFW   STAR2      ; 6
        DEFW   DEL        ; 7
;
;
;
; ************ MODE 3 JUMP TABLE *****************
M3JT    DEFW   M30
        DEFW   M31
        DEFW   M32
        DEFW   M33
;
;  NUMBER INPUT
;
NUMBER   LD    HL,IN1     ; SET UP IN1
         LD    A,C        ; DIGIT IN LO HALF OF C
         RLD
; RLD: A 4-BIT SHIFT AS FOLLOWS--
; LOW A -> LOW IN1, LOW IN1 -> HI IN1, HI IN1 -> LOW A
; THE EFFECT IS TO SHIFT INDIVIDUAL HEX DIGITS INTO IN1.
; ONLY THE LAST 4 ARE REMEMBERED IN IN1 & IN2.
;
        INC    HL         ; BINK POINTER (TO IN2)
        RLD               ; DO IT AGAIN
        LD     A,C        ; RELOAD A WITH DIGIT
        CALL   NUMDIS     ; DISPLAY IT
        RET               ; AND GO HOME
;
;
MODE0   LD     A,C        ; MODE 0, GET DISPLACEMENT
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW--WORD TABLE LOOKUP
        DEFW   M0JT       ; JUMP TABLE ADDRESS
        PUSH   DE
        RET               ; JUMP TO COMMAND
;
MODE1   LD     A,C        ; PUT DISPLACEMENT IN A
        DEFB   SYSSUK     ; REG OPERATIONS
        DEFB   5BH        ; INDEXW--WORD TABLE
        DEFW   M1JT       ; JUMP TABLE ADDRESS
        PUSH   DE         ; JUMP TO PROCESS
M1RT    RET 
;
;
; ADDRESS ROUTINE
;
ADDR    CALL   INAD       ; MOVE DATA FROM INPUT TO ADDR REG
        LD     A,':'      ; COLON TO A
        DEFB   DISP
        XOR    A          ; CLEAR LIST FLAG
        LD     (LFLG),A   
        RET               ; AND GO HOME
;
INAD    LD     DE,ADRG1   ; MOVE ADDRESS TO ADRG1
        LD     HL,IN1     ; FROM INPUT REGISTER 1
        LDI               ; SINGLE INSTRUCTION MOVE
        LDI               ; BETWEEN MEMORY LOCATIONS
                          ; IT'S DONE TWICE BECAUSE TWO BYTES
                          ; OF INFO ARE BEING MOVED
        RET
;
READ_   LD     HL,(ADRG1) ; LOAD ADDRESS
        LD     A,(HL)     ; LOAD CONTENTS TO A
        INC    HL         ; INCREMENT CONTENTS
        LD     (ADRG1),HL ; STORE BACK
        CALL   RGDIS      ; DISPLAY WHAT'S IN A
        CALL   SPACE_
        RET               
;
; WRITE TO MEMORY
;
WRITE   LD     HL,(ADRG1)  ; PICK UP ADDRESS
        LD     A,(IN1)    ; PICK UP INPUT BYTE
        LD     (HL),A      ; STORE IT
        INC    HL          ; BINK ADDRESS
        LD     (ADRG1),HL  ; STORE IT PACK
        CALL   SPACE_      ; OUTPUT A SPACE
        RET                ; GO HOME
;
; INSERT INTO MEMORY
;
; THIS ROUTINE MAKES USE OF AN END OF FILE MARKER (END_)
; THAT SHOULD POINT TO THE LAST BYTE IN A PROGRAM +1.
; THE ROUTINE TESTS FOR ATTEMPTS TO WRITE INTO THE
; STACK, AND MAKES ALLOWANCES FOR ADDED MEMORY.
; IF 'END_' IS LESS THAN THE PRESENT ADDRESS REGISTER
; CONTENTS, THE ROUTINE WILL UPDATE IT TO (ADRG1)+1.
;
INS     LD     HL, (END_) ; GET ADDRESS
        LD     DE,UPRAM   ; TEST IF PUSHING SYSTEM RAM
        OR     A          ; CLEAR CARRY FLAG FOR SBC
        SBC    HL,DE
        JR     C,INS2     ; ADDRESS IS LESS THAN UPRAM
        JR     NZ,INS1    ; ADDRESS IS GREATER
        CALL   RED        ; IF THE SAME ISSUE WARNING
        DEFB   STRING
        DEFW   WAM
        CALL   NORM       ; BACK TO NORMAL PRINT
        JR     INS2       ; AND GO ON
INS1    LD     DE,4FFFH   ; SEE IF INTO ADDED MEMORY
        LD     HL,(ADRG1)
        SBC    HL,DE
        JR     NC,INS2    ; OK IF POSITIVE
        CALL   ERR        ; OTHERWISE OOPS
        RET
;
INS2    LD     HL, (END_) ; GET THE END OF FILE
        LD     DE,(ADRG1) ; SEE IF END>ADRG1
        OR     A          ; CLEAR CARRY
        SBC    HL,DE      ; (HL)-(DE)
        LD     B,H
        LD     C,L        ; MOVE RESULT TO BC (COUNTER)
        JR     NC,INS3    ; ALL SET
        EX     DE,HL      ; HL=(ADRG1)
        INC    HL         ; OTHERWISE END=ADRG+1
        LD     (END_),HL
        LD     BC,01H    ; SET COUNT TO 1
INS3    LD     DE,(END_)
        PUSH   DE
        POP    HL
        DEC    HL         ; HL=END-1
        LDDR              ; COPY FROM (HL) TO (DE),
                          ; (BC) TIMES
                          ; AND DECREMENT EACH TIME.
        CALL   WRITE      ; STUFF THE INFO
        LD     HL,END_    ; INC. END
        INC    (HL)
        RET               ; AND GO HOME
;
;
; EXECUTE A PROGRAM
; NOTE: CALL AND TAPE INPUT ARE INCOMPATIBLE FOR USE
; AT THE SAME TIME BECAUSE BOTH USE ALTERNATE REGISTER
; SET.
;
ACALL   LD     HL,CART    ; SET UP RETURN PROCESS
        PUSH   HL         ; ON STACK
        LD     HL,(IN1)   ; GET ADDRESS OF PROGRAM
        PUSH   HL
        EX     AF,AF'     ; EXCHANGE 'A' REGISTER
                          ; FOR ITS ALTERNATE 'A' REGISTER
        EXX               ; EXCHANGE THE REST OF
                          ; THE BEGS FOR THEIR ALTERNATES
        RET               ; POP THE ADDRESS OFF THE STACK
                          ; AND JUMP TO THE PROGRAM
;
;
CART    EX     AF,AF'     ; CALL RETURN PROCESS
        EXX               ; GET BACK ORIG. SET
        RET               ; ALL DONE, GO HOME
;
; SET UP FOR MODE
;
STAR0   LD    A,02H
        LD    (MODE),A    ; SET MODE 2
        CALL  RED
        LD    A,'*'
        DEFB  DISP        ; TELL OPERATOR
        CALL  NORM
        RET
;
;
; LIST ROUTINE
;
; LFLAG INDICATES BEING IN THE MIDDLE OF SUCCESSIVE SINGLE
; LIST OPERATIONS. IT'S CLEARED BY THE ADDRESS KEY.
;
LIST_  LD      A,(LFLG)   ; TEST THE FLAG
       AND     A
       JR      NZ,OUTLN   ; IF SET, DO A LINE AND GO HOME
;
       LD      A,0DH      ; OTHERWISE END THIS LINE
       DEFB    DISP
       LD      DE,(IN1)   ; CHECK IF END ADDR WAS INPUT
       LD      HL,(ADRG1)
       SBC     HL,DE
       JR      Z,OUTLN    ; IF SAME, DO A LINE, AND GO HOME
;
; MULTI-LINE LIST
;
MLIST_  CALL   OUTLN      ; EA WAS INPUT, DO A LINE AND
                          ; COME BACK.
;
        LD     HL,(IN1)   ; ENDING ADDRESS
        LD     DE,(ADRG1) ; NEW BEGINNING ADDRESS
        SBC    HL,DE      ; SUBTRACT LEA FROM EA
        JR     NC,MLIST_  ; IF POS, DO ANOTHER LINE
        RET               ; ELSE, GO BACK
;
; OUTPUT A LINE
;
OUTLN   LD     A,0FFH     ; SET FLAG
        LD     (LFLG),A
        LD     HL,(ADRG1) ; PICK: UP BEG. ADDR.
        CALL   HLIST      ; DISPLAY 1ST BYTE ADDRESS
        LD     A,':'
        DEFB   DISP
        CALL   SPACE_
OL1     CALL   READ_      ; GET AND DISPLAY DATA
        LD     A,L        ; CHECK FOR END OF LINE
        AND    07H        ; EDIT MASK
                          ; IF 00 OR 08H,
                          ; THE LAST 3 BITS ARE ZERO
        JR     NZ,OL1     ; IF NOT, GO BACK
; END OF LINE
        LD     A,(IOB)    ; CHECK IF TAPE OUT
        BIT    0,A        ; TURNED ON
        JR     Z,LASC     ; IF NOT, DO ASCII PART
        JR     LA3        ; AND EXIT
;
; LIST ASCII INTERPRETATION
;
LASC    LD     BC,08H     ; BACK UP POINTER 8 BYTES
        SBC    HL,BC
        LD     B,C        ; B=8 AS A COUNTER
LAI     LD     A,(HL)     ; DISPLAY ASCII INTERPRETATION
        CP     0DH        ; DON'T DISPLAY A CR
        JR     NZ,LA2
        LD     A,'.'      ; DO A DOT INSTEAD
LA2     DEFB   DISP
        INC    HL         ; INC. POINTER
        DJNZ   LAI        ; DECR. COUNT & LOOP
LA3     LD     A,0DH      ; CARRIAGE RETURN
        DEFB   DISP
        RET               ; GO HOME
;
; LOAD REGISTERS
;
REG     LD     A,01H
        LD     (MODE),A   ; SET MODE TO 1
        DEFB   STRING
        DEFW   AFM        ; PUT OUT MESSAGE
        XOR    A
        LD     (RFG),A    ; TABLE INITIALIZATION
        RET
;
;
; ************ REGISTER TABLE ********
;              ADDR        RFG
RGTBL   DEFW   AFG        ; 0
        DEFW   BCG        ; 1
        DEFW   DEG        ; 2
        DEFW   HLG        ; 3
;
; RFG OFFSET DETERMINES WHICH REGS TO PULL
;
; REGISTER WRITE ROUTINE
;
RWRT    LD     A,(RFG)
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW--WORD TABLE LOOKUP
        DEFW   RGTBL      ; GET JUMP ADDRESS
        PUSH   DE         ; SET UP JUMP
        RET               ; POP, JUMP
AFG     LD     A,(IN1)    ; LOAD NEW VALUE
        EX     AF,AF'     ; PUT IN ALTERNATE A
        CALL   RPLUS      ; OUTPUT DESIGNATOR AND UPDATE RP?
        RET
BCG     LD     BC,(IN1)   ; GET NEW VALUES
        PUSH   BC
        EXX               ; EXCHANGE REGISTER S'E'TS
        POP    BC         ; PUT IN NEW VALUES
        EXX               ; SWAP BACK
        CALL   RPLUS
        RET
DEG     LD     DE,(IN1)
        PUSH   DE
        EXX
        POP    DE
        EXX
        CALL   RPLUS
        RET
HLG     LD     HL,(IN1)
        PUSH   HL
        EXX
        POP    HL
        EXX
        XOR    A          ; CLEAR A
        LD     (RFG),A    ; CLEAR FLAG
        JR     RLIST      ; LIST THE REG SET
;
RPLUS   LD     A , (RFG)
        CP     03H        ; DONE YET?
        JR     Z, RP1     ; SKIP AHEAD IF SO
        INC    A
        LD     (RFG),A
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW, GET MESSAGE ADDR
        DEFW   RMTBL      ; REGISTER MSG TABLE
        CALL   STR1       ; PUT OUT MESSAGE
        RET
RP1     XOR    A
        LD     (RFG),A     ; CLEAR FLAG
        JP     MOD0        ; GO HOME
;
;
RMTBL   DEFW   AFM        ; 0
        DEFW   BCM        ; 1
        DEFW   DEM        ; 2
        DEFW   HLM        ; 3
;
; OUTPUT REGISTER CONTENTS
;
RLIST   XOR    A
        LD     (RFG),A    ; CLF FLAG
        CALL   CRLF
        DEFB   STRING
        DEFW   AFM        ; OUTPUT DESIGNATOR
        EX     AF,AF'     ; GET REG CONTENTS
        PUSH   AF
        EX     AF,AF'
        POP    AF
        CALL   RGDIS
        CALL   RPLUS      ; DESIGNATOR & RFG UPDATE
        EXX               ; ALTERNATE SET
        PUSH   BC         ; SAVE REGISTER
        CALL   SWDIS      ; SWAP AND DISPLAY
        PUSH   DE
        CALL   SWDIS
        PUSH   HL
        CALL   SWDIS
        EXX               ; BACK TO NORMAL SET
        DEFB   STRING
        DEFW   ADM
        LD     HL,(ADRG1)
        CALL   HLIST      ; DISPLAY ADDRESS REGISTER
        CALL   CRLF
        JP     MOD0
;
; SWAP AND DISPLAY A REGISTER
;
SWDIS   EXX               ; NORMAL SET
        POP    DE
        POP    HL         ; GET CONTENTS
        PUSH   DE         ; PUT BACK RETURN ADDR
        CALL   HLIST      ; SHOW CONTENTS
        CALL   RPLUS      ; DESIG. AND RFG UPDATE
        EXX               ; ALTERNATE SET
        RET
;
; CLEAN UP AND RESET MODE
MOD0    XOR    A          ; CLEAR A TO ZERO
        LD     (MODE),A   ; SET MODE TO 0
        LD     (LFLG),A   ; CLEAR LIST FLAG
        LD     (POPT),A   ; CLEAR PRINT OPTIONS
        RET               ; GO HOME
;
; ************ MODE 2 OPERATIONS ***********
;
MODE2
        LD     A,C        ; GET DISPLACEMENT
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW
        DEFW   M2JT       ; JUMP TABLE
        PUSH   DE
        RET               ; POP, JUMP
;
;
TAPIN
        DI                ; INITIALIZE INTERRUPTS
        EXX
        LD     B,0FCH     ; SET COUNT
        EXX
        LD     A,18H      ; INT. ENABLE AND MODE
        OUT   (0EH),A
        EI
        CALL   CRLF
        JP     MOD0       ; CLEAN UP AND GO HOME
;
TADIS
        CALL   TAPIN      ; INIT INTERRUPTS
        LD     HL,IOB     ; SET TAPE DISPLAY BIT
        SET    3,(HL)
        JP     MOD0
;
;
; WRITE TO TAPE
;
TAPOUT
        LD     HL,IOB     ; GET I/0 INFO
        BIT    0,(HL)     ; TAPE OUT SET?
        JR     NZ,TO1     ; YES, CLEAR IT
        SET    0,(HL)     ; NO, SET I T
        RES    1,(HL)     ; CLEAR PRINT BIT
        CALL   RED
        JR     TO2
TO1     RES    0,(HL)
        CALL   GREEN
TO2     LD     A,'T'
        DEFB   DISP
        JP     MOD0
;
;
PRINT
        LD     HL,IOB     ; GET I/O BYTE
        BIT    1,(HL)     ; PRINT EDIT CLEAR?
        JR     Z,PR1      ; YES, SET IT
        RES    1,(HL)     ; NO., CLEAR IT
        CALL   GREEN
        JR     PR2
PR1     CALL   RED
        SET    1,(HL)     ; SET PRINT BIT
        RES    0,(HL)     ; CLEAR TAPE BIT
PR2     LD     A,'P'
        DEFB   DISP
        JP     MOD0       ; GO HOME
;
;
STAR2
        LD     A,08H      ; DISABLE TAPE INPUT
        OUT    (0EH),A
        LD     HL,IOB     ; GET I/0 INFO
        RES    3,(HL)     ; CLEAR TAPE DISPLAY MODE
        CALL   GREEN
        LD     A,'*'
        DEFB   DISP
        JP     MOD0
;
;
; DELETE
;
DEL
        OR     A          ; FIX CARRY FLAG
        LD     HL,(END_)
        LD     DE,(ADRG1)
        SBC    HL,DE      ; GET NUMBER T'7 MOVE
        LD     B,H
        LD     C,L        ; COUNT TO PC
        LD     H,D
        LD     L,E
        INC    HL         ; (ADRG1) +1 TO HL
        LDIR              ; COPY FROM (Hl) TO (DE),
                          ; (BC) TIMES
        LD     A,'<'      ; A MARKER
        CALL   RED
        DEFB   DISP
        LD     HL,END_    ; UPDATE END
        DEC   (HL)
        JP     MOD0       ; GO HOME
; ******** MODE 4 OPERATIONS ************
;
; MODE 4 IS AVAILABLE FOR REDEFINING THE KEYPAD FOR
; OTHER USES. USER MUST ENTER THE ADDRESS OF HIS
; KEYPAD HANDLING ROUTINE IN M4BA (ADDRESS 4FC8),
; LOWER HALF FIRST. SETTING THE MODE TO 4
; IN THE STARTUP ROUTINE WILL ROUTE CONTROL IN THIS
; DIRECTION.
;
MODE4
        LD     HL,(M4BA)  ; GET ENTRY ADDRESS
        JP     (HL)       ; JUMP TO IT
;
;
; ******* DISPLAY CONTROL ROUTINES *******
;
CLEAR
        LD     BC,(SCRN)  ; SIZE OF SCREEN
        LD     DE,4000H   ; START OF SCREEN
        LD     A,0H       ; DATA TO FILL WITH
        DEFB   SYSTEM
        DEFB   1AH        ; DO NT FILL--CLEAR SCREEN
        LD     HL,00H
        LD     (COORD),HL ; SET COORDINATES TO 0,0
        RET
;
; DISPLAY IS THE GENERAL DISPLAY ROUTINE FOR THE
; SYSTEM. IT TAKES CARE OF THE SCREEN, TAPE, AND PRINTER
; PORTS. PRINT DIFFERS FROM TAPE ONLY IN THAT
; NONPRINTABLES ARC FILTERED OUT AND LINE FEEDS
; ARE INSERTED.
;
DISPLAY
        PUSH   HL
        PUSH   DE
        PUSH   BC
        PUSH   AF
        LD     HL,IOB     ; TEST FOR TAPE OR PRINT OUT
        BIT    0,(HL)     ; TAPE OUT BIT
        CALL   NZ,TWRT    ; DO IT
; SIMPLE DISPLAY
        POP    AF         ; RESTORE CHARACTER
        PUSH   AF         ; PUT IT BACK
        CP     0DH        ; CHECK IF CARR. RETURN
        JR     NZ,D1      ; IF NOT, GO AHEAD
        BIT    1,(HL)     ; PRINT ON?
        CALL   NZ,TWRT    ; YES, SEND CR TO PRINTER
D0      CALL   CRLF       ; DO IT ON SCREEN
        JR     DRET
D1      CP     20H        ; CHECK IF PRINTABLE
        JR     C,DOT      ; JUMP IF MINUS
        CP     5BH        ; UPPER LIMIT
        JR     C,OK       ; JUMP IF NEG.
DOT     LD     A,'.'      ; DO A DOT IF NOT PRINTABLE
OK      PUSH   AF         ; SAVE IT
        BIT    1,(HL)     ; PRINT ON?
        CALL   NZ,TWRT    ; YEP, DO IT
        LD     DE,(COORD) ; GET X,Y COORDINATES
        LD     A,(POPT)   ; PICK UP OPTIONS, IF ANY
        LD     C,A        ; PUT IN C
        AND    A
        JR     NZ,OK1     ; IF NONZERO, USE IT
        LD     C,04H      ; OTHERWISE STANDARD PRINT
OK1     POP    AF         ; GET CHAR BACK
        XOR    80H        ; ALTERNATE FONT INDICATOR
        LD     IX,SMLFNT  ; SMALL CHAR. FONT DESCRIPTOR
        DEFB   SYSTEM
        DEFB   32H        ; CHRDIS--OUTPUT CHARACTER ROUTINE
                          ; RETURNS WITH UPDATED X,Y COORDS
                          ; IN DE, D=Y, E=X
        LD     A,9BH      ; TEST FOR END OF LINE
        CP     E
        CALL   C,CLF      ; IF SO,SET UP NEXT LINE
        CALL   CON        ; PAINT CURSOR
DRET    POP    AF         ; AND GO HOME
        POP    BC
        POP    DE
        POP    HL
        RET
;
CON     LD     BC,0503H   ; PAINT 3X5 CURSOR
        LD     A,55H      ; BINARY 01010101 COLOR MASK
                          ; (COLOR #1)
        LD     (COORD),DE ; STORE COORDS BACK
        DEFB   SYSTEM
        DEFB   1CH        ; RECTAN--PAINT RECTANGLE
        RET
;
; NOTE: STRING CLOBBERS ALMOST EVERYTHING, USE WITH CARE
;
STRDIS
        EX     (SP),HL    ; GET ADDRESS FROM CALLING ROUTINE
        LD     E,(HL)
        INC    HL
        LD     D,(HL)
        INC    HL
        EX     (SP),HL    ; FIX THE STACK
STR1    LD     A,(DE)     ; PICK UP CHARACTER
        CP     00H        ; IF NULL, END
        RET    Z
        DEFB   DISP       ; DISPLAY CHARACTER
        INC    DE         ; INCREMENT ADDRESS
        JR     STR1       ; DO ANOTHER
;
; COLOR CHANGES
;
GREEN   PUSH   AF
        LD     A,0CH      ; GREEN ON BLACK OPTION
G1      LD     (POPT),A
        POP    AF
        RET
;
RED     PUSH   AF
        LD     A,08H      ; RED ON BLACK
        JR     G1
;
NORM    PUSH   AF
        XOR    A          ; BACK TO NORMAL
        JR     G1
;
; NUMERICAL DISPLAY ROUTINE
;
NUMDIS  CP     0AH       ; CHECK IF WITHIN NUMERICAL LIMITS
        JR     C,NUM1    ; JUMP IF NEG.
                         ; ELSE NUMBER IS >= 'A' (HEX)
        ADD    A,07H      ; SET UP FOR ASCII
NUM1    ADD    A,30H      ; MAKE IT ASCII
        DEFB   DISP
        RET
;
; CHECK AND SCROLL IF NEEDED
;
SCROLL  LD     A,(SCRLN)
        SUB    6          ; SCRLN-6 IS LOWER LIMIT OF SCREEN
        CP     D          ; D IS Y COORDINATE
        RET    P          ; GO HOME IF NOT THERE YET
        PUSH   AF         ; SAVE THIS VALUE
        XOR    A          ; CLEAR A AND CARRY FLAG
        LD     HL,(SCRN)  ; GET SCREEN SIZE
        LD     BC,0F0H    ; MINUS 1 LINE'S WORTH
        SBC    HL,BC
        JR     Z,SCR1     ; IF ZERO, JUST BLANK TOP LINE
        PUSH   HL
        POP    BC         ; HOW MANY TO MOVE
        LD     HL,40F0H   ; SOURCE
        LD     DE,4000H   ; DESTINATION
        LDIR              ; MOVE (HL) TO (DE) BC TIMES
SCR1    LD     BC,06A0H   ; BLACK OUT LAST LINE
        LD     E,A
        POP    AF         ; RESET COORDS
        LD     D,A
        XOR    A          ; DATA FOR RECTANGLE
        DEFB   SYSTEM
        DEFB   1CH        ; RECTAN
        RET               ; GO HOME
;
CRLF    LD     DE,(COORD) ; GET CURSOR COORDS
        LD     BC,0503H   ; PAINT 3X5 BLANK
        LD     A,00H      ; COLOR
        DEFB   SYSTEM
        DEFB   1CH        ; RECTAN
                          ; UPDATE COORDINATES
CLF     LD     E,0        ; 'CARRIAGE RETURN'
        LD     A,06H       ; 'LINE FEED'
        ADD    A,D
        LD     D,A
        CALL   SCROLL
        CALL   CON        ; PAINT CURSOR
        LD     HL,IOB
        BIT    0,(HL)     ; TAPE WRITE IN PROGRESS?
        RET    Z          ; NOPE, GO HOME
        DEFB   SYSSUK
        DEFB   51H        ; PAWS
        DEFB   8          ; 4 CHARACTERS' WORTH
        RET               ; AND GO HOME
        RET
;
; THIS ROUTINE OUTPUTS ANY 8 BIT VALUE IN THE A REGISTER
; TO THE TAPE OUTPUT PORT.
; NOTE: THE TAPE PORT IS THE SAME AS THE PRINTER PORT
; SO IT IS SUGGESTED THAT FOR PRINTING THE PRINT COMMAND
; BE USED SO THAT THE PRINTER DOESN'T GO BANANAS.
;
TWRT                      ; WRITE TO TAPE
        LD     C,A        ; CHAR. TO C
        RLC    C          ; SHIFT LEFT ONCE
TW1     IN     A,(12H)    ; TAPE PORT FEEDBACK
        AND    2          ; WAIT FOR CLOCK HIGH
        JR     Z,TW1
        LD     B,0AH      ; BIT COUNTER
TW2     LD     A,0C0H     ; TIME COUNTER (192 DECIMAL)
TW3     DEC    A
        JR     NZ,TW3     ; 1.72 MSEC., HALF OF 300 HZ
                          ; CLOCK NOW LOW
        DEC    B          ; START COUNTING BITS
        RET    Z          ; GO HOME IF ALL DONE
        IN     A,(12H)    ; IS FEEDBACK STILL SAME STATE?
        LD     E,A        ; IF SO, THEN CLOCK IS LOW
TW4     IN     A,(12H)
        XOR    E          ; IF SAME, RESULT IS 0
        AND    2          ; ELSE RESULT IS 2
        JR     Z,TW4      ; TRY AGAIN
; CLOCK HIGH
        LD     A,E        ; OLD BIT TO A
        XOR    C          ; SEE IF NEED TO CHANGE STATE
        AND    2          ; OF OUTPUT
        JR     Z,TW5      ; N0, SKIP AHEAD
        IN     A,(12H)    ; TOGGLE OUTPUT
TW5     SET    1,C        ; PUT IN STOP BITS
        RRC    C          ; SET FOR NEXT BIT
        JR     TW2        ; DO IT AGAIN
;
;
;
;
;
SPACE_  LD     A,20H      ; ASCII SPACE
        DEFB   DISP
        RET
;
;
ERR     CALL   RED
        DEFB   STRING
        DEFW   ERM
        JP     MOD0
;
; THIS ROUTINE DISPLAYS THE CONTENTS OF THE A REGISTER.
; THUS ANY BYTE OF DATA CAN BE DISPLAYED BY PUTTING IT
; IN A AND CALLING RGDIS.
RGDIS   PUSH   AF         ; DISPLAY REGISTER CONTENTS
        AND    0F0H       ; MASK OUT LOWER HALF
        RLCA
        RLCA
        RLCA
        RLCA
        CALL   NUMDIS
        POP    AF
        AND    0FH        ; MASK OFF UPPER HALF
        CALL   NUMDIS
        RET
;
HLIST   LD     A,H        ; SHOW HL ROUTINE
        CALL   RGDIS
        LD     A,L
        CALL   RGDIS
        RET
;
;
READY
        LD     DE,(SCRN)  ; HOW MANY SCREEN BYTES
        LD     HL,UPRAM   ; 1ST SYSTEM SCRATCH BYTE
        RES    6,H        ; MAKE INTO A RELATIVE NUMBER
        OR     A          ; CLEAR CARRY FLAG
        SBC    HL,DE      ; (TOTAL RAM-SCREEN RAM)
        CALL   HLIST      ; DISPLAY IT
        DEFB   STRING
        DEFW   RMSG       ; STRING TO GO ALONG WITH IT
        LD     HL,(SCRN)
        SET    6,H        ; FUDGE IT INTO AN ADDRESS
        CALL   HLIST      ; DUMP IT OUT
        CALL   CRLF
        RET
;
;
; *********** KEYBOARD INTERFACE *************
;
; SCANS THE KEYPAD UNTIL A KEY IS PRESSED.  RETURNS WITH
; THE NUMBER OF THE KEY IN B.  NUMBERS ARE ROW-WISE
; RIGHT TO LEFT, 1 THROUGH 24.
;
KEYGET  LD     HL,KEYGET  ; SAVE THIS ADDRESS
        PUSH   HL
        DEFB   SYSSUK     ;
        DEFB   51H        ; PAWS--KEY DEBOUNCER, HOLD FOR
        DEFB   02H         ; 2/60 OF A SECOND
; KEYPAD INPUT RETURNS WITH KEY N0. IN A
        LD     DE,KEYN    ; OLD KEY NUMBER
        LD     BC,414H    ; B=COUNT, C=STARTING PORT
KG1     IN     A,(C)      ; CHECK OUT PORT
        AND    3FH        ; GET RID OF EXTRANEOUS BITS
        JR     NZ,KG2     ; JUMP IF GOT A GOOD ONE
        INC    C          ; NOPE, DO ANOTHER
        DJNZ   KG1
        XOR    A          ; NONE AT ALL
        LD     (DE),A     ; KEEP TRACK OF LAST KEY
        RET               ; BACK TO KEYGET
;
KG2     DEC    B
        LD     C,0
KG3     RRCA              ; FIND THE RIGHT BIT
        JR     C,KG4
        INC    C
        JR     KG3
KG4     LD     A,C        ; BIT #
        RLCA              ; MULT BY 4
        RLCA
        OR     B
        INC    A          ; NOW HAVE KEY NO.
        LD     B,A
        LD     A,(DE)     ; OLD NUMBER
        XOR    B          ; COMPARE
        RET    Z
        LD     A,B        ; DIFFERENT, UPDATE
        LD     (DE),A
        POP    HL         ; FIX THE STACK
        RET               ; AND GO BACK
;
; ********** INTERRUPT ROUTINES *****************
;
;
; INITIALIZE INTERRUPTS
;
ININT   IN     A,(12H)    ; TAPE INPUT PORT
        AND    2          ; MAKE SURE IT'S SET TO 0
        JR     NZ,ININT
        DI                ; DISABLE INTERRUPTS
        IM     2          ; INTERRUPT MODE
        LD     A,4FH      ; SET INTERRUPT PAGE
        LD     I,A
        LD     A,0B2H     ; SCREEN INTERRUPT VECTOR
        OUT    (0DH),A
        LD     A,08
        OUT    (0EH),A    ; SCREEN INTS ONLY
        LD     A,200
        OUT    (0FH),A    ; SCREEN INT. EVERY 200 LINES
        LD     HL,TAPINT  ; LOAD INTERRUPT VECTORS
        LD     (LPINT),HL
        LD     HL,SCRINT
        LD     (SCINT),HL
        EI                ; ENABLE INTERRUPTS
        RET
;
; ***** LIGHT PEN INTERRUPT HANDLER *******
;
; THE TAPE INPUT HANDLER RECOGNIZES A COLON AS AN
; ADDRESS DIRECTIVE, AND SPACE AND CR AS WRITE DIRECTIVES.
;
TAPINT
        PUSH   AF
        EXX
        CALL   COLL       ; GET A CHARACTER
TI1     LD     HL,IOB     ; TEST TAPE DISPLAY BIT
        BIT    3,(HL)
        JR     NZ,TID     ; IF SET, GO DISPLAY
        CP     0DH        ; ELSE TEST FOR CR
        JR     NZ,TI2     ; SKIP IF NOT
        CALL   WRITE      ; DO A WRITE
        LD     A,0DH      ; REPLACE CR
        JR     TID        ; DISPLAY IT
TI2     CP     20H        ; ELSE, ACT ON IT
        JR     C,TID      ; EXIT IF NOT DISPLAYABLE
        JR     NZ,TI3     ; ZERO MEANS A SPACE
        BIT    7,(HL)
; BIT 7 IN IOB IS ADDR FLAG MEANING IGNORE 1ST SPACE
; FOLLOWING COLON
        PUSH   HL         ; SAVE IOB
        CALL   Z,WRITE    ; IF CLEAR
        POP    HL
        RES    7,(HL)     ; CLEAR THE BIT
        JR     TIX        ; EXIT
;
TI3     RES    7,(HL)     ; CLEAR BIT IF NOT A SPACE
        CP     30H        ; CHECK NUMBER LIMITS
        JR     C,TID      ; LESS THAN
        CP     3AH
        JR     NC,TI4     ; >=
TI3A    AND    0FH        ; STRIP AWAY ASCII
        LD     C,A
        CALL   NUMBER
        JR     TIX
TI4     JR     NZ,TI5     ; JUMP IF NOT A COLON
        PUSH   HL         ; SAVE IOB
        CALL   ADDR
        POP    HL
        SET    7,(HL)     ; IGNORE NEXT SPACE
        JR     TIX        ; EXIT
TI5     CP     41H        ; 'A'
        JR     C,TID
        CP     47H        ; 'G'
        JR     NC,TID
        ADD    A,09H      ; SET UP FOR NUMBER
        JR     TI3A       ; GO TO IT
TID     DEFB   DISP
TIX     LD     A,(MODE)
        CP     4          ; MODE 4 SET?
        JP     Z,MODE4    ; SKIP OUT
        POP    AF
        EXX
        EI
        RET
;
COLL    IN     A,(12H)    ; COLLECT HITS FROM TAPE
        RRA               ; BIT TO CARRY
        LD     A,C        ; BITS SO FAR
        RRA               ; NEW BIT SHIFTED IN
        LD     C,A
        LD     A,B        ; COUNT
        AND    A
        JR     C,CO1      ; NEG.
        JR     NZ,CO2     ; NONZERO
        BIT    7,C        ; ZERO, TEST HIGHEST BIT
        JR     NZ,EXIT    ; NOT READY YET
        LD     B,08H      ; GOT ONE
        JR     EXIT
CO1     INC    B          ; NEG. COUNT LOOP
        BIT   7,C        ; STILL COLLECTING BITS
        JR     NZ,EXIT
        LD     B,0FCH     ; A ZERO CAME THRU WITH
                          ; COUNT WRONG
EXIT    POP    HL         ; DROP RETURN ADDRESS
        JR     TIX        ; AND GET OUT
CO2     DJNZ   EXIT       ; POS COUNT, NOT DONE YET
        LD     A,C        ; DONE
        RET
;
; *********** SCREEN INTERRUPT HANDLER ************
;
SCRINT  EI                ; ENABLE INTERRUPTS
        RET               ; AND GO BACK
;
;
;
; ********** UTILITY PROGRAMS **********
;
;
; BREAKPOINTS ARE SET BY WRITING 'CF' AT DESIRED LOCATIONS
;
BRKPT   CALL   CART       ; BREAKPOINT ROUTINE
        CALL   CRLF       ; CART GETS ORIGINAL REG SET
        DEFB   STRING
        DEFW   BKM
        POP    HL         ; GET BRKPT ADDR
        DEC    HL         ; BACK OFF ONE
        CALL   HLIST      ; SHOW IT
        CALL   RLIST      ; SHOW REGISTERS
        JP     START
;
;
;
; SET SCREEN SPECIFICATIONS
;
SCRSP   CALL   CRLF       ; OUTPUT A CARRIAGE RETURN
        LD     A,90       ; DEFAULT VALUE
        LD     (IN1),A    ; TO INPUT REGISTER
        DEFB   STRING
        DEFW   BLM        ; BLANK SPECS MESSAGE
        XOR    A          ; USE REG TYPE SEQUENCE
        LD     (RFG),A
        LD     A,3
        LD     (MODE),A   ; SET MODE 3
        RET
;
; THE FOLLOWING SECTION WILL BE ENTERED EACH TIME A 'W' IS
; INPUT WHILE IN MODE 3
;
MODE3   LD     A,C        ; GET KEY VALUE
        CP     4H
        RET    NZ         ; ACCEPT WRITE ONLY
        LD     A,(RFG)    ; PICK UP FLAG
        DEFB   SYSSUK
        DEFB   5BH        ; INDEXW-JUMP BASED ON FLAG
        DEFW   M3JT       ; JUMP TABLE
        PUSH   DE         ; RETURNED ADDRESS
        LD     A,(IN1)    ; GET INPUT VALUE
        RET               ; JUMP TO ROUTINE
M30            ; CALCULATE WHERE BLANKING
                          ; SHOULD START
        CP     5AH        ; IF 90 DECIMAL
        JR     Z,M302     ; LEAVE ALONE
        AND    0FH        ; MASK OUT UPPER DIGIT
        JR     NZ,M300    ; IF ZERO, MAKE IT ONE
        INC    A
M300    LD     B,A        ; N0. OF TEXT LINES INPUT
        XOR    A
M301    ADD    A,06H      ; CHARACTER FRAME SIZE
        DJNZ   M301
M302    LD     (ADRG1),A  ; TEMP. LINE STORAGE
        LD     A,2CH      ; 44 DECIMAL
        LD     (IN1),A    ; HORIZONTAL COLOR BOUNDARY
        CALL   CRLF
        DEFB   STRING
        DEFW   CBM
        LD     A,1        ; INCREMENT PROCESS POINTER
        LD     (RFG),A
        RET               ; GET THE NEXT SPEC.
;
M31     LD     (HRZCB),A  ; NO LIMIT CHECKS
        LD     A,00H      ; DEFAULT BACK COLOR
        LD     (IN1),A
        CALL   CRLF
        DEFB   STRING
        DEFW   BCLM       ; BACK COLOR MESSAGE
        LD     A,2        ; SET UP FOR NEXT PROCESS
        LD     (RFG),A
        RET               ; GO BACK
;
M32     LD     (BCOL),A   ; SET BCOLOR
        LD     A,07H      ; FORE COLOR
        LD     (IN1),A
        CALL   CRLF
        DEFB   STRING
        DEFW   FCLM       ; FORE COLOR MESSAGE
        LD     A,3        ; SET UP FOR NEXT PROCESS
        LD     (RFG),A
        RET
; THIS IS THE ACTION OF THE LAST KEYPUSH OF THE
; SCREEN SPEC. ROUTINE
M33     LD     (FCOL),A   ; SET FCOLOR
        LD     A,(ADRG1)  ; GET BLANK LINE #
        LD     (SCRLN),A  ; INTO ITS PROPER PLACE
        RLCA           ; SETOUT NEEDS IT
                       ; SHIFTED LEFT ONE BIT
        LD     D,A
        LD     A,(HRZCB)  ; COLOR BOUNDARY
        LD     B,A
        LD     A,08H      ; INTERRUPT MODE
        DEFB   SYSTEM
        DEFB   16H        ; DO NT SETOUT
        LD     HL,COLORS  ; GET ADDRESS OF COLOR LIST
        DEFB   SYSTEM
        DEFB   18H        ; COLSET
        LD     HL,00H     ; CALCULATE SCREEN SIZE
                          ; FROM N0. OF LINES DISPLAYED
        LD     A,(SCRLN)
        LD     B,A
        LD     DE,40      ; DECIMAL BYTES PER LINE
M331
        ADD    HL,DE
        DJNZ   M331       ; FIGURE OUT
        LD     (SCRN),HL  ; NO. OF BYTES IN SCREEN
        CALL   CLEAR      ; CLEAR SCREEN
        CALL   READY
        XOR    A          ; CLEAN OF
        LD     (RFG),A
        LD     (MODE),A
        RET               ; GO HOME
; ******** MESSAGE TABLE ********
AFM     DEFB   'A:'
        DEFB   00
BCM     DEFB   ' BC:'
        DEFB   00
DEM     DEFB   ' DE:'
        DEFB   00
HLM     DEFB   ' HL:'
        DEFB   00
ADM     DEFB   ' ADDR:'
        DEFB   00
BKM     DEFB   'BKPT ADDR:'
        DEFB   00
FCLM    DEFB   'FOREGROUND: '
        DEFB   00
WAM     DEFB   '*WARNING*'
        DEFB   00
RMSG    DEFB   ' BYTES AVAILABLE STARTING AT '
        DEFB   00
BLM     DEFB   'TEXT LINES: '
        DEFB   00
CBM     DEFB   'COLOR BOUNDARY: '
        DEFB   00
BCLM    DEFB   'BACKGROUND COLOR: '
        DEFB   00
ERM     DEFB   'ERR'
        DEFB   00
OKM     DEFB   'OK'
        DEFB   00
;
;
; ********** COLOR LIST *********
COLIST  DEFB   0A3H       ; GREEN
        DEFB   52H        ; RED
        DEFB   07H        ; WHITE
        DEFB   00H        ; BLACK
;
;
; ******* SMALL CHARACTER FONT DESCRIPTOR *****
SMLFNT  DEFB   0A0H       ; 1ST CHARACTER
        DEFB   4          ; X FRAME SIZE
        DEFB   6          ; Y FRAME SIZE
        DEFB   1          ; NO. OF BYTES X PATTERN
        DEFB   5          ; NO. OF BYTES Y PATTERN
        DEFW   SMLCHR     ; ADDRESS OF CHARACTER TABLE
;
;
; ****** CHARACTER TABLE ********
SMLCHR  DEFB   00,00,00,00,00              ; SPACE
        DEFB   20H,20H,20H,00,20H          ; !
        DEFB   0A0H,0A0H,00,00,00          ; "
        DEFB   0A0H,0E0H,0A0H,0E0H,0A0H    ; #
        DEFB   0,0,0,0,0                   ; UNDEFINED
        DEFB   0A0H,20H,40H,80H,0A0H       ; %
        DEFB   0,0,0,0,0                   ; UNDEFINED
        DEFB   40H,80H,0,0,0               ; '
        DEFB   40H,80H,80H,80H,40H         ; (
        DEFB   40H,20H,20H,20H,40H         ; )
        DEFB   00H,0A0H,40H,0A0H,00H       ; *
        DEFB   00H,40H,0E0H,40H,00H        ; +
        DEFB   00H,00H,00H,40H,80H         ; ,
        DEFB   00H,00H,0E0H,00H,00H        ; -
        DEFB   00H,00H,00H,00H,40H         ; .
        DEFB   20H,20H,40H,80H,80H         ; /
        DEFB   40H,0A0H,0A0H,0A0H,40H      ; 0
        DEFB   40H,40H,40H,40H,40H         ; 1
        DEFB   0E0H,20H,0E0H,80H,0E0H      ; 2
        DEFB   0E0H,20H,60H,20H,0E0H       ; 3
        DEFB   0A0H,0A0H,0E0H,20H,20H      ; 4
        DEFB   0E0H,80H,0E0H,20H,0E0H      ; 5
        DEFB   0E0H,80H,0E0H,0A0H,0E0H     ; 6
        DEFB   0E0H,20H,20H,20H,20H        ; 7
        DEFB   0E0H,0A0H,0E0H,0A0H,0E0H    ; 8 
        DEFB   0E0H,0A0H,0E0H,20H,20H      ; 9
        DEFB   00H,40H,00H,40H,00H         ; :
        DEFB   00H,40H,00H,40H,80H         ; ;
        DEFB   20H,40H,80H,40H,20H         ; <
        DEFB   00H,0E0H,00H,0E0H,00H       ; =
        DEFB   80H,40H,20H,40H,80H         ; >
        DEFB   0E0H,20H,60H,40H,40H        ; ?
        DEFB   0E0H,0A0H,20H,0E0H,0E0H     ; @
        DEFB   40H,0A0H,0E0H,0A0H,0A0H     ; A
        DEFB   0C0H,0A0H,0C0H,0A0H,0C0H    ; B
        DEFB   0E0H,80H,80H,80H,0E0H       ; C
        DEFB   0C0H,0A0H,0A0H,0A0H,0C0H    ; D
        DEFB   0E0H,80H,0C0H,80H,0E0H      ; E
        DEFB   0E0H,80H,0C0H,80H,80H       ; F
        DEFB   0E0H,80H,0A0H,0A0H,0E0H     ; G
        DEFB   0A0H,0A0H,0E0H,0A0H,0A0H    ; H
        DEFB   40H,40H,40H,40H,40H         ; I
        DEFB   20H,20H,20H,0A0H,0E0H       ; J
        DEFB   0A0H,0A0H,0C0H,0A0H,0A0H    ; K
        DEFB   80H,80H,80H,80H,0E0H        ; L
        DEFB   0A0H,0E0H,0A0H,0A0H,0A0H    ; M
        DEFB   80H,0E0H,0E0H,0A0H,0A0H     ; N
        DEFB   0E0H,0A0H,0A0H,0A0H,0E0H    ; O
        DEFB   0E0H,0A0H,0E0H,80H,80H      ; P
        DEFB   0E0H,0A0H,0A0H,0E0H,20H     ; Q
        DEFB   0E0H,0A0H,0C0H,0A0H,0A0H    ; R
        DEFB   60H,80H,0E0H,20H,0C0H       ; S
        DEFB   0E0H,40H,40H,40H,40H        ; T
        DEFB   0A0H,0A0H,0A0H,0A0H,0E0H    ; U
        DEFB   0A0H,0A0H,0A0H,0A0H,40H     ; V
        DEFB   0A0H,0A0H,0A0H,0E0H,0A0H    ; W
        DEFB   0A0H,0A0H,40H,0A0H,0A0H     ; X
        DEFB   0A0H,0A0H,40H,40H,40H       ; Y
        DEFB   0E0H,20H,40H,80H,0E0H       ; Z 
        DEFB   '(C) 1981 A. GUEVARA'
        DEFB   00
;
        DEFB   00         ; * NOW MATCHES MLM CART 
        ; END OF PROGRAM
