Compare commits

...

29 Commits
r3 ... master

Author SHA1 Message Date
Kelvin Sherlock a687a08b0b add command-L to toggle local/online
add command-Q to quit.

Since ROM 1 doesn't have _RemoveCDA in ROM, the control panel is only installed in ROM 3.
(TODO -- check at runtime in case launched from GS/OS)
2022-02-07 10:34:10 -05:00
Kelvin Sherlock 90e807ba46 reset - enable auto-repeat. 2022-01-30 22:29:49 -05:00
Kelvin Sherlock 2c432b3fc1 command-L toggles local/online mode. 2022-01-30 22:29:33 -05:00
Kelvin Sherlock dcbafc2999 commentary. 2022-01-30 15:52:38 -05:00
Kelvin Sherlock 80edada6e9 DECCOLM 132 support (partial).
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.
2022-01-30 15:52:32 -05:00
Kelvin Sherlock 04113c4725 Rom 1 _InstallCDA call clobbers some direct page locations.
This is fixed in ROM 3 (or via the TS patches if you boot GS/OS).
Workaround it by switching to DPAGE 0.

Also, allocate memory (since I originally thought that might be relevant).
2022-01-30 15:50:54 -05:00
Kelvin Sherlock 1f7e3b3b4c to make life easier for emacs, backspace will send $7f instead of $08.
command-backspace will send $08 (as will Control-H).
If you have an extended keyboard, delete will also send $08.
(mame uses delete to toggle keyboard mode so it's not yet tested).
2022-01-29 15:43:08 -05:00
Kelvin Sherlock 18daf26568 add DECARM, x, and y to the CDA 2022-01-29 15:41:14 -05:00
Kelvin Sherlock 60259531d5 DECARM - auto repeat support. defaults to auto-repeat on.
n.b. - mame does not currently set the repeat bit in the keymod reg so it's not well tested.
2022-01-29 14:24:55 -05:00
Kelvin Sherlock 22d1c744bb auto-wrap wasn't advancing the cursor after wrapping. 2022-01-29 11:56:15 -05:00
Kelvin Sherlock c15ae6ac4c add DECREQTPARM support, fix a bug with DA/Device attributes response. 2022-01-29 11:23:41 -05:00
Kelvin Sherlock 9dfc3cc7c9 saving the cursor also saves the SGR 2022-01-29 10:43:09 -05:00
Kelvin Sherlock 71993497ea $7f (delete) character is a null char. drop it (and $00) when checking the read queue. 2022-01-28 23:21:13 -05:00
Kelvin Sherlock acfe94a4c7 command keys:
* command 1 - command 4 equivalent to PF1 - PF4
* command-delete = backspace (0x7f)
* command-return = linefeed (0x0a)
2022-01-28 22:25:33 -05:00
Kelvin Sherlock 9cf52cb34e vttest fixes
1. control-space should generate a null character
2. vt52 application mode keys were off.
2022-01-28 22:12:37 -05:00
Kelvin Sherlock 186d71de47 print the cancel character for ^X and ^Z.
based on testing, this applies to vt52 and vt100.
use the current x pos to choose between $56 and $57 (mouse text checkerboard)
so multiple characters look pretty.
2022-01-17 13:13:07 -05:00
Kelvin Sherlock 4eb578b94e merge hexdump code 2022-01-17 13:11:00 -05:00
Kelvin Sherlock c2d3ee0f28 show all SGR (inverse, bold, underscore, blink) as inverted. 2022-01-15 16:36:28 -05:00
Kelvin Sherlock 900dccb3d1 head/tail swapped. 2022-01-15 16:31:38 -05:00
Kelvin Sherlock ea6ee76a9d fix CDA paging 2022-01-15 16:15:05 -05:00
Kelvin Sherlock 1cc501e72a buffer outgoing keystrokes
this also adds a hexdump in the CDA for the outgoing buffer
in local mode, "incoming" data is read from the outgoing buffer.
Currently data is (potentially) sent on each run of the main loop.
I thought about using the TX empty interrupt but it still needs to be
kicked off at some point (unlike incoming data)
2022-01-15 15:59:29 -05:00
Kelvin Sherlock f486bbfb1b don't re-enable the cursor blink while there is still pending modem data. this improves performance and visuals. 2022-01-09 19:38:25 -05:00
Kelvin Sherlock 8fa8d8d1fa move modem q variables to the direct page, adjust CDA hexdump to show most recent 16*8 bytes. 2022-01-08 22:26:34 -05:00
Kelvin Sherlock 02c6e1271c cda print_number - support for 0-255 2021-12-19 20:16:52 -05:00
Kelvin Sherlock 279f424cee cda - improve ssc register display 2021-12-06 20:14:35 -05:00
Kelvin Sherlock e1639db6e4 cda - display SCC registers. 2021-12-05 22:47:40 -05:00
Kelvin Sherlock 6f055a1ef9 update cursor save/cursor restore to also save the DECOM settings. tested with vt100 (mame) 2021-11-28 15:46:29 -05:00
Kelvin Sherlock cd1397e3cf fixed cursor position report
- verified DECOM behavior
- was missing [ write.
2021-11-28 14:45:03 -05:00
ksherlock 3e53d52226
Create README.md 2021-10-26 08:16:26 -04:00
10 changed files with 1334 additions and 158 deletions

12
README.md Normal file
View File

@ -0,0 +1,12 @@
# itty-bitty-vtty
A vt100 emulator for the Apple IIgs
vt100, modem port, 9600 baud, 8-N-1 (MAME defaults)
A vt100 emulator based on The [User Guide](https://www.vt100.net/docs/vt100-ug/contents.html). Underspecified behavior is tested with MAME's vt100 emulation.
Unimplemented due to hardware limitations:
* alternate character sets
* graphic rendition (except plain/reverse)
* 132-column mode

View File

@ -36,6 +36,7 @@ DECOM ds 2 ; origin
DECSCNM ds 2 ; screen mode
DECAWM ds 2 ; wrap
DECARM ds 2 ; auto repeat
DECCOLM ds 2 ; character per line (80/132)
LNM ds 2 ; new line
@ -46,7 +47,6 @@ SGR ds 2 ; graphics, bit 1 = bold, 4 = underscore, 5 = blink, 7 = inverse
*CHARSET ds 2 ;
*GRAPHICS ds 2 ;
*DECCOLM ds 2 ; character per line (80/132)
*DECINLM ds 2 ; interlace
*DECSCLM ds 2 ; scroll mode
@ -82,6 +82,17 @@ mod ds 2
* saved cursor
saved_x ds 2
saved_y ds 2
saved_decom ds 2
saved_sgr ds 2
* async read/write pointers.
*
read_q_head ds 2
read_q_tail ds 2
write_q_head ds 2
write_q_tail ds 2
do *>256
err "too big"

View File

@ -10,6 +10,7 @@
use apple2gs.equ
use vt.equ
use debug
* alternate character set
@ -33,19 +34,71 @@ ptr ds 2
dend
init_cda ent
*
* rom 0/1 doesn't include _RemoveCDA in ROM so it can't be removed.
* additionally, _InstallCDA has bugs.
* so, for now, disable on ROM 1.
cda_startup ent
php
rep #$30
jsr $fe1f ; idroutine. y = rom
cpy #3
bcc :nope
*
* rom 1 IIgs InstallCDA clobbers $3c-$43 on the direct page
*
phd
pea #0
pld
psl #handle
_InstallCDA
pld
:nope
plp
rts
cda_shutdown ent
mx %00
jsr $fe1f ; idroutine. y = rom
cpy #3
bcc :nope
phd
pea #0
pld
psl #handle
_RemoveCDA
pld
:nope
rts
handle adrl Header ; can use a fake handle for now, until we need to _RemoveCDA
Header
str 'Virtual Terminal'
adrl start
adrl shutdown
* variables.
page ds 2
MAX_PAGE equ 8
pages dw variables
dw hexdump_r
dw hexdump_w
dw ssc_registers
shutdown
mx %00
@ -66,20 +119,59 @@ start
sta SETALTCHAR
rep #$30
stz page
jsr clear
jsr box
jsr content
main
jsr clear_inner
ldx page
jsr (pages,x)
:keyloop
sep #$30
lda KBD
bpl :keyloop
sta KEYSTROBE
rep #$30
and #$7f
cmp #$1b
beq :exit
cmp #$08 ; left
beq :left
cmp #$15
beq :right
bra :keyloop
:exit
pld
plb
rtl
:left lda page
dec
dec
bpl :lok
lda #MAX_PAGE-2
:lok sta page
bra main
:right lda page
inc
inc
cmp #MAX_PAGE
bcc :rok
lda #0
:rok sta page
bra main
clear
ldx #23*2
@ -98,6 +190,23 @@ clear
bpl :loop
rts
clear_inner
* clear the inner contents.
ldx #16*2
lda #" "
:loop ldy text+8,x
]offset equ 4
lup 16
sta |0+]offset,y
]offset equ ]offset+2
--^
dex
dex
bpl :loop
rts
box
php
@ -197,28 +306,43 @@ box
* print variables.
content
variables
php
sep #$20
jsr local
jsr decanm
jsr dectm
jsr decbm
jsr decom
jsr deckpam
jsr decckm
jsr decawm
jsr decarm
jsr decscnm
jsr deccolm
jsr lnm
jsr sgr
jsr dectm
jsr decbm
jsr decx
jsr decy
plp
rts
decanm
local
mx %10
ldy #line_4+4
ldx #:str
jsr print_xy_str
lda DECANM
lda DPAGE+LOCAL
jmp print_on_off
:str asc "LOCAL: ",00
decanm
mx %10
ldy #line_5+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECANM
bmi :100
ldx #:vt52
jmp print_xy_str
@ -226,75 +350,62 @@ decanm
:100 ldx #:vt100
jmp print_xy_str
:str asc "DECANM: ",00
:str asc "DECANM: ",00
:vt100 asc "vt100",00
:vt52 asc "vt52",00
dectm
mx %10
ldy #line_5+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECTM
inc
jmp print_number
:str asc "DECTM: ",00
decbm
decom
mx %10
ldy #line_6+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECBM
inc
jmp print_number
lda DPAGE+DECOM
jmp print_on_off
:str asc "DECBM: ",00
:str asc "DECOM: ",00
decom
deckpam
mx %10
ldy #line_7+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECOM
jmp print_check
:str asc "DECOM: ",00
deckpam
mx %10
ldy #line_8+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECKPAM
jmp print_check
jmp print_on_off
:str asc "DECKPAM: ",00
decckm
mx %10
ldy #line_9+4
ldy #line_8+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECCKM
jmp print_check
jmp print_on_off
:str asc "DECCKM: ",00
:str asc "DECCKM: ",00
decawm
mx %10
ldy #line_10+4
ldy #line_9+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECAWM
jmp print_check
jmp print_on_off
:str asc "DECAWM: ",00
:str asc "DECAWM: ",00
decarm
mx %10
ldy #line_10+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECARM
jmp print_on_off
:str asc "DECARM: ",00
decscnm
mx %10
@ -302,20 +413,89 @@ decscnm
ldx #:str
jsr print_xy_str
lda DPAGE+DECSCNM
jmp print_check
jmp print_on_off
:str asc "DECSCNM: ",00
lnm
deccolm
mx %10
ldy #line_12+4
ldx #:str
jsr print_xy_str
lda DPAGE+LNM
jmp print_check
lda DPAGE+DECCOLM
jmp print_on_off
:str asc "LNM: ",00
:str asc "DECCOLM: ",00
lnm
mx %10
ldy #line_13+4
ldx #:str
jsr print_xy_str
lda DPAGE+LNM
jmp print_on_off
:str asc "LNM: ",00
sgr
mx %10
ldy #line_14+4
ldx #:str
jsr print_xy_str
lda DPAGE+SGR
jmp print_binary
:str asc "SGR: ",00
dectm
mx %10
ldy #line_15+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECTM
inc
jmp print_number
:str asc "DECTM: ",00
decbm
mx %10
ldy #line_16+4
ldx #:str
jsr print_xy_str
lda DPAGE+DECBM
inc
jmp print_number
:str asc "DECBM: ",00
decx
mx %10
ldy #line_17+4
ldx #:str
jsr print_xy_str
lda DPAGE+x
and #$7f
inc
jmp print_number
:str asc "X: ",00
decy
mx %10
ldy #line_18+4
ldx #:str
jsr print_xy_str
lda DPAGE+y
inc
jmp print_number
:str asc "Y: ",00
print_xy_str
@ -329,7 +509,7 @@ print_xy_str
:end
rts
print_check
print_on_off
mx %10
bmi :set
ldx #:off
@ -341,32 +521,473 @@ print_check
:off asc "off",00
print_number
debug print_number
*
* print a base-10 number, 0-255
* a = #
mx %10
cmp #20
bcs :2
ldx #0
:100
cmp #100
bcc :10x
inx
* sec
sbc #100
bra :100
:10x
cpx #0
beq :10
pha
txa
* clc
* adc #"0"
ora #"0"
sta |$0,y
iny
pla
ldx #0
:10
cmp #10
bcs :1
:0 ora #"0"
bcc :1x
inx
sbc #10
bra :10
:1x
cpx #0
beq :1
pha
txa
* clc
* adc #"0"
ora #"0"
sta |$0,y
iny
pla
:1
* clc
* adc #"0"
ora #"0"
sta |$0,y
iny
rts
:2 pha
lda #"2"
print_binary
mx %10
* pha
* lda #"%"
* sta |$0,y
* iny
* pla
lup 8
asl
pha
lda #0
adc #"0"
sta |$0,y
iny
pla
sec
sbc #20
bra :0
:1 pha
lda #"1"
--^
rts
print_hex
mx %10
xba
lda #0
xba
pha
lsr
lsr
lsr
lsr
tax
lda hex,x
sta |$0,y
iny
pla
and #$0f
tax
lda hex,x
sta |$0,y
iny
rts
hexdump_r
*
* $1e00 buffer
*
mx %00
lda DPAGE+read_q_tail
sec
sbc #10
bra :0
sbc #8*16
and #$00ff
ora #$1e00
jmp hexdump_common
hexdump_w
*
* $1d00 buffer
*
mx %00
lda DPAGE+write_q_tail
sec
sbc #8*16
and #$00ff
ora #$1d00
jmp hexdump_common
hexdump_common
*
* a = address to start.
:screen equ 0
:screen2 equ 2
*:offset equ 4
:ptr equ 6
:count equ 8
:row equ 10
:c equ 12
mx %00
debug hexdump
php
sta :ptr
lda #0
* stz :offset
sep #$20
ldx #4*2
stx :row
:one_row
ldx :row
ldy text,x
sty :screen
sty :screen2
lda #8
sta :count
:one_byte
lda (:ptr)
inc :ptr
sta :c
lsr
lsr
lsr
lsr
tax
lda hex,x
ldy :screen
sta |$04,y
iny
lda :c
and #$0f
tax
lda hex,x
sta |$04,y
iny
lda #" "
sta |$04,y
iny
sty :screen
* ascii
ldx #"."
lda :c
cmp #$20
blt :dot
cmp #$80
bcs :dot
ora #$80
tax
:dot
txa
ldy :screen2
sta |8*3+4,y
iny
sty :screen2
dec :count
bne :one_byte
ldx :row
inx
inx
stx :row
cpx #20*2
bcc :one_row
plp
rts
hex asc "0123456789abcdef"
ssc_registers
debug ssc_registers
*
* print SSC read registers. read reg 8 (incoming data byte) is skipped.
*
*
*SCCBREG equ $c038
*SCCAREG equ $c039
*SCCBDATA equ $c03a
*SCCADATA equ $c03b
* read everything at once.
php
sep #$34 ; short m/x, ints off
lda #0
xba
* sei
ldx #0
lda SCCAREG ; sync
lda SCCBREG ; sync
stx SCCAREG
lda SCCAREG
sta ssc_data+0
stx SCCBREG
lda SCCBREG
sta ssc_data+1
inx ;1
stx SCCAREG
lda SCCAREG
sta ssc_data+2
stx SCCBREG
lda SCCBREG
sta ssc_data+3
inx ;2
stx SCCAREG
lda SCCAREG
sta ssc_data+4
stx SCCBREG
lda SCCBREG
sta ssc_data+5
inx ;3
stx SCCAREG
lda SCCAREG
sta ssc_data+6
stx SCCBREG
lda SCCBREG
sta ssc_data+7
ldx #10 ; 10
stx SCCAREG
lda SCCAREG
sta ssc_data+8
stx SCCBREG
lda SCCBREG
sta ssc_data+9
ldx #12 ; 12
stx SCCAREG
lda SCCAREG
sta ssc_data+10
stx SCCBREG
lda SCCBREG
sta ssc_data+11
inx ; 13
stx SCCAREG
lda SCCAREG
sta ssc_data+12
stx SCCBREG
lda SCCBREG
sta ssc_data+13
ldx #15 ; 15
stx SCCAREG
lda SCCAREG
sta ssc_data+14
stx SCCBREG
lda SCCBREG
sta ssc_data+15
cli
rep #$10 ; long x
mx %10
jsr rr0
jsr rr1
jsr rr2
jsr rr3 ; only exists in channel A.
jsr rr10
jsr rr12 ; baud low
* jsr rr13 ; baud high
jsr rr15
plp
rts
ssc_data ds 16
rr0
mx %10
ldy #line_5+4
ldx #:str
jsr print_xy_str
lda ssc_data+0
jsr print_binary
iny
iny
lda ssc_data+1
jmp print_binary
:str asc "RR 0: ",00
rr1
mx %10
ldy #line_6+4
ldx #:str
jsr print_xy_str
lda ssc_data+2
jsr print_binary
iny
iny
lda ssc_data+3
jmp print_binary
:str asc "RR 1: ",00
rr2
mx %10
ldy #line_7+4
ldx #:str
jsr print_xy_str
lda ssc_data+4
jsr print_binary
iny
iny
lda ssc_data+5
jmp print_binary
:str asc "RR 2: ",00
rr3
mx %10
ldy #line_8+4
ldx #:str
jsr print_xy_str
lda ssc_data+6
jsr print_binary
iny
iny
lda ssc_data+7
jmp print_binary
:str asc "RR 3: ",00
rr10
mx %10
ldy #line_9+4
ldx #:str
jsr print_xy_str
lda ssc_data+8
jsr print_binary
iny
iny
lda ssc_data+9
jmp print_binary
:str asc "RR 10: ",00
* 12/13 are baud
rr12
mx %10
ldy #line_10+4
ldx #:str
jsr print_xy_str
iny
iny
iny
iny
lda ssc_data+12
jsr print_hex
lda ssc_data+10
jsr print_hex
iny
iny
iny
iny
iny
iny
lda ssc_data+13
jsr print_hex
lda ssc_data+11
jmp print_hex
:str asc "RR 12: ",00
rr15
mx %10
ldy #line_11+4
ldx #:str
jsr print_xy_str
lda ssc_data+14
jsr print_binary
iny
iny
lda ssc_data+15
jmp print_binary
:str asc "RR 15: ",00

