        IF      IODRIVERBODY
        page    Mate Hi-Res Terminal


*       COPYRIGHT (C) 1981 BY SOFTWARE DYNAMICS
*       ALL RIGHTS RESERVED
*
VERSION EQU     $10     LEFT DIGIT = MAJOR REV, RIGHT DIGIT = MINOR REV
*
CHARHEIGHT      EQU     8          # ROWS IN A CHARACTER
CHARWIDTH       EQU     6          # COLUMNS IN A CHARACTER POSITION
ScreenHgt       EQU     192        NUMBER OF ROWS ON THE SCREEN
SCREENWIDTH     EQU     256        NUMBER OF DOTS ACROSS THE SCREEN
CHARLEFTSIDE    EQU     1          CURSOR X AFTER NEWPAGE
CHARTOPSIDE     EQU     (ScreenHgt/CHARHEIGHT)*CHARHEIGHT-1
                                   ;CURSOR Y AFTER NEWPAGE
NBROW           EQU     SCREENWIDTH/8  NUMBER OF BYTES PER ROW
NROWS           EQU     ScreenHgt  NUMBER OF ROWS DOWN SCREEN
ScreenBtm       EQU     $400       Lowest displayable byte
                ; note: this byte is screen's upper left corner
SCREENTOP       EQU     ScreenBtm+NBROW*NROWS HIGHEST ADDRESS DISPLAY BYTE

        PAGE


*       SPECIAL KEYSTROKES
*
CTRLD   EQU     $04     CONTROL D (ACTIVATE DEBUG)
LF      EQU     $0A     LINE FEED
CR      EQU     $0D     CARRIAGE RETURN



*       PICTURE BLOCK DISPLACEMENTS
*
PICTXSIZ        EQU     0               X SIZE OF PICTURE IN BITS
PICTYSIZ        EQU     PICTXSIZ+2      Y SIZE OF PICTURE IN ROWS
PICTBYT         EQU     PICTYSIZ+2      1ST BYTE OF PICTURE DATA

        PAGE    GRAPHBOX CONTROL VARIABLES
::      set     *
        ifund   tempx
        ORG     0       GRAPHRAM APPEARS HERE WHEN GRAPHROM REFERENCED

TEMPX   RMB 2   LOCATIONS 0 AND 1 ARE TASK DEPENDENT
TEMP    EQU     TEMPX   FOR CONVENIENCE
TEMPA   EQU     TEMPX   TEMP STORAGE FOR A REGISTER
TEMPB   EQU     TEMPX+1 TEMP STORAGE FOR B REGISTER
        else
        org     tempx+10
        fin
CURSORX RMB 2   LOGICAL X POSITION IN DOTS FROM SCREEN LEFT SIDE
CURSORY RMB 2   LOGICAL Y POSITION IN DOTS FROM SCREEN BOTTOM LEFT
              ; NOTE THIS IS X & Y LIKE ON GRAPH IN QUADRANT WHERE
              ; X & Y ARE BOTH POSITIVE
CURSORBYTE      RMB 2   POINTER TO SCREEN BYTE CONTAINING CURSORBIT
CURSORBIT       RMB 2   BIT NUMBER OF SCREEN BYTE SELECTED BY (CURSORX, CURSORY)
WRITEATOSCREEN  RMB 2   Pointer to SUBROUTINE TO WRITE (A) TO (U)
*                               (EORMODE, IORMODE OR ANDMODE)
NEWX            RMB 2   NEW VALUE OF CURSORX
SHIFT           RMB 2   POINTER TO ROUTINE TO SHIFT DATA PATTERN
ROWCOUNT        RMB 1   NUMBER OF ROWS OF CHARACTER LEFT TO COPY TO SCREEN
TARGETLEFT      RMB 2   PLACE ON SCREEN TO PUT LEFT BYTE OF NEXT ROW OF CHARACTER
TARGETRIGHT     RMB 2   PLACE ON SCREEN TO PLACE RIGHTMOST CHARACTER ???
DELTAXSIGN      RMB 1   SIGN OF DELTA X (0 OR :FF)
DELTAYSIGN      RMB 1   SIGN OF DELTA Y (0 OR :FF)
*       NOTE! DELTAX, DELTAY MUST BE IN THIS EXACT ORDER FOR "RASSOCIATE"
DELTAX          RMB 2   DIFFERENCE BETWEEN CURSOR AND TARGETX
DELTAY          RMB 2   DIFFERENCE BETWEEN CURSORY AND TARGETY
TARGETX RMB 2   LOGICAL X POSITION TARGET
TARGETY RMB 2   LOGICAL Y POSITION TARGET

PICTUREP        RMB 2   POINTER TO ASSOCIATION TABLE ENTRY
PICTURE RMB     2       POINTER TO PICTURE BLOCK
PICTOP  RMB     2       POINTER TO TOP OF PICTURE BLOCK REGION

MULTIPLIER      RMB 1   USED TO COMPUTE # BYTES IN A PICTURE
PWIDTH          RMB 1   WIDTH OF PICTURE (ROUNDED UP) IN BYTES
WIDTHCNT        RMB 1   DOWN COUNTER USED TO SCAN PICTURE ROW
RESIDUE         RMB 1   PARTIAL PICTURE BYTE NOT YET PLACED ON SCREEN

LEFTEND         RMB 1   LEFT END OF TOP (BOTTOM) LINE OF A BOX
LEFTCOLUMN      RMB 1   LEFT EDGE OF (SIDE OF) EMPTY BOX
RIGHTEND        RMB 1   RIGHT END OF TOP (BOTTOM) LINE OF A BOX
RIGHTCOLUMN     RMB 1   RIGHT EDGE OF (SIDE OF) BOX
CURSORON        RMB 1   REMEMBERS THAT CURSOR IS DISPLAYED
CURSORBLINK     RMB 2  counts down to toggle cursor blink
currentbackground rmb 1 0 --> black background, $FF --> white background
ColorTermStack    equ $ff                       put it somewhere
        org     ::
        page
         fcc   "Copyright (C) 1983 Software Dynamics"

*       CONTROL FUNCTION ENTRY POINTS

CtrlCharBr
        FDB     RETURN          $00 NULL (ILLEGAL)
        FDB     RETURN
        FDB     RETURN          $02 CONTROL B
        FDB     RETURN          $03 CONTROL C
        FDB     RETURN          $04 CONTROL D
        FDB     ERASETOEOL      $05 CONTROL E
        FDB     RETURN          $06 CONTROL F
        FDB     DING            $07 CONTROL G
        FDB     CHCURSORLEFT    $08 CONTROL H
        FDB     RETURN          $09 CONTROL I
        FDB     CHCURSORDOWN    $0A CONTROL J
        FDB     RETURN          $0B CONTROL K
        FDB     NEWPAGE         $0C CONTROL L
        FDB     ENDLINE         $0D CONTROL M
        FDB     RETURN          $0E CONTROL N
        FDB     RETURN          $0F CONTROL O
        FDB     RETURN          $10 CONTROL P
        FDB     RETURN          $11 CONTROL Q
        FDB     CHCURSORRIGHT   $12 CONTROL R
        FDB     CHCURSORLEFT    $13 CONTROL S
        FDB     RETURN          $14 CONTROL T
        FDB     RETURN          $15 CONTROL U
        FDB     RETURN          $16 CONTROL V
        FDB     RETURN          $17 CONTROL W
        FDB     RETURN          $18 CONTROL X
        FDB     RETURN          $19 CONTROL Y
        FDB     RETURN          $1A CONTROL Z
        FDB     RETURN          $1B CONTROL [ (GRAPHICS COMMAND PREAMBLE)
        FDB     RETURN          $1C CONTROL BACKSLASH
        FDB     RETURN          $1D CONTROL ]
        FDB     CHCURSORUP      $1E CONTROL UP ARROW
        FDB     RETURN          $1F CONTROL LEFT ARROW
        page
