Files
open-roms/c64/kernal/chrout.s
T

238 lines
4.3 KiB
ArmAsm

; Function defined on pp272-273 of C64 Programmers Reference Guide
chrout:
;; Crude implementation of character output
;; Save X and Y values
;; (Confirmed by writing a test program that X and Y
;; don't get modified, in agreement with C64 PRG's
;; description of CHROUT)
sta last_printed_character_ascii
txa
pha
tya
pha
jsr hide_cursor_if_visible
lda last_printed_character_ascii
tax
;; Check for special characters
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
jmp screen_advance_to_next_line
not_0d:
;; Check for cursor movement keys
cmp #$11
bne not_11
inc current_screen_y
jsr calculate_screen_line_pointer
jmp chrout_done
not_11:
cmp #$1d
bne not_1d
inc current_screen_x
jsr calculate_screen_line_pointer
jmp chrout_done
not_1d:
cmp #$91
bne not_91
dec current_screen_y
jsr calculate_screen_line_pointer
jmp chrout_done
not_91:
cmp #$9d
bne not_9d
dec current_screen_x
jsr calculate_screen_line_pointer
jmp chrout_done
not_9d:
cmp #$14
bne not_14
;; Delete
ldx current_screen_x
bne delete_non_zero_column
delete_at_column_0:
ldy current_screen_y
bne not_row_0
;; delete from row 0, col 0 does nothing
jmp chrout_done
not_row_0:
dec current_screen_y
lda screen_line_link_table,y
bpl line_not_linked_del
lda #79
.byte $2c ; BIT absolute mode, which we use to skip the next two instruction bytes
line_not_linked_del:
lda #39
sta current_screen_x
jsr calculate_screen_line_pointer
jmp chrout_done
delete_non_zero_column:
jmp chrout_done
not_14:
;; Home cursor
cmp #$13
bne not_13
lda #0
sta current_screen_x
sta current_screen_y
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
cmp #$40
bcc chrout_l1
cmp #$41+26
bcs chrout_l1
and #$1f
chrout_l1:
;; Write normal character on the screen
ldy current_screen_x
sta (current_screen_line_ptr),y
;; XXX - Update colour RAM also
;; Advance the column, and scroll screen down if we need
;; to insert a 2nd line in this logical line.
;; (eg Compute's Mapping the 64 p41)
ldx current_screen_y
iny
sty current_screen_x
cpy #40
bne no_screen_advance_to_next_line
jsr screen_grow_logical_line
cpy #79
bcc no_screen_advance_to_next_line
jmp screen_advance_to_next_line
no_screen_advance_to_next_line:
chrout_done:
;; Restore X and Y, set carry to mark success on exit
pla
tay
pla
tax
lda last_printed_character_ascii
clc ; indicate success
rts
screen_grow_logical_line:
;; XXX - Scroll screen down to make space
rts
screen_advance_to_next_line:
;; Go to start of line
lda #0
sta current_screen_x
;; Advance line number
ldy current_screen_y
inc current_screen_y
jsr calculate_screen_line_pointer
;; Work out if we have gone off the bottom of the screen?
;; 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4),
;; then we are off the bottom of the screen
lda current_screen_line_ptr+1
sec
sbc HIBASE
cmp #3
bcc +
;; Off the bottom of the screen
jsr scroll_screen_up
*
jmp chrout_done
scroll_screen_up:
;; XXX - Not implemented
rts
calculate_screen_line_pointer:
;; Reset pointer to start of screen
lda HIBASE
sta current_screen_line_ptr+1
lda #0
sta current_screen_line_ptr+0
;; Add 40 for every line, or 80 if the lines are linked
ldx current_screen_y
*
;; Stop if we have counted enough lines
beq +
;; Add 40 or 80 based on whether the line is linked
;; or not.
ldy #40
lda screen_line_link_table,x
bpl cslp_l1
ldy #80
cslp_l1:
;; Add computed line length to pointer value
tya
clc
adc current_screen_line_ptr+0
sta current_screen_line_ptr+0
lda current_screen_line_ptr+1
adc #0
sta current_screen_line_ptr+1
;; Loop back to next line
dex
jmp -
*
rts
retreat_screen_pointer_40_bytes:
lda current_screen_line_ptr+0
sec
sbc #<40
sta current_screen_line_ptr+0
lda current_screen_line_ptr+1
sbc #>40
sta current_screen_line_ptr+1
rts
advance_screen_pointer_40_bytes:
lda current_screen_line_ptr+0
clc
adc #<40
sta current_screen_line_ptr+0
lda current_screen_line_ptr+1
adc #>40
sta current_screen_line_ptr+1
rts