Информация
Получен из анализа прошивки системного монитора для Агат-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-й версии ПЭВМ Агат