Информация
Получен из анализа прошивки системного монитора для Агат-7.
Использует синтаксис ассемблера xa.
Побайтово совместим с штатным системным монитором.

Листинг
; Byte compatible system monitor for Agat-7
; For use with XA assembler
; key and control char codes
ENTER_KEY = $8D
SPACE_KEY = $A0
UP_KEY = $99
DOWN_KEY = $9A
LEFT_KEY = $88
RIGHT_KEY = $95
ESC_KEY = $9B
CTRL_G_KEY = $87
CTRL_L_KEY = $8C
CTRL_J_KEY = $8A
RIGHT_6_KEY = $9C
RIGHT_7_KEY = $9D
RIGHT_8_KEY = $9E
CTRL_C_KEY = $83
CTRL_X_KEY = $98
; some constants
num_cmds = $17
num_ctl = 10
line_warn_start= $F8
title_num_bytes= $14
num_vars_3Fx = 5
; parameters
beep_pre_delay = $40
beep_interval = $0C
beep_duration = $C0
tape_delay_1 = $32
tape_delay_0 = $2C
tape_delay_preamble= $4B
tape_read_delay= $3A
tape_preamble_duration= $40
lines_to_disass= $1C
initial_video_page= $0F
flash_cursor_attr= $0F
video_mode_text= $2
cold_boot_const= $A5
cold_boot_code = cold_boot_const ^ (dialog_monitor >> 8)
inverse_attr = $87
normal_attr = $AF
attr_title_green= $2A
attr_title_red = $29
attr_title_white= $2F
; char codes
CHAR_SLASH = $DC
CHAR_MINUS = $AD
CHAR_0 = $B0
CHAR_9 = $B9
CHAR_A = $C1
CHAR_EOL = $8D
CHAR_SPACE = $A0
CHAR_EQ = $BD
CHAR_COLON = $BA
CHAR_ASTERISK = $AA
CHAR_COMMA = $AC
CHAR_HASH = $A3
CHAR_LPAR = $A8
CHAR_RPAR = $A9
CHAR_CUR = $A4
CHAR_X = $D8
CHAR_Y = $D9
CHAR_QUEST = $BF
CHAR_E = $C5
CHAR_R = $D2
CHAR_S = $D3
CHAR_P = $D0
CHAR_CYR_A = $E1
CHAR_CYR_G = $E7
CHAR_CYR_T = $F4
; zero page variables
autostart_addr = $00
video_page_h = $19
video_page_next_h = $1E
wnd_left_2 = $20
wnd_right_2 = $21
wnd_top = $22
wnd_bottom = $23
cur_pos_x = $24
cur_pos_y = $25
cur_scr_addr = $28
tmp_addr = $2A
tmp_2c = $2C
tmp_2d = $2D
tmp_2e = $2E
tmp_2f = $2F
current_op = $31
cur_attr = $32
prompt_char = $33
prompt_index = $34
tmp_35 = $35
store_y = $35
print_char_ptr = $36
input_char_ptr = $38
user_pc = $3A
src_user_ptr = $3C
dst_user_ptr = $3E
current_ptr = $40
dest_user_ptr = $42
tmp_44 = $44
user_a = $45
user_x = $46
user_y = $47
user_p = $48
user_s = $49
rnd_counter_l = $4E
rnd_counter_h = $4F
other_mode_page = $D0
; input buffer
input_buf = $200
; 3Fx variables
brk_addr = $3F0
rst_proc = $3F2
cold_boot = $3F4
ctrl_Y_addr = $3F8
nmi_proc = $3FB
irq_addr = $3FE
; other variables
some_autostart_addr = $7F8
; video page address
title_video_addr = $7810
; i/o addresses
input_kbd = $C000
reset_kbd = $C010
tape_out = $C020
beeper_out = $C030
tape_in = $C060
pdl_input_port = $C064
pdl_reset_port = $C070
mem_selector_c0f0 = $C0F0
mem_selector_c0f1 = $C0F1
video_selector = $C700
; basic vectors
basic_init = $E000
basic_start = $E003
* = $F800
translate_codes: ; unused subroutine
PHA
LSR
LSR
LSR
LSR
TAY
PLA
EOR tbl1,Y
CMP #$A0
BCS tbl_skip
CMP #$90
BCC tbl_skip
TAY
LDA tbl2-$90, Y
tbl_skip: LDY cur_pos_x
RTS
; ---------------------------------------------------------------------------
tbl1: .db $80, $B0, $D0, $D0, $D0, $E0, $B0, $B0
tbl2: .db $88, $A0, $8D, $93, $94, $98, $96, $97, $95, $99
.db $9A, $9B, $9C, $9D, $9E, $9B
; A = page, X = mode (2 = text)
set_video_mode:
STX tmp_2c
LDY video_page_variable,X
ASL
ASL
PHA
ASL
CMP #$C0
BCC wrap_addr
SBC #$3F
wrap_addr: STA 0,Y
ADC video_page_size_h,X ; page size for different video modes
EOR video_page_next_h ; h byte of next page address
AND #$F8
EOR video_page_next_h ; h byte of next page address
STA video_page_next_h ; h byte of next page address
PLA
ADC tmp_2c
TAX
STA video_selector,X
RTS
video_page_size_h:.db $08, $20, $08, $20 ; page size for different video modes
video_page_variable:.db other_mode_page, other_mode_page, video_page_h, other_mode_page
; A = video page address high byte
set_mem_bank:
AND #7
TAY
LDA mem_banks,Y
TAY
STA mem_selector_c0f0,Y
RTS
mem_banks: .db 0, 1, 10, 11, 6, 7, 2, 3
; calculate params for current instruction
; returns A = command name index
calc_listing_params:
LDX user_pc
LDY user_pc+1
JSR print_eol_xy_minus
JSR print_2_spaces ; => X = 0
LDA (user_pc,X) ; current opcode
TAY ; Y = original opcode
LSR
BCC lower_bit_is_zero
ROR
BCS opcode_is_bad ; two lower bits are 11
CMP #$A2 ; 89h, exceptional opcode
BEQ opcode_is_bad ; replace opcode with 80h for bad commands
AND #$87 ; lower bits are 01, drop command bits, process addressing
lower_bit_is_zero:
LSR
TAX
LDA opcode_info,X ; index in addr_and_len table packed by 4 bits
BCS use_lower_flags ; if lower bits are 10 or 101, use lower 4 bits of flags (ZP/ABS) adressing
LSR
LSR
LSR
LSR ; lower bits are 00 or 001, use higher 4 bits of flags
use_lower_flags:
AND #$0F ; check if index is zero (bad opcode)
BNE opcode_not_bad
opcode_is_bad:
LDY #$80 ; replace opcode with 80h for bad commands
LDA #0 ; flags = 0 for bad commands
opcode_not_bad:
TAX
LDA opcode_addr_and_len,X
STA tmp_2e
AND #3 ; max cmd size is 3
STA tmp_2f ; current bit for tape, cmd size-1 for disass
TYA
AND #$8F
TAX
TYA
LDY #3 ; number of max shift iterations
CPX #$8A
BEQ skip_shift
next_shift: LSR
BCC skip_shift
LSR
retry_shift: LSR
ORA #$20
DEY
BNE retry_shift
INY
skip_shift: DEY
BNE next_shift
RTS
; disassemble single line
print_disass_line:
JSR calc_listing_params ; calculate params for current instruction
; returns A = command name index
PHA
cmd_byte_loop: LDA (user_pc),Y
JSR print_hex_byte
LDX #1 ; spaces between command bytes
cmd_space_loop: JSR print_x_spaces
CPY tmp_2f ; current bit for tape, cmd size-1 for disass
INY
BCC cmd_byte_loop
LDX #3 ; print 3 spaces instead of byte and space, use 3-char op names
CPY #4 ; total number of chars = 3*4
BCC cmd_space_loop
PLA
TAY
LDA packed_name_l,Y ; packed by 5 bits per char
STA tmp_2c
LDA packed_name_h,Y ; packed by 5 bits per char
STA tmp_2d
cmd_name_loop: LDA #0
LDY #5 ; number of bits for single char
shift_loop: ASL tmp_2d
ROL tmp_2c
ROL ; insert bits from lower byte
DEY
BNE shift_loop
ADC #CHAR_QUEST ; ?
JSR print_char
DEX
BNE cmd_name_loop
JSR print_2_spaces ; => X = 0
LDY tmp_2f ; current bit for tape, cmd size-1 for disass
LDX #6
operand_loop: CPX #3
BEQ ending_chars
operand_char_loop:
ASL tmp_2e
BCC no_second_char
LDA first_op_chars-1, X
JSR print_char
LDA second_op_chars-1, X
BEQ no_second_char
JSR print_char
no_second_char: DEX
BNE operand_loop
RTS
not_rel_addr: DEY
BMI operand_char_loop ; need ending chars
JSR print_hex_byte
ending_chars: LDA tmp_2e
CMP #$E8
LDA (user_pc),Y
BCC not_rel_addr
JSR calc_rel_addr ; A = offset => X = offset, A = low addr, Y = high addr
TAX ; increment calculated addr
INX
BNE print_xy ; no page cross
INY
print_xy: TYA
JSR print_hex_byte
TXA
JMP print_hex_byte
next_disass_addr:
SEC
LDA tmp_2f ; cmd size-1 for disass
; A = offset => X = offset, A = low addr, Y = high addr
calc_rel_addr: LDY user_pc+1
TAX
BPL forward_offset
DEY
forward_offset: ADC user_pc
BCC no_page_cross
INY
no_page_cross: RTS
; ---------------------------------------------------------------------------
opcode_info: .db $40, $02, $45, $03, $D0, $08, $40, $09, $30, $22, $45, $33, $D0, $08, $40, $09 ; index in addr_and_len table packed by 4 bits
.db $40, $02, $45, $33, $D0, $08, $40, $09, $40, $02, $45, $B3, $D0, $08, $40, $09
.db $00, $22, $44, $33, $D0, $8C, $44, $00, $11, $22, $44, $33, $D0, $8C, $44, $9A
.db $10, $22, $44, $33, $D0, $08, $40, $09, $10, $22, $44, $33, $D0, $08, $40, $09
.db $62, $13, $78, $A9
opcode_addr_and_len:.db $00, $21, $81, $82, $00, $00, $59, $4D, $91, $92, $86, $4A, $85, $9D
first_op_chars: .db CHAR_COMMA, CHAR_RPAR, CHAR_COMMA, CHAR_HASH, CHAR_LPAR, CHAR_CUR
second_op_chars:.db CHAR_Y, 0, CHAR_X, CHAR_CUR, CHAR_CUR, 0
packed_name_l: .db $1C, $8A, $1C, $23, $5D, $8B, $1B, $A1, $9D, $8A, $1D, $23, $9D, $8B, $1D, $A1 ; packed by 5 bits per char relatively to '?'
.db $00, $29, $19, $AE, $69, $A8, $19, $23, $24, $53, $1B, $23, $24, $53, $19, $A1
.db $00, $1A, $5B, $5B, $A5, $69, $24, $24, $AE, $AE, $A8, $AD, $29, $00, $7C, $00
.db $15, $9C, $6D, $9C, $A5, $69, $29, $53, $84, $13, $34, $11, $A5, $69, $23, $A0
packed_name_h: .db $D8, $62, $5A, $48, $26, $62, $94, $88, $54, $44, $C8, $54, $68, $44, $E8, $94
.db $00, $B4, $08, $84, $74, $B4, $28, $6E, $74, $F4, $CC, $4A, $72, $F2, $A4, $8A
.db $00, $AA, $A2, $A2, $74, $74, $74, $72, $44, $68, $B2, $32, $B2, $00, $22, $00
.db $1A, $1A, $26, $26, $72, $72, $88, $C8, $C4, $CA, $26, $48, $44, $44, $A2, $C8
start_irq: STA user_a
PLA
PHA
ASL
ASL
ASL
BMI is_brk
JMP (irq_addr)
is_brk: PLP
JSR store_regs
PLA
STA user_pc
PLA
STA user_pc+1
JMP (brk_addr)
brk_proc: JSR calc_listing_params ; calculate params for current instruction
; returns A = command name index
JSR print_regs
JMP dialog_beep
start_rst: CLD
JSR norm_cmd
JSR reset_scr_wnd
JSR default_output
JSR default_input
BIT reset_kbd
CLD
JSR do_beep
LDA rst_proc+1
EOR #cold_boot_const
CMP cold_boot
BNE do_cold_boot
JSR select_text_mode
LDA rst_proc
CMP #<dialog_monitor
BNE do_soft_boot
LDA #>dialog_monitor
CMP rst_proc+1
BNE do_soft_boot
init_rst_proc: LDY #<dialog_monitor
STY rst_proc
JMP dialog_monitor
do_soft_boot: JMP (rst_proc)
do_cold_boot: BIT mem_selector_c0f1
LDY #0
STY video_page_next_h ; h byte of next page address
LDA #initial_video_page
LDX #video_mode_text ; text mode 32x32
JSR set_video_mode ; A = page, X = mode (2 = text)
JSR clear_scr
LDY #title_num_bytes
title_loop: LDA title_text-1, Y
STA title_video_addr-1, Y
DEY
BNE title_loop
BIT mem_selector_c0f0
LDX #num_vars_3Fx
init_vars_loop: LDA init_vars-1, X
STA brk_addr-1, X
DEX
BNE init_vars_loop ; on exit loop X = 0
LDA #$C7 ; last slot + 1
STX autostart_addr
STA autostart_addr+1
autostart_loop: LDY #7 ; autostart signature size
DEC autostart_addr+1
LDA autostart_addr+1
CMP #$C0 ; first slot + 1
BEQ init_rst_proc
STA some_autostart_addr
sig_check_loop: LDA (autostart_addr), Y
CMP autostart_sig-1, Y
BNE autostart_loop ; autostart signature size
DEY
DEY
BPL sig_check_loop
JMP (autostart_addr)
print_regs_eol: JSR print_eol
print_regs: LDA #user_a
STA current_ptr ; set pointer to register area to enter values
LDA #0
STA current_ptr+1
LDX #<-5 ; number of registers to print
print_reg: LDA #CHAR_SPACE
JSR print_char
LDA reg_names-$FB, X
JSR print_char
LDA #CHAR_EQ ; =
JSR print_char
LDA user_a+5, X
JSR print_hex_byte
INX
BMI print_reg
RTS
init_vars: .dw brk_proc
.dw dialog_monitor
.db cold_boot_code
autostart_sig: .db $20, $FF, $00, $FF, $03, $FF, $3C
title_text: .db CHAR_ASTERISK ; *
.db attr_title_green
.db CHAR_ASTERISK ; *
.db attr_title_green
.db CHAR_SPACE
.db attr_title_white
.db CHAR_CYR_A ; А
.db attr_title_red
.db CHAR_CYR_G ; Г
.db attr_title_red
.db CHAR_CYR_A ; А
.db attr_title_red
.db CHAR_CYR_T ; Т
.db attr_title_red
.db CHAR_SPACE
.db attr_title_white
.db CHAR_ASTERISK ; *
.db attr_title_green
.db CHAR_ASTERISK ; *
.db attr_title_green
reg_names: .db CHAR_A, CHAR_X, CHAR_Y, CHAR_P, CHAR_S
pdl_input_proc: ; unused
LDA pdl_reset_port
LDY #0
NOP
NOP
pdl_input_loop: LDA pdl_input_port,X
BPL pdl_input_end
NOP
NOP
NOP
INY
BNE pdl_input_loop
DEY
pdl_input_end: RTS
.db $10
.db $08
select_text_mode:
LDA video_page_h
LSR
BCC low_mode
ADC #$1F ; add 20h to mode
low_mode: ADC #video_mode_text ; text mode 32x32
TAY
STA video_selector,Y
RTS
reset_scr_wnd: LDA #0
STA user_p
STA wnd_top
LDA #0
STA wnd_left_2
LDA #64
STA wnd_right_2
LDA #32
STA wnd_bottom
LDA #31
STA cur_pos_y
JMP calc_cur_pos_addr
is_esc_ctl: JSR check_print_space
handle_esc_chars:
JSR input_char
CMP #RIGHT_KEY ; RIGHT
BEQ is_esc_ctl
CMP #LEFT_KEY ; LEFT
BEQ is_esc_ctl
leave_edit_mode:
JSR check_print_space
handle_edit_mode:
JSR input_char
CMP #ESC_KEY ; ESC
BEQ handle_esc_chars
CMP #UP_KEY ; UP
BEQ leave_edit_mode
CMP #DOWN_KEY ; DOWN
BEQ leave_edit_mode
is_invisible_char:
RTS
check_print_space:
CMP #SPACE_KEY ; SPACE
BCS is_invisible_char
JMP print_char
; A = cursor Y, not uses window
calc_scr_addr: STA cur_scr_addr+1
LDA #0
STA cur_scr_addr
LSR cur_scr_addr+1
ROR cur_scr_addr
LSR cur_scr_addr+1
ROR cur_scr_addr
LDA video_page_h
AND #$F8
ADC cur_scr_addr+1
STA cur_scr_addr+1
RTS
some_delay: SEC ; A = delay value
outer_loop: PHA
inner_loop: SBC #1
BNE inner_loop
PLA
SBC #1
BNE outer_loop
RTS
inc_user_addr: INC dest_user_ptr
BNE inc_user_ptr
INC dest_user_ptr+1
inc_user_ptr: LDA src_user_ptr
CMP dst_user_ptr
LDA src_user_ptr+1
SBC dst_user_ptr+1
INC src_user_ptr
BNE end_user_ptr
INC src_user_ptr+1
end_user_ptr: RTS
ctl_char_table: .db ENTER_KEY, CTRL_J_KEY, LEFT_KEY, RIGHT_KEY, UP_KEY
.db DOWN_KEY, CTRL_L_KEY, RIGHT_7_KEY, RIGHT_8_KEY, CTRL_G_KEY
.db RIGHT_6_KEY
ctl_addr_l: .db <eol_ctl_proc
.db <eol_ctl_proc
.db <left_key_proc
.db <right_key_proc
.db <up_key_proc
.db <down_key_proc
.db <clear_scr
.db <clr_eol_proc
.db <clr_eos_proc
.db <beep_proc
.db <caps_lock_proc
process_char_output:
CMP #CHAR_EOL
BNE not_eol
LDY input_kbd
BPL not_eol ; nothing pressed
BIT reset_kbd
CPY #CHAR_SPACE ; space char pressed, stop output
BNE not_eol
scroll_lock_loop:
LDY input_kbd
BPL scroll_lock_loop
CPY #CTRL_C_KEY
BEQ not_eol ; do not clear Ctrl+C
BIT reset_kbd
not_eol: CMP #SPACE_KEY
BCS char_is_visible
TAY
BPL char_is_visible
LDY #num_ctl
ctl_char_loop: CMP ctl_char_table,Y
BEQ ctl_char_found
DEY
BPL ctl_char_loop
RTS
ctl_char_found: LDA ctl_addr_l,Y
STA tmp_addr
LDA #>left_key_proc
STA tmp_addr+1
JMP (tmp_addr)
char_is_visible:
LDY cur_pos_x
STA (cur_scr_addr),Y
INY
LDA cur_attr
STA (cur_scr_addr),Y
right_key_proc: INC cur_pos_x
INC cur_pos_x
LDA cur_pos_x
CMP wnd_right_2
BCS eol_ctl_proc
not_jump_right: RTS
left_key_proc: DEC cur_pos_x
DEC cur_pos_x
BPL not_jump_right
LDA wnd_right_2
STA cur_pos_x
DEC cur_pos_x
DEC cur_pos_x
up_key_proc: LDA wnd_top
CMP cur_pos_y
BCS not_on_top
DEC cur_pos_y
calc_cur_pos_addr:
LDA cur_pos_y
; A = cursor Y, uses window
upd_scr_addr: JSR calc_scr_addr ; A = cursor Y, not uses window
LDA cur_scr_addr
ADC wnd_left_2
STA cur_scr_addr
not_on_top: RTS
clear_scr: LDA wnd_top
STA cur_pos_y
LDY #0
STY cur_pos_x
BEQ do_clear
clr_eos_proc: LDY cur_pos_x
LDA cur_pos_y
do_clear: PHA
JSR upd_scr_addr ; A = cursor Y, uses window
JSR clear_scr_block
LDY #0
PLA
ADC #0
CMP wnd_bottom
BCC do_clear
BCS calc_cur_pos_addr
eol_ctl_proc: LDA #0
STA cur_pos_x
down_key_proc: INC cur_pos_y
LDA cur_pos_y
CMP wnd_bottom
BCC upd_scr_addr ; A = cursor Y, uses window
DEC cur_pos_y
LDA wnd_top
PHA
JSR upd_scr_addr ; A = cursor Y, uses window
retry_scroll: LDA cur_scr_addr
STA tmp_addr
LDA cur_scr_addr+1
STA tmp_addr+1
LDY wnd_right_2
DEY
PLA
ADC #1
CMP wnd_bottom
BCS clear_last_line
PHA
JSR upd_scr_addr ; A = cursor Y, uses window
scroll_loop: LDA (cur_scr_addr),Y
STA (tmp_addr),Y
DEY
BPL scroll_loop
BMI retry_scroll
clear_last_line:
LDY #0
JSR clear_scr_block
JMP calc_cur_pos_addr
clr_eol_proc:
LDY cur_pos_x
clear_scr_block:
LDA #CHAR_SPACE
STA (cur_scr_addr),Y
INY
LDA cur_attr
STA (cur_scr_addr),Y
INY
CPY wnd_right_2
BCC clear_scr_block
RTS
caps_lock_proc: LDA cur_attr
EOR #$80 ; toggle top bit of attribs
STA cur_attr
RTS
beep_proc: LDA #beep_pre_delay ; delay before beep
JSR some_delay
LDY #beep_duration ; duration of beep signal
beep_loop: LDA #beep_interval ; delay between signal change
JSR some_delay
LDA beeper_out
DEY
BNE beep_loop
RTS
; X = preamble duration
write_preamble:
LDY #tape_delay_preamble
JSR tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0
BNE write_preamble ; X = preamble duration
ADC #<-2
BCS write_preamble ; X = preamble duration
LDY #33
; Y=delay, CF=bit, X = X - 2
tape_output_bit:
JSR tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0
INY
INY
tape_bit_out: DEY ; Y=retries, CF=output => X = X - 1, Y = delay0
BNE tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0
BCC tape_output_0
LDY #tape_delay_1 ; delay for 1
secod_delay_loop:
DEY
BNE secod_delay_loop
tape_output_0: LDY tape_out
LDY #tape_delay_0 ; delay for 0
DEX
RTS
tape_read_byte: LDX #8 ; number of bits to read
tape_pulse_loop: PHA
JSR input_tape_pulses
PLA
ROL
LDY #tape_read_delay
DEX
BNE tape_pulse_loop
RTS
input_tape_pulses:
JSR input_tape_pulse ; Y = pulses count; => ZF = value
; Y = pulses count; => ZF = value
input_tape_pulse:
DEY
LDA tape_in
EOR tmp_2f ; current bit for tape, cmd size-1 for disass
BPL input_tape_pulse ; Y = pulses count; => ZF = value
EOR tmp_2f ; current bit for tape, cmd size-1 for disass
STA tmp_2f ; current bit for tape, cmd size-1 for disass
CPY #$80
RTS
input_char: JMP (input_char_ptr)
input_char_proc:
LDA video_page_h
JSR set_mem_bank ; A = video page address high byte
LDY cur_pos_x
LDA (cur_scr_addr),Y
STA tmp_35 ; old Y for print_char, current char for input
INY
LDA (cur_scr_addr),Y
PHA
LDA #flash_cursor_attr
STA (cur_scr_addr),Y
PLA
input_loop: INC rnd_counter_l
BNE no_inc_rnd_h
INC rnd_counter_h
no_inc_rnd_h: BIT input_kbd
BPL input_loop
STA (cur_scr_addr),Y
LDA video_page_next_h ; h byte of next page address
JSR set_mem_bank ; A = video page address high byte
LDA input_kbd
ORA #$80
BIT reset_kbd
LDY cur_pos_x
RTS
print_current_char:
JSR print_char
CMP #LEFT_KEY ; LEFT
BEQ do_left_key
CMP #CTRL_X_KEY ; CTRL+X
BEQ on_overflow
CPX #line_warn_start ; number of chars to warn
BCC not_overflow
JSR do_beep
not_overflow: INX
BNE no_input_overflow
on_overflow: LDA #CHAR_SLASH ; /
JSR print_char
do_prompt: JSR print_eol
LDA prompt_char
JSR print_char
LDX #1
do_left_key: TXA
BEQ do_prompt ; is buffer empty?
DEX ; decrease buffer index
no_input_overflow:
JSR handle_edit_mode
CMP #RIGHT_KEY ; RIGHT
BNE not_right ; store char from screen
LDA tmp_35 ; old Y for print_char, current char for input
not_right: STA input_buf,X ; store char from screen
CMP #ENTER_KEY ; ENTER
BNE print_current_char
LDA #RIGHT_7_KEY
JSR print_char
print_eol: LDA #ENTER_KEY
BNE print_char
print_eol_cur_addr_minus:
LDY src_user_ptr+1
LDX src_user_ptr
print_eol_xy_minus:
JSR print_eol
JSR print_xy
LDY #0
LDA #CHAR_MINUS ; -
JMP print_char
dump_next_bytes:
LDA src_user_ptr
ORA #7
STA dst_user_ptr
LDA src_user_ptr+1
STA dst_user_ptr+1
mem_print_loop: LDA src_user_ptr
AND #7
BNE dump_not_eol
dump_addr: JSR print_eol_cur_addr_minus
dump_not_eol: LDA #SPACE_KEY
JSR print_char
LDA (src_user_ptr),Y
JSR print_hex_byte
JSR inc_user_ptr
BCC mem_print_loop
RTS
do_add_sub: LSR
BCC dump_addr
LSR
LSR
LDA dst_user_ptr
BCC do_subtract
EOR #$FF
do_subtract: ADC src_user_ptr
PHA
LDA #CHAR_EQ ; =
JSR print_char
PLA
print_hex_byte:
PHA
LSR
LSR
LSR
LSR
JSR print_hex_digit
PLA
AND #$0F ; lower 4 bits
print_hex_digit:
ORA #CHAR_0 ; 0
CMP #CHAR_9+1
BCC print_char
ADC #CHAR_A - CHAR_0 - $0A - 1
print_char: JMP (print_char_ptr)
print_char_proc:
STY store_y ; old Y for print_char
PHA
LDA video_page_h
JSR set_mem_bank ; A = video page address high byte
PLA
PHA
CMP #SPACE_KEY
BCC skip_caps
BIT cur_attr
BMI skip_caps
AND #$7F ; clear higher bit
skip_caps: JSR process_char_output
LDA video_page_next_h ; h byte of next page address
JSR set_mem_bank ; A = video page address high byte
PLA
LDY store_y ; old Y for print_char
RTS
; X = 1 to set new address
set_user_pc: TXA
BEQ nothing_to_copy
ptr_copy_loop: LDA src_user_ptr,X
STA user_pc,X
DEX
BPL ptr_copy_loop
nothing_to_copy: RTS
process_empty_cmd:
DEC prompt_index
BEQ dump_next_bytes
space_cmd: DEX
BNE not_empty_line
CMP #CHAR_COLON ; :
BNE do_add_sub
STA current_op
LDA dst_user_ptr
STA (current_ptr),Y
INC current_ptr
BNE no_current_ptr_h_inc
INC current_ptr+1
no_current_ptr_h_inc:
RTS
set_current_op:
LDY prompt_index
LDA input_buf-1, Y
not_empty_line: STA current_op
RTS
less_op: LDX #1
copy_loop: LDA dst_user_ptr,X
STA dest_user_ptr,X
STA tmp_44,X
DEX
BPL copy_loop
RTS
move_cmd: LDA (src_user_ptr),Y
STA (dest_user_ptr),Y
JSR inc_user_addr
BCC move_cmd
RTS
verify_cmd: LDA (src_user_ptr),Y
CMP (dest_user_ptr),Y
BEQ verify_cmd_ok
JSR print_eol_cur_addr_minus
LDA (src_user_ptr),Y
JSR print_hex_byte
LDA #SPACE_KEY
JSR print_char
LDA #CHAR_LPAR ; (
JSR print_char
LDA (dest_user_ptr),Y
JSR print_hex_byte
LDA #CHAR_RPAR ; )
JSR print_char
verify_cmd_ok: JSR inc_user_addr
BCC verify_cmd
RTS
list_cmd: JSR set_user_pc ; X = 1 to set new address
LDA #lines_to_disass ; lines in single disassembly listing
list_cmd_loop: PHA
JSR print_disass_line
JSR next_disass_addr
STA user_pc
STY user_pc+1
PLA
SEC
SBC #1
BNE list_cmd_loop
RTS
inverse_cmd: LDY #inverse_attr
BNE cont_attr
norm_cmd: LDY #normal_attr
cont_attr: STY cur_attr
RTS
default_input: LDA #0
STA dst_user_ptr
cmd_ctrl_I: LDX #input_char_ptr ; redirect input to slot
LDY #<input_char_proc
BNE set_io_proc
default_output: LDA #0
STA dst_user_ptr
cmd_ctrl_O: LDX #print_char_ptr ; redirect output to slot
LDY #<print_char_proc
set_io_proc: LDA dst_user_ptr
AND #$0F
BEQ reset_io_proc
ORA #$C0
LDY #0
BEQ store_io_proc
reset_io_proc: LDA #>print_char_proc
store_io_proc: STY 0,X
STA 1,X
RTS
init_basic: JMP basic_init
call_basic: JMP basic_start
call_user_proc: JSR set_user_pc ; X = 1 to set new address
JSR load_regs
JMP (user_pc)
cmd_regs: JMP print_regs_eol
jump_ctrl_y: JMP ctrl_Y_addr
cmd_text_page: LDA dst_user_ptr
AND #$1F ; 32 text pages allowed?
LDX #video_mode_text ; text mode 32x32
JMP set_video_mode ; A = page, X = mode (2 = text)
cmd_set_color: LDA dst_user_ptr
EOR cur_attr
AND #7
EOR cur_attr
STA cur_attr
RTS
cmd_write: LDA #tape_preamble_duration
JSR write_preamble ; X = preamble duration
LDY #39
tape_write_loop:
LDX #0
EOR (src_user_ptr,X)
PHA
LDA (src_user_ptr,X)
JSR tape_output_byte ; A=byte, Y=initial delay
JSR inc_user_ptr
LDY #29
PLA
BCC tape_write_loop
LDY #34
JSR tape_output_byte ; write checksum
BEQ do_beep
tape_output_byte: ; A=byte, Y=initial delay
LDX #2*8 ; double byte size
tape_output_loop:
ASL
JSR tape_output_bit ; Y=delay, CF=bit, X = X - 2
BNE tape_output_loop
RTS
no_cmd: JSR process_empty_cmd
PLA
PLA
BNE dialog_monitor
cmd_read: JSR input_tape_pulses
LDA #22
JSR write_preamble ; X = preamble duration
STA tmp_2e
JSR input_tape_pulses
skip_preamble: LDY #36
JSR input_tape_pulse ; Y = pulses count; => ZF = value
BCS skip_preamble
JSR input_tape_pulse ; Y = pulses count; => ZF = value
LDY #59
tape_read_loop: JSR tape_read_byte
STA (src_user_ptr,X)
EOR tmp_2e
STA tmp_2e
JSR inc_user_ptr
LDY #53
BCC tape_read_loop
JSR tape_read_byte
CMP tmp_2e
BEQ do_beep ; GOOD
LDA #CHAR_E ; E
JSR print_char
LDA #CHAR_R ; R
JSR print_char
JSR print_char
do_beep: LDA #CTRL_G_KEY
JMP print_char
load_regs: LDA user_p
PHA
LDA user_a
LDX user_x
LDY user_y
PLP
RTS
store_all_regs:
STA user_a
store_regs: STX user_x
STY user_y
PHP
PLA
STA user_p
TSX
STX user_s
CLD
RTS
; => X = 0
print_2_spaces: LDX #2
print_x_spaces: LDA #SPACE_KEY
print_x_chars: JSR print_char
DEX
BNE print_x_chars
RTS
dialog_beep: CLD
JSR do_beep
dialog_monitor: LDA #CHAR_ASTERISK ; *
STA prompt_char
JSR do_prompt
JSR clear_cur_op
next_prompt: JSR parse_number ; => X = 1 for number, 0 for command
STY prompt_index
LDY #num_cmds
next_code: DEY
BMI dialog_beep
CMP cmd_char_codes,Y
BNE next_code
JSR call_cmd_proc
LDY prompt_index
JMP next_prompt
parse_digit: LDX #3 ; A = char, => X = 1
ASL
ASL
ASL
ASL
digit_loop: ASL
ROL dst_user_ptr
ROL dst_user_ptr+1
DEX
BPL digit_loop
copy_params_loop:
LDA current_op
BNE has_cur_op
LDA dst_user_ptr+1, X
STA src_user_ptr+1, X
STA current_ptr+1, X
has_cur_op: INX
BEQ copy_params_loop
BNE parse_next
; => X = 1 for number, 0 for command
parse_number: LDX #0
STX dst_user_ptr
STX dst_user_ptr+1
parse_next: LDA input_buf,Y
INY
EOR #CHAR_0 ; 0
CMP #10
BCC parse_digit ; A = char, => X = 1
ADC #$88
CMP #<-6
BCS parse_digit ; A = char, => X = 1
RTS
call_cmd_proc: LDA #>cmd_regs
PHA
LDA cmd_low_bytes,Y
PHA
LDA current_op
clear_cur_op: LDY #0
STY current_op
RTS
; ---------------------------------------------------------------------------
cmd_char_codes: .db $BC, $B2, $BE, $EF, $E9, $08, $C2, $C8, $BB ; BC="=", B2=UP, BE=F2, EF=V, E9=P, 08=O, C2=Ctrl+I, C8=Ctrl+O, BB="."
.db $A6, $A4, $06, $95, $07, $02, $05, $F0, $00, $EB, $93, $A7 ; A6=-, A4=+, 6=M, 95=<, 7=N, 2=I, 5=L, F0=W, 0=G, EB=R, 93=colon, A7=.
.db $C6, $99 ; C6=ENTER, 99=SPACE
cmd_low_bytes: .db <(call_basic-1)
.db <(jump_ctrl_y-1)
.db <(cmd_regs-1)
.db <(verify_cmd-1)
.db <(cmd_text_page-1)
.db <(cmd_set_color-1)
.db <(cmd_ctrl_I-1)
.db <(cmd_ctrl_O-1)
.db <(init_basic-1)
.db <(set_current_op-1)
.db <(set_current_op-1)
.db <(move_cmd-1)
.db <(less_op-1)
.db <(norm_cmd-1)
.db <(inverse_cmd-1)
.db <(list_cmd-1)
.db <(cmd_write-1)
.db <(call_user_proc-1)
.db <(cmd_read-1)
.db <(set_current_op-1)
.db <(set_current_op-1)
.db <(no_cmd-1)
.db <(space_cmd-1)
vec_NMI: .dw nmi_proc
vec_RST: .dw start_rst
vec_IRQ: .dw start_irq
В начало
Вернуться на основную страницу
К прочим материалам
Прочие материалы
Реплики Агат-7
Посмотреть реплики узлов 7-й версии ПЭВМ Агат
Реплики Агат-9
Посмотреть реплики узлов 9-й версии ПЭВМ Агат