diff options
Diffstat (limited to 'programs')
-rw-r--r-- | programs/sub-suite/print_char.s | 147 | ||||
-rw-r--r-- | programs/sub-suite/subeditor-new.s | 1119 |
2 files changed, 1266 insertions, 0 deletions
diff --git a/programs/sub-suite/print_char.s b/programs/sub-suite/print_char.s new file mode 100644 index 0000000..e12461c --- /dev/null +++ b/programs/sub-suite/print_char.s @@ -0,0 +1,147 @@ +print_char: +; sta a ; Save the typed character for now. + pha ; 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. + pha.q ; Push the pointer onto the stack. + lda sp+9 ; Get the character back. +; 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 (sp+1), 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 ; + lda sp+9 ; + sta (sp+1), y ; store typed character into the input buffer. + lda scr_row ; + sta scr_trow ; + bra @update ; +@save: + ldb d ; + bne @update ; +@save1: +; lda a ; + lda sp+9 ; + sta (sp+1), 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: + pla.q ; Pull the pointer off the stack. + pla ; Pull the character off the stack. + and #0 ; Reset A. + rts ; + +nl: + lda #0 ; Reset A. + ldb (sp+1), y ; Is this character not a null terminator? + bne @scroll ; Yes, so don't overwrite it. + sta (sp+1), 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 ; diff --git a/programs/sub-suite/subeditor-new.s b/programs/sub-suite/subeditor-new.s new file mode 100644 index 0000000..6c1cfb1 --- /dev/null +++ b/programs/sub-suite/subeditor-new.s @@ -0,0 +1,1119 @@ +; SuBEditor. +; +; Writen in Sux assembly by +; mr b0nk 500 <b0nk@b0nk.xyz> + + +.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. |