|
- ;
- ; kernal_os.asm
- ; sample C64 OS skeleton that keeps the KERNAL ROM visible
- ;
- ; build:
- ; ca65 kernal_os.asm -o kernal_os.o
- ; ld65 -C kernal_os.cfg kernal_os.o -o kernal_os.prg
- ;
- ; run:
- ; LOAD "KERNAL_OS.PRG",8
- ; RUN
- ;
-
- .setcpu "6502"
-
- ; ------------------------------------------------------------
- ; KERNAL routines
- ; ------------------------------------------------------------
-
- CINT = $FF81
- IOINIT = $FF84
- RESTOR = $FF8A
- CHROUT = $FFD2
- GETIN = $FFE4
- STOPKEY = $FFE1
- SCREEN = $FFED
- READST = $FFB7
- SETLFS = $FFBA
- SETNAM = $FFBD
- OPEN = $FFC0
- CLOSE = $FFC3
- CHKIN = $FFC6
- CHKOUT = $FFC9
- CLRCH = $FFCC
- BASIN = $FFCF
- CLALL = $FFE7
-
- ; ------------------------------------------------------------
- ; system locations
- ; ------------------------------------------------------------
-
- CPU_PORT = $0001
- PTR1_LO = $FB
- PTR1_HI = $FC
-
- ; ------------------------------------------------------------
- ; memory layout for this sample OS
- ; ------------------------------------------------------------
-
- OS_LOAD = $0801
- WORKSPACE = $A000
- FILE_BUFFER = $A100
- FILE_BUFFER_MAX = 224
- INPUT_MAX = 64
- DISK_DEV = 8
- LFN_DIR = 2
- LFN_CMD = 15
- SYS_ENTRY = 2061
-
- ; ------------------------------------------------------------
- ; PETSCII constants
- ; ------------------------------------------------------------
-
- CR = $0D
- CLR_HOME = $93
-
- .segment "LOADADDR"
-
- .word OS_LOAD
-
- .segment "BASIC"
-
- .word basic_end
- .word 10
- .byte $9E
- .byte "2061"
- .byte 0
- basic_end:
- .word 0
-
- .segment "CODE"
-
- start:
- jsr IOINIT
- jsr RESTOR
- jsr CINT
- jsr reset_file_state
- jsr set_os_memory
- jsr init_workspace
- jsr print_banner
- jmp main_loop
-
- main_loop:
- jsr print_prompt
- jsr read_line
- lda exit_requested
- beq parse_shell_command
- jmp exit_to_basic
-
- parse_shell_command:
- jsr parse_command
- lda exit_requested
- beq continue_shell
- jmp exit_to_basic
-
- continue_shell:
- jmp main_loop
-
- do_mem:
- lda #<msg_mode
- ldy #>msg_mode
- jsr print_string
-
- lda CPU_PORT
- jsr print_hex_byte
-
- lda #<msg_workspace
- ldy #>msg_workspace
- jsr print_string
-
- lda WORKSPACE
- jsr print_hex_byte
-
- lda #<msg_layout
- ldy #>msg_layout
- jsr print_string
- rts
-
- do_inc:
- inc workspace_counter
- lda workspace_counter
- sta WORKSPACE
-
- lda #<msg_written
- ldy #>msg_written
- jsr print_string
-
- lda WORKSPACE
- jsr print_hex_byte
-
- lda #CR
- jsr CHROUT
- rts
-
- do_dump:
- lda #<msg_dump
- ldy #>msg_dump
- jsr print_string
-
- ldx #0
-
- dump_loop:
- lda WORKSPACE,x
- jsr print_hex_byte
-
- lda #' '
- jsr CHROUT
-
- inx
- cpx #16
- bne dump_loop
-
- lda #CR
- jsr CHROUT
- rts
-
- do_zero:
- ldx #0
-
- zero_loop:
- lda #0
- sta WORKSPACE,x
- inx
- cpx #16
- bne zero_loop
-
- lda #0
- sta workspace_counter
-
- lda #<msg_zeroed
- ldy #>msg_zeroed
- jsr print_string
- rts
-
- do_sign:
- jsr write_signature
- lda #<msg_signed
- ldy #>msg_signed
- jsr print_string
- rts
-
- do_cls:
- lda #CLR_HOME
- jsr CHROUT
- rts
-
- do_help:
- lda #<msg_help
- ldy #>msg_help
- jsr print_string
- rts
-
- do_about:
- lda #<msg_about
- ldy #>msg_about
- jsr print_string
- rts
-
- do_screen:
- lda #<msg_screen
- ldy #>msg_screen
- jsr print_string
-
- jsr SCREEN
- txa
- jsr print_decimal_byte
-
- lda #'X'
- jsr CHROUT
-
- tya
- jsr print_decimal_byte
-
- lda #CR
- jsr CHROUT
- rts
-
- do_dir:
- lda #0
- sta dir_line_count
- jsr build_dir_spec
- jsr reset_file_state
-
- lda #LFN_DIR
- sta active_lfn
- ldx current_device
- ldy #0
- jsr SETLFS
-
- lda filename_len
- ldx #<filename_spec
- ldy #>filename_spec
- jsr SETNAM
-
- jsr OPEN
- bcc dir_channel_input
- jmp disk_open_error
-
- dir_channel_input:
- ldx #LFN_DIR
- jsr CHKIN
- bcc dir_next_line
- jmp disk_input_error
-
- dir_next_line:
- lda #0
- sta line_had_name
- sta quote_state
-
- jsr BASIN
- sta dir_link_lo
- jsr BASIN
- sta dir_link_hi
-
- lda dir_link_lo
- ora dir_link_hi
- beq dir_done
-
- jsr BASIN
- jsr BASIN
-
- lda dir_line_count
- beq dir_skip_line
-
- dir_line_loop:
- jsr BASIN
- beq dir_line_end
- sta temp_char
-
- cmp #'"'
- beq dir_toggle_quote
-
- lda quote_state
- beq dir_line_loop
-
- lda line_had_name
- bne dir_print_char
- lda #1
- sta line_had_name
-
- dir_print_char:
- lda temp_char
- jsr CHROUT
- jmp dir_line_loop
-
- dir_toggle_quote:
- lda quote_state
- eor #1
- sta quote_state
- jmp dir_line_loop
-
- dir_skip_line:
- jsr BASIN
- beq dir_line_end
- jmp dir_skip_line
-
- dir_line_end:
- inc dir_line_count
-
- lda line_had_name
- beq dir_next_line
-
- lda #CR
- jsr CHROUT
- jmp dir_next_line
-
- dir_done:
- jsr close_active_file
- rts
-
- do_status:
- lda #<msg_status
- ldy #>msg_status
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_CMD
- sta active_lfn
- ldx current_device
- ldy #15
- jsr SETLFS
-
- lda #0
- ldx #0
- ldy #0
- jsr SETNAM
-
- jsr OPEN
- bcc status_channel_input
- jmp disk_open_error
-
- status_channel_input:
- ldx #LFN_CMD
- jsr CHKIN
- bcc status_loop
- jmp disk_input_error
-
- status_loop:
- jsr BASIN
- jsr CHROUT
- jsr READST
- and #$40
- beq status_loop
-
- lda #CR
- jsr CHROUT
- jsr close_active_file
- rts
-
- do_init:
- lda #<msg_init
- ldy #>msg_init
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_CMD
- sta active_lfn
- ldx current_device
- ldy #15
- jsr SETLFS
-
- lda #1
- ldx #<fname_init
- ldy #>fname_init
- jsr SETNAM
-
- jsr OPEN
- bcc init_done
- jmp disk_open_error
-
- init_done:
- jsr close_active_file
- jmp do_status
-
- do_delete:
- jsr find_argument_start
- bcs delete_missing_name
-
- jsr build_scratch_command
- bcs delete_missing_name
-
- lda #<msg_delete
- ldy #>msg_delete
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_CMD
- sta active_lfn
- ldx current_device
- ldy #15
- jsr SETLFS
-
- lda scratch_len
- ldx #<scratch_command
- ldy #>scratch_command
- jsr SETNAM
-
- jsr OPEN
- bcc delete_done
- jmp disk_open_error
-
- delete_done:
- jsr close_active_file
- jmp do_status
-
- delete_missing_name:
- lda #<msg_delete_usage
- ldy #>msg_delete_usage
- jsr print_string
- rts
-
- do_touch:
- jsr find_argument_start
- bcs touch_missing_name
-
- jsr build_write_filename
- bcs touch_missing_name
-
- lda #<msg_touch
- ldy #>msg_touch
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_DIR
- sta active_lfn
- ldx current_device
- ldy #2
- jsr SETLFS
-
- lda filename_len
- ldx #<filename_spec
- ldy #>filename_spec
- jsr SETNAM
-
- jsr OPEN
- bcc touch_done
- jmp disk_open_error
-
- touch_done:
- jsr close_active_file
- jmp do_status
-
- touch_missing_name:
- lda #<msg_touch_usage
- ldy #>msg_touch_usage
- jsr print_string
- rts
-
- do_echo:
- jsr find_argument_start
- bcs echo_missing_text
-
- jsr copy_echo_to_buffer
- bcs echo_missing_text
-
- lda file_buffer_len
- beq echo_missing_text
-
- ldy #0
-
- echo_print_loop:
- cpy file_buffer_len
- beq echo_print_done
- lda FILE_BUFFER,y
- jsr CHROUT
- iny
- bne echo_print_loop
-
- echo_print_done:
- lda #CR
- jsr CHROUT
-
- lda pipe_found
- beq echo_done
-
- jsr rewrite_input_after_pipe
- lda input_buffer
- beq echo_done
- jmp parse_command
-
- echo_done:
- rts
-
- echo_missing_text:
- lda #<msg_echo_usage
- ldy #>msg_echo_usage
- jsr print_string
- rts
-
- do_type:
- jsr find_argument_start
- bcs type_missing_name
-
- jsr build_read_filename
- bcs type_missing_name
- jsr reset_file_state
-
- lda #LFN_DIR
- sta active_lfn
- ldx current_device
- ldy #2
- jsr SETLFS
-
- lda filename_len
- ldx #<filename_spec
- ldy #>filename_spec
- jsr SETNAM
-
- jsr OPEN
- bcc type_channel_input
- jmp disk_open_error
-
- type_channel_input:
- ldx #LFN_DIR
- jsr CHKIN
- bcc type_loop
- jmp disk_input_error
-
- type_loop:
- jsr BASIN
- jsr CHROUT
- jsr READST
- and #$40
- beq type_loop
-
- lda #CR
- jsr CHROUT
- jsr close_active_file
- rts
-
- type_missing_name:
- lda #<msg_type_usage
- ldy #>msg_type_usage
- jsr print_string
- rts
-
- do_load_file:
- jsr find_argument_start
- bcc load_have_arg
- jmp load_missing_name
-
- load_have_arg:
-
- jsr build_read_filename
- bcc load_name_ready
- jmp load_missing_name
-
- load_name_ready:
- jsr reset_file_state
-
- lda #LFN_DIR
- sta active_lfn
- ldx current_device
- ldy #2
- jsr SETLFS
-
- lda filename_len
- ldx #<filename_spec
- ldy #>filename_spec
- jsr SETNAM
-
- jsr OPEN
- bcc load_channel_input
- jmp disk_open_error
-
- load_channel_input:
- ldx #LFN_DIR
- jsr CHKIN
- bcc load_prepare
- jmp disk_input_error
-
- load_prepare:
- lda #0
- sta file_buffer_len
- sta file_truncated
- ldx #0
-
- load_loop:
- jsr BASIN
- sta temp_char
- ldy file_buffer_len
- cpy #FILE_BUFFER_MAX
- bcs load_set_truncated
- lda temp_char
- sta FILE_BUFFER,y
- inc file_buffer_len
- jmp load_check_eof
-
- load_set_truncated:
- lda #1
- sta file_truncated
-
- load_check_eof:
- jsr READST
- and #$40
- beq load_loop
-
- lda file_buffer_len
- tay
- cpy #FILE_BUFFER_MAX
- bcs load_report
- lda #0
- sta FILE_BUFFER,y
-
- load_report:
- jsr close_active_file
- lda #<msg_loaded
- ldy #>msg_loaded
- jsr print_string
- lda file_buffer_len
- jsr print_decimal_byte
- lda #<msg_bytes
- ldy #>msg_bytes
- jsr print_string
- lda file_truncated
- beq load_done
- lda #<msg_truncated
- ldy #>msg_truncated
- jsr print_string
- load_done:
- rts
-
- load_missing_name:
- lda #<msg_load_usage
- ldy #>msg_load_usage
- jsr print_string
- rts
-
- do_save_file:
- jsr find_argument_start
- bcs save_missing_name
-
- lda file_buffer_len
- bne save_have_data
- lda #<msg_buffer_empty
- ldy #>msg_buffer_empty
- jsr print_string
- rts
-
- save_have_data:
- jsr build_write_filename
- bcs save_missing_name
- jsr reset_file_state
-
- lda #LFN_DIR
- sta active_lfn
- ldx current_device
- ldy #2
- jsr SETLFS
-
- lda filename_len
- ldx #<filename_spec
- ldy #>filename_spec
- jsr SETNAM
-
- jsr OPEN
- bcc save_channel_output
- jmp disk_open_error
-
- save_channel_output:
- ldx #LFN_DIR
- jsr CHKOUT
- bcc save_loop_prepare
- jmp disk_input_error
-
- save_loop_prepare:
- ldy #0
-
- save_loop:
- cpy file_buffer_len
- beq save_done
- lda FILE_BUFFER,y
- jsr CHROUT
- iny
- bne save_loop
-
- save_done:
- jsr close_active_file
- lda #<msg_saved
- ldy #>msg_saved
- jsr print_string
- lda file_buffer_len
- jsr print_decimal_byte
- lda #<msg_bytes
- ldy #>msg_bytes
- jsr print_string
- rts
-
- save_missing_name:
- lda #<msg_save_usage
- ldy #>msg_save_usage
- jsr print_string
- rts
-
- do_device:
- jsr find_argument_start
- bcc device_parse_arg
- jmp show_current_target
-
- device_parse_arg:
- jsr parse_decimal_argument
- bcs device_usage
- lda parsed_number
- cmp #8
- bcc device_usage
- cmp #16
- bcs device_usage
- sta current_device
- lda #<msg_device_set
- ldy #>msg_device_set
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- rts
-
- device_usage:
- lda #<msg_device_usage
- ldy #>msg_device_usage
- jsr print_string
- rts
-
- do_drive:
- jsr find_argument_start
- bcc drive_parse_arg
- jmp show_current_target
-
- drive_parse_arg:
- jsr parse_decimal_argument
- bcs drive_usage
- lda parsed_number
- cmp #2
- bcs drive_usage
- sta current_drive
- lda #<msg_drive_set
- ldy #>msg_drive_set
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- rts
-
- drive_usage:
- lda #<msg_drive_usage
- ldy #>msg_drive_usage
- jsr print_string
- rts
-
- do_hex:
- lda file_buffer_len
- bne hex_have_data
- lda #<msg_buffer_empty
- ldy #>msg_buffer_empty
- jsr print_string
- rts
-
- hex_have_data:
- lda #<msg_hex
- ldy #>msg_hex
- jsr print_string
- ldy #0
- ldx #0
-
- hex_loop:
- cpy file_buffer_len
- beq hex_done
- lda FILE_BUFFER,y
- jsr print_hex_byte
- lda #' '
- jsr CHROUT
- iny
- inx
- cpx #8
- bne hex_loop
- lda #CR
- jsr CHROUT
- ldx #0
- jmp hex_loop
-
- hex_done:
- lda #CR
- jsr CHROUT
- rts
-
- do_run:
- lda file_buffer_len
- bne run_have_code
- lda #<msg_buffer_empty
- ldy #>msg_buffer_empty
- jsr print_string
- rts
-
- run_have_code:
- lda #<msg_run
- ldy #>msg_run
- jsr print_string
- jsr FILE_BUFFER
- rts
-
- do_rename:
- jsr find_argument_start
- bcs rename_missing_args
- jsr find_second_argument
- bcs rename_missing_args
- jsr build_rename_command
- bcs rename_missing_args
-
- lda #<msg_rename
- ldy #>msg_rename
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_CMD
- sta active_lfn
- ldx current_device
- ldy #15
- jsr SETLFS
-
- lda scratch_len
- ldx #<scratch_command
- ldy #>scratch_command
- jsr SETNAM
-
- jsr OPEN
- bcc rename_file_done
- jmp disk_open_error
-
- rename_file_done:
- jsr close_active_file
- jmp do_status
-
- rename_missing_args:
- lda #<msg_rename_usage
- ldy #>msg_rename_usage
- jsr print_string
- rts
-
- do_copy:
- jsr find_argument_start
- bcs copy_missing_args
- jsr find_second_argument
- bcs copy_missing_args
- jsr build_copy_command
- bcs copy_missing_args
-
- lda #<msg_copy
- ldy #>msg_copy
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- jsr reset_file_state
-
- lda #LFN_CMD
- sta active_lfn
- ldx current_device
- ldy #15
- jsr SETLFS
-
- lda scratch_len
- ldx #<scratch_command
- ldy #>scratch_command
- jsr SETNAM
-
- jsr OPEN
- bcc copy_file_done
- jmp disk_open_error
-
- copy_file_done:
- jsr close_active_file
- jmp do_status
-
- copy_missing_args:
- lda #<msg_copy_usage
- ldy #>msg_copy_usage
- jsr print_string
- rts
-
- exit_to_basic:
- jsr restore_normal_memory
- rts
-
- request_exit:
- lda #1
- sta exit_requested
- rts
-
- close_active_file:
- jsr CLRCH
- lda active_lfn
- jsr CLOSE
- lda #0
- sta active_lfn
- rts
-
- reset_file_state:
- jsr CLRCH
- jsr CLALL
- lda #0
- sta active_lfn
- rts
-
- disk_open_error:
- sta last_error
- jsr reset_file_state
- lda #<msg_disk_open_error
- ldy #>msg_disk_open_error
- jsr print_string
- lda last_error
- jsr print_hex_byte
- lda #CR
- jsr CHROUT
- rts
-
- disk_input_error:
- sta last_error
- jsr reset_file_state
- lda #<msg_disk_input_error
- ldy #>msg_disk_input_error
- jsr print_string
- lda last_error
- jsr print_hex_byte
- lda #CR
- jsr CHROUT
- rts
-
- parse_command:
- lda input_buffer
- bne check_help
- jmp command_empty
-
- check_help:
-
- lda #<cmd_help
- ldy #>cmd_help
- jsr str_equals_input
- bcc check_mem
- jmp do_help
-
- check_mem:
-
- lda #<cmd_mem
- ldy #>cmd_mem
- jsr str_equals_input
- bcc check_inc
- jmp do_mem
-
- check_inc:
-
- lda #<cmd_inc
- ldy #>cmd_inc
- jsr str_equals_input
- bcc check_dump
- jmp do_inc
-
- check_dump:
-
- lda #<cmd_dump
- ldy #>cmd_dump
- jsr str_equals_input
- bcc check_zero
- jmp do_dump
-
- check_zero:
-
- lda #<cmd_zero
- ldy #>cmd_zero
- jsr str_equals_input
- bcc check_sign
- jmp do_zero
-
- check_sign:
-
- lda #<cmd_sign
- ldy #>cmd_sign
- jsr str_equals_input
- bcc check_cls
- jmp do_sign
-
- check_cls:
-
- lda #<cmd_cls
- ldy #>cmd_cls
- jsr str_equals_input
- bcc check_screen
- jmp do_cls
-
- check_screen:
-
- lda #<cmd_screen
- ldy #>cmd_screen
- jsr str_equals_input
- bcc check_about
- jmp do_screen
-
- check_about:
-
- lda #<cmd_about
- ldy #>cmd_about
- jsr str_equals_input
- bcc check_dir
- jmp do_about
-
- check_dir:
-
- lda #<cmd_dir
- ldy #>cmd_dir
- jsr str_matches_command
- bcc check_status
- jmp do_dir
-
- check_status:
-
- lda #<cmd_status
- ldy #>cmd_status
- jsr str_equals_input
- bcc check_init
- jmp do_status
-
- check_init:
-
- lda #<cmd_init
- ldy #>cmd_init
- jsr str_equals_input
- bcc check_echo
- jmp do_init
-
- check_echo:
-
- lda #<cmd_echo
- ldy #>cmd_echo
- jsr str_matches_command
- bcc check_touch
- jmp do_echo
-
- check_touch:
-
- lda #<cmd_touch
- ldy #>cmd_touch
- jsr str_matches_command
- bcc check_type
- jmp do_touch
-
- check_type:
-
- lda #<cmd_type
- ldy #>cmd_type
- jsr str_matches_command
- bcc check_load
- jmp do_type
-
- check_load:
-
- lda #<cmd_load
- ldy #>cmd_load
- jsr str_matches_command
- bcc check_save
- jmp do_load_file
-
- check_save:
-
- lda #<cmd_save
- ldy #>cmd_save
- jsr str_matches_command
- bcc check_device
- jmp do_save_file
-
- check_device:
-
- lda #<cmd_device
- ldy #>cmd_device
- jsr str_matches_command
- bcc check_dev
- jmp do_device
-
- check_dev:
-
- lda #<cmd_dev
- ldy #>cmd_dev
- jsr str_matches_command
- bcc check_drive
- jmp do_device
-
- check_drive:
-
- lda #<cmd_drive
- ldy #>cmd_drive
- jsr str_matches_command
- bcc check_del
- jmp do_drive
-
- check_del:
-
- lda #<cmd_del
- ldy #>cmd_del
- jsr str_matches_command
- bcc check_erase
- jmp do_delete
-
- check_erase:
-
- lda #<cmd_erase
- ldy #>cmd_erase
- jsr str_matches_command
- bcc check_hex
- jmp do_delete
-
- check_hex:
-
- lda #<cmd_hex
- ldy #>cmd_hex
- jsr str_equals_input
- bcc check_run
- jmp do_hex
-
- check_run:
-
- lda #<cmd_run
- ldy #>cmd_run
- jsr str_equals_input
- bcc check_rename
- jmp do_run
-
- check_rename:
-
- lda #<cmd_rename
- ldy #>cmd_rename
- jsr str_matches_command
- bcc check_copy
- jmp do_rename
-
- check_copy:
-
- lda #<cmd_copy
- ldy #>cmd_copy
- jsr str_matches_command
- bcc check_exit
- jmp do_copy
-
- check_exit:
-
- lda #<cmd_exit
- ldy #>cmd_exit
- jsr str_matches_command
- bcc command_unknown
- jmp request_exit
-
- command_unknown:
- lda #<msg_unknown
- ldy #>msg_unknown
- jsr print_string
- rts
-
- command_empty:
- rts
-
- ; ------------------------------------------------------------
- ; memory mode helpers
- ; ------------------------------------------------------------
-
- set_os_memory:
- lda CPU_PORT
- and #$F8
- ora #$06
- sta CPU_PORT
- rts
-
- restore_normal_memory:
- lda CPU_PORT
- and #$F8
- ora #$07
- sta CPU_PORT
- rts
-
- ; ------------------------------------------------------------
- ; write an initial signature into RAM hidden under BASIC ROM
- ; ------------------------------------------------------------
-
- init_workspace:
- lda #0
- sta WORKSPACE
- sta workspace_counter
- sta exit_requested
- sta dir_line_count
- sta quote_state
- sta line_had_name
- sta argument_index
- sta scratch_len
- sta filename_len
- sta parsed_number
- sta temp_digit
- sta temp_value
- sta current_drive
- sta file_buffer_len
- sta file_truncated
- sta pipe_found
- sta pipe_index
- sta argument2_index
- lda #DISK_DEV
- sta current_device
- jsr write_signature
- rts
-
- write_signature:
- ldx #0
-
- copy_signature:
- lda msg_signature,x
- sta WORKSPACE + 1,x
- beq workspace_done
- inx
- bne copy_signature
-
- workspace_done:
- rts
-
- find_argument_start:
- ldx #0
-
- arg_seek_end:
- lda input_buffer,x
- beq arg_missing
- cmp #' '
- beq arg_skip_spaces
- inx
- bne arg_seek_end
-
- arg_skip_spaces:
- lda input_buffer,x
- beq arg_missing
- cmp #' '
- bne arg_found
- inx
- bne arg_skip_spaces
-
- arg_found:
- stx argument_index
- clc
- rts
-
- arg_missing:
- sec
- rts
-
- find_second_argument:
- ldy argument_index
-
- sec_skip_first:
- lda input_buffer,y
- beq sec_arg_missing
- cmp #' '
- beq sec_find_start
- iny
- bne sec_skip_first
-
- sec_find_start:
- lda input_buffer,y
- beq sec_arg_missing
- cmp #' '
- bne sec_arg_found
- iny
- bne sec_find_start
-
- sec_arg_found:
- sty argument2_index
- clc
- rts
-
- sec_arg_missing:
- sec
- rts
-
- build_scratch_command:
- ldx #0
- lda #'S'
- sta scratch_command,x
- inx
- lda current_drive
- clc
- adc #'0'
- sta scratch_command,x
- inx
- lda #':'
- sta scratch_command,x
- inx
-
- ldy argument_index
-
- copy_delete_name:
- lda input_buffer,y
- beq scratch_done
- sta scratch_command,x
- inx
- iny
- cpx #31
- bcc copy_delete_name
- sec
- rts
-
- scratch_done:
- stx scratch_len
- lda #0
- sta scratch_command,x
- clc
- rts
-
- build_dir_spec:
- lda #'$'
- sta filename_spec
- lda current_drive
- clc
- adc #'0'
- sta filename_spec + 1
- lda #2
- sta filename_len
- lda #0
- sta filename_spec + 2
- rts
-
- build_read_filename:
- jsr build_drive_filename_prefix
- bcs filename_build_error
- lda #','
- jsr append_filename_char
- lda #'S'
- jsr append_filename_char
- lda #','
- jsr append_filename_char
- lda #'R'
- jsr append_filename_char
- bcs filename_build_error
- jmp finish_filename_spec
-
- build_write_filename:
- jsr build_drive_filename_prefix
- bcs filename_build_error
- lda #','
- jsr append_filename_char
- lda #'S'
- jsr append_filename_char
- lda #','
- jsr append_filename_char
- lda #'W'
- jsr append_filename_char
- bcs filename_build_error
- jmp finish_filename_spec
-
- build_drive_filename_prefix:
- ldx #0
- lda current_drive
- clc
- adc #'0'
- sta filename_spec,x
- inx
- lda #':'
- sta filename_spec,x
- inx
-
- ldy argument_index
-
- copy_filename_arg:
- lda input_buffer,y
- beq prefix_done
- sta filename_spec,x
- inx
- iny
- cpx #35
- bcc copy_filename_arg
- sec
- rts
-
- prefix_done:
- stx filename_len
- clc
- rts
-
- append_filename_char:
- ldx filename_len
- cpx #39
- bcs filename_build_error
- sta filename_spec,x
- inx
- stx filename_len
- clc
- rts
-
- finish_filename_spec:
- ldx filename_len
- lda #0
- sta filename_spec,x
- clc
- rts
-
- filename_build_error:
- sec
- rts
-
- ; builds R{d}:{newname}={oldname} in scratch_command
- ; arg1=old (argument_index), arg2=new (argument2_index)
- build_rename_command:
- ldx #0
- lda #'R'
- sta scratch_command,x
- inx
- lda current_drive
- clc
- adc #'0'
- sta scratch_command,x
- inx
- lda #':'
- sta scratch_command,x
- inx
-
- ldy argument2_index
- rename_copy_new_name:
- lda input_buffer,y
- beq rename_new_name_done
- cmp #' '
- beq rename_new_name_done
- sta scratch_command,x
- inx
- iny
- cpx #20
- bcc rename_copy_new_name
- sec
- rts
-
- rename_new_name_done:
- lda #'='
- sta scratch_command,x
- inx
-
- ldy argument_index
- rename_copy_old_name:
- lda input_buffer,y
- beq rename_cmd_done
- cmp #' '
- beq rename_cmd_done
- sta scratch_command,x
- inx
- iny
- cpx #31
- bcc rename_copy_old_name
- sec
- rts
-
- rename_cmd_done:
- stx scratch_len
- lda #0
- sta scratch_command,x
- clc
- rts
-
- ; builds C{d}:{dstname}={d}:{srcname} in scratch_command
- ; arg1=src (argument_index), arg2=dst (argument2_index)
- build_copy_command:
- ldx #0
- lda #'C'
- sta scratch_command,x
- inx
- lda current_drive
- clc
- adc #'0'
- sta scratch_command,x
- inx
- lda #':'
- sta scratch_command,x
- inx
-
- ldy argument2_index
- copy_dst_name:
- lda input_buffer,y
- beq copy_dst_done
- cmp #' '
- beq copy_dst_done
- sta scratch_command,x
- inx
- iny
- cpx #16
- bcc copy_dst_name
- sec
- rts
-
- copy_dst_done:
- lda #'='
- sta scratch_command,x
- inx
- lda current_drive
- clc
- adc #'0'
- sta scratch_command,x
- inx
- lda #':'
- sta scratch_command,x
- inx
-
- ldy argument_index
- copy_src_name:
- lda input_buffer,y
- beq copy_cmd_done
- cmp #' '
- beq copy_cmd_done
- sta scratch_command,x
- inx
- iny
- cpx #31
- bcc copy_src_name
- sec
- rts
-
- copy_cmd_done:
- stx scratch_len
- lda #0
- sta scratch_command,x
- clc
- rts
-
- parse_decimal_argument:
- ldy argument_index
- lda #0
- sta parsed_number
-
- parse_digit_loop:
- lda input_buffer,y
- beq parse_number_done
- cmp #'0'
- bcc parse_number_error
- cmp #'9' + 1
- bcs parse_number_error
- sec
- sbc #'0'
- sta temp_digit
-
- lda parsed_number
- asl
- sta temp_value
- asl
- asl
- clc
- adc temp_value
- clc
- adc temp_digit
- sta parsed_number
-
- iny
- bne parse_digit_loop
-
- parse_number_done:
- clc
- rts
-
- parse_number_error:
- sec
- rts
-
- copy_echo_to_buffer:
- lda #0
- sta pipe_found
- sta file_buffer_len
-
- ldy argument_index
- ldx #0
-
- echo_copy_loop:
- lda input_buffer,y
- beq echo_copy_done
- cmp #'>'
- beq echo_pipe_here
- cpx #FILE_BUFFER_MAX
- bcs echo_copy_done
- sta FILE_BUFFER,x
- inx
- iny
- bne echo_copy_loop
-
- echo_pipe_here:
- lda #1
- sta pipe_found
- sty pipe_index
-
- echo_copy_done:
- stx file_buffer_len
-
- trim_echo_spaces:
- cpx #0
- beq echo_copy_finish
- dex
- lda FILE_BUFFER,x
- cmp #' '
- bne restore_echo_len
- stx file_buffer_len
- jmp trim_echo_spaces
-
- restore_echo_len:
- inx
- stx file_buffer_len
-
- echo_copy_finish:
- ldy file_buffer_len
- lda #0
- sta FILE_BUFFER,y
- clc
- rts
-
- rewrite_input_after_pipe:
- ldy pipe_index
- lda input_buffer,y
- cmp #'>'
- beq pipe_skip_marker
- rts
-
- pipe_skip_marker:
- iny
-
- pipe_skip_spaces:
- lda input_buffer,y
- beq clear_input_after_pipe
- cmp #' '
- bne pipe_copy_command
- iny
- bne pipe_skip_spaces
-
- pipe_copy_command:
- ldx #0
-
- pipe_copy_loop:
- lda input_buffer,y
- beq pipe_rewrite_done
- sta input_buffer,x
- inx
- iny
- cpx #INPUT_MAX
- bcc pipe_copy_loop
-
- pipe_rewrite_done:
- lda #0
- sta input_buffer,x
- rts
-
- clear_input_after_pipe:
- lda #0
- sta input_buffer
- rts
-
- ; ------------------------------------------------------------
- ; utility routines
- ; ------------------------------------------------------------
-
- print_prompt:
- lda #<msg_prompt
- ldy #>msg_prompt
- jmp print_string
-
- show_current_target:
- lda #<msg_current_target
- ldy #>msg_current_target
- jsr print_string
- jsr print_current_target
- lda #CR
- jsr CHROUT
- rts
-
- print_current_target:
- lda current_device
- jsr print_decimal_byte
- lda #'/'
- jsr CHROUT
- lda current_drive
- clc
- adc #'0'
- jsr CHROUT
- rts
-
- print_banner:
- lda #CLR_HOME
- jsr CHROUT
-
- lda #<msg_banner
- ldy #>msg_banner
- jmp print_string
-
- print_string:
- sta PTR1_LO
- sty PTR1_HI
-
- print_loop:
- ldy #0
- lda (PTR1_LO),y
- beq print_done
- jsr CHROUT
- inc PTR1_LO
- bne print_loop
- inc PTR1_HI
- jmp print_loop
-
- print_done:
- rts
-
- read_line:
- lda #0
- sta input_len
-
- read_loop:
- jsr STOPKEY
- bne read_getin
- jmp request_exit
-
- read_getin:
-
- jsr GETIN
- beq read_loop
-
- cmp #CR
- beq read_done
-
- cmp #$14
- beq read_delete
-
- ldx input_len
- cpx #INPUT_MAX
- bcs read_loop
-
- jsr normalize_petscii_letter
- sta input_buffer,x
- inc input_len
- jsr CHROUT
- jmp read_loop
-
- read_delete:
- lda input_len
- beq read_loop
- dec input_len
- lda #$14
- jsr CHROUT
- jmp read_loop
-
- read_done:
- ldx input_len
- lda #0
- sta input_buffer,x
- lda #CR
- jsr CHROUT
- rts
-
- str_equals_input:
- sta PTR1_LO
- sty PTR1_HI
- lda #0
- sta compare_index
-
- compare_loop:
- ldx compare_index
- lda input_buffer,x
- sta temp_char
-
- ldy #0
- lda (PTR1_LO),y
- beq compare_end
-
- cmp temp_char
- bne compare_no
-
- inc PTR1_LO
- bne compare_next
- inc PTR1_HI
-
- compare_next:
- inc compare_index
- jmp compare_loop
-
- compare_end:
- ldx compare_index
- lda input_buffer,x
- beq compare_yes
-
- compare_no:
- clc
- rts
-
- compare_yes:
- sec
- rts
-
- str_matches_command:
- sta PTR1_LO
- sty PTR1_HI
- lda #0
- sta compare_index
-
- match_loop:
- ldx compare_index
- lda input_buffer,x
- sta temp_char
-
- ldy #0
- lda (PTR1_LO),y
- beq match_end
- cmp temp_char
- bne match_no
-
- inc PTR1_LO
- bne match_next
- inc PTR1_HI
-
- match_next:
- inc compare_index
- jmp match_loop
-
- match_end:
- ldx compare_index
- lda input_buffer,x
- beq match_yes
- cmp #' '
- beq match_yes
-
- match_no:
- clc
- rts
-
- match_yes:
- sec
- rts
-
- print_hex_byte:
- pha
- lsr
- lsr
- lsr
- lsr
- jsr print_hex_nibble
- pla
- and #$0F
- jsr print_hex_nibble
- rts
-
- print_hex_nibble:
- cmp #10
- bcc print_hex_digit
- clc
- adc #'A' - 10
- jsr CHROUT
- rts
-
- print_hex_digit:
- clc
- adc #'0'
- jsr CHROUT
- rts
-
- print_decimal_byte:
- ldx #'0'
-
- hundreds_loop:
- cmp #100
- bcc tens_setup
- sec
- sbc #100
- inx
- bne hundreds_loop
-
- tens_setup:
- stx dec_hundreds
- ldx #'0'
-
- tens_loop:
- cmp #10
- bcc decimal_ready
- sec
- sbc #10
- inx
- bne tens_loop
-
- decimal_ready:
- stx dec_tens
- clc
- adc #'0'
- sta dec_ones
-
- lda dec_hundreds
- cmp #'0'
- beq maybe_skip_hundreds
- jsr CHROUT
-
- lda dec_tens
- jsr CHROUT
- lda dec_ones
- jsr CHROUT
- rts
-
- maybe_skip_hundreds:
- lda dec_tens
- cmp #'0'
- beq print_last_digit
- jsr CHROUT
-
- lda dec_ones
- jsr CHROUT
- rts
-
- print_last_digit:
- lda dec_ones
- jsr CHROUT
- rts
-
- normalize_petscii_letter:
- cmp #'a'
- bcc maybe_shifted_letter
- cmp #'z' + 1
- bcs maybe_shifted_letter
- sec
- sbc #$20
- rts
-
- maybe_shifted_letter:
- cmp #$C1
- bcc normalize_done
- cmp #$DB
- bcs normalize_done
- and #$7F
-
- normalize_done:
- rts
-
- .segment "RODATA"
-
- msg_banner:
- .byte "KERNAL OS SHELL", CR
- .byte "BASIC OFF KERNAL ON I/O ON", CR
- .byte "BOOT $0801 WORK $A000", CR
- .byte "HELP FOR CMDS", CR, CR
- .byte 0
-
- msg_prompt:
- .byte "OS> ", 0
-
- msg_unknown:
- .byte "UNKNOWN. HELP", CR, 0
-
- msg_help:
- .byte CR
- .byte "HELP MEM INC DUMP ZERO SIGN", CR
- .byte "SCREEN DIR STATUS INIT CLS", CR
- .byte "ECHO TOUCH TYPE LOAD SAVE", CR
- .byte "HEX RUN RENAME COPY", CR
- .byte "DEVICE DEV DRIVE DEL ERASE", CR
- .byte "ABOUT EXIT", CR
- .byte CR
- .byte 0
-
- msg_mode:
- .byte "CPU PORT $0001 = $", 0
-
- msg_workspace:
- .byte CR, "WORK BYTE $A000 = $", 0
-
- msg_layout:
- .byte CR
- .byte "$0001 LOW BITS %110", CR
- .byte "$080D START $A000-$BFFF RAM", CR
- .byte CR
- .byte 0
-
- msg_written:
- .byte "WROTE $", 0
-
- msg_dump:
- .byte "A000:", ' ', 0
-
- msg_zeroed:
- .byte "ZEROED $A000-$A00F", CR, 0
-
- msg_signed:
- .byte "REWROTE SIGNATURE AT $A001", CR, 0
-
- msg_about:
- .byte CR
- .byte "BASIC LINE 10 SYS 2061 BOOTS THIS.", CR
- .byte "KERNAL STAYS MAPPED IN.", CR
- .byte "SHELL CODE STARTS AT $080D.", CR
- .byte "USE $A000-$BFFF AS WORK RAM.", CR
- .byte CR
- .byte 0
-
- msg_screen:
- .byte "SCREEN SIZE: ", 0
-
- msg_status:
- .byte CR, "STATUS OF TARGET ", 0
-
- msg_init:
- .byte CR, "INITIALIZING TARGET ", 0
-
- msg_delete:
- .byte CR, "SCRATCHING FILE ON TARGET ", 0
-
- msg_delete_usage:
- .byte "USAGE: DEL filename OR ERASE filename", CR, 0
-
- msg_touch:
- .byte CR, "CREATING EMPTY FILE ON TARGET ", 0
-
- msg_touch_usage:
- .byte "USAGE: TOUCH filename", CR, 0
-
- msg_echo_usage:
- .byte "USAGE: ECHO text OR ECHO text > SAVE file", CR, 0
-
- msg_type_usage:
- .byte "USAGE: TYPE filename", CR, 0
-
- msg_load_usage:
- .byte "USAGE: LOAD filename", CR, 0
-
- msg_save_usage:
- .byte "USAGE: SAVE filename", CR, 0
-
- msg_loaded:
- .byte "LOADED ", 0
-
- msg_saved:
- .byte "SAVED ", 0
-
- msg_bytes:
- .byte " BYTES", CR, 0
-
- msg_truncated:
- .byte " (TRUNCATED TO BUFFER SIZE)", CR, 0
-
- msg_buffer_empty:
- .byte "BUFFER EMPTY. USE LOAD FIRST.", CR, 0
-
- msg_current_target:
- msg_device_set:
- .byte "TARGET ", 0
-
- msg_device_usage:
- .byte "USAGE: DEVICE 8-15 OR DEV 8-15", CR, 0
-
- msg_drive_set:
- .byte "TARGET ", 0
-
- msg_drive_usage:
- .byte "USAGE: DRIVE 0 OR DRIVE 1", CR, 0
-
- msg_disk_open_error:
- .byte "DISK OPEN ERROR $", 0
-
- msg_disk_input_error:
- .byte "DISK INPUT ERROR $", 0
-
- msg_signature:
- .byte "OSWORK", 0
-
- fname_init:
- .byte "I0:"
-
- cmd_help:
- .byte "HELP", 0
-
- cmd_mem:
- .byte "MEM", 0
-
- cmd_inc:
- .byte "INC", 0
-
- cmd_dump:
- .byte "DUMP", 0
-
- cmd_zero:
- .byte "ZERO", 0
-
- cmd_sign:
- .byte "SIGN", 0
-
- cmd_cls:
- .byte "CLS", 0
-
- cmd_screen:
- .byte "SCREEN", 0
-
- cmd_about:
- .byte "ABOUT", 0
-
- cmd_dir:
- .byte "DIR", 0
-
- cmd_status:
- .byte "STATUS", 0
-
- cmd_init:
- .byte "INIT", 0
-
- cmd_echo:
- .byte "ECHO", 0
-
- cmd_touch:
- .byte "TOUCH", 0
-
- cmd_type:
- .byte "TYPE", 0
-
- cmd_load:
- .byte "LOAD", 0
-
- cmd_save:
- .byte "SAVE", 0
-
- cmd_device:
- .byte "DEVICE", 0
-
- cmd_dev:
- .byte "DEV", 0
-
- cmd_drive:
- .byte "DRIVE", 0
-
- cmd_del:
- .byte "DEL", 0
-
- cmd_erase:
- .byte "ERASE", 0
-
- cmd_exit:
- .byte "EXIT", 0
-
- cmd_hex:
- .byte "HEX", 0
-
- cmd_run:
- .byte "RUN", 0
-
- cmd_rename:
- .byte "RENAME", 0
-
- cmd_copy:
- .byte "COPY", 0
-
- msg_hex:
- .byte "BUF HEX:", CR, 0
-
- msg_run:
- .byte "RUNNING $A100", CR, 0
-
- msg_rename:
- .byte CR, "RENAMING FILE ON TARGET ", 0
-
- msg_rename_usage:
- .byte "USAGE: RENAME oldname newname", CR, 0
-
- msg_copy:
- .byte CR, "COPYING FILE ON TARGET ", 0
-
- msg_copy_usage:
- .byte "USAGE: COPY srcname dstname", CR, 0
-
- .segment "BSS"
-
- workspace_counter:
- .res 1
-
- exit_requested:
- .res 1
-
- active_lfn:
- .res 1
-
- last_error:
- .res 1
-
- dir_link_lo:
- .res 1
-
- dir_link_hi:
- .res 1
-
- dir_line_count:
- .res 1
-
- quote_state:
- .res 1
-
- line_had_name:
- .res 1
-
- argument_index:
- .res 1
-
- argument2_index:
- .res 1
-
- scratch_len:
- .res 1
-
- scratch_command:
- .res 32
-
- filename_len:
- .res 1
-
- filename_spec:
- .res 40
-
- parsed_number:
- .res 1
-
- temp_digit:
- .res 1
-
- temp_value:
- .res 1
-
- current_device:
- .res 1
-
- current_drive:
- .res 1
-
- file_buffer_len:
- .res 1
-
- file_truncated:
- .res 1
-
- pipe_found:
- .res 1
-
- pipe_index:
- .res 1
-
- input_buffer:
- .res INPUT_MAX + 1
-
- input_len:
- .res 1
-
- compare_index:
- .res 1
-
- temp_char:
- .res 1
-
- dec_hundreds:
- .res 1
-
- dec_tens:
- .res 1
-
- dec_ones:
- .res 1
|