adding everything in progress, regardless of state.

This commit is contained in:
Kelvin Sherlock 2021-09-04 17:52:35 -04:00
parent dbda9761c5
commit 492a3bfbec
11 changed files with 1662 additions and 0 deletions

198
screen.S Normal file
View File

@ -0,0 +1,198 @@
rel
mx %11
ent erase_line
ent erase_line_0
ent erase_line_1
ent erase_line_2
erase_line
; a = 0 - erase x - eol (inclusive)
; a = 1 - erase 0 - x (inclusive)
; a = 2 - erase 0 - eol
cmp #2
bcs :rts
asl
tax
jmp (:table,x)
:rts rts
:table
dw erase_line_0
dw erase_line_1
dw erase_line_2
erase_line_2
* erase entire line.
php
rep #$30
ldy #38
lda #" "
:loop
sta [text01],y
sta (text00),y
dey
dey
bpl :loop
plp
rts
mx %11
erase_line_0
* erase to eol
lda x
lsr
tay
lda #" "
bcs :half
:loop
sta [text01],y
:half sta (text00),y
iny
cpy #40
bcc :loop
rts
erase_line_1
* erase to x (inclusive)
lda x
lsr
tay
lda #" "
bcc :half
:loop
sta (text00),y
:half sta [text01],y
dey
bpl :loop
rts
erase_screen ent
; a = 0 - erase [cursor, end] (inclusive)
; a = 1 - erase [start, cursor] (inclusive)
; a = 2 - erase [start, end]
cmp #2
bcs :rts
asl
tax
jmp (:table,x)
:rts rts
:table
dw erase_screen_0
dw erase_screen_1
dw erase_screen_2
erase_screen_2 ent
* erase the entire screen.
php
rep #$30
lda #" " ; high bit set.
c00 cc $0400
c01 cc $0480
c02 cc $0500
c03 cc $0580
c04 cc $0600
c05 cc $0680
c06 cc $0700
c07 cc $0780
c08 cc $0428
c09 cc $04a8
c10 cc $0528
c11 cc $05a8
c12 cc $0628
c13 cc $06a8
c14 cc $0728
c15 cc $07a8
c16 cc $0450
c17 cc $04d0
c18 cc $0550
c19 cc $05d0
c20 cc $0650
c21 cc $06d0
c22 cc $0750
c23 cc $07d0
plp
rts
mx %11
erase_screen_0 ent
* erase from cursor to the end.
mx %11
ldx #0 ; for jmp (,x)
lda x
ora y
beq :all
lda x
beq :x0
jsr erase_line_0
lda y
inc
bra :x1
:x0
lda y
:x1 cmp #23
bcs :rts
asl
tax
:all php ; clear_table will plp.
rep #$30
lda #" "
jmp (clear_table,x)
:rts rts
erase_screen_1 ent
* erase from start to cursor.
jsr erase_line_1
lda y
bne :ok
rts
:ok
php
rep #$30
lda y
dey
asl
tax
lda #" "
jmp (:clear_table,x)
:clear_table
c23 cc $07d0
c22 cc $0750
c21 cc $06d0
c20 cc $0650
c19 cc $05d0
c18 cc $0550
c17 cc $04d0
c16 cc $0450
c15 cc $07a8
c14 cc $0728
c13 cc $06a8
c12 cc $0628
c11 cc $05a8
c10 cc $0528
c09 cc $04a8
c08 cc $0428
c07 cc $0780
c06 cc $0700
c05 cc $0680
c04 cc $0600
c03 cc $0580
c02 cc $0500
c01 cc $0480
c00 cc $0400
plp
rts

73
table.py Normal file
View File

