nesemu/tests/cpu_exec_space/source/common/print.s

381 lines
5.4 KiB
ArmAsm

; Prints values in various ways to output,
; including numbers and strings.
newline = 10
zp_byte print_temp_
; Prints indicated register to console as two hex
; chars and space
; Preserved: A, X, Y, flags
print_a:
php
pha
print_reg_:
jsr print_hex
lda #' '
jsr print_char_
pla
plp
rts
print_x:
php
pha
txa
jmp print_reg_
print_y:
php
pha
tya
jmp print_reg_
print_p:
php
pha
php
pla
jmp print_reg_
print_s:
php
pha
txa
tsx
inx
inx
inx
inx
jsr print_x
tax
pla
plp
rts
; Prints A as two hex characters, NO space after
; Preserved: A, X, Y
print_hex:
jsr update_crc
pha
lsr a
lsr a
lsr a
lsr a
jsr print_hex_nibble
pla
pha
and #$0F
jsr print_hex_nibble
pla
rts
print_hex_nibble:
cmp #10
blt @digit
adc #6;+1 since carry is set
@digit: adc #'0'
jmp print_char_
; Prints character and updates checksum UNLESS
; it's a newline.
; Preserved: A, X, Y
print_char:
cmp #newline
beq :+
jsr update_crc
: pha
jsr print_char_
pla
rts
; Prints space. Does NOT update checksum.
; Preserved: A, X, Y
print_space:
pha
lda #' '
jsr print_char_
pla
rts
; Advances to next line. Does NOT update checksum.
; Preserved: A, X, Y
print_newline:
pha
lda #newline
jsr print_char_
pla
rts
; Prints string
; Preserved: A, X, Y
.macro print_str str,str2,str3,str4,str5,str6,str7,str8,str9,str10,str11,str12,str13,str14,str15
jsr print_str_
.byte str
.ifnblank str2
.byte str2
.endif
.ifnblank str3
.byte str3
.endif
.ifnblank str4
.byte str4
.endif
.ifnblank str5
.byte str5
.endif
.ifnblank str6
.byte str6
.endif
.ifnblank str7
.byte str7
.endif
.ifnblank str8
.byte str8
.endif
.ifnblank str9
.byte str9
.endif
.ifnblank str10
.byte str10
.endif
.ifnblank str11
.byte str11
.endif
.ifnblank str12
.byte str12
.endif
.ifnblank str13
.byte str13
.endif
.ifnblank str14
.byte str14
.endif
.ifnblank str15
.byte str15
.endif
.byte 0
.endmacro
print_str_:
sta print_temp_
pla
sta addr
pla
sta addr+1
jsr inc_addr
jsr print_str_addr
lda print_temp_
jmp (addr)
; Prints string at addr and leaves addr pointing to
; byte AFTER zero terminator.
; Preserved: A, X, Y
print_str_addr:
pha
tya
pha
ldy #0
beq :+ ; always taken
@loop: jsr print_char
jsr inc_addr
: lda (addr),y
bne @loop
pla
tay
pla
; FALL THROUGH
; Increments 16-bit value in addr.
; Preserved: A, X, Y
inc_addr:
inc addr
beq :+
rts
: inc addr+1
rts
.pushseg
.segment "RODATA"
; >= 60000 ? (EA60)
; >= 50000 ? (C350)
; >= 40000 ? (9C40)
; >= 30000 ? (7530)
; >= 20000 ? (4E20)
; >= 10000 ? (2710)
digit10000_hi: .byte $00,$27,$4E,$75,$9C,$C3,$EA
digit10000_lo: .byte $00,$10,$20,$30,$40,$50,$60
; >= 9000 ? (2328 (hex))
; >= 8000 ? (1F40 (hex))
; >= 7000 ? (1B58 (hex))
; >= 6000 ? (1770 (hex))
; >= 5000 ? (1388 (hex))
; >= 4000 ? (FA0 (hex))
; >= 3000 ? (BB8 (hex))
; >= 2000 ? (7D0 (hex))
; >= 1000 ? (3E8 (hex))
digit1000_hi: .byte $00,$03,$07,$0B,$0F,$13,$17,$1B,$1F,$23
digit1000_lo: .byte $00,$E8,$D0,$B8,$A0,$88,$70,$58,$40,$28
; >= 900 ? (384 (hex))
; >= 800 ? (320 (hex))
; >= 700 ? (2BC (hex))
; >= 600 ? (258 (hex))
; >= 500 ? (1F4 (hex))
; >= 400 ? (190 (hex))
; >= 300 ? (12C (hex))
; >= 200 ? (C8 (hex))
; >= 100 ? (64 (hex))
digit100_hi: .byte $00,$00,$00,$01,$01,$01,$02,$02,$03,$03
digit100_lo: .byte $00,$64,$C8,$2C,$90,$F4,$58,$BC,$20,$84
.popseg
.macro dec16_comparew table_hi, table_lo
.local @lt
cmp table_hi,y
bcc @lt
bne @lt ; only test the lo-part if hi-part is equal
pha
txa
cmp table_lo,y
pla
@lt:
.endmacro
.macro do_digit table_hi, table_lo
pha
; print Y as digit; put X in A and do SEC for subtraction
jsr @print_dec16_helper
sbc table_lo,y
tax
pla
sbc table_hi,y
.endmacro
; Prints A:X as 2-5 digit decimal value, NO space after.
; A = high 8 bits, X = low 8 bits.
print_dec16:
ora #0
beq @less_than_256
ldy #6
sty print_temp_
; TODO: Use binary search?
: dec16_comparew digit10000_hi,digit10000_lo
bcs @got10000
dey
bne :-
;cpy print_temp_
;beq @got10000
@cont_1000:
ldy #9
: dec16_comparew digit1000_hi,digit1000_lo
bcs @got1000
dey
bne :- ; Y = 0.
cpy print_temp_ ; zero print_temp_ = print zero-digits
beq @got1000
@cont_100:
ldy #9
: dec16_comparew digit100_hi,digit100_lo
bcs @got100
dey
bne :-
cpy print_temp_
beq @got100
@got10000:
do_digit digit10000_hi,digit10000_lo
; value is now 0000..9999
ldy #0
sty print_temp_
beq @cont_1000
@got1000:
do_digit digit1000_hi,digit1000_lo
; value is now 000..999
ldy #0
sty print_temp_
beq @cont_100
@got100:
do_digit digit100_hi,digit100_lo
; value is now 00..99
txa
jmp print_dec_00_99
@less_than_256:
txa
jmp print_dec
@print_dec16_helper:
tya
jsr print_digit
txa
sec
rts
; Prints A as 2-3 digit decimal value, NO space after.
; Preserved: Y
print_dec:
; Hundreds
cmp #10
blt print_digit
cmp #100
blt print_dec_00_99
ldx #'0'-1
: inx
sbc #100
bge :-
adc #100
jsr print_char_x
; Tens
print_dec_00_99:
sec
ldx #'0'-1
: inx
sbc #10
bge :-
adc #10
jsr print_char_x
; Ones
print_digit:
ora #'0'
jmp print_char
; Print a single digit
print_char_x:
pha
txa
jsr print_char
pla
rts
; Prints one of two characters based on condition.
; SEC; print_cc bcs,'C','-' prints 'C'.
; Preserved: A, X, Y, flags
.macro print_cc cond,yes,no
; Avoids labels since they're not local
; to macros in ca65.
php
pha
cond *+6
lda #no
bne *+4
lda #yes
jsr print_char
pla
plp
.endmacro