; SuBEditor. ; ; Writen in Sux assembly by ; mr b0nk 500 ; I/O constants. status = $C000 ; Keyboard status. scr = $C001 ; Character that is to be printed. kbd = $C002 ; Character from the Keyboard. step = $C010 ; Enables clock stepping, when set. ; Screen constants. maxrow = 23 ; Screen's row count. maxcol = 79 ; Screen's column count. ; Include SuBAsm. .include "subasm-2.s" .org $A000 ; String Literals/Constants. 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. bits: .byte $80 .byte $40 .byte $20 .byte $10 .byte $08 .byte $04 .byte $02 .byte $01 ; This label is for any included files. incl: ; Linewrap table. .org $1000 bitabl: .qword 0 .qword 0 ; Input buffer. .org $2000 buffer: .org $4000 cmd_buf: ; Screen variables. .org 0 scr_row: .byte 0 scr_col: .byte 0 scr_trow: .byte 0 scr_tcol: .byte 0 scr_ptr: .word 0 scr_ptr2: .word 0 scr_ptr3: .word 0 ; Pseudo registers. a: .byte 0 b: .byte 0 c: .byte 0 d: .byte 0 e: .byte 0 f: .byte 0 g: .byte 0 ; This pseudo register is always zero. zero: .qword 0 ; End of pseudo registers. end: .word 0 bitmask: .byte 0 scr_str: .byte 0 scr_end: .byte 0 wrapped: .byte 0 ; Pointers ptr: .qword 0 ptr2: .qword 0 ptr3: .qword 0 ; Main program .org $8000 reset: cps ; Reset the processor status register. ldx.w #$FFFF ; Reset the stack pointer. txs ; ldy #0 ; Reset the Y register. sty end ; tyx ; Reset the X register. lda #maxrow ; Set the end of the screen to the screen's max row count. sta scr_end ; tya ; Reset the Accumulator. sta scr_str ; Set the start of the screen back to zero. sta.q bitabl ; Reset the first half of the linewrap table. sta.q bitabl+8 ; Reset the second half of the linewrap table. inc end ; lda.w #$1FFF ; Set the clear count to $1FFF. sta.w scr_ptr ; lda.w #buffer ; Set the array to be cleared to the screen buffer. jsl clr_arr ; Clear the screen buffer. jmp start ; Goto the start of the main program. clr_arr: phb #1 ; Preserve whatever was in B. ldb #0 ; Clear B. jsl set_ptr ; Set the first pointer to the parameter. adc #8 ; Set the second pointer to the parameter, plus eight. inb ; Tell set_ptr to set the second pointer. jsl set_ptr ; deb ; Set B back to zero. tba ; clr_arr_st: cpy.w scr_ptr ; Did we clear all of the array? bcs clr_arr_end ; Yes, so we're done. sta.q (ptr), y ; No, so clear eight bytes. sta.q (ptr2), y ; Clear eight more bytes. tya ; Copy the array index. adc #$10 ; Increment the index by 16. tay ; Update the index. tba ; Reset the Accumulator. sta.q (ptr), y ; Do this one more time, to clear 32 bytes. sta.q (ptr2), y ; tya ; adc #$10 ; tay ; tba ; jmp clr_arr_st ; Keep looping. clr_arr_end: ldy.w zero ; Set the index back to zero. plb #1 ; Get whatever was in the B register, back. rtl ; End of clr_arr. start: lda #0 ; TODO: Update this for the Super VIA. sta status ; Clear the control register of the I/O adapter. tax ; Reset X. phy #2 ; Save the cursor index for later. tay ; Reset the cursor index. lda.w #$3FF ; Set the clear count to $3FF. sta.w scr_ptr ; lda.w #cmd_buf ; Set the array to be cleared to the command buffer. jsl clr_arr ; Clear the command buffer. ply #2 ; Get back the cursor index. lda.w #string ; Print the startup message. jsl print_str ; lsr #$10 ; Reset the Accumulator. sta end ; jmp read ; Start reading the keyboard. read: lda #0 ; Reset the Accumulator. sta end ; Disable the dummy flag. inc end ; Enable the dummy flag. lda status ; Did we get a key? beq read ; No, so try again. jsl getchar ; Yes, and was it a newline? beq parse ; Yes, so start parsing the line. jmp read ; No, so keep looping. print_str: sta.w end ; Save the parameter. print_str2: lda.w end ; Get the parameter. ldb #0 ; Clear the B register. jsl set_ptr ; Set the first pointer to the parameter. tba ; Clear the Accumulator. inb ; Enable replace mode. stb b ; pntstr_lp: lda.w ptr ; Get the first pointer. cmp.w end ; Did the pointer change? bne print_str2 ; Yes, so set it back. lsr #$10 ; No, reset the accumulator. phy #2 ; Save the cursor index. txy ; Copy the string index into Y. lda (ptr), y ; Are we at the end of the string? ply #2 ; Get the cursor index back. beq pntstr_end ; Yes, so we're done. inx ; No, so increment the string index. jsl print_char ; Print the character. jmp pntstr_lp ; Keep looping. pntstr_end: ldb #0 ; Enable insert mode. stb b ; rtl ; End of print_str. getbit: clc ; Clear the carry flag. lda scr_str ; Has the screen been scrolled? bne getbt0 ; Yes, so add the screen offset to the current line number. ldx scr_row ; No, so just use the current line number. jmp getbt1 ; Start getting the bit. getbt0: lda scr_row ; Get the current line number. adc scr_str ; Add the screen offset to it. tax ; Use it as the wrap index. getbt1: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.w #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; lsr #$10 ; Clear the Accumulator. pla #1 ; Get the return byte back. jsl bitpos ; Get the bit, and byte position. phy #2 ; Save the screen index. txy ; Get the byte position. ldb (ptr2), y ; Get one byte of the wrap table. ply #2 ; Get the screen index back. aba ; Mask out the bit of the current line number. cmp #1 ; Set the carry flag, if true. jmp bitout ; We are done. clrbit: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.w #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; lsr #$10 ; Clear the Accumulator. pla #1 ; Get the return byte back. jsl bitpos ; Get the bit, and byte position. xor #$FF ; Invert the bitmask. phy #2 ; Save the screen index. txy ; Get the byte position. ldb (ptr2), y ; Get one byte of the wrap table. aba ; Clear the bit of the current line number. bitsav: sta (ptr2), y ; Update the wrap table. ply #2 ; Get the screen index back. bitout: ldx bitmask ; Return the bitmask. rtl ; We are done. setbit: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.w #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; lsr #$10 ; Clear the Accumulator. pla #1 ; Get the return byte back. jsl bitpos ; Get the bit, and byte position. phy #2 ; Save the screen index. txy ; Get the byte position. ldb (ptr2), y ; Get one byte of the wrap table. oab ; Set the bit of the current line number. jmp bitsav ; Save the bit. bitpos: pha #1 ; Save the parameter. ldb #0 ; Make sure that set_ptr sets the first pointer. lda.w #bits ; Set the first pointer to the bitmask table. jsl set_ptr ; lsr #$10 ; Clear the Accumulator. pla #1 ; Get the parameter back. stx bitmask ; Make the line number the bitmask. txa ; Copy it to the Accumulator. and #7 ; Get the bit position. phy #2 ; Save the cursor index. tay ; Use the bit position as the index. tax ; Copy it into X. lda (ptr), y ; Get the bitmask. ply #2 ; Get back the cursor index. pha #1 ; Save the bitmask. lda bitmask ; Get the line number. lsr #3 ; Get the byte position. tax ; Copy it into X. pla #1 ; Get back the bitmask. rtl ; End of bitpos. getchar: lda kbd ; Get the character that was typed from the keyboard. ldb #0 ; Reset the B register. stb e ; Set the temporary row position to zero, in case we get a newline. stb b ; Enable insert mode. pha #1 ; Save the character. phy #2 ; Save the cursor index. cmp #'\n' ; Was the character that was typed, a newline? bne getchar_pnt ; No, so just print the character. jsl cmd_cpy ; Yes, so start copying the line to the command buffer. getchar_pnt: ply #2 ; Get back the cursor index. pla #1 ; Get back the character. ldb e ; Is the temporary row position non zero? bne reset_row ; Yes, so reset the row positon. getchar_pt1: jsl print_char ; No, so print the character. lda a ; Get the return value. cmp #'\n' ; Is the return value, a newline? beq getchar_ln ; Yes, so return 0. jmp getchar_chr ; No, so return 1. reset_row: ldb e ; Get the temporary row position. cpb #maxrow ; Is temporary row position, at, or above the bottom of the screen? beq reset_row2 ; Yes, so leave it as is. bcs reset_row1 ; No, so set it to the bottom of the screen. jmp reset_row2 ; Yes, so leave it as is. reset_row1: ldb #maxrow ; Set the row position to the bottom of the screen. reset_row2: stb scr_row ; Set the row position. jmp getchar_pt1 ; Print the character. getchar_ln: lda #0 ; Return zero. jmp getchar_end ; We are done. getchar_chr: lda #1 ; Return one. getchar_end: rtl ; End of get char. cmd_cpy: lda scr_row ; Get the row position. sta scr_trow ; Save it for later. jsl findend ; Find the end of the line. ldb scr_str ; Has the screen been scrolled? beq cmd_cpy3 ; No, so don't subtract the screen's starting point from the line number. cmd_cpy2: sec ; Yes, so make sure that we don't subtract by the starting point, plus one. sbc scr_str ; Offset the row position, back by the screen's starting point. clc ; Clear the carry flag, so that nothing odd occurs. cmd_cpy3: sta scr_row ; Set the row position to the end of the line. sta e ; Save it into the temporary row posiition. jsl findst ; Find the start of the line. clc ; Clear the carry flag. lda scr_row ; Get the row position. adc scr_str ; Add it with the screen's starting row. mul #maxcol+1 ; Multiply it with the width of the screen, plus one. tay ; Place it into the index. ldx.w #0 ; Reset the X register. ldb #0 ; Make sure that set_ptr sets the first pointer. lda.w #buffer ; Set the first pointer to the start of the screen buffer. jsl set_ptr ; inb ; Make sure that set_ptr sets the second pointer. lda.w #cmd_buf ; Set the second pointer to the start of the command buffer. jsl set_ptr ; deb ; Set B back to zero. tba ; Set the accumulator to zero. cmd_cpy_lp: ldb #0 ; Reset the B register. lda.q (ptr), y ; Get eight bytes from the current line. cmd_cpy_lp1: phy #2 ; Save the screen index. txy ; Get the command buffer index. sta (ptr2), y ; Copy one byte from the screen buffer, to the command buffer. inx ; Increment the command buffer index. ply #2 ; Get back the screen index. cpx.w #$3FF ; Are we at the end of the command buffer? bcs cmd_cpy_nd0 ; Yes, so we're done. iny ; No, so increment the screen index. inb ; Increment the byte count. lsr #8 ; Shift in the next byte. stb g ; Save the byte count. tab ; Save the string buffer. and #$FF ; Is this byte of the buffer, a null terminator? beq cmd_cpy_nd ; Yes, so we're done. tba ; No so get back the string buffer. ldb g ; Get back the byte count. cpb #7 ; Did we shift in eight bytes? beq cmd_cpy_lp ; Yes, so get eight more bytes. jmp cmd_cpy_lp1 ; No, so keep shifting in more bytes. cmd_cpy_nd0: ldb #0 ; Reset B. phy #2 ; Save the screen index. txy ; Get the command buffer index. stb (ptr2), y ; Terminate the command buffer. ply #2 ; Get back the screen index. cmd_cpy_nd: tab ; The B register is zero, so clear the Accumulator. rtl ; End of cmd_cpy. findst: lda #0 ; findst_lp: pha #1 ; jsl getbit ; pla #1 ; bcc findst_done ; inc ; dec scr_row ; bpo findst_lp ; dec ; inc scr_row ; findst_done: cmp #0 ; rtl ; fndend: phb #1 ; Save the contents of the B register. ldb #0 ; Make sure that set_ptr sets the first pointer. lda.w #buffer ; Set the first pointer to the start of the screen buffer. jsl set_ptr ; tba ; Set the Accumulator to zero. plb #1 ; Restore the contents of the B register. phy #2 ; fndend_lp: lda (ptr), y ; Are we at the end of the string? beq fndend_done ; Yes, so we're done. iny ; No, so increment the cursor index. jmp fndend_lp ; Keep looping. fndend_done: sty.w scr_ptr3 ; ply #2 ; rtl ; End of fndend. findend: jsl fndend ; lda.w scr_ptr3 ; div #maxcol+1 ; rtl ; parse: lda #0 ; tax ; jsl dabbed ; beq start ; lda #0 ; tax ; jmp result ; print_char: sta a ; Save the typed character for now. ldb #2 ; Make sure that set_ptr sets the third pointer. lda.w #buffer ; Set the third pointer to the start of the screen buffer. jsl set_ptr ; ldb #0 ; Set B to zero. tba ; Set the Accumulator to zero. lda a ; Get back the character. cmp #$1B ; Did the user type an escape character? beq esc ; Yes, so go check the escape code. cmp #'\n' ; No, but did the user type a newline? beq nl ; Yes, so handle the newline. cmp #$C ; No, but did the user type Ctrl+L? beq clr_scr ; Yes, so clear the screen. cmp #19 ; No, but did the user type Ctrl+S? beq en_step ; Yes, so enable clock/instruction stepping. cmp #18 ; No, but did the user type Ctrl+R? beq dis_step ; Yes, so disable clock/instruction stepping. cmp #'\b' ; No, but did the user type a backspace? beq bs ; Yes, so handle the backspace. cmp #$7F ; No, but did they type Delete? beq bs ; Yes, so treat it as a backspace. printc: lda #0 ; No, so start trying to print a character. sta d ; lda (ptr3), y ; Are we at the end of the string? beq printc_save ; Yes, so just print the character. lda b ; No, but was the flag set? bne printc_save ; Yes, so don't shift the line. sty.w scr_ptr ; No, so save the cursor index for later. jsl fndend ; jmp prntc_movln ; prntc_updt: lda scr_col ; sta scr_tcol ; prntc_updt2: jsl findend ; sta e ; sta scr_row ; jsl findst ; lda scr_row ; prntc_updt3: sta f ; jsl rdrw_ln ; lda scr_trow ; sta scr_row ; lda scr_tcol ; sta scr_col ; jsl update_pos ; dec d ; jmp printc_sav1 ; prntc_movln: ldy.w scr_ptr3 ; inc scr_ptr3 ; tyx ; dey ; ldb #1 ; stb d ; jsl shftln ; ldb #1 ; stb d ; lda a ; sta (ptr3), y ; store typed character into the input buffer. lda scr_row ; sta scr_trow ; jmp prntc_updt ; printc_save: ldb d ; bne prntc_updt ; printc_sav1: lda a ; sta (ptr3), y ; store typed character into the input buffer. printc_inc: inc scr_col ; Increment the cursor's x coordinate. iny ; printc_2: ldb #1 ; stb f ; ldb scr_col ; cpb #maxcol+1 ; bcs printc_4 ; printc_3: sta scr ; Echo typed character. ldb f ; beq printc_wrap ; jmp printc_end ; printc_4: ldb scr_row ; cpb #maxrow ; bcs printc_scrl ; printc_5: ldb #0 ; stb f ; jmp printc_3 ; printc_scrl: sta scr ; Echo typed character. clc ; lda #1 ; sta wrapped ; jsl scrl_down ; jmp printc_wrap ; printc_wrap: ldb #0 stb scr_col ; ldb scr_row ; cpb #maxrow ; bcs printc_wrp2 ; printc_wrap1: inc scr_row ; printc_wrp2: phx #2 ; clc ; lda scr_row ; adc scr_str ; tax ; jsl setbit ; plx #2 ; jsl update_pos ; printc_end: rtl ; nl: lda #0 ; ldb (ptr3), y ; bne nl1 ; sta (ptr3), y ; Store said terminator into the input buffer. nl1: sta scr_col ; lda scr_row ; cmp #maxrow ; bcc nl_inc ; jsl scrl_down ; jmp nl_end ; nl_inc: inc scr_row ; jsl update_pos ; nl_end: lda #'\n' ; sta a ; jmp printc_end ; clr_scr: lda #maxrow ; sta scr_end ; lda #0 ; sta scr_str ; sta.q bitabl ; sta.q bitabl+8 ; tay ; lda.w #$1FFF ; Set the clear count to $1FFF. sta.w scr_ptr ; lda.w #buffer ; Set the array to be cleared to the command buffer. jsl clr_arr ; Clear the screen buffer. tay ; lda.w #$3FF ; Set the clear count to $3FF. sta.w scr_ptr ; lda.w #buffer ; Set the array to be cleared to the command buffer. jsl clr_arr ; Clear the screen buffer. sta scr_col ; sta scr_row ; jsl update_pos ; lda #$C ; sta scr ; jmp printc_end ; en_step: lda step ; beq step_en ; jmp printc_end ; step_en: lda #1 ; sta step ; jmp printc_end ; dis_step: lda step ; bne step_dis ; jmp printc_end ; step_dis: lda #0 ; sta step ; jmp printc_end ; back: ldb #0 ; stb e ; stb f ; lda scr_row ; sta scr_trow ; jsl findend ; sta scr_row ; back0: jsl findst ; beq back1 ; bcs back_updt ; lda scr_trow ; sta scr_row ; back1: dey ; Decrement the buffer's offset. lda #0 ; Place a null terminator sta (ptr3), y ; into the buffer. tyx ; Copy the current cursor index to X. iny ; Increment cursor index. ldb #0 ; stb d ; jsl shftln ; Shift line back by one character. lda #$7F ; Print a backspace to the screen. sta scr ; lda e ; beq back3 ; back2: jsl findend ; sta e ; lda scr_col ; sta scr_tcol ; jsl rdrw_ln ; lda scr_tcol ; sta scr_col ; back3: lda scr_trow ; sta scr_row ; dec scr_col ; Move the cursor back by one column, jsl update_pos ; and update it's position. jmp printc_end ; We are done. back_updt: lda scr_row ; sta f ; inc e ; jmp back1 ; 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. ldb #maxcol+1 ; 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. shftln: ldb d ; Is the flag not set? beq shftln_lp1 ; Yes, so shift, and decrement. ldb #0 ; Clear the B register. jmp shftln_lp0 ; No, so shift, and increment. shftln_neg: ldy.w zero ; Set the source poition to 0. stb (ptr3), y ; Clear the character that is in the source. jmp shftln_end ; We are done. shftln_lp0: sty.w scr_ptr2 ; Save the source position for later. ldy.w scr_ptr ; Get the previous cursor index. cpy.w scr_ptr2 ; Is the source position, at, or below the cursor index? beq shftln_lp01 ; Yes, so keep looping. bcs shftln_end ; No, so we're done. shftln_lp01: ldy.w scr_ptr2 ; Get the source position. lda (ptr3), y ; Get the character from the source position. phy #2 ; Save the source position for later. txy ; Set our position to the destination. sta (ptr3), y ; Place the character from the source position, to the destination position. ply #2 ; Set our position back to the source. stb (ptr3), y ; Clear the character that is in the source. bng shftln_neg ; The source underflowed, so set it back to zero, dey ; Decrement the source position. dex ; Decrement the destination position. jmp shftln_lp0 ; Keep looping. shftln_lp1: stx.w scr_ptr2 ; Save the destination position for later. lda (ptr3), y ; Is the character at the source position, a null terminator? beq shftln_end1 ; Yes, so we're done. phy #2 ; No, so save the source position for later. txy ; Set our position to the destination. sta (ptr3), y ; Place the character from the source position, to the destination position. inx ; Increment the destination position. ply #2 ; Set our position back to the source. stb (ptr3), y ; Clear the character that is in the source. iny ; Increment the source position. jmp shftln_lp1 ; Keep looping. shftln_wrap: tax ; Use the ending line as a parameter for setbit. jsl setbit ; Set the wrap bit of the ending line. jmp shftln_end2 ; We are done. shftln_wrp1: tax ; Use the ending line as a parameter for clrbit. jsl clrbit ; Clear the wrap bit of the ending line. jmp shftln_end2 ; We are done. shftln_end: lda (ptr3), y ; Is this character a null terminator? bne shftln_nd0 ; No, so just find the end of the line. lda #$20 ; Yes, so convert it to a space for now. sta (ptr3), y ; shftln_nd0: jsl findend ; Find the ending line. sta d ; Save ending line for later. lda (ptr3), y ; Is this character a space? cmp #$20 ; bne shftln_nd1 ; No, so skip the conversion. lda #0 ; Yes, so convert it back to zero. sta (ptr3), y ; shftln_nd1: lda d ; Get the ending line. cmp scr_row ; Is the ending line greater than the starting line? beq shftln_end2 ; No, so we're done. bcs shftln_wrap ; Yes, so set the wrap bit. jmp shftln_end2 ; No, so we're done. shftln_end1: jsl findend ; Find the ending line. cpb #0 ; Is the remainder zero? beq shftln_nd2 ; Yes, so check if the ending line is greater than the starting line. jmp shftln_end2 ; No, so we're done. shftln_nd2: cmp scr_row ; Is the ending line greater than the starting line? beq shftln_end2 ; No, so we're done. bcs shftln_wrp1 ; Yes, so clear the wrap bit. shftln_end2: rtl ; End of shftln. esc: lda status ; Get the next character. lda kbd ; cmp #$1B ; Is this character an escape character? beq shftesc ; Yes, so check the other set of escape routines. lda status ; 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 kbd ; 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 ; Clear the D pseudo register. sta d ; jmp printc_end ; We are done. shftesc: lda status ; Skip the '['. lda kbd ; lda status ; Wait for the next character. beq printc_end ; We have an error, so discard it, and go back to getting user input. lda kbd ; Get the escape code. sta c ; Store the escape code, until we need it. lda #0 ; Use the D pseudo register as a skip flag. sta d ; jsl isshftup ; Check if the user pressed shift+up. lda d ; Was it successful? bne shftesc_end ; Yes, so we're done. jsl isshftdown ; No, so check if the user pressed shift+down. shftesc_end: lda #0 ; Clear the D pseudo register. sta d ; jmp printc_end ; We are done. isup: lda c ; Load the escape code into the accumulator. cmp #'A' ; Did the user press the up arrow key? bne isup_done ; No, so we're done. lda scr_row ; Yes, but 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 #'A' ; 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. lda #1 ; Tell the escape routine that we were successful. sta d ; isup_done: rtl ; End of isup. isdown: lda c ; Load the escape code into the accumulator. cmp #'B' ; Did the user press the down arrow key? bne isdown_done ; No, so we're done. lda scr_row ; Yes, so start checking the y coordinate of the cursor. cmp #maxrow ; Is the cursor at the bottom of the screen? beq isdown_scrl ; Yes, so scroll down. lda c ; No, so load the escape code back into the accumulator. cmp #'B' ; 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 ; lda #1 ; Tell the escape routine that we were successful. sta d ; isdown_done: rtl ; End of isdown. isright: lda c ; Load the escape code into the accumulator. cmp #'C' ; 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 #maxcol ; 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 #maxrow ; Are we at the bottom of the screen? beq isright_nd2 ; No, so we're done. bcs isright_scr ; Yes, so check if we are scrolling down. jmp isright_nd2 ; No, so we're 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 ; Load the escape code into the accumulator. cmp #'C' ; Did the user press right? beq isleft_done ; Yes, so we're done lda scr_col ; No, but 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 #'D' ; Did the user press the left arrow key? beq left ; Yes, so move the cursor left. jmp isleft_done ; No, so we're 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 we're done. wrap_dec: lda scr_row ; Is the cursor at the top of the screen? beq wrap_dec1 ; Yes, so don't move up a line. lda #1 ; No, so set the wrapped flag. sta wrapped ; dec scr_row ; Move the cursor up one line. wrap_dec1: lda #maxcol ; Move the Cursor to the far right of the screen. sta scr_col ; lda #1 ; Tell the escape routine that we were successful. 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 ; Move the cursor up a line. jsl update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; jmp isup_done ; We are done. down: inc scr_row ; Move the cursor down a line. jsl update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; jmp isdown_done ; We are done. right: inc scr_col ; Move the cursor right by one character. jsl update_pos ; Update it's position. jmp isright_dne ; We are done. left: dec scr_col ; Move the cursor left a character. jsl update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; jmp isleft_done ; We are done isshftup: lda c ; Load the escape code back into the accumulator. cmp #'A' ; Did the user press the up arrow key? bne shftup_done ; lda #1 ; sta d ; lda scr_str ; beq shftup_done ; jmp shftup ; shftup_done: rtl ; isshftdown: lda c ; Load the escape code back into the accumulator. cmp #'B' ; Did the user press the down arrow key? bne shftdn_done ; lda #1 ; sta d ; lda scr_end ; cmp #71 ; bcs shftdn_done ; jmp shftdown ; shftdn_done: rtl ; shftup: jsl scrl_up ; lda #1 ; sta d ; jmp shftup_done ; shftdown: jsl scrl_down ; lda #1 ; sta d ; jmp shftdn_done ; update_pos: ldb #1 ; Set the F pseudo register to one, to fix some bugs. stb f ; clc ; Clear the carry flag. lda scr_row ; Add the cursor's line number, adc scr_str ; with the starting line number to get the absolute line number. tay ; Place it in the Y regster for now. mul #maxcol+1 ; Multiply the line number by the screen's max column count, plus 1. adc scr_col ; Add the cursor's column number to get the screen index. tay ; Place the index into the Y register. lda #$1B ; Print an escape character sta scr ; to the screen. lda #'[' ; Print '[' sta scr ; 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 #'H' ; Print 'H' sta scr ; 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 #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. rtl ; End of getrow. getcol: lda #';' ; Print ';' sta scr ; to the screen. lda scr_col ; Get the cursor's x coordinate. div #10 ; Divide A by 10. clc adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. clc adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. rtl ; End of getrow. scrl_down: inc scr_str ; Increment the starting line of the screen. inc scr_end ; Increment the ending line of the screen. lda #$1B ; Print an escape character sta scr ; to the screen. lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. lda #'T' ; Print 'T' sta scr ; to the screen, and end the escape sequence. lda scr_row ; Get the cursor's line number. pha #1 ; Save it in the stack. lda wrapped ; Was the wrapped flag set? beq scrldn_save ; Yes, so save the cursor position. scrldn1: jsl rdrw_row ; Redraw this row. lda wrapped ; Was the wrapped flag set? beq scrldn_load ; Yes, so load the previous cursor position back. jmp scrldn_end ; No, so we're done. scrldn_save: lda scr_col ; Get the cursor's column number. pha #1 ; Save it in the stack. jmp scrldn1 ; Start redrawing the current row. scrldn_load: pla #1 ; Get the cursor's previous column number back. sta scr_col ; scrldn_end: pla #1 ; Get the cursor's previous line number back. sta scr_row ; jsl update_pos ; Update the cursor's position. lda #0 ; Clear the wrapped flag. sta wrapped ; scrldn_done: rtl ; End of scrl_down. scrl_up: dec scr_str ; dec scr_end ; lda #$1B ; Print an escape character sta scr ; to the screen. lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. lda #'S' ; Print 'S' sta scr ; 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 (ptr3), y ; beq rdrow_inc ; sta scr ; rdrow_inc: inc scr_col ; lda (ptr3), y ; beq rdrow_skip ; rdrow_inc1: iny ; rdrow_inc2: lda scr_col ; cmp #maxcol+1 ; bcs rdrow_end ; jmp rdrow_st ; rdrow_skip: lda #' ' ; sta scr ; to the screen. jmp rdrow_inc1 ; rdrow_end: lda #0 ; sta scr_col ; jsl update_pos ; rdrow_done: 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 ; Make sure that set_ptr is setting the first pointer. lda.w #cmd_buf ; Set the first pointer to the start of the command buffer. jsl set_ptr ; inb ; Make set_ptr set the second pointer. lda.w #tok ; Set the second pointer to the start of the token string. jsl set_ptr ; deb ; Set B back to zero. tba ; Also set the accumulator back to zero. dab_st: phy #2 ; txy ; lda (ptr), y ; Are we at the end of the string? beq dab_pend ; Yes, so return false. cmp (ptr2), y ; No, but is this character the same as the character in the token string? beq chk_str ; Yes, so increment the character count. jmp dab_pend ; No, so return false. chk_str: ply #2 ; inx ; cpx #3 ; bne dab_st ; ldx #0 ; pnt_msg: lda.w #msg ; ldx #0 ; 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 ; lsr #$10 ; Clear the Accumulator. cmd_clr: lda #'\n' ; jsl print_char ; jmp start ; rdrw_ln: lda scr_row ; pha #1 ; lda f ; sta scr_row ; lda scr_col ; pha #1 ; jsl update_pos ; rdrwln_lp: lda scr_row ; cmp e ; beq rdrwln_lp1 ; bcs rdrwln_done ; rdrwln_lp1: jsl rdrw_row ; rdrwln_inc: inc scr_row ; jmp rdrwln_lp ; rdrwln_done: pla #1 ; sta scr_col ; pla #1 ; sta scr_row ; jsl update_pos ; lda #0 ; sta e ; sta f ; rtl ; set_ptr: cpb #1 ; Are we setting the second pointer? beq set_ptr2 ; Yes, so start setting it. cpb #2 ; No, but are we setting the third pointer? beq set_ptr3 ; Yes, so start setting it. set_ptr1: sta.q ptr ; No, so set the first pointer. jmp setptr_end ; We are done. set_ptr2: sta.q ptr2 ; Set the second pointer. jmp setptr_end ; We are done. set_ptr3: sta.q ptr3 ; Set the third pointer. setptr_end: rtl ; End of set_ptr. ; Entry point for SuBAsm. parser: .org $FFC0 .qword reset a d