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

Всего известно два варианта прошивки системного монитора. В основной прошивке, поставляемой с большинством компьютеров этого семейства и описанной в документации, реализовано переключение 64-х текстовых страниц с использованием механизма выбора банка памяти, выбор палитр, а также загрузка ПЗУ автостарта с использованием битовых флагов, размещаемых по смещению $FE ПЗУ.
Также имеется второй вариант прошивки, включающий в себя значительное количество кода от Агат-7.
В обоих вариантах прошивки присутствует ошибка в вызове команды чтения с магнитофона "R". Из-за того, что код этой подпрограммы размещается на странице памяти $FF (адрес $FF07) вместо страницы $FE, реальный вызов происходит по адресу $FE07 и попадает в тело подпрограммы вывода содержимого памяти.
Подпрограмма записи на магнитофон и соответствующая ей команда "W" удалены из системного монитора, по-видимому, из-за нехватки пространства памяти.
Листинг основного варианта
; System Monitor for Agat-9 ; with memory banks control for text screen output ; with palette control ; with extended autostart control ; key and control char codes ENTER_KEY = $8D SPACE_KEY = $A0 UP_KEY = $99 DOWN_KEY = $9A LEFT_KEY = $88 RIGHT_KEY = $95 CTRL_G_KEY = $87 ; perform beep CTRL_L_KEY = $8C ; clear screen CTRL_J_KEY = $8A RIGHT_7_KEY = $9D RIGHT_8_KEY = $9E CTRL_C_KEY = $83 CTRL_X_KEY = $98 CTRL_E_KEY = $85 ; F2 key CTRL_F_KEY = $86 ; F3 key ; some constants num_cmds = 20 num_ctl = 10 line_warn_start= $F8 ; number of chars to warn num_vars_3Fx = 5 ; parameters beep_pre_delay = $40 ; delay before beep beep_interval = $C ; delay between signal change beep_duration = $C0 ; duration of beep signal tape_delay_1 = $32 ; delay for 1 tape_delay_0 = $2C ; delay for 0 tape_read_delay= $3A lines_to_disass= $1C ; lines in single disassembly listing initial_video_page = 2 ; initial video page number title_pos = 26 ; AGAT title position X video_mode_text = 2 ; text mode 32x32 or 64x32 cold_boot_const = $A5 inverse_mask = $28 ; bits for inversed attribs cold_boot_code = cold_boot_const ^ (dialog_monitor >> 8) BIT_OPCODE = $2C ; opcode for choice optimization color_mask = 7 ; bits for color attribute rom_flags_offset = $FE ; offset of flags byte in device's ROM rom_type_offset = $FF ; offset of device type byte in device's ROM ; char codes CHAR_SLASH = $DC CHAR_MINUS = $AD CHAR_0 = $B0 CHAR_9 = $B9 CHAR_A = $C1 CHAR_EOL = $8D CHAR_SPACE = $A0 ; space character 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_G = $E7 CHAR_T = $D4 CHAR_CTRL_G = $87 ; make beep CHAR_CTRL_L = $8C ; clear screen CHAR_UNDERLINE = $DF CHAR_SPACE_LOW = $20 ; space with bit7 = 0, screen fill ; zero page variables autostart_addr = $00 slot_10_ind = $02 video_page_h = $19 video_page_bank = $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_2a = $2A tmp_2b = $2B tmp_2e = $2E tmp_2f = $2F prev_mem_page = $30 current_op = $31 cur_attr = $32 prompt_char = $33 prompt_index = $34 old_print_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 ; input buffer input_buf = $0200 ; device types table dev_table = $0300 ; 3Fx variables brk_addr = $03F0 dialog_proc = $03F2 cold_boot = $03F4 nmi_proc = $03FB irq_addr = $03FE ; i/o addresses input_kbd_reg = $C000 reset_kbd_reg = $C010 tape_out_reg = $C020 beeper_out = $C030 palette_regs = $C058 tape_in_reg = $C060 input_lang = $C063 io_addr_base = $C080 mem_selector = $C100 video_selector = $C700 * = $F800 set_text_mode: AND #$3F ; total 64 text pages available ASL ASL ADC #video_mode_text ; video selector offset = (page shl 2) + 2 TAY STA video_selector,Y ASL cur_attr ; high bit = T64(1) / T32(0) ASL ; transfer high selector bit to T64 attrib flag PHA ROR cur_attr ; high bit = T64(1) / T32(0) AND #$18 ; compute video page address in memory bank ORA #$20 ; start of address window, bank 1 = $2000 STA video_page_h ; all video pages always maps to address window $2000..$3FFF PLA ROL ; calculate video page bank number ROL ROL ROL AND #7 STA video_page_bank ; store video page bank number RTS restore_text_page: LDA video_page_h ASL ASL ASL ASL ORA video_page_bank ROL ROL ROL ROL ADC #video_mode_text ; text mode 32x32 or 64x32 EOR cur_attr ; high bit = T64(1) / T32(0) AND #$7F ; video selector mask not including 32/64 selector EOR cur_attr ; high bit = T64(1) / T32(0) TAY STA video_selector,Y default_palette: LDA #7 .db BIT_OPCODE set_palette: LDA dst_user_ptr ; higher 7 bits in color code specifies palette switches LDY #7 ; number of palette regs - 1 palette_loop: ASL STA palette_regs,Y DEY BCS skip_palette_bit STA palette_regs,Y skip_palette_bit: DEY BPL palette_loop LDA dst_user_ptr RTS ; switch bank 1 to specified video page bank set_mem_page: LDY video_page_bank LDA mem_selector+$10,Y STA prev_mem_page STA mem_selector+$10,Y RTS ; restore bank 1 restore_mem_page: LDY prev_mem_page STA mem_selector,Y RTS ; calculate params for current instruction ; prints PC address, "-" ; 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 use_lower_flags: AND #$F 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 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 print_disass_line: JSR calc_listing_params ; calculate params for current instruction ; prints PC address, "-" ; returns A = command name index PHA cmd_byte_loop: LDA (user_pc),Y JSR print_hex_byte LDX #1 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_2a ; current character from screen LDA packed_name_h,Y ; packed by 5 bits per char STA tmp_2b cmd_name_loop: LDA #0 LDY #5 ; number of bits for single char shift_loop: ASL tmp_2b ROL tmp_2a ; current character from screen ROL 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 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 INX BNE print_xy INY print_xy: TYA JSR print_hex_byte TXA JMP print_hex_byte next_disass_addr: SEC LDA tmp_2f ; current bit for tape, 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, 2, $45, 3, $D0, 8, $40, 9, $30, $22, $45, $33 .db $D0, 8, $40, 9, $40, 2, $45, $33, $D0, 8, $40, 9 ; index in addr_and_len table packed by 4 bits .db $40, 2, $45, $B3, $D0, 8, $40, 9, 0, $22, $44, $33 .db $D0, $8C, $44, 0, $11, $22, $44, $33, $D0, $8C, $44 .db $9A, $10, $22, $44, $33, $D0, 8, $40, 9, $10, $22 .db $44, $33, $D0, 8, $40, 9, $62, $13, $78, $A9 opcode_addr_and_len:.db 0, $21, $81, $82, 0, 0, $59, $4D, $91, $92, $86 .db $4A, $85, $9D first_op_chars: .db CHAR_COMMA, CHAR_RPAR, CHAR_COMMA, CHAR_HASH, CHAR_LPAR .db 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 .db $1D, $23, $9D, $8B, $1D, $A1, 0, $29, $19, $AE, $69 ; packed by 5 bits per char .db $A8, $19, $23, $24, $53, $1B, $23, $24, $53, $19 .db $A1, 0, $1A, $5B, $5B, $A5, $69, $24, $24, $AE, $AE .db $A8, $AD, $29, 0, $7C, 0, $15, $9C, $6D, $9C, $A5 .db $69, $29, $53, $84, $13, $34, $11, $A5, $69, $23 .db $A0 packed_name_h: .db $D8, $62, $5A, $48, $26, $62, $94, $88, $54, $44 .db $C8, $54, $68, $44, $E8, $94, 0, $B4, 8, $84, $74 ; packed by 5 bits per char .db $B4, $28, $6E, $74, $F4, $CC, $4A, $72, $F2, $A4 .db $8A, 0, $AA, $A2, $A2, $74, $74, $74, $72, $44, $68 .db $B2, $32, $B2, 0, $22, 0, $1A, $1A, $26, $26, $72 .db $72, $88, $C8, $C4, $CA, $26, $48, $44, $44, $A2 .db $C8 start_irq: STA user_a PLA PHA AND #$10 BNE 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 ; prints PC address, "-" JSR print_regs JMP dialog_beep start_rst: CLD JSR beep_proc ; perform beep LDA dialog_proc+1 EOR #cold_boot_const EOR cold_boot CLV ; VF = pass number (0 = forward, 1 = backward) BEQ hot_start LDA #0 ; base ram io addr is C080 STA slot_10_ind LDX #$C1 ; first slot addr_h TXS BNE slot_check dev_loop: TXA ASL ASL ASL ASL STA slot_10_ind ; calculate slot index * $10 slot_check: LDA #0 STA autostart_addr STX autostart_addr+1 LDY #rom_type_offset ; offset of device type byte in device's ROM LDA (autostart_addr),Y ASL BPL not_a_ram ; not a RAM card; RAM card should have $Fx or $7x at offset $FF LDY slot_10_ind LDA io_addr_base,Y AND #$F ; check if slot is empty (lower 4 bits are zero, is it stable?) BEQ store_dev_type LDA #1 ; 1 = RAM card BVS store_dev_type ; store dev type on the second pass after memory init is done LDY #$77 ram_loop: STA (autostart_addr),Y TYA SEC SBC #$11 TAY BCS ram_loop BCC next_slot not_a_ram: LDY #rom_flags_offset ; offset of flags byte in device's ROM LDA (autostart_addr),Y LSR LSR LSR BCC card_not_bootable ; flags bit2 = 1 for bootable cards TXS ; store boot address card_not_bootable: LSR BCC no_early_start ; flags bit3 = 1 for early start card (such as a printer card) JSR call_autostart_rom no_early_start: INY ; Y = device type offset again LDA (autostart_addr),Y store_dev_type: STA dev_table-$C1,X next_slot: BVS second_pass INX CPX #$C7 BCC dev_loop BIT autostart_addr+1 ; set VF, do second pass second_pass: DEX CPX #$C1 BCS dev_loop hot_start: LDA #$2F ORA cur_attr ; high bit = T64(1) / T32(0) STA cur_attr ; high bit = T64(1) / T32(0) PHP JSR reset_scr_wnd JSR default_output JSR default_input STA reset_kbd_reg PLP BVS do_cold_start JSR restore_text_page start_dialog: JMP (dialog_proc) do_cold_start: LDA #initial_video_page ; S = Cx for autostart (C1 if no autostart found) JSR set_text_mode ; A = page number, 0..63. Pages 0..31 are 32x32, pages 32..63 are 64x32 JSR default_palette LDX #agat_title - msg_start JSR print_msg ; X = message offset in table LDY #num_vars_3Fx init_vars_loop: LDA init_vecs-1,Y STA brk_addr-1,Y DEY BNE init_vars_loop TSX ; S = active slot CPX #$C1 ; first slot reached, nothing is bootable BEQ start_dialog STX autostart_addr+1 call_autostart_rom: JMP (autostart_addr) init_vecs: .dw brk_proc .dw dialog_monitor .db cold_boot_code msg_print_char: JSR print_char .db BIT_OPCODE msg_set_pos: STA cur_pos_x INX ; X = message offset in table print_msg: LDA msg_start,X BMI msg_print_char BNE msg_set_pos RTS 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: JSR print_space LDA reg_names-$FB,X JSR print_char JSR print_eq LDA user_a+5,X JSR print_hex_byte INX BMI print_reg 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_reg ; bit 7 = input signal 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 ; check bit 7 RTS write_preamble: LDY #$4B JSR tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0 BNE write_preamble ADC #<-2 BCS write_preamble LDY #33 JSR tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0 INY INY ; Y=retries, CF=output => X = X - 1, Y = delay0 tape_bit_out: DEY BNE tape_bit_out ; Y=retries, CF=output => X = X - 1, Y = delay0 BCC tape_output_0 LDY #tape_delay_1 ; delay for 1 second_delay_loop: DEY BNE second_delay_loop tape_output_0: LDY tape_out_reg LDY #tape_delay_0 ; delay for 0 DEX 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 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 JMP print_minus ; A = cursor Y, not uses window calc_scr_addr: STA cur_scr_addr+1 LDA #0 LSR cur_scr_addr+1 ROR LSR cur_scr_addr+1 ROR STA cur_scr_addr LDA video_page_h ADC cur_scr_addr+1 STA cur_scr_addr+1 RTS msg_start: .db CHAR_E ; E .db CHAR_R ; R .db CHAR_R ; R msg_beep_eol: .db CHAR_CTRL_G ; make BEEP .db CHAR_EOL .db 0 ; --------------------------------------------------------------------------- delay_proc: JMP some_delay ; --------------------------------------------------------------------------- agat_title: .db CHAR_CTRL_L ; clear screen .db title_pos ; AGAT title position X .db CHAR_A ; A .db CHAR_CYR_G ; Г .db CHAR_A ; A .db CHAR_T ; T .db CHAR_MINUS ; - .db CHAR_9 ; 9 .db 0 ; 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 ctl_char_table: .db CTRL_E_KEY ; F2 key .db CTRL_F_KEY ; F3 key .db UP_KEY .db DOWN_KEY .db CTRL_J_KEY .db LEFT_KEY .db RIGHT_KEY .db CTRL_L_KEY ; clear screen .db RIGHT_7_KEY .db RIGHT_8_KEY .db CTRL_G_KEY ; perform beep ctl_addr_l: .db <(char_del_proc-1) ; delete character, move line left .db <(char_ins_proc-1) ; insert character, move line right .db <(up_key_proc-1) ; move cursor up .db <(down_key_proc-1) ; move cursor down ctl_addr_eol_l: .db <(eol_key_proc-1) ; move to start of next line .db <(left_key_proc-1) ; move cursor left .db <(right_key_proc-1) ; move cursor right .db <(clr_scr_proc-1) ; clear screen contents, reset cursor .db <(clr_eol_proc-1) ; clear to end of line .db <(clr_eos_proc-1) ; clear to end of screen .db <(beep_proc-1) ; perform beep process_char_output: CMP #CHAR_EOL BNE not_eol ; do not need to scroll lock LDY input_kbd_reg CPY #CHAR_SPACE ; space character BNE not_eol_out ; not a space, do not lock STY reset_kbd_reg scroll_lock_loop: LDY input_kbd_reg BPL scroll_lock_loop CPY #CTRL_C_KEY BEQ not_eol_out ; do not clear Ctrl+C STY reset_kbd_reg not_eol_out: LDY #ctl_addr_eol_l - ctl_addr_l ctl_char_found: LDA #>beep_proc ; all ctl procs are in single page PHA LDA ctl_addr_l,Y PHA ctl_char_none: RTS reset_scr_wnd: LDA #0 STA user_p STA wnd_top STA wnd_left_2 LDA #64 ; text line size in bytes STA wnd_right_2 LDA #32 ; number of lines STA wnd_bottom LDA #31 ; starting cursor position STA cur_pos_y BNE calc_cur_pos_addr not_eol: BIT ctl_char_none ; 0x60 - check if bit6 and bit5 are both 0 BNE char_output LDY #num_ctl ctl_char_loop: CMP ctl_char_table,Y BEQ ctl_char_found DEY BPL ctl_char_loop BCS ctl_char_none char_output: LDY cur_pos_x STA (cur_scr_addr),Y INY LDA cur_attr ; high bit = T64(1) / T32(0) BMI out_for_t64 STA (cur_scr_addr),Y INY BNE out_for_t64 right_key_proc: LDY cur_pos_x ; move cursor right JSR inc_pos ; Y = pos out_for_t64: STY cur_pos_x CPY wnd_right_2 BCS eol_key_proc ; move to start of next line do_nothing: RTS left_key_proc: LDY cur_pos_x ; move cursor left BNE not_jump_right JSR up_key_proc ; move cursor up LDY wnd_right_2 not_jump_right: JSR dec_pos ; Y = pos STY cur_pos_x LDA (cur_scr_addr),Y ADC #<-34 RTS up_key_proc: LDA wnd_top ; move cursor up CMP cur_pos_y BCS do_nothing DEC cur_pos_y BCC calc_cur_pos_addr clr_scr_proc: LDA wnd_top ; clear screen contents, reset cursor STA cur_pos_y LDY #0 STY cur_pos_x BEQ do_clear clr_eos_proc: LDY cur_pos_x ; clear to end of screen LDA cur_pos_y do_clear: PHA JSR upd_scr_addr ; A = cursor Y, uses window JSR clear_scr_block ; CF = 1 LDY #0 PLA ADC #0 CMP wnd_bottom BCC do_clear 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 RTS eol_key_proc: LDA #0 ; move to start of next line STA cur_pos_x down_key_proc: INC cur_pos_y ; move cursor down 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_2a ; current character from screen LDA cur_scr_addr+1 STA tmp_2b 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_2a),Y ; current character from screen DEY BPL scroll_loop BMI retry_scroll clear_last_line: LDY #0 JSR clear_scr_block ; CF = 1 BCS calc_cur_pos_addr .db 0 some_delay: SEC outer_loop: PHA inner_loop: SBC #1 BNE inner_loop PLA SBC #1 BNE outer_loop RTS clr_eol_proc: LDY cur_pos_x ; clear to end of line clear_scr_block: LDA #CHAR_SPACE_LOW ; space with bit7 = 0, screen fill STA (cur_scr_addr),Y INY LDA cur_attr ; high bit = T64(1) / T32(0) BMI clear_scr_t64 STA (cur_scr_addr),Y INY clear_scr_t64: CPY wnd_right_2 BCC clear_scr_block RTS ; CF = 1 ; perform beep 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 ; delete character, move line left char_del_proc: LDY cur_pos_x char_del_loop: JSR inc_pos ; Y = pos LDA (cur_scr_addr),Y JSR dec_pos ; Y = pos STA (cur_scr_addr),Y CMP #CHAR_SPACE_LOW ; space with bit7 = 0, screen fill BEQ char_del_end JSR inc_pos ; Y = pos BNE char_del_loop char_del_end: RTS ; insert character, move line right char_ins_proc: LDY cur_pos_x skip_to_end_of_block: JSR inc_pos ; Y = pos BEQ char_ins_loop LDA (cur_scr_addr),Y CMP #CHAR_SPACE_LOW ; space with bit7 = 0, screen fill BNE skip_to_end_of_block char_ins_loop: JSR dec_pos ; Y = pos LDA (cur_scr_addr),Y JSR inc_pos ; Y = pos STA (cur_scr_addr),Y JSR dec_pos ; Y = pos CPY cur_pos_x BNE char_ins_loop LDA #CHAR_SPACE ; space character STA (cur_scr_addr),Y RTS inc_pos: BIT cur_attr ; high bit = T64(1) / T32(0) BMI inc_pos_t64 INY inc_pos_t64: INY RTS dec_pos: BIT cur_attr ; high bit = T64(1) / T32(0) BMI dec_pos_t64 DEY dec_pos_t64: DEY RTS ; input char using current char proc vector => A = char input_char: JMP (input_char_ptr) ; input character with cursor blinking => A = char input_char_proc: JSR set_mem_page ; switch bank 1 to specified video page bank LDY cur_pos_x LDA (cur_scr_addr),Y STA tmp_2a ; store current character from screen cursor_toggle: LDA (cur_scr_addr),Y EOR #CHAR_UNDERLINE ; _ EOR tmp_2a ; current character from screen STA (cur_scr_addr),Y ; toggle cursor input_loop: INC rnd_counter_l ; random counter from key input proc, low part BNE no_inc_rnd_h INC rnd_counter_h ; random counter, high part LDA rnd_counter_h ; random counter, high part AND #$3F ; toggle interval BEQ cursor_toggle no_inc_rnd_h: LDA input_kbd_reg BPL input_loop PHA ASL ASL BCC not_switch_reg ; bit6 = 0, not are letters EOR input_lang ; bit7 = 1 for lat, 0 for rus BMI not_switch_reg ; default are latin keys on input PLA EOR #$A0 ; toggle bit5 (rus) and bit7 (small chars) PHA not_switch_reg: STA reset_kbd_reg LDA tmp_2a ; current character from screen STA (cur_scr_addr),Y ; restore character on screen JSR restore_mem_page ; restore bank 1 PLA RTS do_print_char: JSR print_char handle_edit_mode: JSR input_char ; input char using current char proc vector => A = char LDY #3 ; process first 4 control keys for immediate output control_key_loop: CMP ctl_char_table,Y BEQ do_print_char DEY BPL control_key_loop RTS print_current_char: JSR print_char EOR #$20 BEQ no_input_overflow EOR #$B8 ; $98 (Ctrl+X) xor $20 BEQ on_overflow EOR #$10 ; $88 (Left) xor $98 xor $20 BNE not_control_key BCS do_left_key BCC no_input_overflow not_control_key: CPX #line_warn_start ; number of chars to warn BCC not_overflow JSR beep_proc ; perform 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 DEX no_input_overflow: JSR handle_edit_mode CMP #RIGHT_KEY BNE not_right LDA tmp_2a ; current character from screen not_right: STA input_buf,X CMP #ENTER_KEY BNE print_current_char LDA #RIGHT_7_KEY JSR print_char BNE print_eol .db 0 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 JSR print_eq PLA print_hex_byte: PHA LSR LSR LSR LSR JSR print_hex_digit PLA AND #$F print_hex_digit: ORA #CHAR_0 ; 0 CMP #CHAR_9+1 BCC print_char ADC #(CHAR_A - CHAR_0 - $0A - 1) .db BIT_OPCODE print_space: LDA #CHAR_SPACE ; space character .db BIT_OPCODE print_eol: LDA #CHAR_EOL ; end of line .db BIT_OPCODE print_minus: LDA #CHAR_MINUS ; - .db BIT_OPCODE print_eq: LDA #CHAR_EQ ; = .db BIT_OPCODE print_ctrl_l: LDA #CTRL_L_KEY ; clear screen print_char: JMP (print_char_ptr) print_char_proc: STY old_print_y PHA JSR set_mem_page ; switch bank 1 to specified video page bank PLA PHA JSR process_char_output JSR restore_mem_page ; restore bank 1 LDY old_print_y PLA RTS dump_next_byte: LDA src_user_ptr ORA #7 read_broken_ptr: ; real read command locates at the next page 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: JSR print_space LDA (src_user_ptr),Y LDX current_op BEQ dump_as_hex BIT ctl_char_none ; check if char is printable BEQ dump_as_hex JSR print_char JSR print_space BNE dump_end dump_as_hex: JSR print_hex_byte dump_end: JSR inc_user_ptr BCC mem_print_loop RTS process_empty_cmd: DEC prompt_index BEQ dump_next_byte space_cmd: DEX BNE not_empty_line CMP #CHAR_COLON ; : BEQ do_enter_val JMP do_add_sub do_enter_val: STA current_op LDA dst_user_ptr STA (current_ptr),Y INC current_ptr BNE not_current_ptr_h_inc INC current_ptr+1 not_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 JSR print_space 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 dump_text_cmd: STA current_op JSR dump_addr JMP clear_cur_op inverse_cmd: LDA #0 ; set inverse bits to 00 .db BIT_OPCODE normal_cmd: LDA #inverse_mask ; bits for inversed attribs EOR cur_attr ; high bit = T64(1) / T32(0) AND #inverse_mask ; bits for inversed attribs set_attribs: EOR cur_attr ; high bit = T64(1) / T32(0) STA cur_attr ; high bit = T64(1) / T32(0) RTS default_input: LDA #0 STA dst_user_ptr cmd_ctrl_K: LDX #input_char_ptr LDY #<input_char_proc ; input character with cursor blinking => A = char BNE set_io_proc default_output: LDA #0 STA dst_user_ptr cmd_ctrl_1: LDX #print_char_ptr LDY #<print_char_proc set_io_proc: LDA dst_user_ptr AND #$F BEQ reset_io_proc ORA #$C0 LDY #0 .db BIT_OPCODE reset_io_proc: LDA #>print_char_proc STY 0,X STA 1,X RTS 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 cmd_text_page: LDA dst_user_ptr JMP set_text_mode ; A = page number, 0..63. Pages 0..31 are 32x32, pages 32..63 are 64x32 cmd_set_color: JSR set_palette ; higher 7 bits in color code specifies palette switches EOR cur_attr ; high bit = T64(1) / T32(0) AND #color_mask ; bits for color attribute JMP set_attribs call_proc: JSR process_empty_cmd PLA PLA BNE dialog_monitor RTS cmd_read_real: ; located on wrong page, call is broken JSR input_tape_pulses LDA #22 JSR write_preamble 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 BNE tape_cs_error LDX #msg_beep_eol - msg_start .db BIT_OPCODE tape_cs_error: LDX #msg_start - msg_start JMP print_msg ; X = message offset in table 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 print_2_spaces: LDX #2 print_x_spaces: JSR print_space DEX BNE print_x_spaces RTS ; => X = 0 .db 0, 0, 0 dialog_beep: CLD JSR beep_proc ; perform 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 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 ; => X = 1 for number, 0 for command call_cmd_proc: LDA #>cmd_regs ; high byte of address PHA LDA cmd_low_bytes,Y PHA LDA current_op clear_cur_op: LDY #0 STY current_op RTS cmd_char_codes: .db $E9, $EF, $ED, 8, $C4, $A9, $A6, $A4, 6, $95, 7 ; E9=P, EF=V, ED=T, 08=O, C4=Ctrl+K, A9="1", A6=-, A4=+, 6=M, 95=<, 7=N .db 2, 5, $F1, $EB, 0, $93, $A7, $C6, $99 ; 2=I, 5=L, F1=X, EB=R, 0=G, 93=colon, A7=. , C6=ENTER, 99=SPACE cmd_low_bytes: .db <(cmd_regs-1) .db <(verify_cmd-1) .db <(cmd_text_page-1) .db <(cmd_set_color-1) .db <(cmd_ctrl_K-1) .db <(cmd_ctrl_1-1) .db <(set_current_op-1) .db <(set_current_op-1) .db <(move_cmd-1) .db <(less_op-1) .db <(normal_cmd-1) .db <(inverse_cmd-1) .db <(list_cmd-1) .db <(dump_text_cmd-1) .db <(read_broken_ptr+1-1) ; READ command is broken! .db <(call_user_proc-1) .db <(set_current_op-1) .db <(set_current_op-1) .db <(call_proc-1) .db <(space_cmd-1) reg_names: .db CHAR_A ; A .db CHAR_X ; X .db CHAR_Y ; Y .db CHAR_P ; P .db CHAR_S ; S .db 0 .dw nmi_proc .dw start_rst .dw start_irq
В начало
Вернуться на основную страницу
К прочим материалам
Прочие материалы
Реплики Агат-7
Посмотреть реплики узлов 7-й версии ПЭВМ Агат
Реплики Агат-9
Посмотреть реплики узлов 9-й версии ПЭВМ Агат