View File

@ -16,8 +16,9 @@
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
ext write_modem,write_modem_str
vt100_csi ent
@ -261,7 +262,7 @@ vt100_csi_2 ent
dw :rts ; u
dw :rts ; v
dw :rts ; w
dw :rts ; x
dw csi_x ; x
dw csi_y ; y
:modifier
@ -353,7 +354,7 @@ mode_common
dw :rts ; error
dw mode_DECCKM
dw mode_DECANM
dw :rts ; DECCOLM
dw mode_DECCOLM ; DECCOLM
dw :rts ; DECSCLM
dw mode_DECSCNM
dw mode_DECOM
@ -395,10 +396,33 @@ mode_DECANM
:rts rts
*mode_DECCOLM
* sty DECCOLM
* 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
@ -472,12 +496,8 @@ csi_m
cpx pcount
blt :loop
* now update - bit 7 indicates inverse.
lda SGR
and #$80
sta draw_inverse
jmp update_sgr
:rts rts
:and db $00,$ff,$ff,$ff,$ff,$ff,$ff,$ff
@ -787,12 +807,19 @@ csi_n ; status report
lda #'n'
jmp write_modem
:cpr ; cursor report
* TODO - verify and support DECOM
* returned y is in terms of DECOM.
lda #ESC
jsr write_modem
lda #'['
jsr write_modem
lda y
inc
bit DECOM
bpl :y
sec
sbc DECTM
:y inc
jsr write_digit
lda #';'
jsr write_modem
@ -828,23 +855,45 @@ write_digit
:table db 0,10,20,30,40,50,60,70,80
csi_c ; what are you?
lda #ESC
jsr write_modem
lda #'['
jsr write_modem
lda #'?'
jsr write_modem
lda #'1'
jsr write_modem
lda #'?'
jsr write_modem
lda #'0'
jsr write_modem
lda #'c'
jmp write_modem
* 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

