; 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 Y. tyx ; Reset X. jsr clr_scr ; Clear the screen. jsr pnt_strt ; Print the starting message. bra start ; Goto the start of the main program. clr_arr: phb ; Preserve whatever was in B. ldb #0 ; Clear B. jsr 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. jsr set_ptr ; deb ; Set B back to zero. tba ; @loop: cpy.w scr_ptr ; Did we clear all of the array? bcs @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 ; bra @loop ; Keep looping. @end: ldy.w zero ; Set the index back to zero. 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. clr_cmd: and #0 ; Reset A. tay ; Reset Y. lda.w #$3FF ; Set the clear count to $3FF. sta.w scr_ptr ; lda.d #cmd_buf ; Set the array to be cleared to the command buffer. jsr clr_arr ; Clear the command buffer. rts ; End of clr_cmd. start: lda #0 ; TODO: Update this for the Super VIA. sta status ; Clear the control register of the I/O adapter. tax ; Reset X. jsr clr_cmd ; Clear the command buffer. jsr update_ptr ; Get the screen buffer index. tay ; Save it in Y. and #0 ; Reset the Accumulator. bra read ; Start reading the keyboard. read: jsr getchar ; Get a character. jsr handle_char ; Send the character to the handler routine. beq parse ; The handled character was a newline, so start parsing. bra read ; Keep looping. parse: and #0 ; Reset A. tax ; Reset X. jsr subasm ; Call SuBAsm, and start parsing this line. bra start ; Go back to reading the keyboard. getchar: and #0 ; Reset A. @loop: lda status ; Did we get a key? beq @loop ; No, so try again. lda kbd ; Yes, so get the typed character. @end: rts ; End of getchar. print_str: ldx #0 ; Reset X. sta.q end ; Save the parameter. @reset: lda.q end ; Get the parameter. ldb #0 ; Clear the B register. jsr set_ptr ; Set the first pointer to the parameter. tba ; Clear the Accumulator. @loop: ldb #1 ; Enable replace mode. stb regb ; lda.q ptr ; Get the first pointer. cmp.q end ; Did the pointer change? bne @reset ; Yes, so set it back. and #0 ; No, reset the accumulator. txy ; Copy the string index into Y. ldb (ptr), y ; Are we at the end of the string? beq @end ; Yes, so we're done. jsr update_ptr ; No, so get the screen buffer index. tay ; Save it in Y. tba ; Get the character back. inx ; Increment the string index. phx ; Preserve the string index. jsr print_char ; Print the character. plx ; Get the string index back. bra @loop ; Keep looping. @end: ldb #0 ; Enable insert mode. stb regb ; 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: pha ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.d #bitabl ; Set the second pointer to the linewrap table. jsr set_ptr ; lsr #$10 ; Clear the Accumulator. pla ; Get the return byte back. jsr bitpos ; Get the bit, and byte position. phy.w ; Save the screen index. txy ; Get the byte position. ldb (ptr2), y ; Get one byte of the wrap table. ply.w ; Get the screen index back. and b ; Mask out the bit of the current line number. cmp #1 ; Set the carry flag, if true. bra bitout ; We are done. clrbit: pha ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.d #bitabl ; Set the second pointer to the linewrap table. jsr set_ptr ; and #0 ; Clear the Accumulator. pla ; Get the return byte 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 (ptr2), y ; Get one byte of the wrap table. and b ; Clear the bit of the current line number. bitsav: sta (ptr2), y ; Update the wrap table. ply.w ; Get the screen index back. bitout: ldx bitmask ; Return the bitmask. rts ; We are done. setbit: pha ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. lda.d #bitabl ; Set the second pointer to the linewrap table. jsr set_ptr ; and #0 ; Clear the Accumulator. pla ; Get the return byte back. jsr bitpos ; Get the bit, and byte position. phy.w ; Save the screen index. txy ; Get the byte position. ldb (ptr2), y ; Get one byte of the wrap table. ora b ; Set the bit of the current line number. bra bitsav ; Save the bit. bitpos: pha ; 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. jsr set_ptr ; and #0 ; Clear the Accumulator. pla ; 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 (ptr), 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. rts ; End of bitpos. handle_char: ldb #0 ; Reset the B register. stb rege ; Set the temporary row position to zero, in case we get a newline. stb regb ; 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 rege ; 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 rega ; 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 rege ; 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 handle_char. 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 rege ; 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. jsr set_ptr ; inb ; Make sure that set_ptr sets the second pointer. lda.d #cmd_buf ; Set the second pointer to the start of the command buffer. jsr set_ptr ; deb ; Set B back to zero. tba ; Set the accumulator to zero. @loop: ldb #0 ; Reset the B register. lda.q (ptr), y ; Get eight bytes from the current line. @loop1: phy.w ; 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.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 regg ; 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 regg ; 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 (ptr2), y ; Terminate the command buffer. ply.w ; Get back the screen index. @end1: tab ; 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: phb ; Save the contents of the B 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. jsr set_ptr ; tba ; Set the Accumulator to zero. plb ; Restore the contents of the B register. phy.w ; @loop: lda (ptr), 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 ; rts ; End of fndend. findend: jsr fndend ; lda.w scr_ptr3 ; div #maxcol+1 ; rts ; print_char: sta rega ; Preserve the character. 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 ; deb ; Set B to one. tba ; Reset A. lda rega ; Get the character back. jsr get_ctrlidx ; Get the control code jump table index. lsl #1 ; Multiply the return value by two, to get the index. tax ; lda.w ct_jtb, x ; Get the address of the control code handler. jsr set_ptr ; Set the second pointer to the control code handler. deb ; Reset B. tba ; Reset A. jmp (ptr2) ; Jump to the handler for that control code. printc: lda #0 ; start trying to print a character. sta regd ; lda (ptr3), y ; Are we at the end of the string? beq @save ; Yes, so just print the character. lda regb ; 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 rege ; Use it for redrawing the line. lda scr_trow ; Get the current row position. @update2: sta regf ; Set the starting line, to the current row position. 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 regd ; bra @save1 ; @shift: ldy.w scr_ptr3 ; inc scr_ptr3 ; tyx ; dey ; ldb #1 ; stb regd ; jsr shftln ; ldb #1 ; stb regd ; lda rega ; sta (ptr3), y ; store typed character into the input buffer. lda scr_row ; sta scr_trow ; bra @update ; @save: ldb regd ; bne @update ; @save1: lda rega ; 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 regf ; ldb scr_col ; cpb #maxcol+1 ; bcs @scrolled ; @print: sta scr ; Echo typed character. ldb regf ; beq @wrap ; bra printc_end ; @scrolled: ldb scr_row ; cpb #maxrow ; bcs @scroll ; @wrapped2: ldb #0 ; stb regf ; 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 rega ; 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. sta.w scr_ptr ; lda.d #buffer ; Set the array to be cleared to the screen buffer. jsr clr_arr ; Clear the screen buffer. ; tay ; ; lda.w #$3FF ; Set the clear count to $3FF. ; sta.w scr_ptr ; ; lda.d #cmd_buf ; Set the array to be cleared to the command buffer. ; jsr clr_arr ; Clear the screen buffer. 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 rege ; stb regf ; 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 regd ; jsr shftln ; Shift line back by one character. lda #$7F ; Print a backspace to the screen. sta scr ; lda rege ; 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 rege ; 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 (ptr3), y ; Are we at the end of the line? beq @shift ; Yes, so skip redrawing. lda scr_trow ; No, so set the line to start redrawing, to the line that the cursor is on. sta regf ; inc rege ; Set the redraw flag to true. bra @shift ; Start shifting the line back. shftln: ldb regd ; 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 regd ; 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 regd ; 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 regc ; Store the escape code, until we need it. lda #0 ; Set the D pseudo register to zero. sta regd ; jsr isup ; Check if the user pressed up. lda regd ; Did the user press up? bne @end ; Yes, so we're done. jsr isdown ; No, so check if the user pressed down. lda regd ; 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 regd ; 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 regd ; 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 regc ; Store the escape code, until we need it. lda #0 ; Use the D pseudo register as a skip flag. sta regd ; jsr isshftup ; Check if the user pressed shift+up. lda regd ; 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 regd ; rts ; We are done. isup: lda regc ; 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 regc ; 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 regd ; 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 regd ; @end: rts ; End of isup. isdown: lda regc ; 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 regc ; 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 regd ; 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 regd ; @end: rts ; End of isdown. isright: lda regc ; 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 regc ; 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 regc ; 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 regd ; 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 regd ; 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 regc ; Load the escape code back into the accumulator. cmp #'A' ; Did the user press the up arrow key? bne @end ; lda #1 ; sta regd ; lda scr_str ; beq @end ; @shftup: jsr scrl_up ; lda #1 ; sta regd ; @end: rts ; isshftdown: lda regc ; Load the escape code back into the accumulator. cmp #'B' ; Did the user press the down arrow key? bne @end ; lda #1 ; sta regd ; lda scr_end ; cmp #71 ; bcs @end ; @shftdown: jsr scrl_down ; lda #1 ; sta regd ; @end: rts ; update_ptr: 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. 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. ; cmp.w #$2000 ; Is the index greater than, or equal to the end of the screen buffer? ; bcc @end ; No, so we're done. ;@wrap: ; and #0 ; Reset the screen's starting line. ; sta scr_str ; ; sta regf ; Setup the starting line for rdrw_ln. ; lda #maxrow ; Reset the screen's ending line. ; sta scr_end ; ; sta rege ; Setup the ending line for rdrw_ln. ; jsr rdrw_ln ; Redraw the entire screen. ; bra update_ptr ; Get the screen index. @end: rts ; End of update_ptr. update_pos: ldb #1 ; Set the F pseudo register to one, to fix some bugs. stb regf ; jsr update_ptr ; Update the screen buffer 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. lda #';' ; Print ';' sta scr ; to the screen. jsr getcol ; Start printing the column number to the screen. lda #'H' ; Print 'H' sta scr ; to the screen. ;inc step ; rts ; End of update_pos. getrow: lda scr_row ; Get the cursor's y coordinate. bra bcd ; Convert it to BCD. getcol: lda scr_col ; Get the cursor's x coordinate. bcd: inc ; Add one to A. 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 regf ; sta scr_row ; lda scr_col ; pha ; jsr update_pos ; @loop: lda scr_row ; cmp rege ; 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 rege ; sta regf ; 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.