Files
RomWBW/Source/HBIOS/ansi.asm
b1ackmai1er 78f65522b7 Dev (#108)
* added hack to handle tunes

* quiet clean

* added chmod for execution

* suppress warnings

* Multi-boot fixes

* the windows build somehow thinks that these filesystems are cpm3.

* credit and primitive instructions

* Update sd.asm

Cosmetic fix.

* make compile shut up about conditionals

* Add bin2asm for linus and update build to process font files under linix

* fixed quoted double quote bug, added tests

* added tests

* added bin2asm for font file source creation

* Revert linux bin2asm font stuff

* added rule for font source generation

* build fonts

* added directory mapping cache.  if the same directory is being hit
as last run, we don't need to rebuild the map.  will likely break if
you are running more than one at a time, in that the cache will be
ineffective.  also, if the directory contents change, this will also break.

* removed strip.  breaks osx

* added directory tag so . isn't matched all over the place

* added real cache validation

* fixed build

* this file is copied from optdsk.lib or optcmd.lib

* install to ../HBIOS

* prerequisite verbosity

* diff soft failure and casefn speedup

* added lzsa

* added lzsa

* removed strip. breaks on osx

* added clobber

* added code to handle multiple platform rom builds with rom size override

* added align and 0x55 hex syntax

* default to hd64180

* added N8 capability

* added SBC_std.rom to default build

* added support for binary diff

* diff fixes

* clean, identical build.  font source generator emitted .align.  this does not match the windows build

* Upgrade NZCOM to latest

* Misc. Cleanup

* fixed expression parser bug : ~(1|2) returned 0xfe

* added diff build option

* Update Makefile

Makefile enhancement to better handle ncurses library from Bob Dunlop.

* Update sd.asm

Back out hack for uz80as now that Curt fixed it.

* Misc. Cleanup

* UNA Catchup

UNA support was lacking some of the more recent behavior changes.  This corrects most of it.

* Add github action for building RomWBW

* Bump Pre-release Version

* Update build.yml

Added "make clean" which will remove temporary files without removing final binary outputs.

* Update Makefile

Build all ROM variants by default in Linux/Mac build.

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update for GitHub Build

Case issue in TASM includes showing up in GitHub build.  This should correct that.

* Added an gitignore files to exclude generated files

* Removed Tunes/clean.cmd and Tunes/ReadMe.txt - as make clean removes them

* Build.sh: marked as executable

chmod +x Build.sh

* Fix to HBIOS/build.sh

When adding files to rom disk, if files were missing, it would error out.

It appears the intent is to skip non-existing files.

Updated to log out correctly for missing files - and continue operation.

* Update Microsoft NASCOM BASIC.docx

Nascom manual, text version by Jan S (full name unknown)

* Fix issue with Apps/Tune not making

If dest directory does not exist, fails to make Apps

* Create ReadMe.txt

* Update Makefile

* Update Build.sh

* Make .gitignores for Tools/unix more specific

* cpmtools Update

Updated cpmtools applications (Windows only).  Removed hack in diskdefs that is no longer required.

* HBIOS Proxy Temp Stack Enhancement

Reuse the bounce buffer area as the temporary stack space required briefly in HBX_INVOKE when transitioning banks.  Increases size of temporary stack space to 64 bytes.

* Update ReadMe.txt

* HBIOS - clean up TMPSTK

* Update hbios.asm

Minor cosmetic changes.

* Build Process Updates

Minor udpates to build process to improve consistency between Windows and Mac/Linux builds.

* Update hbios.asm

Add improved interrupt protection to HBIOS PEEK, POKE, and BNKCPY functions.

* hbios - wrap hbx_bnkcpy

* hbios - adjust hbx_peek hbx_poke guards

* Update hbios.asm

Adjusted used of DI/EI for PEEK and POKE to regain a bit of INTSTK space.  Added code so that HB_INVBNK can be used as a flag indicating if HBIOS is active, $FF is inactive, anything else means active.

* Add HBIOS MuTex

* Initial Nascom basic ecb-vdu graphics

set and reset for 80x25b screen with 256 character mod

* Finalize Pre-release 34

Final support for FreeRTOS

* Update nascom.asm

Optimization, cleanup, tabs and white spaces

* IDE & PPIDE Cleanup

* Clean up

Make version include files common.

* Update Makefile

* Update Makefile

* Build Test

* Build Test

* Build Fixes

* Update nascom.asm

Cleanup

* Update nascom.asm

Optimization

* hbios - temp stack tweak

* Update hbios.asm

Comments on HBX_BUF usage.

* Update nascom.asm

Optimization

* Update nascom.asm

Setup ECB-VDU build option, remove debug code

* Update nascom.asm

Set default build. update initialization

* Update nascom.asm

Make CLS clear vdu screen

* Update nascom.asm

Fixup top screen line not showing

* Add SC131 Support

Also cleaned up some ReadMe files.

* HBIOS SCZ180 - remove mutex special files

* HBIOS SCZ180 - adjust mutex comment

* Misc. Cleanup

Includes some minor improvements to contents in some disk images.

* Delete FAT.COM

Changing case of FAT.COM extension to lowercase.

* Create FAT.com

Completing change of case in extension of FAT.com.

* Update Makefile

Remove ROM variants that just have the HBIOS MUTEX enabled.  Users can easily enable this in a custom build.

* Cleanup

Removed hack from Images Makefile.  Fixed use of DEFSERCFG in various places.

* GitHub CI Updates

Adds automation of build and release assets upon release.

* Prerelease 36

General cleanup

* Build Script Cleanups

* Config File Cleanups

* Update RomWBW Architecture

General refresh for v2.9.2

* Update vdu.asm

Removed a hack in VDU driver that has existed for 8 years.  :-)

* Fix CONSOLE Constant

Rename CIODEV_CONSOLE constant to CIO_CONSOLE because it is a unit code, not a device type code.

Retabify TastyBasic.

* Minor Bug Fixes

- Disk assignment edge case
- CP/M 3 accidental fall thru
- Cosmetic updates

* Update util.z80

* Documentation Cleanup

* Documentation Update

* Documentation Update

* Documentation Updates

* Documentation Updates

* Create Common.inc

* Documentation Updates

* Documentation Updates

* doc - a few random fixes

* Documentation Cleanup

* Fix IM 0 Build Error in ACIA

* Documentation Updates

* Documentation Cleanup

* Remove OSLDR

The OSLDR application was badly broken and almost impossible to fix with new expanded OS support.

* Bug Fixes

- Init RAM disk at boot under CP/M 3
- Fix ACR activation in TUNE

* FD Motor Timeout

- Made FDC motor timeout smaller and more consistent across different speed CPUs
- Added "boot" messaging to RTC

* Cleanup

* Cleanup

- Fix SuperZAP to work under NZCOM and ZPM3
- Finalize standard config files

* Minor Changes

- Slight change to ZAP configuration
- Added ZSDOS.ZRL to NZCOM image

* ZDE Upgrade