View File

@ -109,8 +109,11 @@ xoff
rts
can
sub
ext draw_char_raw
* cancel esc sequence and display error character
stz state
lda #$57 ; mouse text block
jmp draw_char_raw
rts
esc

View File

@ -12,6 +12,7 @@
ext recalc_cursor,recalc_cursor_x,recalc_cursor_y
ext scroll_up,scroll_down
ext reset
ext update_sgr
vt100_esc ent
* #[()=>cH78DEM
@ -134,21 +135,29 @@ vt100_esc ent
esc_7 ; save cursor position, graphic rendition, and character set.
* based on testing, DECOM is also saved/restored.
lda x
sta saved_x
lda y
sta saved_y
lda DECOM
sta saved_decom
lda SGR
sta saved_sgr
rts
esc_8 ; restore cursor position, graphic rendition, and character set.
* TODO - how does this interact with DECOM?
lda saved_x
sta x
lda saved_y
sta y
lda saved_decom
sta DECOM
lda saved_sgr
sta SGR
jsr update_sgr
jmp recalc_cursor
esc_eq ; enter alternate keypad mode

View File

@ -4,13 +4,16 @@
xc
xc
tbx on
use vt.equ
use apple2gs.equ
use debug
mx %11
ext dispatch
* ext dispatch
ext write_modem
kmShift equ %0000_0001
@ -22,22 +25,58 @@ kmUpdateMod equ %0010_0000
kmOption equ %0100_0000
kmCommand equ %1000_0000
*
* The vt100 has a delete key and a backspace key.
* delete sends 0x7f. backspace sends 0x08.
* stty is general set so 0x7f is the erase character.
* termcaps generally claim 0x08 is the backspace character.
*
* emacs, by default, thinks 0x08 ( ^H ) means you want help.
*
* so, backspace will send 0x7f. control-H or command-backspace
* will send 0x08.
*
* TODO - keys
* command-L -> local/online mode?
* command-Q -> quit
* command-K -> clear screen?
* command-R -> reset settings
*
dispatch
jmp write_modem
keypress ent
debug keypress
lda KBD
bmi :key
rts
:rts rts
:key
and #$7f
sta key
lda KEYMOD
sta mod
sta KEYSTROBE
* if DECARM is clear, skip repeat characters.
*
* a REAL vt100 will never auto-repeat ESC, TAB, RETURN, or if Control is also pressed.
*
bit DECARM
bpl :arm
bit #kmRepeat
bne :rts
:arm
bit #kmOption!kmCommand
bne :command
bne command
bit #kmKeypad
bne keypad
jne keypad
bit #kmControl
bne :ctrl
@ -55,22 +94,35 @@ keypress ent
:ctrl
lda key
and #$1f ; control-space should generate 0, not $20.
bra :send
:notctrl
cmp #$7f ; delete - special case
bne :send
lda #$08
* cmp #$7f ; delete - special case
* bne :send
* lda #$08
:send jmp dispatch
:command ; or option
rts
command ; or option
keypad
* todo - keypad enters honors LNM?
* apple-return -> linefeed
* apple-backspace -> delete
lda key
cmp #$7f
beq :bs
cmp #$0d
beq :lf
cmp #'a'
bcc :0
cmp #'z'+1
bcs :0
and #$df ; ~ $20
:0
cmp #:MIN
blt :rts
cmp #:MAX+1
@ -83,6 +135,104 @@ keypad
:rts rts
:bs lda #$08
jmp dispatch ;
:lf lda #$0a
jmp dispatch
ext enable_modem,disable_modem
:local
bit LOCAL
bmi :online
lda #$80
sta LOCAL
jmp disable_modem
:online
stz LOCAL
jmp enable_modem
:quit
ext quit
jmp quit
rts
:reset
* TODO
rts
:clear
* TODO
rts
:MIN equ 49
:MAX equ 82
:table
dw pf1 ; 1
dw pf2 ; 2
dw pf3 ; 3
dw pf4 ; 4
dw :rts ; 5
dw :rts ; 6
dw :rts ; 7
dw :rts ; 8
dw :rts ; 9
dw :rts ; :
dw :rts ; ;
dw :rts ; <
dw :rts ; =
dw :rts ; >
dw :rts ; ?
dw :rts ; @
dw :rts ; A
dw :rts ; B
dw :rts ; C
dw :rts ; D
dw :rts ; E
dw :rts ; F
dw :rts ; G
dw :rts ; H
dw :rts ; I
dw :rts ; J
dw :clear ; K
dw :local ; L
dw :rts ; M
dw :rts ; N
dw :rts ; O
dw :rts ; P
dw :quit ; Q
dw :reset ; R
keypad
lda key
cmp #:MIN
blt :rts
cmp #:MAX+1
bcs :other
sec
sbc #:MIN
asl
tax
jmp (:table,x)
:other
* keypad delete key ($75 aka 'u') will send as backspace ($08)
*
cmp #'u'
bne :rts
lda #$08
jmp dispatch
:rts rts
:MIN equ 13
:MAX equ 61
:table
@ -118,7 +268,7 @@ keypad
dw pf4 ; *
dw comma ; +
dw :rts ; ,
dw dash ; -
dw dash ; -
dw dot ; .
dw pf3 ; / PF3 -> ESC R
dw digit ; 0
@ -131,9 +281,9 @@ keypad
dw digit ; 7
dw digit ; 8
dw digit ; 9
dw $0 ; :
dw $0 ; ;
dw $0 ; <
dw :rts ; :
dw :rts ; ;
dw :rts ; <
dw pf2 ; = PF2 -> ESC Q
@ -195,6 +345,7 @@ digit
lda #'?'
jsr dispatch
lda key
ora #$40
jmp dispatch