@ -0,0 +1,73 @@
import sys
special = {
}
for x in range(0,0x20): special[chr(x)] = '^' + chr(0x40 + x)
cmap = {
'\'': '\'',
'\"': '\"',
'?': '?',
'\\': '\\',
'a': '\a',
'b': '\b',
'f': '\f',
'n': '\n',
'r': '\r',
't': '\t',
'v': '\v',
}
argv = sys.argv[1:]
chars = []
for arg in argv:
# ^X is a control character
if len(arg) == 2 and arg[0] == '^':
c = chr(ord(arg[1]) & 0x1f)
chars.append(c)
continue
# \X is an escaped character
if len(arg) == 2 and arg[0] == '\\':
c = arg[1]
if c in cmap: chars.append(cmap[c])
continue
# X-Y is a range of characters.
if len(arg) == 4 and arg[1] == '-':
a = arg[0]
b = arg[2]
for c in range(ord(a),ord(b)+1):
chars.append(chr(c))
continue
chars.extend(arg)
chars = list(set(chars))
chars.sort()
if not chars: exit(1)
mmin = ord(chars[0])
mmax = ord(chars[-1])
print(":MIN\tequ {}".format(mmin))
print(":MAX\tequ {}".format(mmax))
print()
print(":table")
for x in range(mmin, mmax+1):
c = chr(x)
print("\tdw $0\t; {}".format(special.get(c, c)))
# for c in chars:
# x = ord(c)
# print("\tdw $0\t; {}".format(special.get(c, c)))

60
vt.equ.S Normal file
View File

@ -0,0 +1,60 @@
st_vt52 equ 0
st_vt52_esc equ 2
st_vt52_dca equ 4
st_vt100 equ 6
st_vt100_esc equ 8
st_vt100_csi equ 10
st_vt100_csi_2 equ 12
st_vt100_esc_pound equ 14 ; #
st_vt100_esc_lparen equ 16 ; (
st_vt100_esc_rparen equ 18 ; )
st_vt100_esc_bad equ 20
st_vt100_csi_bad equ 22
ESC equ $1b
dum 0
state ds 2
x ds 2
y ds 2
DECTM ds 2 ; top margin
DECBM ds 2 ; bottom margin
LOCAL ds 2 ; local mode
DECANM ds 2 ; ansi/vt52
DECKPAM ds 2 ; alternate keypad
DECCKM ds 2 ; cursor key modes
DECOM ds 2 ; origin
DECSCNM ds 2 ; screen mode
DECAWM ds 2 ; wrap
DECARM ds 2 ; auto repeat
LNM ds 2 ; new line
SGR ds 2 ; graphics, bit 1 = bold, 4 = underscore, 5 = blink, 7 = inverse
* not supported
*CHARSET ds 2 ;
*GRAPHICS ds 2 ;
*DECCOLM ds 2 ; character per line (80/132)
*DECINLM ds 2 ; interlace
*DECSCLM ds 2 ; scroll mode
* DECDHL - double height line
* DECDWL - double width line
* parameters
MAX_PCOUNT equ 8
pcount ds 2
parms ds MAX_PCOUNT
pmod ds 2
r0 ds 2
dend

177
vt100.S Normal file
View File

