mirror of
https://github.com/ksherlock/itty-bitty-vtty.git
synced 2024-06-02 03:41:31 +00:00
80edada6e9
I still don't support 132 mode but switching clears the screen, homes the cursor, and clears any scrolling regions, so it's necessary for passing the vttest suite.
900 lines
10 KiB
ArmAsm
900 lines
10 KiB
ArmAsm
|
||
|
||
lst off
|
||
cas se
|
||
|
||
rel
|
||
xc
|
||
xc
|
||
|
||
use vt.equ
|
||
use debug
|
||
|
||
mx %11
|
||
|
||
ext reset_tab,reset_all_tabs
|
||
ext recalc_cursor,recalc_cursor_x,recalc_cursor_y
|
||
ext erase_line_0,erase_line_1,erase_line_2
|
||
ext erase_screen_0,erase_screen_1,erase_screen_2
|
||
ext update_sgr
|
||
|
||
ext write_modem,write_modem_str
|
||
|
||
|
||
vt100_csi ent
|
||
debug vt100_csi
|
||
|
||
* 0123456789;ycnlhgrqJKmABCDHf
|
||
|
||
* based on testing -
|
||
* everything except '0' - '?' and control chars
|
||
* will finish.
|
||
* '?' only matters for h/l
|
||
* a misplaced ? (or anything in '0' - '?', except 0-9;)
|
||
* will cancel the sequence AFTER it's finished.
|
||
* < = > ? are allowed as an initial modifier but only '?' is private
|
||
* a mis-placed < = > ? will prevent 0x20-0x2f from terminating the sequence.
|
||
|
||
|
||
ldx #st_vt100
|
||
stx state
|
||
|
||
stz pcount
|
||
stz parms
|
||
stz parms+1 ; some assume 2 parms.
|
||
stz pmod
|
||
|
||
* tay ; save for modifier
|
||
cmp #:MIN
|
||
blt :rts
|
||
cmp #:MAX+1
|
||
bge :rts
|
||
sec
|
||
sbc #:MIN
|
||
asl
|
||
tax
|
||
jmp (:table,x)
|
||
|
||
*
|
||
:rts rts
|
||
|
||
|
||
|
||
:MIN equ 48
|
||
:MAX equ 121
|
||
:table
|
||
dw :digit ; 0
|
||
dw :digit ; 1
|
||
dw :digit ; 2
|
||
dw :digit ; 3
|
||
dw :digit ; 4
|
||
dw :digit ; 5
|
||
dw :digit ; 6
|
||
dw :digit ; 7
|
||
dw :digit ; 8
|
||
dw :digit ; 9
|
||
dw digit ; :
|
||
dw semi
|
||
dw :xmod ; <
|
||
dw :xmod ; =
|
||
dw :xmod ; >
|
||
dw :modifier ; ?
|
||
dw :rts ; @
|
||
dw csi_A ; A
|
||
dw csi_B ; B
|
||
dw csi_C ; C
|
||
dw csi_D ; D
|
||
dw :rts ; E
|
||
dw :rts ; F
|
||
dw :rts ; G
|
||
dw csi_H ; H
|
||
dw :rts ; I
|
||
dw csi_J ; J
|
||
dw csi_K ; K
|
||
dw :rts ; L
|
||
dw :rts ; M
|
||
dw :rts ; N
|
||
dw :rts ; O
|
||
dw :rts ; P
|
||
dw :rts ; Q
|
||
dw :rts ; R
|
||
dw :rts ; S
|
||
dw :rts ; T
|
||
dw :rts ; U
|
||
dw :rts ; V
|
||
dw :rts ; W
|
||
dw :rts ; X
|
||
dw :rts ; Y
|
||
dw :rts ; Z
|
||
dw :rts ; [
|
||
dw :rts ; \
|
||
dw :rts ; ]
|
||
dw :rts ; ^
|
||
dw :rts ; _
|
||
dw :rts ; `
|
||
dw :rts ; a
|
||
dw :rts ; b
|
||
dw csi_c ; c
|
||
dw :rts ; d
|
||
dw :rts ; e
|
||
dw csi_f ; f
|
||
dw csi_g ; g
|
||
dw csi_h ; h
|
||
dw :rts ; i
|
||
dw :rts ; j
|
||
dw :rts ; k
|
||
dw csi_l ; l
|
||
dw csi_m ; m
|
||
dw csi_n ; n
|
||
dw :rts ; o
|
||
dw :rts ; p
|
||
dw csi_q ; q
|
||
dw csi_r ; r
|
||
dw :rts ; s
|
||
dw :rts ; t
|
||
dw :rts ; u
|
||
dw :rts ; v
|
||
dw :rts ; w
|
||
dw :rts ; x
|
||
dw csi_y ; y
|
||
|
||
|
||
:digit
|
||
ldx #st_vt100_csi_2
|
||
stx state
|
||
|
||
lsr ; undo asl
|
||
sta parms
|
||
rts
|
||
:modifier
|
||
ldx #st_vt100_csi_2
|
||
stx state
|
||
|
||
lda #$80
|
||
sta pmod
|
||
rts
|
||
|
||
:xmod
|
||
* ignored.
|
||
ldx #st_vt100_csi_2
|
||
stx state
|
||
rts
|
||
|
||
vt100_csi_bad ent
|
||
cmp #'@'
|
||
blt :rts
|
||
ldx #st_vt100
|
||
stx state
|
||
:rts rts
|
||
|
||
|
||
|
||
vt100_csi_2 ent
|
||
debug vt100_csi_2
|
||
|
||
ldx #st_vt100
|
||
stx state
|
||
|
||
cmp #:MIN
|
||
blt :rts
|
||
cmp #:MAX+1
|
||
bge :rts
|
||
sec
|
||
sbc #:MIN
|
||
asl
|
||
tax
|
||
jmp (:table,x)
|
||
|
||
:rts rts
|
||
|
||
:MIN equ 48
|
||
:MAX equ 121
|
||
:table
|
||
dw digit ; 0
|
||
dw digit ; 1
|
||
dw digit ; 2
|
||
dw digit ; 3
|
||
dw digit ; 4
|
||
dw digit ; 5
|
||
dw digit ; 6
|
||
dw digit ; 7
|
||
dw digit ; 8
|
||
dw digit ; 9
|
||
dw digit ; :
|
||
dw semi
|
||
dw :modifier ; <
|
||
dw :modifier ; =
|
||
dw :modifier ; >
|
||
dw :modifier ; ?
|
||
dw :rts ; @
|
||
dw csi_A ; A
|
||
dw csi_B ; B
|
||
dw csi_C ; C
|
||
dw csi_D ; D
|
||
dw :rts ; E
|
||
dw :rts ; F
|
||
dw :rts ; G
|
||
dw csi_H ; H
|
||
dw :rts ; I
|
||
dw csi_J ; J
|
||
dw csi_K ; K
|
||
dw :rts ; L
|
||
dw :rts ; M
|
||
dw :rts ; N
|
||
dw :rts ; O
|
||
dw :rts ; P
|
||
dw :rts ; Q
|
||
dw :rts ; R
|
||
dw :rts ; S
|
||
dw :rts ; T
|
||
dw :rts ; U
|
||
dw :rts ; V
|
||
dw :rts ; W
|
||
dw :rts ; X
|
||
dw :rts ; Y
|
||
dw :rts ; Z
|
||
dw :rts ; [
|
||
dw :rts ; \
|
||
dw :rts ; ]
|
||
dw :rts ; ^
|
||
dw :rts ; _
|
||
dw :rts ; `
|
||
dw :rts ; a
|
||
dw :rts ; b
|
||
dw csi_c ; c
|
||
dw :rts ; d
|
||
dw :rts ; e
|
||
dw csi_f ; f
|
||
dw csi_g ; g
|
||
dw csi_h ; h
|
||
dw :rts ; i
|
||
dw :rts ; j
|
||
dw :rts ; k
|
||
dw csi_l ; l
|
||
dw csi_m ; m
|
||
dw csi_n ; n
|
||
dw :rts ; o
|
||
dw :rts ; p
|
||
dw csi_q ; q
|
||
dw csi_r ; r
|
||
dw :rts ; s
|
||
dw :rts ; t
|
||
dw :rts ; u
|
||
dw :rts ; v
|
||
dw :rts ; w
|
||
dw csi_x ; x
|
||
dw csi_y ; y
|
||
|
||
:modifier
|
||
ldx #st_vt100_csi_bad
|
||
stx state
|
||
rts
|
||
|
||
semi
|
||
ldx #st_vt100_csi_2
|
||
stx state
|
||
|
||
ldx pcount
|
||
cpx #MAX_PCOUNT
|
||
bge :big
|
||
|
||
inx
|
||
stx pcount
|
||
:big stz parms,x
|
||
:rts rts
|
||
|
||
* parameter digit. clamped to 255 (250+ rounds up to 255)
|
||
* in 132 is the largest valid parameter so this is ok.
|
||
digit
|
||
ldx #st_vt100_csi_2
|
||
stx state
|
||
|
||
lsr ; undo asl
|
||
sta r0
|
||
ldx pcount
|
||
lda parms,x
|
||
* cmp #255
|
||
* beq :rts
|
||
cmp #25
|
||
bge :v
|
||
|
||
tay
|
||
lda :mult,y
|
||
* clc ; cleared via cmp
|
||
adc r0
|
||
sta parms,x
|
||
|
||
|
||
:rts
|
||
rts
|
||
:v
|
||
lda #$255
|
||
sta parms,x
|
||
rts
|
||
|
||
:mult db 0,10,20,30,40,50,60,70,80,90
|
||
db 100,110,120,130,140,150,160,170,180,190
|
||
db 200,210,220,230,240,250
|
||
|
||
|
||
|
||
csi_h
|
||
; esc [ ... h (vt100)
|
||
; esc [ ? ... h (private)
|
||
ldy #$80
|
||
bra mode_common
|
||
|
||
csi_l
|
||
; esc [ ... l (vt100)
|
||
; esc [ ? ... l (private)
|
||
ldy #0
|
||
|
||
mode_common
|
||
inc pcount
|
||
ldx #0
|
||
:loop lda parms,x
|
||
cmp #:MIN
|
||
blt :next
|
||
cmp #:MAX+1
|
||
bge :next
|
||
phx
|
||
asl
|
||
tax
|
||
jsr (:table,x)
|
||
plx
|
||
|
||
:next inx
|
||
cpx pcount
|
||
blt :loop
|
||
:rts rts
|
||
|
||
:MIN equ 0
|
||
:MAX equ 20
|
||
:table
|
||
dw :rts ; error
|
||
dw mode_DECCKM
|
||
dw mode_DECANM
|
||
dw mode_DECCOLM ; DECCOLM
|
||
dw :rts ; DECSCLM
|
||
dw mode_DECSCNM
|
||
dw mode_DECOM
|
||
dw mode_DECAWM
|
||
dw mode_DECARM
|
||
dw :rts ; DECINLM
|
||
dw :rts ; 10
|
||
dw :rts ; 11
|
||
dw :rts ; 12
|
||
dw :rts ; 13
|
||
dw :rts ; 14
|
||
dw :rts ; 15
|
||
dw :rts ; 16
|
||
dw :rts ; 17
|
||
dw :rts ; 18
|
||
dw :rts ; 19
|
||
dw mode_LNM
|
||
*:mask dw 0,$40,$40,$40,$40,$40,$40,$40,$40,$40
|
||
* dw 0,0,0,0,0,0,0,0,0,0,0
|
||
|
||
|
||
mode_DECCKM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECCKM
|
||
:rts rts
|
||
|
||
mode_DECANM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECANM
|
||
cpy #0
|
||
bne :rts
|
||
* switch to vt52 mode
|
||
ldx #st_vt52
|
||
stx state
|
||
:rts rts
|
||
|
||
|
||
mode_DECCOLM
|
||
* 80/132 mode.
|
||
* vt102 guide states:
|
||
* NOTE: When you change the number of columns per line, the screen is erased.
|
||
* This also sets the scrolling region for full screen (24 lines).
|
||
*
|
||
* based on testing, this always clears the screen and resets x/y, regardless of current mode.
|
||
*
|
||
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECCOLM
|
||
|
||
lda #0
|
||
sta DECTM
|
||
lda #23
|
||
sta DECBM
|
||
stz x
|
||
stz y
|
||
|
||
phy
|
||
jsr recalc_cursor
|
||
jsr erase_screen_2
|
||
ply
|
||
|
||
:rts rts
|
||
|
||
mode_DECSCNM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
* todo - invert on-screen characters?
|
||
sty DECSCNM
|
||
:rts rts
|
||
|
||
mode_DECOM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECOM
|
||
; move to the new home position
|
||
stz x
|
||
stz y
|
||
cpy #0
|
||
beq :rts
|
||
lda DECTM
|
||
sta y
|
||
|
||
phy
|
||
jsr recalc_cursor
|
||
ply
|
||
|
||
:rts rts
|
||
|
||
mode_DECAWM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECAWM
|
||
:rts rts
|
||
|
||
mode_DECARM
|
||
bit pmod
|
||
bpl :rts
|
||
|
||
sty DECARM
|
||
:rts rts
|
||
|
||
mode_LNM
|
||
bit pmod
|
||
bmi :rts
|
||
|
||
sty LNM
|
||
:rts rts
|
||
|
||
|
||
csi_m
|
||
* esc [ ... m
|
||
* 0 - attributes off
|
||
* 1 - bold
|
||
* 4 - underscore
|
||
* 5 - blink
|
||
* 7 - inverted
|
||
|
||
inc pcount
|
||
ldx #0
|
||
:loop lda parms,x
|
||
cmp #8
|
||
bge :next
|
||
tay
|
||
lda SGR
|
||
and :and,y
|
||
ora :or,y
|
||
sta SGR
|
||
|
||
:next inx
|
||
cpx pcount
|
||
blt :loop
|
||
|
||
jmp update_sgr
|
||
|
||
|
||
|
||
:and db $00,$ff,$ff,$ff,$ff,$ff,$ff,$ff
|
||
|
||
:or db %0000_0000,%0000_0010,%0000_0000,%0000_0000
|
||
db %0001_0000,%0010_0000,%0000_0000,%1000_0000
|
||
|
||
|
||
|
||
csi_g
|
||
* ESC [ g, ESC [ 0 g - clear tab at column
|
||
* ESC [ 3 g - clear all tabs
|
||
|
||
lda parms
|
||
beq :0
|
||
cmp #3
|
||
beq :3
|
||
rts
|
||
|
||
:0 ldx x
|
||
jmp reset_tab
|
||
:3 jmp reset_all_tabs
|
||
|
||
|
||
p1 mac
|
||
lda parms
|
||
bne ok
|
||
lda #1
|
||
ok sta parms
|
||
<<<
|
||
|
||
* cursor movement.
|
||
* if private mode, no effect.
|
||
csi_A
|
||
* up
|
||
|
||
* if cursor is outside the scrolling region, it is not locked to the scrolling region.
|
||
|
||
bit pmod
|
||
bmi :rts
|
||
|
||
p1
|
||
|
||
lda y
|
||
cmp DECTM
|
||
beq :rts
|
||
bcc :simple
|
||
|
||
sec
|
||
sbc parms
|
||
bcc :top
|
||
cmp DECTM
|
||
* bcc :top
|
||
* bra :sta
|
||
bcs :sta
|
||
|
||
:top lda DECTM
|
||
bra :sta
|
||
:rts rts
|
||
|
||
|
||
:simple
|
||
* lda y
|
||
sec
|
||
sbc parms
|
||
* bcc :0 ; clear indicate underflow.
|
||
bcc :sta
|
||
:0 lda #0
|
||
:sta sta y
|
||
jmp recalc_cursor_y
|
||
|
||
csi_B
|
||
* down
|
||
|
||
bit pmod
|
||
bmi :rts
|
||
|
||
p1
|
||
|
||
lda y
|
||
cmp DECBM
|
||
beq :rts
|
||
bge :simple
|
||
|
||
clc
|
||
adc parms
|
||
bcs :bottom ; overflow
|
||
cmp DECBM
|
||
bcc :sta
|
||
|
||
:bottom lda DECBM
|
||
bra :sta
|
||
:rts rts
|
||
|
||
:simple
|
||
clc
|
||
adc parms
|
||
bcs :23 ; overflow
|
||
cmp #24
|
||
bcc :sta
|
||
|
||
:23 lda #23
|
||
:sta sta y
|
||
jmp recalc_cursor_y
|
||
|
||
csi_C
|
||
* right
|
||
* in column 80, no effect.
|
||
|
||
bit pmod
|
||
bmi :rts
|
||
|
||
lda x
|
||
cmp #79
|
||
bcs :rts
|
||
|
||
p1
|
||
lda x
|
||
* and #$7f
|
||
|
||
clc
|
||
adc parms
|
||
bcs :79 ; overflow
|
||
cmp #80
|
||
bcc :sta
|
||
|
||
:79 lda #79
|
||
:sta sta x
|
||
jmp recalc_cursor_x
|
||
:rts rts
|
||
|
||
csi_D
|
||
* left
|
||
|
||
bit pmod
|
||
bmi :rts
|
||
|
||
p1
|
||
|
||
lda x
|
||
and #$7f
|
||
|
||
sec
|
||
sbc parms
|
||
* bcc :0 ; underflow
|
||
bcs :sta
|
||
:0 lda #0
|
||
:sta sta x
|
||
jmp recalc_cursor_x
|
||
:rts rts
|
||
|
||
|
||
csi_f
|
||
csi_H ; direct cursor addressing
|
||
|
||
debug csi_H
|
||
|
||
|
||
* honors origin
|
||
* large numbers are clamped
|
||
* 0 or 1 treated as 1 (1-based counting)
|
||
|
||
* based on testing, esc [ 253-255 H will position outside the scrolling
|
||
* region when DECOM is active (to first 3 lines, respectively)
|
||
* this is not emulated.
|
||
|
||
* y
|
||
lda parms
|
||
beq :yy
|
||
dec
|
||
:yy bit DECOM
|
||
bmi :org
|
||
cmp #23
|
||
blt :yyy
|
||
lda #23
|
||
:yyy sta y
|
||
bra :x
|
||
|
||
|
||
:org
|
||
clc
|
||
adc DECTM
|
||
cmp DECBM
|
||
blt :org1
|
||
lda DECBM
|
||
:org1 sta y
|
||
|
||
* x
|
||
:x
|
||
ldx parms+1
|
||
beq :xx
|
||
dex
|
||
:xx
|
||
cpx #79
|
||
blt :xxx
|
||
ldx #79
|
||
:xxx stx x
|
||
|
||
jmp recalc_cursor
|
||
|
||
csi_r ; scrolling region
|
||
debug csi_r
|
||
* based on testing
|
||
* esc [ n r (no second parmeter) is equivalent to esc [ n ; 24 r
|
||
* esc [ r sets scrolling region to 1 ; 24 ( in accordance with above )
|
||
* 24 is assumed value for second parameter
|
||
* invalid parameters exit without updating
|
||
|
||
* based on testing, row parameters are not affected by DECOM.
|
||
|
||
lda parms
|
||
beq :p1
|
||
dec parms
|
||
:p1
|
||
|
||
lda parms+1
|
||
beq :p2
|
||
dec parms+1
|
||
bra :check
|
||
|
||
:p2 lda #23
|
||
sta parms+1
|
||
|
||
:check
|
||
* 23 max
|
||
ldx parms+0
|
||
cpx #23+1
|
||
bge :rts
|
||
|
||
ldx parms+1
|
||
cpx #23+1
|
||
bge :rts
|
||
|
||
|
||
* must be at least 1 line
|
||
lda parms+1
|
||
sec
|
||
sbc parms
|
||
beq :rts
|
||
bmi :rts
|
||
|
||
* move cursor to origin.
|
||
lda parms
|
||
sta DECTM
|
||
sta y
|
||
lda parms+1
|
||
sta DECBM
|
||
stz x
|
||
bit DECOM
|
||
bmi :j
|
||
stz y
|
||
:j jmp recalc_cursor
|
||
|
||
:rts rts
|
||
|
||
csi_J ; erase screen
|
||
|
||
lda parms
|
||
cmp #2+1
|
||
bcs :rts
|
||
asl
|
||
tax
|
||
jmp (:table,x)
|
||
|
||
:rts rts
|
||
|
||
:table
|
||
dw erase_screen_0
|
||
dw erase_screen_1
|
||
dw erase_screen_2
|
||
|
||
csi_K ; erase line
|
||
|
||
lda parms
|
||
cmp #2+1
|
||
bcs :rts
|
||
asl
|
||
tax
|
||
jmp (:table,x)
|
||
|
||
:rts rts
|
||
|
||
:table
|
||
dw erase_line_0
|
||
dw erase_line_1
|
||
dw erase_line_2
|
||
|
||
csi_q ; LEDs
|
||
rts
|
||
csi_n ; status report
|
||
|
||
bit LOCAL
|
||
bmi :rts
|
||
lda parms
|
||
cmp #5
|
||
beq :dsr
|
||
cmp #6
|
||
beq :cpr
|
||
:rts rts
|
||
:dsr ; report status
|
||
lda #ESC
|
||
jsr write_modem
|
||
lda #'['
|
||
jsr write_modem
|
||
lda #'0'
|
||
jsr write_modem
|
||
lda #'n'
|
||
jmp write_modem
|
||
:cpr ; cursor report
|
||
* returned y is in terms of DECOM.
|
||
lda #ESC
|
||
jsr write_modem
|
||
lda #'['
|
||
jsr write_modem
|
||
|
||
lda y
|
||
bit DECOM
|
||
bpl :y
|
||
sec
|
||
sbc DECTM
|
||
|
||
:y inc
|
||
jsr write_digit
|
||
lda #';'
|
||
jsr write_modem
|
||
lda x
|
||
inc
|
||
jsr write_digit
|
||
lda #'R'
|
||
jmp write_modem
|
||
|
||
|
||
write_digit
|
||
* digit must be in the range 1-80
|
||
cmp #10
|
||
bcs :multi
|
||
:0 ora #'0'
|
||
jmp write_modem
|
||
:multi
|
||
ldx #8
|
||
]loop cmp :table,x
|
||
bcs :ok
|
||
dex
|
||
bra ]loop
|
||
|
||
:ok sec
|
||
sbc :table,x
|
||
pha ; save
|
||
txa
|
||
ora #'0'
|
||
jsr write_modem
|
||
pla
|
||
bra :0
|
||
|
||
:table db 0,10,20,30,40,50,60,70,80
|
||
|
||
csi_c ; what are you?
|
||
* DA - Device Attributes
|
||
|
||
mx %11
|
||
|
||
php
|
||
rep #$10 ; long x/y
|
||
ldy #:response
|
||
jsr write_modem_str
|
||
plp
|
||
rts
|
||
|
||
:response asc 1b,'[?1;0c',00 ; No options.
|
||
|
||
csi_y ; invoke confidence test
|
||
* ???
|
||
rts
|
||
|
||
|
||
|
||
csi_x ; request terminal parameters
|
||
* DECREQTPARM – Request Terminal Parameters
|
||
|
||
mx %11
|
||
|
||
lda parms
|
||
cmp #2
|
||
bcs :rts
|
||
inc
|
||
inc
|
||
ora #'0'
|
||
sta :response+2
|
||
|
||
php
|
||
rep #$10 ; long x/y
|
||
ldy #:response
|
||
jsr write_modem_str
|
||
plp
|
||
:rts rts
|
||
|
||
:response asc 1b,'[x;1;1;112;112;1;0x',00 ; no parity, 8-bits, 9600/9600, 16x multiplier, no stp flags.
|
||
|
||
sav vt100.csi.L
|