Files
open-roms/c64/basic/print_packed_message.s
T

233 lines
3.9 KiB
ArmAsm

// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
// This routine prints messages that have been packed
// using the make_error_tables program.
// The general idea is to save space in the ROM.
// The output of make_error_tables is written to packed_messages.s, and
// contains the following:
//
// packed_message_words - List of nybl packed words.
// packed_message_tokens - List of tokens that get joined to make messages
// packed_message_chars - List of characters in messages sorted by frequency.
print_packed_message:
// .X = message number
lda #$ff
ldy #$ff
packed_message_search:
iny
cpx #$00
beq found_message_in_token_stream
lda packed_message_tokens,y
cmp #$ff
bne !+
dex
!:
cpy #$ff
bne packed_message_search
// Could not find message
sec
rts
found_message_in_token_stream: // XXX size-optimize this
// Now print each word in the message
phy_trash_a
lda packed_message_tokens,y
cmp #$FF
beq found_message_in_token_stream_done
jsr print_packed_word
ply_trash_a
iny
beq found_message_in_token_stream_done
!:
phy_trash_a
lda packed_message_tokens,y
cmp #$FF
beq found_message_in_token_stream_done
pha
jsr print_space
pla
jsr print_packed_word
ply_trash_a
iny
bne !-
found_message_in_token_stream_done:
pla
rts
print_packed_word:
// A = the word to print
tax
// Setup pointer to packed words
lda #<packed_message_words
sta FRESPC+0
lda #>packed_message_words
sta FRESPC+1
// Find the word in the list
ldy #$ff
packed_word_search:
iny
cpx #$00
beq found_packed_word
// $x0 is an end of work marker
lda (FRESPC),y
and #$0f
cmp #$00
bne !+
dex
!:
// $FE $xx is an end of work marker
lda (FRESPC),y
cmp #$fe
bne !+
dex
iny // skip next byte
!:
cmp #$ff
bne !+
iny // skip next byte
!:
// Advance to next page if required
cpy #$ff
bne packed_word_search
inc FRESPC+1
jmp packed_word_search
found_packed_word:
// Get pointer to start of packed word
// Make sure we do not wrap on a page boundary
tya
clc
adc FRESPC+0
sta FRESPC+0
lda FRESPC+1
adc #$00
sta FRESPC+1
print_packed_string:
ldy #$ff
next_packed_word_char:
// .Y = offset into packed word data - 1
iny
// Check for end of word
lda (FRESPC),y
cmp #$00
beq end_of_packed_word
cmp #$fe
beq last_literal
cmp #$ff
beq next_is_literal_char
and #$f0
beq end_of_packed_word
// Check if it is an uncommon char
lda (FRESPC),y
and #$f0
cmp #$f0
beq is_uncommon_char
// Is not an uncommon char, so get char of upper nybl
lda (FRESPC),y
// Put high nybl into low bits of X
lsr
lsr
lsr
lsr
tax
// X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x
jsr JCHROUT // preserves .Y
// See if there is a char in the low nybl to print
lda (FRESPC),y
and #$0f
beq end_of_packed_word
cmp #$0f
beq no_lo_nybl_char
has_lo_nybl_char:
// We need to print the low nybl char as well
tax
phy_trash_a
// Skip lower nybls of $F or $0 in nybl packed
// bytes, as these do not encode characters
cpx #$f
beq !+
has_nybl:
cpx #0
beq !+
// X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x
jsr JCHROUT
!:
ply_trash_a
// FALLTHROUGH
no_lo_nybl_char:
// If current byte has $0F in low nybl, then the next
// byte is a whole byte.
lda (FRESPC),y
and #$0f
cmp #$0f
beq next_is_literal_char
ready_for_next_char:
cpy #$ff
bne next_packed_word_char
end_of_packed_word:
// Hit end of packed data
rts
last_literal:
jsr unpack_literal_char
rts
next_is_literal_char:
jsr unpack_literal_char
jmp ready_for_next_char
unpack_literal_char:
// Output the literal char, and ready for next char
iny
phy_trash_a
lda (FRESPC),y
jsr JCHROUT
pla
tay
rts
is_uncommon_char:
// Lower nybl has offset into low-frequency part of the table
lda (FRESPC),y
and #$0f
clc
adc #14
// We need to print the low nybl char as well
tax
phy_trash_a
jmp has_nybl