; SuBEditor. ; ; Writen in Sux assembly by ; mr b0nk 500 ; String Literals/Constants. .org $1000 tok: .byte "dab" msg: .byte "oof, you divided a, and b on me.\n" string: .byte "Please, type something.\n" string2: .byte "You typed, " ; Linewrap bitmask table. .org $1100 bits: .byte $80 .byte $40 .byte $20 .byte $10 .byte $08 .byte $04 .byte $02 .byte $01 ; Input buffer. .org $2000 buffer: .org $4000 cmd_buf: ; Initalize some variables. .org $0 scr_row: .byte $0 scr_col: .byte $0 scr_trow: .byte $0 scr_tcol: .byte $0 scr_ptr: .word $0 ; Registers. a: .byte $0 b: .byte $0 c: .byte $0 d: .byte $0 e: .byte $0 f: .byte $0 ; This register is always zero. zero: .qword $0 ; End of registers. end: .byte $0 bitmask: .byte $0 bitabl: .qword $0 .qword $0 scr_str: .byte $0 scr_end: .byte $0 wrapped: .byte $0 ; Pointers ptr: .qword $0 ptr2: .qword $0 ptr3: .qword $0 ptr4: .qword $0 ptr5: .qword $0 ptr6: .qword $0 ; Main program .org $8000 reset: cps ldx.w #$FFFF txs ldy #0 tyx lda #23 sta scr_end lda.w #buffer sta.q ptr5 lda.w #cmd_buf sta.q ptr6 tya sta scr_str sta.q bitabl sta.q bitabl+8 jsl clr_buf jmp start clr_buf: phb #1 ldb #0 clr_buf_st: cpy.w #$1FFF bcs clr_buf_end sta.q (ptr5), y tya adc #8 tay tba sta.q (ptr5), y tya adc #8 tay tba sta.q (ptr5), y tya adc #8 tay tba sta.q (ptr5), y tya adc #8 tay tba jmp clr_buf_st clr_buf_end: ldy.w zero plb #1 rtl start: lda #0 sta $C000 tax phy #2 tay jsl clr_cbuf ply #2 lda.w #string jsl print_str lda.w zero jmp rset_a clr_cbuf: phb #1 ldb #0 clr_cbuf_st: cpy.w #$3FF bcs clr_cbuf_end sta.q (ptr6), y tya adc #8 tay tba sta.q (ptr6), y tya adc #8 tay tba sta.q (ptr6), y tya adc #8 tay tba sta.q (ptr6), y tya adc #8 tay tba jmp clr_cbuf_st clr_cbuf_end: plb #1 rtl pull_y: ply #2 rset_a: lda #0 sta $C000 inc read: lda $C000 ; Get control register. beq rset_a ; Loop until we get a character. jsl getchar ; We got a key. beq parse ; We got a newline, so start parsing the line. jmp rset_a ; We didn't get a newline, so keep getting more characters. print_str: sta.q ptr ldb #0 tba pntstr_st: phy #2 txy lda (ptr), y ; Get character at offset x. beq pntstr_end ; Did we find a null terminator? ply #2 inx jsl print_char jmp pntstr_st pntstr_end: ply #2 rtl getbit: clc lda scr_str bne getbt0 ldx scr_row jmp getbt1 getbt0: lda scr_row adc scr_str tax getbt1: jsl bitpos ldb bitabl, x aba cmp #1 jmp bitout clrbit: jsl bitpos xor #$FF ldb bitabl, x aba bitsav: sta bitabl, x bitout: ldx bitmask rtl setbit: jsl bitpos ldb bitabl, x oab jmp bitsav bitpos: pha #1 lda.w #bits sta.q ptr3 lda.w zero pla #1 stx bitmask txa and #7 phy #2 tay tax lda (ptr3), y ply #2 pha #1 lda bitmask lsr #3 tax pla #1 rtl getchar: lda $C002 ; Get typed character. ldb #0 stb e pha #1 phy #2 cmp #10 beq cmd_cpy getchar_pnt: ply #2 pla #1 ldb e bne reset_row getchar_pnt1: jsl print_char lda a cmp #10 beq getchar_line jmp getchar_char reset_row: ldb e stb scr_row jmp getchar_pnt1 cmd_cpy: ldb scr_row stb e jsl findst clc lda scr_row adc scr_str mul #80 tay ldx.w #$0 cmd_cpy_strt: lda (ptr5), y beq getchar_pnt phy #2 txy sta (ptr6), y inx ply #2 iny jmp cmd_cpy_strt getchar_line: lda #0 jmp getchar_end getchar_char: lda #1 getchar_end: rtl findst: jsl getbit bcc findst_done dec scr_row bpo findst inc scr_row findst_done: rtl parse: lda #0 tax jsl dabbed beq start lda #0 tax jmp result print_char: sta a cmp #$1B beq esc cmp #$A beq nl ; Did the user type a newline? cmp #$C beq clr_scr cmp #19 beq en_step cmp #18 beq dis_step cmp #8 beq bs ; Did the user type a backspace? cmp #$7F beq bs ; Did the user type a backspace? sta a printc: lda a sta (ptr5), y ; Store typed character into the input buffer. inc scr_col ; Increment the cursor's x coordinate. iny printc_2: ldb #1 stb f ldb scr_col cpb #80 bcs printc_4 printc_3: sta $C001 ; Echo typed character. ldb f beq printc_wrap jmp printc_end printc_4: ldb scr_row cpb #23 bcs printc_scrl printc_5: ldb #0 stb f jmp printc_3 printc_scrl: sta $C001 ; Echo typed character. clc lda #1 sta wrapped jsl scrl_down printc_wrap: ldb #0 stb scr_col ldb scr_row cpb #23 bcs printc_wrap2 printc_wrap1: inc scr_row printc_wrap2: phx #2 clc lda scr_row adc scr_str tax jsl setbit plx #2 jsl update_pos printc_end: rtl nl: lda #0 sta (ptr5), y ; Store said terminator into the input buffer. sta scr_col lda scr_row cmp #23 bne nl_inc jsl scrl_down lda #10 sta a jmp printc_end nl_inc: inc scr_row jsl update_pos lda #10 sta a jmp printc_end clr_scr: lda #23 sta scr_end lda #0 sta scr_str sta.q bitabl sta.q bitabl+8 tay jsl clr_buf tay jsl clr_cbuf sta scr_col sta scr_row jsl update_pos lda #$C sta $C001 jmp printc_end en_step: lda $C010 beq step_en jmp stp_end step_en: lda #1 sta $C010 jmp stp_end dis_step: lda $C010 bne step_dis jmp stp_end step_dis: lda #0 sta $C010 stp_end: jmp printc_end back: lda #$7F ; Print a backspace to the screen. sta $C001 ; dey ; Decrement the buffer's offset. lda #0 ; Place a null terminator sta (ptr5), y ; into the buffer. dec scr_col ; Move the cursor back by one column, jsl update_pos ; and update it's position. jmp printc_end ; We are done. bs: lda scr_col ; Are we at the far left of the screen? beq back_wrap ; Yes, so check for a wrapped line. jmp back ; No, so add the backspace to the buffer. back_wrap: jsl getbit ; Is this line, a wrapped line? bcs back_wrap1 ; Yes, so check if the cursor is at the top. jmp printc_end ; No, so we're done. back_wrap1: lda scr_row ; Are we at the top of the screen? beq back_wrap2 ; Yes, so check if the screen is at the top of the buffer. jmp backwrp ; No, so start clearing the wrap bit. back_wrap2: lda scr_str ; Are we at the top of the buffer? bne back_scrl ; Yes, so scroll up. jmp printc_end ; No, so we're done. back_scrl: clc ; Clear the carry flag, so that we don't get odd behaviour. jsl scrl_up ; Scroll up. inc scr_row ; Move down by one row. backwrp: clc ; Clear the carry flag. lda scr_row ; Add the cursor's row position, adc scr_str ; and the screen's starting row. tax ; Transfer that into X. backwrp2: dec scr_row ; Move up by one row. jsl clrbit ; Clear the wrap bit for this row. ldb #80 ; Move the cursor to the absolute right of the screen. stb scr_col ; jsl update_pos ; Update the cursor's position. jmp back ; Delete the previous character. esc: lda $C000 ; Get the next character. lda $C002 ; cmp #$1B ; Is this character an escape character? beq shftesc ; Yes, so check the other set of escape routines. lda $C000 ; No, so wait for the next character. beq printc_end ; We have an error, so discard it, and go back to getting user input. lda $C002 ; Get the escape code. sta c ; Store the escape code, until we need it. lda #0 ; Set the D pseudo register to zero. sta d ; jsl isup ; Check if the user pressed up. lda d ; Did the user press up? bne esc_end ; Yes, so we're done. jsl isdown ; No, so check if the user pressed down. lda d ; Did the user press down? bne esc_end ; Yes, so we're done. lda #0 ; No, so check if the user pressed left. jsl isleft ; lda d ; Did the user press left? bne esc_end ; Yes, so we're done. jsl isright ; No, so check if the user pressed right. esc_end: lda #0 ; Set the D pseudo register to zero. sta d ; jmp printc_end ; Go back to getting user input. shftesc: lda $C000 ; Skip the '['. lda $C000 ; Get the next character. beq printc_end ; We have an error, so discard it, and go back to getting user input. lda $C002 ; Get the escape code. sta c ; Store the escape code, until we need it. lda #0 ; sta d ; jsl isshftup ; Check if the user pressed shift+up. lda d ; bne shftesc_end ; jsl isshftdown ; Check if the user pressed shift+down. shftesc_end: lda #0 ; sta d ; jmp printc_end ; Go back to getting user input. isup: lda c ; No, so load the escape code back into the accumulator. cmp #$41 ; Did the user press the up arrow key? bne isup_done ; Yes, so we're done. lda scr_row ; No, so is the cursor at the top of the screen? beq isup_scrl ; Yes, so check if we need to scroll. isup_2: lda c ; No, so load the escape code back into the accumulator. cmp #$41 ; Did the user press the up arrow key? beq up ; Yes, so move the cursor up. jmp isup_done ; No, so we're done isup_scrl: lda scr_str ; Are we at the top of the screen buffer? beq isup_done ; Yes, so we're done. jsl scrl_up ; No, so scroll up. isup_done: rtl ; End of isup. isdown: lda c ; No, so load the escape code back into the accumulator. cmp #$42 ; Did the user press the down arrow key? bne isdown_done lda scr_row ; Start checking the y coordinate of the cursor. cmp #23 ; Is the cursor at the bottom of the screen? beq isdown_scrl ; Yes, so return. lda c ; No, so load the escape code back into the accumulator. cmp #$42 ; Did the user press the down arrow key? beq down ; Yes, so move the cursor down. jmp isdown_done isdown_scrl: lda scr_row ; Save the cursor's row number. sta scr_trow ; lda scr_col ; Save the cursor's column number. sta scr_tcol ; jsl scrl_down ; Scroll down. lda scr_trow ; Load the cursor's row number. sta scr_row ; lda scr_tcol ; Load the cursor's column number. sta scr_col ; isdown_done: rtl ; End of isdown. isright: lda c ; No, so load the escape code back into the accumulator. cmp #$43 ; Did the user press the right arrow key? bne isright_dne ; No, so we're done. lda scr_col ; Yes, so start checking the x coordinate of the cursor. cmp #79 ; Is the cursor at the far right of the screen? beq isright_wrp ; Yes, so check if this is a wrapped line. jmp right ; No, so move the cursor right, like normal. isright_wrp: inc scr_row ; Move down a row. jsl getbit ; Is the current line, a wrapped line? bcs wrap_inc ; Yes, so leave the cursor where it is. dec scr_row ; No, so move the cursor back up a row. jmp isright_dne ; We are done. isright_scr: lda scr_str ; Are we at the top of the screen buffer? beq isright_end ; Yes, so we're done. lda #1 ; No, so scroll down. sta wrapped ; Set the wrapped flag. jsl scrl_down ; Scroll down. jmp isright_end ; We are done. wrap_inc: lda #0 ; Set the cursor to the far left of the screen. sta scr_col ; lda scr_row ; Get the current row number. cmp #23 ; Are we at the bottom of the screen? bcs isright_scr ; Yes, so check if we are scrolling down. jmp isright_nd2 ; We are done. isright_end: dec scr_row ; Move back up a row. isright_nd2: jsl update_pos ; Update the cursor position. isright_dne: lda #0 ; Unset the wrapped flag. sta wrapped ; rtl ; End of isright. isleft: lda c cmp #$43 beq isleft_done lda scr_col ; Is the cursor at the far left of the screen? beq isleft_wrp ; Yes, so start checking if this is a wrapped line. lda c ; No, so load the escape code back into the accumulator. cmp #$44 ; Did the user press the left arrow key? beq left ; Yes, so move the cursor left. jmp isleft_done ; We are done. isleft_wrp: jsl getbit ; Is the current line, a wrapped line? bcs wrap_dec ; Yes, so wrap back up a line. jmp isleft_done ; No, so return. wrap_dec: lda scr_row ; Is the cursor at the top of the screen? beq wrap_dec1 ; Yes, so don't move up a row. lda #1 ; No, so move up a row. sta wrapped ; Set the wrapped flag. dec scr_row ; Move the cursor up by one row. wrap_dec1: lda #79 ; Move the Cursor to the far right of the screen. sta scr_col ; lda #1 ; Tell the escape routine to stop after this. sta d ; lda scr_row ; Are we at the top of the screen? beq isleft_scrl ; Yes, so check if we need to scroll. jmp isleft_end ; No, so we're done. isleft_scrl: lda wrapped ; Was the wrapped flag set somewhere else? bne isleft_end ; Yes so we're done. lda scr_str ; No, but are we actually at the top of the screen buffer? beq isleft_done ; Yes, so we're done. jsl scrl_up ; No, so scroll up. jmp isleft_done ; We are done. isleft_end: jsl update_pos ; Update the cursor position. isleft_done: lda #0 ; Unset the wrapped flag. sta wrapped ; rtl ; End of isleft. up: dec scr_row jsl update_pos lda #1 sta d jmp isup_done down: inc scr_row jsl update_pos lda #1 sta d jmp isdown_done right: inc scr_col jsl update_pos jmp isright_dne left: dec scr_col jsl update_pos lda #1 sta d jmp isleft_done isshftup: lda c ; Load the escape code back into the accumulator. cmp #$41 ; Did the user press the up arrow key? bne isshftup_done lda #1 sta d lda scr_str beq isshftup_done jmp shftup isshftup_done: rtl isshftdown: lda c ; Load the escape code back into the accumulator. cmp #$42 ; Did the user press the down arrow key? bne isshftdown_done lda #1 sta d lda scr_end cmp #71 bcs isshftdown_done jmp shftdown isshftdown_done: rtl shftup: jsl scrl_up lda #1 sta d jmp isshftup_done shftdown: jsl scrl_down lda #1 sta d jmp isshftdown_done update_pos: ldb #1 stb f clc lda scr_row adc scr_str clc mul #80 clc adc scr_col tay lda #$1B ; Print an escape character sta $C001 ; to the screen. lda #$5B ; Print '[' sta $C001 ; to the screen, and start the escape sequence. jsl getrow ; Start printing the row number to the screen. jsl getcol ; Start printing the column number to the screen. lda #$48 ; Print 'H' sta $C001 ; to the screen. rtl ; End of update_pos. getrow: lda scr_row ; Get the cursor's y coordinate. div #10 ; Divide A by 10. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. tba ; Get the remainder. adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. rtl ; End of getrow. getcol: lda #$3B ; Print ';' sta $C001 ; to the screen. lda scr_col ; Get the cursor's x coordinate. div #10 ; Divide A by 10. clc adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. tba ; Get the remainder. clc adc #$30 ; Convert it to ascii, and sta $C001 ; print to the screen. rtl ; End of getrow. scrl_down: inc scr_str inc scr_end lda #$1B ; Print an escape character sta $C001 ; to the screen. lda #$5B ; Print '[' sta $C001 ; to the screen, and start the escape sequence. lda #$54 ; Print 'T' sta $C001 ; to the screen, and end the escape sequence. lda wrapped beq scrldn_save scrldn1: jsl rdrw_row lda wrapped beq scrldn_load jmp scrldn_end scrldn_save: lda scr_row pha #1 lda scr_col pha #1 jmp scrldn1 scrldn_load: pla #1 sta scr_col pla #1 sta scr_row jsl update_pos scrldn_end: lda #0 sta wrapped scrldn_done: rtl scrl_up: dec scr_str dec scr_end lda #$1B ; Print an escape character sta $C001 ; to the screen. lda #$5B ; Print '[' sta $C001 ; to the screen, and start the escape sequence. lda #$53 ; Print 'S' sta $C001 ; to the screen, and end the escape sequence. lda scr_row pha #1 lda scr_col pha #1 lda #0 sta scr_row jsl rdrw_row pla #1 sta scr_col pla #1 sta scr_row jsl update_pos scrlup_done: rtl rdrw_row: lda #0 sta scr_col jsl update_pos rdrow_st: lda (ptr5), y beq rdrow_inc sta $C001 rdrow_inc: inc scr_col lda (ptr5), y beq rdrow_skip iny rdrow_inc1: lda scr_col cmp #80 bcs rdrow_end jmp rdrow_st rdrow_skip: jsl update_pos jmp rdrow_inc1 rdrow_end: lda #0 sta scr_col jsl update_pos rdrow_done: rtl ;rdrw_scr: ; lda #$C ; sta $C001 ; lda scr_col ; sta scr_tcol ; lda scr_row ; sta scr_trow ; lda #0 ; sta scr_col ; sta scr_row ; phy #2 ; jsl update_pos ; ply #2 ; ldx scr_ptr ; phy #2 ; txy ; lda (ptr), y ; sta $C001 ; ply #2 ; rtl result: lda.w #string2 ldx.w zero jsl print_str rset_x: lda #0 ; Reset a. tax ; Reset x. jmp print_buf ; Print the input buffer. dabbed: ldb #0 lda.w #tok sta.q ptr2 tba dab_st: phy #2 txy lda (ptr6), y ; Get a character from the input buffer. beq dab_pend ; Are we done with printing the buffer? cmp (ptr2), y beq chk_str jmp dab_pend chk_str: ply #2 inx cpx #3 bne dab_st ldx #0 pnt_msg: lda.w #msg ldx #0 stx.q ptr jsl print_str jmp dab_peqnd dab_pend: ply #2 lda #1 jmp dab_end dab_peqnd: lda #0 jmp dab_end dab_end: rtl print_buf: lda.w #cmd_buf jsl print_str lda.w zero cmd_clr: lda #10 jsl print_char jmp start .org $FFC0 .qword reset .org $FF50 .qword spin .qword spin .qword spin .qword spin .qword spin .qword spin .qword spin r ;.org $8000 ;v ;.org $8100 ;v ;.org $8200 ;v ;.org $8300 ;v ;.org $8400 ;v ;.org $8500 ;v ;q done