adapted to Kick Assembler, some documentation update
This commit is contained in:
1 parent
ae23dbae7b
commit
de27124b4f
198 files changed
+4181
-3976
No files matched your search
+116
-114
@@ -1,126 +1,128 @@
|
||||
; Names of ZP and low memory locations
|
||||
; (Only those for now that we feel the need to implement initially)
|
||||
; (https://www.c64-wiki.com/wiki/Zeropage)
|
||||
// Names of ZP and low memory locations
|
||||
// (Only those for now that we feel the need to implement initially)
|
||||
// (https://www.c64-wiki.com/wiki/Zeropage)
|
||||
|
||||
.alias tokenise_work1 $7
|
||||
.alias tokenise_work2 $8
|
||||
.alias tokenise_work3 $B
|
||||
.alias tokenise_work4 $F
|
||||
.alias basic_line_number $14
|
||||
.alias temp_string_ptr $35
|
||||
.alias load_or_verify_or_tokenise_work5 $C
|
||||
.alias basic_work22 $22
|
||||
.alias basic_work23 $23
|
||||
.alias basic_work24 $24
|
||||
.alias basic_work25 $25
|
||||
// XXX get rid of this file, use ,aliases_ram_lowmem.s instead
|
||||
|
||||
;; The various pointers that separate memory regions for BASIC storage
|
||||
;; We have multiple names for the ones that mark the boundary of regions.
|
||||
.alias basic_start_of_text_ptr $2b
|
||||
.alias basic_end_of_text_ptr $2d
|
||||
.alias basic_start_of_vars_ptr $2d
|
||||
.alias basic_end_of_vars_ptr $2f
|
||||
.alias basic_start_of_arrays_ptr $2f
|
||||
.alias basic_end_of_arrays_ptr $31
|
||||
.alias basic_start_of_free_space_ptr $31
|
||||
.alias basic_start_of_strings_ptr $33
|
||||
.alias basic_top_of_memory_ptr $37
|
||||
.alias basic_current_line_number $39
|
||||
.alias basic_previous_line_number $3b
|
||||
.alias basic_current_line_ptr $3d
|
||||
.label tokenise_work1 = $7
|
||||
.label tokenise_work2 = $8
|
||||
.label tokenise_work3 = $B
|
||||
.label tokenise_work4 = $F
|
||||
.label basic_line_number = $14
|
||||
.label temp_string_ptr = $35
|
||||
.label load_or_verify_or_tokenise_work5 = $C
|
||||
.label basic_work22 = $22
|
||||
.label basic_work23 = $23
|
||||
.label basic_work24 = $24
|
||||
.label basic_work25 = $25
|
||||
|
||||
;; Note that the statement point is in the CHRGET/CHRGOT routine
|
||||
;; in ZP RAM. (Compute's Mapping the 64, p25)
|
||||
.alias basic_current_statement_ptr $7a
|
||||
// The various pointers that separate memory regions for BASIC storage
|
||||
// We have multiple names for the ones that mark the boundary of regions.
|
||||
.label basic_start_of_text_ptr = $2b
|
||||
.label basic_end_of_text_ptr = $2d
|
||||
.label basic_start_of_vars_ptr = $2d
|
||||
.label basic_end_of_vars_ptr = $2f
|
||||
.label basic_start_of_arrays_ptr = $2f
|
||||
.label basic_end_of_arrays_ptr = $31
|
||||
.label basic_start_of_free_space_ptr = $31
|
||||
.label basic_start_of_strings_ptr = $33
|
||||
.label basic_top_of_memory_ptr = $37
|
||||
.label basic_current_line_number = $39
|
||||
.label basic_previous_line_number = $3b
|
||||
.label basic_current_line_ptr = $3d
|
||||
|
||||
// Note that the statement point is in the CHRGET/CHRGOT routine
|
||||
// in ZP RAM. (Compute's Mapping the 64, p25)
|
||||
.label basic_current_statement_ptr = $7a
|
||||
|
||||
.alias basic_numeric_work_area $57 ; $57 - $60 inclusive = 10 bytes
|
||||
.label basic_numeric_work_area = $57 // $57 - $60 inclusive = 10 bytes
|
||||
|
||||
;; Floating point accumulator 1 $61 - $68
|
||||
.alias basic_fac1_exponent $61
|
||||
.alias basic_fac1_mantissa $62 ; $62 - $65
|
||||
.alias basic_fac1_sign $66
|
||||
.alias basic_fac1_overflow $68
|
||||
.alias basic_fac1_mantissa_lob $70
|
||||
// Floating point accumulator 1 $61 - $68
|
||||
.label basic_fac1_exponent = $61
|
||||
.label basic_fac1_mantissa = $62 // $62 - $65
|
||||
.label basic_fac1_sign = $66
|
||||
.label basic_fac1_overflow = $68
|
||||
.label basic_fac1_mantissa_lob = $70
|
||||
|
||||
.alias basic_fac2_exponent $69
|
||||
.alias basic_fac2_mantissa $6A ; $6A - $6D
|
||||
.alias basic_fac2_sign $6E
|
||||
.label basic_fac2_exponent = $69
|
||||
.label basic_fac2_mantissa = $6A // $6A - $6D
|
||||
.label basic_fac2_sign = $6E
|
||||
|
||||
;; We also re-use FAC2 for memory move pointers, since
|
||||
;; we can't be doing calculations while moving memory
|
||||
.alias memmove_src $69
|
||||
.alias memmove_dst $6b
|
||||
.alias memmove_size $6d
|
||||
// We also re-use FAC2 for memory move pointers, since
|
||||
// we can't be doing calculations while moving memory
|
||||
.label memmove_src = $69
|
||||
.label memmove_dst = $6b
|
||||
.label memmove_size = $6d
|
||||
|
||||
.alias current_file_num $98
|
||||
.alias cassette_buffer_bytes_used $A6
|
||||
.alias load_or_scroll_temp_pointer $AC
|
||||
;; We also use the following for temp colour pointer when scrolling
|
||||
.alias load_save_verify_end_address $AE
|
||||
.label current_file_num = $98
|
||||
.label cassette_buffer_bytes_used = $A6
|
||||
.label load_or_scroll_temp_pointer = $AC
|
||||
// We also use the following for temp colour pointer when scrolling
|
||||
.label load_save_verify_end_address = $AE
|
||||
|
||||
.alias cassette_buffer_ptr $B2
|
||||
.alias current_logical_filenum $B8
|
||||
.alias current_secondary_address $B9
|
||||
.alias current_device_number $BA
|
||||
.alias current_filename_ptr $BB
|
||||
.alias load_save_start_ptr $C1
|
||||
.alias load_save_end_ptr $C3
|
||||
.alias last_key_matrix_position $C5
|
||||
.alias keys_in_key_buffer $C6
|
||||
.alias reverse_video_flag $C7
|
||||
.alias end_of_input_line $C8
|
||||
.alias start_of_keyboard_input $C9
|
||||
.alias current_key_index_entry $CB
|
||||
.alias cursor_blink_disable $CC
|
||||
.alias cursor_blink_countdown $CD
|
||||
.alias cursor_saved_character $CE
|
||||
.alias cursor_is_visible $CF
|
||||
.alias keyboard_input_ready $D0
|
||||
.alias current_screen_line_ptr $D1
|
||||
.alias current_screen_x $D3
|
||||
.alias quote_mode_flag $D4
|
||||
.alias logical_line_length $D5
|
||||
.alias current_screen_y $D6
|
||||
.alias last_printed_character_ascii $D7
|
||||
.alias insert_mode $D8
|
||||
; Bits 0 -3 = bits 8-11 of screen line address
|
||||
; Bit 7 = line spans multiple physical lines
|
||||
.alias screen_line_link_table $D9
|
||||
.alias current_screen_line_colour_ptr $F3
|
||||
.alias keyboard_decoding_table_ptr $F5
|
||||
.alias rs232_rx_buffer_ptr $F7
|
||||
.alias rs232_tx_buffer_ptr $F9
|
||||
.label cassette_buffer_ptr = $B2
|
||||
.label current_logical_filenum = $B8
|
||||
.label current_secondary_address = $B9
|
||||
.label current_device_number = $BA
|
||||
.label current_filename_ptr = $BB
|
||||
.label load_save_start_ptr = $C1
|
||||
.label load_save_end_ptr = $C3
|
||||
.label last_key_matrix_position = $C5
|
||||
.label keys_in_key_buffer = $C6
|
||||
.label reverse_video_flag = $C7
|
||||
.label end_of_input_line = $C8
|
||||
.label start_of_keyboard_input = $C9
|
||||
.label current_key_index_entry = $CB
|
||||
.label cursor_blink_disable = $CC
|
||||
.label cursor_blink_countdown = $CD
|
||||
.label cursor_saved_character = $CE
|
||||
.label cursor_is_visible = $CF
|
||||
.label keyboard_input_ready = $D0
|
||||
.label current_screen_line_ptr = $D1
|
||||
.label current_screen_x = $D3
|
||||
.label quote_mode_flag = $D4
|
||||
.label logical_line_length = $D5
|
||||
.label current_screen_y = $D6
|
||||
.label last_printed_character_ascii = $D7
|
||||
.label insert_mode = $D8
|
||||
// Bits 0 -3 = bits 8-11 of screen line address
|
||||
// Bit 7 = line spans multiple physical lines
|
||||
.label screen_line_link_table = $D9
|
||||
.label current_screen_line_colour_ptr = $F3
|
||||
.label keyboard_decoding_table_ptr = $F5
|
||||
.label rs232_rx_buffer_ptr = $F7
|
||||
.label rs232_tx_buffer_ptr = $F9
|
||||
|
||||
.alias basic_input_buffer BUF
|
||||
|
||||
; "Compute's Mapping the 64" book
|
||||
.alias keyboard_buffer $0277
|
||||
.alias text_colour $0286 ; p55
|
||||
.alias colour_under_cursor $0287 ; p56
|
||||
.alias key_buffer_size $0289 ; p57
|
||||
.label basic_input_buffer = BUF
|
||||
|
||||
;; 0 = cursor keys, insert, delete and space repeat, but nothing else
|
||||
;; 128 = all keys repeat
|
||||
;; 64 = no keys repeat
|
||||
.alias key_repeat_flags $028A ; p58
|
||||
;; https://www.c64-wiki.com/wiki/Page_2
|
||||
.alias key_repeat_counter $028B
|
||||
.alias key_first_repeat_delay $028C
|
||||
;; bit 0 = shift, 1 = Vendor Key, 2 = Control
|
||||
.alias key_bucky_state $028D
|
||||
.alias key_last_bucky_state $028E
|
||||
.alias keyboard_decoding_ptr $028F
|
||||
.alias enable_case_switch $0291
|
||||
.alias screen_scroll_disable $0292
|
||||
// "Compute's Mapping the 64" book
|
||||
.label keyboard_buffer = $0277
|
||||
.label text_colour = $0286 // p55
|
||||
.label colour_under_cursor = $0287 // p56
|
||||
.label key_buffer_size = $0289 // p57
|
||||
|
||||
;; BASIC uses some extra bytes for memory access under ROMs located at $2A7 onwards
|
||||
;; IRQs are disabled when doing such accesses, and a default NMI handler only increments
|
||||
;; a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured.
|
||||
.alias missed_nmi_flag $2A7
|
||||
.alias tiny_nmi_handler $2A8
|
||||
.alias shift_mem_up tiny_nmi_handler+shift_mem_up_routine-tiny_nmi_handler_routine
|
||||
.alias shift_mem_down tiny_nmi_handler+shift_mem_down_routine-tiny_nmi_handler_routine
|
||||
.alias peek_under_roms tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
|
||||
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
|
||||
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
|
||||
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
|
||||
// 0 = cursor keys, insert, delete and space repeat, but nothing else
|
||||
// 128 = all keys repeat
|
||||
// 64 = no keys repeat
|
||||
.label key_repeat_flags = $028A // p58
|
||||
// https://www.c64-wiki.com/wiki/Page_2
|
||||
.label key_repeat_counter = $028B
|
||||
.label key_first_repeat_delay = $028C
|
||||
// bit 0 = shift, 1 = Vendor Key, 2 = Control
|
||||
.label key_bucky_state = $028D
|
||||
.label key_last_bucky_state = $028E
|
||||
.label keyboard_decoding_ptr = $028F
|
||||
.label enable_case_switch = $0291
|
||||
.label screen_scroll_disable = $0292
|
||||
|
||||
// BASIC uses some extra bytes for memory access under ROMs located at $2A7 onwards
|
||||
// IRQs are disabled when doing such accesses, and a default NMI handler only increments
|
||||
// a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured.
|
||||
.label missed_nmi_flag = $2A7
|
||||
.label tiny_nmi_handler = $2A8
|
||||
.label shift_mem_up = tiny_nmi_handler+shift_mem_up_routine-tiny_nmi_handler_routine
|
||||
.label shift_mem_down = tiny_nmi_handler+shift_mem_down_routine-tiny_nmi_handler_routine
|
||||
.label peek_under_roms = tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
|
||||
.label poke_under_roms = tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
|
||||
.label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
|
||||
.label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
;; Target-specific hooks
|
||||
// Target-specific hooks
|
||||
|
||||
|
||||
.macro TARGET_HOOK_BANNER
|
||||
.macro TARGET_HOOK_BANNER() {
|
||||
|
||||
.byte " OPEN ROMS, ", $00
|
||||
.text " OPEN ROMS, "
|
||||
.byte $00
|
||||
|
||||
.macend
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
;; Target-specific hooks
|
||||
// Target-specific hooks
|
||||
|
||||
|
||||
.macro TARGET_HOOK_BANNER
|
||||
.macro TARGET_HOOK_BANNER() {
|
||||
|
||||
;; New banner from Retrofan
|
||||
// New banner from Retrofan
|
||||
.byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20
|
||||
.byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20
|
||||
.byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20
|
||||
@@ -21,21 +21,21 @@
|
||||
.byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f
|
||||
.byte $92, $0D, $0D, $05, $00
|
||||
|
||||
;; Original Deft-supplied banner
|
||||
;; .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0
|
||||
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0
|
||||
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20
|
||||
;; .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3
|
||||
;; .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20
|
||||
;; .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF
|
||||
;; .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E
|
||||
;; .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92
|
||||
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92
|
||||
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20
|
||||
;; .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3
|
||||
;; .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F
|
||||
;; .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F
|
||||
;; .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D
|
||||
;; .byte $0D,$05,$92,$00
|
||||
// Original Deft-supplied banner
|
||||
// .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0
|
||||
// .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0
|
||||
// .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20
|
||||
// .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3
|
||||
// .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20
|
||||
// .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF
|
||||
// .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E
|
||||
// .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92
|
||||
// .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92
|
||||
// .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20
|
||||
// .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3
|
||||
// .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F
|
||||
// .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F
|
||||
// .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D
|
||||
// .byte $0D,$05,$92,$00
|
||||
|
||||
.macend
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
|
||||
;; Target-specific hooks
|
||||
// Target-specific hooks
|
||||
|
||||
|
||||
.macro TARGET_HOOK_BANNER
|
||||
.macro TARGET_HOOK_BANNER() {
|
||||
|
||||
.byte " OPEN ROMS FOR ULTIMATE 64", $0D, $0D, " ", $00
|
||||
.text " OPEN ROMS FOR ULTIMATE 64"
|
||||
.byte $0D, $0D
|
||||
.text " "
|
||||
.byte $00
|
||||
|
||||
.macend
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
;; Compute's Mapping the C64 p88
|
||||
// Compute's Mapping the C64 p88
|
||||
|
||||
.word basic_cold_start
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
;; Compute's Mapping the C64 p88
|
||||
// Compute's Mapping the C64 p88
|
||||
|
||||
.word basic_warm_start
|
||||
@@ -1,6 +1,6 @@
|
||||
;; Compute's Mapping the 64, p89
|
||||
;; 8 character name
|
||||
;; MEGABAS2 = "MEGA BASIC 2"
|
||||
// Compute's Mapping the 64, p89
|
||||
// 8 character name
|
||||
// MEGABAS2 = "MEGA BASIC 2"
|
||||
|
||||
.byte $4D,$45,$47,$41,$42,$41,$53,$32
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
;; Print string at $YYAA
|
||||
;; Compute's Mapping the 64 p101
|
||||
// Print string at $YYAA
|
||||
// Compute's Mapping the 64 p101
|
||||
|
||||
print_string:
|
||||
;; Setup pointer
|
||||
// Setup pointer
|
||||
sty temp_string_ptr+1
|
||||
sta temp_string_ptr+0
|
||||
|
||||
txa
|
||||
txa
|
||||
pha
|
||||
|
||||
;; Get offset ready
|
||||
// Get offset ready
|
||||
ldy #$00
|
||||
|
||||
print_string_loop:
|
||||
;; Save Y in X, since X is preserved by chrout, but Y is not
|
||||
// Save Y in X, since X is preserved by chrout, but Y is not
|
||||
tya
|
||||
tax
|
||||
|
||||
@@ -28,7 +28,6 @@ print_string_loop:
|
||||
iny
|
||||
bne print_string_loop
|
||||
|
||||
|
||||
print_string_end:
|
||||
|
||||
pla
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
;; BASIC Cold start entry point
|
||||
;; Compute's Mapping the 64 p211
|
||||
// BASIC Cold start entry point
|
||||
// Compute's Mapping the 64 p211
|
||||
|
||||
basic_cold_start:
|
||||
;; Setup BASIC vectors at $0300
|
||||
;; Initialise interpretor
|
||||
;; Print start up message
|
||||
// Setup BASIC vectors at $0300
|
||||
// Initialise interpretor
|
||||
// Print start up message
|
||||
|
||||
;; Print coloured part of the message
|
||||
;; ldy #>startup_message
|
||||
;; lda #<startup_message
|
||||
;; jsr print_string
|
||||
// Print coloured part of the message
|
||||
// ldy #>startup_message
|
||||
// lda #<startup_message
|
||||
// jsr print_string
|
||||
|
||||
jsr printf // XXX don't use printf, keep it for debug purposes only
|
||||
|
||||
jsr printf
|
||||
; Used 217 bytes
|
||||
startup_banner:
|
||||
|
||||
`TARGET_HOOK_BANNER
|
||||
TARGET_HOOK_BANNER()
|
||||
|
||||
;; Print PAL/NTSC
|
||||
ldx #30 ; NTSC
|
||||
// Print PAL/NTSC
|
||||
ldx #30 // NTSC
|
||||
lda PALNTSC
|
||||
beq +
|
||||
ldx #31 ; PAL
|
||||
*
|
||||
beq !+
|
||||
ldx #31 // PAL
|
||||
!:
|
||||
jsr print_packed_message
|
||||
|
||||
;; Work out free bytes, and display
|
||||
// Work out free bytes, and display
|
||||
jsr basic_do_new
|
||||
lda basic_top_of_memory_ptr+0
|
||||
sec
|
||||
@@ -39,22 +39,21 @@ startup_banner:
|
||||
lda #$20
|
||||
jsr JCHROUT
|
||||
|
||||
;; Print the rest of the start up message
|
||||
// Print the rest of the start up message
|
||||
ldx #34
|
||||
jsr print_packed_message
|
||||
|
||||
;; jump into warm start loop
|
||||
// jump into warm start loop
|
||||
jmp basic_warm_start
|
||||
|
||||
|
||||
startup_message:
|
||||
;; Clear the screen
|
||||
startup_message: // XXX this is probably not needed anymore
|
||||
// Clear the screen
|
||||
.byte $93
|
||||
;; Vertical bars in different colours
|
||||
// Vertical bars in different colours
|
||||
.byte $1C,$B4
|
||||
.byte $9E,$B5
|
||||
.byte $1E,$A1
|
||||
;; <RVS><WHITE>MEGA<NORMAL>BASIC\r\r
|
||||
// <RVS><WHITE>MEGA<NORMAL>BASIC\r\r
|
||||
.byte $12,$05,$4D,$45,$47,$41,$92
|
||||
.byte $42,$41,$53,$49,$43
|
||||
.byte $20,$56,$32,$2e,$30,$2e,$30
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
;; Delete the current BASIC line, which is assumed to have already
|
||||
;; been found with basic_find_line.
|
||||
;; Really only consists of copying memory down.
|
||||
;; The only complication is that we have to do the copy with ROMs
|
||||
;; banked out. Oh, yes, and we have to update all the links in
|
||||
;; the following basic lines.
|
||||
// Delete the current BASIC line, which is assumed to have already
|
||||
// been found with basic_find_line.
|
||||
// Really only consists of copying memory down.
|
||||
// The only complication is that we have to do the copy with ROMs
|
||||
// banked out. Oh, yes, and we have to update all the links in
|
||||
// the following basic lines.
|
||||
|
||||
basic_delete_line:
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "DELETING LINE AT $"
|
||||
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "DELETING LINE AT $"
|
||||
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .byte $0d,0
|
||||
|
||||
;; Get address of next line
|
||||
// Get address of next line
|
||||
ldx #<basic_current_line_ptr
|
||||
ldy #0
|
||||
jsr peek_under_roms
|
||||
@@ -21,7 +22,7 @@ basic_delete_line:
|
||||
jsr peek_under_roms
|
||||
sta tokenise_work4
|
||||
|
||||
;; Work out length of this line by looking at the pointer
|
||||
// Work out length of this line by looking at the pointer
|
||||
lda tokenise_work3
|
||||
sec
|
||||
sbc basic_current_line_ptr+0
|
||||
@@ -30,31 +31,31 @@ basic_delete_line:
|
||||
sbc basic_current_line_ptr+1
|
||||
sta tokenise_work4
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "LINE LENGTH IS $"
|
||||
;; .byte $f0,<tokenise_work4,>tokenise_work4
|
||||
;; .byte $f0,<tokenise_work3,>tokenise_work3
|
||||
;; .byte $0d,0
|
||||
// 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.
|
||||
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
|
||||
!:
|
||||
// Length can now be safely assumed to be in the low
|
||||
// byte only, i.e., stored in tokenise_work3
|
||||
|
||||
lda tokenise_work3
|
||||
pha
|
||||
tax
|
||||
|
||||
;; Shuffle everything down
|
||||
// Shuffle everything down
|
||||
jsr basic_shift_mem_down_and_relink
|
||||
|
||||
;; Now decrease top of BASIC mem
|
||||
// Now decrease top of BASIC mem
|
||||
pla
|
||||
sta tokenise_work3
|
||||
lda basic_end_of_text_ptr+0
|
||||
|
||||
+13
-16
@@ -1,40 +1,37 @@
|
||||
;; Compute's Mapping the 64 p93
|
||||
// Compute's Mapping the 64 p93
|
||||
|
||||
basic_do_error:
|
||||
;; Save error number
|
||||
// Save error number
|
||||
txa
|
||||
pha
|
||||
|
||||
;; Print ? at start
|
||||
lda #$0d
|
||||
// Print ? at start
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
lda #$3f
|
||||
lda #$3F
|
||||
jsr JCHROUT
|
||||
|
||||
;; Print main part of error message
|
||||
// Print main part of error message
|
||||
pla
|
||||
tax
|
||||
jsr print_packed_message
|
||||
|
||||
;; Print ERROR at end
|
||||
// Print ERROR at end
|
||||
lda #$20
|
||||
jsr JCHROUT
|
||||
ldx #33
|
||||
jsr print_packed_message
|
||||
|
||||
;; XXX print IN if not in direct mode
|
||||
// XXX print IN if not in direct mode
|
||||
|
||||
;; XXX print line number if not in direct mode
|
||||
// XXX print line number if not in direct mode
|
||||
|
||||
lda #$0d
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
lda #$0d
|
||||
lda #$0D // XXX do we need this?
|
||||
jsr JCHROUT
|
||||
|
||||
;; Reset stack, and go back to main loop
|
||||
ldx #$fe
|
||||
// Reset stack, and go back to main loop
|
||||
ldx #$FE
|
||||
txs
|
||||
jmp basic_main_loop
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
;; Jump back into the BASIC execute line loop
|
||||
;; after first checking that we have a colon
|
||||
;; or $00 char
|
||||
// Jump back into the BASIC execute line loop
|
||||
// after first checking that we have a colon
|
||||
// or $00 char
|
||||
|
||||
basic_end_of_statement_check:
|
||||
ldx #<basic_current_statement_ptr
|
||||
ldy #0
|
||||
jsr peek_under_roms
|
||||
|
||||
;; Consume any spaces
|
||||
// Consume any spaces
|
||||
cmp #$20
|
||||
bne no_space_to_skip
|
||||
jsr basic_consume_character
|
||||
@@ -15,62 +15,62 @@ basic_end_of_statement_check:
|
||||
|
||||
no_space_to_skip:
|
||||
cmp #$00
|
||||
beq +
|
||||
beq !+
|
||||
cmp #$3a
|
||||
beq +
|
||||
beq !+
|
||||
|
||||
;; not end of statement
|
||||
// not end of statement
|
||||
clc
|
||||
rts
|
||||
*
|
||||
!:
|
||||
sec
|
||||
rts
|
||||
|
||||
basic_execute_statement:
|
||||
|
||||
;; Check for RUN/STOP
|
||||
// Check for RUN/STOP
|
||||
lda STKEY
|
||||
bmi +
|
||||
bmi !+
|
||||
jmp basic_do_break
|
||||
*
|
||||
;; Skip over any white space and :
|
||||
!:
|
||||
// Skip over any white space and :
|
||||
ldy #0
|
||||
ldx #<basic_current_statement_ptr
|
||||
jsr peek_under_roms
|
||||
jsr basic_end_of_statement_check
|
||||
bcs basic_end_of_line
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "LINE PTR = $"
|
||||
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte ", STATEMENT PTR = $"
|
||||
;; .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr
|
||||
;; .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr
|
||||
;; .byte $d,0
|
||||
// jsr printf
|
||||
// .text "LINE PTR = $"
|
||||
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .text ", STATEMENT PTR = $"
|
||||
// .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr
|
||||
// .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr
|
||||
// .byte $d,0
|
||||
|
||||
;; Go through the line until its end is reached.
|
||||
;; If we reach the end are in direct mode, then
|
||||
;; go back to reading input, else look for the
|
||||
;; next line, and advance to that, or else
|
||||
;; return to READY prompt because we have run out
|
||||
;; of program.
|
||||
// Go through the line until its end is reached.
|
||||
// If we reach the end are in direct mode, then
|
||||
// go back to reading input, else look for the
|
||||
// next line, and advance to that, or else
|
||||
// return to READY prompt because we have run out
|
||||
// of program.
|
||||
|
||||
;; Get next char of program text, even if it is hiding under a ROM or the
|
||||
;; IO area.
|
||||
// Get next char of program text, even if it is hiding under a ROM or the
|
||||
// IO area.
|
||||
ldx #<basic_current_statement_ptr
|
||||
ldy #0
|
||||
jsr peek_under_roms
|
||||
cmp #$00
|
||||
beq basic_end_of_line
|
||||
|
||||
;; The checks should be done in order of frequency, so that we are as
|
||||
;; fast as possible.
|
||||
// The checks should be done in order of frequency, so that we are as
|
||||
// fast as possible.
|
||||
|
||||
cmp #$7f
|
||||
bcc not_a_token
|
||||
;; It's a token: So get the jump table entry for it, push it on the stack
|
||||
;; and then RTS to start it.
|
||||
// It's a token: So get the jump table entry for it, push it on the stack
|
||||
// and then RTS to start it.
|
||||
asl
|
||||
tax
|
||||
lda basic_command_jump_table+1,x
|
||||
@@ -78,42 +78,42 @@ basic_execute_statement:
|
||||
lda basic_command_jump_table+0,x
|
||||
pha
|
||||
|
||||
;; Now consume the character
|
||||
// Now consume the character
|
||||
jsr basic_consume_character
|
||||
|
||||
rts
|
||||
|
||||
not_a_token:
|
||||
;; Space, which we can also just ignore
|
||||
// Space, which we can also just ignore
|
||||
cmp #$20
|
||||
beq basic_skip_char
|
||||
;; End of line?
|
||||
// End of line?
|
||||
cmp #$00
|
||||
beq basic_end_of_line
|
||||
;; :, i.e., statement separator, which we can simply ignore
|
||||
// :, i.e., statement separator, which we can simply ignore
|
||||
cmp #$3a
|
||||
beq basic_skip_char
|
||||
|
||||
;; START wedge support
|
||||
// START wedge support
|
||||
|
||||
;; Are we in direct mode?
|
||||
;; DOS Wedge is a hacky solution (inelegant, but convenient),
|
||||
;; BASIC programmers should implement communication with drives
|
||||
;; the standard way, handling channels properly. Besides,
|
||||
;; current implementation does not support characters under ROM
|
||||
// Are we in direct mode?
|
||||
// DOS Wedge is a hacky solution (inelegant, but convenient),
|
||||
// BASIC programmers should implement communication with drives
|
||||
// the standard way, handling channels properly. Besides,
|
||||
// current implementation does not support characters under ROM
|
||||
ldx basic_current_line_number+1
|
||||
cpx #$ff
|
||||
bne +
|
||||
;; We are in direct mode, allow wedge to handle '@' sign
|
||||
;; XXX Maybe it should be allowed only as the first command?
|
||||
bne !+
|
||||
// We are in direct mode, allow wedge to handle '@' sign
|
||||
// XXX Maybe it should be allowed only as the first command?
|
||||
cmp #$40
|
||||
bne +
|
||||
bne !+
|
||||
jsr basic_consume_character
|
||||
jmp wedge_dos
|
||||
*
|
||||
;; END wedge support
|
||||
!:
|
||||
// END wedge support
|
||||
|
||||
;; If all else fails, it's a syntax error
|
||||
// If all else fails, it's a syntax error
|
||||
jmp do_SYNTAX_error
|
||||
|
||||
basic_skip_char:
|
||||
@@ -124,14 +124,14 @@ basic_fetch_and_consume_character:
|
||||
ldy #0
|
||||
ldx #<basic_current_statement_ptr
|
||||
jsr peek_under_roms
|
||||
;; FALL THROUGH
|
||||
// FALL THROUGH
|
||||
|
||||
basic_consume_character:
|
||||
;; Advance basic text pointer
|
||||
// Advance basic text pointer
|
||||
inc basic_current_statement_ptr+0
|
||||
bne +
|
||||
bne !+
|
||||
inc basic_current_statement_ptr+1
|
||||
*
|
||||
!:
|
||||
rts
|
||||
|
||||
basic_unconsume_character:
|
||||
@@ -146,46 +146,46 @@ basic_unconsume_character:
|
||||
|
||||
basic_end_of_line:
|
||||
|
||||
;; XXX - If not in direct mode, then advance to next line, if there is
|
||||
;; one.
|
||||
// XXX - If not in direct mode, then advance to next line, if there is
|
||||
// one.
|
||||
|
||||
;; Are we in direct mode
|
||||
// Are we in direct mode
|
||||
lda basic_current_line_number+1
|
||||
cmp #$ff
|
||||
bne basic_not_direct_mode
|
||||
|
||||
;; Yes, we were in direct mode, so stop now
|
||||
// Yes, we were in direct mode, so stop now
|
||||
jmp basic_main_loop
|
||||
|
||||
basic_not_direct_mode:
|
||||
;; Copy line number to previous line number
|
||||
// Copy line number to previous line number
|
||||
lda basic_current_line_number+0
|
||||
sta basic_previous_line_number+0
|
||||
lda basic_current_line_number+1
|
||||
sta basic_previous_line_number+1
|
||||
|
||||
;; Advance the basic line pointer to the next line
|
||||
// Advance the basic line pointer to the next line
|
||||
jsr basic_follow_link_to_next_line
|
||||
|
||||
;; Are we at the end of the program?
|
||||
// Are we at the end of the program?
|
||||
lda basic_current_line_ptr+0
|
||||
ora basic_current_line_ptr+1
|
||||
bne basic_execute_from_current_line
|
||||
|
||||
;; End of program found
|
||||
// End of program found
|
||||
jmp basic_main_loop
|
||||
|
||||
basic_execute_from_current_line:
|
||||
;; Check if pointer is null, if so, we are at the end of
|
||||
;; the program.
|
||||
// Check if pointer is null, if so, we are at the end of
|
||||
// the program.
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_pointer_null_check
|
||||
bcs +
|
||||
;; End of program reached
|
||||
bcs !+
|
||||
// End of program reached
|
||||
jmp basic_main_loop
|
||||
*
|
||||
;; Skip pointer and line number to get address of first statement
|
||||
!:
|
||||
// Skip pointer and line number to get address of first statement
|
||||
lda basic_current_line_ptr+0
|
||||
clc
|
||||
adc #4
|
||||
@@ -194,7 +194,7 @@ basic_execute_from_current_line:
|
||||
adc #0
|
||||
sta basic_current_statement_ptr+1
|
||||
|
||||
;; Store line number
|
||||
// Store line number
|
||||
ldx #<basic_current_line_ptr
|
||||
ldy #2
|
||||
jsr peek_under_roms
|
||||
@@ -206,7 +206,7 @@ basic_execute_from_current_line:
|
||||
jmp basic_execute_statement
|
||||
|
||||
basic_command_jump_table:
|
||||
;; $80 - $8F
|
||||
// $80 - $8F
|
||||
.word cmd_end-1
|
||||
.word cmd_for-1
|
||||
.word cmd_next-1
|
||||
@@ -221,10 +221,10 @@ basic_command_jump_table:
|
||||
.word cmd_if-1
|
||||
.word cmd_restore-1
|
||||
.word cmd_gosub-1
|
||||
.word cmd_return -1
|
||||
.word cmd_return-1
|
||||
.word cmd_rem-1
|
||||
|
||||
;; $90-$9F
|
||||
// $90-$9F
|
||||
.word cmd_stop-1
|
||||
.word cmd_on-1
|
||||
.word cmd_wait-1
|
||||
@@ -242,7 +242,7 @@ basic_command_jump_table:
|
||||
.word cmd_sys-1
|
||||
.word cmd_open-1
|
||||
|
||||
;; $A0-$AF
|
||||
// $A0-$AF
|
||||
.word cmd_close-1
|
||||
.word cmd_get-1
|
||||
.word cmd_new-1
|
||||
@@ -260,7 +260,7 @@ basic_command_jump_table:
|
||||
.word cmd_exponent-1
|
||||
.word cmd_and-1
|
||||
|
||||
;; $B0-$BF
|
||||
// $B0-$BF
|
||||
.word cmd_or-1
|
||||
.word cmd_greater-1
|
||||
.word cmd_equal-1
|
||||
@@ -278,7 +278,7 @@ basic_command_jump_table:
|
||||
.word cmd_cos-1
|
||||
.word cmd_sin-1
|
||||
|
||||
;; $C0-$CF
|
||||
// $C0-$CF
|
||||
.word cmd_tan-1
|
||||
.word cmd_atn-1
|
||||
.word cmd_peek-1
|
||||
@@ -291,13 +291,13 @@ basic_command_jump_table:
|
||||
.word cmd_right-1
|
||||
.word cmd_mid-1
|
||||
.word cmd_go-1
|
||||
;; Undefined tokens
|
||||
// Undefined tokens
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
|
||||
;; $D0-$DF
|
||||
// $D0-$DF
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
@@ -315,7 +315,7 @@ basic_command_jump_table:
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
|
||||
;; $E0-$EF
|
||||
// $E0-$EF
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
@@ -333,7 +333,7 @@ basic_command_jump_table:
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
|
||||
;; $F0-$FF
|
||||
// $F0-$FF
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
@@ -350,4 +350,3 @@ basic_command_jump_table:
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
.word cmd_unimplemented-1
|
||||
|
||||
+13
-13
@@ -1,50 +1,50 @@
|
||||
;; Find the BASIC line with number basic_line_number
|
||||
// Find the BASIC line with number basic_line_number
|
||||
|
||||
|
||||
basic_find_line:
|
||||
;; Get pointer to start of BASIC text
|
||||
// Get pointer to start of BASIC text
|
||||
lda basic_start_of_text_ptr+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda basic_start_of_text_ptr+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
basic_find_line_loop:
|
||||
;; Then search for line number
|
||||
;; Line number
|
||||
// Then search for line number
|
||||
// Line number
|
||||
|
||||
ldy #3
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_under_roms
|
||||
cmp basic_line_number+1
|
||||
beq +
|
||||
beq !+
|
||||
bcs line_num_too_high
|
||||
bne not_this_line
|
||||
*
|
||||
!:
|
||||
|
||||
dey
|
||||
jsr peek_under_roms
|
||||
cmp basic_line_number+0
|
||||
beq +
|
||||
beq !+
|
||||
bcs line_num_too_high
|
||||
bne not_this_line
|
||||
*
|
||||
!:
|
||||
clc
|
||||
rts
|
||||
not_this_line:
|
||||
;; Not this line, so advance to next line
|
||||
// Not this line, so advance to next line
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_pointer_null_check
|
||||
bcs more_lines_exist
|
||||
|
||||
;; no more lines exist, return failure
|
||||
// no more lines exist, return failure
|
||||
line_num_too_high:
|
||||
sec
|
||||
rts
|
||||
more_lines_exist:
|
||||
|
||||
;; XXX - Add program mangled check here to be triggered
|
||||
;; if the link goes backwards.
|
||||
;; Follow link to next line
|
||||
// XXX - Add program mangled check here to be triggered
|
||||
// if the link goes backwards.
|
||||
// Follow link to next line
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_under_roms
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
;; Advance basic_current_line_ptr by following the
|
||||
;; link to the next line
|
||||
// Advance basic_current_line_ptr by following the
|
||||
// link to the next line
|
||||
|
||||
basic_find_next_line:
|
||||
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
;; Insert the tokenised line stored at $0200.
|
||||
;; First work out where in the list to put it
|
||||
;; (basic_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 the tokenised line stored at $0200.
|
||||
// First work out where in the list to put it
|
||||
// (basic_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.
|
||||
|
||||
basic_insert_line:
|
||||
|
||||
;; ASSUMES basic_find_line has been called to set the insert point.
|
||||
;; We need to insert space for the link link token, the line number,
|
||||
;; and the zero-terminated line itself. This means 2+2+1 plus length
|
||||
;; of tokenised string after the line number
|
||||
// ASSUMES basic_find_line has been called to set the insert point.
|
||||
// We need to insert space for the link link token, the line number,
|
||||
// and the zero-terminated line itself. This means 2+2+1 plus length
|
||||
// of tokenised string after the line number
|
||||
|
||||
;; But first, remember where the pointer will be, so that we can
|
||||
;; put the line in there after.
|
||||
// But first, remember where the pointer will be, so that we can
|
||||
// put the line in there after.
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "INSERTING LINE AT $"
|
||||
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "INSERTING LINE AT $"
|
||||
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
|
||||
// .byte $0d,0
|
||||
|
||||
lda basic_current_line_ptr+0
|
||||
pha
|
||||
@@ -27,20 +28,20 @@ basic_insert_line:
|
||||
|
||||
pha
|
||||
|
||||
;; Get number of bytes in tokenised line after line number
|
||||
// Get number of bytes in tokenised line after line number
|
||||
lda tokenise_work2
|
||||
sec
|
||||
sbc tokenise_work1
|
||||
;; Add on the four bytes space we need
|
||||
// Add on the four bytes space we need
|
||||
clc
|
||||
adc #5
|
||||
pha
|
||||
tax
|
||||
|
||||
;; Make the space
|
||||
// Make the space
|
||||
jsr basic_shift_mem_up_and_relink
|
||||
|
||||
;; Now increase top of BASIC mem
|
||||
// Now increase top of BASIC mem
|
||||
pla
|
||||
clc
|
||||
adc basic_end_of_text_ptr+0
|
||||
@@ -49,13 +50,13 @@ basic_insert_line:
|
||||
adc #0
|
||||
sta basic_end_of_text_ptr+1
|
||||
|
||||
;; Get pointer back
|
||||
// Get pointer back
|
||||
pla
|
||||
sta basic_current_line_ptr+1
|
||||
pla
|
||||
sta basic_current_line_ptr+0
|
||||
|
||||
;; Write the line number
|
||||
// Write the line number
|
||||
ldy #2
|
||||
ldx #<basic_current_line_ptr
|
||||
lda basic_line_number+0
|
||||
@@ -64,7 +65,7 @@ basic_insert_line:
|
||||
lda basic_line_number+1
|
||||
jsr poke_under_roms
|
||||
|
||||
;; Now store the line body itself
|
||||
// Now store the line body itself
|
||||
inc tokenise_work2
|
||||
line_store_loop:
|
||||
ldx tokenise_work1
|
||||
|
||||
+50
-51
@@ -1,43 +1,43 @@
|
||||
basic_main_loop:
|
||||
|
||||
;; XXX - Check if direct or program mode, and get next line of input
|
||||
;; the appropriate way.
|
||||
;; XXX - For now, it is hard coded to direct mode
|
||||
// XXX - Check if direct or program mode, and get next line of input
|
||||
// the appropriate way.
|
||||
// XXX - For now, it is hard coded to direct mode
|
||||
|
||||
;; Tell user we are ready
|
||||
// Tell user we are ready
|
||||
jsr ready_message
|
||||
|
||||
basic_read_next_line:
|
||||
;; Read a line of input
|
||||
// Read a line of input
|
||||
ldx #$00
|
||||
read_line_loop:
|
||||
|
||||
jsr $ffcf ; KERNAL CHRIN
|
||||
jsr JCHRIN
|
||||
bcs read_line_loop
|
||||
|
||||
cmp #$0d
|
||||
beq got_line_of_input
|
||||
;; Not carriage return, so try to append to line so far
|
||||
// Not carriage return, so try to append to line so far
|
||||
cpx #80
|
||||
bcc +
|
||||
;; Report STRING TOO LONG error (Compute's Mapping the 64 p93)
|
||||
bcc !+
|
||||
// Report STRING TOO LONG error (Compute's Mapping the 64 p93)
|
||||
ldx #22
|
||||
jmp basic_do_error
|
||||
*
|
||||
!:
|
||||
sta basic_input_buffer,x
|
||||
inx
|
||||
jmp read_line_loop
|
||||
|
||||
got_line_of_input:
|
||||
|
||||
;; Store length of input buffer ready for tokenising
|
||||
// Store length of input buffer ready for tokenising
|
||||
stx tokenise_work1
|
||||
|
||||
;; Strip leading spaces from the line
|
||||
// Strip leading spaces from the line
|
||||
remove_leading_spaces:
|
||||
lda $0200
|
||||
cmp #$20
|
||||
bne +
|
||||
bne !+
|
||||
ldx #1
|
||||
rsl_l1: lda $0200,x
|
||||
sta $01ff,x
|
||||
@@ -45,40 +45,40 @@ rsl_l1: lda $0200,x
|
||||
cpx tokenise_work1
|
||||
bne rsl_l1
|
||||
|
||||
;; Reduce length of input by one
|
||||
// Reduce length of input by one
|
||||
dec tokenise_work1
|
||||
;; Stop trying to rim if we run out of input
|
||||
// Stop trying to rim if we run out of input
|
||||
bne remove_leading_spaces
|
||||
*
|
||||
;; Do printing of the new line
|
||||
!:
|
||||
// Do printing of the new line
|
||||
lda #$0d
|
||||
jsr JCHROUT
|
||||
|
||||
;; Ignore empty lines
|
||||
// Ignore empty lines
|
||||
lda tokenise_work1
|
||||
beq basic_read_next_line
|
||||
|
||||
;; Else, tokenise the line
|
||||
// Else, tokenise the line
|
||||
jsr tokenise_line
|
||||
|
||||
;; Has the user entered a line of BASIC beginning with a number?
|
||||
// Has the user entered a line of BASIC beginning with a number?
|
||||
lda $0200
|
||||
cmp #$30
|
||||
bcc not_a_line
|
||||
cmp #$39
|
||||
bcs not_a_line
|
||||
|
||||
;; Yes, the line begins with a number.
|
||||
;; Parse the line number and check validity
|
||||
// Yes, the line begins with a number.
|
||||
// Parse the line number and check validity
|
||||
|
||||
;; injest_number follows tokenise_work1 as the offset into the line,
|
||||
;; so remember the line length somewhere else for now.
|
||||
// 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
|
||||
// Try to read line number
|
||||
lda #<$0200
|
||||
sta basic_current_statement_ptr+0
|
||||
lda #>$0200
|
||||
@@ -86,67 +86,66 @@ rsl_l1: lda $0200,x
|
||||
|
||||
jsr basic_parse_line_number
|
||||
|
||||
;; Get pointer to next char
|
||||
// Get pointer to next char
|
||||
lda basic_current_statement_ptr+0
|
||||
sta tokenise_work1
|
||||
|
||||
;; Got a valid line number -- so do add/del line
|
||||
// Got a valid line number -- so do add/del line
|
||||
|
||||
;; Skip any spaces after the line number
|
||||
// Skip any spaces after the line number
|
||||
ldx tokenise_work1
|
||||
skip_spaces:
|
||||
lda $0200,x
|
||||
cmp #$20
|
||||
bne +
|
||||
bne !+
|
||||
inx
|
||||
bne skip_spaces
|
||||
* stx tokenise_work1
|
||||
!: stx tokenise_work1
|
||||
|
||||
;; First, clear all variables, so that we only have to shove BASIC text around.
|
||||
;; (We could later remove this requirement, and the only effect should be
|
||||
;; to slow things down, and that you might have to either CLR if there is no
|
||||
;; memory free, or else it would auto CLR when you ran out of program space).
|
||||
// First, clear all variables, so that we only have to shove BASIC text around.
|
||||
// (We could later remove this requirement, and the only effect should be
|
||||
// to slow things down, and that you might have to either CLR if there is no
|
||||
// memory free, or else it would auto CLR when you ran out of program space).
|
||||
jsr basic_do_clr
|
||||
|
||||
;; Delete line if present
|
||||
// Delete line if present
|
||||
jsr basic_find_line
|
||||
|
||||
bcs +
|
||||
bcs !+
|
||||
|
||||
;; Delete the line, whether we are deleting or
|
||||
;; replacing the line
|
||||
// Delete the line, whether we are deleting or
|
||||
// replacing the line
|
||||
jsr basic_delete_line
|
||||
*
|
||||
;; Insert new line if non-zero length, i.e., that
|
||||
;; we are not just deleting the line.
|
||||
!:
|
||||
// Insert new line if non-zero length, i.e., that
|
||||
// we are not just deleting the line.
|
||||
lda tokenise_work1
|
||||
cmp tokenise_work2
|
||||
beq +
|
||||
beq !+
|
||||
jsr basic_insert_line
|
||||
*
|
||||
;; No READY message after entering or deleting a line of BASIC
|
||||
!:
|
||||
// No READY message after entering or deleting a line of BASIC
|
||||
jmp basic_read_next_line
|
||||
|
||||
not_a_line:
|
||||
|
||||
;; Actually interpret the line
|
||||
// Actually interpret the line
|
||||
|
||||
;; Setup pointer to the statement
|
||||
// Setup pointer to the statement
|
||||
lda #<$0200
|
||||
sta basic_current_statement_ptr+0
|
||||
lda #>$0200
|
||||
sta basic_current_statement_ptr+1
|
||||
|
||||
;; There is no stored line, so zero that pointer out
|
||||
// There is no stored line, so zero that pointer out
|
||||
lda #$00
|
||||
sta basic_current_line_ptr+0
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
;; Put invalid line number in current line number value,
|
||||
;; so that we know we are in direct mode
|
||||
;; (Compute's Mapping the 64 p19)
|
||||
// Put invalid line number in current line number value,
|
||||
// so that we know we are in direct mode
|
||||
// (Compute's Mapping the 64 p19)
|
||||
lda #$ff
|
||||
sta basic_current_line_number+1
|
||||
|
||||
jmp basic_execute_statement
|
||||
|
||||
@@ -3,22 +3,22 @@ basic_parse_line_number:
|
||||
|
||||
jsr injest_number
|
||||
|
||||
;; Check if the number is a valid line number
|
||||
;; i.e., 16 bits, no exponent, no decimal
|
||||
// Check if the number is a valid line number
|
||||
// i.e., 16 bits, no exponent, no decimal
|
||||
lda basic_fac1_mantissa+2
|
||||
ora basic_fac1_mantissa+3
|
||||
ora basic_fac1_exponent
|
||||
beq +
|
||||
beq !+
|
||||
ml_bad_line_number:
|
||||
;; Invalid line number
|
||||
// Invalid line number
|
||||
jmp do_ILLEGAL_QUANTITY_error
|
||||
*
|
||||
;; Line number are not allowed to have decimal points in them
|
||||
!:
|
||||
// Line number are not allowed to have decimal points in them
|
||||
lda tokenise_work4
|
||||
cmp #$ff
|
||||
cmp #$FF
|
||||
bne ml_bad_line_number
|
||||
|
||||
;; Got a valid line number.
|
||||
// Got a valid line number.
|
||||
lda basic_fac1_mantissa+0
|
||||
sta basic_line_number+0
|
||||
lda basic_fac1_mantissa+1
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
basic_shift_mem_down_and_relink:
|
||||
;; Shift memory down to basic_current_line_pointer
|
||||
;; from X bytes further along.
|
||||
// Shift memory down to basic_current_line_pointer
|
||||
// from X bytes further along.
|
||||
|
||||
;; Destination is basic_current_line_ptr
|
||||
// Destination is basic_current_line_ptr
|
||||
lda basic_current_line_ptr+0
|
||||
sta memmove_dst+0
|
||||
lda basic_current_line_ptr+1
|
||||
sta memmove_dst+1
|
||||
|
||||
;; Source is that plus X
|
||||
// Source is that plus X
|
||||
txa
|
||||
pha ; also keep for later
|
||||
pha // also keep for later
|
||||
clc
|
||||
adc basic_current_line_ptr+0
|
||||
sta memmove_src+0
|
||||
@@ -18,7 +18,7 @@ basic_shift_mem_down_and_relink:
|
||||
adc #0
|
||||
sta memmove_src+1
|
||||
|
||||
;; Size is distance from source to end of BASIC text.
|
||||
// Size is distance from source to end of BASIC text.
|
||||
lda basic_end_of_text_ptr+0
|
||||
sec
|
||||
sbc memmove_src+0
|
||||
@@ -27,32 +27,32 @@ basic_shift_mem_down_and_relink:
|
||||
sbc memmove_src+1
|
||||
sta memmove_size+1
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "TOP OF BASIC = $"
|
||||
;; .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $0d
|
||||
;; .byte "SHIFTING DOWN $"
|
||||
;; .byte $f1,<memmove_size,>memmove_size
|
||||
;; .byte $f0,<memmove_size,>memmove_size
|
||||
;; .byte " BYTES FROM $"
|
||||
;; .byte $f1,<memmove_src,>memmove_src
|
||||
;; .byte $f0,<memmove_src,>memmove_src
|
||||
;; .byte " TO $"
|
||||
;; .byte $f1,<memmove_dst,>memmove_dst
|
||||
;; .byte $f0,<memmove_dst,>memmove_dst
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "TOP OF BASIC = $"
|
||||
// .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
// .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
// .byte $0d
|
||||
// .text "SHIFTING DOWN $"
|
||||
// .byte $f1,<memmove_size,>memmove_size
|
||||
// .byte $f0,<memmove_size,>memmove_size
|
||||
// .text " BYTES FROM $"
|
||||
// .byte $f1,<memmove_src,>memmove_src
|
||||
// .byte $f0,<memmove_src,>memmove_src
|
||||
// .text " TO $"
|
||||
// .byte $f1,<memmove_dst,>memmove_dst
|
||||
// .byte $f0,<memmove_dst,>memmove_dst
|
||||
// .byte $0d,0
|
||||
|
||||
;; The copy routine that copies under the ROMs is as simple
|
||||
;; as possible to be as small as possible, so we have
|
||||
;; to adjust the pointers and counts so that the simple
|
||||
;; increment and decrement bounds checks work.
|
||||
// The copy routine that copies under the ROMs is as simple
|
||||
// as possible to be as small as possible, so we have
|
||||
// to adjust the pointers and counts so that the simple
|
||||
// increment and decrement bounds checks work.
|
||||
|
||||
;; Specifically we want Y pre-set so that the end of the
|
||||
;; copy ends when Y = $00.
|
||||
;; So if copying 1 byte, we want Y=$FF
|
||||
;; This means we have to then reduce the source and
|
||||
;; target pointers by the same amount
|
||||
// Specifically we want Y pre-set so that the end of the
|
||||
// copy ends when Y = $00.
|
||||
// So if copying 1 byte, we want Y=$FF
|
||||
// This means we have to then reduce the source and
|
||||
// target pointers by the same amount
|
||||
|
||||
lda memmove_size+0
|
||||
eor #$ff
|
||||
@@ -75,50 +75,50 @@ basic_shift_mem_down_and_relink:
|
||||
sbc #0
|
||||
sta memmove_dst+1
|
||||
|
||||
;; Increase copy page count so we can post-decrement compare with $00
|
||||
// Increase copy page count so we can post-decrement compare with $00
|
||||
inc memmove_size+1
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "REVISED BOUNDS $"
|
||||
;; .byte $f1,<memmove_size,>memmove_size
|
||||
;; .byte $f0,<memmove_size,>memmove_size
|
||||
;; .byte " BYTES FROM $"
|
||||
;; .byte $f1,<memmove_src,>memmove_src
|
||||
;; .byte $f0,<memmove_src,>memmove_src
|
||||
;; .byte " TO $"
|
||||
;; .byte $f1,<memmove_dst,>memmove_dst
|
||||
;; .byte $f0,<memmove_dst,>memmove_dst
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "REVISED BOUNDS $"
|
||||
// .byte $f1,<memmove_size,>memmove_size
|
||||
// .byte $f0,<memmove_size,>memmove_size
|
||||
// .text " BYTES FROM $"
|
||||
// .byte $f1,<memmove_src,>memmove_src
|
||||
// .byte $f0,<memmove_src,>memmove_src
|
||||
// .text " TO $"
|
||||
// .byte $f1,<memmove_dst,>memmove_dst
|
||||
// .byte $f0,<memmove_dst,>memmove_dst
|
||||
// .byte $0d,0
|
||||
|
||||
;; Get Y value ready for the copy
|
||||
// Get Y value ready for the copy
|
||||
ldy memmove_size+0
|
||||
|
||||
jsr shift_mem_down
|
||||
|
||||
;; Get length of deletion back
|
||||
// Get length of deletion back
|
||||
pla
|
||||
sta tokenise_work3
|
||||
|
||||
;; Check if we still have any lines left
|
||||
// Check if we still have any lines left
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_pointer_null_check
|
||||
bcs relink_down_next_line
|
||||
;; Nope, so just return
|
||||
// Nope, so just return
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
relink_down_next_line:
|
||||
;; inc $d020
|
||||
;; jmp relink_down_next_line
|
||||
// inc $d020
|
||||
// jmp relink_down_next_line
|
||||
|
||||
;; Subtract tokenise_work3 from the pointer
|
||||
// Subtract tokenise_work3 from the pointer
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr+0
|
||||
jsr peek_under_roms
|
||||
sec
|
||||
sbc tokenise_Work3
|
||||
sbc tokenise_work3
|
||||
sta memmove_src+0
|
||||
iny
|
||||
jsr peek_under_roms
|
||||
@@ -134,13 +134,13 @@ relink_down_next_line:
|
||||
jsr poke_under_roms
|
||||
|
||||
relink_down_loop:
|
||||
;; Now advance pointer to the next line,
|
||||
// Now advance pointer to the next line,
|
||||
lda memmove_src+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda memmove_src+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
;; Have we run out of lines to patch?
|
||||
// Have we run out of lines to patch?
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_pointer_null_check
|
||||
bcs relink_down_next_line
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
|
||||
basic_shift_mem_up_and_relink:
|
||||
;; Shift memory up from basic_current_line_ptr
|
||||
;; X bytes.
|
||||
// Shift memory up from basic_current_line_ptr
|
||||
// X bytes.
|
||||
|
||||
;; NOTE: Pointers need to be reduced by one, due to the way
|
||||
;; the copyroutine works, so we do that here.
|
||||
;; Work out end point of destination
|
||||
// NOTE: Pointers need to be reduced by one, due to the way
|
||||
// the copyroutine works, so we do that here.
|
||||
// Work out end point of destination
|
||||
txa
|
||||
clc
|
||||
adc basic_end_of_text_ptr+0
|
||||
@@ -22,7 +22,7 @@ basic_shift_mem_up_and_relink:
|
||||
sbc #0
|
||||
sta memmove_dst+1
|
||||
|
||||
;; End point of source is just current end of BASIC text
|
||||
// End point of source is just current end of BASIC text
|
||||
lda basic_end_of_text_ptr+0
|
||||
sec
|
||||
sbc #1
|
||||
@@ -31,7 +31,7 @@ basic_shift_mem_up_and_relink:
|
||||
sbc #0
|
||||
sta memmove_src+1
|
||||
|
||||
;; Work out size of region to copy
|
||||
// Work out size of region to copy
|
||||
lda basic_end_of_text_ptr+0
|
||||
sec
|
||||
sbc basic_current_line_ptr+0
|
||||
@@ -40,25 +40,25 @@ basic_shift_mem_up_and_relink:
|
||||
sbc basic_current_line_ptr+1
|
||||
sta memmove_size+1
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "TOP OF BASIC = $"
|
||||
;; .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $0d
|
||||
;; .byte "SHIFTING UP $"
|
||||
;; .byte $f1,<memmove_size,>memmove_size
|
||||
;; .byte $f0,<memmove_size,>memmove_size
|
||||
;; .byte " BYTES FROM $"
|
||||
;; .byte $f1,<memmove_src,>memmove_src
|
||||
;; .byte $f0,<memmove_src,>memmove_src
|
||||
;; .byte " TO $"
|
||||
;; .byte $f1,<memmove_dst,>memmove_dst
|
||||
;; .byte $f0,<memmove_dst,>memmove_dst
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "TOP OF BASIC = $"
|
||||
// .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
// .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
|
||||
// .byte $0d
|
||||
// .text "SHIFTING UP $"
|
||||
// .byte $f1,<memmove_size,>memmove_size
|
||||
// .byte $f0,<memmove_size,>memmove_size
|
||||
// .text " BYTES FROM $"
|
||||
// .byte $f1,<memmove_src,>memmove_src
|
||||
// .byte $f0,<memmove_src,>memmove_src
|
||||
// .text " TO $"
|
||||
// .byte $f1,<memmove_dst,>memmove_dst
|
||||
// .byte $f0,<memmove_dst,>memmove_dst
|
||||
// .byte $0d,0
|
||||
|
||||
;; To make life simple for the copy routine that lives in RAM,
|
||||
;; we have to adjust the end pointers down one page and set Y to the low
|
||||
;; byte of the copy size.
|
||||
// To make life simple for the copy routine that lives in RAM,
|
||||
// we have to adjust the end pointers down one page and set Y to the low
|
||||
// byte of the copy size.
|
||||
lda memmove_src+0
|
||||
sec
|
||||
sbc memmove_size+0
|
||||
@@ -75,35 +75,35 @@ basic_shift_mem_up_and_relink:
|
||||
sbc #0
|
||||
sta memmove_dst+1
|
||||
|
||||
;; Now make exit easy, by being able to check for zero on size high byte when done
|
||||
// Now make exit easy, by being able to check for zero on size high byte when done
|
||||
inc memmove_size+1
|
||||
|
||||
;; Then set Y to the number offset required
|
||||
// Then set Y to the number offset required
|
||||
ldy memmove_size+0
|
||||
iny
|
||||
|
||||
stx tokenise_work3
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "REVISED BOUNDS $"
|
||||
;; .byte $f1,<memmove_size,>memmove_size
|
||||
;; .byte $f0,<memmove_size,>memmove_size
|
||||
;; .byte " BYTES FROM $"
|
||||
;; .byte $f1,<memmove_src,>memmove_src
|
||||
;; .byte $f0,<memmove_src,>memmove_src
|
||||
;; .byte " TO $"
|
||||
;; .byte $f1,<memmove_dst,>memmove_dst
|
||||
;; .byte $f0,<memmove_dst,>memmove_dst
|
||||
;; .byte $0d,0
|
||||
// jsr printf
|
||||
// .text "REVISED BOUNDS $"
|
||||
// .byte $f1,<memmove_size,>memmove_size
|
||||
// .byte $f0,<memmove_size,>memmove_size
|
||||
// .text " BYTES FROM $"
|
||||
// .byte $f1,<memmove_src,>memmove_src
|
||||
// .byte $f0,<memmove_src,>memmove_src
|
||||
// .text " TO $"
|
||||
// .byte $f1,<memmove_dst,>memmove_dst
|
||||
// .byte $f0,<memmove_dst,>memmove_dst
|
||||
// .byte $0d,0
|
||||
|
||||
;; Do the copy
|
||||
// Do the copy
|
||||
jsr shift_mem_up
|
||||
|
||||
;; Now fix the pointer to the next line
|
||||
// Now fix the pointer to the next line
|
||||
|
||||
;; First, we need to point the current BASIC line
|
||||
;; pointer to itself, so that we can add the shift
|
||||
;; to make it end up pointing to the next line
|
||||
// First, we need to point the current BASIC line
|
||||
// pointer to itself, so that we can add the shift
|
||||
// to make it end up pointing to the next line
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr+0
|
||||
lda basic_current_line_ptr+0
|
||||
@@ -113,10 +113,10 @@ basic_shift_mem_up_and_relink:
|
||||
jsr poke_under_roms
|
||||
|
||||
relink_up_next_line:
|
||||
;; inc $d020
|
||||
;; jmp relink_up_next_line
|
||||
// inc $d020
|
||||
// jmp relink_up_next_line
|
||||
|
||||
;; Advance pointer by tokenise_word3 bytes
|
||||
// Advance pointer by tokenise_word3 bytes
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr+0
|
||||
jsr peek_under_roms
|
||||
@@ -132,20 +132,20 @@ relink_up_next_line:
|
||||
adc #0
|
||||
sta memmove_src+1
|
||||
|
||||
;; jsr printf
|
||||
;; .byte "LINE ADDR = $"
|
||||
;; .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr
|
||||
;; .byte $d," BEFORE = $"
|
||||
;; .byte $f1,<memmove_dst,>memmove_dst
|
||||
;; .byte $f0,<memmove_dst,>memmove_dst
|
||||
;; .byte ", AFTER = $"
|
||||
;; .byte $f1,<memmove_src,>memmove_src
|
||||
;; .byte $f0,<memmove_src,>memmove_src
|
||||
;; .byte $d
|
||||
;; .byte 0
|
||||
// jsr printf
|
||||
// .text "LINE ADDR = $"
|
||||
// .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr
|
||||
// .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr
|
||||
// .text $d," BEFORE = $"
|
||||
// .byte $f1,<memmove_dst,>memmove_dst
|
||||
// .byte $f0,<memmove_dst,>memmove_dst
|
||||
// .text ", AFTER = $"
|
||||
// .byte $f1,<memmove_src,>memmove_src
|
||||
// .byte $f0,<memmove_src,>memmove_src
|
||||
// .byte $d
|
||||
// .byte 0
|
||||
|
||||
;; Write memmove_src back to current line pointer
|
||||
// Write memmove_src back to current line pointer
|
||||
ldy #0
|
||||
ldx #<basic_current_line_ptr
|
||||
lda memmove_src+0
|
||||
@@ -156,13 +156,13 @@ relink_up_next_line:
|
||||
|
||||
|
||||
relink_up_loop:
|
||||
;; Now advance pointer to the next line,
|
||||
// Now advance pointer to the next line,
|
||||
lda memmove_src+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda memmove_src+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
;; Have we run out of lines to patch?
|
||||
// Have we run out of lines to patch?
|
||||
ldx #<basic_current_line_ptr
|
||||
jsr peek_pointer_null_check
|
||||
bcs relink_up_next_line
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
;; Clear screen etc, show READY prompt.
|
||||
// Clear screen etc, show READY prompt.
|
||||
|
||||
basic_warm_start:
|
||||
jsr install_ram_routines
|
||||
|
||||
;; If warm start caused by BRK, print it address
|
||||
// If warm start caused by BRK, print it address
|
||||
lda CMP0
|
||||
ora CMP0+1
|
||||
beq +
|
||||
beq !+
|
||||
|
||||
ldx #32
|
||||
jsr print_packed_message
|
||||
@@ -18,6 +18,6 @@ basic_warm_start:
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
|
||||
*
|
||||
!:
|
||||
jmp basic_main_loop
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
;; Skip the gap between $C000-$DFFF
|
||||
.checkpc $C000
|
||||
.advance $DFFF,$00
|
||||
.checkpc $E000
|
||||
// Skip the gap between $C000-$DFFF
|
||||
|
||||
.fill $2000, $00
|
||||
+13
-12
@@ -1,23 +1,24 @@
|
||||
cmd_stop:
|
||||
basic_do_break:
|
||||
jsr printf
|
||||
.byte "BREAK",0
|
||||
jsr printf // XXX don't use printf, use packed messages!
|
||||
.text "BREAK"
|
||||
.byte 0
|
||||
|
||||
;; Check for direct mode
|
||||
;; Are we in direct mode
|
||||
// Check for direct mode
|
||||
// Are we in direct mode
|
||||
lda basic_current_line_number+1
|
||||
cmp #$ff
|
||||
beq +
|
||||
;; Not direct mode
|
||||
jsr printf
|
||||
.byte " IN ",0
|
||||
cmp #$FF
|
||||
beq !+
|
||||
// Not direct mode
|
||||
jsr printf // XXX don't use printf, use packed messages!
|
||||
.text " IN "
|
||||
.byte 0
|
||||
lda basic_current_line_number+1
|
||||
ldx basic_current_line_number+0
|
||||
jsr print_integer
|
||||
|
||||
*
|
||||
lda #$0d
|
||||
!:
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
cmd_end:
|
||||
jmp basic_main_loop
|
||||
|
||||
+26
-26
@@ -1,9 +1,9 @@
|
||||
;; LIST basic text.
|
||||
;; XXX - Doesn't currently support line number ranges
|
||||
// LIST basic text.
|
||||
// XXX - Doesn't currently support line number ranges
|
||||
|
||||
cmd_list:
|
||||
|
||||
;; Set current line pointer to start of memory
|
||||
// Set current line pointer to start of memory
|
||||
lda basic_start_of_text_ptr+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda basic_start_of_text_ptr+1
|
||||
@@ -16,23 +16,23 @@ list_loop:
|
||||
cmp #$00
|
||||
bne list_more_lines
|
||||
|
||||
;; LIST terminates any running program,
|
||||
;; because it has fiddled with the current line pointer.
|
||||
;; (Confirmed by testing on a C64)
|
||||
// LIST terminates any running program,
|
||||
// because it has fiddled with the current line pointer.
|
||||
// (Confirmed by testing on a C64)
|
||||
jmp basic_main_loop
|
||||
|
||||
list_more_lines:
|
||||
lda STKEY
|
||||
bmi +
|
||||
bmi !+
|
||||
jmp basic_do_break
|
||||
*
|
||||
!:
|
||||
jsr list_single_line
|
||||
;; Now link to the next line
|
||||
// Now link to the next line
|
||||
jsr basic_find_next_line
|
||||
jmp list_loop
|
||||
|
||||
list_single_line: ; entry point needed by DOS wedge
|
||||
;; Print line number
|
||||
list_single_line: // entry point needed by DOS wedge
|
||||
// Print line number
|
||||
ldy #3
|
||||
jsr peek_under_roms
|
||||
pha
|
||||
@@ -44,8 +44,8 @@ list_single_line: ; entry point needed by DOS wedge
|
||||
lda #$20
|
||||
jsr JCHROUT
|
||||
|
||||
;; Iterate through printing out the line
|
||||
;; contents
|
||||
// Iterate through printing out the line
|
||||
// contents
|
||||
lda #0
|
||||
sta quote_mode_flag
|
||||
|
||||
@@ -63,34 +63,34 @@ list_print_loop:
|
||||
lda #$22
|
||||
jmp list_is_literal
|
||||
list_not_quote:
|
||||
;; Check quote mode, and display as literal if required
|
||||
// Check quote mode, and display as literal if required
|
||||
ldx quote_mode_flag
|
||||
bne list_is_literal
|
||||
|
||||
cmp #$7f
|
||||
bcc list_is_literal
|
||||
|
||||
;; Display a token
|
||||
// Display a token
|
||||
|
||||
;; Save registers
|
||||
// Save registers
|
||||
tax
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
|
||||
;; Get pointer to compressed keyword list
|
||||
// Get pointer to compressed keyword list
|
||||
lda #<packed_keywords
|
||||
sta temp_string_ptr+0
|
||||
lda #>packed_keywords
|
||||
sta temp_string_ptr+1
|
||||
|
||||
;; Subtract $80 from token to get offset in word
|
||||
;; list
|
||||
// Subtract $80 from token to get offset in word
|
||||
// list
|
||||
txa
|
||||
and #$7f
|
||||
tax
|
||||
|
||||
;; Now ask for it to be printed
|
||||
// Now ask for it to be printed
|
||||
ldy #$ff
|
||||
jsr packed_word_search
|
||||
|
||||
@@ -100,11 +100,11 @@ list_not_quote:
|
||||
|
||||
cmp #$8f
|
||||
bne list_not_rem
|
||||
;; REM command locks quote flag on until the end of the line, allowing
|
||||
;; funny characters in REM statements without problem.
|
||||
// REM command locks quote flag on until the end of the line, allowing
|
||||
// funny characters in REM statements without problem.
|
||||
inc $0427
|
||||
sta quote_mode_flag ; Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here
|
||||
;; FALL THROUGH
|
||||
sta quote_mode_flag // Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here
|
||||
// FALL THROUGH
|
||||
list_not_rem:
|
||||
|
||||
iny
|
||||
@@ -116,10 +116,10 @@ list_is_literal:
|
||||
bne list_print_loop
|
||||
|
||||
list_end_of_line:
|
||||
;; Clear reverse flag
|
||||
// Clear reverse flag
|
||||
lda #$92
|
||||
jsr JCHROUT
|
||||
;; Print end of line
|
||||
// Print end of line
|
||||
lda #$0d
|
||||
jsr JCHROUT
|
||||
rts
|
||||
|
||||
+66
-66
@@ -1,64 +1,64 @@
|
||||
cmd_load:
|
||||
|
||||
;; Parse filename
|
||||
;; (we can tell the KERNAL where it is in memory directly, since the
|
||||
;; KERNAL will be able to peek under ROMs to read it, since it will have
|
||||
;; to be able to peek under the ROMs for SAVE and VERIFY).
|
||||
;; Parse optional device #
|
||||
;; Parse optional secondary address
|
||||
// Parse filename
|
||||
// (we can tell the KERNAL where it is in memory directly, since the
|
||||
// KERNAL will be able to peek under ROMs to read it, since it will have
|
||||
// to be able to peek under the ROMs for SAVE and VERIFY).
|
||||
// Parse optional device #
|
||||
// Parse optional secondary address
|
||||
|
||||
;; XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the
|
||||
;; middle of a program. For safety, we do.
|
||||
// XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the
|
||||
// middle of a program. For safety, we do.
|
||||
jsr basic_do_clr
|
||||
|
||||
;; Setup Kernal to print control messages or not
|
||||
lda #$80 ; display control messages and omit error messages
|
||||
// Setup Kernal to print control messages or not
|
||||
lda #$80 // display control messages and omit error messages
|
||||
ldx basic_current_line_number+1
|
||||
cpx #$FF
|
||||
beq +
|
||||
lda #$00 ; direct mode - don't display anything
|
||||
*
|
||||
beq !+
|
||||
lda #$00 // direct mode - don't display anything
|
||||
!:
|
||||
jsr JSETMSG
|
||||
|
||||
;; Set filename and length
|
||||
// Set filename and length
|
||||
lda #$00
|
||||
sta FNLEN
|
||||
|
||||
;; Without tape support, LOAD must have a filename
|
||||
;; (This also skips any leading spaces)
|
||||
// Without tape support, LOAD must have a filename
|
||||
// (This also skips any leading spaces)
|
||||
jsr basic_end_of_statement_check
|
||||
bcc +
|
||||
bcc !+
|
||||
jmp do_MISSING_FILENAME_error
|
||||
*
|
||||
!:
|
||||
jsr basic_fetch_and_consume_character
|
||||
cmp #$22
|
||||
beq +
|
||||
jmp do_SYNTAX_ERROR
|
||||
*
|
||||
;; Filename starts here so set pointer
|
||||
beq !+
|
||||
jmp do_SYNTAX_error
|
||||
!:
|
||||
// Filename starts here so set pointer
|
||||
lda basic_current_statement_ptr+0
|
||||
sta current_filename_ptr+0
|
||||
lda basic_current_statement_ptr+1
|
||||
sta current_filename_ptr+1
|
||||
|
||||
;; Now search for end of line or closing quote
|
||||
;; so that we know the length of the filename
|
||||
// Now search for end of line or closing quote
|
||||
// so that we know the length of the filename
|
||||
getting_filename:
|
||||
jsr basic_fetch_and_consume_character
|
||||
cmp #$22
|
||||
beq got_filename
|
||||
cmp #$00
|
||||
bne +
|
||||
bne !+
|
||||
jsr basic_unconsume_character
|
||||
|
||||
jmp got_filename
|
||||
*
|
||||
!:
|
||||
inc FNLEN
|
||||
jmp getting_filename
|
||||
|
||||
got_filename:
|
||||
|
||||
;; Now fetch the file number, start from the default one
|
||||
// Now fetch the file number, start from the default one
|
||||
jsr select_device
|
||||
stx current_device_number
|
||||
jsr injest_comma
|
||||
@@ -66,116 +66,116 @@ got_filename:
|
||||
|
||||
jsr basic_parse_line_number
|
||||
lda basic_line_number+1
|
||||
beq +
|
||||
beq !+
|
||||
jmp do_ILLEGAL_QUANTITY_error
|
||||
*
|
||||
!:
|
||||
lda basic_line_number+0
|
||||
sta current_device_number
|
||||
|
||||
got_devicenumber:
|
||||
|
||||
;; Now fetch the secondary address
|
||||
// Now fetch the secondary address
|
||||
lda #$00
|
||||
sta current_secondary_address
|
||||
jsr injest_comma
|
||||
bcs got_secondaryaddress
|
||||
jsr basic_parse_line_number
|
||||
lda basic_line_number+1
|
||||
bne +
|
||||
bne !+
|
||||
lda basic_line_number+0
|
||||
sta current_secondary_address
|
||||
jmp got_secondaryaddress
|
||||
*
|
||||
;; Second parameter is above 255, this can't be a secondary address
|
||||
;; Use it as load address instead
|
||||
;; XXX temporary syntax, it would be better to use something
|
||||
;; XXX like 'LOAD"FILE",8 TO 49152'
|
||||
!:
|
||||
// Second parameter is above 255, this can't be a secondary address
|
||||
// Use it as load address instead
|
||||
// XXX temporary syntax, it would be better to use something
|
||||
// XXX like 'LOAD"FILE",8 TO 49152'
|
||||
ldx basic_line_number+0
|
||||
ldy basic_line_number+1
|
||||
bne got_loadaddress
|
||||
|
||||
got_secondaryaddress:
|
||||
ldx #<$0801
|
||||
ldx #<$0801 // XXX use start text vector
|
||||
ldy #>$0801
|
||||
|
||||
got_loadaddress:
|
||||
lda #$00 ; LOAD not verify
|
||||
lda #$00 // LOAD not verify
|
||||
jsr via_ILOAD
|
||||
bcc +
|
||||
bcc !+
|
||||
|
||||
;; A = KERNAL error code, which also almost match
|
||||
;; basic ERROR codes, so we can just copy the
|
||||
;; error code to X, decrement, and handle normally
|
||||
// A = KERNAL error code, which also almost match
|
||||
// basic ERROR codes, so we can just copy the
|
||||
// error code to X, decrement, and handle normally
|
||||
tax
|
||||
dex
|
||||
jmp do_basic_error
|
||||
|
||||
*
|
||||
;; $YYXX is the last loaded address, so store it
|
||||
!:
|
||||
// $YYXX is the last loaded address, so store it
|
||||
stx basic_end_of_text_ptr+0
|
||||
sty basic_end_of_text_ptr+1
|
||||
|
||||
;; Now relink the loaded program, as we cannot trust the line
|
||||
;; links supplied. For example, the VICE virtual drive emulation
|
||||
;; always supplies $0101 as the address of the next line.
|
||||
// Now relink the loaded program, as we cannot trust the line
|
||||
// links supplied. For example, the VICE virtual drive emulation
|
||||
// always supplies $0101 as the address of the next line.
|
||||
jsr basic_relink_program
|
||||
|
||||
;; After LOADing, we either start the program from the beginning,
|
||||
;; or go back to the READY prompt if LOAD was called from direct mode.
|
||||
// After LOADing, we either start the program from the beginning,
|
||||
// or go back to the READY prompt if LOAD was called from direct mode.
|
||||
|
||||
;; Reset to start of program
|
||||
// Reset to start of program
|
||||
lda basic_start_of_text_ptr+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda basic_start_of_text_ptr+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
;; XXX - should run program if LOAD was used in program mode
|
||||
// XXX - should run program if LOAD was used in program mode
|
||||
jmp basic_main_loop
|
||||
|
||||
|
||||
basic_relink_program:
|
||||
|
||||
;; Start by getting pointer to the first line
|
||||
// Start by getting pointer to the first line
|
||||
lda basic_start_of_text_ptr+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda basic_start_of_text_ptr+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
basic_relink_loop:
|
||||
;; Is the pointer to the end of the program
|
||||
// Is the pointer to the end of the program
|
||||
ldy #1
|
||||
ldx #<basic_current_line_ptr+0
|
||||
jsr peek_under_roms
|
||||
cmp #$00
|
||||
bne +
|
||||
bne !+
|
||||
|
||||
;; End of program
|
||||
// End of program
|
||||
rts
|
||||
*
|
||||
;; Now search forward to find the end of the line
|
||||
;; Skip forward pointer and line number
|
||||
!:
|
||||
// Now search forward to find the end of the line
|
||||
// Skip forward pointer and line number
|
||||
ldy #4
|
||||
end_of_line_search:
|
||||
ldx #<basic_current_line_ptr+0
|
||||
jsr peek_under_roms
|
||||
cmp #$00
|
||||
beq +
|
||||
beq !+
|
||||
|
||||
;; Not yet end of line
|
||||
// Not yet end of line
|
||||
iny
|
||||
bne end_of_line_search
|
||||
|
||||
;; line too long
|
||||
// line too long
|
||||
jmp do_STRING_TOO_LONG_error
|
||||
|
||||
*
|
||||
;; Found end of line, so update pointer
|
||||
!:
|
||||
// Found end of line, so update pointer
|
||||
|
||||
;; First, skip over the $00 char
|
||||
// First, skip over the $00 char
|
||||
iny
|
||||
|
||||
;; Now overwrite the pointer (carefully)
|
||||
;;
|
||||
// Now overwrite the pointer (carefully)
|
||||
//
|
||||
tya
|
||||
clc
|
||||
adc basic_current_line_ptr+0
|
||||
|
||||
+21
-23
@@ -2,18 +2,18 @@
|
||||
cmd_new:
|
||||
jsr basic_do_new
|
||||
|
||||
;; NEW command terminates execution
|
||||
;; (Confirmed on a C64)
|
||||
// NEW command terminates execution
|
||||
// (Confirmed on a C64)
|
||||
jmp basic_main_loop
|
||||
|
||||
cmd_clr:
|
||||
jsr basic_do_clr
|
||||
;; CLR command does not stop execution
|
||||
;; (Cconfirmed on a c64)
|
||||
// CLR command does not stop execution
|
||||
// (Cconfirmed on a c64)
|
||||
jmp basic_execute_statement
|
||||
|
||||
basic_do_new:
|
||||
;; Setup pointers to memory storage
|
||||
// Setup pointers to memory storage XXX should depend on text start vector
|
||||
lda #<$0801
|
||||
sta basic_start_of_text_ptr+0
|
||||
lda #>$0801
|
||||
@@ -22,8 +22,8 @@ basic_do_new:
|
||||
lda #<$0803
|
||||
sta basic_start_of_vars_ptr+0
|
||||
|
||||
;; Zero line pointer
|
||||
;; XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1
|
||||
// Zero line pointer
|
||||
// XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1
|
||||
ldy #$00
|
||||
tya
|
||||
sta (basic_start_of_text_ptr),y
|
||||
@@ -31,32 +31,32 @@ basic_do_new:
|
||||
sta (basic_start_of_text_ptr),y
|
||||
|
||||
|
||||
;; Get top of memory.
|
||||
;; If a cart is present, then it is $7FFF,
|
||||
;; if not, then it is $F7FF, since we support having
|
||||
;; programs and variables under ROM.
|
||||
;; i.e., we support 56KB RAM for BASIC, keeping some space
|
||||
;; free for some optimisation structures, e.g., FOR/NEXT loop
|
||||
;; records (without them going on the stack), GOSUB stack
|
||||
;; (same story), expression value cache?
|
||||
// Get top of memory.
|
||||
// If a cart is present, then it is $7FFF,
|
||||
// if not, then it is $F7FF, since we support having
|
||||
// programs and variables under ROM.
|
||||
// i.e., we support 56KB RAM for BASIC, keeping some space
|
||||
// free for some optimisation structures, e.g., FOR/NEXT loop
|
||||
// records (without them going on the stack), GOSUB stack
|
||||
// (same story), expression value cache?
|
||||
|
||||
sec ; Read, not write value
|
||||
sec // Read, not write value
|
||||
jsr JMEMTOP
|
||||
cpx #$80
|
||||
beq +
|
||||
beq !+
|
||||
lda #>$f7ff
|
||||
.byte $2c
|
||||
* lda #>$7FFF
|
||||
.byte $2C
|
||||
!: lda #>$7FFF
|
||||
sta basic_top_of_memory_ptr+1
|
||||
sta basic_start_of_strings_ptr+1
|
||||
lda #<$f7ff
|
||||
sta basic_top_of_memory_ptr+0
|
||||
sta basic_start_of_strings_ptr+0
|
||||
|
||||
;; FALL THROUGH
|
||||
// FALL THROUGH
|
||||
|
||||
basic_do_clr:
|
||||
;; Clear variables, arrays and strings
|
||||
// Clear variables, arrays and strings
|
||||
lda basic_start_of_vars_ptr+0
|
||||
sta basic_start_of_arrays_ptr+0
|
||||
sta basic_start_of_free_space_ptr+0
|
||||
@@ -65,5 +65,3 @@ basic_do_clr:
|
||||
sta basic_start_of_free_space_ptr+1
|
||||
|
||||
rts
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
;; REM statement just skips to the next line
|
||||
// REM statement just skips to the next line
|
||||
|
||||
cmd_rem:
|
||||
jmp basic_end_of_line
|
||||
+7
-7
@@ -1,21 +1,21 @@
|
||||
cmd_run:
|
||||
;; RUN clears all variables
|
||||
// RUN clears all variables
|
||||
jsr basic_do_clr
|
||||
cmd_goto:
|
||||
;; Reset line pointer to first line of program.
|
||||
// Reset line pointer to first line of program.
|
||||
lda basic_start_of_text_ptr+0
|
||||
sta basic_current_line_ptr+0
|
||||
lda basic_start_of_text_ptr+1
|
||||
sta basic_current_line_ptr+1
|
||||
|
||||
jsr basic_end_of_statement_check
|
||||
bcs +
|
||||
bcs !+
|
||||
|
||||
jsr basic_parse_line_number
|
||||
jsr basic_find_line
|
||||
bcc +
|
||||
;; Line doesn't exist, so report error
|
||||
bcc !+
|
||||
// Line doesn't exist, so report error
|
||||
jmp do_UNDEFD_STATEMENT_error
|
||||
*
|
||||
;; Run it!
|
||||
!:
|
||||
// Run it!
|
||||
jmp basic_execute_from_current_line
|
||||
+8
-8
@@ -1,23 +1,23 @@
|
||||
cmd_sys:
|
||||
|
||||
jsr basic_end_of_statement_check
|
||||
bcc +
|
||||
bcc !+
|
||||
|
||||
;; SYS requires an argument
|
||||
jmp do_SYNTAX_ERROR
|
||||
// SYS requires an argument
|
||||
jmp do_SYNTAX_error
|
||||
|
||||
*
|
||||
!:
|
||||
jsr basic_parse_line_number
|
||||
|
||||
;; setup call
|
||||
lda #$4C ;JMP
|
||||
// setup call
|
||||
lda #$4C // JMP opcode
|
||||
sta USRPOK
|
||||
lda basic_line_number+0
|
||||
sta USRADD+0
|
||||
lda basic_line_number+1
|
||||
sta USRADD+1
|
||||
|
||||
;; Setup the register values
|
||||
// Setup the register values
|
||||
lda SPREG
|
||||
pha
|
||||
ldy SYREG
|
||||
@@ -25,7 +25,7 @@ cmd_sys:
|
||||
lda SAREG
|
||||
plp
|
||||
|
||||
;; Call the routine.
|
||||
// Call the routine.
|
||||
jsr USRPOK
|
||||
|
||||
jmp basic_execute_statement
|
||||
@@ -1,4 +1,4 @@
|
||||
;; Default handler for all not-yet-implemented commands
|
||||
// Default handler for all not-yet-implemented commands
|
||||
|
||||
cmd_for:
|
||||
cmd_next:
|
||||
@@ -13,7 +13,7 @@ cmd_restore:
|
||||
cmd_gosub:
|
||||
cmd_return:
|
||||
|
||||
;; $90-$9F
|
||||
// $90-$9F
|
||||
cmd_on:
|
||||
cmd_wait:
|
||||
cmd_save:
|
||||
@@ -26,7 +26,7 @@ cmd_cont:
|
||||
cmd_cmd:
|
||||
cmd_open:
|
||||
|
||||
;; $A0-$AF
|
||||
// $A0-$AF
|
||||
cmd_close:
|
||||
cmd_get:
|
||||
cmd_tab:
|
||||
@@ -43,7 +43,7 @@ cmd_div:
|
||||
cmd_exponent:
|
||||
cmd_and:
|
||||
|
||||
;; $B0-$BF
|
||||
// $B0-$BF
|
||||
cmd_or:
|
||||
cmd_greater:
|
||||
cmd_equal:
|
||||
@@ -61,7 +61,7 @@ cmd_exp:
|
||||
cmd_cos:
|
||||
cmd_sin:
|
||||
|
||||
;; $C0-$CF
|
||||
// $C0-$CF
|
||||
cmd_tan:
|
||||
cmd_atn:
|
||||
cmd_peek:
|
||||
@@ -73,10 +73,10 @@ cmd_chr:
|
||||
cmd_left:
|
||||
cmd_right:
|
||||
cmd_mid:
|
||||
cmd_go:
|
||||
;; Undefined tokens
|
||||
cmd_go:
|
||||
|
||||
// Undefined tokens
|
||||
cmd_unimplemented:
|
||||
|
||||
|
||||
|
||||
|
||||
jmp do_NOT_IMPLEMENTED_error
|
||||
+55
-54
@@ -1,48 +1,48 @@
|
||||
;; As many errors are triggered from many places in the BASIC
|
||||
;; interprettor, it is important to have an efficicent means of
|
||||
;; calling them.
|
||||
;; LDX #$nn / jmp do_basic_error
|
||||
;; is the simplest, but takes 5 bytes.
|
||||
;; Having a direct JMP address for each error is preferable, as
|
||||
;; it reduces the overhead to 3 bytes, but at the cost of having
|
||||
;; a jump table of some sort. The .byte $2C method can be used
|
||||
;; to have a set of addresses that each execute a different
|
||||
;; LDX #$nn command, reducing the cost of the jump table to 3
|
||||
;; bytes per error number.
|
||||
;; But we can do better with a bit of scullduggery and carnal
|
||||
;; knowledge of ZP usage.
|
||||
;; The INC $nn opcode is $E6. ZP location $E6 is one of the screen
|
||||
;; link addresses. In the original KERNAL, the lower bits of those
|
||||
;; addresses have meaning, but in our KERNAL, we ignore them, and just
|
||||
;; have them all zeroes. So.... We can have a sequence of $E6 bytes,
|
||||
;; and know exactly how many of them have been executed, by checking
|
||||
;; the value of $E6. Then all we need to worry about is if an odd
|
||||
;; number is required, then we have to have an exit that has a $E6
|
||||
;; opcode with some other address as target, but where the byte value
|
||||
;; of that argument can be safely executed as a CPU instruction.
|
||||
;; NOP = $EA is the obvious choice, as if used as an argument to
|
||||
;; $E6 will increment location $EA, which is another of the screen
|
||||
;; link addresses.
|
||||
// As many errors are triggered from many places in the BASIC
|
||||
// interprettor, it is important to have an efficicent means of
|
||||
// calling them.
|
||||
// LDX #$nn / jmp do_basic_error
|
||||
// is the simplest, but takes 5 bytes.
|
||||
// Having a direct JMP address for each error is preferable, as
|
||||
// it reduces the overhead to 3 bytes, but at the cost of having
|
||||
// a jump table of some sort. The .byte $2C method can be used
|
||||
// to have a set of addresses that each execute a different
|
||||
// LDX #$nn command, reducing the cost of the jump table to 3
|
||||
// bytes per error number.
|
||||
// But we can do better with a bit of scullduggery and carnal
|
||||
// knowledge of ZP usage.
|
||||
// The INC $nn opcode is $E6. ZP location $E6 is one of the screen
|
||||
// link addresses. In the original KERNAL, the lower bits of those
|
||||
// addresses have meaning, but in our KERNAL, we ignore them, and just
|
||||
// have them all zeroes. So.... We can have a sequence of $E6 bytes,
|
||||
// and know exactly how many of them have been executed, by checking
|
||||
// the value of $E6. Then all we need to worry about is if an odd
|
||||
// number is required, then we have to have an exit that has a $E6
|
||||
// opcode with some other address as target, but where the byte value
|
||||
// of that argument can be safely executed as a CPU instruction.
|
||||
// NOP = $EA is the obvious choice, as if used as an argument to
|
||||
// $E6 will increment location $EA, which is another of the screen
|
||||
// link addresses.
|
||||
|
||||
;; This gives a total overhead of 18 bytes + 1 byte per error
|
||||
;; message. This compares favourably to the 3 bytes per error
|
||||
;; message that the $2C method would result in.
|
||||
// This gives a total overhead of 18 bytes + 1 byte per error
|
||||
// message. This compares favourably to the 3 bytes per error
|
||||
// message that the $2C method would result in.
|
||||
|
||||
do_NOT_IMPLEMENTED_error:
|
||||
.byte $E6
|
||||
do_MEMORY_CORRUPT_error:
|
||||
.byte $E6
|
||||
;; the message "BYTES FREE"
|
||||
// the message "BYTES FREE"
|
||||
.byte $E6
|
||||
;; the word ERROR
|
||||
// the word ERROR
|
||||
.byte $E6
|
||||
;; The word "SAVING"
|
||||
// The word "SAVING"
|
||||
.byte $E6
|
||||
;; The word "VERIFYING"
|
||||
// The word "VERIFYING"
|
||||
.byte $E6
|
||||
;; The word "LOADING"
|
||||
// The word "LOADING"
|
||||
.byte $E6
|
||||
;; The word "READY."
|
||||
// The word "READY."
|
||||
.byte $E6
|
||||
do_LOAD_error:
|
||||
.byte $E6
|
||||
@@ -103,69 +103,70 @@ do_FILE_OPEN_error:
|
||||
do_TO_MANY_FILES_error:
|
||||
.byte $EA
|
||||
|
||||
;; Now get the error # and restore $E6 to its correct value
|
||||
// Now get the error # and restore $E6 to its correct value
|
||||
lda $E6
|
||||
pha
|
||||
and #$80
|
||||
sta $E6
|
||||
pla
|
||||
;; $E6 has even part
|
||||
// $E6 has even part
|
||||
asl
|
||||
ora $EA
|
||||
and #$7f
|
||||
tax
|
||||
|
||||
;; Restore $EA to correct value in case the NOP above is used
|
||||
;; as an argument to the preceeding INC $nn (opcode $E6).
|
||||
LDA $EA
|
||||
// Restore $EA to correct value in case the NOP above is used
|
||||
// as an argument to the preceeding INC $nn (opcode $E6).
|
||||
lda $EA
|
||||
and #$80
|
||||
sta $EA
|
||||
|
||||
;; FALL THROUGH
|
||||
// FALL THROUGH
|
||||
|
||||
;; Error # in X
|
||||
// Error # in X
|
||||
|
||||
do_basic_error:
|
||||
;; "?"
|
||||
// "?"
|
||||
txa
|
||||
pha
|
||||
lda #$0d
|
||||
jsr $ffd2
|
||||
jsr JCHROUT
|
||||
lda #$3f
|
||||
jsr $ffd2
|
||||
jsr JCHROUT
|
||||
pla
|
||||
tax
|
||||
|
||||
;; Error message text
|
||||
// Error message text
|
||||
jsr print_packed_message
|
||||
|
||||
;; A space between error name and word error
|
||||
// A space between error name and word error
|
||||
lda #$20
|
||||
jsr $ffd2
|
||||
|
||||
;; "ERROR"
|
||||
// "ERROR"
|
||||
ldx #33
|
||||
jsr print_packed_message
|
||||
|
||||
lda basic_current_line_number+1
|
||||
cmp #$ff
|
||||
beq +
|
||||
beq !+
|
||||
|
||||
;; We were in a program, so show IN <line>
|
||||
jsr printf
|
||||
.byte " IN ",0
|
||||
// We were in a program, so show IN <line>
|
||||
jsr printf // XXX don't use printf, use packed messages
|
||||
.text " IN "
|
||||
.byte 0
|
||||
|
||||
lda basic_current_line_number+1
|
||||
ldx basic_current_line_number+0
|
||||
jsr print_integer
|
||||
*
|
||||
;; New lines
|
||||
!:
|
||||
// New lines
|
||||
lda #$0d
|
||||
jsr $ffd2
|
||||
lda #$00
|
||||
jsr $ffd2
|
||||
|
||||
;; XXX - Restore stack depth first?
|
||||
// XXX - Restore stack depth first?
|
||||
|
||||
jmp basic_main_loop
|
||||
|
||||
+26
-26
@@ -1,23 +1,23 @@
|
||||
;; Multiply Floating Point Accumulator by 10
|
||||
;; = 8x + 2x
|
||||
;; Implement by shifting MAC left one bit,
|
||||
;; and then keeping that value to add on after
|
||||
;; shifting two more bits left.
|
||||
;; This should be done using basic_fac1_overflow to
|
||||
;; hold the overflow bits, so that the result can
|
||||
;; be exponent adjusted after, if required.
|
||||
// Multiply Floating Point Accumulator by 10
|
||||
// = 8x + 2x
|
||||
// Implement by shifting MAC left one bit,
|
||||
// and then keeping that value to add on after
|
||||
// shifting two more bits left.
|
||||
// This should be done using basic_fac1_overflow to
|
||||
// hold the overflow bits, so that the result can
|
||||
// be exponent adjusted after, if required.
|
||||
|
||||
fac1_mul10:
|
||||
lda #$00
|
||||
sta basic_fac1_overflow
|
||||
|
||||
;; Multiply mantissa by 2
|
||||
// Multiply mantissa by 2
|
||||
jsr fac1_mantissa_mul2
|
||||
|
||||
;; copy down to BASIC numeric work area at $57
|
||||
;; (basic_numeric_work_area)
|
||||
;; (We copy all 7 bytes off the FAC1, so that we have
|
||||
;; the overflow bits, and the copy is as small as possible)
|
||||
// copy down to BASIC numeric work area at $57
|
||||
// (basic_numeric_work_area)
|
||||
// (We copy all 7 bytes off the FAC1, so that we have
|
||||
// the overflow bits, and the copy is as small as possible)
|
||||
ldx #7
|
||||
f1m10_l1:
|
||||
lda basic_fac1_mantissa,x
|
||||
@@ -25,11 +25,11 @@ f1m10_l1:
|
||||
dex
|
||||
bpl f1m10_l1
|
||||
|
||||
;; Multiply mantissa by 4, so it is now 8x original
|
||||
// Multiply mantissa by 4, so it is now 8x original
|
||||
jsr fac1_mantissa_mul2
|
||||
jsr fac1_mantissa_mul2
|
||||
|
||||
;; Now add stored value of 2x to it, to get the total x10
|
||||
// Now add stored value of 2x to it, to get the total x10
|
||||
ldy #3
|
||||
ldx #0
|
||||
clc
|
||||
@@ -44,22 +44,22 @@ f1m10_l2:
|
||||
adc basic_numeric_work_area+7
|
||||
sta basic_fac1_overflow
|
||||
|
||||
;; Now shift right and increase exponent until overflow
|
||||
;; bits = $00
|
||||
// Now shift right and increase exponent until overflow
|
||||
// bits = $00
|
||||
f1m10_l3:
|
||||
lda basic_fac1_overflow
|
||||
bne +
|
||||
;; All done, return
|
||||
bne !+
|
||||
// All done, return
|
||||
clc
|
||||
rts
|
||||
*
|
||||
;; Divide mantissa by two, and increment exponent
|
||||
!:
|
||||
// Divide mantissa by two, and increment exponent
|
||||
jsr fac1_mantissa_div2
|
||||
inc basic_fac1_exponent
|
||||
lda basic_fac1_exponent
|
||||
bpl f1m10_l3
|
||||
;; Exponent has bit 7 set, so has wrapped.
|
||||
;; = OVERFLOW ERROR
|
||||
// Exponent has bit 7 set, so has wrapped.
|
||||
// = OVERFLOW ERROR
|
||||
jmp do_OVERFLOW_error
|
||||
|
||||
fac1_mantissa_mul2:
|
||||
@@ -67,8 +67,8 @@ fac1_mantissa_mul2:
|
||||
ldx #0
|
||||
clc
|
||||
f1m1_l1:
|
||||
;; Multiply mantissa by 2, and store overflow
|
||||
;; in basic_fac1_bits
|
||||
// Multiply mantissa by 2, and store overflow
|
||||
// in basic_fac1_bits
|
||||
lda basic_fac1_mantissa,x
|
||||
rol
|
||||
sta basic_fac1_mantissa,x
|
||||
@@ -82,7 +82,7 @@ f1m1_l1:
|
||||
rts
|
||||
|
||||
fac1_mantissa_div2:
|
||||
;; Divide mantissa by 2, including using overflow bits
|
||||
// Divide mantissa by 2, including using overflow bits
|
||||
clc
|
||||
lda basic_fac1_overflow
|
||||
ror
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
;; Consummes a comma in a BASIC code, C set for no coma found
|
||||
// Consummes a comma in a BASIC code, C set for no coma found
|
||||
|
||||
injest_comma:
|
||||
|
||||
jsr basic_fetch_and_consume_character
|
||||
cmp #$2C ; comma character
|
||||
cmp #$2C // comma character
|
||||
beq injest_comma_found
|
||||
cmp #$20
|
||||
beq injest_comma ; space, can always be skipped
|
||||
cmp #$20 // space, can always be skipped
|
||||
beq injest_comma
|
||||
|
||||
;; not found
|
||||
// not found
|
||||
jsr basic_unconsume_character
|
||||
sec
|
||||
rts
|
||||
@@ -17,4 +17,3 @@ injest_comma:
|
||||
injest_comma_found:
|
||||
clc
|
||||
rts
|
||||
|
||||
+50
-51
@@ -1,37 +1,37 @@
|
||||
;; Parse a number from the input buffer at (basic_current_statement_ptr)
|
||||
;; Result is put into FAC1.
|
||||
;; basic_current_statement_ptr is updated with first position after the number.
|
||||
// Parse a number from the input buffer at (basic_current_statement_ptr)
|
||||
// Result is put into FAC1.
|
||||
// basic_current_statement_ptr is updated with first position after the number.
|
||||
|
||||
;; XXX - Remember decimal position and exponent, and apply them
|
||||
;; after to produce normalised floating point number.
|
||||
// XXX - Remember decimal position and exponent, and apply them
|
||||
// after to produce normalised floating point number.
|
||||
|
||||
;; XXX - Doesn't use routines to access memory under ROMs etc.
|
||||
;; This is important, because this routine operates on numbers in BASIC text.
|
||||
// XXX - Doesn't use routines to access memory under ROMs etc.
|
||||
// This is important, because this routine operates on numbers in BASIC text.
|
||||
|
||||
ij_not_a_digit:
|
||||
;; XXX check for "." or "E"
|
||||
;; Other chars terminate the accumulation.
|
||||
// XXX check for "." or "E"
|
||||
// Other chars terminate the accumulation.
|
||||
|
||||
;; Look for exponentiation marker
|
||||
;; XXX - Implement me!
|
||||
;; Probably should have a flag so that we know if we are accumulating
|
||||
;; exponent or mantissa digits
|
||||
// Look for exponentiation marker
|
||||
// XXX - Implement me!
|
||||
// Probably should have a flag so that we know if we are accumulating
|
||||
// exponent or mantissa digits
|
||||
|
||||
;; Look for decimal point
|
||||
// Look for decimal point
|
||||
cmp #$2e
|
||||
bne ij_not_decimal
|
||||
lda tokenise_work4
|
||||
cmp #$ff
|
||||
beq ij_found_decimal
|
||||
;; More than one decimal point in a number means we have reached the end of the number
|
||||
// More than one decimal point in a number means we have reached the end of the number
|
||||
clc
|
||||
rts
|
||||
|
||||
ij_found_decimal:
|
||||
;; Found decimal.
|
||||
;; Thus start counting digits after the decimal, so that we
|
||||
;; can do the necessary number of divide by 10s on the final
|
||||
;; number.
|
||||
// Found decimal.
|
||||
// Thus start counting digits after the decimal, so that we
|
||||
// can do the necessary number of divide by 10s on the final
|
||||
// number.
|
||||
lda #$00
|
||||
sta tokenise_work4
|
||||
|
||||
@@ -39,31 +39,30 @@ ij_found_decimal:
|
||||
|
||||
ij_not_decimal:
|
||||
|
||||
|
||||
CLC
|
||||
RTS
|
||||
clc
|
||||
rts
|
||||
|
||||
injest_number:
|
||||
;; Clear FAC1
|
||||
// Clear FAC1
|
||||
jsr erase_fac1
|
||||
|
||||
;; Clear decimal position flag
|
||||
// Clear decimal position flag
|
||||
lda #$ff
|
||||
sta tokenise_work4
|
||||
|
||||
;; Check if leading char is a - sign
|
||||
;; Note: the - will have been tokenised to $AB
|
||||
;; XXX - implement
|
||||
// Check if leading char is a - sign
|
||||
// Note: the - will have been tokenised to $AB
|
||||
// XXX - implement
|
||||
ldy #$00
|
||||
lda (basic_current_statement_ptr),y
|
||||
cmp #$AB
|
||||
bne ij_not_minus
|
||||
|
||||
;; Set sign to negative
|
||||
// Set sign to negative
|
||||
lda #$ff
|
||||
sta basic_fac1_sign
|
||||
|
||||
;; Skip over the minus sign
|
||||
// Skip over the minus sign
|
||||
jsr basic_consume_character
|
||||
|
||||
ij_not_minus:
|
||||
@@ -77,43 +76,43 @@ ij_loop1:
|
||||
cmp #$3a
|
||||
bcs ij_not_a_digit
|
||||
|
||||
;; It is a digit
|
||||
// It is a digit
|
||||
|
||||
;; Only add digit if we have not overflowed the accuracy of
|
||||
;; the mantissa
|
||||
// Only add digit if we have not overflowed the accuracy of
|
||||
// the mantissa
|
||||
lda basic_fac1_exponent
|
||||
beq ij_accept_precision
|
||||
|
||||
;; We have an extra digit after saturating our precision.
|
||||
;; Thus we should ignore the digit, and just multiply the FAC
|
||||
;; by 10, but only if we have not seen a decimal point.
|
||||
;; If we have seen a decimal point, then we can completely ignore
|
||||
;; the digit, as it is contributing not recordable information
|
||||
// We have an extra digit after saturating our precision.
|
||||
// Thus we should ignore the digit, and just multiply the FAC
|
||||
// by 10, but only if we have not seen a decimal point.
|
||||
// If we have seen a decimal point, then we can completely ignore
|
||||
// the digit, as it is contributing not recordable information
|
||||
|
||||
lda tokenise_work4
|
||||
cmp #$ff
|
||||
bne ij_seen_decimal_point
|
||||
|
||||
jsr fac1_mul10
|
||||
;; Fall through
|
||||
// Fall through
|
||||
ij_seen_decimal_point:
|
||||
jmp ij_consider_next_digit
|
||||
|
||||
ij_accept_precision:
|
||||
;; We can accept more precision, so multiply the mantissa by 10, so that
|
||||
;; we can add the new digit in
|
||||
// We can accept more precision, so multiply the mantissa by 10, so that
|
||||
// we can add the new digit in
|
||||
jsr fac1_mul10
|
||||
|
||||
lda basic_fac1_exponent
|
||||
bne ij_consider_next_digit
|
||||
|
||||
;; Get digit
|
||||
// Get digit
|
||||
ldy #$00
|
||||
lda (basic_current_statement_ptr),y
|
||||
sec
|
||||
sbc #$30
|
||||
|
||||
;; Add to FAC1 mantissa
|
||||
// Add to FAC1 mantissa
|
||||
clc
|
||||
adc basic_fac1_mantissa+0
|
||||
sta basic_fac1_mantissa+0
|
||||
@@ -127,16 +126,16 @@ ij_loop2:
|
||||
dey
|
||||
bne ij_loop2
|
||||
|
||||
bcc +
|
||||
;; Carry set, so we have overflowed.
|
||||
;; We should shift everything right one digit, and increase
|
||||
;; the exponent by one. The non-zero exponent tells us that we
|
||||
;; can't fit any more precision in.
|
||||
bcc !+
|
||||
// Carry set, so we have overflowed.
|
||||
// We should shift everything right one digit, and increase
|
||||
// the exponent by one. The non-zero exponent tells us that we
|
||||
// can't fit any more precision in.
|
||||
jsr fac1_mantissa_div2
|
||||
*
|
||||
!:
|
||||
|
||||
ij_consider_next_digit:
|
||||
;; Consider next digit
|
||||
// Consider next digit
|
||||
jsr basic_consume_character
|
||||
jmp ij_loop1
|
||||
|
||||
@@ -146,10 +145,10 @@ ij_consider_next_digit:
|
||||
erase_fac1:
|
||||
lda #$00
|
||||
ldx #8
|
||||
*
|
||||
!:
|
||||
sta basic_fac1_exponent,x
|
||||
dex
|
||||
bpl -
|
||||
bpl !-
|
||||
sta basic_fac1_mantissa_lob
|
||||
|
||||
rts
|
||||
|
||||
+88
-87
@@ -1,76 +1,77 @@
|
||||
;; Pack a word using the simple compression scheme.
|
||||
;; This has to be the same implementation as in compress_text.c
|
||||
;; because we compress input lines of BASIC to do the tokenisation.
|
||||
;; 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 BASIC 7 or BASIC 10 compatibility, since the
|
||||
;; compression and decompression machinery is of fixed size.
|
||||
// Pack a word using the simple compression scheme.
|
||||
// This has to be the same implementation as in compress_text.c
|
||||
// because we compress input lines of BASIC to do the tokenisation.
|
||||
// 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 BASIC 7 or BASIC 10 compatibility, since the
|
||||
// compression and decompression machinery is of fixed size.
|
||||
|
||||
pack_word:
|
||||
;; Inputs:
|
||||
;; X = offset of string to pack. Address is $0200 + X
|
||||
;; tokenise_work1 = number of bytes to pack
|
||||
;; tokenise_work2 = packed length of string
|
||||
// Inputs:
|
||||
// X = offset of string to pack. Address is $0200 + X
|
||||
// tokenise_work1 = number of bytes to pack
|
||||
// tokenise_work2 = packed length of string
|
||||
|
||||
;; Outputs:
|
||||
;; Output is written to $0100 (bottom of stack).
|
||||
// Outputs:
|
||||
// Output is written to $0100 (bottom of stack).
|
||||
|
||||
;; Memory modified:
|
||||
;; tokenise_work4 = temporary storage
|
||||
;; tokenise_work3 = flag for whether we have a nybl prepared or not.
|
||||
;; (This can also be checked on exit, to know whether the last byte
|
||||
;; is incomplete, which is important for searching for abbreviated
|
||||
;; key words.)
|
||||
// Memory modified:
|
||||
// tokenise_work4 = temporary storage
|
||||
// tokenise_work3 = flag for whether we have a nybl prepared or not.
|
||||
// (This can also be checked on exit, to know whether the last byte
|
||||
// is incomplete, which is important for searching for abbreviated
|
||||
// key words.)
|
||||
|
||||
|
||||
;; Make sure we have a sane request
|
||||
// Make sure we have a sane request
|
||||
lda tokenise_work1
|
||||
bne +
|
||||
bne !+
|
||||
sec
|
||||
rts
|
||||
*
|
||||
;; Initialise internal variables
|
||||
!:
|
||||
// Initialise internal variables
|
||||
lda #$00
|
||||
sta tokenise_work2
|
||||
sta tokenise_work3
|
||||
|
||||
pack_char_loop:
|
||||
|
||||
;; Get the next char
|
||||
// Get the next char
|
||||
lda $0200,x
|
||||
|
||||
;; Work out what type of character we have, and thus
|
||||
;; how we need to pack it.
|
||||
// Work out what type of character we have, and thus
|
||||
// how we need to pack it.
|
||||
jsr get_packed_char_index
|
||||
|
||||
cmp #$00
|
||||
bne not_exception_char
|
||||
|
||||
;; Char is an exception char.
|
||||
;; We need to either finish the previous byte with $xF,
|
||||
;; Or if there is no existing nybl, then we need to output
|
||||
;; either $FE or $FF, depending on whether this is the last
|
||||
;; byte or not
|
||||
// Char is an exception char.
|
||||
// We need to either finish the previous byte with $xF,
|
||||
// Or if there is no existing nybl, then we need to output
|
||||
// either $FE or $FF, depending on whether this is the last
|
||||
// byte or not
|
||||
|
||||
lda tokenise_work3
|
||||
bne have_nybl_before_exception_char
|
||||
|
||||
;; No nybl exists before the exception char, so prefix with $FE or $FF
|
||||
;; based on whether we are at the end of the input string or not
|
||||
// No nybl exists before the exception char, so prefix with $FE or $FF
|
||||
// based on whether we are at the end of the input string or not
|
||||
inx
|
||||
lda tokenise_work1
|
||||
cmp #$01
|
||||
beq at_end
|
||||
lda #$FF
|
||||
.byte $2C
|
||||
at_end: LDA #$FE
|
||||
at_end:
|
||||
lda #$FE
|
||||
dex
|
||||
jsr write_unpacked_char
|
||||
;; Fall through
|
||||
// Fall through
|
||||
|
||||
output_exception_byte:
|
||||
lda $0200,x
|
||||
@@ -78,18 +79,18 @@ output_exception_byte:
|
||||
jmp consider_next_char
|
||||
|
||||
have_nybl_before_exception_char:
|
||||
;; Or existing byte with #$0F, and clear nybl flag
|
||||
// Or existing byte with #$0F, and clear nybl flag
|
||||
ldy tokenise_work2
|
||||
lda $0100,y
|
||||
ora #$0f
|
||||
sta $0100,y
|
||||
inc tokenise_work2
|
||||
|
||||
;; FALL THROUGH
|
||||
// FALL THROUGH
|
||||
|
||||
write_literal_and_terminate_if_required:
|
||||
|
||||
;; Clear have nybl flag
|
||||
// Clear have nybl flag
|
||||
lda #$00
|
||||
sta tokenise_work3
|
||||
|
||||
@@ -99,19 +100,19 @@ write_literal_and_terminate_if_required:
|
||||
jmp end_string_if_required
|
||||
|
||||
end_string_if_required:
|
||||
;; Check if X points to last char of string to be packed
|
||||
// Check if X points to last char of string to be packed
|
||||
inx
|
||||
lda tokenise_work1
|
||||
cmp #$01
|
||||
beq +
|
||||
beq !+
|
||||
dex
|
||||
jmp consider_next_char
|
||||
*
|
||||
!:
|
||||
dex
|
||||
;; Fall through
|
||||
// Fall through
|
||||
|
||||
end_string:
|
||||
;; Write end of string sequence if required
|
||||
// Write end of string sequence if required
|
||||
lda #$00
|
||||
jsr write_unpacked_char
|
||||
rts
|
||||
@@ -124,53 +125,53 @@ write_unpacked_char:
|
||||
rts
|
||||
|
||||
not_exception_char:
|
||||
;; It wasn't an exception char, so write the symbol out
|
||||
// It wasn't an exception char, so write the symbol out
|
||||
cmp #$10
|
||||
bcs whole_byte_symbol
|
||||
|
||||
;; Nybl encoded value: Put in upper half or lower half of a byte?
|
||||
// Nybl encoded value: Put in upper half or lower half of a byte?
|
||||
ldy tokenise_work3
|
||||
bne store_low_nybl
|
||||
|
||||
;; Store in high nybl -- so shift it into the hi nybl
|
||||
// Store in high nybl -- so shift it into the hi nybl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
ldy tokenise_work2
|
||||
sta $0100,y
|
||||
bne stored_nybl ; Must be taken, as A cannot be $00
|
||||
bne stored_nybl // Must be taken, as A cannot be $00
|
||||
|
||||
store_low_nybl:
|
||||
;; Low nybl gets added to high nybl already stored in the byte
|
||||
// Low nybl gets added to high nybl already stored in the byte
|
||||
ldy tokenise_work2
|
||||
ora $0100,y
|
||||
sta $0100,y
|
||||
|
||||
stored_nybl:
|
||||
;; Now toggle the nybl flag
|
||||
// Now toggle the nybl flag
|
||||
lda tokenise_work3
|
||||
eor #$ff
|
||||
sta tokenise_work3
|
||||
;; And advance the offset if we filled this byte up
|
||||
bne consider_next_char ; Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free
|
||||
// And advance the offset if we filled this byte up
|
||||
bne consider_next_char // Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free
|
||||
|
||||
;; Count the filled up byte
|
||||
// Count the filled up byte
|
||||
inc tokenise_work2
|
||||
|
||||
;; Add termination byte if required
|
||||
;; (This re-writes the same byte again, which we don't care about)
|
||||
// Add termination byte if required
|
||||
// (This re-writes the same byte again, which we don't care about)
|
||||
jmp end_string_if_required
|
||||
|
||||
whole_byte_symbol:
|
||||
;; It's a $Fx symbol.
|
||||
;; But if we have a nybl to flush, then we handle it like
|
||||
;; a full exception character
|
||||
// It's a $Fx symbol.
|
||||
// But if we have a nybl to flush, then we handle it like
|
||||
// a full exception character
|
||||
|
||||
ldy tokenise_work3
|
||||
beq nothing_to_flush
|
||||
|
||||
;; Set low nybl to $F to mark next byte as literal
|
||||
// Set low nybl to $F to mark next byte as literal
|
||||
ldy tokenise_work2
|
||||
lda $0100,y
|
||||
ora #$0f
|
||||
@@ -180,30 +181,30 @@ whole_byte_symbol:
|
||||
jmp write_literal_and_terminate_if_required
|
||||
|
||||
nothing_to_flush:
|
||||
;; Write the symbol as it is, or the literal
|
||||
;; if it has been passed to us via fall-through
|
||||
// Write the symbol as it is, or the literal
|
||||
// if it has been passed to us via fall-through
|
||||
jsr write_unpacked_char
|
||||
|
||||
jmp end_string_if_required
|
||||
|
||||
consider_next_char:
|
||||
;; Pack next char
|
||||
// Pack next char
|
||||
inx
|
||||
dec tokenise_work1
|
||||
beq +
|
||||
beq !+
|
||||
jmp pack_char_loop
|
||||
*
|
||||
;; Add 1 to length if nybl waiting to be flushed
|
||||
;; (but leave flag set so the caller knows if the
|
||||
;; bottom nybl might be different if the string were
|
||||
;; longer).
|
||||
!:
|
||||
// Add 1 to length if nybl waiting to be flushed
|
||||
// (but leave flag set so the caller knows if the
|
||||
// bottom nybl might be different if the string were
|
||||
// longer).
|
||||
lda tokenise_work3
|
||||
beq +
|
||||
beq !+
|
||||
inc tokenise_work2
|
||||
rts
|
||||
*
|
||||
;; Last byte was full, so we need at $00 on the end
|
||||
;; (unless a $FE token was written 2 bytes ago)
|
||||
!:
|
||||
// Last byte was full, so we need at $00 on the end
|
||||
// (unless a $FE token was written 2 bytes ago)
|
||||
ldy tokenise_work2
|
||||
iny
|
||||
lda #$00
|
||||
@@ -213,21 +214,21 @@ consider_next_char:
|
||||
rts
|
||||
|
||||
get_packed_char_index:
|
||||
;; Find char in A in the packed char list, and return
|
||||
;; $1 - $E, $F1 - $FD if the charactar is abbreviable,
|
||||
;; or else return $00 if the character has to be stored literally.
|
||||
// Find char in A in the packed char list, and return
|
||||
// $1 - $E, $F1 - $FD if the charactar is abbreviable,
|
||||
// or else return $00 if the character has to be stored literally.
|
||||
|
||||
;; Y register and A are modified, as are processor flags.
|
||||
// Y register and A are modified, as are processor flags.
|
||||
|
||||
ldy #$00
|
||||
find_char_loop:
|
||||
cmp packed_message_chars,y
|
||||
bne not_a_match
|
||||
enumerate:
|
||||
;; Is it a nybl abbreviable char?
|
||||
// Is it a nybl abbreviable char?
|
||||
cpy #14
|
||||
bcs not_nybl_char
|
||||
;; Yes, so add 1 and return it
|
||||
// Yes, so add 1 and return it
|
||||
iny
|
||||
tya
|
||||
rts
|
||||
@@ -235,9 +236,9 @@ enumerate:
|
||||
not_nybl_char:
|
||||
cpy #27
|
||||
bcs not_a_match
|
||||
;; It's a $Fx character.
|
||||
;; Since the lowest index is $E, and it should be encoded as $F1
|
||||
;; we need to add $E3
|
||||
// It's a $Fx character.
|
||||
// Since the lowest index is $E, and it should be encoded as $F1
|
||||
// we need to add $E3
|
||||
tya
|
||||
clc
|
||||
adc #$E3
|
||||
@@ -245,10 +246,10 @@ not_nybl_char:
|
||||
|
||||
not_a_match:
|
||||
iny
|
||||
;; Loop until we find it, or we discover it isn't
|
||||
;; a character with a special encoding
|
||||
// Loop until we find it, or we discover it isn't
|
||||
// a character with a special encoding
|
||||
cpy #27
|
||||
bne find_char_loop
|
||||
;; Not a char that we can pack, so return 0
|
||||
// Not a char that we can pack, so return 0
|
||||
lda #$00
|
||||
rts
|
||||
@@ -1,5 +1,5 @@
|
||||
;; Return C=1 if a pointer in BASIC memory space is NULL, else C=0
|
||||
;; X = ZP pointer to check
|
||||
// Return C=1 if a pointer in BASIC memory space is NULL, else C=0
|
||||
// X = ZP pointer to check
|
||||
|
||||
peek_pointer_null_check:
|
||||
ldy #$00
|
||||
@@ -11,10 +11,10 @@ peek_pointer_null_check:
|
||||
cmp #$00
|
||||
bne ptr_not_null
|
||||
|
||||
;; Pointer is NULL
|
||||
// Pointer is NULL
|
||||
clc
|
||||
rts
|
||||
ptr_not_null:
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
+31
-30
@@ -1,26 +1,27 @@
|
||||
;; Works similar to $BDCD in original C64 BASIC
|
||||
;; XXX Should eventually get replaced by a more flexible and optimal routine.
|
||||
;; Temp result gets written to $0100-$0104
|
||||
// Works similar to $BDCD in original C64 BASIC
|
||||
// XXX Should eventually get replaced by a more flexible and optimal routine.
|
||||
// Temp result gets written to $0100-$0104
|
||||
|
||||
print_integer:
|
||||
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
|
||||
;; Clear temporary output
|
||||
// Clear temporary output
|
||||
lda #$00
|
||||
ldy #5
|
||||
* sta $0100,y
|
||||
!: sta $0100,y
|
||||
dey
|
||||
bpl -
|
||||
bpl !-
|
||||
|
||||
pla
|
||||
ldy #23 ; 8 x 3 - 1 = offset of last digit of 128
|
||||
ldy #23 // 8 x 3 - 1 = offset of last digit of 128
|
||||
lo_loop:
|
||||
cmp #$7f
|
||||
bcc bit_clear
|
||||
|
||||
;; Bit set, so add the digits
|
||||
// Bit set, so add the digits
|
||||
pha
|
||||
ldx #2
|
||||
clc
|
||||
@@ -45,16 +46,16 @@ next_lo_bit:
|
||||
bcc lo_loop
|
||||
|
||||
|
||||
;; Now do the same for upper byte
|
||||
// Now do the same for upper byte
|
||||
pla
|
||||
|
||||
ldy #39 ; 8 x 5 - 1 = offset of last digit of 32768
|
||||
ldy #39 // 8 x 5 - 1 = offset of last digit of 32768
|
||||
hi_loop:
|
||||
cmp #$7f
|
||||
bcc bit_clear_hi
|
||||
|
||||
|
||||
;; Bit set, so add the digits
|
||||
// Bit set, so add the digits
|
||||
pha
|
||||
ldx #4
|
||||
clc
|
||||
@@ -67,8 +68,8 @@ hi_add_loop:
|
||||
dex
|
||||
bpl hi_add_loop
|
||||
pla
|
||||
jmp next_hi_bit
|
||||
|
||||
jmp next_hi_bit
|
||||
|
||||
bit_clear_hi:
|
||||
dey
|
||||
dey
|
||||
@@ -78,47 +79,47 @@ bit_clear_hi:
|
||||
next_hi_bit:
|
||||
asl
|
||||
cpy #$7f
|
||||
bcc hi_loop
|
||||
bcc hi_loop
|
||||
|
||||
fix_carry:
|
||||
|
||||
;; Deal with any carries
|
||||
|
||||
// Deal with any carries
|
||||
ldx #3
|
||||
carry_fix_loop:
|
||||
carry_fix_loop:
|
||||
lda $0101,x
|
||||
cmp #10
|
||||
bcc +
|
||||
bcc !+
|
||||
inc $0100,x
|
||||
sec
|
||||
sbc #10
|
||||
sta $0101,x
|
||||
|
||||
jmp carry_fix_loop
|
||||
|
||||
* dex
|
||||
|
||||
!: dex
|
||||
bpl carry_fix_loop
|
||||
|
||||
post_carry:
|
||||
post_carry:
|
||||
|
||||
;; Got digits.
|
||||
;; Skip leading zeros, and print the resulting number
|
||||
// Got digits.
|
||||
// Skip leading zeros, and print the resulting number
|
||||
|
||||
;; Skip leading zeros
|
||||
// Skip leading zeros
|
||||
ldy #0
|
||||
* lda $0100,y
|
||||
!: lda $0100,y
|
||||
bne found_start_of_number
|
||||
iny
|
||||
cpy #4
|
||||
bne -
|
||||
bne !-
|
||||
|
||||
found_start_of_number:
|
||||
;; Print digits
|
||||
* lda $0100,y
|
||||
found_start_of_number:
|
||||
// Print digits
|
||||
!: lda $0100,y
|
||||
ora #$30
|
||||
jsr JCHROUT
|
||||
iny
|
||||
cpy #5
|
||||
bne -
|
||||
bne !-
|
||||
|
||||
|
||||
rts
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
;; This routine prints messages that have been packed
|
||||
;; using the make_error_tables program.
|
||||
;; The general idea is to save space in the ROM.
|
||||
// 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.
|
||||
|
||||
|
||||
;; 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
|
||||
// .X = message number
|
||||
|
||||
lda #$ff
|
||||
ldy #$ff
|
||||
packed_message_search:
|
||||
packed_message_search:
|
||||
iny
|
||||
cpx #$00
|
||||
beq found_message_in_token_stream
|
||||
lda packed_message_tokens,y
|
||||
cmp #$ff
|
||||
bne +
|
||||
bne !+
|
||||
dex
|
||||
*
|
||||
!:
|
||||
cpy #$ff
|
||||
bne packed_message_search
|
||||
;; Could not find message
|
||||
// Could not find message
|
||||
sec
|
||||
rts
|
||||
|
||||
found_message_in_token_stream:
|
||||
;; Now print each word in the message
|
||||
// Now print each word in the message
|
||||
tya
|
||||
pha
|
||||
lda packed_message_tokens,y
|
||||
cmp #$ff
|
||||
beq +
|
||||
beq !+
|
||||
jsr print_packed_word
|
||||
lda #$20
|
||||
jsr JCHROUT
|
||||
@@ -43,50 +44,50 @@ found_message_in_token_stream:
|
||||
tay
|
||||
iny
|
||||
bne found_message_in_token_stream
|
||||
*
|
||||
!:
|
||||
pla
|
||||
;; Rub out space at the end
|
||||
// Rub out space at the end
|
||||
lda #$14
|
||||
jsr JCHROUT
|
||||
rts
|
||||
|
||||
print_packed_word:
|
||||
;; A = the word to print
|
||||
// A = the word to print
|
||||
tax
|
||||
|
||||
;; Setup pointer to packed words
|
||||
// Setup pointer to packed words
|
||||
lda #<packed_message_words
|
||||
sta temp_string_ptr+0
|
||||
lda #>packed_message_words
|
||||
sta temp_string_ptr+1
|
||||
|
||||
;; Find the word in the list
|
||||
// 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
|
||||
// $x0 is an end of work marker
|
||||
lda (temp_string_ptr),y
|
||||
and #$0f
|
||||
cmp #$00
|
||||
bne +
|
||||
bne !+
|
||||
dex
|
||||
*
|
||||
;; $FE $xx is an end of work marker
|
||||
!:
|
||||
// $FE $xx is an end of work marker
|
||||
lda (temp_string_ptr),y
|
||||
cmp #$fe
|
||||
bne +
|
||||
bne !+
|
||||
dex
|
||||
iny ; skip next byte
|
||||
*
|
||||
iny // skip next byte
|
||||
!:
|
||||
cmp #$ff
|
||||
bne +
|
||||
iny ; skip next byte
|
||||
*
|
||||
bne !+
|
||||
iny // skip next byte
|
||||
!:
|
||||
|
||||
;; Advance to next page if required
|
||||
// Advance to next page if required
|
||||
cpy #$ff
|
||||
bne packed_word_search
|
||||
inc temp_string_ptr+1
|
||||
@@ -94,8 +95,8 @@ packed_word_search:
|
||||
|
||||
found_packed_word:
|
||||
|
||||
;; Get pointer to start of packed word
|
||||
;; Make sure we don't wrap on a page boundary
|
||||
// Get pointer to start of packed word
|
||||
// Make sure we don't wrap on a page boundary
|
||||
tya
|
||||
clc
|
||||
adc temp_string_ptr+0
|
||||
@@ -104,14 +105,14 @@ found_packed_word:
|
||||
adc #$00
|
||||
sta temp_string_ptr+1
|
||||
|
||||
print_packed_string:
|
||||
print_packed_string:
|
||||
ldy #$ff
|
||||
|
||||
next_packed_word_char:
|
||||
;; Y = offset into packed word data - 1
|
||||
// .Y = offset into packed word data - 1
|
||||
iny
|
||||
|
||||
;; Check for end of word
|
||||
|
||||
// Check for end of word
|
||||
lda (temp_string_ptr),y
|
||||
cmp #$00
|
||||
beq end_of_packed_word
|
||||
@@ -122,31 +123,31 @@ next_packed_word_char:
|
||||
and #$f0
|
||||
beq end_of_packed_word
|
||||
|
||||
;; Check if it is an uncommon char
|
||||
// Check if it is an uncommon char
|
||||
lda (temp_string_ptr),y
|
||||
and #$f0
|
||||
cmp #$f0
|
||||
beq is_uncommon_char
|
||||
|
||||
;; Is not an uncommon char, so get char of upper nybl
|
||||
// Is not an uncommon char, so get char of upper nybl
|
||||
lda (temp_string_ptr),y
|
||||
|
||||
;; Put high nybl into low bits of X
|
||||
// Put high nybl into low bits of X
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
|
||||
;; Save Y so it doesn't get clobbered by CHROUT
|
||||
// Save Y so it doesn't get clobbered by CHROUT
|
||||
tya
|
||||
pha
|
||||
|
||||
;; X=1-14 = first 14 chars, so subtract one
|
||||
// X=1-14 = first 14 chars, so subtract one
|
||||
lda packed_message_chars-1,x
|
||||
jsr JCHROUT
|
||||
|
||||
;; See if there is a char in the low nybl to print
|
||||
// See if there is a char in the low nybl to print
|
||||
pla
|
||||
tay
|
||||
lda (temp_string_ptr),y
|
||||
@@ -155,54 +156,54 @@ next_packed_word_char:
|
||||
cmp #$0f
|
||||
beq no_lo_nybl_char
|
||||
|
||||
has_lo_nybl_char:
|
||||
;; We need to print the low nybl char as well
|
||||
has_lo_nybl_char:
|
||||
// We need to print the low nybl char as well
|
||||
tax
|
||||
tya
|
||||
pha
|
||||
|
||||
;; Skip lower nybls of $F or $0 in nybl packed
|
||||
;; bytes, as these do not encode characters
|
||||
// Skip lower nybls of $F or $0 in nybl packed
|
||||
// bytes, as these do not encode characters
|
||||
cpx #$f
|
||||
beq +
|
||||
has_nybl:
|
||||
beq !+
|
||||
has_nybl:
|
||||
cpx #0
|
||||
beq +
|
||||
beq !+
|
||||
|
||||
;; X=1-14 = first 14 chars, so subtract one
|
||||
// X=1-14 = first 14 chars, so subtract one
|
||||
lda packed_message_chars-1,x
|
||||
jsr JCHROUT
|
||||
*
|
||||
!:
|
||||
pla
|
||||
tay
|
||||
;; FALL THROUGH
|
||||
// FALLTHROUGH
|
||||
|
||||
no_lo_nybl_char:
|
||||
|
||||
;; If current byte has $0F in low nybl, then the next
|
||||
;; byte is a whole byte.
|
||||
// If current byte has $0F in low nybl, then the next
|
||||
// byte is a whole byte.
|
||||
lda (temp_string_ptr),y
|
||||
and #$0f
|
||||
cmp #$0f
|
||||
beq next_is_literal_char
|
||||
|
||||
ready_for_next_char:
|
||||
ready_for_next_char:
|
||||
cpy #$ff
|
||||
bne next_packed_word_char
|
||||
end_of_packed_word:
|
||||
;; Hit end of packed data
|
||||
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
|
||||
unpack_literal_char:
|
||||
// Output the literal char, and ready for next char
|
||||
iny
|
||||
tya
|
||||
pha
|
||||
@@ -211,16 +212,16 @@ unpack_literal_char:
|
||||
pla
|
||||
tay
|
||||
rts
|
||||
|
||||
|
||||
is_uncommon_char:
|
||||
;; Lower nybl has offset into low-frequency part of the table
|
||||
// Lower nybl has offset into low-frequency part of the table
|
||||
|
||||
lda (temp_string_ptr),y
|
||||
and #$0f
|
||||
clc
|
||||
adc #14
|
||||
|
||||
;; We need to print the low nybl char as well
|
||||
// We need to print the low nybl char as well
|
||||
tax
|
||||
tya
|
||||
pha
|
||||
|
||||
+38
-38
@@ -1,17 +1,17 @@
|
||||
;; printf()-like routine for simplifying debugging
|
||||
// printf()-like routine for simplifying debugging
|
||||
|
||||
;; Prints the literal zero-terminated string that follows,
|
||||
;; which may also include special tokens that allow
|
||||
;; printing of hex byte and word values stored at the indicated
|
||||
;; addresses.
|
||||
// Prints the literal zero-terminated string that follows,
|
||||
// which may also include special tokens that allow
|
||||
// printing of hex byte and word values stored at the indicated
|
||||
// addresses.
|
||||
|
||||
;; .byte 1,$byte = display byte as hex
|
||||
;; .byte 2,$low,$hi = display word as hex
|
||||
;; .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
|
||||
// .byte 1,$byte = display byte as hex
|
||||
// .byte 2,$low,$hi = display word as hex
|
||||
// .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
|
||||
|
||||
printf:
|
||||
;; Temporary storage is between end of screen at $0400
|
||||
;; and the sprite pointers at $7f8
|
||||
// Temporary storage is between end of screen at $0400
|
||||
// and the sprite pointers at $7f8
|
||||
sta $7f0
|
||||
stx $7f1
|
||||
sty $7f2
|
||||
@@ -19,14 +19,14 @@ printf:
|
||||
pla
|
||||
sta $7f3
|
||||
|
||||
;; Set up read routine
|
||||
lda #$ad ; LDA $nnnn
|
||||
// Set up read routine
|
||||
lda #$ad // LDA $nnnn
|
||||
sta $7f4
|
||||
lda #$60
|
||||
sta $7f7 ; RTS
|
||||
sta $7f7 // RTS
|
||||
|
||||
;; Get PC of caller from the stack, so that
|
||||
;; we can parse through it
|
||||
// Get PC of caller from the stack, so that
|
||||
// we can parse through it
|
||||
pla
|
||||
clc
|
||||
adc #$01
|
||||
@@ -39,8 +39,8 @@ printf_loop:
|
||||
jsr $7f4
|
||||
cmp #$00
|
||||
bne printf_continues
|
||||
;; Put return address on stack and restore
|
||||
;; registers
|
||||
// Put return address on stack and restore
|
||||
// registers
|
||||
lda $7f6
|
||||
pha
|
||||
lda $7f5
|
||||
@@ -56,33 +56,33 @@ printf_loop:
|
||||
printf_continues:
|
||||
cmp #$01
|
||||
bne not_hexbyte
|
||||
;; Print a hex byte
|
||||
// Print a hex byte
|
||||
|
||||
;; Skip the token
|
||||
// Skip the token
|
||||
jsr printf_advance
|
||||
;; Read the low byte
|
||||
// Read the low byte
|
||||
jsr $7f4
|
||||
;; Print as hex
|
||||
// Print as hex
|
||||
jsr printf_printhexbyte
|
||||
jmp printf_nextchar
|
||||
|
||||
not_hexbyte:
|
||||
cmp #$02
|
||||
bne not_hexword
|
||||
;; Print a hex word
|
||||
// Print a hex word
|
||||
|
||||
;; Skip the token
|
||||
// Skip the token
|
||||
jsr printf_advance
|
||||
jsr printf_advance
|
||||
;; Read the high byte
|
||||
// Read the high byte
|
||||
jsr $7f4
|
||||
;; Print as hex
|
||||
// Print as hex
|
||||
jsr printf_printhexbyte
|
||||
;; Skip the token
|
||||
// Skip the token
|
||||
jsr printf_retreat
|
||||
;; Read the low byte
|
||||
// Read the low byte
|
||||
jsr $7f4
|
||||
;; Print as hex
|
||||
// Print as hex
|
||||
jsr printf_printhexbyte
|
||||
jsr printf_advance
|
||||
jmp printf_nextchar
|
||||
@@ -91,11 +91,11 @@ not_hexword:
|
||||
cmp #$f0
|
||||
bcc not_pointer
|
||||
|
||||
;; Treat two-byte arg as base address
|
||||
;; and lower 4 bits of token as offset from
|
||||
;; that location.
|
||||
// Treat two-byte arg as base address
|
||||
// and lower 4 bits of token as offset from
|
||||
// that location.
|
||||
|
||||
;; Get offset
|
||||
// Get offset
|
||||
and #$0f
|
||||
tay
|
||||
|
||||
@@ -111,7 +111,7 @@ not_hexword:
|
||||
jmp printf_nextchar
|
||||
|
||||
not_pointer:
|
||||
;; Print character
|
||||
// Print character
|
||||
jsr JCHROUT
|
||||
|
||||
printf_nextchar:
|
||||
@@ -120,15 +120,15 @@ printf_nextchar:
|
||||
jmp printf_loop
|
||||
|
||||
printf_advance:
|
||||
;; Advance pointer to next character
|
||||
// Advance pointer to next character
|
||||
inc $7f5
|
||||
bne +
|
||||
bne !+
|
||||
inc $7f6
|
||||
*
|
||||
!:
|
||||
rts
|
||||
|
||||
printf_retreat:
|
||||
;; Retreat pointer to previous char
|
||||
// Retreat pointer to previous char
|
||||
lda $7f5
|
||||
sec
|
||||
sbc #1
|
||||
@@ -139,7 +139,7 @@ printf_retreat:
|
||||
rts
|
||||
|
||||
printf_printhexbyte:
|
||||
;; Print the hex value in .A as two digits, idea by Haubitze
|
||||
// Print the hex value in .A as two digits, idea by Haubitze
|
||||
sed
|
||||
pha
|
||||
lsr
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ready_message:
|
||||
;; See src/make_error_tables.c for packed message handling
|
||||
;; information.
|
||||
// See src/make_error_tables.c for packed message handling
|
||||
// information.
|
||||
ldx #29
|
||||
jmp print_packed_message
|
||||
|
||||
+10
-10
@@ -1,19 +1,19 @@
|
||||
|
||||
select_device:
|
||||
|
||||
;; Take last device number, make sure it's a drive - 8 or above. Above 30,
|
||||
;; although illegal for IEC we also consider a drive, as they exists
|
||||
;; drivers assigning these numbers to CBM-DOS capable devices - like some
|
||||
;; IEEE-488 carts.
|
||||
;;
|
||||
;; If current device is not a drive, set device to 8 (first drive number)
|
||||
;; Device number is left in X, for SETFLS Kernal routine
|
||||
// Take last device number, make sure it's a drive - 8 or above. Above 30,
|
||||
// although illegal for IEC we also consider a drive, as they exists
|
||||
// drivers assigning these numbers to CBM-DOS capable devices - like some
|
||||
// IEEE-488 carts.
|
||||
//
|
||||
// If current device is not a drive, set device to 8 (first drive number)
|
||||
// Device number is left in X, for SETFLS Kernal routine
|
||||
|
||||
;; Note: if tape support is introduced here, make sure DOS wedge won't get broken
|
||||
// Note: if tape support is introduced here, make sure DOS wedge won't get broken
|
||||
|
||||
ldx current_device_number
|
||||
cpx #$08
|
||||
bcs +
|
||||
bcs !+
|
||||
ldx #$08
|
||||
*
|
||||
!:
|
||||
rts
|
||||
+100
-100
@@ -1,18 +1,18 @@
|
||||
;; Tokenise a line of BASIC
|
||||
;; Stored at $0200
|
||||
;; Length in tokenise_work1
|
||||
// Tokenise a line of BASIC
|
||||
// Stored at $0200
|
||||
// Length in tokenise_work1
|
||||
|
||||
tokenise_line:
|
||||
|
||||
;; We need to consider each offset in the string to see if it matches
|
||||
;; a token. No BASIC keyword is > 7 bytes, so we need to start with that
|
||||
;; length (or remaining length of string) and count our way back down.
|
||||
;; This means we need separate start and end points to keep track of.
|
||||
// We need to consider each offset in the string to see if it matches
|
||||
// a token. No BASIC keyword is > 7 bytes, so we need to start with that
|
||||
// length (or remaining length of string) and count our way back down.
|
||||
// This means we need separate start and end points to keep track of.
|
||||
|
||||
;; $0110 = offset into string
|
||||
;; $0111 = number of bytes to pack
|
||||
;; $0112 = offset into tokenised output
|
||||
;; $0113 = length of raw string
|
||||
// $0110 = offset into string
|
||||
// $0111 = number of bytes to pack
|
||||
// $0112 = offset into tokenised output
|
||||
// $0113 = length of raw string
|
||||
|
||||
lda #$00
|
||||
sta $0110
|
||||
@@ -24,56 +24,56 @@ tokenise_line:
|
||||
|
||||
tokenise_char:
|
||||
|
||||
;; Check if we have reached end of the line?
|
||||
// Check if we have reached end of the line?
|
||||
lda $0110
|
||||
cmp $0113
|
||||
bne +
|
||||
bne !+
|
||||
|
||||
;; End of line reached
|
||||
// End of line reached
|
||||
|
||||
;; Finished tokenising line
|
||||
;; Update tokenise_work1 and terminate with null
|
||||
// Finished tokenising line
|
||||
// Update tokenise_work1 and terminate with null
|
||||
ldx $0112
|
||||
lda #$00
|
||||
sta $0200,x
|
||||
stx tokenise_work1
|
||||
|
||||
;; Clear quote mode flag that is also used by KERNAL for screen display
|
||||
// Clear quote mode flag that is also used by KERNAL for screen display
|
||||
lda #$00
|
||||
sta quote_mode_flag
|
||||
rts
|
||||
*
|
||||
;; More to do
|
||||
!:
|
||||
// More to do
|
||||
|
||||
;; Maximum keyword length
|
||||
// Maximum keyword length
|
||||
lda #7
|
||||
sta $0111
|
||||
|
||||
tokenise_char_loop:
|
||||
;; Pack the word from the start (start = X, raw len = tokenise_work1)
|
||||
;; Returns packed length in tokenise_work2 and writes the packed
|
||||
;; word at $0100+
|
||||
// Pack the word from the start (start = X, raw len = tokenise_work1)
|
||||
// Returns packed length in tokenise_work2 and writes the packed
|
||||
// word at $0100+
|
||||
|
||||
ldx $0110
|
||||
lda $0200,x
|
||||
cmp #$22
|
||||
bne tk_not_quote
|
||||
|
||||
;; Quote
|
||||
// Quote
|
||||
lda quote_mode_flag
|
||||
eor #$ff
|
||||
sta quote_mode_flag
|
||||
jmp tk_literal_char
|
||||
|
||||
tk_not_quote:
|
||||
;; Check for literal characters in various ranges
|
||||
;; (This just speeds the tokeniser up, by avoiding the packed token search
|
||||
;; for such characters).
|
||||
// Check for literal characters in various ranges
|
||||
// (This just speeds the tokeniser up, by avoiding the packed token search
|
||||
// for such characters).
|
||||
|
||||
;; SPACE and punctuation before +,- and *
|
||||
// SPACE and punctuation before +,- and *
|
||||
cmp #$2a
|
||||
bcc tk_literal_char
|
||||
;; Don't try to tokenise digits
|
||||
// Don't try to tokenise digits
|
||||
cmp #$30
|
||||
bcc tk_might_be_keyword
|
||||
cmp #$3a
|
||||
@@ -81,41 +81,41 @@ tk_not_quote:
|
||||
jmp tk_literal_char
|
||||
|
||||
tk_might_be_keyword:
|
||||
;; Don't tokenise in quote mode
|
||||
// Don't tokenise in quote mode
|
||||
lda quote_mode_flag
|
||||
bne tk_literal_char
|
||||
|
||||
;; Pack string
|
||||
// Pack string
|
||||
ldx $0110
|
||||
lda $0111
|
||||
sta tokenise_work1
|
||||
|
||||
;; XXX - We should implement an optimisation where we
|
||||
;; trim the last symbol of successively, instead of re-packing the word
|
||||
;; again with one less char each time.
|
||||
;; XXX - We should limit the word length to the length of interesting chars
|
||||
;; that are available.
|
||||
// XXX - We should implement an optimisation where we
|
||||
// trim the last symbol of successively, instead of re-packing the word
|
||||
// again with one less char each time.
|
||||
// XXX - We should limit the word length to the length of interesting chars
|
||||
// that are available.
|
||||
|
||||
jsr pack_word
|
||||
lda tokenise_work2
|
||||
cmp #$10
|
||||
bcc +
|
||||
;; Packed string too long
|
||||
bcc !+
|
||||
// Packed string too long
|
||||
jmp do_STRING_TOO_LONG_error
|
||||
*
|
||||
!:
|
||||
|
||||
;; Search for it in keywords
|
||||
// Search for it in keywords
|
||||
jsr keyword_search
|
||||
|
||||
;; Did we find a keyword?
|
||||
// Did we find a keyword?
|
||||
bcc found_token_in_line
|
||||
|
||||
;; Nope, so try shorter
|
||||
// Nope, so try shorter
|
||||
dec $0111
|
||||
bne tokenise_char_loop
|
||||
|
||||
tk_literal_char:
|
||||
;; Is not a token, so copy to output verbatim
|
||||
// Is not a token, so copy to output verbatim
|
||||
ldx $0110
|
||||
ldy $0112
|
||||
lda $0200,x
|
||||
@@ -123,68 +123,68 @@ tk_literal_char:
|
||||
inc $0112
|
||||
inc $0110
|
||||
|
||||
;; Tokenise next char
|
||||
// Tokenise next char
|
||||
jmp tokenise_char
|
||||
|
||||
found_token_in_line:
|
||||
|
||||
;; Got a token, so write it out
|
||||
// Got a token, so write it out
|
||||
ldx $0112
|
||||
sta $0200,x
|
||||
inx
|
||||
stx $0112
|
||||
|
||||
;; If it is REM, then lock us in quote mode to the end of the line
|
||||
// If it is REM, then lock us in quote mode to the end of the line
|
||||
cmp #$8f
|
||||
bne not_rem
|
||||
sta quote_mode_flag
|
||||
not_rem:
|
||||
|
||||
;; Now skip over the length of the token
|
||||
// Now skip over the length of the token
|
||||
lda $0110
|
||||
clc
|
||||
adc $0111
|
||||
sta $0110
|
||||
|
||||
;; See if there is more of the line left to process
|
||||
// See if there is more of the line left to process
|
||||
jmp tokenise_char
|
||||
|
||||
|
||||
|
||||
|
||||
;; Search for word in keyword list
|
||||
;; The packed form is canonical, so we can search for the keyword while
|
||||
;; it remains compressed. This also saves a little time.
|
||||
;; Algorithm is simply to find matching first bytes, and then look for
|
||||
;; the rest being a match.
|
||||
|
||||
|
||||
// Search for word in keyword list
|
||||
// The packed form is canonical, so we can search for the keyword while
|
||||
// it remains compressed. This also saves a little time.
|
||||
// Algorithm is simply to find matching first bytes, and then look for
|
||||
// the rest being a match.
|
||||
|
||||
keyword_search:
|
||||
;; Search for the compressed keyword stored at $0100 in the list
|
||||
;; of compressed keywords
|
||||
|
||||
;; tokenise_work1 = offset in line of input
|
||||
;; tokenise_work2 = length of token we are matching
|
||||
;; tokenise_work3 = offset in token list
|
||||
;; load_or_verify_or_tokenise_work5 = temporary work space
|
||||
;; X and Y registers used as temporary space.
|
||||
;; returns C=1 if no matching token, else C=0 and A=token
|
||||
// Search for the compressed keyword stored at $0100 in the list
|
||||
// of compressed keywords
|
||||
|
||||
// tokenise_work1 = offset in line of input
|
||||
// tokenise_work2 = length of token we are matching
|
||||
// tokenise_work3 = offset in token list
|
||||
// load_or_verify_or_tokenise_work5 = temporary work space
|
||||
// X and Y registers used as temporary space.
|
||||
// returns C=1 if no matching token, else C=0 and A=token
|
||||
|
||||
lda #$00
|
||||
sta tokenise_work1
|
||||
sta tokenise_work3
|
||||
next_kw_offset:
|
||||
;; Advance offset in compressed keyword list, to see if a match
|
||||
;; BEGINS here
|
||||
// Advance offset in compressed keyword list, to see if a match
|
||||
// BEGINS here
|
||||
|
||||
;; Get count of bytes to compare
|
||||
// Get count of bytes to compare
|
||||
lda tokenise_work2
|
||||
sta load_or_verify_or_tokenise_work5
|
||||
|
||||
;; Load current position
|
||||
|
||||
// Load current position
|
||||
ldy tokenise_work3
|
||||
ldx tokenise_work1
|
||||
|
||||
;; Advance offset in compressed token list, and stop at the end
|
||||
|
||||
// Advance offset in compressed token list, and stop at the end
|
||||
inc tokenise_work3
|
||||
lda tokenise_work3
|
||||
cmp #packed_keyword_table_len
|
||||
@@ -194,76 +194,76 @@ next_in_match:
|
||||
lda $0100,x
|
||||
cmp packed_keywords,y
|
||||
bne next_kw_offset
|
||||
;; Advance to next chars in source and target
|
||||
// Advance to next chars in source and target
|
||||
inx
|
||||
iny
|
||||
|
||||
dec load_or_verify_or_tokenise_work5 ; Have we compared all bytes yet?
|
||||
dec load_or_verify_or_tokenise_work5 // Have we compared all bytes yet?
|
||||
|
||||
bne next_in_match
|
||||
|
||||
;; Keyword matches!
|
||||
// Keyword matches!
|
||||
|
||||
;; Now make sure we started on a keyword boundary
|
||||
;; (we know we finished on one, because of the structure of the compressed
|
||||
;; keyword data).
|
||||
;; Offset 0
|
||||
;; previous byte is $x0
|
||||
;; two byte prior is $FE
|
||||
// Now make sure we started on a keyword boundary
|
||||
// (we know we finished on one, because of the structure of the compressed
|
||||
// keyword data).
|
||||
// Offset 0
|
||||
// previous byte is $x0
|
||||
// two byte prior is $FE
|
||||
|
||||
;; Get offset of first byte of this token
|
||||
// Get offset of first byte of this token
|
||||
ldx tokenise_work3
|
||||
dex ; pointer points one late, so rewind it
|
||||
dex // pointer points one late, so rewind it
|
||||
|
||||
;; At start of list?
|
||||
// At start of list?
|
||||
cpx #$00
|
||||
beq word_boundary
|
||||
dex
|
||||
;; Previous byte is $x0 end token?
|
||||
// Previous byte is $x0 end token?
|
||||
lda packed_keywords,x
|
||||
and #$0f
|
||||
beq word_boundary
|
||||
dex
|
||||
;; Uber-previouss byte is $FE final literal token?
|
||||
// Uber-previouss byte is $FE final literal token?
|
||||
lda packed_keywords,x
|
||||
cmp #$fe
|
||||
beq word_boundary
|
||||
|
||||
;; Not a word boundary, so ignore
|
||||
// Not a word boundary, so ignore
|
||||
jmp next_kw_offset
|
||||
|
||||
word_boundary:
|
||||
;; Found a token whose offset is in tokenise_work3
|
||||
;; Now trace back to the start of the compressed keyword list
|
||||
;; to work out what keyword number we are, so that we can return
|
||||
;; the token number.
|
||||
// Found a token whose offset is in tokenise_work3
|
||||
// Now trace back to the start of the compressed keyword list
|
||||
// to work out what keyword number we are, so that we can return
|
||||
// the token number.
|
||||
|
||||
ldy #$80
|
||||
|
||||
token_count_loop:
|
||||
lda packed_keywords,x
|
||||
cmp #$fe
|
||||
bne +
|
||||
bne !+
|
||||
iny
|
||||
*
|
||||
!:
|
||||
and #$0f
|
||||
cmp #$00
|
||||
bne +
|
||||
bne !+
|
||||
iny
|
||||
*
|
||||
!:
|
||||
cpx #$00
|
||||
beq +
|
||||
beq !+
|
||||
dex
|
||||
jmp token_count_loop
|
||||
*
|
||||
|
||||
!:
|
||||
|
||||
tya
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
done_searching_for_token:
|
||||
;; No token found
|
||||
// No token found
|
||||
sec
|
||||
lda #$00
|
||||
rts
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
;; IMPORTANT:
|
||||
;; These routines lengths cannot be changed without changing
|
||||
;; the aliases for peek_under_roms, poke_under_roms etc
|
||||
;; in ,aliases.s.
|
||||
;; Thus those addresses are expressed using formulae.
|
||||
// IMPORTANT:
|
||||
// These routines lengths cannot be changed without changing
|
||||
// the aliases for peek_under_roms, poke_under_roms etc
|
||||
// in ,aliases.s.
|
||||
// Thus those addresses are expressed using formulae.
|
||||
|
||||
install_ram_routines:
|
||||
;; Copy routines into place
|
||||
ldx #ram_routines_len-1
|
||||
*
|
||||
// Copy routines into place
|
||||
ldx #ram_routines_end-ram_routines_start-1
|
||||
!:
|
||||
lda ram_routines_start,x
|
||||
sta tiny_nmi_handler,x
|
||||
dex
|
||||
bpl -
|
||||
bpl !-
|
||||
|
||||
;; Point NMI handler to tiny_nmi_handler
|
||||
// Point NMI handler to tiny_nmi_handler
|
||||
lda #<tiny_nmi_handler
|
||||
sta $FFFE
|
||||
lda #>tiny_nmi_handler
|
||||
@@ -23,14 +23,14 @@ install_ram_routines:
|
||||
|
||||
ram_routines_start:
|
||||
|
||||
;; XXX - Routine order must match that of the KERNAL version of the file.
|
||||
;; (since it has fewer routines)
|
||||
// XXX - Routine order must match that of the KERNAL version of the file.
|
||||
// (since it has fewer routines)
|
||||
tiny_nmi_handler_routine:
|
||||
inc missed_nmi_flag
|
||||
rti
|
||||
peek_under_roms_routine:
|
||||
php
|
||||
; Offset of arg of lda ($00),y
|
||||
// Offset of arg of lda ($00),y
|
||||
stx peek_under_roms+pa-peek_under_roms_routine+1
|
||||
jsr memmap_allram
|
||||
pa: lda ($00),y
|
||||
@@ -40,7 +40,7 @@ pa: lda ($00),y
|
||||
|
||||
poke_under_roms_routine:
|
||||
php
|
||||
; Offset of arg of lda ($00),y
|
||||
// Offset of arg of lda ($00),y
|
||||
stx poke_under_roms+pb-poke_under_roms_routine+1
|
||||
jsr memmap_allram
|
||||
pb: sta ($00),y
|
||||
@@ -64,12 +64,12 @@ memmap_allram_routine:
|
||||
rts
|
||||
|
||||
shift_mem_up_routine:
|
||||
;; Move memmove_size bytes from memmove_src to memmove_dst,
|
||||
;; where memmove_dst > memmove_src
|
||||
;; This means we have to copy from the back end down.
|
||||
;; This routine assumes the pointers are already pointed
|
||||
;; to the end of the areas, and that Y is correctly initialised
|
||||
;; to allow the copy to begin.
|
||||
// Move memmove_size bytes from memmove_src to memmove_dst,
|
||||
// where memmove_dst > memmove_src
|
||||
// This means we have to copy from the back end down.
|
||||
// This routine assumes the pointers are already pointed
|
||||
// to the end of the areas, and that Y is correctly initialised
|
||||
// to allow the copy to begin.
|
||||
php
|
||||
jsr memmap_allram
|
||||
smu1:
|
||||
@@ -85,12 +85,12 @@ smu1:
|
||||
jmp memmap_normal
|
||||
|
||||
shift_mem_down_routine:
|
||||
;; Move memmove_size bytes from memmove_src to memmove_dst,
|
||||
;; where memmove_dst > memmove_src
|
||||
;; This means we have to copy from the back end down.
|
||||
;; This routine assumes the pointers are already pointed
|
||||
;; to the end of the areas, and that Y is correctly initialised
|
||||
;; to allow the copy to begin.
|
||||
// Move memmove_size bytes from memmove_src to memmove_dst,
|
||||
// where memmove_dst > memmove_src
|
||||
// This means we have to copy from the back end down.
|
||||
// This routine assumes the pointers are already pointed
|
||||
// to the end of the areas, and that Y is correctly initialised
|
||||
// to allow the copy to begin.
|
||||
php
|
||||
jsr memmap_allram
|
||||
smd1:
|
||||
@@ -105,7 +105,4 @@ smd1:
|
||||
plp
|
||||
jmp memmap_normal
|
||||
|
||||
|
||||
ram_routines_end:
|
||||
.alias ram_routines_len ram_routines_end-ram_routines_start
|
||||
|
||||
+89
-89
@@ -1,161 +1,161 @@
|
||||
|
||||
;; START wedge support
|
||||
// START wedge support
|
||||
|
||||
wedge_dos:
|
||||
|
||||
;; Close all the channels, so that wedge has full control
|
||||
// Close all the channels, so that wedge has full control
|
||||
jsr JCLALL
|
||||
|
||||
;; Set file parameters, channel 15 is a typical one for commands
|
||||
jsr select_device ; sets X register
|
||||
// Set file parameters, channel 15 is a typical one for commands
|
||||
jsr select_device // sets .X register
|
||||
lda #$0F
|
||||
ldy #$0F
|
||||
jsr JSETFLS
|
||||
|
||||
;; Now we have to check what the user wants us to do
|
||||
// Now we have to check what the user wants us to do
|
||||
|
||||
;; Check if user asked for a status
|
||||
// Check if user asked for a status
|
||||
ldy #$00
|
||||
lda (basic_current_statement_ptr), y
|
||||
bne +
|
||||
jmp wedge_dos_status ; XXX try to optimize this, perhaps move 'wedge_dos_status' above?
|
||||
*
|
||||
;; Check if asked for a directory
|
||||
bne !+
|
||||
jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above?
|
||||
!:
|
||||
// Check if asked for a directory
|
||||
cmp #$24
|
||||
bne +
|
||||
bne !+
|
||||
jmp wedge_dos_directory
|
||||
*
|
||||
;; Check if asked to change drive number, or if it is a regular command
|
||||
!:
|
||||
// Check if asked to change drive number, or if it is a regular command
|
||||
cmp #$30
|
||||
bcc wedge_dos_command ; char code before 0
|
||||
bcc wedge_dos_command // char code before 0
|
||||
cmp #$3A
|
||||
bcs wedge_dos_command ; char code after 9
|
||||
bcs wedge_dos_command // char code after 9
|
||||
iny
|
||||
lda (basic_current_statement_ptr), y
|
||||
beq wedge_dos_change_drive ; end of buffer
|
||||
beq wedge_dos_change_drive // end of buffer
|
||||
cmp #$20
|
||||
beq wedge_dos_change_drive
|
||||
jmp -
|
||||
jmp !-
|
||||
|
||||
wedge_dos_command:
|
||||
|
||||
;; Provide command name
|
||||
// Provide command name
|
||||
jsr wedge_dos_setnam
|
||||
|
||||
jsr JSETNAM
|
||||
jsr JOPEN
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
;; Retrieve status, print it if not OK
|
||||
bcc !+
|
||||
jmp wedge_dos_basic_error // XXX combine with other such jumps
|
||||
!:
|
||||
// Retrieve status, print it if not OK
|
||||
jsr JCLALL
|
||||
jsr wedge_dos_status_get
|
||||
lda BUF+0
|
||||
cmp #$30 ; '0'
|
||||
cmp #$30 // '0'
|
||||
bne wedge_dos_status_print
|
||||
lda BUF+1
|
||||
cmp #$30 ; '0'
|
||||
cmp #$30 // '0'
|
||||
bne wedge_dos_status_print
|
||||
|
||||
;; Clean-up and exit
|
||||
// Clean-up and exit
|
||||
jmp wedge_dos_clean_exit
|
||||
|
||||
wedge_dos_change_drive:
|
||||
|
||||
;; Reuse the line number parser for device number retrieval
|
||||
// Reuse the line number parser for device number retrieval
|
||||
jsr basic_parse_line_number
|
||||
lda basic_line_number+1
|
||||
beq +
|
||||
beq !+
|
||||
jmp do_ILLEGAL_QUANTITY_error
|
||||
*
|
||||
!:
|
||||
lda basic_line_number+0
|
||||
cmp #$08
|
||||
bpl +
|
||||
bcs +
|
||||
bpl !+
|
||||
bcs !+
|
||||
jmp do_ILLEGAL_DEVICE_NUMBER_error
|
||||
*
|
||||
!:
|
||||
sta current_device_number
|
||||
jmp basic_end_of_line
|
||||
|
||||
wedge_dos_status_get:
|
||||
|
||||
;; Here the flow is mostly the same as in the example from
|
||||
;; https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive
|
||||
// Here the flow is mostly the same as in the example from
|
||||
// https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive
|
||||
|
||||
;; Set remaining file parameters, open the channel
|
||||
lda #$00 ; empty file name
|
||||
// Set remaining file parameters, open the channel
|
||||
lda #$00 // empty file name
|
||||
jsr JSETNAM
|
||||
jsr JOPEN
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
bcc !+
|
||||
jmp wedge_dos_basic_error // XXX combine with other such jumps
|
||||
!:
|
||||
|
||||
;; Set channel for input
|
||||
// Set channel for input
|
||||
ldx #$0F
|
||||
jsr JCHKIN
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
|
||||
bcc !+
|
||||
jmp wedge_dos_basic_error // XXX combine with other such jumps
|
||||
!:
|
||||
|
||||
ldy #$00
|
||||
*
|
||||
cpy #$50 ; buffer overflow protection
|
||||
beq +
|
||||
jsr JREADST ; retrieve errors
|
||||
;; XXX error in case of status != EOF
|
||||
;; Print out everything retrieved from the drive
|
||||
bne +
|
||||
!:
|
||||
cpy #$50 // buffer overflow protection
|
||||
beq !+
|
||||
jsr JREADST // retrieve errors
|
||||
// XXX error in case of status != EOF
|
||||
// Print out everything retrieved from the drive
|
||||
bne !+
|
||||
jsr JCHRIN
|
||||
bcc wedge_dos_x1
|
||||
jmp wedge_dos_basic_error ; XXX try to optimize this
|
||||
jmp wedge_dos_basic_error // XXX try to optimize this
|
||||
wedge_dos_x1:
|
||||
sta BUF, y
|
||||
iny
|
||||
jmp -
|
||||
*
|
||||
jmp !-
|
||||
!:
|
||||
rts
|
||||
|
||||
wedge_dos_status:
|
||||
jsr wedge_dos_status_get
|
||||
;; FALLTROUGH
|
||||
// FALLTROUGH
|
||||
|
||||
wedge_dos_status_print:
|
||||
|
||||
;; Print buffered status
|
||||
// Print buffered status
|
||||
ldx #$00
|
||||
*
|
||||
!:
|
||||
dey
|
||||
bmi +
|
||||
bmi !+
|
||||
lda BUF, x
|
||||
jsr JCHROUT
|
||||
inx
|
||||
bne -
|
||||
*
|
||||
;; Clean-up and exit
|
||||
bne !-
|
||||
!:
|
||||
// Clean-up and exit
|
||||
jmp wedge_dos_clean_exit
|
||||
|
||||
wedge_dos_directory:
|
||||
|
||||
;; First change the secondary address to the one suitable for
|
||||
;; directory loading
|
||||
lda #$00 ; logical device number
|
||||
// First change the secondary address to the one suitable for
|
||||
// directory loading
|
||||
lda #$00 // logical device number
|
||||
ldx current_device_number
|
||||
ldy #$60
|
||||
jsr JSETFLS
|
||||
|
||||
;; Provide file name
|
||||
// Provide file name
|
||||
jsr wedge_dos_setnam
|
||||
|
||||
;; Open the file
|
||||
// Open the file
|
||||
jsr JOPEN
|
||||
bcs wedge_dos_basic_error
|
||||
|
||||
;; Set channel for file reading
|
||||
// Set channel for file reading
|
||||
ldx #$00
|
||||
jsr JCHKIN
|
||||
bcs wedge_dos_basic_error
|
||||
|
||||
;; Ignore start address (2 first bytes) - XXX check for errors
|
||||
// Ignore start address (2 first bytes) - XXX check for errors
|
||||
jsr JCHRIN
|
||||
bcs wedge_dos_basic_error
|
||||
jsr JCHRIN
|
||||
@@ -163,37 +163,37 @@ wedge_dos_directory:
|
||||
|
||||
wedge_dos_directory_line:
|
||||
|
||||
;; Load a single line, reuse BASIC input buffer
|
||||
// Load a single line, reuse BASIC input buffer
|
||||
ldy #$FF
|
||||
*
|
||||
!:
|
||||
iny
|
||||
jsr JCHRIN
|
||||
bcs wedge_dos_basic_error
|
||||
sta BUF, y
|
||||
cpy #$50
|
||||
beq + ; line too long, terminate loading file
|
||||
beq !+ // line too long, terminate loading file
|
||||
jsr JREADST
|
||||
bne + ; end of file
|
||||
cpy #$04 ; 2 bytes (pointer to next line) + 2 bytes (line number)
|
||||
bcc -
|
||||
bne !+ // end of file
|
||||
cpy #$04 // 2 bytes (pointer to next line) + 2 bytes (line number)
|
||||
bcc !-
|
||||
lda BUF, y
|
||||
bne -
|
||||
;; End of line, but not end of file
|
||||
bne !-
|
||||
// End of line, but not end of file
|
||||
beq wedge_dos_directory_display
|
||||
*
|
||||
!:
|
||||
lda #K_STS_END_OF_FILE
|
||||
sta IOSTATUS ; make sure end of file is marked
|
||||
;; FALLTROUGH
|
||||
sta IOSTATUS // make sure end of file is marked
|
||||
// FALLTROUGH
|
||||
|
||||
wedge_dos_directory_display:
|
||||
|
||||
cpy #$05 ; protection against malformed directory
|
||||
cpy #$05 // protection against malformed directory
|
||||
bcc wedge_dos_clean_exit
|
||||
|
||||
lda #$00 ; extra protection agains buffer overflow
|
||||
lda #$00 // extra protection agains buffer overflow
|
||||
sta BUF, y
|
||||
|
||||
;; Display line
|
||||
// Display line
|
||||
ldx #<BUF
|
||||
stx basic_current_line_ptr+0
|
||||
ldx #>BUF
|
||||
@@ -201,14 +201,14 @@ wedge_dos_directory_display:
|
||||
ldx #basic_current_line_ptr
|
||||
jsr list_single_line
|
||||
|
||||
;; Read & display next line or quit
|
||||
// Read & display next line or quit
|
||||
lda IOSTATUS
|
||||
beq wedge_dos_directory_line
|
||||
;; FALLTROUGH
|
||||
// FALLTROUGH
|
||||
|
||||
wedge_dos_clean_exit:
|
||||
jsr JCLALL
|
||||
;; Print new line
|
||||
// Print new line
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
jmp basic_end_of_line
|
||||
@@ -222,17 +222,17 @@ wedge_dos_basic_error:
|
||||
jmp do_basic_error
|
||||
|
||||
wedge_dos_setnam:
|
||||
;; Now determine the length of the 'file' name
|
||||
// Now determine the length of the 'file' name
|
||||
ldy #$FF
|
||||
*
|
||||
!:
|
||||
iny
|
||||
lda (basic_current_statement_ptr), y
|
||||
bne -
|
||||
bne !-
|
||||
|
||||
;; Set the name to open
|
||||
// Set the name to open
|
||||
tya
|
||||
ldx basic_current_statement_ptr+0
|
||||
ldy basic_current_statement_ptr+1
|
||||
jmp JSETNAM
|
||||
|
||||
;; END wedge support
|
||||
// END wedge support
|
||||
Reference in new issue
Block a user