CHROUT screen output routine split, size and performance optimizations
This commit is contained in:
1 parent
a442bf910f
commit
2cc6587b5c
8 files changed
+627
-521
No files matched your search
+16
-521
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user