@ -0,0 +1,177 @@
vt100
mx %11
and #$7f
cmp #' '
bcs :notctrl
asl
tax
jmp (ctrl,x)
:notctrl
ldx state
jmp (:state_table,x)
:state_table
ext vt52_esc,vt52_dca
ext vt100_esc,vt100_csi,vt100_csi_2
ext vt100_esc_pound,vt100_esc_lparen,vt100_esc_rparen
dw char
dw vt52_esc
dw vt52_dca
dw char
dw vt100_esc
dw vt100_csi
dw vt100_csi_2
dw vt100_esc_pound
dw vt100_esc_lparen
dw vt100_esc_rparen
vt100_csi_bad ent
cmp #'@'
blt :rts
ldx #st_vt100
stx state
:rts rts
esc_csi
stz pcount
stz params
stz params+1
stz csi_private
lda #st_csi
sta state
rts
csi
inc state
inc state
cmp #'?'
bne csi0
lda #$80
sta csi_private
rts
csi0
cmp #';'
beq :semi
cmp #'0'
bcc csi_final
cmp #'9'+1
bcs csi_final
:num
and #$0f ; 0-9
tay ; save
ldx pcount
lda params,x
asl ; x 2
sta params,x
asl ; x 4
asl ; x 8
clc
adc params,x
sta params,x
tya
clc
adc params,x
sta params,x
rts
:semi
ldx pcount
inx
cpx #MAX_PCOUNT
bcs :srts
stx pcount
stz params,x
:srts
rts
csi_final
* c, h, l have private modes.
bit csi_private
bmi :priv
cmp #:MIN_FINAL
bcc :rts
cmp #:MAX_FINAL+1
bcs :rts
asl
tax
jmp (:table,x)
:rts rts
:priv
cmp #:MIN_FINAL_PRIV
bcc :rts
cmp #:MAX_FINAL_PRIV+1
bcs :rts
asl
tax
jmp (:table_priv,x)
csi
*
* ESC [ encountered.
*
* ? -> DEC private
* 0-9 -> parameter value
* ; parameter delim
* other - final character.
cmp #'0'
blt :notnum
cmp #'9'+1
bge :notnum
sep #$30
and #$0f
tay
ldx pcount
lda parms,x
asl
pha
asl
asl
clc
adc 1,s
sta 1,s
tya
adc 1,s
ply
sta parms,x
sep #$30
]rts rts
:notnum
cmp #';'
bne :notsemi
ldx pcount
cpx #MAXPCOUNT
bge ]rts
inx
stx pcount
stz parms,
stz parms+1,x
]rts rts
:notsemi
cmp #'?'
bne :final
sta ptype
rts
:final

413
vt100.csi.S Normal file
View File

