From 2cc6587b5cfa46350795b00f79fad504f315fd29 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 9 Oct 2019 18:45:37 +0200 Subject: [PATCH] CHROUT screen output routine split, size and performance optimizations --- c64/kernal/chrout_screen.s | 537 +----------------- c64/kernal/screen/chrout_screen_control.s | 206 +++++++ c64/kernal/screen/chrout_screen_del.s | 63 ++ c64/kernal/screen/chrout_screen_ins.s | 64 +++ c64/kernal/screen/chrout_screen_quote.s | 20 + .../screen/screen_calculate_line_pointer.s | 54 ++ c64/kernal/screen/screen_grow_logical_line.s | 122 ++++ c64/kernal/screen/screen_normalize_xy.s | 82 +++ 8 files changed, 627 insertions(+), 521 deletions(-) create mode 100644 c64/kernal/screen/chrout_screen_control.s create mode 100644 c64/kernal/screen/chrout_screen_del.s create mode 100644 c64/kernal/screen/chrout_screen_ins.s create mode 100644 c64/kernal/screen/chrout_screen_quote.s create mode 100644 c64/kernal/screen/screen_calculate_line_pointer.s create mode 100644 c64/kernal/screen/screen_grow_logical_line.s create mode 100644 c64/kernal/screen/screen_normalize_xy.s diff --git a/c64/kernal/chrout_screen.s b/c64/kernal/chrout_screen.s index 6e4b0ac5..c516dcf4 100644 --- a/c64/kernal/chrout_screen.s +++ b/c64/kernal/chrout_screen.s @@ -14,285 +14,24 @@ chrout_screen: lda SCHAR tax - // Check for special characters + // All the PETSCII control codes are within $0x, $1x, $8x, $9x, remaining + // ones are always printable characters; separate away control codes - cmp #$00 - bne not_00 - jmp chrout_done -not_00: - - // Linefeed (simply ignored) - // Trivia: BASIC does CRLF with READY. prompt - cmp #$0a - bne not_0a - jmp chrout_done -not_0a: - - // Carriage return - cmp #$0d - bne not_0d - // RETURN clears quote and insert modes, it also clears reverse flag - lda #$00 - sta QTSW - sta INSRT - sta RVS - jmp screen_advance_to_next_line -not_0d: - - cmp #$94 - bne not_94 - - // Insert (shift-DELETE) - - // Abort if line already max length, ie 79th char is not a space - jsr get_current_line_logical_length - cmp #79 - bne definitely_not_too_long - tay - lda (PNT),y - cmp #$20 - beq definitely_not_too_long - - // Line is too long to extend - jmp chrout_done - -definitely_not_too_long: - // Work out if line needs to be expanded, and if so expand it - ldy #39 - lda (PNT),y - cmp #$20 - beq no_need_to_extend - - jsr screen_grow_logical_line - -no_need_to_extend: - // Shuffle chars towards end of line - jsr get_current_line_logical_length - tay -!: - // Note: While the following routine is obvious to any skilled - // in the art as the most obvious simple and efficient solution, - // if the screen writes are before the colour writes, it results - // in a relatively long verbatim stretch of bytes when compared to - // the C64 KERNAL. Thus we have swapped the order, just to reduce - // the potential for any argument of copyright infringement, even - // though we really don't believe that the routine can be copyrighted - // due to the lack of creativity. - dey - lda (USER),y - iny - sta (USER),y - dey - lda (PNT),y - iny - sta (PNT),y - - dey - cpy PNTR - bne !- - - // Increase insert mode count (which causes quote-mode like behaviour) - inc INSRT - - // Put space in the inserted gap - lda #$20 - sta (PNT),y - - jmp chrout_done -not_94: - - // DELETE in insert mode embeds control character - ldx INSRT - bne not_14 - - cmp #$14 - bne not_14 - - // Delete - ldx PNTR - bne delete_non_zero_column -delete_at_column_0: - ldy TBLX - bne not_row_0 - // delete from row 0, col 0 does nothing - jmp chrout_done -not_row_0: - // Column 0 delete just moves us to the end of the - // previous line, without actually deleting anything - dec TBLX - jsr get_current_line_logical_length - lda LNMX - - sta PNTR - jsr calculate_screen_line_pointer - jmp chrout_done - -delete_non_zero_column: - // Copy rest of line down - jsr get_current_line_logical_length - ldy PNTR - cpy LNMX - beq done_delete - dey -!: - iny - lda (PNT),y - dey - sta (PNT),y - iny - lda (USER),y - dey - sta (USER),y - iny - cpy LNMX - bne !- - - // Clear char at end of line - jsr get_current_line_logical_length - tay - lda #$20 - sta (PNT),y - -done_delete: - dec PNTR - jmp chrout_done -not_14: - - // Check for quote mode - ldx QTSW - bne is_quote_mode - ldx INSRT - bne is_quote_mode - jmp not_quote_mode - -is_quote_mode: - // Is it a control code? - // control codes are $00-$1f and $80-$9f - // (from reading C64 PRG p379-381) - // so we can just check if bits 5 or 6 are set, and if so, - // then it isn't a control character. - pha and #$60 bne !+ - - // Yes, a control code in quote mode means we display it as a reverse character - pla - - // Low control codes are just +$80 - clc - adc #$80 - // If it overflowed, then it is a high control code, - // so we need to make it be $80 + $40 + char - // as we will have flipped back to just $00 + char, we should - // now add $c0 if C is set from overflow - bcc low_ctrl_char - adc #$bf // C=1, so adding $BF + C = add $C0 -low_ctrl_char: - jmp output_literal_char + jmp chrout_screen_control !: - pla -not_quote_mode: + txa - // Check for colours - ldx #$f -colour_check_loop: - cmp colour_codes,x - bne !+ - stx COLOR - jmp chrout_done -!: dex - bpl colour_check_loop - - // Compute's Mapping the 64 p38 - cmp #$12 - bne not_12 - lda #$80 - sta RVS - jmp chrout_done -not_12: - // Compute's Mapping the 64 p 38 - cmp #$92 - bne not_92 - lda #$00 - sta RVS - jmp chrout_done -not_92: - - // Check for cursor movement keys - cmp #$11 - bne not_11 - lda PNTR - clc - adc #40 - sta PNTR - // We need to advance the pointer manually, as normalising - // now will break things. The pointer update is required - // so that we can tell if we really are on the bottom phys - // screen line or not - jsr scroll_up_if_on_last_line - jsr calculate_screen_line_pointer - jmp chrout_done -not_11: - cmp #$1d - bne not_1d - inc PNTR - jsr calculate_screen_line_pointer - jmp chrout_done -not_1d: - cmp #$91 - bne not_91 - lda PNTR - sec - sbc #40 - sta PNTR - jsr calculate_screen_line_pointer - jmp chrout_done -not_91: - cmp #$9d - bne not_9d - lda TBLX - ora PNTR - beq !+ // branch if top-left screen character - dec PNTR - jsr calculate_screen_line_pointer -!: - jmp chrout_done -not_9d: - - // Home cursor - cmp #$13 - bne not_13 - lda #0 - sta PNTR - sta TBLX - jsr calculate_screen_line_pointer - jmp chrout_done -not_13: - - // Clear screen - cmp #$93 - bne not_clearscreen - jsr clear_screen - jmp chrout_done - -not_clearscreen: - - // Convert PETSCII to screen code - - // Don't print other control codes - cmp #$1f - bcs !+ - jmp chrout_done -!: + // Literals - first convert PETSCII to screen code // Codes $C0-$DF become $40-$5F - // But - cmp #$e0 + cmp #$E0 bcs !+ - cmp #$c0 + cmp #$C0 bcc !+ - and #$7f + and #$7F jmp output_literal_char // not high char !: @@ -368,127 +107,9 @@ not_quote: no_screen_advance_to_next_line: jmp chrout_done -screen_grow_logical_line: - ldy TBLX - // Don't grow line if it is already grown - lda LDTBL,y - bpl !+ - jmp not_last_line // doneb grow line -!: - lda #$80 - sta LDTBL,y - // Now make space for the extra line added. - // If we are on the last physical line of the screen, - // Then we need to scroll the screen up - jsr scroll_up_if_on_last_line - - // Scroll screen down to make space - // As we are scrolling down, we start from the end, - // and work backwards. We can't be as simple and efficient - // here as we are for scrolling up, because we don't know - // how much must be scrolled. - // Simple solution is to work out how many physical lines - // need shifting down, and then move lines at a time after - // initialising the pointers to the end area of the screen. - ldx #25-2 - ldy #0 -count_rows_loop: - dex - lda LDTBL,y - bpl !+ - dex -!: iny - cpy TBLX - bne count_rows_loop - cpx #0 - beq no_copy_down - bmi no_copy_down - - // Set pointers to end of screen line, and one line - // above. (It is always one physical line, because - // this can only happen when expanding a line from 40 to - // 80 characters). - // XXX - This is not very efficient, and longer than it - // needs to be. Better would be to work out size to - // copy, and count it down in a pointer somewhere, so - // that loop iteration logic is simpler. - lda HIBASE - clc - adc #3 - sta PNT+1 - sta SAL+1 - lda #>$DBC0 - sta EAL+1 - sta USER+1 - lda #<$03C0 - sta PNT+0 - sta USER+0 - // souce address is line above - sec - sbc #40 - sta SAL+0 - sta EAL+0 - -copy_line_down_loop: - ldy #39 -cl_inner: - lda (EAL),y - sta (USER),y - lda (SAL),y - sta (PNT),y - dey - bpl cl_inner - - // Decrement all pointers by 40 - // Low bytes are in common pairs - - // Old source is new destination - // Use different registers to minimise byte similarity with C64 KERNAl - ldy SAL+1 - sty PNT+1 - lda EAL+1 - ldy SAL+0 - sta USER+1 - sty PNT+0 - sty USER+0 - - // Decrementing source pointers - lda SAL+0 - sec - sbc #<40 - sta SAL+0 - sta EAL+0 - lda SAL+1 - sbc #>40 - sta SAL+1 - // convert to screen equivalent - sec - sbc HIBASE - clc - adc #>$D800 - sta EAL+1 - - dex - bne copy_line_down_loop - -no_copy_down: - jsr calculate_screen_line_pointer - - // Erase newly inserted line - ldy #79 -!: - lda COLOR - sta (USER),y - lda #$20 - sta (PNT),y - dey - cpy #40 - bne !- - - rts not_last_line: rts @@ -607,6 +228,14 @@ link_copy: rts + + + + + + + + get_current_line_logical_length: ldy TBLX lda LDTBL,y @@ -663,138 +292,4 @@ screen_advance_to_next_line: !: jsr calculate_screen_line_pointer - jmp chrout_done - -add_40_to_screen_x: - lda PNTR - clc - adc #40 - sta PNTR - rts - -normalise_screen_x_y: - // Normalise X and Y values - - // If X < 0, then make X = X + 40 (or 80, if previous line is linked) -!: lda PNTR - bpl x_not_negative - dec TBLX - // Check that we didn't go backwards off the top of the screen - bpl !+ - lda #0 - sta TBLX - -!: jsr add_40_to_screen_x - - // Check if line is linked, if so, add 40 again - ldy TBLX - lda LDTBL,y - bpl !+ - jsr add_40_to_screen_x -!: - -x_not_negative: - // Work out if X is too big - ldy TBLX - lda LDTBL,y - bpl !+ - lda #79 - .byte $2C // BIT $nnnn, used to skip next instruction -!: lda #39 - cmp PNTR - bcs x_not_too_big - - // X value is too big, so subtract 40 and increment Y - lda PNTR - sec - sbc #40 - sta PNTR - inc TBLX - -x_not_too_big: - - // Make sure Y isn't negative - lda TBLX - bpl !+ - lda #0 - sta TBLX -!: - // Make sure Y isn't too large for absolute size of - // screen - cmp #24 - bcc !+ - lda #24 - sta TBLX -!: - // Make sure Y isn't too much for the screen, taking - // into account the line link table - ldy #24 // max allowable line - ldx #0 -link_count_loop: - lda LDTBL,x - bpl !+ - dey -!: inx - cpx #25 - bne link_count_loop - tya - cmp TBLX - bcs y_ok - sta TBLX -y_ok: - rts - -calculate_screen_line_pointer: - jsr normalise_screen_x_y - - // Reset pointer to start of screen - lda HIBASE - sta PNT+1 - lda #0 - sta PNT+0 - - // Add 40 for every line, or 80 if the lines are linked - ldx TBLX - -!: - // Stop if we have counted enough lines - beq !+ - - // Add 40 or 80 based on whether the line is linked - // or not. - ldy #40 - // -1 offset is because we count down from N to 1, not - // N-1 to 0. - lda LDTBL-1,x - bpl cslp_l1 - ldy #80 -cslp_l1: - // Add computed line length to pointer value - tya - clc - adc PNT+0 - sta PNT+0 - lda PNT+1 - adc #0 - sta PNT+1 - - // Loop back to next line - dex - jmp !- -!: - - // FALL THROUGH - -update_colour_line_pointer: - // Now setup pointer to colour RAM - lda PNT+0 - sta USER+0 - lda PNT+1 - sec - sbc HIBASE - clc - adc #>$d800 - sta USER+1 - - rts diff --git a/c64/kernal/screen/chrout_screen_control.s b/c64/kernal/screen/chrout_screen_control.s new file mode 100644 index 00000000..11bb2608 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_control.s @@ -0,0 +1,206 @@ + +// +// CHROUT routine - screen support, control codes +// + +chrout_screen_control: + + txa + + // Order here is not random + // 1. First handle the ones that do not depend on quoote mode + // 2. Handle remaining control codes starting from the most commonly used + // in situations when speed might matter, we want to be + // as snappy as possible + +chrout_try_RETURN: + + cmp #$0D + bne !+ + + // RETURN clears quote and insert modes, it also clears reverse flag + lda #$00 + sta QTSW + sta INSRT + sta RVS + jmp screen_advance_to_next_line +!: +chrout_try_DEL: + + cmp #$14 + bne !+ + jmp chrout_screen_del +!: +chrout_try_quote: + + lda QTSW + ora INSRT + beq !+ + jmp chrout_screen_quote +!: + txa + +chrout_try_CRSR_UP: + + cmp #$91 + bne !+ + + lda PNTR + sec + sbc #40 + sta PNTR + jsr calculate_screen_line_pointer + jmp chrout_done +!: +chrout_try_CRSR_DOWN: + + cmp #$11 + bne !+ + + lda PNTR + clc + adc #40 + sta PNTR + // We need to advance the pointer manually, as normalising + // now will break things. The pointer update is required + // so that we can tell if we really are on the bottom phys + // screen line or not + jsr scroll_up_if_on_last_line + jsr calculate_screen_line_pointer + jmp chrout_done +!: +chrout_try_CRSR_LEFT: + + cmp #$9D + bne !+ + + lda TBLX + ora PNTR + beq chrout_screen_control_done // if top-left screen character + dec PNTR + jmp chrout_screen_control_calcptr_done +!: +chrout_try_CRSR_RIGHT: + + cmp #$1D + bne !+ + + inc PNTR + jsr calculate_screen_line_pointer + jmp chrout_done +!: +chrout_try_RVS_ON: + + cmp #$12 + bne !+ + + lda #$80 + sta RVS + bne chrout_screen_control_done // branch always +!: +chrout_try_RVS_OFF: + + cmp #$92 + bne !+ + + lda #$00 + sta RVS + beq chrout_screen_control_done // branch always +!: +chrout_try_MODE_TXT: + + cmp #$0E + bne !+ + + // XXX + + jmp chrout_done +!: +chrout_try_MODE_GFX: + + cmp #$8E + bne !+ + + // XXX + + jmp chrout_done +!: +chrout_try_COLOR: + + ldx #$0F +colour_check_loop: + cmp colour_codes,x + bne !+ + stx COLOR + jmp chrout_done +!: + dex + bpl colour_check_loop + +chrout_try_SHIFT_ENABLE: + + cmp #$09 + bne !+ + + // XXX + + jmp chrout_done +!: +chrout_try_SHIFT_DISABLE: + + cmp #$08 + bne !+ + + // XXX + + jmp chrout_done +!: +chrout_try_HOME: + + cmp #$13 + bne !+ + + // XXX try cursor_home instead + lda #$00 + sta PNTR + sta TBLX + beq chrout_screen_control_calcptr_done // branch always +!: +chrout_try_CLR: + + cmp #$93 + bne !+ + + jsr clear_screen + jmp chrout_done +!: +chrout_try_INS: + + cmp #$94 + bne !+ + + jmp chrout_screen_ins +!: +chrout_try_RUN_STOP: + + cmp #$03 + bne !+ + + // XXX + + jmp chrout_done +!: +chrout_try_FKEY: + + // XXX + + // FALLTROUGH + +chrout_screen_control_done: // unknown, LF, or no more actions required // XXX to !csc_done + + jmp chrout_done + +chrout_screen_control_calcptr_done: // XXX to !csc_calcptr_done + + jsr calculate_screen_line_pointer + jmp chrout_done diff --git a/c64/kernal/screen/chrout_screen_del.s b/c64/kernal/screen/chrout_screen_del.s new file mode 100644 index 00000000..7ef44b8b --- /dev/null +++ b/c64/kernal/screen/chrout_screen_del.s @@ -0,0 +1,63 @@ + +// +// CHROUT routine - screen support, DEL key handling +// + +chrout_screen_del: + + // In insert mode it embeds control character + ldx INSRT + beq !+ + jmp chrout_screen_quote +!: + ldx PNTR + bne chrout_screen_del_column_non_0 + + // FALLTROUGH + +chrout_screen_del_column_0: + + ldy TBLX + beq chrout_screen_del_done // delete from row 0, col 0 does nothing + + // Column 0 delete just moves us to the end of the + // previous line, without actually deleting anything + + dec TBLX + jsr get_current_line_logical_length + lda LNMX + sta PNTR + + jmp chrout_screen_control_calcptr_done + +chrout_screen_del_column_non_0: + + // Copy rest of line down + jsr get_current_line_logical_length + ldy PNTR + cpy LNMX + beq !++ + dey +!: + iny + lda (PNT),y + dey + sta (PNT),y + iny + lda (USER),y + dey + sta (USER),y + iny + cpy LNMX + bne !- + + // Clear char at end of line + jsr get_current_line_logical_length + tay + lda #$20 + sta (PNT),y +!: + dec PNTR + +chrout_screen_del_done: + jmp chrout_done diff --git a/c64/kernal/screen/chrout_screen_ins.s b/c64/kernal/screen/chrout_screen_ins.s new file mode 100644 index 00000000..a56b6a80 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_ins.s @@ -0,0 +1,64 @@ + +// +// CHROUT routine - screen support, INS key handling +// + +chrout_screen_ins: + + // Insert (shift-DELETE) + + // Abort if line already max length, ie 79th char is not a space + jsr get_current_line_logical_length + cmp #79 + bne !+ + tay + lda (PNT),y + cmp #$20 + beq !+ + + // Line is too long to extend + jmp chrout_done + +!: + // Work out if line needs to be expanded, and if so expand it + ldy #39 + lda (PNT),y + cmp #$20 + beq !+ + + jsr screen_grow_logical_line + +!: + // Shuffle chars towards end of line + jsr get_current_line_logical_length + tay +!: + // Note: While the following routine is obvious to any skilled + // in the art as the most obvious simple and efficient solution, + // if the screen writes are before the colour writes, it results + // in a relatively long verbatim stretch of bytes when compared to + // the C64 KERNAL. Thus we have swapped the order, just to reduce + // the potential for any argument of copyright infringement, even + // though we really don't believe that the routine can be copyrighted + // due to the lack of creativity. + dey + lda (USER),y + iny + sta (USER),y + dey + lda (PNT),y + iny + sta (PNT),y + + dey + cpy PNTR + bne !- + + // Increase insert mode count (which causes quote-mode like behaviour) + inc INSRT + + // Put space in the inserted gap + lda #$20 + sta (PNT),y + + jmp chrout_done diff --git a/c64/kernal/screen/chrout_screen_quote.s b/c64/kernal/screen/chrout_screen_quote.s new file mode 100644 index 00000000..266f6d36 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_quote.s @@ -0,0 +1,20 @@ + +// +// CHROUT routine - screen support, control codes in quote mode +// + + +chrout_screen_quote: + + // Low control codes are just +$80 + clc + adc #$80 + + // If it overflowed, then it is a high control code, + // so we need to make it be $80 + $40 + char + // as we will have flipped back to just $00 + char, we should + // now add $c0 if C is set from overflow + bcc !+ + adc #$BF // C=1, so adding $BF + C = add $C0 +!: + jmp output_literal_char diff --git a/c64/kernal/screen/screen_calculate_line_pointer.s b/c64/kernal/screen/screen_calculate_line_pointer.s new file mode 100644 index 00000000..de1aa1d3 --- /dev/null +++ b/c64/kernal/screen/screen_calculate_line_pointer.s @@ -0,0 +1,54 @@ + +calculate_screen_line_pointer: // XXX rename to screen_calculate_line_pointer + jsr screen_normalize_xy + + // Reset pointer to start of screen + lda HIBASE + sta PNT+1 + lda #0 + sta PNT+0 + + // Add 40 for every line, or 80 if the lines are linked + ldx TBLX + +!: + // Stop if we have counted enough lines + beq !+ + + // Add 40 or 80 based on whether the line is linked + // or not. + ldy #40 + // -1 offset is because we count down from N to 1, not + // N-1 to 0. + lda LDTBL-1,x + bpl cslp_l1 + ldy #80 +cslp_l1: + // Add computed line length to pointer value + tya + clc + adc PNT+0 + sta PNT+0 + lda PNT+1 + adc #0 + sta PNT+1 + + // Loop back to next line + dex + jmp !- +!: + + // FALLTHROUGH + +update_colour_line_pointer: + // Now setup pointer to colour RAM + lda PNT+0 + sta USER+0 + lda PNT+1 + sec + sbc HIBASE + clc + adc #>$d800 + sta USER+1 + + rts diff --git a/c64/kernal/screen/screen_grow_logical_line.s b/c64/kernal/screen/screen_grow_logical_line.s new file mode 100644 index 00000000..26bd5ac9 --- /dev/null +++ b/c64/kernal/screen/screen_grow_logical_line.s @@ -0,0 +1,122 @@ + +screen_grow_logical_line: + ldy TBLX + // Don't grow line if it is already grown + lda LDTBL,y + bpl !+ + jmp not_last_line // doneb grow line +!: + lda #$80 + sta LDTBL,y + + // Now make space for the extra line added. + // If we are on the last physical line of the screen, + // Then we need to scroll the screen up + jsr scroll_up_if_on_last_line + + // Scroll screen down to make space + // As we are scrolling down, we start from the end, + // and work backwards. We can't be as simple and efficient + // here as we are for scrolling up, because we don't know + // how much must be scrolled. + // Simple solution is to work out how many physical lines + // need shifting down, and then move lines at a time after + // initialising the pointers to the end area of the screen. + ldx #25-2 + ldy #0 +count_rows_loop: + dex + lda LDTBL,y + bpl !+ + dex +!: iny + cpy TBLX + bne count_rows_loop + + cpx #0 + beq no_copy_down + bmi no_copy_down + + // Set pointers to end of screen line, and one line + // above. (It is always one physical line, because + // this can only happen when expanding a line from 40 to + // 80 characters). + // XXX - This is not very efficient, and longer than it + // needs to be. Better would be to work out size to + // copy, and count it down in a pointer somewhere, so + // that loop iteration logic is simpler. + lda HIBASE + clc + adc #3 + sta PNT+1 + sta SAL+1 + lda #>$DBC0 + sta EAL+1 + sta USER+1 + + lda #<$03C0 + sta PNT+0 + sta USER+0 + // souce address is line above + sec + sbc #40 + sta SAL+0 + sta EAL+0 + +copy_line_down_loop: + ldy #39 +cl_inner: + lda (EAL),y + sta (USER),y + lda (SAL),y + sta (PNT),y + dey + bpl cl_inner + + // Decrement all pointers by 40 + // Low bytes are in common pairs + + // Old source is new destination + // Use different registers to minimise byte similarity with C64 KERNAl + ldy SAL+1 + sty PNT+1 + lda EAL+1 + ldy SAL+0 + sta USER+1 + sty PNT+0 + sty USER+0 + + // Decrementing source pointers + lda SAL+0 + sec + sbc #<40 + sta SAL+0 + sta EAL+0 + lda SAL+1 + sbc #>40 + sta SAL+1 + // convert to screen equivalent + sec + sbc HIBASE + clc + adc #>$D800 + sta EAL+1 + + dex + bne copy_line_down_loop + +no_copy_down: + jsr calculate_screen_line_pointer + + // Erase newly inserted line + ldy #79 +!: + lda COLOR + sta (USER),y + lda #$20 + sta (PNT),y + dey + cpy #40 + bne !- + + rts diff --git a/c64/kernal/screen/screen_normalize_xy.s b/c64/kernal/screen/screen_normalize_xy.s new file mode 100644 index 00000000..147895a4 --- /dev/null +++ b/c64/kernal/screen/screen_normalize_xy.s @@ -0,0 +1,82 @@ + +// +// Normalise X and Y values +// If X < 0, then make X = X + 40 (or 80, if previous line is linked) +// + +screen_normalize_xy: + + lda PNTR + bpl x_not_negative + dec TBLX + // Check that we didn't go backwards off the top of the screen + bpl !+ + lda #0 + sta TBLX + +!: jsr add_40_to_screen_x + + // Check if line is linked, if so, add 40 again + ldy TBLX + lda LDTBL,y + bpl !+ + jsr add_40_to_screen_x +!: + +x_not_negative: + // Work out if X is too big + ldy TBLX + lda LDTBL,y + bpl !+ + lda #79 + .byte $2C // BIT $nnnn, used to skip next instruction +!: lda #39 + cmp PNTR + bcs x_not_too_big + + // X value is too big, so subtract 40 and increment Y + lda PNTR + sec + sbc #40 + sta PNTR + inc TBLX + +x_not_too_big: + + // Make sure Y isn't negative + lda TBLX + bpl !+ + lda #0 + sta TBLX +!: + // Make sure Y isn't too large for absolute size of + // screen + cmp #24 + bcc !+ + lda #24 + sta TBLX +!: + // Make sure Y isn't too much for the screen, taking + // into account the line link table + ldy #24 // max allowable line + ldx #0 +link_count_loop: + lda LDTBL,x + bpl !+ + dey +!: inx + cpx #25 + bne link_count_loop + tya + cmp TBLX + bcs y_ok + sta TBLX +y_ok: + rts + +add_40_to_screen_x: + lda PNTR + clc + adc #40 + sta PNTR + rts