View File

@ -4,6 +4,8 @@
xc
xc
tbx on ; qasm
mx %11
use vt.equ
use apple2gs.equ
@ -11,13 +13,14 @@
ext scroll_down
ext recalc_cursor,recalc_cursor_x,recalc_cursor_y
ext write_modem,read_modem,init_modem,modem_vector,reset_modem_buffer
ext modem_io,modem_vector,reset_modem_buffer
ext modem_startup,modem_shutdown
ext keypress
ext disable_cursor,enable_cursor,cursor_vector
ext erase_screen,fill_screen
ext init_tabs
ext init_audio
ext init_cda
ext cda_startup,cda_shutdown
main debug main
@ -37,18 +40,17 @@ main debug main
stz SCANINT ; reset 1-sec interrupt
loop
bit LOCAL
bmi :kb
jsr read_modem
bcc :kb
jsr keypress ; check for a keypress, write data to out buffer.
jsr modem_io ;
bcc :nope
pha
jsr disable_cursor
pla
jsr vt100
:kb
jsr keypress
bra loop
:nope ; no modem data, re-enable the cursor.
jsr enable_cursor
bra loop
@ -63,6 +65,9 @@ init
sta SETALTCHAR
rep #$30
jsr init_mem
ldx #254
:zloop stz 0,x
dex
@ -107,19 +112,78 @@ init
sta DECBM
lda #$80
* sta LOCAL
sta DECANM
sta DECANM ; ANSI (vt100) on
sta DECARM ; key repeat on
* lda #st_vt52
lda #st_vt100
sta state
* jsr erase_screen
jsr init_modem
jsr modem_startup
jsr init_tabs
jsr init_audio
jsr init_cda
jsr cda_startup
rts
MasterID dw 0
init_mem
*
* see prodos technote #27
*
* _InstallCDA uses the memory manager ; otherwise I wouldn't bother
* This is here to prevent MM from stomping on our memory.
*
mx %00
stz MasterID
_TLStartUp
pha
_MMStartUp
pla
bcs :p8
rts
:p8
_MTStartUp
pea #0
pea #$1000
_GetNewID
pla
sta MasterID
* bank 0
pha
pha
pea #$0000
pea #$b800
lda MasterID
pha
pea #$c013
pea #0000
pea #0800
_NewHandle
pla
pla
* bank 1
pha
pha
pea #$0000
pea #$b800
lda MasterID
pha
pea #$c013
pea #$0001
pea #$0800
_NewHandle
pla
pla
rts
reset ent
mx %11
php
@ -165,7 +229,8 @@ reset ent
lda #23
sta DECBM
lda #$80
sta DECANM
sta DECANM ; ansi mode
sta DECARM ; key repeat on
lda #st_vt100
sta state
@ -183,16 +248,60 @@ reset ent
rts
dispatch ent
mx %11
* a = character to xmit
bit LOCAL
bmi :local
jmp write_modem
:local
quit ent
* need to disable modem interrupts
sep #$30
lda #4
trb VGCINT ; disable 1-sec interrupt.
stz SCANINT ; reset 1-sec interrupt
jsr modem_shutdown
rep #$30
jsr cda_shutdown
lda MasterID
beq :e
pha
jsr disable_cursor
pla
pha
_DisposeAll
_DeleteID
:e
pea #0
pld
sec
xce
mx %00
inc $3f4 ; invalidate power-up bit
jsr $bf00
db $65
dw :parms
brk $ea
:parms db 4
db 0
dw 0
db 0
dw 0
*dispatch ent
* mx %11
** a = character to xmit
* bit LOCAL
* bmi :local
* jmp write_modem
*:local
* pha
* jsr disable_cursor
* pla
* fall through
@ -215,7 +324,7 @@ vt100
ext vt100_esc,vt100_csi,vt100_csi_2
ext vt100_esc_pound,vt100_esc_lparen,vt100_esc_rparen
ext vt100_esc_bad,vt100_csi_bad
ext draw_char
ext draw_char,draw_char_raw
dw draw_char
dw vt52_esc
@ -291,7 +400,16 @@ ctrl_18
ctrl_1a
* vt100 - abort current escape sequence
* and display error character.
* TODO - display error character (mouse text)
*
* based on testing, this applies to vt52 and vt100;
* cancel character is drawn regardless of current state.
lda x
and #$1
ora #$56 ; $56 or $57
* lda #$57
jsr draw_char_raw
bit DECANM
bpl :vt52
lda #st_vt100

