adapted to Kick Assembler, some documentation update

This commit is contained in:
FeralChild64 committed 2019-09-07 12:35:21 +02:00
1 parent ae23dbae7b
commit de27124b4f
198 files changed
+4181 -3976

No files matched your search

+116 -114
View File
@@ -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
+5 -4
View File
@@ -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
}
+20 -20
View File
@@ -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
}
+3 -2
View File
@@ -1,3 +1,4 @@
;; Compute's Mapping the C64 p88
// Compute's Mapping the C64 p88
.word basic_cold_start
+2 -1
View File
@@ -1,2 +1,3 @@
;; Compute's Mapping the C64 p88
// Compute's Mapping the C64 p88
.word basic_warm_start
+5 -5
View File
@@ -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
+6 -7
View File
@@ -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
+24 -25
View File
@@ -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
+27 -26
View File
@@ -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
View File
@@ -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
+78 -79
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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:
+26 -25
View File
@@ -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
View File
@@ -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
+8 -8
View File
@@ -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
+52 -52
View File
@@ -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
+61 -61
View File
@@ -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
+4 -4
View File
@@ -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
+3 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
+5 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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
+67 -66
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+26 -29
View File
@@ -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
View File
@@ -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