2020/c64/screen.asm

350 lines
4.9 KiB
NASM

// vim: filetype=kickass
*=* "Screen Routines"
//
// clear_screen
//
// Destroys: a, y
//
clear_screen:
lda #$06
sta $d021
lda #$0e
sta $d020
ldy #0
!loop:
lda #' '
sta SCREEN_RAM, y
sta SCREEN_RAM + $0100, y
sta SCREEN_RAM + $0200, y
sta SCREEN_RAM + $0300, y
sta SCREEN_RAM + $03e7, y
lda #1
sta COLOR_RAM, y
sta COLOR_RAM + $0100, y
sta COLOR_RAM + $0200, y
sta COLOR_RAM + $0300, y
sta COLOR_RAM + $03e7, y
iny
bne !loop-
lda #<SCREEN_RAM
sta cursor_pointer_lo
lda #>SCREEN_RAM
sta cursor_pointer_hi
lda #23
sta $d018
rts
//
// print_carriage_return
//
// Input:
// - cursor_pointer_{lo,hi} - Cursor pointer.
//
// Destroys: a, zp_temp
//
print_newline:
sec
lda cursor_pointer_lo
adc #40
sta cursor_pointer_lo
bcc !done+
inc cursor_pointer_hi
!done:
// fallthrough
//
// print_carriage_return
//
// Input:
// - cursor_pointer_{lo,hi} - Cursor pointer.
//
// Destroys: a, zp_temp
//
print_carriage_return:
// Subtract SCREEN_RAM from cursor pointer
sec
lda cursor_pointer_hi
sbc #>SCREEN_RAM
sta cursor_pointer_hi
// Divide the cursor position by 40 (one row)
i16_div8(cursor_pointer_lo, cursor_pointer_hi)
// At this point, the pointer fits in a 8-bit register
lda cursor_pointer_lo
i8_div5_a()
// Multiply it by 40 again
i8_mul5_a()
sta cursor_pointer_lo
i16_mul8(cursor_pointer_lo, cursor_pointer_hi)
// Add SCREEN_RAM back
clc
lda cursor_pointer_hi
adc #>SCREEN_RAM
sta cursor_pointer_hi
rts
//
// write_string
//
// Input:
// - $03-$04 - Pointer to null-terminated string.
// - $05-$06 - Cursor pointer.
//
// Destroys: a, x, y, $02
//
write_string:
ldx #0
ldy #0
!loop:
lda ($03), y
beq !done+
iny
cmp #'\r'
beq !carriage_return+
cmp #'\n'
beq !newline+
sta (cursor_pointer_lo, x)
i16_inc(cursor_pointer_lo)
jmp !loop-
!newline:
jsr print_newline
jmp !loop-
!carriage_return:
jsr print_carriage_return
jmp !loop-
!done:
rts
.macro i16_print_hex_0x(addr) {
lda addr + 1
jsr print_hex_0x
lda addr
jsr print_hex
}
// Destroys: a, x, y, zp_temp ($02)
print_hex_0x:
sta zp_temp
ldx #0
lda #'0'
sta (cursor_pointer_lo, x)
i16_inc(cursor_pointer_lo)
lda #'x'
sta (cursor_pointer_lo, x)
i16_inc(cursor_pointer_lo)
lda zp_temp
// fallthrough
print_hex:
ldx #0
sta zp_temp
lsr
lsr
lsr
lsr
tay
lda !hex_chars+, y
sta (cursor_pointer_lo, x)
i16_inc(cursor_pointer_lo)
lda zp_temp
and #$0f
tay
lda !hex_chars+, y
sta (cursor_pointer_lo, x)
i16_inc(cursor_pointer_lo)
rts
!hex_chars:
.text "0123456789ABCDEF"
// Input:
// - $03..$04: The number to print
//
// Destroys: a, y, $24..$25
print_decimal_u16:
ldy #6
// Null-terminate the buffer
lda #0
sta !buffer+, y
!loop:
u16_div10()
u16_u16_move($22, $24)
i16_mul10($22)
i16_i16_sub($22, $23, $03, $04, $22, $23)
u16_u16_move($03, $24)
lda $22
clc
adc #'0'
sta !buffer+ - 1, y
dey
bne !loop-
// Find the first digit
ldy #0
!:
lda !buffer+, y
iny
cmp #'0'
beq !-
dey
tya
clc
adc #<(!buffer+)
sta $03
lda #0
adc #>(!buffer+)
sta $04
jsr write_string
rts
//
// Input:
// - udivmod32_dividend - Number to print
//
// Destroys: a, y, $02..$04, $10..$2b
//
print_decimal_u32:
ldy #11
// Null-terminate the buffer
lda #0
sta !buffer+, y
lda #0
sta udivmod32_divisor + 3
sta udivmod32_divisor + 2
sta udivmod32_divisor + 1
lda #10
sta udivmod32_divisor + 0
!loop:
jsr udivmod32
lda udivmod32_remainder
clc
adc #'0'
sta !buffer+ - 1, y
lda udivmod32_result + 0
sta udivmod32_dividend + 0
lda udivmod32_result + 1
sta udivmod32_dividend + 1
lda udivmod32_result + 2
sta udivmod32_dividend + 2
lda udivmod32_result + 3
sta udivmod32_dividend + 3
dey
bne !loop-
// Find the first digit
ldy #0
!:
lda !buffer+, y
iny
cmp #'0'
beq !-
dey
tya
clc
adc #<(!buffer+)
sta $03
lda #0
adc #>(!buffer+)
sta $04
jsr write_string
rts
!buffer:
.fill 12, 0
wait_space_then_reset:
ldx #$ff
stx $dc02
ldy #$00
sty $dc03
!:
lda #$7f
sta $dc00
lda $dc01
and #$10
bne !-
move_16_imm($03, !str_resetting+)
jsr write_string
// Reset
lda #%00110111
sta $01
jmp $fce2
rts
!str_resetting:
.byte '\n'
.text "Resetting..."
.byte 0
str_part2:
.byte '\n'
.text "Part 2: "
.byte 0
str_done:
.byte '\n', '\n'
.text "* Done"
.byte '\n', 0