View File

@ -6,7 +6,8 @@
mx %11
cas se
* use vt.equ
use vt.equ
use debug
SCCBREG equ $c038
SCCAREG equ $c039
@ -29,14 +30,25 @@ SerFlag equ $e10104 ;
*
* see IIgs TN #18 - Do-It-Yourself SCC Access
init_modem ent
modem_startup ent
enable_modem ent
* sep #$30
php
sei
stz q_head
stz q_tail
stz read_q_head
stz read_q_tail
stz write_q_head
stz write_q_tail
* zero out the buffer [for CDA debugger]
ldx #0
]loop stz read_buffer,x
inx
bne ]loop
lda SCCBREG ; sync access
ldx #0
@ -78,7 +90,50 @@ init_modem ent
db 9,%00_0_0_1_0_1_0 ; master interrupts enabled.
db -1,-1
write_modem ent
disable_modem ent
* local mode
mx %11
php
sei
lda SCCBREG ; sync access
lda #9
sta SCCBREG
lda #%01_0_1_0_0_0_1 ; reset channel B.
sta SCCBREG
stz read_q_head
stz read_q_tail
stz write_q_head
stz write_q_tail
plp
rts
modem_shutdown ent
mx %11
php
sei
lda SCCBREG ; sync access
lda #9
sta SCCBREG
lda #%01_0_1_0_0_0_1 ; reset channel B.
sta SCCBREG
lda >SerFlag
and #%11_111_000 ; channel B interrupts.
sta >SerFlag
plp
rts
write_modem_sync ent
mx %11
* a: byte to send
tay ; save
@ -100,6 +155,7 @@ write_modem ent
plp
rts
read_modem_sync ent
* c set if data read
* v set if overrun
@ -136,7 +192,8 @@ read_modem_sync ent
:rts rts
buffer equ $1e00
write_buffer equ $1d00
read_buffer equ $1e00
modem_vector ent
jml modem_int
@ -150,12 +207,18 @@ modem_int
* doesn't access direct page.
* check/clear overrun?
*
* n.b. - vt100 would drop $00 and $7f characters here - I drop them later.
*
mx %11
phb
phk
plb
lda SCCBREG ; sync
stz SCCBREG
lda SCCBREG
and #%0000_0001 ; rx ready.
@ -163,9 +226,9 @@ modem_int
:read
lda SCCBDATA
ldx q_tail
sta buffer,x
inc q_tail
ldx DPAGE+read_q_head
sta read_buffer,x
inc DPAGE+read_q_head
* more?
stz SCCBREG
@ -192,6 +255,130 @@ modem_int
plb
rtl
modem_io ent
debug modem_io
mx %11
php
sei
bit LOCAL
bmi :local
:write
* send any outbound data...
:mask = %0010_0100 ; tx buffer empty, clear to send
ldx write_q_tail
cpx write_q_head
beq :read
lda SCCBREG ; sync
stz SCCBREG
lda SCCBREG
and #:mask
cmp #:mask
bne :read
* ldx write_q_tail
lda write_buffer,x
sta SCCBDATA
inc write_q_tail
:read
ldx read_q_tail
cpx read_q_head
beq :nope
lda read_buffer,x
inc read_q_tail
* $00 and $7f dropped here.
and #$7f
beq :read
cmp #$7f
beq :read
plp
sec
rts
:nope
plp
clc
rts
:local
ldx write_q_tail
cpx write_q_head
beq :nope
lda write_buffer,x
inc write_q_tail
plp
sec
rts
write_modem ent
write_modem_async ent
mx %11
php
sei
* bit LOCAL
* bmi :local
ldx write_q_head
sta write_buffer,x
inc write_q_head
plp
rts
*:local
* ldx read_q_head
* sta read_buffer,x
* inc read_q_head
* plp
* rts
write_modem_str ent
; y = address of string (0-terminated)
; inc write_q_head vs inx
; because it wraps at $ff
mx %10
php
sei
* bit LOCAL
* bmi :local
:loop lda |$0000,y
beq :fini
ldx write_q_head
sta write_buffer,x
inc write_q_head
iny
bra :loop
*:local lda |$0000,y
* beq :fini
* ldx read_q_head
* sta read_buffer,x
* inc read_q_head
* iny
* bra :local
:fini
plp
rts
read_modem ent
read_modem_async ent
@ -199,12 +386,12 @@ read_modem_async ent
php
sei
ldx q_head
cpx q_tail
ldx read_q_tail
cpx read_q_head
beq :nope
lda buffer,x
inc q_head
lda read_buffer,x
inc read_q_tail
plp
sec
rts
@ -218,13 +405,15 @@ reset_modem_buffer ent
mx %11
php
sei
stz q_head
stz q_tail
stz read_q_head
stz read_q_tail
stz write_q_head
stz write_q_tail
plp
rts
q_head ds 2
q_tail ds 2
*buffer ds 256
sav vt100.modem.L

