; vim: set tabstop=8 noexpandtab :
; 
; HTERM - Fast Model T Terminal with Hardware Flow Control
; Copyright (C) 2011 Speaker To Machines, Inc.
;
; Credits:
; Steve Adolph, Tandy 200 Port

#INCLUDE "ORIGIN.H"
#INCLUDE "CONFIG.H"

; Underlying queue size is 64 ($40) bytes.
LOW_WATER	.EQU	30 ; peer gets flowed on when pending < LOW_WATER
HIGH_WATER	.EQU	40 ; peer gets flowed off when pend > HIGH_WATER

; Include model-specific library and atypical system addresses
#if modeltype = 0
#include        "lib/M100rom_published_lib.asm"
#include        "lib/M100rom_unpublished_lib.asm"

INT_6_5		.EQU	$6DAF
CHARS_AVAIL	.EQU	$FF86

#else

#include        "lib/T200rom_published_lib.asm"
#include        "lib/T200rom_unpublished_lib.asm"

INT_6_5		.EQU	$854A
CHARS_AVAIL	.EQU	$FCF5

#endif

; HL has address to CALL
#DEFINE CALLHL() PUSH H\ LXI H,$+5\ XTHL\ PCHL

#DEFINE TRAN(state_id) LXI H,FSM + (state_id * N_EVENTS * 2)\ SHLD STATE_ROW_PTR

; Include utility macros  common to all platforms
#include	"lib/util_common_lib.asm"

ASC_ESC			.EQU		27


START_BYTE:

; -------------------------------------------------------------------------
; INIT routine
;
; One-time setup of:
;  * State machine, extended state
;  * Serial port parameters including baud rate
;  * Initial RTS, DTR state
;  * RX interrupt (6_5) hook
;  * Timer hook (TODO)
; -------------------------------------------------------------------------

INIT:			CALL		RESET_CHAR_STATE ; char machine
			TRAN(S_IDLE)

OPENPORT:

			LXI		H,SERPAR
			STC
			CALL		SETSER		; set up serial port
							; 19200 8N1 XON/XOFF disabled


#if modeltype=0
			; Assert RTS, DTR
			IN		$BA
			ANI		$3F	; set bit 7 and 6 = 0
			OUT		$BA	; bit 7 = RTS, bit 6 = DTR

#else
			; Assert RTS, DTR
			; bit 7        = 0, normal mode,
			; bit 6        = 0, no reset,
			; bit 5 (RTS)  = 1
			; bit 4:3      = 0, normal mode
			; bit 2 (RxEn) = 1
			; bit 1 (DSR)  = 1
			; bit 0 (TxEn) = 1
			; don't bother with loading from FCFE, initialize it
			MVI		A,00100111b		
			STA		$FCFE
			OUT		$CF

#endif

#if modeltype == 0
			; up baud rate to 38400bps
UPPER_DIV		.EQU		$ + 1
			MVI		A, 64
			OUT		$BD
LOWER_DIV:		.EQU		$ + 1
			MVI		A, 8
			OUT		$BC
			MVI		A, $C3
			OUT		$B8

; High baud rate on T200? Is it capable of 38400bps?
; Its display is faster so you would think it could keep up.

#endif
			; Install serial interrupt handler
			SET_HOOK(INT_6_5_HOOK,MY_INT_6_5)

; -------------------------------------------------------------------------
; MAIN PROCESSING LOOP
;
; Monitor event sources:
;  * RS232 Receive Queue
;  * Keyboard
;  * Timer/timeouts
;
; Detected events result in state machine triggers
; -------------------------------------------------------------------------

POLL_LOOP:


;; add extra check for full queue
;			LDA		CHARS_AVAIL	; # characters waiting in buffer
;			CPI		HIGH_WATER	; check against high-water mark
;			JC		DONE_RTS
;#if modeltype=0
;			IN		$BA
;			ORI		$80		; set bit 7
;			OUT		$BA		; deassert RTS (flow-off the peer)
;#else
;			LDA		$FCFE
;			ANI		11011111b	; bit 5 (RTS)=0;
;			STA		$FCFE
;			OUT		$CF		; deassert RTS (flow-off the peer)
;#endif
;
;DONE_RTS:

; --- Process received/enqueued characters

			CALL		RCVX		; RS232 pending?
			JZ		POLL_KEYBOARD
			CALL		RV232C  	; Dequeue char to A register

			; invoke char event handler
			LHLD		STATE_ROW_PTR
			XCHG
			LHLI
			CALLHL()

			; since we processed one character,
			; check pressure and assert RTS if relieved
			LDA		CHARS_AVAIL	; # characters waiting in buffer
			CPI		LOW_WATER
			JNC		POLL_LOOP
#if modeltype=0 	
			IN		$BA
			ANI		$7F		; bit 7 = 0
			OUT		$BA		; assert RTS (flow-on peer)
#else
			LDA		$FCFE
			ORI		00100000b	; bit 5 (RTS)=1;
			STA		$FCFE
			OUT		$CF		; assert RTS (flow-on peer)
#endif


POLL_KEYBOARD:		CALL		KYREAD
			JZ		POLL_TIMER
			PUSH		PSW		; preserve flags till dispatch
			LHLD		STATE_ROW_PTR
			LXI		D,E_KEY*2
			DAD		D
			XCHG
			LHLI
			POP		PSW
			CALLHL()

POLL_TIMER:		; stack the top of the poll loop so return to there
			LXI		H,POLL_LOOP
			PUSH		H
			
			LHLD		STATE_ROW_PTR
			INX		H
			INX		H
			XCHG
			LHLI

			PCHL

			; callee RETs to POLL_LOOP.
			;
			; nb: this will need to be altered if another polling stanza
			; is added following this one.

	
