From c0528a05f7a804d5b339b21c4875c14e1e306074 Mon Sep 17 00:00:00 2001 From: doug Date: Wed, 28 Nov 2012 23:15:35 +0000 Subject: [PATCH] assembles but is incomplete --- branches/dwg/Source/ansi.asm | 216 +++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 9 deletions(-) diff --git a/branches/dwg/Source/ansi.asm b/branches/dwg/Source/ansi.asm index b6a989b4..16f0ed93 100644 --- a/branches/dwg/Source/ansi.asm +++ b/branches/dwg/Source/ansi.asm @@ -3,13 +3,167 @@ ; ANSI EMULATION MODULE ;================================================================================================== ; -; TODO: -; - THIS IS CURRENTLY JUST A CLONE OF TTY.ASM! NEEDS A REAL IMPLEMENTATION! -; - SOME FUNCTIONS ARE NOT IMPLEMENTED! -; + +; The ANSI handler is a superset of the TTY handler in that is does simple +; processing of control characters such as CR, LF... But in addition is Hasbro +; a state machine driven escape sequence parser that accepts parameters and +; command characters and builds a table of data required to perform the indicated +; operation. + +; For instance, a screen clear escaper sequence such as [2J is parsed as +; a leading CSI ()escape which places us in state1 (waiting for [ ). When the +; next character arrives and turns out to be [, the parser's next state is +; state2. + +; State2 processing is a little more complex. If the next character is a numeral, +; it is placed in the parameter1 buffer and the next state is state3 (collecting +; parameter1). + +; State3 processing implies that the buffer already has 1 byte of a parameter in +; the parameter1 buffer. If the next character is a semi-colon, that implies that +; the parameter1 buffer is complete and the next state should be state4. If the +; next byte is a numeral, it is appended to the parameter1 buffer and we stay INC +; state3. If the nect character is a semi-colon, that indicates the parameter1 is +; complete and we need to enter state4 to begin collection of parameter2. If the +; next character is neither a numeral or a semi-colon, then it needs +; to be decoded as a command. Commands result in the calling of low-level driver +; functions to perform the indicated operation. Subsequently we return to state0. + +; State4 processing implies we are collecting parameter2 data. If the next byte +; is a numeral, it is assigned to the parameter2 buffer. In this case we go to +; state5 which is used to finish collection of parameter2. + +; State5 processing is for collecting additional parameter2 bytes to be appended +; to the parameter2 buffer. When a non-numeral arrives, that implies that parameter2 +; is complete and the new character is either a semi-colon or the awaited command +; character. If it is a semi-colon, that would imply the existance of a parameter3, +; which may or may not be supported in this implementation. If it is the command +; character, then the propper low-level driver calls need to be invoked to perform +; the desired operations on the video screen. + +; Once state5 is complete, we re-enter state0. + +ANSI_ERR1 .EQU 1 + + +ANSI_CMD_DISP: + LD A,B + CP 'J' + JR ANSI_CMD_NOT_CRTCLR + + ; THIS IS THE CRTCLR FUNCTIONAL CODE + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + LD DE,0 ; row 0 column 0 + LD B,BF_VDASCP ; FUNCTION IS SET CURSOR POSITION + CALL EMU_VDADISP ; CALL THE VIDEO HARDWARE DRIVER + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + LD DE,0 ; row 0 column 0 + LD B,BF_VDAQRY ; FUNCTION IS QUERY FOR SCREEN SIZE + LD HL,0 ; WE DO NOT WANT A COPY OF THE CHARACTER BITMAP DATA + CALL EMU_VDADISP ; PERFORM THE QUERY FUNCTION + ; on return, D=row count, E=column count + ; for the fill call, we need hl=number of chars to fill + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + LD E,' ' ; fill with spaces + ; + LD A,(ANSI_ROWS) ; given A = number of rows + CALL N8V_OFFSET ; return HL = num_rows * num_cols + ; + LD B,BF_VDAFIL ; FUNCTION IS FILL + CALL EMU_VDADISP ; PERFORM THE QUERY FUNCTION + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + XOR A + RET ; return SUCCESS to caller + ; +ANSI_CMD_NOT_CRTCLR: + + CP 66h ; is it cursor position? + JR ANSI_CMD_NOT_CRTLC + +ANSI_CMD_NOT_CRTLC: + +; since only the crtclr and crtlc are supported right now... +; any other command is an error + CALL PANIC ; A has the unknown command byte + +;------------------------------------------------------------------------------------ +ANSI_IS_NUMERAL: + RET + +;------------------------------------------------------------------------------------ +ANSI_IS_ALPHA: + RET +;------------------------------------------------------------------------------------ +ANSI_MARSHALL_PARM1: + RET +;------------------------------------------------------------------------------------ +ANSI_MARSHALL_PARM2: + RET +;------------------------------------------------------------------------------------ +ANSI_PROC_COMMAND: + RET +;------------------------------------------------------------------------------------ + + +ANSI_STATE1: + ; Waiting for [ + ; (the only valid character to follow an ESC would be the [ ) + ; (if we get something else, we go back to state0 and begin again) + LD A,B + CP '[' + JR NZ,ANSI_STATE1_ERR ; if not the expected [, go around + LD HL,ANSI_STATE2 ; having found the [, set the next state + LD (ANSI_STATE),HL ; to state2 (waiting for a parm1 char). + XOR A ; set retcode to SUCCESS + RET ; and return to caller +ANSI_STATE1_ERR: + LD HL,ANSI_STATE0 + LD (ANSI_STATE),HL ; set next state to state 0 + LD A,ANSI_ERR1 ; "state1 expected [ not found" + RET + +;------------------------------------------------------------------------------------ + +ANSI_STATE2: + ; waiting for parm1 + LD A,B + CALL ANSI_IS_NUMERAL + JR NZ,ANSI_STATE2_NOT_NUMERAL + CALL ANSI_MARSHALL_PARM1 + XOR A ; set SUCCESS return code + RET +ANSI_STATE2_NOT_NUMERAL: + LD A,B + CP 59 ; semi-colon + JR NZ,ANSI_STATE2_NOT_SEMI + LD HL,ANSI_STATE3 + LD (ANSI_STATE),HL ; set next state to waiting for parm2 + XOR A + RET ; return SUCCESS +ANSI_STATE2_NOT_SEMI: + ; if it is not a semi, or a numeral, it must be a command char + LD HL,ANSI_STATE0 ; after we do the command dispatcher, the + LD (ANSI_STATE),HL ; next state we will want is the default state + JP ANSI_CMD_DISP + ANSI_INIT: JR ANSI_INI ; REUSE THE INI FUNCTION BELOW ; + +ANSI_STATE3: + ; waiting for parm2 + LD A,B + CALL ANSI_IS_NUMERAL + JR NZ,ANSI_STATE3_NOT_NUMERAL + CALL ANSI_MARSHALL_PARM2 + XOR A + RET +ANSI_STATE3_NOT_NUMERAL: + LD A,B + CALL ANSI_PROC_COMMAND + LD HL,ANSI_STATE0 + LD (ANSI_STATE),HL + RET ; ; ANSI_DISPATCH: @@ -39,9 +193,13 @@ ANSI_IN: ; ; ANSI_OUT: - CALL ANSI_DOCHAR ; HANDLE THE CHARACTER (EMULATION ENGINE) - XOR A ; SIGNAL SUCCESS - RET + LD HL,(ANSI_STATE) + JP (HL) + +;; CALL ANSI_DOCHAR ; HANDLE THE CHARACTER (EMULATION ENGINE) +;; XOR A ; SIGNAL SUCCESS +;; RET + ; ; ; @@ -65,6 +223,9 @@ ANSI_CFG: ; ; ANSI_INI: + LD HL,ANSI_STATE0 ; load the address of the default state function + LD (ANSI_STATE),HL ; and place it in the ANSI_STATE variable for later. + 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 @@ -82,7 +243,33 @@ ANSI_QRY: ; ; ; -ANSI_DOCHAR: + + + ; This is probably the best place to insert a state sensitive + ; dispatcher for handling ANSI escape sequences. Ansi sequences + ; are unusual because they contain a number of parameters + ; subsequently followed by a command character that comes last. + + ; It is wise to create a list of supported sequences so we know + ; before writing the parser what the most complex sequence will + ; consist of. + + ; RomWBW utilities written by Douglas Goodall only use several + ; sequences. A screen clear, and a cursor position. + ; + ; crtclr() uses [2J + ; crtlc() uses [;<0x66> + + ; Programs such as wordstar use more complex operations. + ; + ; +;; ANSI_DOCHAR: +ANSI_STATE0: + ; ANSI_STATE0 is the default state where random output characters May + ; be normal visible characters, a control character such as BS, CR, LF... + ; or a CSI such as an escape character (27). + + LD A,E ; CHARACTER TO PROCESS CP 8 ; BACKSPACE JR Z,ANSI_BS @@ -92,6 +279,15 @@ ANSI_DOCHAR: JR Z,ANSI_CR CP 10 ; LINEFEED JR Z,ANSI_LF + + CP 27 ; ESCAPE ; This is the hook into the escape handler + JR Z,ANSI_NOT_ESC ; go around if not CSI + LD HL,ANSI_STATE1 + LD (ANSI_STATE),HL + XOR A ; setup SUCCESS as return status + RET +ANSI_NOT_ESC: + CP 32 ; COMPARE TO SPACE (FIRST PRINTABLE CHARACTER) RET C ; SWALLOW OTHER CONTROL CHARACTERS LD B,BF_VDAWRC @@ -157,7 +353,9 @@ ANSI_XY: LD B,BF_VDASCP ; SET FUNCTIONT TO SET CURSOR POSITION JP EMU_VDADISP ; REPOSITION CURSOR ; -; +; The ANSI_STATE variable (word) contains the +; address of the next state function +ANSI_STATE .DW ANSI_STATE0 ; by default, ANSI_STATE0 ; ANSI_POS: ANSI_COL .DB 0 ; CURRENT COLUMN - 0 BASED