forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1198 lines
33 KiB
1198 lines
33 KiB
'******************************************************************************
|
|
'* vt100.spin - DEC VT100 terminal emulation
|
|
'*
|
|
'* (c) Juergen Buchmueller <pullmoll@t-online.de>
|
|
'*
|
|
'* $Id: vt100.spin,v 1.6 2010-04-17 13:48:13 pm Exp $
|
|
'******************************************************************************
|
|
CON
|
|
attr_highlite = %00000001
|
|
attr_underline = %00000010
|
|
attr_inverse = %00000100
|
|
attr_blinking = %00001000
|
|
|
|
flag_deccm = %0_00000001 ' DEC cursor mode (0: off, 1: on)
|
|
flag_decim = %0_00000010 ' DEC insert mode
|
|
flag_decom = %0_00000100 ' DEC origin mode
|
|
flag_deccr = %0_00001000 ' DEC send CRLF or LF (0: LF, 1: CRLF)
|
|
flag_decck = %0_00010000 ' DEC send cursor keys
|
|
flag_decawm = %0_00100000 ' DEC auto wrap mode
|
|
flag_decarm = %0_01000000 ' DEC auto repeat mode
|
|
flag_meta = %0_10000000 ' meta character toggle
|
|
flag_ctrl = %1_00000000 ' display control characters
|
|
flag_decrm = 1<<10 ' DEC report mouse
|
|
|
|
VAR
|
|
long cog
|
|
|
|
PUB start(params) : okay
|
|
stop
|
|
okay := cog := COGNEW(@entry, params) + 1
|
|
|
|
PUB stop : okay
|
|
if cog
|
|
COGSTOP(cog~~ - 1)
|
|
|
|
DAT
|
|
org 0
|
|
entry
|
|
command_ptr mov t1, PAR
|
|
cmd rdlong command_ptr, t1 ' parameter 0
|
|
screen_ptr add t1, #4
|
|
screen_end rdlong screen_ptr, t1 ' parameter 1
|
|
cursor_ptr add t1, #4
|
|
vsync_ptr rdlong cursor_ptr, t1 ' parameter 2
|
|
screen_w add t1, #4
|
|
screen_w2 rdlong vsync_ptr, t1 ' parameter 3
|
|
screen_h add t1, #4
|
|
cur_ptr rdlong screen_w, t1 ' parameter 4
|
|
scroll_top add t1, #4
|
|
scroll_bot rdlong screen_h, t1 ' parameter 5
|
|
dst mov screen_w2, screen_w
|
|
src shr screen_w2, #1 ' screen width / 2
|
|
end mov t1, screen_w
|
|
data mov t2, screen_h
|
|
cols call #mul16x16
|
|
rows mov screen_end, t2 ' result in t2
|
|
lmm_pc add screen_end, t2 ' * 2
|
|
cur_x_save add screen_end, screen_ptr
|
|
cur_y_save mov scroll_top, #0
|
|
new_x_save mov scroll_bot, screen_h
|
|
attr_save mov cur_delay, CNT
|
|
jmp #startup
|
|
control_ptr long @@@control_table
|
|
csi_cmds_ptr long @@@csi_cmds
|
|
x00200020 long $00200020
|
|
cur_block long $5f
|
|
|
|
inverse long 0
|
|
cur_x long 0
|
|
new_x long 0
|
|
cur_y long 0
|
|
attr long 0 ' attribute mode
|
|
flags long flag_decom | flag_decawm
|
|
cur_char long 0
|
|
cur_delay long 0
|
|
fgcol long %0111 ' foreground color
|
|
bgcol long %0000 ' background color
|
|
color long %00000111_00000000 ' composed fore- and background
|
|
esc_mode long 0
|
|
csi_mode long 0
|
|
csi_argc long 0
|
|
csi_argf long 0
|
|
csi_args long 0,0,0,0,0,0,0,0
|
|
question_mark long 0
|
|
|
|
t1 long 0
|
|
t2 long 0
|
|
t3 long 0
|
|
|
|
goto_xay
|
|
' TODO: check origin mode flag
|
|
add cur_y, scroll_top
|
|
validate_cursor
|
|
mov cur_x, cur_x WC ' negative x?
|
|
if_c mov cur_x, #0 ' yes, clip to 0
|
|
cmp cur_x, screen_w WZ, WC
|
|
if_ae mov cur_x, screen_w ' stay inside the boundaries
|
|
if_ae sub cur_x, #1
|
|
mov new_x, cur_x
|
|
mov cur_y, cur_y WC ' negative y?
|
|
if_c mov cur_y, #0 ' yes, clip to 0
|
|
cmp cur_y, screen_h WZ, WC
|
|
if_ae mov cur_y, screen_h ' stay inside the boundaries
|
|
if_ae sub cur_y, #1
|
|
cmdloop
|
|
mov cmd, #0
|
|
wrlong cmd, command_ptr
|
|
startup
|
|
:loop tjz cursor_ptr, #:cursor ' skip if cursor_ptr is null
|
|
wrbyte new_x, cursor_ptr ' write the (new) cursor position
|
|
add cursor_ptr, #1
|
|
wrbyte cur_y, cursor_ptr ' and the cursor row, too
|
|
sub cursor_ptr, #1
|
|
call #calc_cursor
|
|
jmp #:check_cmd
|
|
:cursor mov t1, cur_delay ' software cursor
|
|
sub t1, CNT
|
|
cmps t1, #0 WZ, WC
|
|
if_ae jmp #:check_cmd
|
|
rdlong t1, #0 ' get clkfreq
|
|
shr t1, #2 ' / 4
|
|
add cur_delay, t1 ' next cursor flash event
|
|
call #calc_cursor
|
|
cmp new_x, screen_w WZ, WC ' new_x beyond last column?
|
|
if_ae jmp #:check_cmd
|
|
mov t1, cur_char WZ ' get saved character
|
|
if_z rdbyte cur_char, cur_ptr ' none: save character under cursor
|
|
if_z wrbyte cur_block, cur_ptr ' display a cursor block
|
|
if_nz mov cur_char, #0 ' reset saved character
|
|
if_nz wrbyte t1, cur_ptr ' restore saved character in screen buffer
|
|
:check_cmd rdlong cmd, command_ptr WZ
|
|
if_z jmp #:loop
|
|
|
|
mov t1, cur_char WZ ' get saved character
|
|
if_nz cmp cur_ptr, screen_end WC
|
|
if_nz_and_c mov cur_char, #0 ' reset saved character
|
|
if_nz_and_c wrbyte t1, cur_ptr ' restore saved character in screen buffer
|
|
|
|
and cmd, #$ff
|
|
tjnz csi_mode, #csi ' go to CSI decoding if enabled
|
|
tjnz esc_mode, #esc ' go to ESC decoding if enabled
|
|
cmp cmd, #$20 WZ, WC ' other control characters?
|
|
if_ae jmp #do_emit ' no, just emit to the screen buffer
|
|
shl cmd, #1
|
|
add cmd, control_ptr
|
|
rdword cmd, cmd
|
|
jmp cmd ' dispatch on control_table
|
|
|
|
do_emit call #emit
|
|
jmp #cmdloop
|
|
|
|
do_nul ' NUL - null character
|
|
do_soh ' SOH - start of header
|
|
do_stx ' STX - start of text
|
|
do_etx ' ETX - end of text
|
|
do_eot ' EOT - end of transmission
|
|
do_enq ' ENQ - enquiry
|
|
do_ack ' ACK - acknowledgement
|
|
do_bel ' BEL - bell
|
|
do_dle ' DLE - data link escape
|
|
do_dc1 ' DC1 - device control 1 (XON)
|
|
do_dc2 ' DC2 - device control 2
|
|
do_dc3 ' DC3 - device control 3 (XOFF)
|
|
do_dc4 ' DC4 - device control 4
|
|
do_nak ' NAK - negative acknowledgement
|
|
do_syn ' SYN - synchronous idle
|
|
do_etb ' ETB - end of transmission block
|
|
do_em ' EM - end of medium
|
|
do_sub ' SUB - substitute
|
|
do_fs ' FS - file separator
|
|
do_gs ' GS - group separator
|
|
do_rs ' RS - request to send
|
|
do_us ' US - unit separator
|
|
jmp #cmdloop
|
|
|
|
do_cr call #cr
|
|
jmp #cmdloop
|
|
|
|
do_bs call #bs
|
|
jmp #cmdloop
|
|
|
|
do_ht call #ht
|
|
jmp #cmdloop
|
|
|
|
do_lf call #lf
|
|
jmp #cmdloop
|
|
|
|
do_vt call #vt
|
|
jmp #cmdloop
|
|
|
|
do_ff call #ff
|
|
jmp #cmdloop
|
|
|
|
do_so ' ???
|
|
jmp #cmdloop
|
|
|
|
do_si ' ???
|
|
jmp #cmdloop
|
|
|
|
do_can ' CAN - cancel
|
|
call #can
|
|
jmp #cmdloop
|
|
do_esc
|
|
mov esc_mode, #1
|
|
jmp #cmdloop
|
|
esc
|
|
mov esc_mode, #0
|
|
cmp cmd, #"[" WZ
|
|
if_z jmp #:csi
|
|
' TODO: non-CSI escape sequences
|
|
jmp #cmdloop
|
|
:csi
|
|
mov csi_mode, #1 ' start CSI mode
|
|
mov csi_argc, #0 ' argument count = 0
|
|
mov csi_argf, #0 ' argument flag = 0
|
|
mov csi_args, #0 ' first argument = 0
|
|
jmp #cmdloop
|
|
|
|
csi
|
|
cmp csi_mode, #1 WZ ' first character after "["?
|
|
if_nz jmp #:not_question ' no, check arguments
|
|
mov csi_mode, #2 ' skip this test in the future
|
|
cmp cmd, #"?" WZ ' "<ESC>[?" mode?
|
|
muxz question_mark, #1
|
|
if_z jmp #cmdloop
|
|
|
|
:not_question
|
|
cmp cmd, #"0" WZ, WC
|
|
if_b jmp #:not_numeric
|
|
cmp cmd, #"9" WZ, WC
|
|
if_a jmp #:not_numeric
|
|
mov t1, csi_argc
|
|
add t1, #csi_args
|
|
movs :get_arg, t1
|
|
movd :put_arg, t1
|
|
mov csi_argf, #1 ' set the "seen arguments" flag
|
|
:get_arg mov t1, 0-0 ' get csi_args[csi_argc]
|
|
mov t2, t1 ' to t2 also
|
|
shl t1, #2 ' * 4
|
|
add t1, t2 ' * 5
|
|
shl t1, #1 ' * 10
|
|
add t1, cmd ' + digit
|
|
sub t1, #"0" ' - ASCII for "0"
|
|
:put_arg mov 0-0, t1 ' put csi_args[csi_argc]
|
|
jmp #cmdloop
|
|
|
|
:not_numeric
|
|
cmp cmd, #";" WZ ' next argument delimiter?
|
|
if_nz jmp #:not_delimiter
|
|
cmp csi_argc, #7 WZ ' reached maximum number of arguments?
|
|
if_nz add csi_argc, #1 ' no, use next slot
|
|
mov t1, csi_argc
|
|
add t1, #csi_args
|
|
movd :clr_arg, t1
|
|
nop
|
|
:clr_arg mov 0-0, #0 ' preset csi_args[csi_argc] to 0
|
|
jmp #cmdloop
|
|
|
|
:not_delimiter
|
|
mov csi_mode, #0 ' end CSI mode
|
|
add csi_argc, csi_argf ' incr. argument count, if any arguments were specified
|
|
|
|
cmp cmd, #"@" WZ, WC ' below @?
|
|
if_b jmp #cmdloop
|
|
cmp cmd, #"z" WZ, WC ' above z?
|
|
if_ae jmp #cmdloop
|
|
sub cmd, #"@"
|
|
shl cmd, #1 ' function word index
|
|
add cmd, csi_cmds_ptr
|
|
rdword cmd, cmd ' get function pointer
|
|
testn cmd, #$1ff WZ ' any bits outside the cog?
|
|
if_z jmp cmd ' cog function
|
|
mov lmm_pc, cmd ' otherwise it's an LMM address
|
|
jmp #lmm_loop ' execute LMM code
|
|
|
|
'********************************************************************************************
|
|
' non_zero_args - make sure the first argument is at least 1
|
|
'
|
|
non_zero_args
|
|
tjnz csi_args, #non_zero_args_ret
|
|
add csi_args, #1
|
|
non_zero_args_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' shift_csi_args - remove the first value from the list of arguments, pad with 0
|
|
'
|
|
shift_csi_args
|
|
mov csi_args, csi_args + 1
|
|
mov csi_args + 1, csi_args + 2
|
|
mov csi_args + 2, csi_args + 3
|
|
mov csi_args + 3, csi_args + 4
|
|
mov csi_args + 4, csi_args + 5
|
|
mov csi_args + 5, csi_args + 6
|
|
mov csi_args + 6, csi_args + 7
|
|
mov csi_args + 7, #0
|
|
shift_csi_args_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' cr - carriage return
|
|
'
|
|
cr
|
|
mov cur_x, #0
|
|
mov new_x, #0
|
|
cr_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' bs - back space
|
|
'
|
|
bs
|
|
cmp new_x, #0 WZ
|
|
if_nz sub new_x, #1
|
|
if_nz jmp #bs_ret
|
|
mov new_x, screen_w
|
|
sub new_x, #1
|
|
call #vt
|
|
bs_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' fs - forward space
|
|
'
|
|
fs
|
|
add cur_x, #1
|
|
cmp cur_x, screen_w WZ
|
|
if_z sub cur_x, #1 ' stay in last column
|
|
fs_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' ht - horizontal tabulator
|
|
'
|
|
ht
|
|
mov cmd, #$20
|
|
call #emit
|
|
test new_x, #7 WZ
|
|
if_nz jmp #ht
|
|
ht_ret
|
|
ret
|
|
'********************************************************************************************
|
|
' lf - line feed
|
|
'
|
|
lf
|
|
add cur_y, #1
|
|
test flags, #flag_decom WZ ' origin mode enabled?
|
|
if_nz jmp #:origin ' yes, check cursor in scroll range
|
|
|
|
:screen cmp cur_y, screen_h WZ, WC ' no, check cursor in screen range
|
|
if_b jmp #lf_ret
|
|
mov cur_y, screen_h
|
|
sub cur_y, #1
|
|
mov dst, screen_ptr ' destination = screen buffer
|
|
mov src, screen_ptr ' source = dito
|
|
mov rows, screen_h ' screen height
|
|
jmp #scroll_up_1 ' scroll the entire screen
|
|
|
|
:origin cmp cur_y, scroll_bot WZ, WC
|
|
if_b jmp #lf_ret
|
|
mov cur_y, scroll_bot
|
|
sub cur_y, #1
|
|
scroll_up
|
|
mov t1, scroll_top
|
|
mov t2, screen_w
|
|
call #mul16x16
|
|
shl t2, #1
|
|
add t2, screen_ptr
|
|
mov dst, t2 ' destination = scroll_top of screen buffer
|
|
mov src, t2 ' source = dito
|
|
mov rows, scroll_bot ' scroll range height
|
|
sub rows, scroll_top
|
|
scroll_up_1
|
|
add src, screen_w ' copy from one line below
|
|
add src, screen_w
|
|
sub rows, #1 WZ, WC ' - 1 rows to move
|
|
if_be jmp #:fill ' nothing left to scroll?
|
|
:rows mov cols, screen_w2 ' columns = screen width / 2
|
|
:cols rdlong data, src
|
|
add src, #4
|
|
wrlong data, dst
|
|
add dst, #4
|
|
djnz cols, #:cols
|
|
djnz rows, #:rows
|
|
:fill mov cols, screen_w2 ' columns = screen width / 2
|
|
mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:blank wrlong t1, dst ' fill 4 spaces
|
|
add dst, #4
|
|
djnz cols, #:blank
|
|
scroll_up_ret
|
|
lf_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' vt - vertical tab (inverse line feed)
|
|
'
|
|
vt
|
|
sub cur_y, #1
|
|
test flags, #flag_decom WZ ' origin mode enabled?
|
|
if_nz jmp #:origin ' yes, check cursor in scroll range
|
|
|
|
:screen ' no, check cursor in screen range
|
|
cmps cur_y, #0 WZ, WC ' < 0?
|
|
if_ae jmp #vt_ret ' in range
|
|
mov cur_y, #0 ' stay in line 0
|
|
mov src, screen_end
|
|
mov dst, screen_end
|
|
mov rows, screen_h
|
|
jmp #scroll_down_1
|
|
:origin
|
|
cmps cur_y, scroll_top WZ, WC
|
|
if_ae jmp #vt_ret
|
|
mov cur_y, scroll_top
|
|
scroll_down
|
|
mov t1, scroll_bot
|
|
mov t2, screen_w
|
|
call #mul16x16
|
|
shl t2, #1
|
|
add t2, screen_ptr
|
|
mov dst, t2 ' destination = end of scroll range buffer
|
|
mov src, t2 ' source = last row of scroll range buffer
|
|
mov rows, scroll_bot ' scroll range height
|
|
sub rows, scroll_top
|
|
scroll_down_1
|
|
sub src, screen_w
|
|
sub src, screen_w
|
|
sub rows, #1 WZ, WC ' - 1 rows to move
|
|
if_be jmp #:fill ' nothing left to scroll?
|
|
:rows mov cols, screen_w2 ' columns = screen width / 2
|
|
:cols sub src, #4 ' pre decrement source
|
|
rdlong data, src
|
|
sub dst, #4 ' pre decrement destination
|
|
wrlong data, dst
|
|
djnz cols, #:cols ' for all columns
|
|
djnz rows, #:rows ' for all rows
|
|
:fill mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
mov cols, screen_w2 ' columns = screen width / 2
|
|
:blank sub dst, #4
|
|
wrlong t1, dst
|
|
djnz cols, #:blank
|
|
scroll_down_ret
|
|
vt_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' ff - form feed (clear screen)
|
|
'
|
|
ff
|
|
mov dst, screen_ptr
|
|
mov rows, screen_h ' screen height rows
|
|
mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:rows mov cols, screen_w2 ' columns = screen width / 2
|
|
:cols wrlong t1, dst ' fill with 4 blanks
|
|
add dst, #4
|
|
djnz cols, #:cols ' for all columns
|
|
djnz rows, #:rows ' for all rows
|
|
call #home
|
|
ff_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' home - cursor home
|
|
'
|
|
home
|
|
mov cur_x, #0
|
|
mov new_x, #0
|
|
mov cur_y, #0
|
|
home_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' can - clear from cursor to end of line
|
|
'
|
|
can
|
|
mov dst, cur_ptr
|
|
mov cols, screen_w
|
|
sub cols, new_x WZ, WC
|
|
if_be jmp #can_ret
|
|
mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:fill wrword t1, dst
|
|
add dst, #2
|
|
djnz cols, #:fill
|
|
can_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' emit - emit character to cursor and advance cursor position
|
|
'
|
|
emit
|
|
cmp new_x, screen_w WZ, WC ' reached end of line?
|
|
if_b jmp #:in_bounds
|
|
test flags, #flag_decawm WZ ' auto wrap mode active?
|
|
if_z jmp #emit_ret ' no, don't emit character
|
|
call #cr
|
|
call #lf
|
|
:in_bounds mov cur_x, new_x
|
|
call #calc_cursor
|
|
or cmd, color
|
|
test attr, #attr_underline WZ
|
|
muxnz cmd, #$80
|
|
wrword cmd, cur_ptr ' write character to screen RAM
|
|
mov new_x, cur_x
|
|
add new_x, #1
|
|
add cur_ptr, #2
|
|
emit_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' calc_cursor - compute cursor address in cur_ptr
|
|
'
|
|
calc_cursor
|
|
mov t1, cur_y ' cursor row
|
|
mov t2, screen_w ' * screen width
|
|
call #mul16x16
|
|
mov cur_ptr, t2 ' product in cur_ptr
|
|
add cur_ptr, new_x ' + new cursor column
|
|
shl cur_ptr, #1 ' * 2
|
|
add cur_ptr, screen_ptr ' + screen buffer address
|
|
calc_cursor_ret
|
|
ret
|
|
|
|
'********************************************************************************************
|
|
' enable_cursor - enable or disable the cursor depending on the deccm flag
|
|
'
|
|
enable_cursor
|
|
tjz cursor_ptr, #cmdloop
|
|
test flags, #flag_deccm WZ ' cursor enabled?
|
|
if_z mov t1, #%000 ' cursor off
|
|
if_nz mov t1, #%110 ' cursor on, blink slow
|
|
add cursor_ptr, #2 ' cursor control
|
|
wrbyte t1, cursor_ptr
|
|
sub cursor_ptr, #2
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' set_color - combine background and foreground color and write the table
|
|
'
|
|
set_color
|
|
test attr, #attr_inverse WZ
|
|
if_z jmp #:default
|
|
:inverse
|
|
mov color, fgcol ' compose inverse color
|
|
shl color, #4
|
|
or color, bgcol
|
|
jmp #:cont
|
|
:default
|
|
mov color, bgcol ' compose default color
|
|
shl color, #4
|
|
or color, fgcol
|
|
:cont
|
|
test attr, #attr_highlite WZ
|
|
muxnz color, #$08
|
|
test attr, #attr_blinking WZ
|
|
muxnz color, #$80
|
|
shl color, #8 ' in bits 15..8
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' mul16x16 - multiply 16 bits in t1 by 16 bits in t2, result in t2
|
|
'
|
|
mul16x16
|
|
shl t1, #16 ' multiplicand in bits 31..16
|
|
mov t3, #16 ' loop 16 times
|
|
shr t2, #1 WC ' get initial multiplier bit in carry
|
|
:loop if_c add t2, t1 WC ' if carry set, add multiplicand to product
|
|
rcr t2, #1 WC ' next multiplier bit to carry, shift product
|
|
djnz t3, #:loop ' until done
|
|
mul16x16_ret
|
|
ret
|
|
|
|
lmm_loop
|
|
rdlong :op1, lmm_pc
|
|
add lmm_pc, #4
|
|
:op1 nop
|
|
rdlong :op2, lmm_pc
|
|
add lmm_pc, #4
|
|
:op2 nop
|
|
rdlong :op3, lmm_pc
|
|
add lmm_pc, #4
|
|
:op3 nop
|
|
rdlong :op4, lmm_pc
|
|
add lmm_pc, #4
|
|
:op4 nop
|
|
jmp #lmm_loop
|
|
|
|
fit $1f0
|
|
|
|
control_table word do_nul, do_soh, do_stx, do_etx, do_eot, do_enq, do_ack, do_bel
|
|
word do_bs, do_ht, do_lf, do_vt, do_ff, do_cr, do_so, do_si
|
|
word do_dle, do_dc1, do_dc2, do_dc3, do_dc4, do_nak, do_syn, do_etb
|
|
word do_can, do_em, do_sub, do_esc, do_fs, do_gs, do_rs, do_us
|
|
|
|
csi_cmds word @@@do_insert_char ' <ESC>[...@
|
|
word @@@do_cursor_up ' <ESC>[...A
|
|
word @@@do_cursor_down ' <ESC>[...B
|
|
word @@@do_cursor_left ' <ESC>[...C
|
|
word @@@do_cursor_right ' <ESC>[...D
|
|
word @@@do_rows_up ' <ESC>[...E
|
|
word @@@do_rows_down ' <ESC>[...F
|
|
word @@@do_cursor_column ' <ESC>[...G
|
|
word @@@do_cursor_address ' <ESC>[...H
|
|
word cmdloop ' I unused?
|
|
word @@@do_clear_screen ' <ESC>[...J
|
|
word @@@do_clear_row ' <ESC>[...K
|
|
word @@@do_insert_line ' <ESC>[...L
|
|
word @@@do_delete_line ' <ESC>[...M
|
|
word cmdloop ' N unused?
|
|
word cmdloop ' O unused?
|
|
word @@@do_delete_char ' P unused?
|
|
word cmdloop ' Q unused?
|
|
word cmdloop ' R unused?
|
|
word cmdloop ' S unused?
|
|
word cmdloop ' T unused?
|
|
word cmdloop ' U unused?
|
|
word cmdloop ' V unused?
|
|
word cmdloop ' W unused?
|
|
word @@@do_blank_chars ' <ESC>[...X
|
|
word cmdloop ' Y unused?
|
|
word cmdloop ' Z unused?
|
|
word cmdloop ' [ unused
|
|
word cmdloop ' \ unused
|
|
word cmdloop ' ] unused
|
|
word cmdloop ' ^ unused
|
|
word cmdloop ' _ unused
|
|
word @@@do_cursor_column ' <ESC>[...` alternate form for <ESC>[...G
|
|
word cmdloop ' a unused?
|
|
word cmdloop ' b unused?
|
|
word cmdloop ' c unused?
|
|
word cmdloop ' d unused?
|
|
word cmdloop ' e unused?
|
|
word @@@do_cursor_address ' <ESC>[...f alternate form for <ESC>[...H
|
|
word cmdloop ' g unused?
|
|
word @@@do_flag_set ' h unused?
|
|
word cmdloop ' i unused?
|
|
word cmdloop ' j unused?
|
|
word cmdloop ' k unused?
|
|
word @@@do_flag_res ' h unused?
|
|
word @@@do_mode_attributes ' <ESC>[...m
|
|
word cmdloop ' n unused?
|
|
word cmdloop ' o unused?
|
|
word cmdloop ' p unused?
|
|
word cmdloop ' q unused?
|
|
word @@@do_scroll_range ' <ESC>[...r
|
|
word @@@do_save_cursor ' <ESC>[?...s
|
|
word cmdloop ' t unused?
|
|
word @@@do_restore_cursor ' <ESC>[?...u
|
|
word cmdloop ' v unused?
|
|
word cmdloop ' w unused?
|
|
word cmdloop ' x unused?
|
|
word cmdloop ' y unused?
|
|
word cmdloop ' z unused?
|
|
|
|
'********************************************************************************************
|
|
'
|
|
' LMM code fragments following
|
|
'
|
|
'********************************************************************************************
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...@ - insert n spaces at the cursor position
|
|
'
|
|
do_insert_char
|
|
call #non_zero_args
|
|
cmp new_x, screen_w WZ, WC
|
|
if_ae jmp #cmdloop
|
|
:loop mov t1, cur_y
|
|
mov t2, screen_w
|
|
call #mul16x16
|
|
add t2, new_x
|
|
shl t2, #1
|
|
add t2, screen_ptr
|
|
mov dst, t2
|
|
add dst, #2
|
|
mov src, t2
|
|
mov cols, screen_w
|
|
sub cols, new_x
|
|
sub cols, #1 WZ, WC
|
|
if_be add lmm_pc, #4*(:blank - $ - 1)
|
|
:insert rdword data, src
|
|
add src, #2
|
|
wrword data, dst
|
|
add dst, #2
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :insert)
|
|
mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:blank wrword t1, t2
|
|
sub csi_args, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...A - cursor up
|
|
'
|
|
do_cursor_up
|
|
call #non_zero_args
|
|
:loop call #vt
|
|
sub csi_args, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...B - cursor down
|
|
'
|
|
do_cursor_down
|
|
call #non_zero_args
|
|
:loop call #lf
|
|
djnz csi_args, #:loop
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...C - cursor left
|
|
'
|
|
do_cursor_left
|
|
call #non_zero_args
|
|
mov cur_x, new_x
|
|
sub cur_x, csi_args WC
|
|
if_c mov cur_x, #0
|
|
jmp #validate_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...D - cursor right
|
|
'
|
|
do_cursor_right
|
|
call #non_zero_args
|
|
mov cur_x, new_x
|
|
add cur_x, csi_args
|
|
jmp #validate_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...E - rows up, cursor column = 0
|
|
'
|
|
do_rows_up
|
|
call #non_zero_args
|
|
mov cur_x, #0
|
|
mov new_x, #0
|
|
sub cur_y, csi_args WC
|
|
if_c mov cur_y, #0
|
|
jmp #validate_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...F - rows down, cursor column = 0
|
|
'
|
|
do_rows_down
|
|
call #non_zero_args
|
|
mov cur_x, #0
|
|
mov new_x, #0
|
|
add cur_y, csi_args
|
|
jmp #validate_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...H - cursor address - row, column
|
|
'
|
|
do_cursor_address
|
|
cmp csi_argf, #0 WZ ' nor arguments at all?
|
|
if_z call #home
|
|
if_z jmp #cmdloop
|
|
call #non_zero_args
|
|
mov cur_y, csi_args
|
|
sub cur_y, #1
|
|
cmp csi_argc, #1 WZ, WC ' the caller specified just a row?
|
|
if_be jmp #validate_cursor
|
|
call #shift_csi_args
|
|
' fall through
|
|
'********************************************************************************************
|
|
' <ESC>[...G - cursor column
|
|
'
|
|
do_cursor_column
|
|
call #non_zero_args
|
|
mov cur_x, csi_args
|
|
sub cur_x, #1
|
|
jmp #validate_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...J - clear screen
|
|
'
|
|
do_clear_screen
|
|
call #calc_cursor
|
|
cmp csi_args, #0 WZ ' cursor to end of screen?
|
|
if_nz add lmm_pc, #4*(:not_0 - $ - 1)
|
|
mov dst, cur_ptr
|
|
mov end, screen_end
|
|
add lmm_pc, #4*(:fill - $ - 1)
|
|
:not_0 cmp csi_args, #1 WZ ' start of screen to cursor?
|
|
if_nz add lmm_pc, #4*(:not_1 - $ - 1)
|
|
mov dst, screen_ptr
|
|
mov end, cur_ptr
|
|
add lmm_pc, #4*(:fill - $ - 1)
|
|
:not_1 cmp csi_args, #2 WZ ' entire screen?
|
|
if_nz jmp #cmdloop ' invalid argument
|
|
mov dst, screen_ptr ' default = entire screen
|
|
mov end, screen_end
|
|
:fill mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:loop wrword t1, dst ' fill a word
|
|
add dst, #2
|
|
cmp dst, end WZ, WC
|
|
if_b sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...K - clear cursor row
|
|
'
|
|
do_clear_row
|
|
call #calc_cursor
|
|
cmp csi_args, #0 WZ ' cursor to end of row?
|
|
if_nz add lmm_pc, #4*(:not_0 - $ - 1)
|
|
mov dst, cur_ptr ' default = cursor to end of row
|
|
mov end, cur_ptr
|
|
sub end, new_x
|
|
add end, screen_w ' end of row
|
|
add lmm_pc, #4*(:fill - $ - 1)
|
|
:not_0 cmp csi_args, #1 WZ ' start of row to cursor?
|
|
if_nz add lmm_pc, #4*(:not_1 - $ - 1)
|
|
mov dst, cur_ptr
|
|
sub dst, new_x ' start of row
|
|
mov end, cur_ptr ' to cursor
|
|
add lmm_pc, #4*(:fill - $ - 1)
|
|
:not_1 cmp csi_args, #2 WZ ' entire row?
|
|
if_nz jmp #cmdloop ' invalid argument
|
|
mov dst, cur_ptr
|
|
sub dst, new_x ' start of row
|
|
mov end, dst
|
|
add end, screen_w ' end of row
|
|
:fill mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:loop wrword t1, dst ' fill a word
|
|
add dst, #2
|
|
cmp dst, end WZ, WC
|
|
if_b sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...L - insert line(s)
|
|
'
|
|
do_insert_line
|
|
call #non_zero_args
|
|
:loop mov dst, screen_end
|
|
mov src, screen_end
|
|
sub src, screen_w
|
|
mov rows, screen_h ' screen rows
|
|
sub rows, cur_y ' - cursor row
|
|
sub rows, #1 WZ, WC ' - 1
|
|
if_be add lmm_pc, #4*(:fill - $ - 1) ' nothing left to move?
|
|
:rows mov cols, screen_w2 ' columns = screen width / 2
|
|
:cols sub src, #4
|
|
rdlong data, src
|
|
sub dst, #4
|
|
wrlong data, dst
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :cols)
|
|
sub rows, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :rows)
|
|
:fill mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
mov cols, screen_w2 ' columns = screen width / 2
|
|
:blank sub dst, #4
|
|
wrlong t1, dst
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :blank) ' for all columns
|
|
sub csi_args, #1 WZ ' more lines to insert?
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...M - delete line(s)
|
|
'
|
|
do_delete_line
|
|
call #non_zero_args
|
|
:loop mov t1, cur_y
|
|
mov t2, screen_w
|
|
call #mul16x16
|
|
shl t2, #1
|
|
add t2, screen_ptr ' cursor row address
|
|
mov dst, t2
|
|
mov src, t2
|
|
add src, screen_w ' one row down
|
|
add src, screen_w
|
|
mov rows, screen_h ' screen rows
|
|
sub rows, cur_y ' - cursor row
|
|
sub rows, #1 WZ, WC ' - 1
|
|
if_be add lmm_pc, #4*(:fill - $ - 1) ' nothing left to move?
|
|
:rows mov cols, screen_w2 ' columns = screen width / 2
|
|
:cols rdlong data, src
|
|
add src, #4
|
|
wrlong data, dst
|
|
add dst, #4
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :cols)
|
|
sub rows, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :rows)
|
|
:fill mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
mov cols, screen_w2 ' columns = screen width / 2
|
|
:blank wrlong t1, dst
|
|
add dst, #4
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :blank) ' for all columns
|
|
sub csi_args, #1 WZ ' more lines to insert?
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...P - delete n characters at the cursor position
|
|
'
|
|
do_delete_char
|
|
call #non_zero_args
|
|
cmp new_x, screen_w WZ, WC
|
|
if_ae jmp #cmdloop ' can't delete beyond last column
|
|
:loop mov t1, cur_y
|
|
mov t2, screen_w
|
|
call #mul16x16
|
|
add t2, new_x
|
|
shl t2, #1
|
|
add t2, screen_ptr
|
|
mov dst, t2
|
|
mov src, t2
|
|
add src, #2
|
|
mov cols, screen_w
|
|
sub cols, new_x
|
|
sub cols, #1 WZ, WC
|
|
if_be add lmm_pc, #4*(:blank - $ - 1) ' new_x is beyond the last column
|
|
:insert rdword data, src
|
|
add src, #2
|
|
wrword data, dst
|
|
add dst, #2
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :insert)
|
|
:blank mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
wrword t1, dst ' clear the last character in the row
|
|
sub csi_args, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...X - blank characters
|
|
'
|
|
do_blank_chars
|
|
call #non_zero_args
|
|
mov dst, cur_ptr
|
|
mov cols, screen_w
|
|
sub cols, new_x WZ, WC
|
|
if_be jmp #cmdloop
|
|
mov t1, x00200020
|
|
or t1, color
|
|
rol t1, #16
|
|
or t1, color
|
|
:fill wrword t1, dst
|
|
add dst, #2
|
|
sub csi_args, #1 WZ
|
|
if_z jmp #cmdloop
|
|
sub cols, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :fill)
|
|
jmp #cmdloop
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...h - set flag(s)
|
|
'
|
|
do_flag_set
|
|
:loop
|
|
mov cmd, csi_args
|
|
cmp question_mark, #1 WZ ' <ESC>[? sequence?
|
|
if_z add lmm_pc, #4*(:ques - $ - 1)
|
|
cmp cmd, #3 WZ ' <ESC>[3h - display control characters
|
|
if_z or flags, #flag_ctrl
|
|
cmp cmd, #4 WZ ' <ESC>[4h - set insert mode
|
|
if_z or flags, #flag_decim
|
|
cmp cmd, #20 WZ ' <ESC>[20h - set auto CR mode
|
|
if_z or flags, #flag_deccr
|
|
add lmm_pc, #4*(:next - $ - 1)
|
|
:ques
|
|
cmp cmd, #1 WZ ' <ESC>[?1h - enable cursor keys
|
|
if_z or flags, #flag_decck
|
|
' cmp cmd, #2 WZ ' <ESC>[?2h - enable 132 column mode
|
|
' if_z or flags, #flag_decck
|
|
cmp cmd, #5 WZ ' <ESC>[?5h - inverse terminal on
|
|
if_z or inverse, #1
|
|
cmp cmd, #6 WZ ' <ESC>[?6h - enable origin mode
|
|
if_z or flags, #flag_decom
|
|
cmp cmd, #7 WZ ' <ESC>[?7h - enable auto wrap mode
|
|
if_z or flags, #flag_decawm
|
|
cmp cmd, #8 WZ ' <ESC>[?8h - enable auto repeat mode
|
|
if_z or flags, #flag_decarm
|
|
' cmp cmd, #9 WZ ' <ESC>[?9h - enable report mouse mode
|
|
' if_z or flags, #flag_decrm
|
|
cmp cmd, #25 WZ ' <ESC>[?25h - enable cursor
|
|
if_z or flags, #flag_deccm
|
|
:next
|
|
cmp csi_argf, #0 WZ ' no arguments specified?
|
|
if_z jmp #cmdloop
|
|
|
|
call #shift_csi_args
|
|
sub csi_argc, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #enable_cursor
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...l - reset flag(s)
|
|
'
|
|
do_flag_res
|
|
:loop
|
|
mov cmd, csi_args
|
|
cmp question_mark, #1 WZ ' <ESC>[? sequence?
|
|
if_z add lmm_pc, #4*(:ques - $ - 1)
|
|
cmp cmd, #3 WZ ' <ESC>[3l - don't display control characters
|
|
if_z andn flags, #flag_ctrl
|
|
cmp cmd, #4 WZ ' <ESC>[4l - reset insert mode
|
|
if_z andn flags, #flag_decim
|
|
cmp cmd, #20 WZ ' <ESC>[20l - reset auto CR mode
|
|
if_z andn flags, #flag_deccr
|
|
add lmm_pc, #4*(:next - $ - 1)
|
|
:ques
|
|
cmp cmd, #1 WZ ' <ESC>[?1l - disable cursor keys
|
|
if_z andn flags, #flag_decck
|
|
' cmp cmd, #2 WZ ' <ESC>[?2l - disable 132 column mode
|
|
' if_z andn flags, #flag_decck
|
|
cmp cmd, #5 WZ ' <ESC>[?5l - inverse terminal off
|
|
if_z andn inverse, #1
|
|
cmp cmd, #6 WZ ' <ESC>[?6l - disable origin mode
|
|
if_z andn flags, #flag_decom
|
|
cmp cmd, #7 WZ ' <ESC>[?7l - disable auto wrap mode
|
|
if_z andn flags, #flag_decawm
|
|
cmp cmd, #8 WZ ' <ESC>[?8l - disable auto repeat mode
|
|
if_z andn flags, #flag_decarm
|
|
' cmp cmd, #9 WZ ' <ESC>[?9l - disable report mouse mode
|
|
' if_z andn flags, #flag_decrm
|
|
cmp cmd, #25 WZ ' <ESC>[?25l - disable cursor
|
|
if_z andn flags, #flag_deccm
|
|
:next
|
|
cmp csi_argf, #0 WZ ' no arguments specified?
|
|
if_z jmp #cmdloop
|
|
|
|
call #shift_csi_args
|
|
sub csi_argc, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :loop)
|
|
jmp #enable_cursor
|
|
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...m - set mode attributes
|
|
'
|
|
do_mode_attributes
|
|
:get_arg mov cmd, csi_args ' get next argument
|
|
cmp cmd, #0 WZ ' 0 = reset all attributes
|
|
if_z mov attr, #0
|
|
if_z mov bgcol, #%0000
|
|
if_z mov fgcol, #%0111
|
|
cmp cmd, #1 WZ ' 1 = highlight on
|
|
if_z or attr, #attr_highlite
|
|
cmp cmd, #2 WZ ' 2 = highlight off
|
|
if_z andn attr, #attr_highlite
|
|
cmp cmd, #4 WZ ' 4 = underline on
|
|
if_z or attr, #attr_underline
|
|
cmp cmd, #5 WZ ' 5 = blinking on
|
|
if_z or attr, #attr_blinking
|
|
cmp cmd, #7 WZ ' 7 = inverse on
|
|
if_z or attr, #attr_inverse
|
|
cmp cmd, #10 WZ ' 10 = primary font, no ctrl, no meta
|
|
if_z andn flags, #flag_ctrl
|
|
if_z andn flags, #flag_meta
|
|
cmp cmd, #11 WZ ' 11 = alternate font, ctrl chars, low half, meta off
|
|
if_z or flags, #flag_ctrl
|
|
if_z andn flags, #flag_meta
|
|
cmp cmd, #12 WZ ' 12 = alternate font, ctrl chars, low half, meta on
|
|
if_z or flags, #flag_ctrl
|
|
if_z or flags, #flag_meta
|
|
cmp cmd, #21 WZ ' 21 = highlight on
|
|
if_z or attr, #attr_highlite
|
|
cmp cmd, #22 WZ ' 22 = highlight on
|
|
if_z or attr, #attr_highlite
|
|
cmp cmd, #24 WZ ' 24 = underline off
|
|
if_z andn attr, #attr_underline
|
|
cmp cmd, #25 WZ ' 25 = blinking off
|
|
if_z andn attr, #attr_blinking
|
|
cmp cmd, #27 WZ ' 27 = inverse off
|
|
if_z andn attr, #attr_inverse
|
|
cmp cmd, #30 WZ ' 30 = foreground color 0
|
|
if_z mov fgcol, #%0000
|
|
cmp cmd, #31 WZ ' 31 = foreground color 1
|
|
if_z mov fgcol, #%0001
|
|
cmp cmd, #32 WZ ' 32 = foreground color 2
|
|
if_z mov fgcol, #%0010
|
|
cmp cmd, #33 WZ ' 33 = foreground color 3
|
|
if_z mov fgcol, #%0011
|
|
cmp cmd, #34 WZ ' 34 = foreground color 4
|
|
if_z mov fgcol, #%0100
|
|
cmp cmd, #35 WZ ' 35 = foreground color 5
|
|
if_z mov fgcol, #%0101
|
|
cmp cmd, #36 WZ ' 36 = foreground color 6
|
|
if_z mov fgcol, #%0110
|
|
cmp cmd, #37 WZ ' 37 = foreground color 7
|
|
if_z mov fgcol, #%0111
|
|
cmp cmd, #38 WZ ' 38 = default color and underline on
|
|
if_z mov fgcol, #%0111
|
|
if_z or attr, #attr_underline
|
|
cmp cmd, #39 WZ ' 39 = default color and underline off
|
|
if_z mov fgcol, #%0111
|
|
if_z andn attr, #attr_underline
|
|
cmp cmd, #40 WZ ' 40 = default background
|
|
if_z mov bgcol, #%0000 ' black
|
|
cmp cmd, #41 WZ ' 41 = background color 1
|
|
if_z mov bgcol, #%0001
|
|
cmp cmd, #42 WZ ' 42 = background color 2
|
|
if_z mov bgcol, #%0010
|
|
cmp cmd, #43 WZ ' 43 = background color 3
|
|
if_z mov bgcol, #%0011
|
|
cmp cmd, #44 WZ ' 44 = background color 4
|
|
if_z mov bgcol, #%0100
|
|
cmp cmd, #45 WZ ' 45 = background color 5
|
|
if_z mov bgcol, #%0101
|
|
cmp cmd, #46 WZ ' 46 = background color 6
|
|
if_z mov bgcol, #%0110
|
|
cmp cmd, #47 WZ ' 47 = background color 7
|
|
if_z mov bgcol, #%0111
|
|
cmp cmd, #49 WZ ' 49 = default background
|
|
if_z mov bgcol, #%0000 ' black
|
|
|
|
cmp csi_argf, #0 WZ ' no arguments specified?
|
|
if_z jmp #cmdloop
|
|
|
|
call #shift_csi_args
|
|
sub csi_argc, #1 WZ
|
|
if_nz sub lmm_pc, #4*($ + 1 - :get_arg)
|
|
jmp #set_color
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[...r - set scroll range
|
|
'
|
|
do_scroll_range
|
|
cmp csi_argc, #2 WZ, WC ' 2 arguments specified?
|
|
if_ae add lmm_pc, #4*(:set_range - $ - 1)
|
|
mov scroll_top, #1
|
|
mov scroll_bot, screen_h
|
|
add lmm_pc, #4*(:bottom_ok - $ - 1)
|
|
:set_range
|
|
mov scroll_top, csi_args
|
|
mov scroll_bot, csi_args + 1
|
|
cmp scroll_top, scroll_bot WZ, WC ' bottom => top?
|
|
if_be add lmm_pc, #4*(:order_ok - $ - 1)
|
|
mov scroll_top, #1
|
|
mov scroll_bot, screen_h
|
|
add lmm_pc, #4*(:bottom_ok - $ - 1)
|
|
:order_ok
|
|
cmp scroll_bot, screen_h WZ, WC ' bottom > screen height?
|
|
if_be add lmm_pc, #4*(:bottom_ok - $ - 1)
|
|
mov scroll_top, #1
|
|
mov scroll_bot, screen_h
|
|
:bottom_ok
|
|
sub scroll_top, #1
|
|
mov cur_x, #0
|
|
mov cur_y, #0
|
|
jmp #goto_xay
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[?...s - save cursor position and attributes
|
|
'
|
|
do_save_cursor
|
|
mov cur_x_save, cur_x
|
|
mov new_x_save, new_x
|
|
mov cur_y_save, cur_y
|
|
mov attr_save, attr
|
|
jmp #cmdloop
|
|
|
|
|
|
'********************************************************************************************
|
|
' <ESC>[?...u - restore cursor position and attributes
|
|
'
|
|
do_restore_cursor
|
|
mov cur_x, cur_x_save
|
|
mov new_x, new_x_save
|
|
mov cur_y, cur_y_save
|
|
mov attr, attr_save
|
|
jmp #cmdloop
|
|
|