; --- ANSI+UTF-8 -> M100 Character Set Mapper
; 
; This code interprets inbound characters from the peer in order to discard them
; or map to characters that can be displayed.
;
; STATE MACHINE
; Master file: doc/diagrams/CharacterTranslationFSM.aco
; UTF-8 section is still TO BE IMPLEMENTED
;
;  -----.                     High bit set
;       v                  -------------------
; .----------.              Store # initial 1's
; | IDLE     |-------------------------------------------------------.
; |          |                                                       |
; |          |<------------------------.                             |
; |          |                         |     ASCII Non-ESC           |
; |          |<--------------------.   |  -------------------        v
; |          |                     |   |     Emit new char  .----------------.
; |          |------------------.  |   '--------------------| UTF8_GATHER    |
; |          |   ASCII ESC      |  |                        |                |
; |          |                  |  |                        |                |
; |          |                  |  |                        |                |
; |          |                  |  |      10 prefix         |                |
; |          |                  |  |      Last              |                |
; '----------'                  |  |   -------------------  |                |
;      ^    ^                   |  |     Append bits        |                |
;      |    |                   |  '------------------------|                |
;      |    |                   |                           |                |
;      |    |                   v                           |                |
;      |    |             .----------.                      |                |
;      |    |             | RECV_ESC |                      |                |
;      |    |             |          |  ASCII ESC           |                |
;      |    '-------------|          |<---------------------|                |
;      |           Non-[  |          |                 .----|                |
;      |         -------- '----------'                 |    '----------------'
;      |         Emit ESC       |                      |             ^
;      |                        |                      |             |
;      |                        | Recv CSI             |             |
;      |                        |     [                |             |
;      |                        |                      '-------------'
;      |                        v                               10 prefix 
;      |                .---------------.                       Not last  
;      |                | RECV_WAIT_CMD |                  -------------------
;      '----------------|               |---.                Append bits    
;   Final 64..126 char  |               |   |                Count-down byte
;                       '---------------'   |
;                                    ^      |
;                                    '------'
;                              Non-final ]64..126[ byte 
;
;
; Register usage:
;   Pointer to RECV_STATE maintained in H
;   C contains the new character to process
;

H_IDLE:			MOV		C,A
			CALL		CUROFF			; turn off cursor while printing
			TRAN(S_DISPLAY)
			MOV		A,C

; FALL-THROUGH to H_DISPLAY (free-ride)!
;
; The S_IDLE/S_DISPLAY division is to handle the state of cursor on vs. cursor off
; While there are characters available to process, that are likely to need
; to be displayed at some point, the cursor should be off.

H_DISPLAY:
			MOV		C,A			; save char unshifted
                        RLC
                        JC              COUNT_UTF8_INIT         ; handle UTF-8 'header'
			RRC
			CPI		ASC_ESC                 ; handle $27 (ESC)
			JZ		GOTO_ESC
			RST		4			; display the char
			RET
GOTO_ESC:		TRAN(S_ESC)
H_NULL:			RET

H_DISPPOLL:		CALL		RCVX
			RNZ
			CALL		CURSON
			TRAN(S_IDLE)
			RET


H_ESC:			CPI		'['			; do we have CSI?
			JZ		GOTO_WAIT_CMD		; yes, advance state
			CPI		']'				; do we have OSC (Xterm operating system command)?
			JZ		GOTO_OS_CMD
			MOV		C,A
			MVI		A,ASC_ESC		; else, disgorge ESC
			RST		4
			MOV		A,C
			RST		4			; send new char
			TRAN(S_DISPLAY)
			RET
GOTO_WAIT_CMD:		TRAN(S_WAIT_CMD)
			RET					; eat the '['

GOTO_OS_CMD:		TRAN(S_WAIT_OS_CMD)
			RET					; eat the ']'


H_UTF8_GATHER:		LXI		H,UTF8_CHAR		; append new char
			MOV		C,A			; copy new char
			LDA		UTF8_LEN
			MOV 		E,A
			MVI		D,0
			DAD		D
			MOV		M,C			; store new byte of utf-8 char
			INR		A			; increase length by one, and store
			STA		UTF8_LEN
			MOV		B,A
			MOV		A,C
			ANI		%11000000                                   	
			CPI		%10000000
			JNZ		EMIT_UTF8_RAW		; not utf-8; disgorge chars	

			LDA		UTF8_LIMIT
			CMP		B
			RNZ					; continue gathering characters

; Convert and display unicode character

			LDA		UTF8_LEN
			CPI		2
			JNZ		CHECK_PACK_3

; Decode 2-byte UTF-8 to unicode
; result in HL
; destroys DE register
PACK_2:

			; load 2 bytes, swap to Intel order, clear high bits
			LHLD		UTF8_CHAR
			MOV		A,H
			RAL				; align low byte to high bits
			RAL
			MOV		H,L
			MOV		L,A
			MOV		A,H
			ANI		%00011111
			MOV		H,A

			; align right
			SHLR
			SHLR
			JMP		MAP_IN_UNICODE

CHECK_PACK_3:
			CPI		3
			JNZ		STUB_CHAR

; Decode 3-byte UTF-8 to Unicode
; result in HL
; destroys DE register
; destroys C register
PACK_3:

			; load HL with 2 lowest bytes, swap to intel order
			LHLD		UTF8_CHAR+1
			MOV		A,H
			RAL
			RAL
			MOV		H,L
			MOV		L,A
			MOV		A,H
			ANI		%00111111
			MOV		H,A

			; HL has least significant bytes
			; C has most significant byte

			; align right
			SHLR
			SHLR

			; OR bits from prefix byte into most significant nibble 
			LDA		UTF8_CHAR
			ADD		A		; << 1
			ADD		A		; << 1
			ADD		A		; << 1
			ADD		A		; << 1
			ORA		H
			MOV		H,A

; Lookup Unicode mapping via Pearson Hash
; Uses 8 bit cipher
; Where U_msb = most significant and U_lsb = least significant byte
;  of unicode character,
; ndx = CIPHER[U_msb] ^ CIPHER[U_lsb], ^ = Bitwise XOR
; There are $0000, $00 sprinkled throughout the table so that 
; lookups for unsupported characters do not take too long.
; The table was generated via brute force using gen_ucode_inc.pl
; For now, linear search to find the Unicode -> Model T native mapping.
; eventually, change to a hash then linear search (for speed).


MAP_IN_UNICODE:

			MOV		B,H			; move char to find to BC
			MOV		C,L

			; hash unicode char to get table index
			LXI		H,CIPHER		; use cipher for fast hash function
			MOV		E,B
			MVI		D,0
			DAD		D
			MOV		A,M
			LXI		H,CIPHER
			MOV		E,C
			DAD		D
			XRA		M			; ndx = CIPHER[msb] ^ CIPHER[lsb]

			; verify in table range
			CPI		N_UNICODE
			JNC		STUB_CHAR

			; lookup entry starting at table index
			; nb: assumes D is already 0.
			MOV		E,A
			MOV		H,D
			MOV		L,E
			DAD		D			; offset = base + ndx * 3 (each entry is 3 bytes)
			DAD		D
			LXI		D,UNICODE-1
			DAD		D
			XCHG					; D is our pointer into lookup table

NEXT_CHAR:		INX		D			; skip past mapped 8-bit char
FIRST_CHAR:		LHLI					; HL = [DE], where [DE] is Unicode reference value

			MOV		A,H			; print stub char if passed last entry
			ORA		L
			JZ		STUB_CHAR
			HLMBC					; 16-bit subtraction to see if found entry
			INX		D			; advance DE to point to mapped char
			INX		D
			JNZ		NEXT_CHAR		; continue looping if not found
			LDAX		D			; get mapped char
SHOW_RESET:		RST		4
			CALL		RESET_CHAR_STATE
			TRAN(S_DISPLAY)
			RET
STUB_CHAR:

#ifdef dump_unknown_char
			LXI		H,UTF8_CHAR
			LDA		UTF8_LEN
			MOV		B,A
			CALL		DUMP_HEX
			CALL		DUMP_NEWLINE
#endif
			MVI		A,$FF
			JMP		SHOW_RESET



COUNT_UTF8_INIT:	MVI		B,0
COUNT_UTF8_NEXT:	INR             B
			ORA		A			; clear carry
			RLC
			JC		COUNT_UTF8_NEXT
STORE_UTF8_HDR:		MOV		A,B			; set # bytes to expect
			STA		UTF8_LIMIT
			MVI		A,1			; save current char length
			STA		UTF8_LEN
			MOV		A,C			; save the hdr byte
			STA		UTF8_CHAR
			TRAN(S_UTF8_GATHER)
			RET

EMIT_UTF8_RAW:		LDA		UTF8_LEN
			MOV		B,A
			LXI		H,UTF8_CHAR
NEXT_UTF8_RAW:		MOV		A,M
			RST		4
			INX		H
			DCR		B
			JNZ		NEXT_UTF8_RAW
			CALL		RESET_CHAR_STATE
			TRAN(S_DISPLAY)
			RET

RESET_CHAR_STATE:	LXI		H,UTF8_LIMIT
			XRA		A
			MOV		M,A
			INX		H
			MOV		M,A
			RET

H_WAIT_CMD:		CPI		$40
			RC
			CPI		$80
			RNC
			CALL		RESET_CHAR_STATE
			TRAN(S_DISPLAY)
			RET

H_WAIT_OS_CMD	CPI		$07
			JZ  CMD_DONE
			CPI		$9c
			JZ	CMD_DONE
			RET
CMD_DONE:	TRAN(S_DISPLAY)
			RET

	
H_KEY:			; if carry not set, it's a non-fkey. Just map, transmit, and return
			JC		CHECK_F6

			; map to unicode and transmit the character
SEND:			CPI		$80
			JC		SEND_BYTE

			; L <- index of unicode char descriptor
			SBI		$80
			LXI		H,NATIVE	; NATIVE table maps
			MOV		E,A
			MVI		D,0
			DAD		D
			MOV		E,M		; E has index to unicode char descriptor

			; nb: D must be left as zero by preceeding code

			; Point to unicode character descriptor: HL = UNICODE + DE * 3
			LXI		H,UNICODE
			DAD		D
			DAD		D
			DAD		D

			; Load HL with unicode character
			XCHG
			LHLI

			; Output as 2 or 3 byte character
			; 0080..07FF encodes as 2-byte UTF-8
			; 0800..FFFF encodes as 3-byte UTF-8
			MOV		A,H
			CPI		$08
			JNC		U8_SEND_3BYTE

U8_SEND_2BYTE:		MOV		A,L		; preserve unshifed low bits
			ANI		%00111111
			ORI		%10000000
			DAD		H		; shift two bits up into high byte
			DAD		H
			MOV		L,A
			MOV		A,H
			ORI		%11000000
			CALL		SD232C		; send the UTF-8 encoded character
			MOV		A,L
			CALL		SD232C
			RET

U8_SEND_3BYTE:		MOV		D,H		; save all
			MOV		E,L

			MOV		A,H		; byte #1
			ANA		A
			RAR
			RAR
			RAR
			RAR
			ORI		%11100000
			CALL		SD232C

			DAD		H		; byte #2
			DAD		H
			MOV		A,H
			ANI		%00111111
			ORI		%10000000
			CALL		SD232C

			MOV		A,E		; byte #3
			ANI		%00111111
			ORI		%10000000

SEND_BYTE:		CALL		SD232C
			RET

#if modeltype=0
			; handle scroll toggle (F6) to speed up term on long responses
CHECK_F6:		CPI		5
			JNZ		CHECK_F8
			LDA		$F63E		; From TOGGLE.100, P.Globman, 1990.
		        XRI		1
        		CALL		$4441
#else
			; handle scroll toggle (F6) to speed up term on long responses
CHECK_F6:		CPI		5
			JNZ		CHECK_F8
			LDA		$EF0B		; From TOGGLE.100, P.Globman, 1990.
		        XRI		1
        		CALL		$5170					
#endif

			; handle quit (F8), discard other function keys
CHECK_F8:		CPI		7
			RNZ

			; ensure that the laptop doesn't shut down immediately upon exit
			CALL		RSTINA		; reset the inactivity timer
			XRA		A
			STA		TMRSDN		; clear the shutdown flag

			; uninstall INT6.5 hook and exit to menu
			CLEAR_HOOK(INT_6_5_HOOK)
			POP		H		; drop return to idle loop
			RET				; exit HTERM


; Handler for INT6.5... just updates RTS and then
; then chains to the built in INT.6.5 handler
MY_INT_6_5:		

			PUSH	PSW

; add extra check for full queue
			LDA		CHARS_AVAIL	; # characters waiting in buffer
			CPI		HIGH_WATER	; check against high-water mark
			JC		DONE_RTS
#if modeltype=0
			IN		$BA
			ORI		$80		; set bit 7
			OUT		$BA		; deassert RTS (flow-off the peer)
#else
			LDA		$FCFE
			ANI		11011111b	; bit 5 (RTS)=0;
			STA		$FCFE
			OUT		$CF		; deassert RTS (flow-off the peer)
#endif

DONE_RTS:
			POP PSW

			; execute the default serial handler
			RET


#ifdef dump_unknown_char

; Damages: B
HL_HDR			.DB		"HL:"

DUMP_HL:		PUSH		H
			PUSH		B
			PUSH		D
			PUSH		PSW

			PUSH		H	
			LXI		H,HL_HDR
			MVI		A,3
			CALL		DUMP_STRING
			POP		H

			MOV		A,H
			STA		DISPLAY_HL
			MOV		A,L
			STA		DISPLAY_HL+1
			LXI		H,DISPLAY_HL
			MVI		B,2
			CALL		DUMP_HEX

			POP		PSW
			POP		D
			POP		B
			POP		H
			RET

; Print a string to debug port
; damages HL, A
DUMP_STRING:		PUSH		B
			MOV		B,A
NEXT_STR_CHAR:		MOV		A,M
			CALL		PRINTR
			INX		H
			DCR		B
			JNZ		NEXT_STR_CHAR
			POP		B
			RET

DUMP_NEWLINE:		PUSH		PSW
			MVI		A,$0A
			CALL		PRINTR
			MVI		A,$0D
			CALL		PRINTR
			POP		PSW
			RET

DUMP_A:
			PUSH H
			PUSH B
			PUSH D
			PUSH PSW
			MOV B,A
			MVI A,'<'
			CALL PRINTR
			MOV A,B
			LXI H,DISPLAY_HL
			MOV M,A
			MVI B,1
			CALL DUMP_HEX
			MVI A,'>'
			CALL PRINTR
			POP PSW
			POP D
			POP B
			POP H
			RET

; Dump byte array in hex
; M = addr of byte array
; B = # bytes to display
; Damages: M, B, A, E. Preserve on stack if you need these.
DUMP_HEX:		MVI		A,'['
			CALL		PRINTR

			XRA		A		; test B
			ORA		B
			JZ		END_DUMP

DUMP_HEX_AGAIN:		MOV		E,M		; get next char
			MOV		A,E		; save low nibble
			ORA		A		; clear carry
			RRC				; A >> 4
			RRC
			RRC
			RRC
			CALL		PRINT_NIBBLE	; print high nibble
			MOV		A,E		; print low nibble
			CALL		PRINT_NIBBLE
			INX		H		; array++, len--
			DCR		B
			JNZ		DUMP_HEX_AGAIN

END_DUMP:		MVI		A,']'
			CALL		PRINTR
			RET

PRINT_NIBBLE:		ANI		$0F
			CPI		$0A
			JM		LESS_THAN_10
			ADI		'A' - $0A	; find character code
			CALL		PRINTR
			RET
LESS_THAN_10:		ADI		'0'
			CALL		PRINTR
			RET

#endif	
			
			

; don't re-order without fixing code that resets variables en-masse
STATE_ROW_PTR		.DW		0
UTF8_LIMIT		.DB		0
UTF8_LEN		.DB		0
UTF8_CHAR		.BLOCK		6
DISPLAY_HL		.DB		$00,$00

#DEFINE DECL_CHAR(UNICODE,NATIVE)  .DW UNICODE\ .DB NATIVE
#DEFINE DECL_BLANK()  .DW $0000\ .DB $00

CIPHER:
;     x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF
;------------------------------------------------------------------
 .DB $FC,$21,$E0,$DA,$32,$14,$08,$13,$11,$07,$43,$2E,$0B,$29,$4D,$35 ; | 0x
 .DB $1E,$4A,$0C,$45,$38,$1C,$2F,$C4,$7C,$79,$F8,$82,$42,$17,$2A,$03 ; | 1x
 .DB $61,$97,$C2,$BE,$60,$7A,$5A,$8F,$C7,$80,$0E,$56,$3E,$10,$C5,$AD ; | 2x
 .DB $24,$3A,$E3,$6D,$70,$00,$AA,$7B,$1F,$26,$5F,$62,$27,$01,$BD,$20 ; | 3x
 .DB $C1,$34,$59,$B0,$4C,$FD,$37,$1A,$67,$4F,$40,$98,$83,$2D,$3D,$F6 ; | 4x
 .DB $7F,$F1,$EA,$25,$58,$ED,$9D,$9F,$E2,$A1,$BA,$9A,$F5,$74,$EF,$8A ; | 5x
 .DB $AB,$5B,$57,$8C,$F0,$75,$12,$C6,$78,$22,$B6,$6F,$FE,$8E,$A5,$66 ; | 6x
 .DB $F2,$D3,$46,$D4,$DC,$8D,$B7,$B5,$D0,$63,$6B,$16,$68,$09,$DF,$CD ; | 7x
 .DB $FF,$0D,$3F,$CF,$0F,$B8,$A4,$4E,$2C,$28,$9B,$49,$3B,$93,$95,$A8 ; | 8x
 .DB $1D,$A7,$30,$AE,$31,$E4,$33,$05,$36,$18,$3C,$EB,$2B,$44,$0A,$04 ; | 9x
 .DB $81,$5D,$D7,$C9,$D8,$94,$39,$A3,$A0,$86,$E6,$CA,$CC,$AF,$C0,$71 ; | Ax
 .DB $EE,$EC,$02,$E1,$72,$55,$D1,$85,$A2,$F9,$9E,$6A,$6C,$8B,$DD,$89 ; | Bx
 .DB $7E,$91,$A6,$47,$B2,$06,$88,$15,$52,$D2,$92,$7D,$E8,$73,$D6,$65 ; | Cx
 .DB $23,$90,$A9,$E9,$CE,$48,$AC,$DB,$DE,$51,$BF,$F4,$C8,$D9,$FA,$D5 ; | Dx
 .DB $B4,$77,$5C,$F7,$F3,$4B,$CB,$C3,$96,$BC,$B1,$B9,$B3,$E7,$69,$9C ; | Ex
 .DB $E5,$FB,$1B,$50,$6E,$84,$53,$19,$76,$54,$BB,$87,$64,$99,$5E,$41 ; | Fx

N_UNICODE	.EQU	176

UNICODE:
 DECL_CHAR($2020, $A8) ; (  0) DAGGER
 DECL_CHAR($2661, $9E) ; (  1) WHITE HEART SUIT
 DECL_BLANK()
 DECL_CHAR($2642, $95) ; (  3) MALE SIGN
 DECL_CHAR($25C0, $8F) ; (  4) BLACK LEFT-POINTING TRIANGLE
 DECL_CHAR($263A, $93) ; (  5) WHITE SMILING FACE
 DECL_CHAR($2518, $F7) ; (  6) BOX DRAWING LIGHT UP AND LEFT
 DECL_CHAR($00F1, $CD) ; (  7) LATIN SMALL LETTER N WITH TILDE
 DECL_CHAR($00DB, $D4) ; (  8) LATIN CAPITAL LETTER U WITH CIRCUMFLEX
 DECL_BLANK()
 DECL_CHAR($2534, $F8) ; ( 10) BOX DRAWING LIGHT UP AND HORIZONTAL
 DECL_CHAR($00E3, $CE) ; ( 11) LATIN SMALL LETTER A WITH TILDE
 DECL_BLANK()
 DECL_CHAR($2662, $9D) ; ( 13) WHITE DIAMOND SUIT
 DECL_BLANK()
 DECL_CHAR($00E4, $B6) ; ( 15) LATIN SMALL LETTER A WITH DIAERESIS
 DECL_CHAR($00B1, $8D) ; ( 16) PLUS-MINUS SIGN
 DECL_CHAR($0192, $BF) ; ( 17) LATIN SMALL LETTER F WITH HOOK
 DECL_CHAR($00B0, $A6) ; ( 18) DEGREE SIGN
 DECL_CHAR($005E, $C5) ; ( 19) CIRCUMFLEX ACCENT
 DECL_BLANK()
 DECL_CHAR($00D3, $DA) ; ( 21) LATIN CAPITAL LETTER O WITH ACUTE
 DECL_CHAR($25BC, $A7) ; ( 22) BLACK DOWN-POINTING TRIANGLE
 DECL_CHAR($260E, $80) ; ( 23) BLACK TELEPHONE
 DECL_CHAR($2019, $27) ; ( 24) RIGHT SINGLE QUOTE
 DECL_BLANK()
 DECL_CHAR($2524, $F9) ; ( 26) BOX DRAWING LIGHT VERTICAL AND LEFT
 DECL_CHAR($00ED, $C9) ; ( 27) LATIN SMALL LETTER I WITH ACUTE
 DECL_BLANK()
 DECL_CHAR($2018, $A4) ; ( 29) LEFT SINGLE QUOTE
 DECL_BLANK()
 DECL_CHAR($25CF, $E4) ; ( 31) BLACK CIRCLE
 DECL_BLANK()
 DECL_CHAR($00BE, $AD) ; ( 33) VULGAR FRACTION THREE QUARTERS
 DECL_BLANK()
 DECL_CHAR($201C, $22) ; ( 35) LEFT DOUBLE QUOTE
 DECL_CHAR($2013, $2D) ; ( 36) EN DASH
 DECL_CHAR($00DD, $DC) ; ( 37) LATIN CAPITAL LETTER Y WITH ACUTE
 DECL_CHAR($25E2, $FC) ; ( 38) BLACK LOWER RIGHT TRIANGLE
 DECL_CHAR($25A1, $9D) ; ( 39) WHITE SQUARE
 DECL_CHAR($02DC, $B5) ; ( 40) SMALL TILDE
 DECL_CHAR($00DF, $B9) ; ( 41) LATIN SMALL LETTER SHARP S
 DECL_CHAR($00CE, $D2) ; ( 42) LATIN CAPITAL LETTER I WITH CIRCUMFLEX
 DECL_CHAR($00A2, $B4) ; ( 43) CENT SIGN
 DECL_CHAR($200E, $00) ; ( 44) LEFT-TO-RIGHT MARK
 DECL_CHAR($00B6, $AF) ; ( 45) PILCROW SIGN
 DECL_CHAR($00C9, $D7) ; ( 46) LATIN CAPITAL LETTER E WITH ACUTE
 DECL_BLANK()
 DECL_CHAR($2191, $98) ; ( 48) UPWARDS ARROW
 DECL_CHAR($25E5, $FD) ; ( 49) BLACK UPPER RIGHT TRIANGLE
 DECL_CHAR($00D4, $D3) ; ( 50) LATIN CAPITAL LETTER O WITH CIRCUMFLEX
 DECL_BLANK()
 DECL_CHAR($00DC, $B3) ; ( 52) LATIN CAPITAL LETTER U WITH DIAERESIS
 DECL_CHAR($00A3, $A3) ; ( 53) POUND SIGN
 DECL_CHAR($00AB, $9B) ; ( 54) LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
 DECL_BLANK()
 DECL_CHAR($251C, $F4) ; ( 56) BOX DRAWING LIGHT VERTICAL AND RIGHT
 DECL_CHAR($2193, $99) ; ( 57) DOWNWARDS ARROW
 DECL_CHAR($221A, $89) ; ( 58) SQUARE ROOT
 DECL_CHAR($2026, $BE) ; ( 59) HORIZONTAL ELLIPSIS
 DECL_CHAR($00AE, $AA) ; ( 60) REGISTERED SIGN
 DECL_BLANK()
 DECL_CHAR($259D, $E2) ; ( 62) QUADRANT UPPER RIGHT
 DECL_CHAR($00E7, $A2) ; ( 63) LATIN SMALL LETTER C WITH CEDILLA
 DECL_CHAR($00E9, $BB) ; ( 64) LATIN SMALL LETTER E WITH ACUTE
 DECL_CHAR($258C, $E9) ; ( 65) LEFT HALF BLOCK
 DECL_CHAR($2514, $F6) ; ( 66) BOX DRAWING LIGHT UP AND RIGHT
 DECL_CHAR($00DA, $DB) ; ( 67) LATIN CAPITAL LETTER U WITH ACUTE
 DECL_CHAR($252C, $F3) ; ( 68) BOX DRAWING LIGHT DOWN AND HORIZONTAL
 DECL_CHAR($00EB, $C6) ; ( 69) LATIN SMALL LETTER E WITH DIAERESIS
 DECL_CHAR($259A, $E5) ; ( 70) QUADRANT UPPER LEFT AND LOWER RIGHT
 DECL_CHAR($00FA, $CB) ; ( 71) LATIN SMALL LETTER U WITH ACUTE
 DECL_CHAR($00E0, $A1) ; ( 72) LATIN SMALL LETTER A WITH GRAVE
 DECL_CHAR($2596, $E3) ; ( 73) QUADRANT LOWER LEFT
 DECL_CHAR($2592, $FF) ; ( 74) MEDIUM SHADE 50%
 DECL_CHAR($2608, $83) ; ( 75) THUNDERSTORM
 DECL_CHAR($2598, $E1) ; ( 76) QUADRANT UPPER LEFT
 DECL_CHAR($00EA, $C1) ; ( 77) LATIN SMALL LETTER E WITH CIRCUMFLEX
 DECL_CHAR($00C4, $B1) ; ( 78) LATIN CAPITAL LETTER A WITH DIAERESIS
 DECL_BLANK()
 DECL_CHAR($00D6, $B2) ; ( 80) LATIN CAPITAL LETTER O WITH DIAERESIS
 DECL_CHAR($259C, $EC) ; ( 81) QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
 DECL_CHAR($2606, $2A) ; ( 82) WHITE STAR
 DECL_BLANK()
 DECL_CHAR($200F, $00) ; ( 84) RIGHT-TO_LEFT MARK
 DECL_CHAR($2122, $BA) ; ( 85) TRADE MARK SIGN
 DECL_CHAR($2588, $EF) ; ( 86) FULL BLOCK
 DECL_CHAR($0060, $A4) ; ( 87) GRAVE ACCENT
 DECL_BLANK()
 DECL_CHAR($2014, $F1) ; ( 89) EM DASH
 DECL_CHAR($00C2, $D0) ; ( 90) LATIN CAPITAL LETTER A WITH CIRCUMFLEX
 DECL_CHAR($2501, $F1) ; ( 91) BOX DRAWING HEAVY HORIZONTAL
 DECL_CHAR($00A8, $BE) ; ( 92) DIAERESIS
 DECL_CHAR($253C, $FA) ; ( 93) BOX DRAWING LIGHT VERTICAL AND HORIZONTAL
 DECL_CHAR($2302, $86) ; ( 94) HOUSE
 DECL_CHAR($00A7, $A9) ; ( 95) SECTION SIGN
 DECL_CHAR($00EF, $C7) ; ( 96) LATIN SMALL LETTER I WITH DIAERESIS
 DECL_CHAR($237E, $90) ; ( 97) BELL SYMBOL
 DECL_CHAR($2599, $ED) ; ( 98) QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
 DECL_BLANK()
 DECL_CHAR($2510, $F2) ; (100) BOX DRAWING LIGHT DOWN AND LEFT
 DECL_CHAR($00FD, $CC) ; (101) LATIN SMALL LETTER Y WITH ACUTE
 DECL_CHAR($269A, $87) ; (102) STAFF OF HERMES
 DECL_CHAR($2590, $EA) ; (103) RIGHT HALF BLOCK
 DECL_CHAR($00A5, $B0) ; (104) YEN SIGN
 DECL_CHAR($2260, $8A) ; (105) NOT EQUAL TO
 DECL_CHAR($00E8, $BD) ; (106) LATIN SMALL LETTER E WITH GRAVE
 DECL_BLANK()
 DECL_CHAR($00D1, $CD) ; (108) LATIN CAPITAL LETTER N WITH TILDE
 DECL_CHAR($00C1, $D8) ; (109) LATIN CAPITAL LETTER A WITH ACUTE
 DECL_CHAR($00CA, $D1) ; (110) LATIN CAPITAL LETTER E WITH CIRCUMFLEX
 DECL_CHAR($260F, $81) ; (111) WHITE TELEPHONE
 DECL_CHAR($259E, $E6) ; (112) QUADRANT UPPER RIGHT AND LOWER LEFT
 DECL_CHAR($250C, $F0) ; (113) BOX DRAWING LIGHT DOWN AND RIGHT
 DECL_BLANK()
 DECL_CHAR($2195, $92) ; (115) UP-DOWN ARROW
 DECL_CHAR($226A, $8F) ; (116) MUCH LESS-THAN
 DECL_CHAR($2584, $E8) ; (117) LOWER HALF BLOCK
 DECL_CHAR($201D, $22) ; (118) RIGHT DOUBLE QUOTE
 DECL_CHAR($00BD, $AE) ; (119) VULGAR FRACTION ONE HALF
 DECL_CHAR($00F5, $CF) ; (120) LATIN SMALL LETTER O WITH TILDE
 DECL_CHAR($00B7, $9D) ; (121) MIDDLE DOT
 DECL_CHAR($00A9, $AB) ; (122) COPYRIGHT SIGN
 DECL_CHAR($00FB, $C4) ; (123) LATIN SMALL LETTER U WITH CIRCUMFLEX
 DECL_CHAR($2639, $94) ; (124) WHITE FROWING FACE
 DECL_CHAR($00A0, $20) ; (125) NO-BREAK SPACE
 DECL_CHAR($259F, $EE) ; (126) QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
 DECL_CHAR($2597, $E4) ; (127) QUADRANT LOWER RIGHT
 DECL_BLANK()
 DECL_CHAR($00CB, $D6) ; (129) LATIN CAPITAL LETTER E WITH DIAERESIS
 DECL_CHAR($00C0, $DF) ; (130) LATIN CAPITAL LETTER A WITH GRAVE
 DECL_CHAR($2105, $97) ; (131) CARE OF
 DECL_BLANK()
 DECL_CHAR($2580, $E7) ; (133) UPPER HALF BLOCK
 DECL_CHAR($2500, $F1) ; (134) BOX DRAWING LIGHT HORIZONTAL
 DECL_CHAR($2706, $82) ; (135) TELEPHONE LOCATION SIGN
 DECL_CHAR($2211, $8B) ; (136) N-ARY SUMMATION
 DECL_CHAR($25E4, $FB) ; (137) BLACK UPPER LEFT TRIANGLE
 DECL_CHAR($2190, $9B) ; (138) LEFTWARDS ARROW
 DECL_CHAR($00E1, $C8) ; (139) LATIN SMALL LETTER A WITH ACUTE
 DECL_BLANK()
 DECL_CHAR($25E3, $FE) ; (141) BLACK UPPER RIGHT TRIANGLE
 DECL_CHAR($00B4, $A0) ; (142) ACUTE ACCENT
 DECL_CHAR($00CD, $D9) ; (143) LATIN CAPITAL LETTER I WITH ACUTE
 DECL_CHAR($00BC, $AC) ; (144) VULGAR FRACTION ONE QUARTER
 DECL_CHAR($259B, $EB) ; (145) QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
 DECL_CHAR($00F4, $C3) ; (146) LATIN SMALL LETTER O WITH CIRCUMFLEX
 DECL_BLANK()
 DECL_CHAR($222B, $8E) ; (148) INTEGRAL
 DECL_CHAR($00EE, $C2) ; (149) LATIN SMALL LETTER I WITH CIRCUMFLEX
 DECL_CHAR($00BB, $9A) ; (150) RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
 DECL_CHAR($267F, $84) ; (151) WHEELCHAIR SYMBOL
 DECL_CHAR($00FC, $B8) ; (152) LATIN SMALL LETTER U WITH DIAERESIS
 DECL_CHAR($00CF, $D5) ; (153) LATIN CAPITAL LETTER I WITH DIAERESIS
 DECL_CHAR($2502, $F5) ; (154) BOX DRAWING LIGHT VERTICAL
 DECL_CHAR($2640, $96) ; (155) FEMALE SIGN
 DECL_CHAR($2667, $9C) ; (156) WHITE CLUB SUIT
 DECL_CHAR($0020, $E0) ; (157) SPACE
 DECL_CHAR($2708, $85) ; (158) AIRPLANE
 DECL_CHAR($262E, $91) ; (159) PEACE SYMBOL
 DECL_CHAR($00E2, $C0) ; (160) LATIN SMALL LETTER A WITH CIRCUMFLEX
 DECL_CHAR($00A1, $88) ; (161) INVERTED EXCLAMATION MARK
 DECL_BLANK()
 DECL_CHAR($2022, $A6) ; (163) BULLET
 DECL_BLANK()
 DECL_CHAR($2248, $8C) ; (165) ALMOST EQUAL TO
 DECL_BLANK()
 DECL_CHAR($2192, $9A) ; (167) RIGHTWARDS ARROW
 DECL_CHAR($00F9, $BC) ; (168) LATIN SMALL LETTER U WITH GRAVE
 DECL_CHAR($00B5, $A5) ; (169) MICRO SIGN
 DECL_CHAR($2664, $9F) ; (170) WHITE SPADE SUIT
 DECL_CHAR($25B6, $3E) ; (171) BLACK RIGHT-POINTING TRIANGLE
 DECL_CHAR($00F3, $CA) ; (172) LATIN SMALL LETTER O WITH ACUTE
 DECL_CHAR($00D9, $DD) ; (173) LATIN CAPITAL LETTER U WITH GRAVE
 DECL_CHAR($00C8, $DE) ; (174) LATIN CAPITAL LETTER E WITH GRAVE
 DECL_CHAR($00F6, $B7) ; (175) LATIN SMALL LETTER O WITH DIAERESIS
 .DW $0000

NATIVE:
 .DB 23  ; (80) BLACK TELEPHONE
 .DB 111 ; (81) WHITE TELEPHONE
 .DB 135 ; (82) TELEPHONE LOCATION SIGN
 .DB 75  ; (83) THUNDERSTORM
 .DB 151 ; (84) WHEELCHAIR SYMBOL
 .DB 158 ; (85) AIRPLANE
 .DB 94  ; (86) HOUSE
 .DB 102 ; (87) STAFF OF HERMES
 .DB 161 ; (88) INVERTED EXCLAMATION MARK
 .DB 58  ; (89) SQUARE ROOT
 .DB 105 ; (8A) NOT EQUAL TO
 .DB 136 ; (8B) N-ARY SUMMATION
 .DB 165 ; (8C) ALMOST EQUAL TO
 .DB 16  ; (8D) PLUS-MINUS SIGN
 .DB 148 ; (8E) INTEGRAL
 .DB 4   ; (8F) BLACK LEFT-POINTING TRIANGLE
 .DB 97  ; (90) BELL SYMBOL
 .DB 159 ; (91) PEACE SYMBOL
 .DB 115 ; (92) UP-DOWN ARROW
 .DB 5   ; (93) WHITE SMILING FACE
 .DB 124 ; (94) WHITE FROWING FACE
 .DB 3   ; (95) MALE SIGN
 .DB 155 ; (96) FEMALE SIGN
 .DB 131 ; (97) CARE OF
 .DB 48  ; (98) UPWARDS ARROW
 .DB 57  ; (99) DOWNWARDS ARROW
 .DB 167 ; (9A) RIGHTWARDS ARROW
 .DB 138 ; (9B) LEFTWARDS ARROW
 .DB 156 ; (9C) WHITE CLUB SUIT
 .DB 13  ; (9D) WHITE DIAMOND SUIT
 .DB 1   ; (9E) WHITE HEART SUIT
 .DB 170 ; (9F) WHITE SPADE SUIT
 .DB 142 ; (A0) ACUTE ACCENT
 .DB 72  ; (A1) LATIN SMALL LETTER A WITH GRAVE
 .DB 63  ; (A2) LATIN SMALL LETTER C WITH CEDILLA
 .DB 53  ; (A3) POUND SIGN
 .DB 87  ; (A4) GRAVE ACCENT
 .DB 169 ; (A5) MICRO SIGN
 .DB 18  ; (A6) DEGREE SIGN
 .DB 22  ; (A7) BLACK DOWN-POINTING TRIANGLE
 .DB 0   ; (A8) DAGGER
 .DB 95  ; (A9) SECTION SIGN
 .DB 60  ; (AA) REGISTERED SIGN
 .DB 122 ; (AB) COPYRIGHT SIGN
 .DB 144 ; (AC) VULGAR FRACTION ONE QUARTER
 .DB 33  ; (AD) VULGAR FRACTION THREE QUARTERS
 .DB 119 ; (AE) VULGAR FRACTION ONE HALF
 .DB 45  ; (AF) PILCROW SIGN
 .DB 104 ; (B0) YEN SIGN
 .DB 78  ; (B1) LATIN CAPITAL LETTER A WITH DIAERESIS
 .DB 80  ; (B2) LATIN CAPITAL LETTER O WITH DIAERESIS
 .DB 52  ; (B3) LATIN CAPITAL LETTER U WITH DIAERESIS
 .DB 43  ; (B4) CENT SIGN
 .DB 40  ; (B5) SMALL TILDE
 .DB 15  ; (B6) LATIN SMALL LETTER A WITH DIAERESIS
 .DB 175 ; (B7) LATIN SMALL LETTER O WITH DIAERESIS
 .DB 152 ; (B8) LATIN SMALL LETTER U WITH DIAERESIS
 .DB 41  ; (B9) LATIN SMALL LETTER SHARP S
 .DB 85  ; (BA) TRADE MARK SIGN
 .DB 64  ; (BB) LATIN SMALL LETTER E WITH ACUTE
 .DB 168 ; (BC) LATIN SMALL LETTER U WITH GRAVE
 .DB 106 ; (BD) LATIN SMALL LETTER E WITH GRAVE
 .DB 92  ; (BE) DIAERESIS
 .DB 17  ; (BF) LATIN SMALL LETTER F WITH HOOK
 .DB 160 ; (C0) LATIN SMALL LETTER A WITH CIRCUMFLEX
 .DB 77  ; (C1) LATIN SMALL LETTER E WITH CIRCUMFLEX
 .DB 149 ; (C2) LATIN SMALL LETTER I WITH CIRCUMFLEX
 .DB 146 ; (C3) LATIN SMALL LETTER O WITH CIRCUMFLEX
 .DB 123 ; (C4) LATIN SMALL LETTER U WITH CIRCUMFLEX
 .DB 19  ; (C5) CIRCUMFLEX ACCENT
 .DB 69  ; (C6) LATIN SMALL LETTER E WITH DIAERESIS
 .DB 96  ; (C7) LATIN SMALL LETTER I WITH DIAERESIS
 .DB 139 ; (C8) LATIN SMALL LETTER A WITH ACUTE
 .DB 27  ; (C9) LATIN SMALL LETTER I WITH ACUTE
 .DB 172 ; (CA) LATIN SMALL LETTER O WITH ACUTE
 .DB 71  ; (CB) LATIN SMALL LETTER U WITH ACUTE
 .DB 101 ; (CC) LATIN SMALL LETTER Y WITH ACUTE
 .DB 7   ; (CD) LATIN SMALL LETTER N WITH TILDE
 .DB 11  ; (CE) LATIN SMALL LETTER A WITH TILDE
 .DB 120 ; (CF) LATIN SMALL LETTER O WITH TILDE
 .DB 90  ; (D0) LATIN CAPITAL LETTER A WITH CIRCUMFLEX
 .DB 110 ; (D1) LATIN CAPITAL LETTER E WITH CIRCUMFLEX
 .DB 42  ; (D2) LATIN CAPITAL LETTER I WITH CIRCUMFLEX
 .DB 50  ; (D3) LATIN CAPITAL LETTER O WITH CIRCUMFLEX
 .DB 8   ; (D4) LATIN CAPITAL LETTER U WITH CIRCUMFLEX
 .DB 153 ; (D5) LATIN CAPITAL LETTER I WITH DIAERESIS
 .DB 129 ; (D6) LATIN CAPITAL LETTER E WITH DIAERESIS
 .DB 46  ; (D7) LATIN CAPITAL LETTER E WITH ACUTE
 .DB 109 ; (D8) LATIN CAPITAL LETTER A WITH ACUTE
 .DB 143 ; (D9) LATIN CAPITAL LETTER I WITH ACUTE
 .DB 21  ; (DA) LATIN CAPITAL LETTER O WITH ACUTE
 .DB 67  ; (DB) LATIN CAPITAL LETTER U WITH ACUTE
 .DB 37  ; (DC) LATIN CAPITAL LETTER Y WITH ACUTE
 .DB 173 ; (DD) LATIN CAPITAL LETTER U WITH GRAVE
 .DB 174 ; (DE) LATIN CAPITAL LETTER E WITH GRAVE
 .DB 130 ; (DF) LATIN CAPITAL LETTER A WITH GRAVE
 .DB 157 ; (E0) SPACE
 .DB 76  ; (E1) QUADRANT UPPER LEFT
 .DB 62  ; (E2) QUADRANT UPPER RIGHT
 .DB 73  ; (E3) QUADRANT LOWER LEFT
 .DB 127 ; (E4) QUADRANT LOWER RIGHT
 .DB 70  ; (E5) QUADRANT UPPER LEFT AND LOWER RIGHT
 .DB 112 ; (E6) QUADRANT UPPER RIGHT AND LOWER LEFT
 .DB 133 ; (E7) UPPER HALF BLOCK
 .DB 117 ; (E8) LOWER HALF BLOCK
 .DB 65  ; (E9) LEFT HALF BLOCK
 .DB 103 ; (EA) RIGHT HALF BLOCK
 .DB 145 ; (EB) QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
 .DB 81  ; (EC) QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
 .DB 98  ; (ED) QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
 .DB 126 ; (EE) QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
 .DB 86  ; (EF) FULL BLOCK
 .DB 113 ; (F0) BOX DRAWING LIGHT DOWN AND RIGHT
 .DB 134 ; (F1) BOX DRAWING LIGHT HORIZONTAL
 .DB 100 ; (F2) BOX DRAWING LIGHT DOWN AND LEFT
 .DB 68  ; (F3) BOX DRAWING LIGHT DOWN AND HORIZONTAL
 .DB 56  ; (F4) BOX DRAWING LIGHT VERTICAL AND RIGHT
 .DB 154 ; (F5) BOX DRAWING LIGHT VERTICAL
 .DB 66  ; (F6) BOX DRAWING LIGHT UP AND RIGHT
 .DB 6   ; (F7) BOX DRAWING LIGHT UP AND LEFT
 .DB 10  ; (F8) BOX DRAWING LIGHT UP AND HORIZONTAL
 .DB 26  ; (F9) BOX DRAWING LIGHT VERTICAL AND LEFT
 .DB 93  ; (FA) BOX DRAWING LIGHT VERTICAL AND HORIZONTAL
 .DB 137 ; (FB) BLACK UPPER LEFT TRIANGLE
 .DB 38  ; (FC) BLACK LOWER RIGHT TRIANGLE
 .DB 49  ; (FD) BLACK UPPER RIGHT TRIANGLE
 .DB 141 ; (FE) BLACK UPPER RIGHT TRIANGLE
 .DB 74  ; (FF) MEDIUM SHADE 50%

SERPAR:	
	
#if modeltype=0
			.DB		"98N1D",0
#else
			.DB		"98N1DNN",0
#endif

; State machine event IDs/indices
E_CHAR			.EQU		0
E_POLL			.EQU		1
E_KEY			.EQU		2
N_EVENTS		.EQU		3

; State machine state IDs/indices
S_IDLE			.EQU		0
S_DISPLAY		.EQU		1
S_ESC			.EQU		2
S_WAIT_CMD		.EQU		3
S_WAIT_OS_CMD	.EQU		4
S_UTF8_GATHER	.EQU		5

FSM:
;		E_CHAR				E_POLL				E_KEY
;		---------------		---------------		--------------	;
 .DW	H_IDLE			,	H_NULL		,		H_KEY			; S_IDLE
 .DW	H_DISPLAY		,	H_DISPPOLL	,		H_KEY			; S_DISPLAY
 .DW	H_ESC			,	H_NULL		,		H_KEY			; S_ESC
 .DW	H_WAIT_CMD		,	H_NULL		,		H_KEY			; S_WAIT_CMD
 .DW	H_WAIT_OS_CMD	,	H_NULL		,		H_KEY			; S_WAIT_OS_CMD
 .DW	H_UTF8_GATHER	,	H_NULL		,		H_KEY			; S_UTF8_GATHER

LAST_BYTE		.END