- Upgraded ZDE 1.6 -> 1.6a

* Config File Tuning

* Pre-release for Testing

* cfg - mutex consistent config language

* Bump to Version 3.0

* Update SD Card How-To

Thanks David!

* update ReadMe.md

Remove some odd `\`.

* Update ReadMe.txt

* Update ReadMe.md

* Update Generated Doc Files

* Improve XModem Startup

- Extended startup timeout for XM.COM so that it doesn't timeout so quickly while host is selecing a file to send.
- Updated SD Card How-To from David Reese.

* XModem Timing Refinements

* TMS Driver Z180 Improvements

- TMS driver udpated to insert Z180 I/O waitstates internally so other code can run at full speed.
- Updated How-To documents from David.
- Fixed TUNE app to properly restore Z180 I/O waitstates after manipulating them.

* CLRDIR and ZDE updates

- CLRDIR has been updated by Max Scane for CP/M 3 compatibility.
- A minor issue in the preconfigured ZDE VT100 terminal escape sequences was corrected.

* Fix Auto CRT Console Switch on CP/M 3

* Handle lack of RTC better

DSRTC driver now correctly returns an error if there is no RTC present.

* Minor RTC Updates

* Finalize v3.0.1

Cleanup release for v3.0

* New ROMLDR and INTRTC driver

- Refactored romldr.asm
- Added new periodic timer based RTC driver

* CP/M 3 Date Hack

- Hack to allow INTRTC to increment time without destroying the date

* Update romldr.asm

Work around minor Linux build inconsistency

* Update Apps for New Version

* Revert "Update Apps for New Version"

This reverts commit ad80432252.

* Revert "Update romldr.asm"

This reverts commit 4a9825cd57.

* Revert "CP/M 3 Date Hack"

This reverts commit 153b494e61.

* Revert "New ROMLDR and INTRTC driver"

This reverts commit d9bed4563e.

* Start v3.1 Development

* Update FDISK80.COM

Updated FDISK80 to allow reserving up to 256 slices.

* Update sd.asm

For Z180 CSIO, ensure that xmit is finished, before asserting CS for next transaction.

* Add RC2014 UART, Improve SD protocol fix

- RC2014 and related platforms will autodetect a UART at 0xA0 and 0xA8
- Ensure that CS fully brackets all SD I/O

* ROMLDR Improvements

.com files can now be started from CP/M and size of .com files has been reduced so they always fit.

* Update commit.yml

Run commit build in all branches

* Update commit.yml

Run commit build for master and dev branches

* Improved clock driver auto-detect/fallback

* SIO driver now CTC aware

The SIO driver can now use a CTC (if available) to provide much more flexible baud rate programming.

* CTC driver fine tuning

* Update xmdm125.asm

Fixed a small issue in core XM125 code that caused a file write error message to not be displayed when it should be.

* CF Card compatibility improvement

Older CF Cards did not reset IDE registers to defaults values when reset.  Implemented a work around.

* Update ACIA detection

ACIA should no longer be detected if there is also a UART module in the system.

* Handle CTC anomaly

Small update to accommodate CTC behavior that occurs when the CTC trigger is more than half the CTC clock.

* Update acia.asm

Updated ACIA detection to use primary ACIA port instead of phantom port.

* Update acia.asm

Fix bug in ACIA detection.

Thanks Alan!

* MacOS Build Improvement

Build script updated to improve compatibility with MacOS.

Credit to Fredrik Axtelius for this.

* HBIOS Makefile - use env vars for target

Allow build ROM targets to be restricted to just one platform thru use of ENV vars:

ROM_PLATFORM - if defined to a known platform, only this platform is build - defaults to std config
ROM_CONFIG - sets the desired platform config - defaults to std

if the above ENVs are not defined, builds all ROMs

* Added some more gitignores

* Whitespace changes (crlf)

* HBIOS: Force the assembly to fail for vdu drivers if function table count is not correct

* Whitespace: trailing whitespaces

* makefile: updated some make scripts to use  when calling subdir makefiles

* linux build: update to Build.sh fix for some platforms

The initialization of the Rom dat file used the pipe (|) operator to build an initial empty file.

But the pipe operator | may sometimes return a non-zero exit code for some linux platforms, if the
the streams are closed before dd has fully processed the stream.

This issue occured on a travis linux ubuntu image.

Solution was to change to redirection.

* Bump version

* Enhance CTC periodic timer

Add ability to use TIMER mode in CTC driver to generate priodic interrupts.

* HBIOS: Added support for sound drivers

New sound driver support with initial support for the SN76489 chip

New build configuration entry:
* SN76489ENABLE

Ports are currently locked in with:
* SN76489_PORT_LEFT       .EQU    $FC     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)
* SN76489_PORT_RIGHT      .EQU    $F8     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)

* Miscellaneous Cleanup

No functional changes.

Co-authored-by: curt mayer <curt@zen-room.org>
Co-authored-by: Wayne Warthen <wwarthen@gmail.com>
Co-authored-by: ed <linux@maidavale.org>
Co-authored-by: Dean Netherton <dnetherton@dius.com.au>
Co-authored-by: ed <ed@maidavale.org>
Co-authored-by: Phillip Stevens <phillip.stevens@gmail.com>
Co-authored-by: Dean Netherton <dean.netherton@gmail.com>
2020-04-24 06:17:22 +08:00

1402 lines
38 KiB
NASM

;
;==================================================================================================
; ANSI EMULATION MODULE
;==================================================================================================
;
; TODO:
; 1) INSERT/DELETE CHARACTERS CTL SEQUENCES
; 2) OTHER CTL SEQUENCES?
;
;==================================================================================================
; ANSI EMULATION MODULE CONSTANTS
;==================================================================================================
;
ANSI_DEFATTR .EQU 0 ; ALL ATTRIBUTES OFF
ANSI_DEFCOLOR .EQU 7 ; WHITE ON BLACK
;
;==================================================================================================
; ANSI EMULATION MODULE
;==================================================================================================
;
; INITIALIZATION OF EMULATION MODULE CALLED BY PARENT VDA DRIVER
; ON ENTRY:
; DE: DISPATCH ADDRESS OF CALLING VDA DRIVER
; RETURNS:
; DE: OUR CIO FUNC TBL ADDRESS
;
ANSI_INIT:
; PREVENT ATTEMPTS TO INIT MULTIPLE INSTANCES FOR NOW
LD A,(ANSI_VDAUNIT) ; LOAD CURRENT VDA UNIT VALUE
INC A ; SHOULD BE $FF, INC TO $00
RET NZ ; IF NOT 0, PREVIOUSLY ATTACHED, RETURN W/ NZ
;
; SAVE INCOMING DATA
LD A,B ; TERMINAL DEVICE NUM PASSED IN B
LD (ANSI_DEVNUM),A ; SAVE IT
LD A,C ; VDA UNIT NUMBER PASSED IN C
LD (ANSI_VDAUNIT),A ; SAVE IT
;LD (ANSI_VDADISPADR),DE ; RECORD VDA DISPATCH ADDRESS
;
; INIT/RESET OUR INTERNAL STATE
CALL ANSI_RESET ; FULL RESET OF EMULATOR INTERNAL STATE
RET NZ ; BAIL OUT ON ERROR
;
LD DE,ANSI_FNTBL ; RETURN OUR FUNC TBL ADDRESS
XOR A ; SIGNAL SUCCESS
RET ; RETURN
;
ANSI_RESET:
; 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 ANSI_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
LD A,ANSI_DEFATTR ; DEFAULT ATTRIBUTE
LD (ANSI_ATTR),A ; CLEAR ATTRIBUTES
LD A,ANSI_DEFCOLOR ; DEFAULT COLOR
LD (ANSI_COLOR),A ; RESET COLOR
XOR A ; ZERO ACCUM
LD (ANSI_WRAP),A ; CLEAR WRAP FLAG
LD (ANSI_LNM),A ; SET LINE FEED NEW LINE MODE
LD (ANSI_CKM),A ; CLEAR DEC CURSOR KEY MODE
LD (ANSI_COLM),A ; CLEAR 132 COLUMN MODE
LD (ANSI_QLEN),A ; ZERO THE QUEUE LENGTH
LD A,$FF ; SET ALL BITS OF ACCUM
LD (ANSI_AWM),A ; SET DEC AUTOWRAP MODE
;
; RESET TAB STOPS TO DEFAULT (EVERY 8 CHARACTERS)
LD A,%10000000 ; STOP AT FIRST OF EVERY 8 CHARACTERS
LD HL,ANSI_TABS ; POINT TO TAB STOP BITMAP
LD B,32 ; INIT 32 BYTES
;
ANSI_RESET1: ; LOOP TO RESET TAB STOPS
LD (HL),A ; SET A BYTE
INC HL ; POINT TO NEXT BYTE
DJNZ ANSI_RESET1 ; LOOP TILL ALL BYTES DONE
;
XOR A
RET
;
;
;
ANSI_VDADISP:
; JP PANIC
;ANSI_VDADISPADR .EQU $ - 2
LD A,(ANSI_VDAUNIT)
LD C,A
JP VDA_DISPATCH
;
; FUNCTION TABLE
;
ANSI_FNTBL:
.DW ANSI_IN
.DW ANSI_OUT
.DW ANSI_IST
.DW ANSI_OST
.DW ANSI_INITDEV
.DW ANSI_QUERY
.DW ANSI_DEVICE
#IF (($ - ANSI_FNTBL) != (CIO_FNCNT * 2))
.ECHO "*** INVALID ANSI FUNCTION TABLE ***\n"
#ENDIF
;
;==================================================================================================
; ANSI EMULATION MODULE BIOS FUNCTION ENTRY POINTS
;==================================================================================================
;
; READ A CHARACTER
;
ANSI_IN: ; HANDLE INPUT REQUEST
;
; RETURN QUEUED DATA IF WE HAVE ANY
LD A,(ANSI_QLEN) ; GET THE CURRENT QUEUE LENGTH
OR A ; SET FLAGS
JR Z,ANSI_IN1 ; NOTHING THERE, GO TO KEYBOARD READ
DEC A ; DECREMENT THE QUEUE LENGTH
LD (ANSI_QLEN),A ; AND SAVE IT
LD HL,(ANSI_QPTR) ; GET THE QUEUE POINTER
LD A,(HL) ; GET THE NEXT QUEUE BYTE
INC HL ; INCREMENT THE POINTER
LD (ANSI_QPTR),HL ; AND SAVE IT
LD E,A ; RETURN VALUE IN E
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
ANSI_IN1: ; PERFORM ACTUAL KEYBOARD INPUT
LD B,BF_VDAKRD ; SET FUNCTION TO KEYBOARD READ
CALL ANSI_VDADISP ; CALL VDA DISPATCHER
LD A,E ; CHARACTER READ INTO A
BIT 7,A ; TEST HIGH BIT
JR NZ,ANSI_IN2 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR
XOR A ; OTHERWISE, SIGNAL SUCCESS
RET ; AND RETURN THE KEY
;
ANSI_IN2: ; HANDLE SPECIAL KEY
CALL ANSI_KDISP ; IF $80 OR HIGHER, DISPATCH
JR ANSI_IN ; AND LOOP
;
; WRITE A CHARACTER W/ EMULATION
;
ANSI_OUT:
LD HL,ANSI_OUT2 ; RETURN ADDRESS
PUSH HL ; PUT IT ON STACK
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
JP (HL) ; DO IT
; CALL JPHL ; DO IT
;
ANSI_OUT2: ; SET RESULT AND RETURN
XOR A ; SIGNAL SUCCESS
RET
;
; CHECK INPUT STATUS
;
ANSI_IST: ; CHECK QUEUE FIRST
LD A,(ANSI_QLEN) ; GET CURRENT QUEUE LENGTH
OR A ; SET FLAGS
RET NZ ; RETURN IF CHAR(S) WAITING
;
; QUEUE WAS EMPTY, CHECK HARDWARE STATUS
LD B,BF_VDAKST ; SET FUNCTION TO KEYBOARD STATUS
CALL ANSI_VDADISP ; CHECK STATUS
OR A ; SET FLAGS
RET Z ; NO KEYS WAITING, RETURN NO JOY
;
; KEY WAITING, GET IT AND HANDLE IT
LD B,BF_VDAKRD ; SET FUNCTION TO KEYBOARD READ
CALL ANSI_VDADISP ; DO IT
LD A,E ; CHARACTER READ TO A
BIT 7,A ; TEST HIGH BIT
JR NZ,ANSI_IST1 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR
;
; REGULAR CHARACTER RECEIVED, QUEUE IT AND RETURN CHARS WAITING STATUS
LD HL,ANSI_QUEUE ; SET HL TO START OF QUEUE
LD (ANSI_QPTR),HL ; RESET QUEUE POINTER
LD A,E ; RESTORE CHARACTER RECEIVED
LD (HL),A ; SAVE IT AT THE HEAD OF THE QUEUE
XOR A ; ZERO ACCUM
INC A ; ASSUM := 1 (NUM CHARS IN QUEUE)
LD (ANSI_QLEN),A ; SAVE NEW QUEUE LEN
JR ANSI_IST ; REPEAT
;
ANSI_IST1: ; HANDLE SPECIAL KEY
CALL ANSI_KDISP ; DO SPECIAL KEY HANDLING
JR ANSI_IST ; REPEAT
;
; CHECK OUTPUT STATUS
;
ANSI_OST: ; VIDEO OUTPUT IS *ALWAYS* READY
XOR A ; ZERO ACCUM
INC A ; A := $FF TO SIGNAL OUTPUT BUFFER READY
RET
;
; INITIALIZE
;
ANSI_INITDEV:
; RESET THE ATTACHED VDA DEVICE
LD B,BF_VDAINI ; FUNC: INIT
LD E,-1 ; DO NOT CHANGE VIDEO MODE
LD HL,0 ; DO NOT LOAD A BITMAP
CALL ANSI_VDADISP ; CALL THE VDA DRIVER
; RESET OUR INTERNAL STATE AND RETURN
JP ANSI_RESET ; RESET OURSELVES AND RETURN
;
; QUERY STATUS
;
ANSI_QUERY:
LD DE,$FFFF
LD HL,$FFFF
XOR A
RET
;
; REPORT DEVICE
;
ANSI_DEVICE:
LD D,CIODEV_TERM ; TYPE IS TERMINAL
LD A,(ANSI_DEVNUM) ; GET DEVICE NUMBER
LD E,A ; PUT IT IN E
LD A,(ANSI_VDAUNIT) ; GET VDA UNIT NUM
SET 7,A ; SET BIT 7 TO INDICATE TERMINAL TYPE
LD C,A ; PUT IT IN C
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 INTERMEDIATE 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 $09 ; HT: TAB
JP Z,ANSI_HT
CP $0A ; LF: LINEFEED
JP Z,ANSI_LF
CP $0B ; VT: VERTICAL TAB
JP Z,ANSI_LF ; TREAT 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 $84 ; IND: INDEX
JP Z,ANSI_LF ; DO IT
CP $85 ; NEL: NEXT LINE
JP Z,ANSI_NEL ; DO IT
CP $88 ; HTS: HORIZONTAL TAB SET
JP Z,ANSI_HTS ; DO IT
CP $8D ; RI: REVERSE INDEX
JP Z,ANSI_RI ; DO IT
CP $9B ; CSI: CONTROL SEQ INTRODUCER
JP Z,ANSI_CSI ; HANDLE IT
;
; IGNORE OTHERS
RET
;
;==================================================================================================
; ANSI ESCAPE SEQUENCE DISPATCHING
;==================================================================================================
;
ANSI_ESCDISP:
#IF (ANSITRACE >= 2)
PRTS("<ESC>($")
PUSH AF
LD A,(ANSI_INT)
OR A
CALL NZ,COUT
CALL PC_COMMA
POP AF
CALL COUT
CALL PC_RPAREN
#ENDIF
LD (ANSI_FINAL),A ; RECORD THE FINAL CHARACTER
LD A,(ANSI_INT) ; LOAD THE INTERMEDIATE CHARACTER
OR A ; SET FLAGS
JR Z,ANSI_ESCDISP1 ; NO INT CHARACTER, DO NORMAL DISPATCH
CP '#' ; INTERMEDIATE CHAR == '#'?
JR Z,ANSI_ESCDISP2 ; YES, DO # DISPATCHING
JP ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_ESCDISP1: ; NORMAL ESCAPE DISPATCHING, NO INT CHARACTER
LD A,(ANSI_FINAL) ; GET FINAL CHARACTER
CP $40 ; $30-$3F
JR C,ANSI_ESCDISP1A ; YES, CONTINUE NORMALLY
CP $60 ; $40-$5F
JR NC,ANSI_ESCDISP1A ; NOPE, $60 AND ABOVE CONTINUE NORMALLY
;
; $40-$5F MAPS 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_ESCDISP1A: ; CONTINUE NORMAL ESCAPE SEQ DISPATCHING
CP 'c' ; RIS: RESET TO INITIAL STATE
JP Z,ANSI_RESET ; DO A FULL RESET
JP ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_ESCDISP2: ; ESC DISPATCHING FOR '#' INT CHAR
LD A,(ANSI_FINAL) ; GET FINAL CHARACTER
CP '8' ; DECALN: DEC SCREEN ALIGNMENT TEST
JP Z,ANSI_DECALN ; HANDLE IT
JP ANSI_UNK ; UNKNOWN, ABORT
;
;==================================================================================================
; ANSI CONTROL SEQUENCE DISPATCHING
;==================================================================================================
;
ANSI_CTLDISP:
LD (ANSI_FINAL),A ; RECORD THE FINAL CHARACTER
#IF (ANSITRACE >= 2)
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
#ENDIF
; BRANCH BASED ON PRIVATE CHARACTER OF SEQUENCE
LD A,(ANSI_PRI) ; GET THE PRIVATE CHARACTER
OR A ; SET FLAGS
JR Z,ANSI_STD ; IF ZERO, NO PRIVATE CHAR, DO STANDARD
CP '?' ; '?' = DEC PRIVATE
JR Z,ANSI_DEC ; HANDLE DEC PRIVATE SEQUENCES
JR ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_STD: ; DISPATCH ON INTERMEDIATE CHAR W/ NO PRIVATE CHAR (STD)
LD A,(ANSI_INT) ; GET THE INTERMEDIATE CHARCACTER
OR A ; SET FLAGS
JR Z,ANSI_STD1 ; NO INTERMEDIATE CHARACTER, HANDLE IT
; CHECK FOR ANY OTHER STD INTERMEDIATE CHARACTERS HERE...
JR ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_STD1: ; DISPATCH FOR FINAL CHAR W/ NO INTERMEDIATE CHAR AND NO PRIVATE CHAR (STD)
LD A,(ANSI_FINAL) ; GET FINAL CHARACTER
CP 'A' ; CUU: CURSOR UP
JP Z,ANSI_CUU
CP 'B' ; CUD: CURSOR DOWN
JP Z,ANSI_CUD
CP 'C' ; CUF: CURSOR FORWARD
JP Z,ANSI_CUF
CP 'D' ; CUB: CURSOR BACKWARD
JP Z,ANSI_CUB
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 'L' ; IL: INSERT LINE
JP Z,ANSI_IL
CP 'M' ; DL: DELETE LINE
JP Z,ANSI_DL
CP 'f' ; HVP: HORIZONTAL/VERTICAL POSITION
JP Z,ANSI_HVP
CP 'g' ; TBC: TAB CLEAR
JP Z,ANSI_TBC
CP 'h' ; SM: SET MODE
JP Z,ANSI_SM
CP 'l' ; RM: RESET MODE
JP Z,ANSI_RM
CP 'm' ; SGR: SELECT GRAPHIC RENDITION
JP Z,ANSI_SGR
; CHECK FOR ANY OTHERS HERE
JR ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_DEC: ; DISPATCH ON INTERMEDIATE CHAR W/ PRIVATE CHAR = '?' (DEC)
LD A,(ANSI_INT) ; GET THE INTERMEDIATE CHARCACTER
OR A ; SET FLAGS
JR Z,ANSI_DEC1 ; NO INTERMEDIATE CHARACTER, HANDLE IT
; CHECK FOR ANY OTHER DEC INTERMEDIATE CHARACTERS HERE...
JR ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_DEC1: ; DISPATCH FOR FINAL CHAR W/ NO INTERMEDIATE CHAR AND PRIVATE CHAR = '?' (DEC)
LD A,(ANSI_FINAL) ; GET FINAL CHARACTER
CP 'h' ; SM: SET DEC MODE
JP Z,ANSI_DECSM
CP 'l' ; RM: RESET DEC MODE
JP Z,ANSI_DECRM
JR ANSI_UNK ; UNKNOWN, ABORT
;
ANSI_UNK: ; DIAGNOSE UNKNOWN SEQUENCE
#IF (ANSITRACE >= 2)
PRTS("***UNK***$")
#ENDIF
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:
#IF (ANSITRACE >= 2)
LD A,E
CALL COUT
#ENDIF
PUSH DE
; IF WRAP PENDING, DO IT NOW
LD A,(ANSI_WRAP) ; GET THE WRAP FLAG
OR A ; SET FLAGS
JR Z,ANSI_RENDER1 ; IF Z, NO WRAP, CONTINUE
LD A,(ANSI_AWM) ; GET AUTOWRAP MODE SETTING
OR A ; SET FLAGS
CALL NZ,ANSI_NEL ; IF SET, PERFORM A LINEWRAP (CLEARS WRAP FLAG)
;
ANSI_RENDER1: ; WRITE THE CHARACTER
POP DE ; RECOVER THE CHAR TO RENDER
LD B,BF_VDAWRC ; FUNC := WRITE CHARACTER
CALL ANSI_VDADISP ; SPIT OUT THE RAW CHARACTER
;
; END OF LINE HANDLING (CHECK FOR RIGHT MARGIN EXCEEDED)
LD A,(ANSI_COLS) ; GET SCREEN COLUMNS
LD B,A ; PUT IT IN B
LD A,(ANSI_COL) ; GET COLUMN
INC A ; BUMP IT TO REFLECT NEW CURSOR POSITION
LD (ANSI_COL),A ; SAVE IT
CP B ; PAST MAX?
RET C ; IF NOT, ALL DONE, JUST RETURN
;
; CURSOR MOVED PAST RIGHT MARGIN, FIX IT AND SET WRAP FLAG
DEC A ; BACK TO RIGHT MARGIN
LD (ANSI_COL),A ; SAVE IT
CALL ANSI_XY ; UPDATE CURSOR POSITION ON SCREEN
LD A,$FF ; LOAD $FF TO SET FLAG
LD (ANSI_WRAP),A ; SAVE FLAG
RET ; 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 ANSI_VDADISP ; PERFORM FILL
JP ANSI_XY ; HOME CURSOR AND RETURN
;
ANSI_BS:
LD A,(ANSI_COL) ; GET CURRENT COLUMN
DEC A ; BACK IT UP BY ONE
RET C ; IF CARRY, MARGIN EXCEEDED, ABORT
LD (ANSI_COL),A ; SAVE NEW COLUMN
JP ANSI_XY ; UDPATE CUSROR AND RETURN
;
ANSI_CR:
XOR A ; ZERO ACCUM
LD (ANSI_COL),A ; COL := 0
JP ANSI_XY ; REPOSITION CURSOR AND RETURN
;
ANSI_LF: ; LINEFEED (FORWARD INDEX)
LD A,(ANSI_ROW) ; GET CURRENT ROW
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
DEC D ; D := MAX ROW NUM
CP D ; >= LAST ROW?
JR NC,ANSI_LF1 ; NEED TO SCROLL
INC A ; BUMP TO NEXT ROW
LD (ANSI_ROW),A ; SAVE IT
JP ANSI_XY ; UPDATE CURSOR AND RETURN
;
ANSI_LF1: ; SCROLL
LD E,1 ; SCROLL FORWARD 1 LINE
LD B,BF_VDASCR ; SET FUNCTION TO SCROLL
JP ANSI_VDADISP ; DO THE SCROLLING AND RETURN
;
ANSI_RI: ; REVERSE INDEX (REVERSE LINEFEED)
LD A,(ANSI_ROW) ; GET CURRENT ROW
OR A ; SET FLAGS
JR Z,ANSI_RI1 ; IF AT TOP (ROW 0), NEED TO SCROLL
DEC A ; BUMP TO PRIOR ROW
LD (ANSI_ROW),A ; SAVE IT
JP ANSI_XY ; RESPOSITION CURSOR AND RETURN
;
ANSI_HT: ; HORIZONTAL TAB
;
; CHECK FOR RIGHT MARGIN, IF AT MARGIN, IGNORE
LD A,(ANSI_COLS) ; GET SCREEN COLUMN COUNT
DEC A ; MAKE IT MAX COL NUM
LD E,A ; SAVE IN E
LD A,(ANSI_COL) ; GET CURRENT COLUMN
CP E ; COMPARE TO MAX
RET NC ; IF COL >= MAX, IGNORE
;
; INCREMENT COL TILL A TAB STOP IS HIT OR RIGHT MARGIN
ANSI_HT1:
INC A ; NEXT COLUMN
LD D,A ; SAVE COLUMN
; PUSH AF ; SAVE COLUMN
; PUSH BC ; SAVE MAX COLUMN
LD HL,ANSI_TABS ; POINT TO TABSTOP BITMAP
CALL BITTST ; TEST BIT FOR CURRENT COLUMN
; POP BC ; RECOVER MAX COLUMN
; POP AF ; RECOVER CUR COLUMN
LD A,D ; RECOVER COLUMN
JR NZ,ANSI_HT2 ; IF TABSTOP HIT, COMMIT NEW COLUMN
CP E ; TEST FOR RIGHT MARGIN
JR NC,ANSI_HT2 ; IF AT RIGHT MARGIN, COMMIT NEW COLUMN
JR ANSI_HT1 ; LOOP UNTIL DONE
;
ANSI_HT2: ; COMMIT THE NEW COLUMN VALUE
LD (ANSI_COL),A ; SAVE THE NEW COLUMN
JP ANSI_XY ; UPDATE CURSOR AND RETURN
;
ANSI_RI1: ; REVERSE SCROLL
LD E,-1 ; SCROLL -1 LINES (REVERSE SCROLL 1 LINE)
LD B,BF_VDASCR ; SET FUNCTION TO SCROLL
JP ANSI_VDADISP ; DO THE SCROLLING AND RETURN
;
;
;
ANSI_HTS: ; HORIZONTAL TAB SET
LD HL,ANSI_TABS ; POINT TO TAB STOP BITMAP
LD A,(ANSI_COL) ; SET TAB STOP AT CURRENT COL
CALL BITSET ; SET THE APPROPRIATE BIT
RET
;
;
;
ANSI_TBC: ; TAB CLEAR
LD A,(ANSI_PARLST) ; GET FIRST PARM
OR A ; SET FLAGS
JR Z,ANSI_TBC1 ; 0 = CLEAR TAB AT CURRENT COL
CP 3 ; TEST FOR 3
JR Z,ANSI_TBC2 ; 3 = CLEAR ALL TABS
RET ; ANYTHING ELSE IS IGNORED
;
ANSI_TBC1: ; CLEAR TAB AT CURRENT COL
LD HL,ANSI_TABS ; POINT TO TAB STOP BITMAP
LD A,(ANSI_COL) ; SET TAB STOP AT CURRENT COL
CALL BITCLR ; CLEAR THE APPROPRIATE BIT
RET ; DONE
;
ANSI_TBC2: ; CLEAR ALL TABS
LD HL,ANSI_TABS ; POINT TO TABSTOP BITMAP
LD B,32 ; CLEAR 32 BYTES
XOR A ; CLEAR WITH VALUE OF ZERO
;
ANSI_TBC3: ; CLEAR ALL TABS LOOP
LD (HL),A ; SET THE CURRENT BYTE
INC HL ; POINT TO NEXT BYTE
DJNZ ANSI_TBC3 ; LOOP UNTIL DONE
RET ; DONE
;
;
;
ANSI_SM: ; SET MODE
ANSI_DECSM: ; SET DEC MODE
LD C,$FF ; FLAG VALUE (SET VALUE)
JR ANSI_MODE ; GO TO SET/RESET MODE
;
ANSI_RM: ; RESET MODE
ANSI_DECRM: ; RESET DEC MODE
LD C,$00 ; FLAG VALUE (RESET VALUE)
JR ANSI_MODE ; GO TO SET/RESET MODE
;
ANSI_MODE: ; (RE)SET MODES, FLAG VALUE IN C
LD A,(ANSI_PARIDX) ; GET CURRENT PARM INDEX
INC A ; INCREMENT TO MAKE IT THE PARM COUNT
LD B,A ; MOVE COUNT TO B FOR LOOPING
LD HL,ANSI_PARLST ; USE HL AS PARM POINTER
ANSI_MODE1: ; (RE)SET MODE LOOP
PUSH BC ; SAVE LOOP COUNTER
PUSH HL ; SAVE PARM INDEX
CALL ANSI_MODE2 ; DO THE WORK
POP HL ; RESTORE PARM INDEX
POP BC ; RESTORE LOOP COUNTER
INC HL ; BUMP THE PARM INDEX
DJNZ ANSI_MODE1 ; LOOP THRU ALL PARMS
ANSI_MODE2: ; (RE)SET MODE LOOP
LD A,(ANSI_PRI) ; GET PRIVATE CHAR
OR A ; SET FLAGS
JR Z,ANSI_MODE3 ; IF ZERO, HANDLE SANDARD MODES
CP '?' ; IF '?', DEC PRIVATE
JR Z,ANSI_MODE4 ; HANDLE DEC PRIVATE MODES
RET ; OTHERWISE IGNORE
;
ANSI_MODE3: ; STANDARD MODES
LD A,(HL) ; GET PARM
INC HL ; INCREMENT POINTER FOR NEXT LOOP
CP 20 ; LNM: LINE FEED NEW LINE MODE?
JR Z,ANSI_MDLNM ; DO IT
RET ; OTHERWISE IGNORE
;
ANSI_MODE4: ; DEC PRIVATE MODES
LD A,(HL) ; GET PARM
CP 1 ; DECCKM: DEC CURSOR KEY MODE
JR Z,ANSI_MDDECCKM ; DO IT
CP 3 ; DECCOLM: DEC COLUMN MODE
JR Z,ANSI_MDDECCOLM ; DO IT
CP 7 ; DECAWM: DEC AUTOWRAP MODE
JR Z,ANSI_MDDECAWM ; DO IT
RET ; OTHERWISE IGNORE
;
ANSI_MDLNM: ; (RE)SET LINE FEED NEW LINE MODE
LD A,C ; GET THE VALUE
LD (ANSI_LNM),A ; SAVE IT
RET
;
ANSI_MDDECCKM: ; (RE)SET DEC CURSOR KEY MODE FLAG
LD A,C ; GET THE VALUE
LD (ANSI_CKM),A ; SAVE IT
RET ; DONE
;
ANSI_MDDECCOLM: ; (RE)SET DEC COLUMN MODE
LD A,C ; GET THE VALUE
LD (ANSI_COLM),A ; SAVE IT
JP ANSI_FF ; CLEAR SCREEN
;
ANSI_MDDECAWM: ; (RE)SET DEC AUTOWRAP MODE
LD A,C ; GET THE VALUE
LD (ANSI_AWM),A ; SAVE IT
RET ; DONE
;
;
;
ANSI_NEL: ; NEXT LINE
CALL ANSI_CR
JP ANSI_LF
;
;
;
ANSI_CUU: ; CURSOR UP
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_CUU1 ; WE HAVE A PARM, CONTINUE
INC A ; DEFAULT TO 1
;
ANSI_CUU1:
LD B,A ; PARM IN B
LD A,(ANSI_ROW) ; GET CURRENT ROW
SUB B ; DECREMENT BY PARM VALUE
JR NC,ANSI_CUU2 ; NO CARRY, WE ARE GOOD
XOR A ; LESS THAN 0, FIX IT
;
ANSI_CUU2:
LD (ANSI_ROW),A ; SAVE IT
JP ANSI_XY ; MOVE CURSOR AND RETURN
;
;
;
ANSI_CUD: ; CURSOR DOWN
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_CUD1 ; WE HAVE A PARM, CONTINUE
INC A ; DEFAULT TO 1
ANSI_CUD1:
LD B,A ; PARM IN B
LD A,(ANSI_ROWS) ; GET ROW COUNT
DEC A ; DEC FOR MAX ROW NUM
LD C,A ; MAX ROW NUM IN C
LD A,(ANSI_ROW) ; GET CURRENT ROW
ADD A,B ; ADD PARM VALUE, A HAS NEW ROW
CP C ; COMPARE NEW ROW TO MAX ROW
JR C,ANSI_CUD2 ; IF CARRY, WE ARE WITHIN MARGIN
LD A,C ; OTHERWISE, SET TO MARGIN
;
ANSI_CUD2:
LD (ANSI_ROW),A ; SAVE IT
JP ANSI_XY ; MOVE CURSOR AND RETURN
;
;
;
ANSI_CUF: ; CURSOR FORWARD
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_CUF1 ; WE HAVE A PARM, CONTINUE
INC A ; DEFAULT TO 1
;
ANSI_CUF1:
LD B,A ; PARM IN B
LD A,(ANSI_COLS) ; GET COL COUNT
DEC A ; DEC FOR MAX COL NUM
LD C,A ; MAX COL NUM IN C
LD A,(ANSI_COL) ; GET CURRENT COL
ADD A,B ; ADD PARM VALUE, A HAS NEW COL
CP C ; COMPARE NEW COL TO MAX COL
JR C,ANSI_CUF2 ; IF CARRY, WE ARE WITHIN MARGINS
LD A,C ; OTHERWISE, SET TO MARGIN
;
ANSI_CUF2:
LD (ANSI_COL),A ; SAVE IT
JP ANSI_XY ; MOVE CURSOR AND RETURN
;
;
;
ANSI_CUB: ; CURSOR BACKWARD
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_CUB1 ; WE HAVE A PARM, CONTINUE
INC A ; DEFAULT TO 1
;
ANSI_CUB1:
LD B,A ; PARM IN B
LD A,(ANSI_COL) ; GET CURRENT COL
SUB B ; DECREMENT BY PARM VALUE
JR NC,ANSI_CUB2 ; NO CARRY, WE ARE GOOD
XOR A ; LESS THAN 0, FIX IT
;
ANSI_CUB2:
LD (ANSI_COL),A ; SAVE IT
JP ANSI_XY ; MOVE CURSOR AND RETURN
;
;
;
ANSI_CUP: ; CURSOR UPDATE
ANSI_HVP: ; HORIZONTAL/VERTICAL POSITION
;
; 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_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_XY2IDX ; HL NOW HAS CURSOR INDEX
PUSH HL ; SAVE IT
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
LD E,0 ; COL POSITION := 0
CALL ANSI_XY2IDX ; HL NOW HAS EOS INDEX
POP DE ; RECOVER CURSOR POS INDEX
OR A ; CLEAR CARRY
SBC HL,DE ; SUBTRACT CURSOR INDEX FROM EOS INDEX
JR ANSI_ED4 ; COMPLETE THE FILL
;
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 ANSI_VDADISP ; DO IT
LD DE,(ANSI_POS) ; GET ORIGINAL CURSOR POSITION
CALL ANSI_XY2IDX ; HL NOW HAS INDEX
INC HL ; ADD 1 POSITION TO ERASE THRU CURSOR POSITION
JR ANSI_ED4 ; COMPLETE THE FILL
;
ANSI_ED3: ; ERASE FULL DISPLAY
LD DE,0 ; CURSOR POS 0,0
LD B,BF_VDASCP ; FUNCTION = SET CURSOR POS
CALL ANSI_VDADISP ; DO IT
LD DE,(ANSI_DIM) ; DE := SCREEN ROWS/COLS
CALL ANSI_XY2IDX ; HL := CHARS ON SCREEN
;
ANSI_ED4: ; COMMON FILL PROCESS COMPLETION
LD E,' ' ; FILL WITH BLANK
LD B,BF_VDAFIL ; FUNCTION = FILL
CALL ANSI_VDADISP ; DO IT
JP ANSI_XY ; RESTORE CURSOR POS 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_XY2IDX ; 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_XY2IDX ; HL NOW HAS EOL INDEX
POP DE ; RECOVER CURSOR POS INDEX
OR A ; CLEAR CARRY
SBC HL,DE ; SUBTRACT CURSOR INDEX FROM EOL INDEX
JR ANSI_EL4 ; COMPLETE THE FILL
;
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 ANSI_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
JR ANSI_EL4 ; COMPLETE THE FILL
;
ANSI_EL3: ; ERASE FULL LINE
LD DE,(ANSI_POS) ; GET CURSOR POSITION
LD E,0 ; COL := 0 (START OF ROW)
LD B,BF_VDASCP ; FUNC = SET CURSOR POS
CALL ANSI_VDADISP ; DO IT
LD HL,(ANSI_DIM) ; GET SCREEN DIM IN HL
LD H,0 ; H := 0, HL IS NOW CHARS IN A LINE
JR ANSI_EL4 ; COMPLETE THE FILL
;
ANSI_EL4 .EQU ANSI_ED4 ; REUSE CODE ABOVE
;
;
;
ANSI_IL: ; INSERT LINE
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_IL1 ; GOT IT CONTINUE
INC A ; NO PARM, DEFAULT TO 1
;
ANSI_IL1:
LD B,A ; SET LOOP COUNTER
LD DE,(ANSI_DIM) ; GET SCREEN DIMENSIONS
DEC D ; POINT TO LAST ROW
LD E,0 ; FIRST CHAR OF ROW
;
ANSI_IL2:
PUSH BC ; PRESERVE LOOP COUNTER
PUSH DE ; PRESERVE STARTING POSTION
CALL ANSI_IL3 ; DO AN ITERATION
POP DE ; RECOVER STARTING POSITION
POP BC ; RECOVER LOOP COUNTER
DJNZ ANSI_IL2 ; LOOP AS NEEDED
;
; RESTORE CURSOR POSTION AND RETURN
JP ANSI_XY
;
ANSI_IL3:
; SET CURSOR POSITION TO DEST
PUSH DE ; PRESERVE DE
LD B,BF_VDASCP ; FUNC = SET CURSOR POS
CALL ANSI_VDADISP ; DO IT
POP DE ; RECOVER DE
; SET HL TO LENGTH
LD HL,(ANSI_DIM) ; GET DIMENSIONS
LD H,0 ; ZERO MSB, SO COPY LEN IS COL COUNT
; CHECK ROW, GET OUT IF WORKING ROW IS CURRENT ROW
LD A,(ANSI_ROW) ; GET CURRENT ROW
CP D ; COMPARE TO WORKING ROW NUM
JR Z,ANSI_IL4 ; IF EQUAL WE ARE DONE
; SET DE TO SOURCE POS
DEC D ; DE NOW POINTS TO PRIOR ROW
; DO THE COPY
PUSH DE ; PRESERVE DE
LD B,BF_VDACPY ; FUNCTION = COPY
CALL ANSI_VDADISP ; COPY THE LINE
POP DE ; RECOVER DE
JR ANSI_IL3 ; LOOP
;
ANSI_IL4: ;CLEAR INSERTED LINE
LD E,' ' ; FILL WITH BLANK
LD B,BF_VDAFIL ; FUNCTION = FILL
JP ANSI_VDADISP ; DO IT
;
;
;
ANSI_DL: ; DELETE LINE
LD A,(ANSI_PARLST) ; GET PARM
OR A ; SET FLAGS
JR NZ,ANSI_DL1 ; GOT IT CONTINUE
INC A ; NO PARM, DEFAULT TO 1
;
ANSI_DL1:
LD B,A ; SET LOOP COUNTER
LD DE,(ANSI_POS) ; GET CURSOR POS
LD E,0 ; COL := 0, START OF ROW
;
ANSI_DL2:
PUSH BC ; PRESERVE LOOP COUNTER
PUSH DE ; PRESERVE STARTING POSTION
CALL ANSI_DL3 ; DO AN ITERATION
POP DE ; RECOVER STARTING POSITION
POP BC ; RECOVER LOOP COUNTER
DJNZ ANSI_DL2 ; LOOP AS NEEDED
;
; RESTORE CURSOR POSTION AND RETURN
JP ANSI_XY
;
ANSI_DL3:
; SET CURSOR TO START OF DEST ROW
PUSH DE ; PRESERVE DE
LD B,BF_VDASCP ; FUNC = SET CURSOR POS
CALL ANSI_VDADISP ; DO IT
POP DE ; RECOVER DE
; SET DE TO SOURCE POS
INC D ; NEXT ROW, DE NOW HAS SOURCE
; SET HL TO LENGTH
LD HL,(ANSI_DIM) ; GET DIMENSIONS
LD H,0 ; ZERO MSB, SO COPY LEN IS COL COUNT
; CHECK ROW, GET OUT IF WORKING ROW NUM PAST END
LD A,(ANSI_ROWS) ; GET ROW COUNT
CP D ; COMPARE TO WORKING ROW NUM
JR Z,ANSI_DL4 ; IF EQUAL WE ARE DONE
; DO THE COPY
PUSH DE ; PRESERVE DE
LD B,BF_VDACPY ; FUNCTION = COPY
CALL ANSI_VDADISP ; COPY THE LINE
POP DE ; RECOVER DE
JR ANSI_DL3 ; LOOP
;
ANSI_DL4: ;CLEAR BOTTOM LINE
LD E,' ' ; FILL WITH BLANK
LD B,BF_VDAFIL ; FUNCTION = FILL
JP ANSI_VDADISP ; DO IT
;
;
;
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 ANSI_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 ANSI_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 5 ; BLINK
JR Z,ANSI_SGR_BLINK ; 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:
LD A,ANSI_DEFATTR ; DEFAULT ATTRIBUTE
LD (ANSI_ATTR),A ; CLEAR ATTRIBUTES
LD A,ANSI_DEFCOLOR ; DEFAULT COLOR
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_BLINK:
LD A,(ANSI_ATTR) ; LOAD CURRENT ATTRIBUTE
OR %00000001 ; SET BLINK 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
;
;
;
ANSI_DECALN: ; DEC SCREEN ALIGNMENT TEST
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,'E' ; FILL SCREEN WITH BLANKS
LD B,BF_VDAFIL ; SET FUNCTION TO FILL
CALL ANSI_VDADISP ; PERFORM FILL
JP ANSI_XY ; HOME CURSOR AND RETURN
;
;==================================================================================================
; ANSI PROTOCOL KEYBOARD DISPATCHING
;==================================================================================================
;
; HANDLE SPECIAL KEYBOARD CHARACTERS BY FILLING QUEUE WITH DATA
;
ANSI_KDISP:
; RESET THE QUEUE POINTER
LD HL,ANSI_QUEUE
LD (ANSI_QPTR),HL
;
; HANDLE FUNCTION KEYS
LD B,'P'
CP $E0 ; F1
JR Z,ANSI_KDISP_FN
LD B,'Q'
CP $E1 ; F2
JR Z,ANSI_KDISP_FN
LD B,'R'
CP $E2 ; F3
JR Z,ANSI_KDISP_FN
LD B,'S'
CP $E3 ; F4
JR Z,ANSI_KDISP_FN
;
; HANDLE EDIT KEYS
LD B,'2'
CP $F0 ; INSERT
JR Z,ANSI_KDISP_ED
LD B,'3'
CP $F1 ; DELETE
JR Z,ANSI_KDISP_ED
LD B,'1'
CP $F2 ; HOME
JR Z,ANSI_KDISP_ED
LD B,'4'
CP $F3 ; END
JR Z,ANSI_KDISP_ED
LD B,'5'
CP $F4 ; PAGEUP
JR Z,ANSI_KDISP_ED
LD B,'6'
CP $F5 ; PAGEDOWN
JR Z,ANSI_KDISP_ED
;
; HANDLE DIRECTION KEYS
LD B,'A'
CP $F6 ; UP
JR Z,ANSI_KDISP_DIR
LD B,'B'
CP $F7 ; DOWN
JR Z,ANSI_KDISP_DIR
LD B,'D'
CP $F8 ; LEFT
JR Z,ANSI_KDISP_DIR
LD B,'C'
CP $F9 ; RIGHT
JR Z,ANSI_KDISP_DIR
;
RET ; NO MATCH, DONE
;
ANSI_KDISP_FN: ; ADD FUNCTION KEY SEQUENCE TO QUEUE
LD A,$1B
LD (HL),A
INC HL
LD A,'O'
LD (HL),A
INC HL
LD A,B
LD (HL),A
LD A,3
LD (ANSI_QLEN),A
RET
;
ANSI_KDISP_ED: ; ADD EDIT KEY SEQUENCE TO QUEUE
LD A,$1B
LD (HL),A
INC HL
LD A,'['
LD (HL),A
INC HL
LD A,B
LD (HL),A
INC HL
LD A,'~'
LD (HL),A
LD A,4
LD (ANSI_QLEN),A
RET
;
ANSI_KDISP_DIR: ; ADD DIRECTION KEY SEQUENCE TO QUEUE
;
; SPECIAL CASE FOR CURSOR KEY MODE
LD A,(ANSI_CKM)
OR A
JR NZ,ANSI_KDISP_FN ; HANDLE LIKE FUNCTION KEY
;
LD A,$1B
LD (HL),A
INC HL
LD A,'['
LD (HL),A
INC HL
LD A,B
LD (HL),A
LD A,3
LD (ANSI_QLEN),A
RET
;
;==================================================================================================
; SUPPORT FUNCTIONS
;==================================================================================================
;
ANSI_XY:
XOR A ; ZERO ACCUM
LD (ANSI_WRAP),A ; CLEAR THE WRAP FLAG
LD DE,(ANSI_POS) ; GET THE DESIRED CURSOR POSITION
LD B,BF_VDASCP ; SET FUNCTION TO SET CURSOR POSITION
JP ANSI_VDADISP ; REPOSITION CURSOR
;
; CONVERT XY COORDINATES IN DE INTO LINEAR INDEX IN HL
; D=ROW, E=COL
;
ANSI_XY2IDX:
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_ATTR .DB ANSI_DEFATTR ; CURRENT CHARACTER ATTRIBUTE
ANSI_COLOR .DB ANSI_DEFCOLOR ; CURRENT CHARACTER COLOR;
ANSI_WRAP .DB 0 ; WRAP PENDING FLAG
ANSI_TABS .FILL 32,0 ; TAB STOP BIT MAP (256 BITS)
ANSI_LNM .DB 0 ; LINE FEED NEW LINE MODE FLAG
ANSI_CKM .DB 0 ; DEC CURSOR KEY MODE FLAG
ANSI_COLM .DB 0 ; DEC 132 COLUMN MODE FLAG
ANSI_AWM .DB 0 ; DEC AUTOWRAP MODE FLAG
ANSI_QLEN .DB 0 ; INPUT QUEUE LENGTH
ANSI_QPTR .DW 0 ; CURRENT QUEUE POINTER
ANSI_QUEUE .FILL 16,0 ; 16 BYTE QUEUE BUFFER
;
ANSI_VARS:
ANSI_PRI .DB 0 ; PRIVATE CHARACTER RECORDED HERE
ANSI_INT .DB 0 ; INTERMEDIATE CHARACTER RECORDED HERE
ANSI_FINAL .DB 0 ; FINAL 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_VDAUNIT .DB $FF ; VIDEO UNIT NUM OF ATTACHED VDA DEVICE
ANSI_DEVNUM .DB $FF ; TERMINAL DEVICE NUMBER