CHARACTERSET    EQU     *       ASCII TO BIT PATTERN CONVERSION TABLE
         list  0                       just uses up paper
*       EACH CHARACTER BIT PATTERN OCCUPIES A 5 BY 7 MATRIX
*       THIS BIT PATTERN OCCUPIES 7 CONTIGUOUS BYTES...
*       WITH THE FIRST BYTE BEING THE FIRST DOT ROW OF THE CHARACTER, ETC.
*       THE 5 X 7 BIT MATRIX IS RIGHT JUSTIFIED IN THE BLOCK OF BYTES
*       THE TABLE IS ORDERED IN ASCII SEQUENCE...
*       SO THE PROCESS OF FINDING THE BIT MATRIX FOR A CHARACTER...
*       IS SIMPLY: LOC(BIT MATRIX):=CHARACTERSET+(CHAR-$20)*7
*       1ST BYTE OF CHARACTER HAS SIGN BIT SET IF CHARACTER HAS TAIL (SMALL G,J,P,Q,Y)


        FCB     %00000  SPACE
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000

        FCB     %00100  ! BANG
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00000
        FCB     %00100

        FCB     %01010  " DOUBLE QUOTE
        FCB     %01010
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000

        FCB     %01010  # HASH
        FCB     %01010
        FCB     %11111
        FCB     %01010
        FCB     %11111
        FCB     %01010
        FCB     %01010

        FCB     %00100  $ DOLLAR
        FCB     %01111
        FCB     %10100
        FCB     %01110
        FCB     %00101
        FCB     %11110
        FCB     %00100

        FCB     %11001  % PERCENT
        FCB     %11001
        FCB     %00010
        FCB     %00100
        FCB     %01000
        FCB     %10011
        FCB     %10011

        FCB     %01100  & AMPERSAND
        FCB     %10010
        FCB     %01100
        FCB     %11000
        FCB     %10101
        FCB     %10010
        FCB     %01101

        FCB     %00100  ' SINGLE QUOTE
        FCB     %00100
        FCB     %00100
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000

        FCB     %00010  ( LEFT PARENTHESES
        FCB     %00100
        FCB     %01000
        FCB     %01000
        FCB     %01000
        FCB     %00100
        FCB     %00010

        FCB     %01000  ) RIGHT PARENTHESES
        FCB     %00100
        FCB     %00010
        FCB     %00010
        FCB     %00010
        FCB     %00100
        FCB     %01000

        FCB     %00100  * ASTERISK
        FCB     %10101
        FCB     %01110
        FCB     %11111
        FCB     %01110
        FCB     %10101
        FCB     %00100

        FCB     %00000  + PLUS
        FCB     %00100
        FCB     %00100
        FCB     %11111
        FCB     %00100
        FCB     %00100
        FCB     %00000

        FCB     %00000  , COMMA
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00010
        FCB     %00010
        FCB     %00100

        FCB     %00000  - DASH
        FCB     %00000
        FCB     %00000
        FCB     %11111
        FCB     %00000
        FCB     %00000
        FCB     %00000

        FCB     %00000  . DOT
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00110
        FCB     %00110

        FCB     %00001  / SLASH
        FCB     %00001
        FCB     %00010
        FCB     %00100
        FCB     %01000
        FCB     %10000
        FCB     %10000

        FCB     %01110  0 ZERO
        FCB     %10001
        FCB     %10011
        FCB     %10101
        FCB     %11001
        FCB     %10001
        FCB     %01110

        FCB     %00100  1 ONE
        FCB     %01100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %11111

        FCB     %01110  2 TWO
        FCB     %10001
        FCB     %00001
        FCB     %01110
        FCB     %10000
        FCB     %10000
        FCB     %11111

        FCB     %01110  3 THREE
        FCB     %10001
        FCB     %00001
        FCB     %01110
        FCB     %00001
        FCB     %10001
        FCB     %01110

        FCB     %10010  4 FOUR
        FCB     %10010
        FCB     %10010
        FCB     %11111
        FCB     %00010
        FCB     %00010
        FCB     %00010

        FCB     %11111  5 FIVE
        FCB     %10000
        FCB     %10000
        FCB     %11110
        FCB     %00001
        FCB     %00001
        FCB     %11110

        FCB     %01110  6 SIX
        FCB     %10001
        FCB     %10000
        FCB     %11110
        FCB     %10001
        FCB     %10001
        FCB     %01110

        FCB     %11111  7 SEVEN
        FCB     %10001
        FCB     %00010
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100

        FCB     %01110  8 EIGHT
        FCB     %10001
        FCB     %10001
        FCB     %01110
        FCB     %10001
        FCB     %10001
        FCB     %01110

        FCB     %01110  9 NINE
        FCB     %10001
        FCB     %10001
        FCB     %01111
        FCB     %00001
        FCB     %00010
        FCB     %11100

        FCB     %00000  : COLON
        FCB     %00110
        FCB     %00110
        FCB     %00000
        FCB     %00110
        FCB     %00110
        FCB     %00000

        FCB     %00000  ; SEMICOLON
        FCB     %00100
        FCB     %00100
        FCB     %00000
        FCB     %00100
        FCB     %00100
        FCB     %01000

        FCB     %00011  < LEFT ANGLE BRACKET
        FCB     %00100
        FCB     %01000
        FCB     %10000
        FCB     %01000
        FCB     %00100
        FCB     %00011

        FCB     %00000  = EQUAL
        FCB     %00000
        FCB     %11111
        FCB     %00000
        FCB     %11111
        FCB     %00000
        FCB     %00000

        FCB     %11000  > RIGHT ANGLE BRACKET
        FCB     %00100
        FCB     %00010
        FCB     %00001
        FCB     %00010
        FCB     %00100
        FCB     %11000

        FCB     %01110  ? QUESTION MARK
        FCB     %10001
        FCB     %00010
        FCB     %00100
        FCB     %00000
        FCB     %00110
        FCB     %00110

        FCB     %01110  @ AT SIGN
        FCB     %10001
        FCB     %10101
        FCB     %10111
        FCB     %10110
        FCB     %10000
        FCB     %01111

        FCB     %01110  LETTER A
        FCB     %10001
        FCB     %10001
        FCB     %11111
        FCB     %10001
        FCB     %10001
        FCB     %10001

        FCB     %11110  LETTER B
        FCB     %10001
        FCB     %10001
        FCB     %11110
        FCB     %10001
        FCB     %10001
        FCB     %11110

        FCB     %01110  LETTER C
        FCB     %10001
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %10001
        FCB     %01110

        FCB     %11110  LETTER D
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %11110

        FCB     %11111  LETTER E
        FCB     %10000
        FCB     %10000
        FCB     %11100
        FCB     %10000
        FCB     %10000
        FCB     %11111

        FCB     %11111  LETTER F
        FCB     %10000
        FCB     %10000
        FCB     %11100
        FCB     %10000
        FCB     %10000
        FCB     %10000

        FCB     %01110  LETTER G
        FCB     %10001
        FCB     %10000
        FCB     %10000
        FCB     %10011
        FCB     %10001
        FCB     %01110

        FCB     %10001  LETTER H
        FCB     %10001
        FCB     %10001
        FCB     %11111
        FCB     %10001
        FCB     %10001
        FCB     %10001

        FCB     %11111  LETTER I
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %11111

        FCB     %01111  LETTER J
        FCB     %00010
        FCB     %00010
        FCB     %00010
        FCB     %00010
        FCB     %10010
        FCB     %01100

        FCB     %10001  LETTER K
        FCB     %10010
        FCB     %10100
        FCB     %11000
        FCB     %10100
        FCB     %10010
        FCB     %10001

        FCB     %10000  LETTER L
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %11111

        FCB     %10001  LETTER M
        FCB     %11011
        FCB     %10101
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001

        FCB     %10001  LETTER N
        FCB     %10001
        FCB     %11001
        FCB     %10101
        FCB     %10011
        FCB     %10001
        FCB     %10001

        FCB     %01110  LETTER OH
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %01110

        FCB     %11110  LETTER P
        FCB     %10001
        FCB     %10001
        FCB     %11110
        FCB     %10000
        FCB     %10000
        FCB     %10000

        FCB     %01110  LETTER Q
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10101
        FCB     %10010
        FCB     %01101

        FCB     %11110  LETTER R
        FCB     %10001
        FCB     %10001
        FCB     %11110
        FCB     %10100
        FCB     %10010
        FCB     %10001

        FCB     %01110  LETTER S
        FCB     %10001
        FCB     %10000
        FCB     %01110
        FCB     %00001
        FCB     %10001
        FCB     %01110

        FCB     %11111  LETTER T
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100

        FCB     %10001  LETTER U
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %01110

        FCB     %10001  LETTER V
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %01010
        FCB     %00100

        FCB     %10001  LETTER W
        FCB     %10001
        FCB     %10001
        FCB     %10101
        FCB     %10101
        FCB     %11011
        FCB     %10001

        FCB     %10001  LETTER X
        FCB     %10001
        FCB     %01010
        FCB     %00100
        FCB     %01010
        FCB     %10001
        FCB     %10001

        FCB     %10001  LETTER Y
        FCB     %10001
        FCB     %01010
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100

        FCB     %11111  LETTER Z
        FCB     %00001
        FCB     %00010
        FCB     %00100
        FCB     %01000
        FCB     %10000
        FCB     %11111

        FCB     %11111  [ LEFT SQUARE BRACKET
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %11111

        FCB     %10000  BACK SLASH
        FCB     %10000
        FCB     %01000
        FCB     %00100
        FCB     %00010
        FCB     %00001
        FCB     %00001

        FCB     %11111  ] RIGHT SQUARE BRACKET
        FCB     %00001
        FCB     %00001
        FCB     %00001
        FCB     %00001
        FCB     %00001
        FCB     %11111

        FCB     %00100  ^ UP ARROW OR CARET
        FCB     %01110
        FCB     %10101
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100

        FCB     %00000  _ LEFT ARROW OR UNDERSCORE
        FCB     %00100
        FCB     %01000
        FCB     %11111
        FCB     %01000
        FCB     %00100
        FCB     %00000

        FCB     %01000  ` ACCENT GRAVE
        FCB     %00100
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000
        FCB     %00000

        FCB     %00000  SMALL A
        FCB     %00000
        FCB     %01110
        FCB     %10010
        FCB     %10010
        FCB     %10010
        FCB     %01111

        FCB     %10000  SMALL B
        FCB     %10000
        FCB     %10000
        FCB     %11110
        FCB     %10001
        FCB     %10001
        FCB     %11110

        FCB     %00000  SMALL C
        FCB     %00000
        FCB     %01110
        FCB     %10000
        FCB     %10000
        FCB     %10000
        FCB     %01110

        FCB     %00001  SMALL D
        FCB     %00001
        FCB     %00001
        FCB     %01111
        FCB     %10001
        FCB     %10001
        FCB     %01111

        FCB     %00000  SMALL E
        FCB     %00000
        FCB     %01110
        FCB     %10001
        FCB     %11110
        FCB     %10000
        FCB     %01110

        FCB     %00110  SMALL F
        FCB     %01001
        FCB     %01000
        FCB     %11100
        FCB     %01000
        FCB     %01000
        FCB     %01000

        FCB     %00111+$80      SMALL G
        FCB     %01001
        FCB     %01001
        FCB     %00111
        FCB     %00001
        FCB     %00001
        FCB     %00110

        FCB     %10000  SMALL H
        FCB     %10000
        FCB     %10000
        FCB     %11110
        FCB     %10001
        FCB     %10001
        FCB     %10001

        FCB     %00100  SMALL I
        FCB     %00000
        FCB     %01100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00110

        FCB     $82     SMALL J
        FCB     %00000
        FCB     %00110
        FCB     %00010
        FCB     %00010
        FCB     %00010
        FCB     %01100

        FCB     %10000  SMALL K
        FCB     %10000
        FCB     %10010
        FCB     %10100
        FCB     %11000
        FCB     %10100
        FCB     %10010

        FCB     %01100  SMALL L
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %00100
        FCB     %01110

        FCB     %00000  SMALL M
        FCB     %10000
        FCB     %11010
        FCB     %10101
        FCB     %10101
        FCB     %10101
        FCB     %10101

        FCB     %00000  SMALL N
        FCB     %00000
        FCB     %10000
        FCB     %11110
        FCB     %10001
        FCB     %10001
        FCB     %10001

        FCB     %00000  SMALL O
        FCB     %00000
        FCB     %01110
        FCB     %10001
        FCB     %10001
        FCB     %10001
        FCB     %01110

        FCB     %11100+$80      SMALL P
        FCB     %10010
        FCB     %10010
        FCB     %11100
        FCB     %10000
        FCB     %10000
        FCB     %10000

        FCB     %00111+$80      SMALL Q
        FCB     %01001
        FCB     %01001
        FCB     %00111
        FCB     %00001
        FCB     %00001
        FCB     %00001

        FCB     %00000  SMALL R
        FCB     %00000
        FCB     %10110
        FCB     %11001
        FCB     %10000
        FCB     %10000
        FCB     %10000

        FCB     %00000  SMALL S
        FCB     %00000
        FCB     %01110
        FCB     %10000
        FCB     %01110
        FCB     %00001
        FCB     %01110

        FCB     %00000  SMALL T
        FCB     %01000
        FCB     %11100
        FCB     %01000
        FCB     %01000
        FCB     %01000
        FCB     %00100

        FCB     %00000  SMALL U
        FCB     %00000
        FCB     %10010
        FCB     %10010
        FCB     %10010
        FCB     %10010
        FCB     %01101

        FCB     %00000  SMALL V
        FCB     %00000
        FCB     %10001
        FCB     %10001
        FCB     %01010
        FCB     %01010
        FCB     %00100

        FCB     %00000  SMALL W
        FCB     %00000
        FCB     %10001
        FCB     %10001
        FCB     %10101
        FCB     %10101
        FCB     %01010

        FCB     %00000  SMALL X
        FCB     %00000
        FCB     %10001
        FCB     %01010
        FCB     %00100
        FCB     %01010
        FCB     %10001

        FCB     %01001+$80      SMALL Y
        FCB     %01001
        FCB     %01001
        FCB     %00111
        FCB     %00001
        FCB     %00001
        FCB     %00110

        FCB     %00000  SMALL Z
        FCB     %00000
        FCB     %01111
        FCB     %00001
        FCB     %00010
        FCB     %00100
        FCB     %01111

        FCB     %00110  LEFT CURLY BRACKET
        FCB     %01000
        FCB     %01000
        FCB     %10000
        FCB     %01000
        FCB     %01000
        FCB     %00110

        FCB     %00100  VERTICAL BAR
        FCB     %00100
        FCB     %00100
        FCB     %00000
        FCB     %00100
        FCB     %00100
        FCB     %00100

        FCB     %01100  RIGHT CURLY BRACKET
        FCB     %00010
        FCB     %00010
        FCB     %00001
        FCB     %00010
        FCB     %00010
        FCB     %01100

        FCB     %00000  TILDE
        FCB     %00000
        FCB     %01001
        FCB     %10101
        FCB     %10010
        FCB     %00000
        FCB     %00000

        FCB     %11111  RUBOUT
        FCB     %11111
        FCB     %11111
        FCB     %11111
        FCB     %11111
        FCB     %11111
        FCB     %11111
         list 1
        PAGE    DISPLAY PRINTING CHARACTER

PUTCHAR ; (A) contains 7 bit ASCII code, output to G6R ColorComputer screen
        PSHA
        JSR     TASKLEVELCURSOR        TURN OFF CURSOR IF ON AND LOCK
        PULA
        CMPA    #$1F
        BHI     DISPLAYCHRJSR          IF PRINTING GO DISPLAY AND UNLOCK
        ASLA
        LDX     #CTRLCHARBR
        ; GO HANDLE CONTROL CODE, WHICH CAN MOVE CURSOR
        JSR     [A,X]
        BRA     TASKLEVELCURSORUNLOCK
DISPLAYCHRJSR   EQU     *
        JSR     DISPLAYCHAR


; UNLOCK BLINK FOR OUTPUT

TASKLEVELCURSORUNLOCK   EQU            *
        CLR    CURSORLOCK
        RTS

CURSORLOCK FCB 0

; LOCK CURSOR BLINK FOR OUTPUT AND TURN OFF IF ON

TASKLEVELCURSOR EQU     *
        COM     CURSORLOCK             TELL INTERRUPTS WITH $FF
        LDAB    CURSORON               NOT TO BLINK CURSOR
        BEQ     CURSOROFF              IS CURSOR OFF? B/Y
        LDX     CURSORX
        PSHX                           SAVE LOCATION ON LINE
        LDX     #CHARWIDTH
        LDD     #CHARHEIGHT
        JSR     EMPTYBOX               PUT UP EORA EMPTY BOX
        PULX                           REMOVING BOX
        STX     CURSORX                RESTORE SO BOX DOES NOT WALK
        CLR     CURSORON               NOTE CURSOR OFF
CURSOROFF       EQU     *
        LDAA    #5         TURN ON CURSOR 100 MILLI-SECONDS AFTER I/O
        STAA    CURSORBLINK            60HZ COUNT UNTIL BLINK
        RTS

EMPTYBOX ; (X) CONTAINS BOX X SIZE, (D) CONTAINS Y SIZE
        JSR     BOXEDGE                COMPUTE BOX EDGES AND POINTERS
        BEQ     EMPTYBOXIT             QUIT IF BOX IS ZERO BYTES WIDE
        JSR     DRAWHORZLINE           GO DRAW TOP OF BOX
        DEC     DELTAY+1               IS BOX ONLY ONE ROW DEEP ?
        BEQ     EMPTYBOXIT             YES, GET OUT NOW !
EMPTYLOOP       EQU     *
        LDU     TARGETLEFT             ADVANCE POINTER...
        LEAU    NBROW,U                DOWN SCREEN...
        STU     TARGETLEFT             ONE LINE
        DEC     DELTAY+1               ON LAST LINE OF BOX ?
        BEQ     EMPTYLAST              YES, GO DRAW A SOLID LINE
        LDAA    LEFTCOLUMN             INSERT LEFT SIDE OF BOX
        JSR     [WRITEATOSCREEN]
        LDB     PWIDTH                 COMPUTE RIGHT END POINTER
        LEAU    B,U                    = LEFT END + PICTUREWIDTH - 1
        LEAU    -1-1,U                 IN SAME ROW (EXTRA -1 OFFSETS AUTOINC...
        LDAA    RIGHTCOLUMN            IN WRITEATOSCREEN)
        JSR     [WRITEATOSCREEN]
        BRA     EMPTYLOOP

EMPTYLAST       EQU     *
        JSR     DRAWHORZLINE           GO DRAW A SOLID HORIZONTAL LINE
EMPTYBOXIT      EQU     *
        LDX     NEWX                   NOW ADVANCE CURSORX PAST THE BOX
        STX     CURSORX
        RTS                            AND QUIT
*       DRAWHORZLINE -- DRAWS A HORIZONTAL LINE
*       TARGETLEFT POINTS TO 1ST SCREEN BYTE
*       LEFTEND CONTAINS LEFT HAND END OF LINE MASK
*       PWIDTH CONTAINS WIDTH OF LINE IN BYTES
*       RIGHTEND CONTAINS RIGHTMOST MOST BYTE OF LINE
*       IF ONLY ONE BYTE IS TO BE MODIFIED,
*       LEFTEND = BYTE CONTENTS...
*       AND RIGHTEND MUST BE ZERO
*
DRAWHORZLINE    EQU     *
        LDU     TARGETLEFT             GET POINTER TO LEFTMOST BYTE OF LINE
        LDAB    PWIDTH                 GET WIDTH OF HORIZONTAL LINE
        LDAA    LEFTEND                GET LEFTMOST BYTE OF LINE
        JSR     [WRITEATOSCREEN]       COMBINE (A) WITH SCREEN BYTE
        DECB                           ROW HIT YET ?
        BEQ     DRAWHORZLINERTS        B/ YES, GET OUT!
        DECB                           2 BYTE WIDE PATTERN ?
        BEQ     DRAWHORZLINERIGHTMOST  B/ YES, GO HANDLE
DRAWHORZLOOP    EQU     *
        LDAA    #%11111111             GET ALL 1'S PATTERN
        JSR     [WRITEATOSCREEN]       COMBINE (A) WITH SCREEN BYTE
        DECB                           ALL BYTES IN ROW HIT YET ?
        BNE     DRAWHORZLOOP           NO
DRAWHORZLINERIGHTMOST ; re-enter here if box is only two bytes wide
        LDAA    RIGHTEND               GET LAST BYTE BIT PATTERN
        JSR     [WRITEATOSCREEN]       AND DUMP INTO SCREEN MEMORY
DRAWHORZLINERTS
        RTS

DING ; output <BEL> sound
        LDX     #$100       GET LENGTH OF DING TIME
DingLoop ; loop here to output cycles of sound
        lda     $ff22           toggle single bit sound output
        eora    #%00000010
        staa    $ff22
        ldab    #$50            duration of 1/2 of sound cycle
DingBitLoop
        decb
        bne     DingBitLoop
        dex                     down count # sound cycles to output
        bne     DingLoop
RETURN  RTS                     YOU GUESS...

DISPLAYCHAR ; DISPLAY PRINTING CHARACTER (A)
        PSHA                    SAVE THE CHARACTER, WE NEED IT LATER
        LDX     CURSORX         IS THIS LINE FULL ?
        CMPX    #(SCREENWIDTH-CHARWIDTH-1) ... ?
        BLS     CHAR1           NO, GO CHECK FOR OVERRUN BOTTOM OF SCREEN
        LDX     #CHARLEFTSIDE   CHARACTER WOULD RUN OFF RIGHT SIDE OF SCREEN
        STX     CURSORX         SO PUT CURSOR BACK TO LEFT SIDE OF SCREEN
        LDD     CURSORY         NOW MOVE DOWN THE SCREEN A ROW
        SUBD    #CHARHEIGHT     RUN OFF BOTTOM OF SCREEN ?
        BLO     CHAR2           YES, MUST ROLL SCREEN
        STD     CURSORY         (ADVANCE CURSORY DOWN A CHARACTER ROW)
CHAR1   EQU     *       CHECK FOR OVERRUN BOTTOM OF SCREEN
        LDD     CURSORY         GET VERTICAL CURSOR POSITION
        CMPD    #CHARHEIGHT-1   DOES NEXT LINE RUN OFF BOTTOM OF SCREEN ?
        BHS     CHARPUTC        NO, JUST GO DISPLAY THE CHARACTER
CHAR2   EQU     *               MUST ROLL SCREEN MORE THAN 1 CHARACTER LINE
        SUBD    #CHARHEIGHT-1+(ScreenHgt-(ScreenHgt/CHARHEIGHT)*CHARHEIGHT)
*                               ADD ANOTHER LINE TO OVERRUN DISTANCE
CHARR   EQU     *               ROLL THE SCREEN; (D) = - # LINES
        JSR     RollUp1Line  ROLL THE SCREEN UP ONE CHARACTER LINE
*       NEXT, WE OUTPUT THE CHARACTER TO THE SCREEN
CHARPUTC ; NOW PUT CHARACTER ON THE SCREEN
        PULA                    GIMME MY CHARACTER BACK !
        SUBA    #$20            subtract of bias for control characters
        LDB     #7              MULTIPLY CHARACTER BY 7
        MUL
        LDX     #CHARACTERSET COMPUTE POINTER TO DOT MATRIX PATTERN
        LEAX    D,X
        STX     PICTURE         AND SAVE IT
        LDD     CURSORY         IF WE ARE DISPLAYING A LETTER WITH A TAIL,
        TST     0,X             THEN PLACE ON SCREEN 2 LINES BELOW NORMAL
        BPL     CPUT1           B/ NO TAIL (not small G,J,P,Q,Y)
        SUBD    #1              TAIL, SKIP DOWN SCREEN ONE LINE
CPUT1   JSR     GENCURSORCHAR   GET POINTER TO BYTE WHICH CURSOR SELECTS
        STX     TARGETLEFT      SAVE POINTER TO LEFT TARGET BYTE
        ASLB                    DOUBLE BIT INDEX FOR WORD JUMP TABLE
        LDX     #CSHIFTBL       compute pointer to shift routine
        LDY     B,X
        LDAA    #7              GET NUMBER OF ROWS TO INSERT
        STAA    ROWCOUNT        SET UP LOOP LIMIT COUNTER
        ldaa    currentbackground
        anda    #%00011111
        staa    charbackground         ; GET BACKGROUND FOR CHARWIDTH
        ldx     #charmasktable
        ldd     b,x
        std     charmask               ; SAVE MASK TO REMOVE CHAR ON SCREEN
        comd
        anda    currentbackground
        andb    currentbackground
        std     charfillin
        ldx     picture
        ldu     targetleft
        lda     0,x
        bpl     notail
tail    equ     *
        ldd     -nbrow,u               ; clear first line of character area
        anda    charmask               ; because have shifted down for tail
        andb    charmask+1
        eora    charfillin             ; set to background
        eorb    charfillin+1
        std     -nbrow,u
        bra     taildone

notail  equ     *
        ldd     7*nbrow,u              ; clear possible tail in place
        anda    charmask               ; because are not outputting tail
        andb    charmask+1
        eora    charfillin
        eorb    charfillin+1
        std     7*nbrow,u

taildone   EQU *
        ldd     charmask
        anda    0,u                    ; clear first line of character
        andb    1,u
        std     0,u
        lda     ,x+                    ; fetch 1st row of dot matrix
        anda    #$1f                   ; mask off tail

*
*       THE PUMP IS PRIMED, NOW LET'S INSERT THE CHARACTER DOT MATRIX
*

; mask out row of bits for character area in memory

eoraandjmp      equ *
        eora    charbackground
        clrb
        jmp ,Y

CHARPUTX ; DONE INSERTING CHARACTER ON SCREEN
        LDD     CURSORX         GRAB CURSOR POINTER
        ADDD    #CHARWIDTH      ADVANCE IT TO NEXT CHARACTER POSITION
        ; (THIS CANNOT OVERRUN THE RIGHT EDGE OF THE SCREEN)
        STD     CURSORX
        RTS                     RETURN TO CALLER

CSHIFTL3 ASLA                   SHIFT DOT MATRIX LEFT 3 BITS
CSHIFTL2 ASLA                   SHIFT DOT MATRIX LEFT 2 BITS
CSHIFTL1 ASLA                   SHIFT DOT MATRIX LEFT 1 BIT
CSHIFT0  JSR    [WRITEATOSCREEN] STORE BIT PATTERN FOR CHARACTER TO SCREEN
        DEC     ROWCOUNT        ANY MORE ROWS LEFT TO INSERT ?
        BEQ     CHARPUTX        NO, JUST ADVANCE THE CURSOR
        LEAU    NBROW-1,U       ADVANCE POINTER TO NEXT ROW
        ldd     0,u
        anda    charmask
        andb    charmask+1
        std     0,u
        lda     ,x+
        eora    charbackground
        jmp ,Y

CSHIFTR4 LSRA                   SHIFT RIGHT 4 PLACES
         RORB
CSHIFTR3 LSRA                   SHIFT RIGHT 3 PLACES
         RORB
CSHIFTR2 LSRA                   SHIFT RIGHT 2 PLACES
         RORB
CSHIFTR1 LSRA                   SHIFT RIGHT 1 PLACE
         RORB
        JSR     [WRITEATOSCREEN]
        TFR     B,A             COPY RIGHT HALF OF CHARACTER TO (A)
        JSR     [WRITEATOSCREEN] INSERT RIGHT HALF OF CHARACTER
        DEC     ROWCOUNT        ANY MORE ROWS LEFT TO INSERT ?
        BEQ     CHARPUTX        NO, JUST ADVANCE THE CURSOR
        LEAU    NBROW-2,U       ADVANCE POINTER TO NEXT ROW
        ldd     0,u
        anda    charmask
        andb    charmask+1
        std     0,u
        lda     ,x+
        bra     eoraandjmp

CSHIFTBL ; POINTERS TO CHARACTER SHIFT ROUTINES
        CSHIFTL3                BIT # =0 --> SHIFT LEFT 3
        CSHIFTL2                =1 --> LEFT 2
        CSHIFTL1                ETC.
        CSHIFT0
        CSHIFTR1
        CSHIFTR2
        CSHIFTR3
        CSHIFTR4
         page
SETCURSORX      EQU     *       SETS X VALUE OF CURSOR TO (X)
        STX     CURSORX
        RTS

SETCURSORY      EQU     *       SETS Y VALUE OF CURSOR TO (D)
        STD     CURSORY         STORE AS CURSORY Y VALUE
        RTS                     AND EXIT

SETCURSORXY     EQU     *       SET CURSOR X TO (X), CURSORY TO (A)
        STX     CURSORX
        STD     CURSORY
        RTS

charbackground fcb $00
charmask   fdb $0000
charfillin fdb $0000

; mask table used to remove character based on where it is across
; two bytes in memory

charmasktable   equ *
        fcb %00000111,%11111111
        fcb %10000011,%11111111
        fcb %11000001,%11111111
        fcb %11100000,%11111111
        fcb %11110000,%01111111
        fcb %11111000,%00111111
        fcb %11111100,%00011111
        fcb %11111110,%00001111

BITMSK  FCB     %10000000       BIT # 0
        FCB     %01000000       BIT # 1
        FCB     %00100000       BIT # 2
        FCB     %00010000       BIT # 3
        FCB     %00001000       BIT # 4
        FCB     %00000100       BIT # 5
        FCB     %00000010       BIT # 6
        FCB     %00000001       BIT # 7

ModScrnSHIFT ; (D) contains # scan lines to roll screen up
;  shuffles from high part of display area to lower addresses
        ldu     #ScreenBtm-NBRow+16 = shuffle to target
        lda     #nbrow          figure out distance to move screen lines
        mul
        leax    d,u             = shuffle from source
ModScrnShftShufUp
        ldd     -16,x
        std     -16,u
        ldd     -14,x
        std     -14,u
        ldd     -12,x
        std     -12,u
        ldd     -10,x
        std     -10,u
        ldd     -8,x
        std     -8,u
        ldd     -6,x
        std     -6,u
        ldd     -4,x
        std     -4,u
        ldd     -2,x
        std     -2,u
        ldd     ,x
        std     ,u
        ldd     2,x
        std     2,u
        ldd     4,x
        std     4,u
        ldd     6,x
        std     6,u
        ldd     8,x
        std     8,u
        ldd     10,x
        std     10,u
        ldd     12,x
        std     12,u
        ldd     14,x
        std     14,u
        leax    32,x
        leau    32,u
; assert: number of bytes per row is divisible by 8
        cmpx    #ScreenTop+16 shuffle complete ?
        bne     ModScrnShftShufUp
        rts
         page
*       GENCURSORBYTE -- RETURNS POINTER TO BYTE ON SCREEN IN (X)
*       WHICH CONTAINS THE BIT SPECIFIED BY CURSORX, CURSORY
*       ALSO SETS CURSORBYTE TO (X)
*       (B) = BIT NUMBER  (0 = MSB, 7 = LSB)
*       BYTE = CURSORY*ROWSIZE+INT(CURSORX/8)
*       BIT = CURSORX MOD 8
*
*       GENCURSOR1 IS ENTRY POINT WITH (A,B) = X POSITION
*               AND TOP OF STACK = Y POSITION
*
; on color computer, x and y are limited to 255!!!
GENCURSORBYTE   EQU     *
        LDD     CURSORY         GET Y POSITION
GENCURSORCHAR ; ENTRY TO GENERATE CURSORBYTE FOR CHARACTER DISPLAY
        NEGD                    OFFSET INTO BUFFER
        ADDD    #ScreenHgt-1 produces 0 for max Y position
        LDX     #ScreenBtm   = (X,Y) = (0,255)
        LDA     #NBROW
        MUL
        PSHD                    (D) = offset to desired screen row
        LDD     CURSORX
        LSRD                    compute cursorx divided by 8
        lsrb                    ...=/4; assert: (A)=0
        lsrb                    ...=/8
        addd    ,s++            combine with row offset
        leax    d,x             pointer to desired location
        STX     CURSORBYTE      SAVE POINTER WHERE WE PROMISED
        LDB     CURSORX+1       GET BIT NUMBER BACK
        ANDB    #7              = CURSORX MOD 8
        RTS                     AND EXIT
        page
*       CLEARLINES -- SUBROUTINE TO CLEAR HORIZONTAL SCREEN LINES
*       (X) POINTS TO 1ST BYTE OF LINE
*       (B) CONTAINS LINE COUNT
*       CLEARS LINES ABOVE AND INCLUDING (X) ON SCREEN
*
CLEARLINES      EQU     *
        LEAX    16,X            to compensate for STD -16,X below
        STB     TEMPB
        LDA     CURRENTBACKGROUND GET BACKGROUND TO STORE
        TFR     A,B
CLEARLOOP       EQU     *
        RPT     16
        STD     *-CLEARLOOP-16,X clear 32 bytes (1 screen row)
        LEAX    32,X            advance (X) to "start" of next row
        DEC     TEMPB           ALL ROWS ZEROED ?
        BNE     CLEARLOOP       B/ no, go clear another!
CLEARRTS
        RTS

NEWPAGE EQU     *
        LDX     #ScreenBtm   ZERO THE ENTIRE SCREEN
        LDD     #ScreenHgt
        JSR     CLEARLINES
        LDX     #CHARLEFTSIDE   POSITION CURSOR...
        STX     CURSORX         AT TOP LEFT CORNER OF SCREEN
        LDX     #CHARTOPSIDE
        STX     CURSORY
        RTS                     ALL DONE !

SETCHCURSOR ; (A)= ROW, (B)= COLUMN; (0,0) is upper left corner
        PSHB                    save column number
        PSHA
        JSR     TASKLEVELCURSOR
        PULA
        LDAB    #CHARHEIGHT     Scan lines/character row
        MUL                     = Scan lines to skip (assert: < 256!)
        NEGD                    ROW #0 = MAX Y POSITION
        ADDD    #CHARTOPSIDE
        STD     CURSORY
        PULB                    get character column number
        LDAA    #CHARWIDTH      convert to X dot number
        MUL
        ADDD    #CHARLEFTSIDE   add position of leftmost character column
        STD     CURSORX         RESULT <= 511 GAURANTEED!!
        JMP     TASKLEVELCURSORUNLOCK
        PAGE
BACKSPACE       EQU     *       BACKSPACE THE CHARACTER CURSOR AND ERASE
        LDD     CURSORX         GET CURRENT CURSOR POSITION
        SUBD    #CHARWIDTH      BACK UP ONE CHARACTER WIDTH
        BCC     BACKSPACE1      B/ DIDN'T RUN OFF LEFT SIDE OF SCREEN
        LDD     #CHARLEFTSIDE   DID RUN OFF LEFT SIDE, STOP IT AT LEFT SIDE
BACKSPACE1      EQU     *
        STD     CURSORX         UPDATE CURSOR POSITION
        LDX     #CHARWIDTH      NOW STOMP ON THE CHARACTER
        LDD     #CHARHEIGHT
        JSR     BLANKREGION
CHCURSORLEFT    EQU     *       MOVE CHARACTER CURSOR LEFT
        LDD     CURSORX         GET CURRENT CURSOR POSITION
        SUBD    #CHARWIDTH      MOVE IT LEFT 6 DOT POSITIONS
        BCS     ENDLINE         GO IF RUNS OFF LEFT SIDE OF SCREEN
CHCURSORXSTAB   EQU     *       STORE (A,B) INTO CURSORX
        STD     CURSORX
        RTS

CHCURSORRIGHT   EQU     *       MOVE CURSOR ON CHARACTER POSITION TO THE RIGHT
        LDD     CURSORX         GET THE CURRENT CURSOR
        ADDD    #CHARWIDTH      ADVANCE TO RIGHT 6 COLUMNS
        CMPD    #(SCREENWIDTH/CHARWIDTH*CHARWIDTH-CHARWIDTH)/256
        BLS     CHCURSORXSTAB   GO IF UPDATED VALUE IS OK
CHCURSORXMAX    EQU     *       NEW VALUE FOR CURSOR IS PAST RIGHT SIDE OF SCRREN
        LDX     #(SCREENWIDTH/CHARWIDTH)*CHARWIDTH-CHARWIDTH-1
        STX     CURSORX         FORCE TO RIGHTMOST SCREEN CHARACTER POSITION
        RTS                     AND QUIT

ENDLINE EQU     *       END OF LINE SEEN ($0D)
        LDX     #CHARLEFTSIDE   MOVE CURSOR TO LEFT SIDE OF SCREEN
        STX     CURSORX         WITHOUT MOVING DOWN A ROW
        RTS                     GO PROCESS THE NEXT COMMAND
        PAGE
CHCURSORUP      EQU     *       MOVE CURSOR UP ONE CHARACTER ROW
        LDD     CURSORY         GET CURRENT ROW POSITION
        ADDD    #CHARHEIGHT     BUMP IT BY ONE CHARACTER ROW
        CMPD    #ScreenHgt-1 OFF TOP OF SCREEN ?
        BLS     CHCURSORYSTAB   GO STORE THE VALUE IF NOT OFF TOP OF SCREEN
        LDD     #ScreenHgt-1 OFF TOP OF SCREEN, MOVE BACK
CHCURSORYSTAB   EQU     *       STORE (A) INTO CURSORY
        STD     CURSORY         DO IT !
        RTS

CHCURSORDOWN    EQU     *       MOVE CURSOR DOWN ONE CHARACTER ROW
        LDD     CURSORY         GET CURRENT ROW POSITION
        SUBD    #CHARHEIGHT     MOVE DOWN SCREEN ONE CHARACTER ROW
        BCS     CHCURSORYMIN    OOPS, RAN OFF BOTTOM OF SCREEN
        CMPD    #CHARHEIGHT-1   NOT QUITE, STILL A CHARACTER ROW LEFT ?
        BCC     CHCURSORYSTAB   YES, GO STORE VALUE
CHCURSORYMIN    EQU     *       RAN OFF BOTTOM OF SCREEN, ROLL SCREEN
        SUBD    #CHARHEIGHT-1+(ScreenHgt-(ScreenHgt/CHARHEIGHT)*CHARHEIGHT)
*                               COMPUTE MINUS NUMBER OF LINES TO CLEAR
*
*       RollUp1Line -- ROLL SCREEN UP -(D) SCAN LINES AND CLEAR
*       SETS CURSORY TO CHARHEIGHT-1
*       (= LOWEST ROW ON SCREEN WHICH DOESN'T CHOP OFF PART OF A ROW AT THE TOP)
*
RollUp1Line  EQU     *
        NEGD
        PSHD                    SAVE # SCAN LINES TO CLEAR
        JSR     ModScrnSHIFT GO SHUFFLE THE DISPLAY BUFFER
        LDD     ,S              RESTORE # LINES TO CLEAR
        LDA     #NBROW
        MUL
        NEGD
        LDX     #SCREENTOP
        LEAX    D,X             = address of 1st screen line to clear
        PULD                    = # lines to clear
        JSR     CLEARLINES      GO ZERO THEM
        LDD     #CHARHEIGHT-1+(ScreenHgt-(ScreenHgt/CHARHEIGHT)*CHARHEIGHT)
*                               SET NEW CURSOR POSITION...
        STD     CURSORY         TO TOP OF BOTTOM CHARACTER LINE
        RTS                     WHEW! ALL DONE
        PAGE
*       MAKESPACE -- ROLLS SCREEN UP FOR OBJECT
*       DIMENSIONS: (X) IS SIZE IN X ($1FF IS MAXIMUM!)
*       (D) IS SIZE IN Y
*       ADJUSTS CURSORY UP APPROPRIATELY...
*       IF SCREEN IS ROLLED
*       CAUSE ERROR IF OBJECT WILL GO OFF RIGHT HAND SIDE OF SCREEN!
*
MAKESPACE       EQU     *
        STX     DELTAX          FOR CONVENIENCE TO THE CALLING ROUTINES
        STD     DELTAY
        SEC                     COMPUTE - # HORZ LINES LEFT BELOW OBJECT
        SBCB    CURSORY+1
        SBCA    CURSORY
        BLS     MAKESPACE1      GO IF ZERO OR MORE LINES LEFT
        JSR     ModScrnSHIFT OBJECT WILL GO OFF SCREEN, ROLL TO MAKE SPACE
*       NOW CLEAR THE SCREEN SPACE
MAKESPACE1      EQU     *
        LDD     CURSORX         COMPUTE WHERE CURSORX WILL BE...
        ADDD    DELTAX          AFTER DRAWING IS COMPLETE
        if      0
        CMPD    #SCREENWIDTH-1  ENOUGH SPACE TO RIGHT ?
        BLS     MAKESPACE2      YES, STORE NEW VALUE FOR X AND QUIT
        JMP     ERROR           WELL, YOU FIGURE THIS OUT
        fin
MAKESPACE2      EQU     *
        STD     NEWX            STORE NEW VALUE FOR CURSORX
        RTS
         page
*       DRAWBLANKLINE -- DRAWS A BLANK HORIZONTAL LINE
*       TARGETLEFT POINTS TO 1ST SCREEN BYTE
*       LEFTEND CONTAINS LEFT HAND END OF LINE MASK
*       PWIDTH CONTAINS WIDTH OF LINE IN BYTES
*       RIGHTEND CONTAINS RIGHTMOST MOST BYTE OF LINE MASK
*       IF ONLY ONE BYTE IS TO BE MODIFIED,
*       THEN LEFTEND = BYTE CONTENT MASK,...
*            AND RIGHTEND MUST BE ZERO
*
DRAWBLANKLINE   EQU     *
        LDA     CURRENTBACKGROUND IS BACKGROUND 1's or 0's?
        BNE     DRAWSOLIDLINE   B/ BACKGROUND is 1's
        LDX     TARGETLEFT      GET POINTER TO LEFTMOST BYTE OF LINE
        LDB     PWIDTH          GET WIDTH OF HORIZONTAL LINE
        LDAA    LEFTEND         GET LEFTMOST BYTE OF LINE
        COMA                    MAKE MASK OF BITS TO RETAIN
        ANDA    0,X             COMBINE (A) WITH SCREEN BYTE
        STAA    ,X+
        DECB                    ALL BYTES IN ROW HIT YET ?
        BEQ     DRAWBLANKRTS    B/ SPECIAL ONE BYTE CASE
        DECB                    TWO BYTE WIDE BLANK REGION ?
        BEQ     DRAWBLANKRTS    B/ SPECIAL ONE BYTE CASE
        DECB                    TWO BYTE WIDE BLANK REGION ?
        BEQ     DRAWBLANKLAST   B/ yes, go handle last byte
        CLRA                    GET ALL 0'S PATTERN
DRAWBLANKLOOP   EQU     *
        STA     ,X+             COMBINE (A) WITH SCREEN BYTE
        DECB                    ALL BYTES IN ROW HIT YET ?
        BNE     DRAWBLANKLOOP   NO
DRAWBLANKLAST ; re-enter here to handle two byte wide blank region
        LDAA    RIGHTEND        GET LAST BYTE BIT PATTERN
        COMA                    MAKE MASK OFEBITS TO RETAIN
        ANDA    0,X             AND DUMP INTO SCREEN MEMORY
        STAA    0,X
DRAWBLANKRTS
        RTS

DRAWSOLIDLINE   EQU     *
        LDX     TARGETLEFT      GET POINTER TO LEFTMOST BYTE OF LINE
        LDB     PWIDTH          GET WIDTH OF HORIZONTAL LINE
        LDAA    LEFTEND         GET LEFTMOST BYTE OF LINE
        ORAA    0,X             COMBINE (A) WITH SCREEN BYTE
        STAA    ,X+
        DECB                    ALL BYTES IN ROW HIT YET ?
        BEQ     DRAWSOLIDRTS    B/ SPECIAL ONE BYTE CASE
        DECB                    TWO BYTE WIDE BLANK REGION ?
        BEQ     DRAWSOLIDLAST   B/ yes, go handle last byte
        LDAA    #%11111111      GET ALL 1'S PATTERN
DRAWSOLIDLOOP   EQU     *
        STAA    ,X+             COMBINE (A) WITH SCREEN BYTE
        DECB                    ALL BYTES IN ROW HIT YET ?
        BNE     DRAWSOLIDLOOP   NO
DRAWSOLIDLAST ; re-enter here to handle two byte wide blank region
        LDAA    RIGHTEND        GET LAST BYTE BIT PATTERN
        ORAA    0,X             AND DUMP INTO SCREEN MEMORY
        STAA    0,X
DRAWSOLIDRTS
        RTS
        PAGE    BLANK REGION
BLANKREGION ; (X) CONTAINS BOX X SIZE, (D) CONTAINS Y SIZE
        BSR     BOXEDGE         GO COMPUTE BOX EDGES AND POINTERS
        BEQ     BLANKREGIONXIT  IF X DIMENSION IS ZERO, GET OUT!
BLANKLOOP       EQU     *       DRAW ONE ROW OF A BLANK BOX
        JSR     DRAWBLANKLINE   GO DRAW A BLANK HORIZONTAL LINE
        LDD     TARGETLEFT      NOW ADVANCE DOWN THE SCREEN A ROW
        ADDD    #NBROW
        STD     TARGETLEFT      UPDATE THE BOX LINE LEFT SIDE POINTER
        DEC     DELTAY+1        MORE LINES OF BOX TO DRAW ?
        BNE     BLANKLOOP       YES, GO DO ANOTHER
        LDX     NEWX            NOW ADVANCE CURSORX PAST THE BOX
        STX     CURSORX
BLANKREGIONXIT  EQU     *
        RTS                     AND QUIT
        PAGE    BOXEDGE SUBROUTINE

*       BOXEDGE -- SUBROUTINE TO COMPUTE POINTERS AND PIECES OF BOXES
*       USED BY SOLIDBOX AND EMPTYBOX
*
BOXEDGE ; (X) = SIZE IN X, (D) = SIZE IN Y
        JSR     MAKESPACE       MAKE ENOUGH ROOM ON SCREEN FOR BOX
        JSR     GENCURSORBYTE   FIND UPPER LEFT HAND CORNER OF BOX
        STX     TARGETLEFT      AND REMEMBER LEFT EDGE OF BOX
        PSHB                    SAVE BEGINNING BIT NUMBER
        LDX     #BITMSK         COMPUTE LEFT MOST BYTE OF BOX
        LDA     B,X             = SPECIFIED BIT W/ ALL BITS TO RIGHT TURNED ON
        STAA    LEFTCOLUMN      THIS IS FOR EMPTY BOX SIDES
        ASLA                    TURN ON ALL BITS TO RIGHT OF SPECIFIED BIT
        DECA                    NOW WE HAVE LEFTMOST BYTE OF SOLIDBOX
        STAA    LEFTEND         WE MAY NEED THIS A LOT...
        LDAB    NEWX+1          NOW WE MUST FIND RIGHTMOST BYTE OF EMPTYBOX
        DECB                    SINCE BOX DOES NOT ACTUALLY EXTEND TO NEWX
        ANDB    #$7             (JUST LIKE GENCURSORBYTE DOES IT)
        LDA     B,X             RIGHTEND HAS ALL BITS TO LEFT TURNED ON
        STAA    RIGHTCOLUMN     THIS IS RIGHT SIDE OF EMPTYBOX
        DECA                    TURN ON ALL THE BITS TO THE LEFT...
        COMA                    OF THE SPECIFIED BIT
        STAA    RIGHTEND        NOW WE HAVE RIGHTMOST BYTE OF SOLIDBOX
        PULB                    COMPUTE WIDTH OF BOX IN BYTES
        CLRA                    = CEILING(DELTAX + LEFT BIT # )
        ADDB    #7              (CEILING WE GET BY ROUNDING UP)
        ADDD    DELTAX          (THIS CAN BE AS LARGE AS 512+7+7)
        LSRD                    (DIVIDE NUMBER OF BITS BY 8)
        LSRD
        LSRD                    (B) = WIDTH OF BOX IN BYTES
        STAB    PWIDTH          SAVE WIDTH OF BOX
        CMPB    #1              IS BOX ONE BYTE WIDE ?
        BNE     BOXIT           NO, DON'T HAVE TO MASK DNDS TOGETHER
        LDAA    LEFTEND         YES, BOX <= 1 BYTE WIDE...
        ANDA    RIGHTEND        SO LEFT AND RIGHT ENDS OVERLAP
        STAA    LEFTEND         SET LEFT END MASK TO BOX PATTERN
        CLR     RIGHTEND        PREVENT THIS GUY FROM MUCKING UP THE WORKS
BOXIT   TSTB                    LOOK AT BYTE WIDTH OF BOX
        RTS                     AND EXIT WITH CC BIT Z SET
        page
SELECTEORMODE EQU *
        BSR     SETUPWRITE
        EORA    ,U
        STAA    ,U+
        RTS

SELECTIORMODE   EQU     *
        BSR     SETUPWRITE
        ORAA    ,U
        STAA    ,U+
        RTS

SELECTANDMODE   EQU     *
        BSR     SETUPWRITE
        COMA
        ANDA    ,U
        STAA    ,U+
        RTS

SETUPWRITE      EQU     *
        PULX                    POINTER TO SUBROUTINE TO COPY
        LDD     WRITEATOSCREEN GET OLD DISPLAY MODE
        STX     WRITEATOSCREEN REMEMBER NEW DISPLAY MODE
        RTS                     ALL DONE, GET OUT!

; Logically, this is what WRITEATOSCREEN is:
; WRITEATOSCREEN ; write bit pattern in (A) to screen at (X)
;       (A) placed on screen according to current display mode (XOR, IOR, AND)
;       Current display mode selected by changing 1st opcode byte(s)
;       of this routine
;       NOP                     this is changed to COMA for AND mode
;       EORA    ,U              combine bytes (changed to ORA for IOR mode)
;       STA     ,U+             store byte onto screen, advance pointer
;       RTS

SelBlkBkGrnd    ;call this routine to select black characters on white background
        clr     CurrentBackground
        rts

SelWhtBkGrnd    ;call this routine to select black characters on white background
        lda     #$ff
        sta     CurrentBackground
        rts

        PAGE
*
*       HOMEUP -- SET CURSOR TO TOP LEFT CORNER OF SCREEN [(0,0) Char cursor]
*
HOMEUP  EQU     *
        LDX     #CHARLEFTSIDE   = X POSITION OF HOME
        LDD     #CHARTOPSIDE    = Y POSITION OF HOME
        JMP     SETCURSORXY
*

ERASETOEOL ; erase to end of line
        LDD     CURSORX         save current cursor position
        PSHD
        NEGD                    compute distance from cursor to side of screen
        ADDD    #SCREENWIDTH
        TFR     D,X             = width of box to blank
        LDD     #CHARHEIGHT     = height of box to blank
        JSR     BLANKREGION     make region empty
        PULD                    set cursorx back to original value
        STD     CURSORX
        RTS                     all done!

CURSORERASE ; call here to make cursor go away
        lda     cursoron        ; is cursor displayed ?
        beq     CursorToggleRts ; b/ no, all done!
CURSORTOGGLE ; EOR CURSOR DISPLAY INTO SCREEN AT CURSOR LOCATION
        COM     CURSORON        remember whether cursor present on screen
        JSR     SelectEORMode   so successive passes install/erase cursor
        ; also, we want EOR mode in case Cursor sits on top of some char
        PSHD                    remember old display mode
        LDA     #$7F            rubout is cursor blotch
        JSR     DISPLAYCHAR
        LDD     CURSORX         backup cursor to point before display blotch
        SUBD    #CHARWIDTH
        STD     CURSORX
        PULX                    restore current display mode
        STX     WRITEATOSCREEN
CursorToggleRts
        RTS

ColorTermPatch
        rmb     200

CoCoCodeEnd

        FIN     IODRIVERBODY