@ -0,0 +1,413 @@
rel
xc
xc
use vt.equ
vt100_csi ent
inc state
inc state
stz pcount
stz parms
stz parms+1 ; some assume 2 parms.
stz pmod
tay ; save for modifier
cmp #:MIN
blt :bad
cmp #:MAX+1
bge :bad
sec
sbc #:MIN
asl
tax
jmp (:table,x)
:bad
ldx #st_vt100
stx state
:rts rts
:table
* 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.
: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 :rts ; <
dw :rts ; =
dw :rts ; >
dw :modifier ; ?
dw $0 ; @
dw $0 ; A
dw $0 ; B
dw $0 ; C
dw $0 ; D
dw $0 ; E
dw $0 ; F
dw $0 ; G
dw $0 ; H
dw $0 ; I
dw $0 ; J
dw $0 ; K
dw $0 ; L
dw $0 ; M
dw $0 ; N
dw $0 ; O
dw $0 ; P
dw $0 ; Q
dw $0 ; R
dw $0 ; S
dw $0 ; T
dw $0 ; U
dw $0 ; V
dw $0 ; W
dw $0 ; X
dw $0 ; Y
dw $0 ; Z
dw $0 ; [
dw $0 ; \
dw $0 ; ]
dw $0 ; ^
dw $0 ; _
dw $0 ; `
dw $0 ; a
dw $0 ; b
dw $0 ; c
dw $0 ; d
dw $0 ; e
dw $0 ; f
dw $0 ; g
dw $0 ; h
dw $0 ; i
dw $0 ; j
dw $0 ; k
dw $0 ; l
dw $0 ; m
dw $0 ; n
dw $0 ; o
dw $0 ; p
dw $0 ; q
dw $0 ; r
dw $0 ; s
dw $0 ; t
dw $0 ; u
dw $0 ; v
dw $0 ; w
dw $0 ; x
dw $0 ; y
:digit
lsr ; undo asl
sta parms
rts
:modifier
ldx #$40 ; bit -> v
stx pmod
rts
vt100_csi_2 ent
; if < '0' and invalid modifier, don't terminate.
bit pmod
bmi :badmod
cmp #'@'
blt :0
ldx #st_vt100
stx state
:0 cmp #:MIN
blt :bad
cmp #:MAX+1
bge :bad
sec
sbc #:MIN
jmp (:table,x)
:badmod
cmp #'@'
blt :rts
:bad
ldx #st_vt100
stx state
: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 ; ?
:modifier
lda #$80
sta pmod
rts
semi
ldx pcount
cpx #MAX_PCOUNT
bge :rts
inx
stx pcount
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
lsr ; undo asl
sta r0
ldx pcount
lda parms,x
* cmp #255
* beq :rts
cmp #25
bge :v
tay
lda :table,y
* clc ; cleared via cmp
adc r1
sta parms,x
:rts
rts
:v
lda #$255
sta parms,x
rts
:table da 0,10,20,30,40,50,60,70,80,90
da 100,110,120,130,140,150,160,170,180,190
da 200,210,220,230,240,250
set_mode
; esc [ ... h (vt100)
; esc [ ? ... h (private)
ldy #$80
bra mode_common
reset_mode
; 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
bgt :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 :rts ; 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
bvc :rts
sty DECCKM
:rts rts
mode_DECANM
bit pmod
bvc :rts
sty DECANM
cpy #0
bne :rts
* switch to vt52 mode
ldx #st_vt52
stx state
:rts rts
*mode_DECCOLM
* sty DECCOLM
* rts
mode_DECSCNM
bit pmod
bvc :rts
* todo - invert on-screen characters?
sty DECSCNM
:rts rts
mode_DECOM
bit pmod
bvc :rts
sty DECOM
; move to the new home position
stz x
stz y
cpy #0
beq :rts
lda #DECTM
sta y
phy
jsr update_cursor
ply
:rts rts
mode_DECAWM
bit pmod
bvc :rts
sty DECAWM
:rts rts
mode_DECARM
bit pmod
bvc :rts
sty DECARM
:rts rts
mode_LNM
bit pmod
bvs :rts
sty LNM
:rts rts
char_attr
* esc [ ... m
inc pcount
ldx #0
:loop lda parms,x
cmp #8
bge :next
tay
lda SGR
and :and,y
ora :or,y
lda :table,y
sta SGR
:next inx
cpx pcount
blt :loop
:rts rts
: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
reset_tab
* ESC H - set tab at current column [vt100.s]
* ESC [ g, ESC [ 0 g - clear tab at column
* ESC [ 3 g - clear all tabs
lda parm
beq :0
cmp #3
beq :3
rts
:0
ldx x
stz tabs,x
rts
:3
ldx #80-1
:loop stz tabs,x
dex
bpl :loop
rts
sav vt100.csi.L

103
vt100.ctrl.S Normal file
View File

@ -0,0 +1,103 @@
*control chars
ext draw_char,update_cursor
control ent
asl
tax
jmp (:table,x)
:table
dw :rts ; ^@
dw :rts ; ^A
dw :rts ; ^B
dw :rts ; ^C
dw :rts ; ^D
dw enq ; ^E
dw :rts ; ^F
dw bel ; ^G
dw bs ; ^H
dw tab ; ^I
dw lf ; ^J
dw vt ; ^K
dw ff ; ^L
dw cr ; ^M
dw so ; ^N
dw si ; ^O
dw :rts ; ^P
dw xon ; ^Q
dw :rts ; ^R
dw xoff ; ^S
dw :rts ; ^T
dw :rts ; ^U
dw :rts ; ^V
dw :rts ; ^W
dw can ; ^X
dw :rts ; ^Y
dw sub ; ^Z
dw esc ; ^[
dw :rts ; ^\
dw :rts ; ^]
dw :rts ; ^^
dw :rts ; ^_
:rts rts
enq
* send answer back message.
* answer back message is a user-controllable string of text sent as-is
* (with no specific terminator character)
rts
bel
* todo - trigger nice ensoniq beep.
rts
bs
* backspace, no wrap
lda x
beq :rts
dec x
jmp update_cursor
:rts rts
tab
* go to next tab stop
rts
lf
vt
ff
* vt and ff interpreted as lf
* LNM: also do cr.
bit LNM
bpl :lnm
stz x
:lnm
lda y
cmp BM ; bottom margin
bne :iny
jmp scroll_up
:iny inc y
jmp update_cursor
cr
stz x
jmp update_cursor
xon
xoff
* flow control...
rts
can
sub
* cancel esc sequence and display error character
stz state
rts
esc
lda #st_esc
sta state
rts

164
vt100.esc.S Normal file
View File

@ -0,0 +1,164 @@
rel
xc
xc
use vt.equ
vt100_esc ent
* #[()=>cH78DEM
* based on testing, unspecified chars in the 0x20-0x2f range cause it to gobble
* chars until 0x30- terminator (which ends the sequence but does not take an action)
* esc 1 -> hangs? [undocumented]
ldx #st_vt100
stx state
cmp #:MIN
blt :bad
cmp #:MAX+1
bge :rts
sec
sbc #:MIN
asl
tax
jmp (:table,x)
:bad
ldx #st_vt100_esc_bad
stx state
:rts
rts
:MIN equ 35
:MAX equ 99
:table
dw :pound ; #
dw :bad ; $
dw :bad ; %
dw :bad ; &
dw :bad ; '
dw :lparen ; (
dw :rparen ; )
dw :bad ; *
dw :bad ; +
dw :bad ; ,
dw :bad ; -
dw :bad ; .
dw :bad ; /
dw :rts ; 0
dw :rts ; 1
dw :rts ; 2
dw :rts ; 3
dw :rts ; 4
dw :rts ; 5
dw :rts ; 6
dw esc_7 ; 7
dw esc_8 ; 8
dw :rts ; 9
dw :rts ; :
dw :rts ; ;
dw :rts ; <
dw esc_eq ; =
dw esc_gt ; >
dw :rts ; ?
dw :rts ; @
dw :rts ; A
dw :rts ; B
dw :rts ; C
dw esc_D ; D
dw esc_E ; E
dw :rts ; F
dw :rts ; G
dw esc_H ; H
dw :rts ; I
dw :rts ; J
dw :rts ; K
dw :rts ; L
dw esc_M ; 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 esc_c ; c
:lparen
ldx #st_vt100_esc_lparen
stx state
rts
:rparen
ldx #st_vt100_esc_rparen
stx state
rts
:pound
ldx #st_vt100_esc_pound
stx state
rts
esc_7 ; save cursor position, graphic rendition, and character set.
rts
esc_8 ; restore cursor position, graphic rendition, and character set.
rts
esc_eq ; enter alternate keypad mode
lda #$80
sta DECKPAM
rts
esc_gt ; exit alternate keypad mode
stz DECKPAM
rts
esc_H ; set tab stop
ext set_tab
ldx x
jmp set_tab
esc_E ; next line
stz x
; drop through
esc_D ; index
rts
esc_M ; reverse index
rts
esc_c ; reset terminal.
rts
vt100_esc_bad ent
cmp #'0'
blt :rts
ldx #st_vt100
stx state
:rts
rts
sav vt100.esc.L

22
vt100.link.S Normal file
View File

@ -0,0 +1,22 @@
ovr all
* binary linker
lkv 0
org $6000
asm boot.S
asm vt100.ctrl.S
lnk boot.S
pos ; reset
pos EMU_SIZE
EMU_SIZE ext
EMU_BLOCKS geq EMU_SIZE+511\512
sav vt100.bin

147
vt100.main.S Normal file
View File

@ -0,0 +1,147 @@
vt100
mx %11
and #$7f
cmp #' '
bcs :notctrl
asl
tax
jmp (:ctrl_table,x)
:notctrl
ldx state
jmp (:state_table,x)
:state_table
ext vt52_esc,vt52_dca_1,vt52_dca_2
ext vt100_esc,vt100_csi,vt100_csi_2
ext vt100_esc_pound,vt100_esc_lparen,vt100_esc_rparen
dw char
dw vt52_esc
dw vt52_dca_1
dw vt52_dca_2
dw char
dw vt100_esc
dw vt100_csi
dw vt100_csi_2
dw vt100_esc_pound
dw vt100_esc_lparen
dw vt100_esc_rparen
:ctrl_table
dw ctrl_00,ctrl_01,ctrl_02,ctrl_03
dw ctrl_04,ctrl_05,ctrl_06,ctrl_07
dw ctrl_08,ctrl_09,ctrl_0a,ctrl_0b
dw ctrl_0c,ctrl_0d,ctrl_0e,ctrl_0f
dw ctrl_10,ctrl_11,ctrl_12,ctrl_13
dw ctrl_14,ctrl_15,ctrl_16,ctrl_17
dw ctrl_18,ctrl_19,ctrl_1a,ctrl_1b
dw ctrl_1c,ctrl_1d,ctrl_1e,ctrl_1f
ctrl_00
ctrl_01
ctrl_02
ctrl_03
ctrl_04
ctrl_05 ; answer ENQ
ctrl_06
ctrl_0e ; G1 character set
ctrl_0f ; G0 character set
ctrl_10
ctrl_11 ; XON
ctrl_12
ctrl_13 ; XOFF
ctrl_14
ctrl_15
ctrl_16
ctrl_17
ctrl_19
ctrl_1c
ctrl_1d
ctrl_1e
ctrl_1f
rts
ctrl_07 ; ring the bell.
rts
ctrl_1b ; escape -
* vt100 - aborts current escape sequence and starts a new one.
* vt52 - esc esc aborts and starts new
* vt50 - esc esc aborts
lda DECANM
bne :vt52
lda #st_vt100_esc
sta state
rts
:vt52
lda #st_vt52_esc
sta state
rts
ctrl_18
ctrl_1a
* vt100 - abort current escape sequence
* and display error character.
lda DECANM
bne :vt52
lda #st_vt100
sta state
rts
:vt52
lda #st_vt52
sta state
rts
ctrl_09 ; tab
* vt100 has adjustable tabs.
ext tab_table
ldx x
lp:
cpx #79
bcs :rts
lda tab_table,x
bne :hit
inx
bra :lp
stx x
jmp update_cursor
:rts rts
ctrl_0a ; line feed - cursor down w/ scroll
ctrl_0b ; vertical tab
ctrl_0c ; form feed.
* if LNM is active, equivalent to CR, LF
lda #LNM
bne :lnm
stz x
:lnm
lda y
cmp #23
blt :simple
lda #" "
sta cursor_saved_char
jmp scroll_down
:simple
inc y
jmp update_cursor
ctrl_0d ; carriage return - cursor to column 0.
stz x
jmp update_cursor

77
vt100.tabs.S Normal file
View File

@ -0,0 +1,77 @@
rel
xc
xc
use vt.equ
init_tabs ent
ldx #80
:loop stz tabs,x
dex
bpl :loop
lda #72
ldy #$80
:tloop tax
sty tabs,x
sec
sbc #8
bne :tloop
rts
*:table db 8*1,8*2,8*3,8*4,8*5,8*6,8*7,8*8*,8*9
set_tab ent
* input x = x
* ldx x
cpx #80
bge :rts
lda #$80
sta tabs,x
:rts rts
reset_tab ent
* input x = x
* ldx x
cpx #80
bge :rts
stz tabs,x
:rts rts
reset_all_tabs ent
ldx #80-1
:loop stz tabs,x
dex
bpl :loop
rts
next_tab_stop ent
* input x = x
* ldx x
cpx 79
bge :80
:loop bit tabs,x
bmi :rts
inx
cpx #80
bcc :loop
:80 ldx #80
:rts rts
tabs ds 80
sav vt100.tabs.L

228
vt100.vt52.S Normal file
View File

@ -0,0 +1,228 @@
*
* vt52 emulation for the vt100
*
* ESC < exits
lst off
rel
xc
xc
use vt.equ
ext update_cursor,write_modem,draw_char
vt52_esc ent
* ABCDFGHIJKYZ<>=
ldx #st_vt52
stx state
cmp #:MIN
blt :rts
cmp #:MAX+1
bge :rts
sec
sbc #:MIN
asl
tax
jmp (:table,x)
:rts
rts
:MIN equ 60
:MAX equ 90
:table
dw esc_lt ; <
dw esc_eq ; =
dw esc_gt ; >
dw :rts ; ?
dw :rts ; @
dw esc_A ; A
dw esc_B ; B
dw esc_C ; C
dw esc_D ; D
dw :rts ; E
dw esc_F ; F
dw esc_G ; G
dw esc_H ; H
dw esc_I ; I
dw esc_J ; J
dw esc_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 esc_Y ; Y
dw esc_Z ; Z
esc_lt
* based on testing, this also resets graphics mode
* (which we don't support anyhow.)
lda #$80
sta DECANM
lda #st_vt100
sta state
rts
esc_eq ; enter alternate keypad mode
lda #$80
sta DECKPAM
rts
esc_gt ; exit alternate keypad mode
stz DECKPAM
rts
* cursor movement respects the scrolling region.
esc_A ; cursor up.
lda y
beq :rts
cmp DECTM
beq :rts
dec y
jmp update_cursor
:rts rts
esc_B ; cursor down
lda y
cmp #79
beq :rts
cmp DECBM
beq :rts
iny y
jmp update_cursor
:rts rts
esc_C ; cursor right
lda x
cmp #79
bcs :rts
inc x
jmp update_cursor
:rts rts
esc_D ; cursor left
lda x
beq :rts
dec x
jmp update_cursor
:rts rts
esc_I ; cursor up w/ line scroll
* based on testing, scrolling only occurs within the
* scroll region.
rts
esc_J rts
esc_K rts
esc_H ; cursor home
; based on testing, does not respect scrolling region but does
; respect origin mode.
stz x
* stz y
* bit DECOM
* bpl :go
lda DECTM
sta y
:go jmp update_cursor
esc_F ; enter graphics mode
* lda #%0010
* tsb mode
rts
esc_G ; exit graphics mode
* lda #%0010
* trb mode
rts
esc_Y ; direct cursor address
* vt100 - does not take effect until the end.
* based on testing, there is internal state information,
* so esc Y a esc B esc Y b is equivalent to esc Y a b
*
* if width exceeded, clamps at right margin.
* if height exceeded, does not change.
lda #st_vt52_dca
sta state
rts
esc_Z ; terminal identity.
; return ESC / Z
; based on testing, no display in local mode
bit LOCAL
bmi :local
lda #ESC
jsr write_modem
lda #'/'
jsr write_modem
lda #'Z'
jmp write_modem
:local rts
* lda #'Z'
* jmp draw_char
vta52_dca ent
* this differs from esc [ H in that invalid
* values are ignored rather than clamped.
* based on testing, does not respect DECOM.
* based on testing, state is saved if ESC aborts, even
* if switching to vt100 mode and back or ^X to cancel.
sec
sbc #' '
bit :tmp
bmi :go
ora #$80
sta :tmp
rts
:go ; a = x
cmp #80
bge :y
sta x
:y lda :tmp
and #$7f
cmp #24
bge :update
sta y
:update
stz :tmp
jmp update_cursor
:tmp ds 2
sav vt100.vt52.L