variable support cleanup

This commit is contained in:
FeralChild64 committed 2020-07-19 08:54:53 +02:00
1 parent 51aec45c8d
commit 09f85cea8a
64 files changed
+266 -87

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
This routine is used to launch other software. It is used by:
- Uncrunch (see https://github.com/mist64/pucrunch/blob/master/uncrunch.asm)
- FileBrowser64 (FB64) - found by debugging
and probably others.
+120
View File
@@ -0,0 +1,120 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 BASIC_0 #TAKE
// #LAYOUT# M65 BASIC_1 #TAKE-FLOAT
// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000
// #LAYOUT# * * #IGNORE
//
// Well-known BASIC routine, described in:
//
// - [CM64] Computes Mapping the Commodore 64 - page 95
// - https://www.lemon64.com/forum/viewtopic.php?t=64721&sid=bc400a5a6d404f8f092e4d32a92f5de7
//
LINKPRG:
#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0)
jsr map_BASIC_1
jsr_ind VB1__LINKPRG
jmp map_NORMAL
#else
// Start by getting pointer to the first line
jsr init_oldtxt
linkprg_loop:
// Is the pointer to the end of the program
ldy #1
#if ROM_LAYOUT_M65
jsr peek_via_OLDTXT
#elif CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms
cmp #$00
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
bne !+
// End of program
rts
!:
// Now search forward to find the end of the line
// Skip forward pointer and line number
ldy #4
linkprg_end_of_line_search:
#if ROM_LAYOUT_M65
jsr peek_via_OLDTXT
#elif CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp #$00
beq !+
// Not yet end of line
iny
bne linkprg_end_of_line_search
// line too long
jmp do_STRING_TOO_LONG_error
!:
// Found end of line, so update pointer
// First, skip over the $00 char
iny
// Now overwrite the pointer (carefully)
//
tya
clc
adc OLDTXT+0
pha
php
ldy #0
#if ROM_LAYOUT_M65
jsr poke_via_OLDTXT
#elif CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms
#else
sta (OLDTXT),y
#endif
plp
lda OLDTXT+1
adc #0
ldy #1
#if ROM_LAYOUT_M65
jsr poke_via_OLDTXT
#elif CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms
#else
sta (OLDTXT),y
#endif
sta OLDTXT+1
pla
sta OLDTXT+0
jmp linkprg_loop
#endif // ROM layout
+78
View File
@@ -0,0 +1,78 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Delete the current BASIC line, which is assumed to have already been found with find_line.
// Consists of copying memory down and lline linkage update.
//
delete_line:
// jsr printf
// .text "DELETING LINE AT $"
// .byte $f1,<OLDTXT,>OLDTXT
// .byte $f0,<OLDTXT,>OLDTXT
// .byte $0d,0
// Get address of next line
ldy #$00
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __tokenise_work3
iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __tokenise_work4
// Work out length of this line by looking at the pointer
lda __tokenise_work3
sec
sbc OLDTXT+0
sta __tokenise_work3
lda __tokenise_work4
sbc OLDTXT+1
sta __tokenise_work4
// jsr printf
// .text "LINE LENGTH IS $"
// .byte $f0,<__tokenise_work4,>__tokenise_work4
// .byte $f0,<__tokenise_work3,>__tokenise_work3
// .byte $0d,0
lda __tokenise_work4
sbc #0
cmp #$00
beq !+
// Line length is <0 or >255 bytes.
// Either way, things are bad, so abort.
jmp do_MEMORY_CORRUPT_error
!:
// Length can now be safely assumed to be in the low
// byte only, i.e., stored in __tokenise_work3
ldx __tokenise_work3
// Shuffle everything down
jsr shift_txt_down
// Finish by fixing program linkage and calculating new
jmp update_LINKPRG_VARTAB_do_clr
+105
View File
@@ -0,0 +1,105 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
// Find the BASIC line with number in LINNUM
find_line_from_start:
// Get pointer to start of BASIC text
jsr init_oldtxt
// FALLTROUGH
find_line_from_current:
// Check if line is not empty
jsr peek_line_pointer_null_check
bcc find_line_fail
// Fetch the high byte of line number and compare
ldy #$03
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp LINNUM+1
beq !+
bcs find_line_fail // branch if line number too high
bne find_line_next
!:
// Fetch the low byte of line number and compare
dey
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp LINNUM+0
beq find_line_success
bcs find_line_fail // branch if line number too high
bne find_line_next
find_line_success:
clc
rts
find_line_next:
// Advance to the next line
jsr peek_line_pointer_null_check
bcc find_line_fail // branch in no more lines exist
ldy #$00
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
pha
iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_OLDTXT
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta OLDTXT+1
pla
sta OLDTXT+0
#if HAS_OPCODES_65C02
bra find_line_from_current
#else
jmp find_line_from_current
#endif
find_line_fail:
sec
rts
+93
View File
@@ -0,0 +1,93 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Insert the tokenised line stored at $0200.
//
// First work out where in the list to put it (find_line with the line number can be used to work
// out the insertion point, as it should abort once it finds a line number too high).
// Then all we have to do is push the rest of the BASIC text up,
// and update the pointers in all following basic lines.
//
insert_line:
// ASSUMES find_line_from_start has been called to set the insert point.
// jsr printf
// .text "INSERTING LINE AT $"
// .byte $f1,<OLDTXT,>OLDTXT
// .byte $f0,<OLDTXT,>OLDTXT
// .byte $0d,0
// Get number of bytes in tokenised line after line number
lda __tokenise_work2
sec
sbc __tokenise_work1
// Add on the five bytes space we need (2 bytes for linkage, 2 bytes for line number, 1 byte for terminator)
clc
adc #$05
tax
// Make the space
jsr shift_txt_up
// Put dummy linkage, we will correct it later
ldy #$01
tya
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
sta (OLDTXT),y
#endif
// Put the line number
iny
lda LINNUM+0
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
sta (OLDTXT),y
#endif
iny
lda LINNUM+1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
sta (OLDTXT),y
#endif
// Now store the line body itself
inc __tokenise_work2
!:
ldx __tokenise_work1
lda $0200,x
inc __tokenise_work1
iny
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
sta (OLDTXT),y
#endif
lda __tokenise_work1
cmp __tokenise_work2
bne !-
// FALLTROUGH
update_LINKPRG_VARTAB_do_clr:
// Finish by fixing program linkage and calculating new VARTAB
jsr LINKPRG
jmp update_VARTAB_do_clr
+194
View File
@@ -0,0 +1,194 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
end_of_program:
// Entry point for commands not wishing to continue
pha
pha
// FALLTROUGH
shell_main_loop:
// Tell user we are ready
ldx #IDX__STR_READY
jsr print_packed_misc_str
// Mark mode as direct
lda #$FF
sta CURLIN+1
// Enable Kernal messages
lda #$80
jsr JSETMSG
shell_read_next_line:
// Read a line of input
ldx #$00
!:
jsr JCHRIN
bcs !-
// Check for RETURN key
cmp #$0D
beq shell_got_line
// Not carriage return, so try to append to line so far
cpx #80
bcs_16 do_STRING_TOO_LONG_error // see Computes Mapping the 64 p93
sta BUF,x
inx
jmp !-
shell_got_line:
// Store length of input buffer ready for tokenising
stx __tokenise_work1
// Store 0 as the sentinel
lda #$00
sta BUF, x
// FALLTROUGH
shell_strip_leading_spaces:
// Strip leading spaces from the line
lda BUF
cmp #$20
bne shell_process_line // branch if no more leading spaces
// We have a leading space - strip it away
ldx #$01
!:
lda BUF,x
sta BUF-1,x
inx
cpx __tokenise_work1
bne !-
// Reduce length of input by one
dec __tokenise_work1
// Stop trying to rim if we run out of input
bne shell_strip_leading_spaces
// FALLTROUGH
shell_process_line:
// Print a new line
jsr print_return
// Ignore empty lines
lda __tokenise_work1
beq shell_read_next_line
// Check if a wedge should take over
#if CONFIG_DOS_WEDGE
ldx __tokenise_work1 // size of the input, DOS wedges needs this XXX this should not be needed
#endif
#if CONFIG_DOS_WEDGE || CONFIG_TAPE_WEDGE
// Check if DOS wedge should take over
lda BUF
#if CONFIG_DOS_WEDGE
cmp #$40 // '@'
beq_16 wedge_dos
#endif
#if CONFIG_TAPE_WEDGE
cmp #$5F // left arrow
beq_16 wedge_tape
#endif
#endif
// Tokenise the line
jsr tokenise_line
// Has the user entered a line of BASIC beginning with a number?
lda BUF
cmp #$30
bcc shell_execute_line
cmp #$39
bcs shell_execute_line
// Yes, the line begins with a number - parse it and check validity
// The injest_number follows __tokenise_work1 as the offset into the line,
// so remember the line length somewhere else for now.
lda __tokenise_work1
sta __tokenise_work2
lda #$00
sta __tokenise_work1
// Try to read line number
lda #<BUF
sta TXTPTR+0
lda #>BUF
sta TXTPTR+1
jsr fetch_line_number
// Get pointer to next char
lda TXTPTR+0
sta __tokenise_work1
// Got a valid line number - we will be adding/deleting a new line
// Skip any spaces after the line number
ldx __tokenise_work1
!:
lda BUF,x
cmp #$20
bne !+
inx
bne !-
!:
stx __tokenise_work1
// FALLTROUGH
shell_add_delete_line:
// First make sure VARTAB is correct and clear all the variables
jsr update_VARTAB_do_clr
// Check if line already present
jsr find_line_from_start
bcs !+
// Line already present - delete it
jsr delete_line
jsr find_line_from_start // refresh OLDTXT
!:
// Insert new line if non-zero length, i.e., that
// we are not just deleting the line.
lda __tokenise_work1
cmp __tokenise_work2
beq !+
jsr insert_line
!:
// No READY message after entering or deleting a line of BASIC
jmp shell_read_next_line
shell_execute_line:
jsr prepare_direct_execution
jmp execute_statements
+43
View File
@@ -0,0 +1,43 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Shift the BASIC program down to cover the area of removed line
//
shift_txt_down:
// First byte of destination is OLDTXT
lda OLDTXT+0
sta memmove__dst+0
lda OLDTXT+1
sta memmove__dst+1
// First byte of source is memmove__dst + .X
clc
txa
adc memmove__dst+0
sta memmove__src+0
lda memmove__dst+1
adc #$00
sta memmove__src+1
// Size is distance from source to the end of BASIC text (VARTAB)
lda VARTAB+0
sec
sbc memmove__src+0
sta memmove__size+0
lda VARTAB+1
sbc memmove__src+1
sta memmove__size+1
// Perform the copy
jmp shift_mem_down
+58
View File
@@ -0,0 +1,58 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Shift the BASIC program up to make space for a new line
//
shift_txt_up:
// Last byte of source is VARTAB-1
#if !HAS_OPCODES_65CE02
sec
lda VARTAB+0
sbc #$01
sta memmove__src+0
lda VARTAB+1
sbc #$00
sta memmove__src+1
#else // HAS_OPCODES_65CE02
lda VARTAB+0
sta memmove__src+0
lda VARTAB+1
sta memmove__src+1
dew memmove__src
#endif
// Last byte of destination is memmove__src + .X
clc
txa
adc memmove__src+0
sta memmove__dst+0
lda memmove__src+1
adc #$00
sta memmove__dst+1
// Size is distance from OLDTXT to the end of BASIC text (VARTAB)
lda VARTAB+0
sec
sbc OLDTXT+0
sta memmove__size+0
lda VARTAB+1
sbc OLDTXT+1
sta memmove__size+1
// Perform the copy
jmp shift_mem_up
+46
View File
@@ -0,0 +1,46 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 BASIC_1 #TAKE
// #LAYOUT# X16 BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Cuts away unnecessary characters after tokenizing a keyword
//
tk_cut_away_2: // for two-bytes tokenized keywords
dec tk__len_unpacked
// FALLTROUGH
tk_cut_away_1: // for single-byte tokenized keywords
dec tk__len_unpacked // keyword length, afterwards number of bytes to cut away
// Correct the line length
sec
lda tk__length
sbc tk__len_unpacked
sta tk__length
// Copy the remaining,. untokenized part in the proper place
inc tk__offset
ldy tk__offset
lda tk__len_unpacked
clc
adc tk__offset
tax
!:
lda BUF, x
sta BUF, y
beq !+
inx
iny
bne !-
!:
rts
+229
View File
@@ -0,0 +1,229 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 BASIC_1 #TAKE
// #LAYOUT# X16 BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Packs a keyword candidate using a simple compression scheme,
// same as in 'generate_strings.cc'.
//
// This allows us to search through the compressed tokens directly
// using the compressed fragment of BASIC, and thus work out the
// token for a given piece of string.
//
// This also helps ensure that we have an implementation that is totally
// different to that of the original C64 BASIC, as well as likely
// saving a bit of space in the ROM, especially once we start implementing
// larger keyword vocabs for extended BASIC, since the compression and
// decompression machinery is of fixed size.
//
// Input:
// - .X = offset of string to pack, address is BUF ($0200) + .X
// Output:
// - see labels in 'tk_pack'
//
tk_pack:
// Reuse the CPU stack - address $100 is used by 'tokenise_line.s'
.label tk__len_unpacked = $101 // length of unpacked data; it could replace 'tk__nibble_flag', but at the cost of code size/performance
.label tk__shorten_bits = $102 // 2 bytes for quick shortening of packed candidate
.label tk__nibble_flag = $104 // $00 = start from new byte, $FF = start from high nibble
.label tk__byte_offset = $105 // offset of the current byte (to place new data) in tk__packed
.label tk__packed = $106 // packed candidate, 25 bytes is enough for worst case - a 16 byte keyword
// Initialize variables
lda #$00
ldy #($04 + 25) // initialize 5 bytes of data + 25 bytes of space for packing
!:
sta tk__len_unpacked, y
dey
bpl !-
// FALLTROUGH
tk_pack_loop:
// Get the next character
lda BUF, x
// If character cannot be a part of a keyword - do not pack anything more
cmp #$23 // '#' - first sane character for a keyword
bcc tk_pack_done // branch if below '#'
cmp #$7B // 'Z' + 1
bcs tk_pack_done // branch if above 'Z'
// Keywords should not contain digits, colons, or semicolons
cmp #$30
bcc !+ // branch if below '0'
cmp #$3C
bcc tk_pack_done // branch if below '<'
!:
// Try to find a nibble to encode the character
ldy #$0E
!:
cmp packed_as_1n-1, y
beq tk_pack_1n
dey
bne !-
// Try to find a 3-nibble sequence to encode the character (1st nibble is always 0xF in this case)
ldy #TK__PACKED_AS_3N
!:
cmp packed_as_3n-1, y
beq tk_pack_3n
dey
bne !-
// If it is not on the list, it cannot be a part of token - quit
// FALLTROUGH
tk_pack_done:
rts
tk_pack_1n:
// .Y contains our nibble; check whether we should start a new encoded byte
bit tk__nibble_flag
bpl tk_pack_1n_new_byte
// Store in the high nibble of the current byte
tya
asl
asl
asl
asl
ldy tk__byte_offset
ora tk__packed, y
sta tk__packed, y
// Adjust remaining counters / flags
inc tk__byte_offset
inc tk__nibble_flag // $FF -> $00
// FALLTROUGH
tk_pack_1n_done:
// Put the bit mark - to indicate 1-nibble encoding
clc
ror tk__shorten_bits+0
ror tk__shorten_bits+1
// FALLTROUGH
tk_pack_loop_next:
// Prepare for the next loop iteration - increment counters
inx
inc tk__len_unpacked
// Check length, if it is OK to pack one more byte; quit if not
lda tk__len_unpacked
cmp #TK__MAX_KEYWORD_LEN
bne tk_pack_loop
rts
tk_pack_1n_new_byte:
// Store in the low nibble of the next byte
tya
ldy tk__byte_offset
sta tk__packed, y
// Adjust remaining counters / flags
dec tk__nibble_flag // $00 -> $FF
bmi tk_pack_1n_done
tk_pack_3n:
// .Y contains 2 nibbles to encode; check whether we should start a new encoded byte
bit tk__nibble_flag
bpl tk_pack_3n_new_byte
// Store 1st nibble (alwys 0xF) in the high nibble of the current byte
phy_trash_a
lda #$F0
ldy tk__byte_offset
ora tk__packed, y
sta tk__packed, y
// Store byte in the next byte
iny
pla
sta tk__packed, y
// Adjust remaining counters / flags
iny
sty tk__byte_offset
inc tk__nibble_flag // $FF -> $00
// FALLTROUGH
tk_pack_3n_done:
// Put the bit mark - to indicate 3-nibble encoding
sec
ror tk__shorten_bits+0
ror tk__shorten_bits+1
bcc tk_pack_loop_next // branch always
tk_pack_3n_new_byte:
// First store everything in the current byte, we will set '0xF' mark later
tya
ldy tk__byte_offset
sta tk__packed, y
// Now store just the low nibble in the next byte
iny
and #$0F
sta tk__packed, y
// Go back for a moment and set the '0xF' mark in the low nibble
dey
lda tk__packed, y
ora #$0F
sta tk__packed, y
iny
// Adjust remaining counters / flags
sty tk__byte_offset
dec tk__nibble_flag // $00 -> $FF
bmi tk_pack_3n_done // branch always
+93
View File
@@ -0,0 +1,93 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 BASIC_1 #TAKE
// #LAYOUT# X16 BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Search for a token on the list pointed by FRESPC
//
// Input:
// - list address in FRESPC, has to be refreshed after routine call
// - uses same variables as 'tk_pack'
// Output:
// - Carry set = not found
// - .X = index of token found
//
tk_search:
ldx #$00 // initial token index
// FALLTROUGH
tk_search_loop:
// Check if end of the list
ldy #$00
lda (FRESPC), y
cmp #$FF
bne tk_search_compare
iny
lda (FRESPC), y
dey
cmp #$FF
bne tk_search_compare
// End of the list
sec
rts
tk_search_compare:
// Compare the packed candidate with the current keyword list entry
lda (FRESPC), y
cmp tk__packed, y
bne tk_search_not_matching
cmp #$00
beq tk_search_found
// For now everything matches, try the next byte
iny
bne tk_search_compare // branch always
tk_search_not_matching:
inx // increment token index
// We need to find the end of the keyword on the list
// and proceed one byte further
cmp #$00
beq tk_search_next
!:
iny
lda (FRESPC), y
bne !-
// FALLTROUGH
tk_search_next:
// Update FRESPC - advance by .Y
iny
tya
clc
adc FRESPC+0
sta FRESPC+0
lda FRESPC+1
adc #$00
sta FRESPC+1
bcc tk_search_loop // branch always
tk_search_found:
clc
rts
+112
View File
@@ -0,0 +1,112 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 BASIC_1 #TAKE
// #LAYOUT# X16 BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Shortens a keyword candidate previously packed by tk_pack by 1 character
//
// Input:
// - uses same variables as 'tk_pack'
//
tk_shorten:
// First make sure we actually can shorten anything
dec tk__len_unpacked
beq tk_shorten_end
// Now check if the last character was encoded as 1 nibble or 3 nibbles
asl tk__shorten_bits+1
rol tk__shorten_bits+0
bcs tk_shorten_3n
// FALLTROUGH
tk_shorten_1n:
ldy tk__byte_offset // will be needed in both cases
// Now we need to check which nibble to cut away
bit tk__nibble_flag
bmi tk_shorten_1n_lo
// FALLTROUGH
tk_shorten_1n_hi: // tk__nibble_flag = $00, both nibbles free
// Go back one byte and clear the high nibble only
dey
sty tk__byte_offset
lda tk__packed, y
and #$0F
sta tk__packed, y
// Adjust remaining counters / flags, and quit
dec tk__nibble_flag // $00 -> $FF
// FALLTROUGH
tk_shorten_end:
rts
tk_shorten_1n_lo: // tk__nibble_flag = $FF, only the high nibble is free
// Clear the whole byte, it will be faster
lda #$00
sta tk__packed, y
// Adjust remaining counters / flags, and quit
inc tk__nibble_flag // $FF -> $00
rts
tk_shorten_3n:
ldy tk__byte_offset // will be needed in both cases
lda #$00
// Now we need to check which nibble to cut away
bit tk__nibble_flag
bmi tk_shorten_3n_2bytes
// FALLTROUGH
tk_shorten_3n_byte_nibble: // tk__nibble_flag = $00, both nibbles free
// Go back one byte, clear it, go back and clear the high nibble only
dey
sta tk__packed, y
// Reuse 'tk_shorten_1n_hi'
sty tk__byte_offset
#if HAS_OPCODES_65C02
bra tk_shorten_1n_hi
#else
jmp tk_shorten_1n_hi
#endif
tk_shorten_3n_2bytes: // tk__nibble_flag = $FF, only the high nibble is free
// Clear the byte, go back, clear one more byte
sta tk__packed, y
dey
sta tk__packed, y
// Adjust remaining counters / flags, and quit
sty tk__byte_offset
inc tk__nibble_flag // $FF -> $00
rts
+207
View File
@@ -0,0 +1,207 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 * #TAKE
// #LAYOUT# X16 BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tokenise a line of BASIC stored at $0200
//
// Input:
// - length in __tokenise_work1
//
tokenise_line:
#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0)
jsr map_BASIC_1
jsr_ind VB1__tokenise_line
jmp map_NORMAL
#else
// Reuse the CPU stack - addresses above $100 are used by 'tk_pack.s'
.label tk__offset = $100 // offset into string
.label tk__length = __tokenise_work1 // length of the raw string
// Initialize variables
lda #$00
sta tk__offset
// Terminate input string with $00
// XXX do we need this?
ldx tk__length
sta BUF, x
// FALLTROUGH
tokenise_line_loop:
// Check if we have reached end of the line
lda tk__offset
cmp tk__length
beq tokenise_line_done
// Check for some special characters
ldx tk__offset
lda BUF, x
cmp #$22
beq tokenise_line_quote
cmp #$DE
beq tokenise_line_pi
cmp #$3F
beq tokenise_line_question_mark // shortcut for PRINT command
// Try to tokenise
jsr tk_pack
!:
lda tk__len_unpacked
beq tokenise_line_char // branch if attempt to tokenise failed
// Check for BASIC V2 tokens
lda #<packed_freq_keywords_V2
sta FRESPC+0
lda #>packed_freq_keywords_V2
sta FRESPC+1
jsr tk_search
bcc tokenise_line_keyword_V2 // branch if keyword identified
// Check for extended tokens
lda #<packed_freq_keywords_CC
sta FRESPC+0
lda #>packed_freq_keywords_CC
sta FRESPC+1
jsr tk_search
bcc tokenise_line_keyword_CC // branch if keyword identified
lda #<packed_freq_keywords_CD
sta FRESPC+0
lda #>packed_freq_keywords_CD
sta FRESPC+1
jsr tk_search
bcc tokenise_line_keyword_CD // branch if keyword identified
// Shorten packed keyword candidate and try again
jsr tk_shorten
#if HAS_OPCODES_65C02
bra !-
#else
jmp !-
#endif
tokenise_line_keyword_V2:
// .X contains a token ID, starting from 0
txa
pha // store the token on the stack, we will need it for REM support
// Store the token
ldx tk__offset
clc
adc #$80
sta BUF, x
// Cut away unnecessary bytes
jsr tk_cut_away_1
// Special handling for REM command - after this one nothing more should be tokenised
pla
cmp #$0F // REM token index
bne tokenise_line_loop
// FALLTROUGH
tokenise_line_done:
// Quit
rts
tokenise_line_quote:
// For the quote, we advance without tokenizing, until the next quote is found
inc tk__offset
ldx tk__offset
lda BUF, x
beq tokenise_line_done
cmp #$22
beq tokenise_line_char
bne tokenise_line_quote // branch always
tokenise_line_pi:
lda #$FF // token for PI
skip_2_bytes_trash_nvz
// FALLTROUGH
tokenise_line_question_mark:
lda #$99 // token for PRINT
sta BUF, x
// FALLTROUGH
tokenise_line_char:
inc tk__offset
jmp tokenise_line_loop
// Support for extended keyword lists
tokenise_line_keyword_CC:
// Store the token list index
lda #$CC
skip_2_bytes_trash_nvz
// FALLTROUGH
tokenise_line_keyword_CD:
// Store the token list index
lda #$CD
ldy tk__offset
sta BUF, y
// Store the sub-token itself
inx
txa
iny
sty tk__offset
sta BUF, y
// Cut away unnecessary bytes
jsr tk_cut_away_2
jmp tokenise_line_loop
#endif // ROM layout
@@ -0,0 +1,47 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Calculate the VARTAB value - to mark the end of BASIC program code. Also clears all variables.
//
update_VARTAB_do_clr:
lda TXTTAB+0
sta OLDTXT+0
lda TXTTAB+1
sta OLDTXT+1
!:
lda OLDTXT+0
sta VARTAB+0
lda OLDTXT+1
sta VARTAB+1
jsr follow_link_to_next_line
lda OLDTXT+0
ora OLDTXT+1
bne !- // branch if pointer not NULL
// Correct VARTAB by 2 bytes NULL pointer
#if HAS_OPCODES_65CE02
inw VARTAB
inw VARTAB
#else
clc
lda VARTAB+0
adc #$02
sta VARTAB+0
bcc !+
inc VARTAB+1
!:
#endif
// Call CLR to set-up remaining variables
jmp do_clr