itty-bitty-vtty/vt100.csi.S

900 lines
10 KiB
ArmAsm
Raw Normal View History

2021-09-25 17:57:27 +00:00
lst off
2021-09-05 00:27:42 +00:00
cas se
rel
xc
xc
use vt.equ
2021-09-25 15:05:06 +00:00
use debug
mx %11
2021-09-19 22:49:29 +00:00
ext reset_tab,reset_all_tabs
ext recalc_cursor,recalc_cursor_x,recalc_cursor_y
2021-09-26 01:27:48 +00:00
ext erase_line_0,erase_line_1,erase_line_2
ext erase_screen_0,erase_screen_1,erase_screen_2
2022-01-29 15:43:09 +00:00
ext update_sgr
2021-09-26 01:27:48 +00:00
ext write_modem,write_modem_str
vt100_csi ent
2021-09-25 15:05:06 +00:00
debug vt100_csi
2021-09-05 00:27:42 +00:00
* 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.
2021-09-25 17:57:27 +00:00
ldx #st_vt100
stx state
stz pcount
stz parms
stz parms+1 ; some assume 2 parms.
stz pmod
2021-09-05 00:27:42 +00:00
* tay ; save for modifier
cmp #:MIN
2021-09-25 17:57:27 +00:00
blt :rts
cmp #:MAX+1
2021-09-25 17:57:27 +00:00
bge :rts
sec
sbc #:MIN
asl
tax
jmp (:table,x)
2021-09-05 00:27:42 +00:00
*
: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
2021-09-25 17:57:27 +00:00
dw :xmod ; <
dw :xmod ; =
dw :xmod ; >
dw :modifier ; ?
2021-09-25 17:57:27 +00:00
dw :rts ; @
2021-09-05 00:27:42 +00:00
dw csi_A ; A
dw csi_B ; B
dw csi_C ; C
dw csi_D ; D
2021-09-25 17:57:27 +00:00
dw :rts ; E
dw :rts ; F
dw :rts ; G
2021-09-05 00:27:42 +00:00
dw csi_H ; H
2021-09-25 17:57:27 +00:00
dw :rts ; I
2021-09-05 00:27:42 +00:00
dw csi_J ; J
dw csi_K ; K
2021-09-25 17:57:27 +00:00
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
2021-09-05 00:27:42 +00:00
dw csi_c ; c
2021-09-25 17:57:27 +00:00
dw :rts ; d
dw :rts ; e
2021-09-05 00:27:42 +00:00
dw csi_f ; f
dw csi_g ; g
dw csi_h ; h
2021-09-25 17:57:27 +00:00
dw :rts ; i
dw :rts ; j
dw :rts ; k
2021-09-05 00:27:42 +00:00
dw csi_l ; l
dw csi_m ; m
dw csi_n ; n
2021-09-25 17:57:27 +00:00
dw :rts ; o
dw :rts ; p
2021-09-05 00:27:42 +00:00
dw csi_q ; q
dw csi_r ; r
2021-09-25 17:57:27 +00:00
dw :rts ; s
dw :rts ; t
dw :rts ; u
dw :rts ; v
dw :rts ; w
dw :rts ; x
2021-09-05 00:27:42 +00:00
dw csi_y ; y
:digit
2021-09-25 17:57:27 +00:00
ldx #st_vt100_csi_2
stx state
lsr ; undo asl
sta parms
rts
:modifier
2021-09-25 17:57:27 +00:00
ldx #st_vt100_csi_2
stx state
2021-09-05 00:27:42 +00:00
lda #$80
sta pmod
rts
2021-09-25 17:57:27 +00:00
:xmod
* ignored.
ldx #st_vt100_csi_2
stx state
rts
2021-09-05 00:27:42 +00:00
vt100_csi_bad ent
cmp #'@'
2021-09-05 00:27:42 +00:00
blt :rts
ldx #st_vt100
stx state
2021-09-05 00:27:42 +00:00
:rts rts
vt100_csi_2 ent
2021-09-25 15:05:06 +00:00
debug vt100_csi_2
2021-09-25 17:57:27 +00:00
ldx #st_vt100
stx state
2021-09-05 00:27:42 +00:00
cmp #:MIN
2021-09-25 17:57:27 +00:00
blt :rts
cmp #:MAX+1
2021-09-25 17:57:27 +00:00
bge :rts
sec
sbc #:MIN
2021-09-25 15:05:06 +00:00
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 ; ?
2021-09-25 17:57:27 +00:00
dw :rts ; @
2021-09-05 00:27:42 +00:00
dw csi_A ; A
dw csi_B ; B
dw csi_C ; C
dw csi_D ; D
2021-09-25 17:57:27 +00:00
dw :rts ; E
dw :rts ; F
dw :rts ; G
2021-09-05 00:27:42 +00:00
dw csi_H ; H
2021-09-25 17:57:27 +00:00
dw :rts ; I
2021-09-05 00:27:42 +00:00
dw csi_J ; J
dw csi_K ; K
2021-09-25 17:57:27 +00:00
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
2021-09-05 00:27:42 +00:00
dw csi_c ; c
2021-09-25 17:57:27 +00:00
dw :rts ; d
dw :rts ; e
2021-09-05 00:27:42 +00:00
dw csi_f ; f
dw csi_g ; g
dw csi_h ; h
2021-09-25 17:57:27 +00:00
dw :rts ; i
dw :rts ; j
dw :rts ; k
2021-09-05 00:27:42 +00:00
dw csi_l ; l
dw csi_m ; m
dw csi_n ; n
2021-09-25 17:57:27 +00:00
dw :rts ; o
dw :rts ; p
2021-09-05 00:27:42 +00:00
dw csi_q ; q
dw csi_r ; r
2021-09-25 17:57:27 +00:00
dw :rts ; s
dw :rts ; t
dw :rts ; u
dw :rts ; v
dw :rts ; w
dw csi_x ; x
2021-09-05 00:27:42 +00:00
dw csi_y ; y
:modifier
2021-09-05 00:27:42 +00:00
ldx #st_vt100_csi_bad
stx state
rts
semi
2021-09-25 17:57:27 +00:00
ldx #st_vt100_csi_2
stx state
ldx pcount
cpx #MAX_PCOUNT
2021-09-05 00:27:42 +00:00
bge :big
inx
stx pcount
2021-09-05 00:27:42 +00:00
: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
2021-09-25 17:57:27 +00:00
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
2021-09-05 00:27:42 +00:00
lda :mult,y
* clc ; cleared via cmp
2021-09-05 00:27:42 +00:00
adc r0
sta parms,x
:rts
rts
:v
lda #$255
sta parms,x
rts
2021-09-25 17:57:27 +00:00
: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
2021-09-05 00:27:42 +00:00
csi_h
; esc [ ... h (vt100)
; esc [ ? ... h (private)
ldy #$80
bra mode_common
2021-09-05 00:27:42 +00:00
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
2021-09-05 00:27:42 +00:00
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
2021-09-05 00:27:42 +00:00
bpl :rts
sty DECCKM
:rts rts
mode_DECANM
bit pmod
2021-09-05 00:27:42 +00:00
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
2021-09-05 00:27:42 +00:00
bpl :rts
* todo - invert on-screen characters?
sty DECSCNM
:rts rts
mode_DECOM
bit pmod
2021-09-05 00:27:42 +00:00
bpl :rts
sty DECOM
; move to the new home position
stz x
stz y
cpy #0
beq :rts
2021-09-23 21:16:10 +00:00
lda DECTM
sta y
phy
2021-09-19 22:49:29 +00:00
jsr recalc_cursor
ply
:rts rts
mode_DECAWM
bit pmod
2021-09-05 00:27:42 +00:00
bpl :rts
sty DECAWM
:rts rts
mode_DECARM
bit pmod
2021-09-05 00:27:42 +00:00
bpl :rts
sty DECARM
:rts rts
mode_LNM
bit pmod
2021-09-05 00:27:42 +00:00
bmi :rts
sty LNM
:rts rts
2021-09-05 00:27:42 +00:00
csi_m
* esc [ ... m
2021-09-27 21:53:13 +00:00
* 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
2021-09-27 21:53:13 +00:00
2022-01-29 15:43:09 +00:00
jmp update_sgr
2021-09-27 21:53:13 +00:00
: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
2021-09-05 00:27:42 +00:00
csi_g
* ESC [ g, ESC [ 0 g - clear tab at column
* ESC [ 3 g - clear all tabs
2021-09-05 00:27:42 +00:00
lda parms
beq :0
cmp #3
beq :3
rts
2021-09-05 00:27:42 +00:00
:0 ldx x
jmp reset_tab
:3 jmp reset_all_tabs
2021-09-25 17:57:27 +00:00
p1 mac
lda parms
bne ok
lda #1
2021-09-26 01:27:48 +00:00
ok sta parms
2021-09-25 17:57:27 +00:00
<<<
2021-09-05 00:27:42 +00:00
* cursor movement.
2021-09-26 01:27:48 +00:00
* if private mode, no effect.
2021-09-05 00:27:42 +00:00
csi_A
2021-09-25 17:57:27 +00:00
* up
* if cursor is outside the scrolling region, it is not locked to the scrolling region.
2021-09-26 01:27:48 +00:00
bit pmod
bmi :rts
2021-09-25 17:57:27 +00:00
p1
lda y
cmp DECTM
beq :rts
bcc :simple
sec
2021-09-26 01:27:48 +00:00
sbc parms
2021-09-25 17:57:27 +00:00
bcc :top
2021-09-26 01:27:48 +00:00
cmp DECTM
2021-09-25 17:57:27 +00:00
* bcc :top
* bra :sta
bcs :sta
:top lda DECTM
bra :sta
:rts rts
:simple
* lda y
sec
2021-09-26 01:27:48 +00:00
sbc parms
2021-09-25 17:57:27 +00:00
* bcc :0 ; clear indicate underflow.
bcc :sta
:0 lda #0
:sta sta y
jmp recalc_cursor_y
2021-09-05 00:27:42 +00:00
csi_B
2021-09-25 17:57:27 +00:00
* down
2021-09-26 01:27:48 +00:00
bit pmod
bmi :rts
2021-09-25 17:57:27 +00:00
p1
lda y
cmp DECBM
beq :rts
bge :simple
clc
2021-09-26 01:27:48 +00:00
adc parms
2021-09-25 17:57:27 +00:00
bcs :bottom ; overflow
2021-09-26 01:27:48 +00:00
cmp DECBM
2021-09-25 17:57:27 +00:00
bcc :sta
:bottom lda DECBM
bra :sta
:rts rts
:simple
clc
2021-09-26 01:27:48 +00:00
adc parms
2021-09-25 17:57:27 +00:00
bcs :23 ; overflow
cmp #24
bcc :sta
:23 lda #23
:sta sta y
jmp recalc_cursor_y
2021-09-05 00:27:42 +00:00
csi_C
2021-09-25 17:57:27 +00:00
* right
2021-09-26 01:27:48 +00:00
* in column 80, no effect.
bit pmod
bmi :rts
lda x
cmp #79
bcs :rts
2021-09-25 17:57:27 +00:00
p1
lda x
2021-09-26 01:27:48 +00:00
* and #$7f
2021-09-25 17:57:27 +00:00
clc
2021-09-26 01:27:48 +00:00
adc parms
2021-09-25 17:57:27 +00:00
bcs :79 ; overflow
cmp #80
bcc :sta
:79 lda #79
:sta sta x
jmp recalc_cursor_x
2021-09-26 01:27:48 +00:00
:rts rts
2021-09-25 17:57:27 +00:00
2021-09-05 00:27:42 +00:00
csi_D
2021-09-25 17:57:27 +00:00
* left
2021-09-26 01:27:48 +00:00
bit pmod
bmi :rts
2021-09-25 17:57:27 +00:00
p1
lda x
and #$7f
sec
2021-09-26 01:27:48 +00:00
sbc parms
2021-09-25 17:57:27 +00:00
* bcc :0 ; underflow
bcs :sta
:0 lda #0
:sta sta x
jmp recalc_cursor_x
2021-09-26 01:27:48 +00:00
:rts rts
2021-09-25 17:57:27 +00:00
2021-09-05 00:27:42 +00:00
csi_f
csi_H ; direct cursor addressing
2021-09-25 15:05:06 +00:00
debug csi_H
2021-09-05 21:04:52 +00:00
* 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
2021-09-19 22:49:29 +00:00
jmp recalc_cursor
2021-09-05 00:27:42 +00:00
csi_r ; scrolling region
debug csi_r
2021-09-05 21:04:52 +00:00
* based on testing
* esc [ n r (no second parmeter) is equivalent to esc [ n ; 24 r
2021-09-25 17:57:27 +00:00
* esc [ r sets scrolling region to 1 ; 24 ( in accordance with above )
2021-09-05 21:04:52 +00:00
* 24 is assumed value for second parameter
* invalid parameters exit without updating
2021-09-26 01:27:48 +00:00
* based on testing, row parameters are not affected by DECOM.
2021-09-05 21:04:52 +00:00
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
2021-09-05 21:04:52 +00:00
bge :rts
ldx parms+1
cpx #23+1
2021-09-05 21:04:52 +00:00
bge :rts
* must be at least 1 line
lda parms+1
sec
sbc parms
beq :rts
bmi :rts
2021-09-26 01:27:48 +00:00
* move cursor to origin.
2021-09-05 21:04:52 +00:00
lda parms
sta DECTM
sta y
lda parms+1
sta DECBM
stz x
2021-09-26 01:27:48 +00:00
bit DECOM
bmi :j
stz y
:j jmp recalc_cursor
2021-09-05 21:04:52 +00:00
:rts rts
2021-09-05 00:27:42 +00:00
2021-09-26 01:27:48 +00:00
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
2021-09-05 00:27:42 +00:00
csi_q ; LEDs
rts
2021-09-05 00:27:42 +00:00
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
2021-09-05 00:27:42 +00:00
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.
2021-09-05 00:27:42 +00:00
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