You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

684 lines
19 KiB

;
;==================================================================================================
; ANSI EMULATION MODULE
;==================================================================================================
;
; TODO:
; - SOME FUNCTIONS ARE NOT IMPLEMENTED!!!
;
ANSI_INIT:
PRTS("ANSI: RESET$")
;
JR ANSI_INI ; REUSE THE INI FUNCTION BELOW
;
;
;
ANSI_DISPATCH:
LD A,B ; GET REQUESTED FUNCTION
AND $0F ; ISOLATE SUB-FUNCTION
JR Z,ANSI_IN ; $30
DEC A
JR Z,ANSI_OUT ; $31
DEC A
JR Z,ANSI_IST ; $32
DEC A
JR Z,ANSI_OST ; $33
DEC A
JR Z,ANSI_CFG ; $34
CP 8
JR Z,ANSI_INI ; $38
CP 9
JR Z,ANSI_QRY ; $39
CALL PANIC
;
;==================================================================================================
; ANSI EMULATION MODULE BIOS FUNCTION ENTRY POINTS
;==================================================================================================
;
; READ A CHARACTER
;
ANSI_IN: ; JUST DEFER TO KEYBOARD
LD B,BF_VDAKRD ; SET FUNCTION TO KEYBOARD READ
JP EMU_VDADISP ; CHAIN TO VDA DISPATCHER
;
; WRITE A CHARACTER W/ EMULATION
;
ANSI_OUT:
LD A,E ; GET THE INCOMING CHARACTER
CP $20 ; $00-$1F IS C0
JP C,ANSI_C0DISP ; IF C0, DO C0 DISPATCH
CP $80 ; $20-$7F
JR C,ANSI_OUT1 ; HANDLE VIA STATE MACHINE
CP $A0 ; $80-$9F IS C1
JP C,ANSI_C1DISP ; IF C1, DO C1 DISPATCH
;
ANSI_OUT1: ; PROCESS OTHER CHARS VIA STATE MACHINE
LD HL,(ANSI_STATE) ; LOAD THE CURRENT STATE
CALL JPHL ; DO IT
XOR A ; SIGNAL SUCCESS
RET
;
; CHECK INPUT STATUS
;
ANSI_IST: ; DEFER TO KEYBOARD STATUS
LD B,BF_VDAKST ; SET FUNCTION TO KEYBOARD STATUS
JP EMU_VDADISP ; CHAIN TO VDA DISPATCHER
;
; CHECK OUTPUT STATUS
;
ANSI_OST: ; VIDEO OUTPUT IS *ALWAYS* READY
XOR A ; ZERO ACCUM
INC A ; A := $FF TO SIGNAL OUTPUT BUFFER READY
RET
;
; SET CONFIGURATION
;
ANSI_CFG:
XOR A ; SIGNAL SUCCESS
RET
;
; INITIALIZE
;
ANSI_INI:
; QUERY THE VIDEO DRIVER FOR SCREEN DIMENSIONS
LD B,BF_VDAQRY ; FUNCTION IS QUERY
LD HL,0 ; WE DO NOT WANT A COPY OF THE CHARACTER BITMAP DATA
CALL EMU_VDADISP ; PERFORM THE QUERY FUNCTION
LD (ANSI_DIM),DE ; SAVE THE SCREEN DIMENSIONS RETURNED
;
; INITIALIZE ALL WORKING VARIABLES
LD DE,0 ; DE := 0, CURSOR TO HOME POSITION 0,0
LD (ANSI_POS),DE ; SAVE CURSOR POSITION
LD HL,ANSI_STBASE ; SET STATE TO BASE
LD (ANSI_STATE),HL ; DO IT
;
; RESET THE CURRENT VIDEO DRIVER
LD B,BF_VDARES ; SET FUNCTION TO RESET
JP EMU_VDADISP ; RESET VDA AND RETURN
;
; QUERY STATUS
;
ANSI_QRY:
XOR A ; SIGNAL SUCCESS
RET
;
;==================================================================================================
; ANSI STATE MACHINE ENTRY POINTS
;==================================================================================================
;
ANSI_STBASE: ; STATE == BASE
JP ANSI_RENDER ; RENDER THE GLYPH
;
;
;
ANSI_STESC: ; STATE == ESCAPE SEQUENCE
RES 7,A ; CLEAR HIGH BIT
CP $30 ; $20 - $2F ARE PARAMETER CHARS
JP C,ANSI_COLLINT ; COLLECT INTERMEDIATE CHARACTERS
CP $7F ; $30 - $7E
RET NC ; IGNORE $7F
LD HL,ANSI_STBASE ; BASE STATE
LD (ANSI_STATE),HL ; SET IT
JP ANSI_ESCDISP ; DISPATCH FOR ESCAPE SEQUENCE
;
;
;
ANSI_STCTL: ; STATE == CONTROL SEQUENCE
RES 7,A ; CLEAR HIGH BIT
CP $30
JP C,ANSI_COLLINT ; COLLECT INTERMEDIATE CHARACTERS
CP $3C
JP C,ANSI_COLLPAR ; COLLECT PARAMETERS
CP $40
JP C,ANSI_COLLPRI ; COLLECT PRIVATE CHARACTERS
CP $7F ; $30 - $7E
RET NC ; IGNORE $7F
LD HL,ANSI_STBASE ; BASE STATE
LD (ANSI_STATE),HL ; SET IT
JP ANSI_CTLDISP ; DISPATCH FOR CONTROL SEQUENCE
;
;
;
ANSI_STSTR: ; STATE == STRING DATA
RET
;
;==================================================================================================
; ANSI C0 DISPATCHING
;==================================================================================================
;
ANSI_C0DISP:
CP $08 ; BS: BACKSPACE
JP Z,ANSI_BS
CP $0A ; LF: LINEFEED
JP Z,ANSI_LF
CP $0B ; VT: VERTICAL TAB
JP Z,ANSI_LF ; TREAD AS LINEFEED
CP $0C ; FF: FORMFEED
JP Z,ANSI_LF ; TREAT AS LINEFEED
CP $0D ; CR: CARRIAGE RETURN
JP Z,ANSI_CR
CP $18 ; CAN: CANCEL
JP Z,ANSI_CAN
CP $1A ; SUB: ???
JP Z,ANSI_SUB
CP $1B ; ESC: ESCAPE
JP Z,ANSI_ESC
RET
;
;==================================================================================================
; ANSI C1 DISPATCHING
;==================================================================================================
;
ANSI_C1DISP:
CP $9B ; CSI: CONTROL SEQ INTRODUCER
JP Z,ANSI_CSI ; HANDLE IT
;
; IGNORE OTHERS
RET
;
;==================================================================================================
; ANSI ESCAPE SEQUENCE DISPATCHING
;==================================================================================================
;
ANSI_ESCDISP:
CP $60 ; $40-$5F
JR NC,ANSI_ESCDISP1 ; NOPE, CONTINUE
;
; $40-$5F MAP TO $80-$9F IN C1 RANGE
CALL ANSI_CLEAR ; CLEAR STATE RELATED VARIABLES
LD HL,ANSI_STBASE ; BASE STATE
LD (ANSI_STATE),HL ; SET IT
ADD A,$40 ; MAP $40-$5F -> $80-$9F
JP ANSI_C1DISP ; PROCESS AS C1 CHARACTER
;
ANSI_ESCDISP1:
; CONTINUE ESCAPE SEQ DISPATCHING
; *DEBUG*
PRTS("<ESC>($")
PUSH AF
LD A,(ANSI_INT)
OR A
CALL NZ,COUT
CALL PC_COMMA
POP AF
CALL COUT
CALL PC_RPAREN
RET
;
;==================================================================================================
; ANSI CONTROL SEQUENCE DISPATCHING
;==================================================================================================
;
ANSI_CTLDISP:
CP 'H' ; CUP: CURSOR POSITION
JP Z,ANSI_CUP
CP 'J' ; ED: ERASE IN DISPLAY
JP Z,ANSI_ED
CP 'K' ; EL: ERASE IN LINE
JP Z,ANSI_EL
CP 'f' ; HVP: HORIZONTAL/VERTICAL POSITION
JP Z,ANSI_CUP
CP 'm' ; SGR: SELECT GRAPHIC RENDITION
JP Z,ANSI_SGR
; *DEBUG*
PUSH AF
PRTS("<CTL>($")
LD A,(ANSI_PRI)
OR A
CALL NZ,COUT
CALL PC_COMMA
LD DE,ANSI_PARLST
LD A,(ANSI_PARIDX)
INC A
CALL PRTHEXBUF
CALL PC_COMMA
LD A,(ANSI_INT)
OR A
CALL NZ,COUT
CALL PC_COMMA
POP AF
CALL COUT
CALL PC_RPAREN
RET
;
;==================================================================================================
; ANSI PROTOCOL SUPPORT FUNCTIONS
;==================================================================================================
;
; CLEAR THE WORKING VARIABLES AT START OF NEW ESC/CTL SEQUENCE
;
ANSI_CLEAR:
PUSH AF ; PRESERVE AF
LD HL,ANSI_VARS ; POINT TO VARS
LD B,ANSI_VARLEN ; B := NUMBER OF BYTES TO CLEAR
XOR A ; A := 0
;
ANSI_CLEAR1: ; LOOP
LD (HL),A ; CLEAR THE BYTE
INC HL ; BUMP POINTER
DJNZ ANSI_CLEAR1 ; LOOP AS NEEDED
;
POP AF ; RECOVER AF
RET ; DONE
;
; COLLECT INTERMEDIATE CHARACTERS
; WE DO NOT SUPPORT MORE THAN 1 WHICH IS ALL THAT IS EVER
; USED BY THE STANDARD. IF MORE THAN ONE RECEIVED, IT IS OVERLAID
;
ANSI_COLLINT:
LD (ANSI_INT),A ; RECORD INTERMEDIATE CHAR
RET ; DONE
;
; COLLECT PARAMETERS
; ';' SEPARATES PARAMETERS
; '0'-'9' ARE DIGITS OF CURRENT PARAMETER
;
ANSI_COLLPAR:
; HANDLE SEPARATOR
CP $3B ; ';' SEPARATOR?
JR NZ,ANSI_COLLPAR1 ; NOPE, CONTINUE
LD A,(ANSI_PARIDX) ; GET CURRENT PARM POS INDEX
INC A ; INCREMENT
AND $0F ; 16 PARMS MAX!!!
LD (ANSI_PARIDX),A ; SAVE IT
RET ; DONE
;
ANSI_COLLPAR1: ; HANDLE '0'-'9'
CP '9' + 1 ; > '9'?
RET NC ; YUP, IGNORE CHAR
SUB '0' ; CONVERT TO BINARY VALUE
LD B,A ; SAVE VALUE IN B
LD A,(ANSI_PARIDX) ; A := CURRENT PARM INDEX
LD HL,ANSI_PARLST ; POINT TO START OF PARM LIST
LD DE,0 ; SETUP DE := 0
LD E,A ; NOW DE := PARM OFFSET
ADD HL,DE ; NOW HL := PARM BYTE TO UPDATE
LD A,(HL) ; GET CURRENT VALUE
LD C,A ; COPY TO C
RLCA ; MULTIPLY BY 10
RLCA ; "
ADD A,C ; "
RLCA ; "
ADD A,B ; ADD NEW DIGIT
LD (HL),A ; SAVE UPDATED VALUE
RET ; DONE
;
; COLLECT PRIVATE CHARACTERS
; WE DO NOT SUPPORT MORE THAN 1 WHICH IS ALL THAT IS EVER
; USED BY THE STANDARD. IF MORE THAN ONE RECEIVED, IT IS OVERLAID
;
ANSI_COLLPRI:
LD (ANSI_PRI),A ; RECORD THE PRIVATE CHARACTER
RET ; DONE
;
; CANCEL AN ESC/CTL SEQUENCE IN PROGRESS
; SOME VT TERMINALS WILL SHOW AN ERROR SYMBOL IN THIS CASE
;
ANSI_SUB:
; DISPLAY AN ERR SYMBOL???
;
; CANCEL AN ESC/CTL SEQUENCE IN PROGRESS
;
ANSI_CAN:
LD HL,ANSI_STBASE ; SET STATE TO BASE
LD (ANSI_STATE),HL ; SAVE IT
RET
;
; START AN ESC SEQ, CANCEL ANY ESC/CTL SEQUENCE IN PROGRESS
;
ANSI_ESC:
CALL ANSI_CLEAR ; CLEAR STATE RELEATED VARIABLES
LD HL,ANSI_STESC ; SET STATE TO ESCAPE SEQUENCE
LD (ANSI_STATE),HL ; SAVE IT
RET
;
; START A CTL SEQ
;
ANSI_CSI:
CALL ANSI_CLEAR ; CLEAR STATE RELEATED VARIABLES
LD HL,ANSI_STCTL ; SET STATE TO CONTROL SEQUENCE
LD (ANSI_STATE),HL ; SAVE IT
RET
;
;==================================================================================================
; ANSI FUNCTION EXECUTION
;==================================================================================================
;
ANSI_RENDER:
LD B,BF_VDAWRC ; FUNC := WRITE CHARACTER
CALL EMU_VDADISP ; SPIT OUT THE RAW CHARACTER
LD A,(ANSI_COL) ; GET CUR COL
INC A ; INCREMENT
LD (ANSI_COL),A ; SAVE IT
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
CP E ; COMPARE TO COLS IN LINE
RET C ; NOT PAST END OF LINE, ALL DONE
CALL ANSI_CR ; CARRIAGE RETURN
JR ANSI_LF ; LINEFEED AND RETURN
;
ANSI_FF:
LD DE,0 ; PREPARE TO HOME CURSOR
LD (ANSI_POS),DE ; SAVE NEW CURSOR POSITION
CALL ANSI_XY ; EXECUTE
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
LD H,D ; SET UP TO MULTIPLY ROWS BY COLS
CALL MULT8 ; HL := H * E TO GET TOTAL SCREEN POSITIONS
LD E,' ' ; FILL SCREEN WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
CALL EMU_VDADISP ; PERFORM FILL
JP ANSI_XY ; HOME CURSOR AND RETURN
;
ANSI_BS:
LD DE,(ANSI_POS) ; GET CURRENT ROW/COL IN DE
LD A,E ; GET CURRENT COLUMN
CP 1 ; COMPARE TO COLUMN 1
RET C ; LESS THAN 1, NOTHING TO DO
DEC E ; POINT TO PREVIOUS COLUMN
LD (ANSI_POS),DE ; SAVE NEW COLUMN VALUE
CALL ANSI_XY ; MOVE CURSOR TO NEW TARGET COLUMN
LD E,' ' ; LOAD A SPACE CHARACTER
LD B,BF_VDAWRC ; SET FUNCTION TO WRITE CHARACTER
CALL EMU_VDADISP ; OVERWRITE WITH A SPACE CHARACTER
JP ANSI_XY ; NEED TO MOVE CURSOR BACK TO NEW TARGET COLUMN
;
ANSI_CR:
XOR A ; ZERO ACCUM
LD (ANSI_COL),A ; COL := 0
JP ANSI_XY ; REPOSITION CURSOR AND RETURN
;
ANSI_LF:
LD A,(ANSI_ROW) ; GET CURRENT ROW
INC A ; BUMP TO NEXT
LD (ANSI_ROW),A ; SAVE IT
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
CP D ; COMPARE TO SCREEN ROWS
JP C,ANSI_XY ; NOT PAST END, ALL DONE
DEC D ; D NOW HAS MAX ROW NUM (ROWS - 1)
SUB D ; A WILL NOW HAVE NUM LINES TO SCROLL
LD E,A ; LINES TO SCROLL -> E
LD B,BF_VDASCR ; SET FUNCTION TO SCROLL
CALL EMU_VDADISP ; DO THE SCROLLING
LD A,(ANSI_ROWS) ; GET SCREEN ROW COUNT
DEC A ; A NOW HAS LAST ROW
LD (ANSI_ROW),A ; SAVE IT
JP ANSI_XY ; RESPOSITION CURSOR AND RETURN
;
;
;
ANSI_ED: ; ERASE IN DISPLAY
LD A,(ANSI_PARLST + 0) ; GET FIRST PARM
CP 0 ; ERASE CURSOR TO EOS
JR Z,ANSI_ED1
CP 1 ; ERASE START THRU CURSOR
JR Z,ANSI_ED2
CP 2 ; ERASE FULL DISPLAY?
JR Z,ANSI_ED3
RET ; INVALID?
;
ANSI_ED1: ; ERASE CURSOR THRU EOS
LD DE,(ANSI_POS) ; GET CURSOR POSITION
CALL ANSI_POS2IDX ; HL NOW HAS CURSOR INDEX
PUSH HL ; SAVE IT
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
LD E,0 ; COL POSITION := 0
CALL ANSI_POS2IDX ; HL NOW HAS EOS INDEX
POP DE ; RECOVER CURSOR POS INDEX
OR A ; CLEAR CARRY
SBC HL,DE ; SUBTRACT CURSOR INDEX FROM EOS INDEX
LD E,' ' ; FILL WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
JP EMU_VDADISP ; PERFORM FILL AND RETURN
;
ANSI_ED2: ; ERASE START THRU CURSOR
LD DE,0 ; CURSOR TO 0,0 FOR NOW
LD B,BF_VDASCP ; SET FUNCTION TO SET CURSOR POSITION
CALL EMU_VDADISP ; DO IT
LD DE,(ANSI_POS) ; GET ORIGINAL CURSOR POSITION
CALL ANSI_POS2IDX ; HL NOW HAS INDEX
INC HL ; ADD 1 POSITION TO ERASE THRU CURSOR POSITION
LD E,' ' ; FILL WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
CALL EMU_VDADISP ; DO IT
JP ANSI_XY ; RESTORE CURSOR AND RETURN
;
ANSI_ED3: ; ERASE FULL DISPLAY
LD DE,(ANSI_POS) ; GET CURSOR POS
PUSH DE ; SAVE IT
LD DE,0 ; PREPARE TO HOME CURSOR
LD (ANSI_POS),DE ; SAVE NEW CURSOR POSITION
CALL ANSI_XY ; EXECUTE
CALL ANSI_ED1 ; ERASE THRU EOS
POP DE ; RECOVER CURSOR POS
LD (ANSI_POS),DE ; SAVE IT
JP ANSI_XY ; UPDATE CURSOR AND RETURN
;
;
;
ANSI_EL: ; ERASE IN LINE
LD A,(ANSI_PARLST + 0) ; GET FIRST PARM
CP 0 ; ERASE CURSOR TO EOL
JR Z,ANSI_EL1
CP 1 ; ERASE START THRU CURSOR
JR Z,ANSI_EL2
CP 2 ; ERASE FULL LINE?
JR Z,ANSI_EL3
RET ; INVALID?
;
ANSI_EL1: ; ERASE CURSOR THRU EOL
LD DE,(ANSI_POS) ; GET CURSOR POSITION
CALL ANSI_POS2IDX ; HL NOW HAS CURSOR INDEX
PUSH HL ; SAVE IT
LD DE,(ANSI_POS) ; GET CURSOR POSITION
LD E,0 ; COL POSITION := 0
INC D ; ROW := ROW + 1
CALL ANSI_POS2IDX ; HL NOW HAS EOL INDEX
POP DE ; RECOVER CURSOR POS INDEX
OR A ; CLEAR CARRY
SBC HL,DE ; SUBTRACT CURSOR INDEX FROM EOL INDEX
LD E,' ' ; FILL WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
JP EMU_VDADISP ; PERFORM FILL AND RETURN
;
ANSI_EL2: ; ERASE START THRU CURSOR
LD DE,(ANSI_POS) ; GET CURSOR POS
LD E,0 ; COL := 0, START OF ROW
LD B,BF_VDASCP ; SET FUNCTION TO SET CURSOR POSITION
CALL EMU_VDADISP ; DO IT
LD HL,(ANSI_POS) ; GET ORIGINAL CURSOR POSITION
LD H,0 ; ONLY ERASE COLUMNS
INC HL ; ADD 1 POSITION TO ERASE THRU CURSOR POSITION
LD E,' ' ; FILL WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
CALL EMU_VDADISP ; DO IT
JP ANSI_XY ; RESTORE CURSOR AND RETURN
;
ANSI_EL3: ; ERASE FULL LINE
LD DE,(ANSI_POS) ; GET CURSOR POS
PUSH DE ; SAVE IT
LD E,0 ; CURSOR TO START OF LINE
LD (ANSI_POS),DE ; SAVE NEW CURSOR POSITION
CALL ANSI_XY ; EXECUTE
CALL ANSI_EL1 ; ERASE THRU EOL
POP DE ; RECOVER CURSOR POS
LD (ANSI_POS),DE ; SAVE IT
JP ANSI_XY ; UPDATE CURSOR AND RETURN
;
;
;
ANSI_HVP: ; HORIZONTAL/VERTICAL POSITION
ANSI_CUP: ; CURSOR UPDATE
;
; HANDLE ROW NUMBER
LD A,(ANSI_PARLST + 0) ; ROW PARM
DEC A ; ADJUST FOR ZERO OFFSET
JP P,ANSI_CUP1 ; 0 OR MORE, OK, CONTINUE
XOR A ; NEGATIVE, FIX IT
ANSI_CUP1:
LD HL,ANSI_ROWS ; HL POINTS TO ROW COUNT
CP (HL) ; COMPARE TO ROW COUNT
JR C,ANSI_CUP2 ; IN BOUNDS, CONTINUE
LD A,(HL) ; FIX IT, LOAD ROW COUNT
DEC A ; SET TO LAST ROW NUM
ANSI_CUP2:
LD D,A ; COMMIT ROW NUMBER TO D
;
; HANDLE COL NUMBER
LD A,(ANSI_PARLST + 1) ; COL PARM
DEC A ; ADJUST FOR ZERO OFFSET
JP P,ANSI_CUP3 ; 0 OR MORE, OK, CONTINUE
XOR A ; NEGATIVE, FIX IT
ANSI_CUP3:
LD HL,ANSI_COLS ; HL POINTS TO COL COUNT
CP (HL) ; COMPARE TO COL COUNT
JR C,ANSI_CUP4 ; IN BOUNDS, CONTINUE
LD A,(HL) ; FIX IT, LOAD COL COUNT
DEC A ; SET TO LAST COL NUM
ANSI_CUP4:
LD E,A ; COMMIT COL NUMBER TO E
;
; COMMIT THE NEW CURSOR POSITION AND RETURN
LD (ANSI_POS),DE ; SAVE IT
JP ANSI_XY ; UPDATE CURSOR AND RETURN
;
;
;
ANSI_SGR: ; SET GRAPHIC RENDITION
LD A,(ANSI_PARIDX) ; GET CURRENT PARM INDEX
INC A ; INC TO MAKE IT THE COUNT
LD B,A ; B IS NOW LOOP COUNTER
LD HL,ANSI_PARLST ; HL POINTS TO START OF PARM LIST
;
ANSI_SGR1: ; PROCESSING LOOP
PUSH BC ; PRESERVE BC
PUSH HL ; PRESERVE HL
LD A,(HL)
CALL ANSI_SGR2 ; HANDLE PARM
POP HL ; RESTORE HL
POP BC ; RESTORE BC
INC HL ; POINT TO NEXT PARM
DJNZ ANSI_SGR1 ; LOOP TILL DONE
;
; NOW IMPLEMENT ALL CHANGES
LD A,(ANSI_ATTR) ; GET THE ATTRIBUTE VALUE
LD E,A ; MOVE TO E
LD B,BF_VDASAT ; SET ATTRIBUTE FUNCTION
CALL EMU_VDADISP ; CALL THE FUNCTION
LD A,(ANSI_COLOR) ; GET THE COLOR VALUE
LD E,A ; MOVE TO E
LD B,BF_VDASCO ; SET ATTRIBUTE FUNCTION
CALL EMU_VDADISP ; CALL THE FUNCTION
RET ; RETURN
;
ANSI_SGR2: ; HANDLE THE REQUEST CODE
CP 0 ; ALL OFF
JR Z,ANSI_SGR_OFF ; DO IT
CP 1 ; BOLD
JR Z,ANSI_SGR_BOLD ; DO IT
CP 4 ; UNDERLINE
JR Z,ANSI_SGR_UL ; DO IT
CP 7 ; REVERSE
JR Z,ANSI_SGR_REV ; DO IT
CP 30 ; START OF FOREGROUND
RET C ; OUT OF RANGE
CP 38 ; END OF RANGE
JR C,ANSI_SGR_FG ; SET FOREGROUND
CP 40 ; START OF BACKGROUND
RET C ; OUT OF RANGE
CP 48 ; END OF RANGE
JR C,ANSI_SGR_BG ; SET BACKGROUND
RET ; OTHERWISE OUT OF RANGE
;
ANSI_SGR_OFF:
XOR A ; ZERO ACCUM
LD (ANSI_ATTR),A ; CLEAR ATTRIBUTES
LD A,7 ; WHITE ON BLACK
LD (ANSI_COLOR),A ; RESET COLOR
RET
;
ANSI_SGR_BOLD:
LD A,(ANSI_COLOR) ; LOAD CURRENT COLOR
OR %00001000 ; SET BOLD BIT
LD (ANSI_COLOR),A ; SAVE IT
RET
;
ANSI_SGR_UL:
LD A,(ANSI_ATTR) ; LOAD CURRENT ATTRIBUTE
OR %00000010 ; SET UNDERLINE BIT
LD (ANSI_ATTR),A ; SAVE IT
RET
;
ANSI_SGR_REV:
LD A,(ANSI_ATTR) ; LOAD CURRENT ATTRIBUTE
OR %00000100 ; SET REVERSE BIT
LD (ANSI_ATTR),A ; SAVE IT
RET
;
ANSI_SGR_FG:
SUB 30
LD E,A
LD A,(ANSI_COLOR)
AND %11111000
OR E
LD (ANSI_COLOR),A
RET
;
ANSI_SGR_BG:
SUB 40
RLCA
RLCA
RLCA
RLCA
LD E,A
LD A,(ANSI_COLOR)
AND %10001111
OR E
LD (ANSI_COLOR),A
RET
;
;==================================================================================================
; SUPPORT FUNCTIONS
;==================================================================================================
;
ANSI_XY:
LD DE,(ANSI_POS) ; GET THE DESIRED CURSOR POSITION
LD B,BF_VDASCP ; SET FUNCTION TO SET CURSOR POSITION
JP EMU_VDADISP ; REPOSITION CURSOR
;
; CONVERT XY COORDINATES IN DE INTO LINEAR INDEX IN HL
; D=ROW, E=COL
;
ANSI_POS2IDX:
PUSH DE
LD HL,(ANSI_DIM) ; GET DIMENSIONS
LD H,L ; COLS -> H
LD E,D ; ROW NUM -> E
CALL MULT8 ; HL := H * E (ROW OFFSET)
POP DE ; RECOVER ORIGINAL ROW/COL
LD D,0 ; GET RID OF ROW COUNT
ADD HL,DE ; ADD COLUMN OFFSET
RET ; RETURN, HL HAS INDEX
;
;==================================================================================================
; WORKING DATA STORAGE
;==================================================================================================
;
ANSI_POS:
ANSI_COL .DB 0 ; CURRENT COLUMN - 0 BASED
ANSI_ROW .DB 0 ; CURRENT ROW - 0 BASED
;
ANSI_DIM:
ANSI_COLS .DB 80 ; NUMBER OF COLUMNS ON SCREEN
ANSI_ROWS .DB 24 ; NUMBER OF ROWS ON SCREEN
;
ANSI_STATE .DW PANIC ; CURRENT FUNCTION FOR STATE MACHINE
;
ANSI_VARS:
ANSI_PRI .DB 0 ; PRIVATE CHARACTER RECORDED HERE
ANSI_INT .DB 0 ; INTERMEDIATE CHARACTER RECORDED HERE
ANSI_PARIDX .DB 0 ; NUMBER OF PARAMETERS RECORDED
ANSI_PARLST .FILL 16,0 ; PARAMETER VALUE LIST (UP TO 16 BYTE VALUES)
ANSI_VARLEN .EQU $ - ANSI_VARS
;
ANSI_ATTR .DB 0 ; CURRENT CHARACTER ATTRIBUTE
ANSI_COLOR .DB 7 ; CURRENT CHARACTER COLOR