View File

@ -21,6 +21,17 @@
* cursor_state - $80 = disabled, $40 = on
update_sgr ent
stz draw_inverse
lda SGR
beq :rts
lda #$80
sta draw_inverse
:rts rts
text
dw $0400
@ -236,16 +247,20 @@ draw_char ent
bpl :normal
; invert it.
cmp #$60 ; `, first lowercase
bge :draw ; nothing to do for lowercase
bge draw_char_raw ; nothing to do for lowercase
cmp #$40 ; @, first uppercase
bcc :draw ; nothing to do for special
bcc draw_char_raw ; nothing to do for special
:uc and #%10111111 ; ~ $40
bra :draw
bra draw_char_raw
:normal ora #$80
:draw
draw_char_raw ent
* entry point for writing character to screen w/o processing it
* sta cursor_saved_char
* with DECAWM, x = 79, will CR LF (with scroll) before drawing character.
@ -280,8 +295,6 @@ draw_char ent
rts
:wrap
stz x
ldy y
@ -295,7 +308,7 @@ draw_char ent
jsr recalc_cursor
pla
sta [cursor_base] ; offset 0
rts
jmp advance_x
:scroll
pha ; save
@ -304,7 +317,7 @@ draw_char ent
jsr recalc_cursor_x
pla
sta [cursor_base] ; offset 0
rts
jmp advance_x
* erase screen commands are not affected by origin or scrolling region.