; SuBEditor. ; ; Writen in Sux assembly by ; mr b0nk 500 .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. pha.w ; Push the clear count to the stack. lda.d #buffer ; Set the array to be cleared to the screen buffer. pha.q ; Push it on to the stack. jsr clr_arr ; Clear the screen buffer. pla.q ; Pull the pointer off of the stack. pla.w ; Pull the clear count off of the stack. and #0 ; Reset A. jsr pnt_strt ; Print the starting message. lda #$C ; Clear the screen. sta scr ; bra start ; Goto the start of the main program. clr_arr: phb ; Preserve whatever was in B. ldb #0 ; Clear B. clc ; Prepare for a non carrying add. adc #8 ; Set the second pointer to the parameter, plus eight. pha.q ; Push it onto the stack. tba ; @loop: cpy.w sp+26 ; Did we clear all of the array? bcs @end ; Yes, so we're done. sta.q (sp+18), y; No, so clear eight bytes. sta.q (sp+1), 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 (sp+18), y; Do this one more time, to clear 32 bytes. sta.q (sp+1), y ; tya ; adc #$10 ; tay ; tba ; bra @loop ; Keep looping. @end: ldy.w zero ; Set the index back to zero. pla.q ; Move the stack pointer back. tba ; Reset A. plb ; Get whatever was in the B register, back. rts ; End of clr_arr. pnt_strt: lda.w #ed_name ; Print the name of the editor. jsr print_str ; lda.w #ver_str ; Print the version text. jsr print_str ; lda.w #ed_ver ; Print the version number. jsr print_str ; lda.w #ed_sver ; Print the sub version number. jsr print_str ; lda #'\n' ; Print a newline. jsr print_char ; lda.w #made ; Print the "Created by" text. jsr print_str ; lda.w #author ; Print the name of the author. jsr print_str ; lda #'\n' ; Print a newline. jsr print_char ; rts ; End of pnt_strt. 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.w ; Save the cursor index for later. tay ; Reset the cursor index. lda.w #$3FF ; Set the clear count to $3FF. pha.w ; Push the clear count onto the stack. lda.d #cmd_buf ; Set the array to be cleared to the command buffer. pha.q ; Push the pointer onto the stack. jsr clr_arr ; Clear the command buffer. pla.q ; Pull the pointer off of the stack. pla.w ; Pull the clear count off of the stack. ply.w ; Get back the cursor index. and #0 ; Reset the Accumulator. sta end ; bra 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. jsr getchar ; Yes, and was it a newline? beq parse ; Yes, so start parsing the line. bra read ; No, so keep looping. parse: lda #0 ; tax ; jsr subasm ; bra start ; print_str: ldx #0 ; Reset X. pha.q ; Push the parameter onto the stack. @loop: ldb #1 ; Enable replace mode. stb b ; and #0 ; No, reset the accumulator. phy.w ; Save the cursor index. txy ; Copy the string index into Y. lda (sp+3), y ; Are we at the end of the string? ply.w ; Get the cursor index back. beq @end ; Yes, so we're done. inx ; No, so increment the string index. jsr print_char ; Print the character. bra @loop ; Keep looping. @end: pla.q ; Pull the parameter off the stack. ldb #0 ; Enable insert mode. stb b ; tba ; Reset A. rts ; 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. bra 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: tab ; Save the parameter. lda.d #bitabl ; Set the second pointer to the linewrap table. pha.q ; Push the pointer onto the stack. tba ; Get the parameter back. jsr bitpos ; Get the bit, and byte position. phy.w ; Save the screen index. txy ; Get the byte position. ldb (sp+3), y ; Get one byte of the wrap table. ply.w ; Get the screen index back. aba ; Mask out the bit of the current line number. cmp #1 ; Set the carry flag, if true. bra bitout ; We are done. clrbit: tab ; Save the parameter. lda.d #bitabl ; Set the second pointer to the linewrap table. pha.q ; Push the pointer onto the stack. tba ; Get the parameter back. jsr bitpos ; Get the bit, and byte position. xor #$FF ; Invert the bitmask. phy.w ; Save the screen index. txy ; Get the byte position. ldb (sp+3), y ; Get one byte of the wrap table. aba ; Clear the bit of the current line number. bitsav: sta (sp+3), y ; Update the wrap table. ply.w ; Get the screen index back. bitout: pla.q ; Pull the pointer off the stack. and #0 ; Reset A. ldx bitmask ; Return the bitmask. rts ; We are done. setbit: tab ; Save the parameter. lda.d #bitabl ; Set the second pointer to the linewrap table. pha.q ; Push the pointer onto the stack. tba ; Get the parameter back. jsr bitpos ; Get the bit, and byte position. phy.w ; Save the screen index. txy ; Get the byte position. ldb (sp+3), y ; Get one byte of the wrap table. oab ; Set the bit of the current line number. bra bitsav ; Save the bit. bitpos: tab ; Save the parameter. lda.w #bits ; Set the first pointer to the bitmask table. pha.q ; Push the pointer onto the stack. tba ; 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.w ; Save the cursor index. tay ; Use the bit position as the index. tax ; Copy it into X. lda (sp+3), y ; Get the bitmask. ply.w ; Get back the cursor index. pha ; Save the bitmask. lda bitmask ; Get the line number. lsr #3 ; Get the byte position. tax ; Copy it into X. pla ; Get back the bitmask. tab ; Preserve the bitmask. pla.q ; Pull the pointer off the stack. tba ; Get the bitmask back. rts ; 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 ; Save the character. phy.w ; Save the cursor index. cmp #'\n' ; Was the character that was typed, a newline? bne @print ; No, so just print the character. jsr cmd_cpy ; Yes, so start copying the line to the command buffer. @print: ply.w ; Get back the cursor index. pla ; Get back the character. ldb e ; Is the temporary row position non zero? bne @row ; Yes, so reset the row positon. @print1: jsr print_char ; No, so print the character. lda a ; Get the return value. cmp #'\n' ; Is the return value, a newline? beq @true ; Yes, so return true. bra @false ; No, so return false. @row: ldb e ; Get the temporary row position. cpb #maxrow ; Is temporary row position, at, or above the bottom of the screen? beq @row2 ; Yes, so leave it as is. bcs @row1 ; No, so set it to the bottom of the screen. bra @row2 ; Yes, so leave it as is. @row1: ldb #maxrow ; Set the row position to the bottom of the screen. @row2: stb scr_row ; Set the row position. bra @print1 ; Print the character. @true: lda #0 ; Return true. bra @end ; We are done. @false: lda #1 ; Return false. @end: rts ; End of getchar. cmd_cpy: lda scr_row ; Get the row position. sta scr_trow ; Save it for later. jsr findend ; Find the end of the line. ldb scr_str ; Has the screen been scrolled? beq @start ; No, so don't subtract the screen's starting point from the line number. @offset: 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. @start: sta scr_row ; Set the row position to the end of the line. sta e ; Save it into the temporary row posiition. jsr 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.d #buffer ; Set the first pointer to the start of the screen buffer. pha.q ; Push the pointer onto the stack. lda.d #cmd_buf ; Set the second pointer to the start of the command buffer. pha.q ; Push the pointer onto the stack. tba ; Set the accumulator to zero. @loop: ldb #0 ; Reset the B register. lda.q (sp+9), y ; Get eight bytes from the current line. @loop1: phy.w ; Save the screen index. txy ; Get the command buffer index. sta (sp+3), y ; Copy one byte from the screen buffer, to the command buffer. inx ; Increment the command buffer index. ply.w ; Get back the screen index. cpx.w #$3FF ; Are we at the end of the command buffer? bcs @end ; 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 @end1 ; 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 @loop ; Yes, so get eight more bytes. bra @loop1 ; No, so keep shifting in more bytes. @end: ldb #0 ; Reset B. phy.w ; Save the screen index. txy ; Get the command buffer index. stb (sp+3), y ; Terminate the command buffer. ply.w ; Get back the screen index. @end1: pla.q ; Pull one of the pointers off the stack. pla.q ; Pull the other pointer off the stack. tba ; The B register is zero, so clear the Accumulator. rts ; End of cmd_cpy. findst: lda #0 ; Reset A. @loop: pha ; Save the current line number. jsr getbit ; Is this the start of the line? pla ; Get the current line number back. bcc @end ; Yes, so we're done. inc ; No, so check the next physical line. dec scr_row ; Are we at the top of the screen? bpo @loop ; No, so keep looping. dec ; Yes, so move back one line. inc scr_row ; Put the row postiion back to zero. @end: cmp #0 ; Update all the flags. rts ; End of findst. fndend: lda.d #buffer ; Set the first pointer to the start of the screen buffer. pha.q ; Push the pointer onto the stack. phb ; Save the contents of the B register. ldb #0 ; Make sure that set_ptr sets the first pointer. tba ; Set the Accumulator to zero. plb ; Restore the contents of the B register. phy.w ; @loop: lda (sp+3), y ; Are we at the end of the string? beq @end ; Yes, so we're done. iny ; No, so increment the cursor index. bra @loop ; Keep looping. @end: sty.w scr_ptr3 ; ply.w ; pla.q ; Pull the pointer off the stack. and #0 ; Reset A. rts ; End of fndend. findend: jsr fndend ; lda.w scr_ptr3 ; div #maxcol+1 ; rts ; print_char: sta a ; Save the typed character for now. ldb #2 ; Make sure that set_ptr sets the third pointer. lda.d #buffer ; Set the third pointer to the start of the screen buffer. jsr 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 @save ; Yes, so just print the character. lda b ; No, but was the flag set? bne @save ; Yes, so don't shift the line. sty.w scr_ptr ; No, so save the cursor index for later. jsr fndend ; Find the end of the line. bra @shift ; Start shifting the line right. @update: lda scr_col ; Save the current column position for later. sta scr_tcol ; @update1: jsr findend ; Find the end of the line. sta e ; Use it for redrawing the line. sta scr_row ; Set the row position to to the end of the line. jsr findst ; Find the start of the line. lda scr_row ; Get the start of the line. @update2: sta f ; Set the starting line, to the start of the line. jsr rdrw_ln ; Redraw the line. lda scr_trow ; Get the real row position back. sta scr_row ; lda scr_tcol ; Get the real column position back. sta scr_col ; jsr update_pos ; Update the cursor's position. dec d ; bra @save1 ; @shift: ldy.w scr_ptr3 ; inc scr_ptr3 ; tyx ; dey ; ldb #1 ; stb d ; jsr shftln ; ldb #1 ; stb d ; lda a ; sta (ptr3), y ; store typed character into the input buffer. lda scr_row ; sta scr_trow ; bra @update ; @save: ldb d ; bne @update ; @save1: lda a ; sta (ptr3), y ; store typed character into the input buffer. @incr: inc scr_col ; Increment the cursor's x coordinate. iny ; @wrapped: ldb #1 ; stb f ; ldb scr_col ; cpb #maxcol+1 ; bcs @scrolled ; @print: sta scr ; Echo typed character. ldb f ; beq @wrap ; bra printc_end ; @scrolled: ldb scr_row ; cpb #maxrow ; bcs @scroll ; @wrapped2: ldb #0 ; stb f ; bra @print ; @scroll: sta scr ; Echo typed character. clc ; lda #1 ; sta wrapped ; jsr scrl_down ; @wrap: ldb #0 stb scr_col ; ldb scr_row ; cpb #maxrow ; bcs @wrap2 ; @wrap1: inc scr_row ; @wrap2: phx.w ; clc ; lda scr_row ; adc scr_str ; tax ; jsr setbit ; plx.w ; jsr update_pos ; printc_end: rts ; nl: lda #0 ; Reset A. ldb (ptr3), y ; Is this character not a null terminator? bne @scroll ; Yes, so don't overwrite it. sta (ptr3), y ; No, so overwrite it. @scroll: sta scr_col ; Move the cursor to the start of the next line. lda scr_row ; Get the row position. cmp #maxrow ; Are we at the bottom of the screen? bcc @incr ; No, so move down one line. jsr scrl_down ; Yes, so scroll down one line. bra @end ; We are done. @incr: inc scr_row ; Move the cursor down by one line. jsr update_pos ; Update the cursor's position. @end: lda #'\n' ; Print the newline. sta a ; rts ; 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. pha.w ; Push the clear count onto the stack. ; sta.w scr_ptr ; lda.d #buffer ; Set the array to be cleared to the screen buffer. pha.q ; Push the pointer onto the stack. jsr clr_arr ; Clear the screen buffer. tay ; pla.q ; Pull the pointer off of the stack. pla.w ; Pull the clear count off of the stack. lda.w #$3FF ; Set the clear count to $3FF. pha.w ; Push the clear count onto the stack. ; sta.w scr_ptr ; lda.d #cmd_buf ; Set the array to be cleared to the command buffer. pha.q ; jsr clr_arr ; Clear the screen buffer. pla.q ; Pull the pointer off of the stack. pla.w ; Pull the clear count off of the stack. and #0 ; Reset A. sta scr_col ; sta scr_row ; jsr update_pos ; lda #$C ; sta scr ; rts ; en_step: lda step ; beq step_en ; rts ; step_en: lda #1 ; sta step ; rts ; dis_step: lda step ; bne step_dis ; rts ; step_dis: lda #0 ; sta step ; rts ; bs: lda scr_col ; Are we at the far left of the screen? beq @wrap ; Yes, so check for a wrapped line. bra back ; No, so add the backspace to the buffer. @wrap: jsr getbit ; Is this line, a wrapped line? bcs @wrap1 ; Yes, so check if the cursor is at the top. rts ; No, so we're done. @wrap1: lda scr_row ; Are we at the top of the screen? beq @wrap2 ; Yes, so check if the screen is at the top of the buffer. bra @wrap3 ; No, so start clearing the wrap bit. @wrap2: lda scr_str ; Are we at the top of the buffer? bne @scroll ; Yes, so scroll up. rts ; No, so we're done. @scroll: clc ; Clear the carry flag, so that we don't get odd behaviour. jsr scrl_up ; Scroll up. inc scr_row ; Move down by one row. @wrap3: 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. @wrap4: dec scr_row ; Move up by one row. ldb #maxcol+1 ; Move the cursor to the absolute right of the screen. stb scr_col ; jsr update_pos ; Update the cursor's position. back: ldb #0 ; Reset B, and some flags. stb e ; stb f ; lda scr_row ; Save the current row position for later. sta scr_trow ; jsr findend ; Find the end of the line. sta scr_row ; Set our row position to the end of the line. @find_st: jsr findst ; Does this line take up more than one real line? beq @shift ; No, so skip updating any other lines. bcs @update ; Yes, so update the other lines. lda scr_trow ; Get the real row position back. sta scr_row ; @shift: 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 ; Set shifting direction to left. stb d ; jsr shftln ; Shift line back by one character. lda #$7F ; Print a backspace to the screen. sta scr ; lda e ; Are we updating more than one line? beq @load ; No, so skip to the next step. @find_end: jsr findend ; Yes, so find the end of the line. sta e ; Set the end parameter to it. lda scr_col ; Save the current column position for now. sta scr_tcol ; jsr rdrw_ln ; Start redrawing the line. lda scr_tcol ; Get the real column position back. sta scr_col ; @load: lda scr_trow ; Get the real row position back. sta scr_row ; dec scr_col ; Move the cursor back by one column, jsr update_pos ; and update it's position. rts ; We are done. @update: lda scr_row ; Set the line to start redrawing, to the start of the line. sta f ; inc e ; Set the redraw flag to true. bra @shift ; Start shifting the line back. shftln: ldb d ; Is the flag not set? beq @dec_loop ; Yes, so shift, and decrement. ldb #0 ; Clear the B register. bra @inc_loop ; No, so shift, and increment. @neg: ldy.w zero ; Set the source poition to 0. stb (ptr3), y ; Clear the character that is in the source. bra @end ; We are done. @inc_loop: 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 @inc_loop1 ; Yes, so keep looping. bcs @end ; No, so we're done. @inc_loop1: ldy.w scr_ptr2 ; Get the source position. lda (ptr3), y ; Get the character from the source position. phy.w ; 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.w ; Set our position back to the source. stb (ptr3), y ; Clear the character that is in the source. bng @neg ; The source underflowed, so set it back to zero, dey ; Decrement the source position. dex ; Decrement the destination position. bra @inc_loop ; Keep looping. @dec_loop: stx.w scr_ptr2 ; Save the destination position for later. lda (ptr3), y ; Is the character at the source position, a null terminator? beq @end3 ; Yes, so we're done. phy.w ; 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.w ; Set our position back to the source. stb (ptr3), y ; Clear the character that is in the source. iny ; Increment the source position. bra @dec_loop ; Keep looping. @wrap: tax ; Use the ending line as a parameter for setbit. jsr setbit ; Set the wrap bit of the ending line. bra @end5 ; We are done. @wrap1: tax ; Use the ending line as a parameter for clrbit. jsr clrbit ; Clear the wrap bit of the ending line. bra @end5 ; We are done. @end: lda (ptr3), y ; Is this character a null terminator? bne @end1 ; No, so just find the end of the line. lda #$20 ; Yes, so convert it to a space for now. sta (ptr3), y ; @end1: jsr findend ; Find the ending line. sta d ; Save ending line for later. lda (ptr3), y ; Is this character a space? cmp #$20 ; bne @end5 ; No, so skip the conversion. lda #0 ; Yes, so convert it back to zero. sta (ptr3), y ; @end2: lda d ; Get the ending line. cmp scr_row ; Is the ending line greater than the starting line? beq @end5 ; No, so we're done. bcs @wrap ; Yes, so set the wrap bit. bra @end5 ; No, so we're done. @end3: jsr findend ; Find the ending line. cpb #0 ; Is the remainder zero? beq @end4 ; Yes, so check if the ending line is greater than the starting line. bra @end5 ; No, so we're done. @end4: cmp scr_row ; Is the ending line greater than the starting line? beq @end5 ; No, so we're done. bcs @wrap1 ; Yes, so clear the wrap bit. @end5: rts ; 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 @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 ; jsr isup ; Check if the user pressed up. lda d ; Did the user press up? bne @end ; Yes, so we're done. jsr isdown ; No, so check if the user pressed down. lda d ; Did the user press down? bne @end ; Yes, so we're done. lda #0 ; No, so check if the user pressed left. jsr isleft ; lda d ; Did the user press left? bne @end ; Yes, so we're done. jsr isright ; No, so check if the user pressed right. @end: lda #0 ; Clear the D pseudo register. sta d ; rts ; We are done. shftesc: lda status ; Skip the '['. lda kbd ; lda status ; Wait for the next character. beq @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 ; jsr isshftup ; Check if the user pressed shift+up. lda d ; Was it successful? bne @end ; Yes, so we're done. jsr isshftdown ; No, so check if the user pressed shift+down. @end: lda #0 ; Clear the D pseudo register. sta d ; rts ; We are done. isup: lda c ; Load the escape code into the accumulator. cmp #'A' ; Did the user press the up arrow key? bne @end ; No, so we're done. lda scr_row ; Yes, but is the cursor at the top of the screen? beq @scroll ; Yes, so check if we need to scroll. @check2: 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. bra @end ; No, so we're done. @up: dec scr_row ; Move the cursor up a line. jsr update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; rts ; We are done. @scroll: lda scr_str ; Are we at the top of the screen buffer? beq @end ; Yes, so we're done. jsr scrl_up ; No, so scroll up. lda #1 ; Tell the escape routine that we were successful. sta d ; @end: rts ; End of isup. isdown: lda c ; Load the escape code into the accumulator. cmp #'B' ; Did the user press the down arrow key? bne @end ; 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 @scroll ; 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. bra @end ; No, so we're done. @down: inc scr_row ; Move the cursor down a line. jsr update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; rts ; We are done. @scroll: lda scr_row ; Save the cursor's row number. sta scr_trow ; lda scr_col ; Save the cursor's column number. sta scr_tcol ; jsr 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 ; @end: rts ; End of isdown. isright: lda c ; Load the escape code into the accumulator. cmp #'C' ; Did the user press the right arrow key? bne @end2 ; 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 @wrap ; Yes, so check if this is a wrapped line. bra @right ; No, so move the cursor right, like normal. @wrap: inc scr_row ; Move down a row. jsr getbit ; Is the current line, a wrapped line? bcs @incr ; Yes, so leave the cursor where it is. dec scr_row ; No, so move the cursor back up a row. bra @end2 ; We are done. @scroll: lda scr_str ; Are we at the top of the screen buffer? beq @end ; Yes, so we're done. lda #1 ; No, so scroll down. sta wrapped ; Set the wrapped flag. jsr scrl_down ; Scroll down. bra @end ; We are done. @incr: 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 @end1 ; No, so we're done. bcs @scroll ; Yes, so check if we are scrolling down. bra @end1 ; No, so we're done. @right: inc scr_col ; Move the cursor right by one character. jsr update_pos ; Update it's position. rts ; End of isright. @end: dec scr_row ; Move back up a row. @end1: jsr update_pos ; Update the cursor position. @end2: lda #0 ; Unset the wrapped flag. sta wrapped ; rts ; End of isright. isleft: lda c ; Load the escape code into the accumulator. cmp #'C' ; Did the user press right? beq @end1 ; Yes, so we're done lda scr_col ; No, but is the cursor at the far left of the screen? beq @wrap ; 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. bra @end1 ; No, so we're done. @wrap: jsr getbit ; Is the current line, a wrapped line? bcs @decr ; Yes, so wrap back up a line. bra @end1 ; No, so we're done. @decr: lda scr_row ; Is the cursor at the top of the screen? beq @decr1 ; 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. @decr1: 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 @scroll ; Yes, so check if we need to scroll. bra @end ; No, so we're done. @scroll: lda wrapped ; Was the wrapped flag set somewhere else? bne @end ; Yes so we're done. lda scr_str ; No, but are we actually at the top of the screen buffer? beq @end1 ; Yes, so we're done. jsr scrl_up ; No, so scroll up. bra @end1 ; We are done. @left: dec scr_col ; Move the cursor left a character. jsr update_pos ; Update it's position. lda #1 ; Tell the escape routine that we succeded. sta d ; rts ; We are done @end: jsr update_pos ; Update the cursor position. @end1: lda #0 ; Unset the wrapped flag. sta wrapped ; rts ; End of isleft. isshftup: lda c ; Load the escape code back into the accumulator. cmp #'A' ; Did the user press the up arrow key? bne @end ; lda #1 ; sta d ; lda scr_str ; beq @end ; @shftup: jsr scrl_up ; lda #1 ; sta d ; @end: rts ; isshftdown: lda c ; Load the escape code back into the accumulator. cmp #'B' ; Did the user press the down arrow key? bne @end ; lda #1 ; sta d ; lda scr_end ; cmp #71 ; bcs @end ; @shftdown: jsr scrl_down ; lda #1 ; sta d ; @end: rts ; 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. clc ; Clear the carry flag. adc scr_col ; Add the cursor's column number to get the screen index. tay ; Place the index into the Y register. tba ; Reset A. lda #$1B ; Print an escape character sta scr ; to the screen. lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. jsr getrow ; Start printing the row number to the screen. jsr getcol ; Start printing the column number to the screen. lda #'H' ; Print 'H' sta scr ; to the screen. rts ; End of update_pos. getrow: lda scr_row ; Get the cursor's y coordinate. bra bcd ; Convert it to BCD. getcol: lda #';' ; Print ';' sta scr ; to the screen. lda scr_col ; Get the cursor's x coordinate. bcd: div #10 ; Divide A by 10. ora #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. ora #'0' ; Convert it to ascii, and sta scr ; print to the screen. rts ; End of bcd. 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 ; Save it in the stack. lda wrapped ; Was the wrapped flag set? beq @save ; Yes, so save the cursor position. @redraw: jsr rdrw_row ; No, so redraw this row. lda wrapped ; Was the wrapped flag set? beq @load ; Yes, so load the previous cursor position back. bra @end ; No, so we're done. @save: lda scr_col ; Get the cursor's column number. pha ; Save it in the stack. bra @redraw ; Start redrawing the current row. @load: pla ; Get the cursor's previous column number back. sta scr_col ; @end: pla ; Get the cursor's previous line number back. sta scr_row ; jsr update_pos ; Update the cursor's position. lda #0 ; Clear the wrapped flag. sta wrapped ; @end1: rts ; 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 ; lda scr_col ; pha ; lda #0 ; sta scr_row ; jsr rdrw_row ; pla ; sta scr_col ; pla ; sta scr_row ; jsr update_pos ; @end: rts ; rdrw_row: lda #0 ; sta scr_col ; jsr update_pos ; @loop: lda (ptr3), y ; beq @incr ; sta scr ; @incr: inc scr_col ; lda (ptr3), y ; beq @skip ; @incr1: iny ; @incr2: lda scr_col ; cmp #maxcol+1 ; bcs @end ; bra @loop ; @skip: lda #' ' ; sta scr ; to the screen. bra @incr1 ; @end: lda #0 ; sta scr_col ; jsr update_pos ; @end1: rts ; rdrw_ln: lda scr_row ; pha ; lda f ; sta scr_row ; lda scr_col ; pha ; jsr update_pos ; @loop: lda scr_row ; cmp e ; beq @loop1 ; bcs @end ; @loop1: jsr rdrw_row ; @incr: inc scr_row ; bra @loop ; @end: pla ; sta scr_col ; pla ; sta scr_row ; jsr update_pos ; lda #0 ; sta e ; sta f ; rts ; set_ptr: cpb #1 ; Are we setting the second pointer? beq @ptr2 ; Yes, so start setting it. cpb #2 ; No, but are we setting the third pointer? beq @ptr3 ; Yes, so start setting it. @ptr1: stb.q ptr ; Reset the first pointer. sta.q ptr ; No, so set the first pointer. bra @end ; We are done. @ptr2: stb.q ptr2 ; Reset the second pointer. sta.q ptr2 ; Set the second pointer. bra @end ; We are done. @ptr3: stb.q ptr3 ; Reset the third pointer. sta.q ptr3 ; Set the third pointer. @end: rts ; End of set_ptr.