0001 ;;; 0002 ;;; MCFS2 kernel version 2.0.1 0003 ;;; By: Daniel Tufvesson 2017 0004 ;;; 0005 0006 c000 monitor_return: equ $c000 ; return to monitor 0007 0008 7fe5 console_status: equ $7fe5 ; console status vector 0009 7fe8 console_output: equ $7fe8 ; console output vector 0010 7feb console_input: equ $7feB ; console input vector 0011 0012 0002 page_register: equ $0002 ; I/O page select register 0013 0014 ;;; 0015 ;;; RTC-72421 registers 0016 ;;; 0017 9fc0 rtc_base: equ $9fc0 0018 9fc0 rtc_reg_s1: equ rtc_base+$0 ; 1-second digit 0019 9fc1 rtc_reg_s10: equ rtc_base+$1 ; 10-seconds digit 0020 9fc2 rtc_reg_mi1: equ rtc_base+$2 ; 1-minute digit 0021 9fc3 rtc_reg_mi10: equ rtc_base+$3 ; 10-minutes digit 0022 9fc4 rtc_reg_h1: equ rtc_base+$4 ; 1-hour digit 0023 9fc5 rtc_reg_h10: equ rtc_base+$5 ; 10-hours digit 0024 9fc6 rtc_reg_d1: equ rtc_base+$6 ; 1-day digit 0025 9fc7 rtc_reg_d10: equ rtc_base+$7 ; 10-days digit 0026 9fc8 rtc_reg_mo1: equ rtc_base+$8 ; 1-month digit 0027 9fc9 rtc_reg_mo10: equ rtc_base+$9 ; 10-months digit 0028 9fca rtc_reg_y1: equ rtc_base+$a ; 1-year digit 0029 9fcb rtc_reg_y10: equ rtc_base+$b ; 10-years digit 0030 9fcc rtc_reg_w: equ rtc_base+$c ; Day of week 0031 9fcd rtc_reg_cd: equ rtc_base+$d ; Control reg D 0032 9fce rtc_reg_ce: equ rtc_base+$e ; Control reg E 0033 9fcf rtc_reg_cf: equ rtc_base+$f ; Control reg F 0034 0035 ;;; 0036 ;;; CF registers 0037 ;;; 0038 9fd0 cf_base: equ $9fd0 0039 9fd0 cf_reg_0: equ cf_base+0 ; data port 0040 9fd1 cf_reg_1: equ cf_base+1 ; read: error code, write: feature 0041 9fd2 cf_reg_2: equ cf_base+2 ; number of sectors to transfer 0042 9fd3 cf_reg_3: equ cf_base+3 ; sector address LBA 0 [0:7] 0043 9fd4 cf_reg_4: equ cf_base+4 ; sector address LBA 1 [8:15] 0044 9fd5 cf_reg_5: equ cf_base+5 ; sector address LBA 2 [16:23] 0045 9fd6 cf_reg_6: equ cf_base+6 ; sector address LBA 3 [24:27 (LSB of reg)] 0046 9fd7 cf_reg_7: equ cf_base+7 ; read: status, write: command 0047 0048 ;;; 0049 ;;; CF commands 0050 ;;; 0051 0004 cf_cmd_reset: equ $04 0052 *cf_cmd_id: equ $ec 0053 0020 cf_cmd_read: equ $20 0054 0030 cf_cmd_write: equ $30 0055 0056 ;;; 0057 ;;; Program begin here 0058 ;;; 0059 d000 org $d000 0060 d000 7e d0 eb jmp cold_start 0061 d003 7e d1 ca jmp warm_start 0062 d006 7e d3 4e jmp ext_call 0063 0064 ;;; 0065 ;;; Texts 0066 ;;; 0067 txt_init: 0068 d009 4d 43 46 53 20 32 fcc "MCFS 2.0.1" 2e 30 2e 31 0069 d013 0d 0a 00 fcb $0d,$0a,$00 0070 txt_prompt: 0071 d016 20 23 20 fcc " # " 0072 d019 00 fcb $00 0073 txt_term_bs: 0074 d01a 08 20 08 00 fcb $08,$20,$08,$00 0075 txt_error: 0076 d01e 45 72 72 6f 72 3a fcc "Error: " 20 0077 d025 00 fcb $00 0078 txt_err_not_found: 0079 d026 4e 6f 74 20 66 6f fcc "Not found" 75 6e 64 0080 d02f 00 fcb $00 0081 txt_err_exist: 0082 d030 41 6c 72 65 61 64 fcc "Already exist" 79 20 65 78 69 73 74 0083 d03d 00 fcb $00 0084 txt_err_no_space: 0085 d03e 4e 6f 20 73 70 61 fcc "No space left" 63 65 20 6c 65 66 74 0086 d04b 00 fcb $00 0087 txt_err_not_empty: 0088 d04c 4e 6f 74 20 65 6d fcc "Not empty" 70 74 79 0089 d055 00 fcb $00 0090 txt_err_argument: 0091 d056 4d 69 73 73 69 6e fcc "Missing or malformed argument" 67 20 6f 72 20 6d 61 6c 66 6f 72 6d 65 64 20 61 72 67 75 6d 65 6e 74 0092 d073 00 fcb $00 0093 txt_err_denied: 0094 d074 41 63 63 65 73 73 fcc "Access denied" 20 64 65 6e 69 65 64 0095 d081 00 fcb $00 0096 txt_err_not_exec: 0097 d082 4e 6f 74 20 65 78 fcc "Not executable" 65 63 75 74 61 62 6c 65 0098 d090 00 fcb $00 0099 txt_saving: 0100 d091 53 61 76 69 6e 67 fcc "Saving " 20 0101 d098 00 fcb $00 0102 txt_loading: 0103 d099 4c 6f 61 64 69 6e fcc "Loading " 67 20 0104 d0a1 00 fcb $00 0105 txt_time_not_set: 0106 d0a2 53 79 73 74 65 6d fcc "System time is not set" 20 74 69 6d 65 20 69 73 20 6e 6f 74 20 73 65 74 0107 d0b8 0d 0a 00 fcb $0d,$0a,$00 0108 txt_help: 0109 d0bb 43 6f 6d 6d 61 6e fcc "Commands:" 64 73 3a 0110 d0c4 0d 0a 00 fcb $0d,$0a,$00 0111 txt_help_settime: 0112 d0c7 46 6f 72 6d 61 74 fcc "Format YYYY MM DD HH MM SS" 20 59 59 59 59 20 4d 4d 20 44 44 20 48 48 20 4d 4d 20 53 53 0113 d0e1 0d 0a 00 fcb $0d,$0a,$00 0114 0115 ;;; 0116 ;;; Name of system dir 0117 ;;; 0118 txt_sys_dir: 0119 d0e4 73 79 73 74 65 6d fcc "system" 0120 d0ea 00 fcb $00 0121 0122 ;;; 0123 ;;; Program begin here 0124 ;;; 0125 cold_start: 0126 d0eb bd d7 41 jsr print_crlf 0127 d0ee 86 f0 ldaa #$f0 0128 d0f0 97 02 staa page_register 0129 ;;; Clear variable area 0130 d0f2 ce bc 00 ldx #beg_of_vars 0131 var_clear_loop: 0132 d0f5 6f 00 clr ,x 0133 d0f7 08 inx 0134 d0f8 8c bc ea cpx #end_of_vars 0135 d0fb 23 f8 bls var_clear_loop 0136 ;;; Init CF card 0137 d0fd ce d0 09 ldx #txt_init 0138 d100 bd d7 36 jsr print_string 0139 d103 bd e1 ce jsr cf_init 0140 d106 bd e1 f3 jsr cf_check_error 0141 d109 27 03 beq *+5 0142 d10b 7e d1 16 jmp start_error 0143 ;;; Goto root directry 0144 d10e bd e0 6e jsr open_volume 0145 d111 26 03 bne start_error 0146 d113 7e d1 e4 jmp prompt 0147 start_error: 0148 * ldaa #'! 0149 * jsr console_output 0150 d116 b7 bc e6 staa temp 0151 d119 ce d0 1e ldx #txt_error 0152 d11c bd d7 36 jsr print_string 0153 d11f ce bc e6 ldx #temp 0154 d122 bd d7 61 jsr print_2hex 0155 d125 bd d7 41 jsr print_crlf 0156 d128 7e c0 00 jmp monitor_return 0157 0158 ;;; 0159 ;;; Variable checksum routine 0160 ;;; 0161 var_checksum_calc: 0162 d12b 86 47 ldaa #$47 ; random non-zero value 0163 d12d bb bc 00 adda media_addr_3 0164 d130 bb bc 01 adda media_addr_2 0165 d133 bb bc 04 adda volume_beg 0166 d136 bb bc 05 adda volume_beg+1 0167 d139 bb bc 06 adda volume_end 0168 d13c bb bc 07 adda volume_end+1 0169 d13f bb bc 08 adda alloc_beg 0170 d142 bb bc 09 adda alloc_beg+1 0171 d145 bb bc 0a adda alloc_end 0172 d148 bb bc 0b adda alloc_end+1 0173 d14b bb bc 0c adda root_dir_beg 0174 d14e bb bc 0d adda root_dir_beg+1 0175 d151 bb bc 0e adda root_dir_end 0176 d154 bb bc 0f adda root_dir_end+1 0177 d157 bb bc 10 adda wrk_dir_beg 0178 d15a bb bc 11 adda wrk_dir_beg+1 0179 d15d bb bc 12 adda wrk_dir_end 0180 d160 bb bc 13 adda wrk_dir_end+1 0181 d163 39 rts 0182 0183 ;;; 0184 ;;; Print error code in A and return to prompt 0185 ;;; 0186 error_general: 0187 d164 b7 bc e6 staa temp 0188 d167 ce d0 1e ldx #txt_error 0189 d16a bd d7 36 jsr print_string 0190 d16d ce bc e6 ldx #temp 0191 d170 bd d7 61 jsr print_2hex 0192 d173 bd d7 41 jsr print_crlf 0193 d176 7e d1 e4 jmp prompt 0194 0195 ;;; 0196 ;;; Print pretty error messages and return to prompt 0197 ;;; 0198 error_not_found: 0199 d179 16 tab 0200 d17a ce d0 26 ldx #txt_err_not_found 0201 d17d 20 24 bra error_print 0202 error_exist: 0203 d17f 16 tab 0204 d180 ce d0 30 ldx #txt_err_exist 0205 d183 20 1e bra error_print 0206 error_argument: 0207 d185 16 tab 0208 d186 ce d0 56 ldx #txt_err_argument 0209 d189 20 18 bra error_print 0210 error_no_space: 0211 d18b 16 tab 0212 d18c ce d0 3e ldx #txt_err_no_space 0213 d18f 20 12 bra error_print 0214 error_not_empty: 0215 d191 16 tab 0216 d192 ce d0 4c ldx #txt_err_not_empty 0217 d195 20 0c bra error_print 0218 error_denied: 0219 d197 16 tab 0220 d198 ce d0 74 ldx #txt_err_denied 0221 d19b 20 06 bra error_print 0222 error_not_exec: 0223 d19d 16 tab 0224 d19e ce d0 82 ldx #txt_err_not_exec 0225 d1a1 20 00 bra error_print 0226 error_print: 0227 d1a3 3c pshx 0228 d1a4 ce d0 1e ldx #txt_error 0229 d1a7 bd d7 36 jsr print_string 0230 d1aa 38 pulx 0231 d1ab bd d7 36 jsr print_string 0232 d1ae bd d7 4b jsr print_space 0233 d1b1 86 28 ldaa #'( 0234 d1b3 bd 7f e8 jsr console_output 0235 d1b6 f7 bc e6 stab temp 0236 d1b9 ce bc e6 ldx #temp 0237 d1bc bd d7 61 jsr print_2hex 0238 d1bf 86 29 ldaa #') 0239 d1c1 bd 7f e8 jsr console_output 0240 d1c4 bd d7 41 jsr print_crlf 0241 d1c7 7e d1 e4 jmp prompt 0242 0243 ;;; 0244 ;;; Return from user program 0245 ;;; 0246 warm_start: 0247 d1ca 86 f0 ldaa #$f0 0248 d1cc 97 02 staa page_register 0249 d1ce bd d1 2b jsr var_checksum_calc 0250 d1d1 b1 bc eb cmpa var_checksum 0251 d1d4 27 03 beq *+5 0252 d1d6 7e d0 eb jmp cold_start 0253 d1d9 bd e1 ce jsr cf_init 0254 d1dc bd e1 f3 jsr cf_check_error 0255 d1df 27 03 beq *+5 0256 d1e1 7e d0 eb jmp cold_start 0257 0258 ;;; 0259 ;;; Read prompt 0260 ;;; 0261 prompt: 0262 d1e4 bd e3 33 jsr update_ram_time 0263 d1e7 ce bc 14 ldx #wrk_path 0264 d1ea bd d7 36 jsr print_string 0265 d1ed ce d0 16 ldx #txt_prompt 0266 d1f0 bd d7 36 jsr print_string 0267 d1f3 ce bc a0 ldx #line_buffer 0268 d1f6 6f 00 clr ,x 0269 prompt_loop: 0270 d1f8 bd 7f eb jsr console_input 0271 d1fb 81 08 cmpa #$08 ; is it back space? 0272 d1fd 27 19 beq prompt_bs 0273 d1ff 81 0d cmpa #$0d ; is it carriage return? 0274 d201 27 27 beq prompt_end 0275 d203 81 1f cmpa #$1f ; ignore control characters 0276 d205 23 f1 bls prompt_loop 0277 d207 81 7f cmpa #$7f ; ignore control characters 0278 d209 22 ed bhi prompt_loop 0279 d20b 8c bc df cpx #line_end 0280 d20e 27 e8 beq prompt_loop 0281 d210 bd 7f e8 jsr console_output 0282 d213 a7 00 staa ,x 0283 d215 08 inx 0284 d216 20 e0 bra prompt_loop 0285 prompt_bs: 0286 d218 8c bc a0 cpx #line_buffer 0287 d21b 27 db beq prompt_loop 0288 d21d 09 dex 0289 d21e 6f 00 clr ,x 0290 d220 3c pshx 0291 d221 ce d0 1a ldx #txt_term_bs 0292 d224 bd d7 36 jsr print_string 0293 d227 38 pulx 0294 d228 20 ce bra prompt_loop 0295 prompt_end: 0296 ;;; User has completed input 0297 d22a bd d7 41 jsr print_crlf 0298 d22d 6f 00 clr ,x 0299 d22f 8c bc a0 cpx #line_buffer 0300 d232 27 b0 beq prompt 0301 d234 fe bc 10 ldx wrk_dir_beg ; set work dir as current dir for commands 0302 d237 ff bc 94 stx cur_dir_beg 0303 d23a fe bc 12 ldx wrk_dir_end 0304 d23d ff bc 96 stx cur_dir_end 0305 d240 7e d2 d1 jmp command_lookup 0306 0307 ;;; 0308 ;;; Command table 0309 ;;; 0310 command_table: 0311 d243 d2 62 fdb cmd0 0312 d245 d2 67 fdb cmd1 0313 d247 d2 6d fdb cmd2 0314 d249 d2 72 fdb cmd3 0315 d24b d2 7a fdb cmd4 0316 d24d d2 81 fdb cmd5 0317 d24f d2 88 fdb cmd6 0318 d251 d2 8e fdb cmd7 0319 d253 d2 97 fdb cmd8 0320 d255 d2 a0 fdb cmd9 0321 d257 d2 a7 fdb cmd10 0322 d259 d2 af fdb cmd11 0323 d25b d2 b6 fdb cmd12 0324 d25d d2 c0 fdb cmd13 0325 d25f d2 ca fdb cmd14 0326 d261 00 fcb 0 0327 cmd0: 0328 d262 6c 73 fcc "ls" 0329 d264 00 fcb 0 0330 d265 d7 d8 fdb command_dir 0331 cmd1: 0332 d267 64 69 72 fcc "dir" 0333 d26a 00 fcb 0 0334 d26b d7 d8 fdb command_dir 0335 cmd2: 0336 d26d 63 64 fcc "cd" 0337 d26f 00 fcb 0 0338 d270 d8 6b fdb command_cd 0339 cmd3: 0340 d272 6d 6b 64 69 72 fcc "mkdir" 0341 d277 00 fcb 0 0342 d278 d8 ff fdb command_mkdir 0343 cmd4: 0344 d27a 73 61 76 65 fcc "save" 0345 d27e 00 fcb 0 0346 d27f d9 b2 fdb command_save 0347 cmd5: 0348 d281 6c 6f 61 64 fcc "load" 0349 d285 00 fcb 0 0350 d286 da d1 fdb command_load 0351 cmd6: 0352 d288 72 75 6e fcc "run" 0353 d28b 00 fcb 0 0354 d28c db 76 fdb command_run 0355 cmd7: 0356 d28e 64 65 6c 65 74 65 fcc "delete" 0357 d294 00 fcb 0 0358 d295 db 9f fdb command_delete 0359 cmd8: 0360 d297 72 65 6e 61 6d 65 fcc "rename" 0361 d29d 00 fcb 0 0362 d29e dc 0d fdb command_rename 0363 cmd9: 0364 d2a0 61 74 74 72 fcc "attr" 0365 d2a4 00 fcb 0 0366 d2a5 dc 96 fdb command_attr 0367 cmd10: 0368 d2a7 74 6f 75 63 68 fcc "touch" 0369 d2ac 00 fcb 0 0370 d2ad dd 06 fdb command_touch 0371 cmd11: 0372 d2af 74 69 6d 65 fcc "time" 0373 d2b3 00 fcb 0 0374 d2b4 dd 4c fdb command_time 0375 cmd12: 0376 d2b6 73 65 74 74 69 6d fcc "settime" 65 0377 d2bd 00 fcb 0 0378 d2be dd a3 fdb command_settime 0379 cmd13: 0380 d2c0 6d 6f 6e 69 74 6f fcc "monitor" 72 0381 d2c7 00 fcb 0 0382 d2c8 de a1 fdb command_monitor 0383 cmd14: 0384 d2ca 68 65 6c 70 fcc "help" 0385 d2ce 00 fcb 0 0386 d2cf de aa fdb command_help 0387 0388 ;;; 0389 ;;; Command lookup 0390 ;;; 0391 command_lookup: 0392 d2d1 ce d2 43 ldx #command_table 0393 d2d4 ff bc e7 stx xtemp 0394 command_loop: 0395 d2d7 ce bc a0 ldx #line_buffer 0396 d2da ff bc e0 stx line_pointer 0397 d2dd fe bc e7 ldx xtemp 0398 d2e0 6d 00 tst ,x 0399 d2e2 26 03 bne *+5 0400 d2e4 7e d3 08 jmp command_lookup_dir ; no built in command found - check system dir 0401 d2e7 ee 00 ldx ,x 0402 d2e9 bd d7 1e jsr string_compare 0403 d2ec 27 0a beq command_found 0404 d2ee fe bc e7 ldx xtemp 0405 d2f1 08 inx 0406 d2f2 08 inx 0407 d2f3 ff bc e7 stx xtemp 0408 d2f6 20 df bra command_loop 0409 command_found: 0410 d2f8 3c pshx 0411 d2f9 ce bc a0 ldx #line_buffer 0412 d2fc ff bc e0 stx line_pointer 0413 d2ff 38 pulx 0414 d300 08 inx 0415 d301 ee 00 ldx ,x 0416 d303 6e 00 jmp ,x 0417 d305 7e d1 e4 jmp prompt 0418 0419 ;;; 0420 ;;; Command look for executable file 0421 ;;; 0422 command_lookup_dir: 0423 ;;; Check for file in 'system' dir 0424 d308 fe bc 0c ldx root_dir_beg 0425 d30b ff bc 94 stx cur_dir_beg 0426 d30e fe bc 0e ldx root_dir_end 0427 d311 ff bc 96 stx cur_dir_end 0428 d314 ce d0 e4 ldx #txt_sys_dir 0429 d317 ff bc e0 stx line_pointer 0430 d31a bd df f7 jsr find_file_entry 0431 d31d 27 02 beq *+4 0432 d31f 20 2a bra command_lookup_dir_not 0433 ;;; System directory found 0434 d321 a6 00 ldaa ,x 0435 d323 84 c1 anda #$C1 0436 d325 81 c1 cmpa #$C1 ; check entry is a directory and readable 0437 d327 27 02 beq *+4 0438 d329 20 20 bra command_lookup_dir_not 0439 ;;; Enter directory 0440 d32b ec 01 ldd 1,x 0441 d32d fd bc 94 std cur_dir_beg 0442 d330 ec 03 ldd 3,x 0443 d332 fd bc 96 std cur_dir_end 0444 ;;; Check for command file in system dir 0445 d335 ce bc a0 ldx #line_buffer 0446 d338 ff bc e0 stx line_pointer 0447 d33b bd df f7 jsr find_file_entry ; look for file 0448 d33e 27 02 beq *+4 0449 d340 20 09 bra command_lookup_dir_not 0450 d342 cc bc a0 ldd #line_buffer 0451 d345 fd bc e0 std line_pointer 0452 d348 7e e1 21 jmp execute_file 0453 command_lookup_dir_not: 0454 d34b 7e d1 79 jmp error_not_found 0455 0456 ;;; 0457 ;;; External call - main entry 0458 ;;; IN: pointer to file control block in X 0459 ;;; OUT: updated file control block 0460 ;;; 0461 ext_call: 0462 d34e 86 f0 ldaa #$f0 0463 d350 97 02 staa page_register 0464 d352 86 ff ldaa #$ff ; prepare general error code 0465 d354 a7 01 staa 1,x ; save error code in FCB 0466 d356 bd e1 ce jsr cf_init 0467 d359 bd e1 f3 jsr cf_check_error 0468 d35c 27 01 beq *+3 0469 d35e 39 rts 0470 d35f bd d1 2b jsr var_checksum_calc ; check checksum 0471 d362 b1 bc eb cmpa var_checksum 0472 d365 27 01 beq *+3 0473 d367 39 rts 0474 ext_call_do: 0475 d368 ff bc e4 stx ext_fcb ; save pointer to control block 0476 d36b fc bc 10 ldd wrk_dir_beg ; set work dir as current dir for commands 0477 d36e fd bc 94 std cur_dir_beg 0478 d371 fc bc 12 ldd wrk_dir_end 0479 d374 fd bc 96 std cur_dir_end 0480 d377 a6 00 ldaa ,x ; get command 0481 d379 81 01 cmpa #$01 ; command $01 - check file 0482 d37b 26 03 bne *+5 0483 d37d 7e d3 a8 jmp ext_check_file 0484 d380 81 07 cmpa #$07 ; command $07 - rename file 0485 d382 26 03 bne *+5 0486 d384 7e d4 03 jmp ext_rename 0487 d387 81 08 cmpa #$08 ; command $08 - delete file 0488 d389 26 03 bne *+5 0489 d38b 7e d4 69 jmp ext_delete 0490 d38e 81 10 cmpa #$10 ; command $10 - load file 0491 d390 26 03 bne *+5 0492 d392 7e d4 c8 jmp ext_load_file 0493 d395 81 11 cmpa #$11 ; command $11 - load file sector 0494 d397 26 03 bne *+5 0495 d399 7e d5 42 jmp ext_load_file_sec 0496 d39c 81 20 cmpa #$20 ; command $20 - save file 0497 d39e 26 03 bne *+5 0498 d3a0 7e d5 ac jmp ext_save_file 0499 d3a3 86 fe ldaa #$fe ; error code - illegal command 0500 d3a5 a7 01 staa 1,x ; save error code in FCB 0501 d3a7 39 rts 0502 0503 ;;; 0504 ;;; External call - check file 0505 ;;; IN: ptr to FCB in X and ext_fcb 0506 ;;; 0507 ext_check_file: 0508 d3a8 ec 02 ldd 2,x ; set file name 0509 d3aa fd bc e0 std line_pointer 0510 ;;; Handle special case of checking current directory "." 0511 d3ad ee 02 ldx 2,x ; load file name pointer 0512 d3af ee 00 ldx ,x ; load first two characters of name 0513 d3b1 8c 2e 00 cpx #$2E00 ; is it "."? 0514 d3b4 26 15 bne ext_check_file_find 0515 d3b6 fe bc e4 ldx ext_fcb 0516 d3b9 86 c1 ldaa #$C1 0517 d3bb a7 04 staa 4,x 0518 d3bd fc bc 12 ldd wrk_dir_end 0519 d3c0 b3 bc 10 subd wrk_dir_beg 0520 d3c3 c3 00 01 addd #1 0521 d3c6 ed 05 std 5,x ; store sector count 0522 d3c8 6f 01 clr 1,x ; error code ok 0523 d3ca 39 rts 0524 ;;; Look for file 0525 ext_check_file_find: 0526 d3cb bd df f7 jsr find_file_entry 0527 d3ce 26 2d bne ext_check_file_end 0528 ;;; File entry found 0529 d3d0 ff bc e7 stx xtemp ; save file entry pointer 0530 d3d3 a6 00 ldaa ,x ; read flags 0531 d3d5 fe bc e4 ldx ext_fcb 0532 d3d8 a7 04 staa 4,x 0533 d3da fe bc e7 ldx xtemp 0534 d3dd ec 03 ldd 3,x ; calc number of sectors in file 0535 d3df a3 01 subd 1,x 0536 d3e1 c3 00 01 addd #1 0537 d3e4 fe bc e4 ldx ext_fcb 0538 d3e7 ed 05 std 5,x ; save number of sectors 0539 ;;; Copy remaining part on file entry 0540 ;;; file size and time stamp - bytes 6 to 14 0541 d3e9 c6 05 ldab #5 0542 ext_check_file_loop: 0543 d3eb fe bc e7 ldx xtemp 0544 d3ee 3a abx 0545 d3ef a6 00 ldaa ,x 0546 d3f1 fe bc e4 ldx ext_fcb 0547 d3f4 3a abx 0548 d3f5 a7 02 staa 2,x 0549 d3f7 5c incb 0550 d3f8 c1 0f cmpb #15 0551 d3fa 23 ef bls ext_check_file_loop 0552 d3fc 4f clra ; error code ok 0553 ext_check_file_end: 0554 d3fd fe bc e4 ldx ext_fcb ; save error code to fcb 0555 d400 a7 01 staa 1,x 0556 d402 39 rts 0557 0558 ;;; 0559 ;;; External call - rename 0560 ;;; IN: ptr to FCB in X and ext_fcb 0561 ;;; 0562 ext_rename: 0563 ;;; Check if new file name valid 0564 d403 ee 04 ldx 4,x 0565 d405 ff bc e0 stx line_pointer 0566 d408 bd d7 70 jsr validate_filename_arg 0567 d40b 25 03 bcs *+5 0568 d40d 7e d4 65 jmp ext_ren_err 0569 ;;; Check if new entry name exists 0570 d410 bd df f7 jsr find_file_entry 0571 d413 26 03 bne *+5 0572 d415 7e d4 65 jmp ext_ren_err 0573 ;;; Check if old entry name exists 0574 d418 fe bc e4 ldx ext_fcb 0575 d41b ee 02 ldx 2,x 0576 d41d ff bc e0 stx line_pointer 0577 d420 bd df f7 jsr find_file_entry 0578 d423 27 03 beq *+5 0579 d425 7e d4 65 jmp ext_ren_err 0580 ;;; Check if file is writable 0581 d428 a6 00 ldaa ,x 0582 d42a 85 02 bita #$02 0583 d42c 26 03 bne *+5 0584 d42e 7e d4 65 jmp ext_ren_err 0585 ;;; Update directory entry name 0586 d431 3c pshx 0587 d432 fe bc e4 ldx ext_fcb 0588 d435 ee 04 ldx 4,x ; get new name pointer 0589 d437 ff bc e0 stx line_pointer 0590 d43a 38 pulx 0591 d43b c6 10 ldab #16 ; go to start of entry file name 0592 d43d 3a abx 0593 d43e c6 1f ldab #31 0594 ext_rename_name: ; copy name char by char 0595 d440 bd d6 7b jsr line_pull_char 0596 d443 4d tsta 0597 d444 27 0a beq ext_rename_name_e 0598 d446 81 20 cmpa #$20 0599 d448 27 06 beq ext_rename_name_e 0600 d44a a7 00 staa ,x 0601 d44c 08 inx 0602 d44d 5a decb 0603 d44e 26 f0 bne ext_rename_name 0604 ext_rename_name_e: 0605 d450 4f clra 0606 d451 a7 00 staa ,x ; terminate name sting 0607 ;;; Write back directory sector 0608 d453 ce bc ec ldx #sector_buffer 0609 d456 bd e1 ba jsr write_sector 0610 d459 27 03 beq *+5 0611 d45b 7e d4 5f jmp ext_ren_end 0612 ext_ren_done: 0613 d45e 4f clra ; error code OK 0614 ext_ren_end: 0615 d45f fe bc e4 ldx ext_fcb ; save error code to fcb 0616 d462 a7 01 staa 1,x 0617 d464 39 rts 0618 ext_ren_err: 0619 d465 86 f1 ldaa #$F1 0620 d467 20 f6 bra ext_ren_end 0621 0622 ;;; 0623 ;;; External call - delete 0624 ;;; IN: ptr to FCB in X and ext_fcb 0625 ;;; 0626 ext_delete: 0627 ;;; Move line_pointer to file name (first argument) 0628 d469 ec 02 ldd 2,x ; set file name 0629 d46b fd bc e0 std line_pointer 0630 d46e fd bc e2 std arg_pointer 0631 ;;; Check if file exists 0632 d471 bd df f7 jsr find_file_entry ; lookup directory entry 0633 d474 27 03 beq *+5 0634 d476 7e d4 c2 jmp ext_del_end 0635 d479 a6 00 ldaa ,x ; get entry flags 0636 d47b 85 02 bita #$02 ; check if writable 0637 d47d 26 03 bne *+5 0638 d47f 7e d4 c2 jmp ext_del_end 0639 d482 85 40 bita #$40 0640 d484 27 16 beq ext_del_do ; entry is a file - perform delete 0641 d486 bd e0 3b jsr check_dir_empty ; entry is a directory - check if empty 0642 d489 27 03 beq *+5 0643 d48b 7e d4 c2 jmp ext_del_end 0644 d48e fe bc e2 ldx arg_pointer ; retore line_pointer (point to file name) 0645 d491 ff bc e0 stx line_pointer 0646 d494 bd df f7 jsr find_file_entry ; lookup directory entry again 0647 d497 27 03 beq *+5 0648 d499 7e d4 c2 jmp ext_del_end: 0649 ext_del_do: 0650 d49c ec 01 ldd 1,x ; file start sector 0651 d49e fd bc 98 std cur_file_beg 0652 d4a1 ec 03 ldd 3,x ; file end sector 0653 d4a3 fd bc 9a std cur_file_end 0654 ;;; Clear directory entry for file 0655 d4a6 86 40 ldaa #64 0656 ext_del_clear_entry: 0657 d4a8 6f 00 clr ,x 0658 d4aa 08 inx 0659 d4ab 4a deca 0660 d4ac 26 fa bne ext_del_clear_entry 0661 ;;; write back directory sector 0662 d4ae ce bc ec ldx #sector_buffer 0663 d4b1 bd e1 ba jsr write_sector 0664 d4b4 27 03 beq *+5 0665 d4b6 7e d4 c2 jmp ext_del_end 0666 ;;; Free allocated sectors 0667 d4b9 bd df 81 jsr dealloc 0668 d4bc 27 03 beq *+5 0669 d4be 7e d4 c2 jmp ext_del_end 0670 ext_del_done: 0671 d4c1 4f clra ; error code OK 0672 ext_del_end: 0673 d4c2 fe bc e4 ldx ext_fcb ; save error code to fcb 0674 d4c5 a7 01 staa 1,x 0675 d4c7 39 rts 0676 0677 ;;; 0678 ;;; External call - load file 0679 ;;; IN: ptr to FCB in X and ext_fcb 0680 ;;; 0681 ext_load_file: 0682 d4c8 ec 02 ldd 2,x ; set file name 0683 d4ca fd bc e0 std line_pointer 0684 d4cd ec 04 ldd 4,x ; read file start address 0685 d4cf fd bc 9c std cur_file_saddr 0686 ;;; Handle special case of loading current directory "." 0687 d4d2 ee 02 ldx 2,x ; load file name pointer 0688 d4d4 ee 00 ldx ,x ; load first two characters of name 0689 d4d6 8c 2e 00 cpx #$2E00 ; is it "."? 0690 d4d9 26 17 bne ext_load_file_find 0691 ;;; Load current directory (special case) 0692 d4db fc bc 10 ldd wrk_dir_beg 0693 d4de fd bc 98 std cur_file_beg 0694 d4e1 fc bc 12 ldd wrk_dir_end 0695 d4e4 fd bc 9a std cur_file_end 0696 d4e7 fc bc 9c ldd cur_file_saddr 0697 d4ea c3 10 00 addd #$1000 0698 d4ed fd bc 9e std cur_file_eaddr 0699 d4f0 20 27 bra ext_load_read_file_data 0700 ;;; Look for file 0701 ext_load_file_find: 0702 d4f2 bd df f7 jsr find_file_entry 0703 d4f5 26 45 bne ext_load_file_end 0704 ;;; File entry found 0705 d4f7 ff bc e7 stx xtemp ; save file entry pointer 0706 d4fa a6 00 ldaa ,x ; read flags 0707 d4fc 85 01 bita #$01 ; verify that file is readable 0708 d4fe 26 04 bne ext_load_file_do 0709 d500 86 f4 ldaa #$F4 ; error code - access denied 0710 d502 20 38 bra ext_load_file_end 0711 ;;; Load file in to memory 0712 ext_load_file_do: 0713 d504 ec 01 ldd 1,x ; get file start sector 0714 d506 fd bc 98 std cur_file_beg 0715 d509 ec 03 ldd 3,x ; get file end sector 0716 d50b fd bc 9a std cur_file_end 0717 ;;; Calculate file memory range 0718 d50e ec 07 ldd 7,x 0719 d510 83 00 01 subd #1 0720 d513 f3 bc 9c addd cur_file_saddr 0721 d516 fd bc 9e std cur_file_eaddr 0722 ;;; Read file data sectors 0723 ext_load_read_file_data: 0724 d519 fe bc 98 ldx cur_file_beg ; set first sector to read 0725 d51c ff bc 02 stx media_addr_1 0726 d51f 5f clrb ; no byte skip when reading buffer 0727 ext_load_file_loop: 0728 d520 ce bc ec ldx #sector_buffer 0729 d523 bd e1 a6 jsr read_sector 0730 d526 27 02 beq *+4 0731 d528 20 12 bra ext_load_file_end 0732 d52a bd e0 f9 jsr sector_buffer_out ; copy data from buffer 0733 d52d fe bc 02 ldx media_addr_1 0734 d530 bc bc 9a cpx cur_file_end ; all data sectors written? 0735 d533 27 06 beq ext_load_file_done 0736 d535 08 inx 0737 d536 ff bc 02 stx media_addr_1 0738 d539 20 e5 bra ext_load_file_loop 0739 ext_load_file_done: 0740 d53b 4f clra 0741 ext_load_file_end: 0742 d53c fe bc e4 ldx ext_fcb ; save error code to fcb 0743 d53f a7 01 staa 1,x 0744 d541 39 rts 0745 0746 ;;; 0747 ;;; External call - load file sector 0748 ;;; IN: ptr to FCB in X and ext_fcb 0749 ;;; 0750 ext_load_file_sec: 0751 d542 ec 02 ldd 2,x ; set file name 0752 d544 fd bc e0 std line_pointer 0753 d547 ec 04 ldd 4,x ; read file start address 0754 d549 fd bc 9c std cur_file_saddr 0755 d54c ec 06 ldd 6,x ; read file sector number (0-n) 0756 d54e fd bc 98 std cur_file_beg 0757 ;;; Handle special case of loading current directory "." 0758 d551 ee 02 ldx 2,x ; load file name pointer 0759 d553 ee 00 ldx ,x ; load first two characters of name 0760 d555 8c 2e 00 cpx #$2E00 ; is it "."? 0761 d558 26 15 bne ext_load_file_sec_find 0762 ;;; Load current directory (special case) 0763 d55a fc bc 98 ldd cur_file_beg 0764 d55d f3 bc 10 addd wrk_dir_beg 0765 d560 fd bc 98 std cur_file_beg 0766 d563 fe bc 98 ldx cur_file_beg ; check requested sector is within file range 0767 d566 bc bc 12 cpx wrk_dir_end 0768 d569 23 2f bls ext_load_file_sec_do 0769 d56b 86 f5 ldaa #$F5 ; error code - value out of range 0770 d56d 20 37 bra ext_load_file_sec_end 0771 ;;; Look for file 0772 ext_load_file_sec_find: 0773 d56f bd df f7 jsr find_file_entry 0774 d572 26 32 bne ext_load_file_sec_end 0775 ;;; File entry found 0776 d574 ff bc e7 stx xtemp ; save file entry pointer 0777 d577 a6 00 ldaa ,x ; read flags 0778 d579 85 01 bita #$01 ; verify that file is readable 0779 d57b 26 04 bne ext_load_file_sec_pre 0780 d57d 86 f4 ldaa #$F4 ; error code - access denied 0781 d57f 20 25 bra ext_load_file_sec_end 0782 ;;; Prepare to load file sector in to memory 0783 ext_load_file_sec_pre: 0784 d581 fc bc 98 ldd cur_file_beg ; this contais the requested file sector number (0-n) 0785 d584 e3 01 addd 1,x 0786 d586 fd bc 98 std cur_file_beg ; this contais the requested media sector number 0787 d589 ec 03 ldd 3,x ; read file end sector 0788 d58b fd bc 9a std cur_file_end 0789 d58e fe bc 98 ldx cur_file_beg ; check requested sector is within file range 0790 d591 bc bc 9a cpx cur_file_end 0791 d594 23 04 bls ext_load_file_sec_do 0792 d596 86 f5 ldaa #$F5 ; error code - value out of range 0793 d598 20 0c bra ext_load_file_sec_end 0794 ;;; Load requested sector into memory 0795 ext_load_file_sec_do: 0796 d59a fc bc 98 ldd cur_file_beg ; set media address 0797 d59d fd bc 02 std media_addr_1 0798 d5a0 fe bc 9c ldx cur_file_saddr ; set destination address 0799 d5a3 bd e1 a6 jsr read_sector ; red sector into memory 0800 ext_load_file_sec_end: 0801 d5a6 fe bc e4 ldx ext_fcb ; save error code to fcb 0802 d5a9 a7 01 staa 1,x 0803 d5ab 39 rts 0804 0805 ;;; 0806 ;;; External call - save file 0807 ;;; IN: ptr to FCB in X and ext_fcb 0808 ;;; 0809 ext_save_file: 0810 d5ac ec 02 ldd 2,x ; set file name 0811 d5ae fd bc e0 std line_pointer 0812 d5b1 fd bc e2 std arg_pointer 0813 d5b4 ec 04 ldd 4,x ; read data start address 0814 d5b6 fd bc 9c std cur_file_saddr 0815 d5b9 ec 06 ldd 6,x ; read data end address 0816 d5bb fd bc 9e std cur_file_eaddr 0817 ;;; Check if valid file name 0818 d5be fe bc e0 ldx line_pointer 0819 d5c1 bd d7 70 jsr validate_filename_arg 0820 d5c4 25 03 bcs *+5 0821 d5c6 7e d6 75 jmp ext_save_file_end 0822 ;;; Check if file already exists 0823 d5c9 bd df f7 jsr find_file_entry 0824 d5cc 26 05 bne ext_save_file_nexist 0825 d5ce 86 f4 ldaa #$F4 0826 d5d0 7e d6 75 jmp ext_save_file_end 0827 ext_save_file_nexist: 0828 ;;; Determine number of sectors needed for the file 0829 d5d3 86 01 ldaa #$01 0830 d5d5 b7 bc e6 staa temp ; sector counter (start at one sector) 0831 d5d8 fc bc 9e ldd cur_file_eaddr ; calculate file size 0832 d5db b3 bc 9c subd cur_file_saddr 0833 ext_save_loop1: 0834 d5de 81 01 cmpa #$01 0835 d5e0 23 08 bls ext_save_loop1_done ; calculation done? 0836 d5e2 83 02 00 subd #512 0837 d5e5 7c bc e6 inc temp 0838 d5e8 20 f4 bra ext_save_loop1 0839 ext_save_loop1_done: 0840 ;;; Allocate sectors for the file 0841 d5ea b6 bc e6 ldaa temp ; number of sectors to allocate 0842 d5ed bd de de jsr alloc 0843 d5f0 27 03 beq *+5 ; enough free space left on volume for file? 0844 d5f2 7e d6 75 jmp ext_save_file_end 0845 ;;; Setup new directory entry 0846 d5f5 bd df c9 jsr find_free_entry ; find the empty entry in current directory again 0847 d5f8 27 03 beq *+5 0848 d5fa 7e d6 75 jmp ext_save_file_end 0849 d5fd 3c pshx 0850 d5fe fe bc e4 ldx ext_fcb 0851 d601 a6 08 ldaa 8,x ; get file attributes from fcb 0852 d603 84 07 anda #$07 0853 d605 8a a0 oraa #$A0 ; set entry to status "in use file" 0854 d607 38 pulx 0855 d608 a7 00 staa ,x 0856 d60a fc bc 98 ldd cur_file_beg ; set file start sector 0857 d60d ed 01 std 1,x 0858 d60f fc bc 9a ldd cur_file_end ; set file end sector 0859 d612 ed 03 std 3,x 0860 d614 fc bc 9e ldd cur_file_eaddr ; set file size 0861 d617 b3 bc 9c subd cur_file_saddr 0862 d61a c3 00 01 addd #1 0863 d61d 24 02 bcc ext_save_size_lsb 0864 d61f 6c 06 inc 6,x 0865 ext_save_size_lsb: 0866 d621 ed 07 std 7,x 0867 d623 fc bc e2 ldd arg_pointer ; set file name 0868 d626 fd bc e0 std line_pointer 0869 d629 c6 09 ldab #9 ; go to start of time stamp 0870 d62b 3a abx 0871 d62c bd e2 53 jsr rtc_get_time ; write time stamp 0872 d62f c6 07 ldab #7 ; go to start of entry file name 0873 d631 3a abx 0874 d632 c6 1f ldab #31 0875 ext_save_name: ; copy name into file entry 0876 d634 bd d6 7b jsr line_pull_char 0877 d637 4d tsta 0878 d638 27 0a beq ext_save_name_done 0879 d63a 81 20 cmpa #$20 0880 d63c 27 06 beq ext_save_name_done 0881 d63e a7 00 staa ,x 0882 d640 08 inx 0883 d641 5a decb 0884 d642 26 f0 bne ext_save_name 0885 ext_save_name_done: 0886 d644 4f clra 0887 d645 a7 00 staa ,x ; terminate name sting 0888 ;;; Write back directory sector 0889 d647 ce bc ec ldx #sector_buffer 0890 d64a bd e1 ba jsr write_sector 0891 d64d 27 03 beq *+5 0892 d64f 7e d6 75 jmp ext_save_file_end 0893 ;;; Write file data to data sectors 0894 d652 fe bc 98 ldx cur_file_beg ; set first sector to write 0895 d655 ff bc 02 stx media_addr_1 0896 ext_save_data_loop: 0897 d658 bd e0 d1 jsr sector_buffer_in ; copy data to buffer 0898 d65b ce bc ec ldx #sector_buffer 0899 d65e bd e1 ba jsr write_sector 0900 d661 27 03 beq *+5 0901 d663 7e d6 75 jmp ext_save_file_end 0902 d666 fe bc 02 ldx media_addr_1 0903 d669 bc bc 9a cpx cur_file_end ; all data sectors written? 0904 d66c 27 06 beq ext_save_complete 0905 d66e 08 inx 0906 d66f ff bc 02 stx media_addr_1 0907 d672 20 e4 bra ext_save_data_loop 0908 ext_save_complete: 0909 d674 4f clra 0910 ext_save_file_end: 0911 d675 fe bc e4 ldx ext_fcb ; save error code to fcb 0912 d678 a7 01 staa 1,x 0913 d67a 39 rts 0914 0915 ;;; 0916 ;;; Pull one char from line buffer and update pointer 0917 ;;; 0918 line_pull_char: 0919 d67b 3c pshx 0920 d67c fe bc e0 ldx line_pointer 0921 d67f a6 00 ldaa ,x 0922 d681 27 06 beq line_pull_char_e ; end of buffer 0923 d683 08 inx 0924 d684 ff bc e0 stx line_pointer 0925 d687 38 pulx 0926 d688 39 rts 0927 line_pull_char_e: 0928 d689 4f clra 0929 d68a 38 pulx 0930 d68b 39 rts 0931 0932 ;;; 0933 ;;; Pull 2 hex chars from line buffer and store in temp 0934 ;;; OUT: Carry set on OK, value in temp 0935 ;;; 0936 line_pull_2hex: 0937 d68c bd d6 7b jsr line_pull_char 0938 d68f bd d7 04 jsr char_to_hex 0939 d692 24 18 bcc line_pull_2hex_fail 0940 d694 48 asla 0941 d695 48 asla 0942 d696 48 asla 0943 d697 48 asla 0944 d698 b7 bc e6 staa temp 0945 d69b bd d6 7b jsr line_pull_char 0946 d69e bd d7 04 jsr char_to_hex 0947 d6a1 24 09 bcc line_pull_2hex_fail 0948 d6a3 ba bc e6 oraa temp 0949 d6a6 b7 bc e6 staa temp 0950 d6a9 4f clra 0951 d6aa 0d sec 0952 d6ab 39 rts 0953 line_pull_2hex_fail: 0954 d6ac 0c clc 0955 d6ad 39 rts 0956 0957 ;;; 0958 ;;; Pull 4 hex chars from line buffer and store in xtemp 0959 ;;; OUT: Carry set on OK, value in xtemp 0960 ;;; 0961 line_pull_4hex: 0962 d6ae bd d6 7b jsr line_pull_char 0963 d6b1 bd d7 04 jsr char_to_hex 0964 d6b4 24 35 bcc line_pull_4hex_fail 0965 d6b6 48 asla 0966 d6b7 48 asla 0967 d6b8 48 asla 0968 d6b9 48 asla 0969 d6ba b7 bc e7 staa xtemp 0970 d6bd bd d6 7b jsr line_pull_char 0971 d6c0 bd d7 04 jsr char_to_hex 0972 d6c3 24 26 bcc line_pull_4hex_fail 0973 d6c5 ba bc e7 oraa xtemp 0974 d6c8 b7 bc e7 staa xtemp 0975 d6cb bd d6 7b jsr line_pull_char 0976 d6ce bd d7 04 jsr char_to_hex 0977 d6d1 24 18 bcc line_pull_4hex_fail 0978 d6d3 48 asla 0979 d6d4 48 asla 0980 d6d5 48 asla 0981 d6d6 48 asla 0982 d6d7 b7 bc e8 staa xtemp+1 0983 d6da bd d6 7b jsr line_pull_char 0984 d6dd bd d7 04 jsr char_to_hex 0985 d6e0 24 09 bcc line_pull_4hex_fail 0986 d6e2 ba bc e8 oraa xtemp+1 0987 d6e5 b7 bc e8 staa xtemp+1 0988 d6e8 4f clra 0989 d6e9 0d sec 0990 d6ea 39 rts 0991 line_pull_4hex_fail: 0992 d6eb 0c clc 0993 d6ec 39 rts 0994 0995 ;;; 0996 ;;; Find next word in string pointed at by X 0997 ;;; 0998 str_skp_next: 0999 d6ed a6 00 ldaa ,x 1000 d6ef 27 12 beq str_skp_next_e 1001 d6f1 81 20 cmpa #$20 1002 d6f3 27 03 beq str_skp_next_1 1003 d6f5 08 inx 1004 d6f6 20 f5 bra str_skp_next 1005 str_skp_next_1: 1006 d6f8 a6 00 ldaa ,x 1007 d6fa 27 07 beq str_skp_next_e 1008 d6fc 81 20 cmpa #$20 1009 d6fe 26 03 bne str_skp_next_e 1010 d700 08 inx 1011 d701 20 f5 bra str_skp_next_1 1012 str_skp_next_e: 1013 d703 39 rts 1014 1015 ;;; 1016 ;;; Convert ASCII char to hex 1017 ;;; IN: Chanracter in A 1018 ;;; OUT: Value in A. Carry set on OK 1019 ;;; 1020 char_to_hex: 1021 d704 27 16 beq char_to_hex_fail ; end of string 1022 d706 80 30 suba #$30 1023 d708 2b 12 bmi char_to_hex_fail ; not hex 1024 d70a 81 09 cmpa #$09 1025 d70c 2f 0c ble char_to_hex_ok ; $9 and below 1026 d70e 84 df anda #$df ; to upper case 1027 d710 81 11 cmpa #$11 1028 d712 2b 08 bmi char_to_hex_fail ; not hex 1029 d714 81 16 cmpa #$16 1030 d716 2e 04 bgt char_to_hex_fail ; not hex 1031 d718 80 07 suba #7 1032 char_to_hex_ok: 1033 d71a 0d sec 1034 d71b 39 rts 1035 char_to_hex_fail: 1036 d71c 0c clc 1037 d71d 39 rts 1038 1039 ;;; 1040 ;;; String compare 1041 ;;; IN: line_pointer, X 1042 ;;; OUT: Z set on match 1043 ;;; 1044 string_compare: 1045 d71e bd d6 7b jsr line_pull_char 1046 d721 e6 00 ldab ,x 1047 d723 11 cba 1048 d724 26 06 bne string_cmp_not 1049 d726 4d tsta 1050 d727 27 03 beq string_cmp_not 1051 d729 08 inx 1052 d72a 20 f2 bra string_compare 1053 string_cmp_not: 1054 d72c 1b aba 1055 d72d 27 05 beq string_cmp_match 1056 d72f 81 20 cmpa #$20 1057 d731 27 01 beq string_cmp_match 1058 d733 39 rts 1059 string_cmp_match: 1060 d734 4f clra 1061 d735 39 rts 1062 1063 ;;; 1064 ;;; Print null terminated string 1065 ;;; 1066 print_string: 1067 d736 a6 00 ldaa ,x 1068 d738 27 06 beq print_string_e 1069 d73a bd 7f e8 jsr console_output 1070 d73d 08 inx 1071 d73e 20 f6 bra print_string 1072 print_string_e: 1073 d740 39 rts 1074 1075 ;;; 1076 ;;; Print CR LF 1077 ;;; 1078 print_crlf: 1079 d741 86 0d ldaa #$0d 1080 d743 bd 7f e8 jsr console_output 1081 d746 86 0a ldaa #$0a 1082 d748 7e 7f e8 jmp console_output 1083 1084 ;;; 1085 ;;; Print space 1086 ;;; 1087 print_space: 1088 d74b 86 20 ldaa #$20 1089 d74d 7e 7f e8 jmp console_output 1090 1091 ;;; 1092 ;;; Print HEX characters 1093 ;;; 1094 print_hex_l: 1095 d750 44 lsra ; out hex left BCD 1096 d751 44 lsra 1097 d752 44 lsra 1098 d753 44 lsra 1099 print_hex_r: 1100 d754 84 0f anda #$f ; out hex right BCD 1101 d756 8b 30 adda #$30 1102 d758 81 39 cmpa #$39 1103 d75a 23 02 bls *+4 1104 d75c 8b 07 adda #$7 1105 d75e 7e 7f e8 jmp console_output 1106 print_2hex: 1107 d761 a6 00 ldaa ,x 1108 d763 bd d7 50 jsr print_hex_l ; out left hex char 1109 d766 a6 00 ldaa ,x 1110 d768 08 inx 1111 d769 7e d7 54 jmp print_hex_r ; out right hex char 1112 print_4hex: 1113 d76c 8d f3 bsr print_2hex ; print 4 hex chars 1114 d76e 20 f1 bra print_2hex ; print 2 hex chars 1115 1116 ;;; 1117 ;;; Validate file name argument pointed at by X 1118 ;;; OUT: Carry set on valid 1119 ;;; 1120 validate_filename_arg: 1121 d770 6d 00 tst ,x 1122 d772 27 2d beq invalid_filename_arg ; no zero length name 1123 validate_filename_arg_l: 1124 d774 a6 00 ldaa ,x 1125 d776 27 27 beq validate_filename_arg_e 1126 d778 81 20 cmpa #$20 1127 d77a 27 23 beq validate_filename_arg_e 1128 d77c 81 1f cmpa #$1F 1129 d77e 23 21 bls invalid_filename_arg 1130 d780 81 7e cmpa #$7E 1131 d782 22 1d bhi invalid_filename_arg 1132 d784 81 22 cmpa #$22 ; '"' 1133 d786 27 19 beq invalid_filename_arg 1134 d788 81 27 cmpa #$27 ; ''' 1135 d78a 27 15 beq invalid_filename_arg 1136 d78c 81 2a cmpa #$2A ; '*' 1137 d78e 27 11 beq invalid_filename_arg 1138 d790 81 2f cmpa #$2F ; '/' 1139 d792 27 0d beq invalid_filename_arg 1140 d794 81 5c cmpa #$5C ; '\' 1141 d796 27 09 beq invalid_filename_arg 1142 d798 81 60 cmpa #$60 ; '`' 1143 d79a 27 05 beq invalid_filename_arg 1144 d79c 08 inx 1145 d79d 20 d5 bra validate_filename_arg_l 1146 validate_filename_arg_e: 1147 d79f 0d sec 1148 d7a0 39 rts 1149 invalid_filename_arg: 1150 d7a1 0c clc 1151 d7a2 39 rts 1152 1153 ;;; 1154 ;;; Print file attributes 1155 ;;; 1156 print_file_attr: 1157 d7a3 86 2d ldaa #'- 1158 d7a5 e6 00 ldab ,x 1159 d7a7 c5 40 bitb #$40 1160 d7a9 27 02 beq *+4 1161 d7ab 86 64 ldaa #'d 1162 d7ad bd 7f e8 jsr console_output 1163 d7b0 86 2d ldaa #'- 1164 d7b2 e6 00 ldab ,x 1165 d7b4 c5 01 bitb #$01 1166 d7b6 27 02 beq *+4 1167 d7b8 86 72 ldaa #'r 1168 d7ba bd 7f e8 jsr console_output 1169 d7bd 86 2d ldaa #'- 1170 d7bf e6 00 ldab ,x 1171 d7c1 c5 02 bitb #$02 1172 d7c3 27 02 beq *+4 1173 d7c5 86 77 ldaa #'w 1174 d7c7 bd 7f e8 jsr console_output 1175 d7ca 86 2d ldaa #'- 1176 d7cc e6 00 ldab ,x 1177 d7ce c5 04 bitb #$04 1178 d7d0 27 02 beq *+4 1179 d7d2 86 78 ldaa #'x 1180 d7d4 bd 7f e8 jsr console_output 1181 d7d7 39 rts 1182 1183 ;;; 1184 ;;; Command 'dir' 1185 ;;; 1186 command_dir: 1187 d7d8 fe bc 94 ldx cur_dir_beg 1188 cmd_dir_loop1: 1189 d7db bc bc 96 cpx cur_dir_end ; compare with end of current directory 1190 d7de 22 2b bhi cmd_dir_done ; end if we have looped through entire directory 1191 d7e0 ff bc 02 stx media_addr_1 1192 ;;; Read directory sector 1193 d7e3 ce bc ec ldx #sector_buffer 1194 d7e6 bd e1 a6 jsr read_sector ; read next sector of directory 1195 d7e9 27 03 beq *+5 1196 d7eb 7e d1 64 jmp error_general 1197 ;;; Print contents of directory sector 1198 d7ee ce bc ec ldx #sector_buffer 1199 cmd_dir_loop2: 1200 d7f1 a6 00 ldaa ,x 1201 d7f3 27 08 beq cmd_dir_nxt_entry ; is the directory entry empty? 1202 d7f5 ff bc e7 stx xtemp ; save current position in sector_buffer 1203 d7f8 8d 14 bsr cmd_dir_print ; print directory entry + crlf 1204 ;;; Go to next directory entry 1205 d7fa fe bc e7 ldx xtemp ; restore sector_buffer pointer 1206 cmd_dir_nxt_entry: ; goto next directory entry 1207 d7fd c6 40 ldab #64 ; within current sector 1208 d7ff 3a abx 1209 d800 8c be ec cpx #sector_buffer+512 1210 d803 26 ec bne cmd_dir_loop2 1211 ;;; Go to next sector in directory 1212 d805 fe bc 02 ldx media_addr_1 1213 d808 08 inx 1214 d809 20 d0 bra cmd_dir_loop1 1215 cmd_dir_done: 1216 d80b 7e d1 e4 jmp prompt 1217 1218 ;;; 1219 ;;; Print directory entry pointed at by X 1220 ;;; 1221 cmd_dir_print: 1222 d80e bd d7 a3 jsr print_file_attr 1223 d811 08 inx 1224 * inx 1225 * inx 1226 * inx 1227 * inx 1228 d812 bd d7 4b jsr print_space 1229 d815 bd d7 6c jsr print_4hex ; start sector 1230 d818 bd d7 4b jsr print_space 1231 d81b bd d7 6c jsr print_4hex ; end sector 1232 d81e bd d7 4b jsr print_space 1233 d821 bd d7 6c jsr print_4hex ; file size 1234 d824 bd d7 6c jsr print_4hex ; file size 1235 d827 bd d7 4b jsr print_space 1236 d82a bd d7 6c jsr print_4hex ; year 1237 d82d 86 2d ldaa #'- 1238 d82f bd 7f e8 jsr console_output 1239 d832 bd d7 61 jsr print_2hex ; month 1240 d835 86 2d ldaa #'- 1241 d837 bd 7f e8 jsr console_output 1242 d83a bd d7 61 jsr print_2hex ; day 1243 d83d bd d7 4b jsr print_space 1244 d840 bd d7 61 jsr print_2hex ; hour 1245 d843 86 3a ldaa #': 1246 d845 bd 7f e8 jsr console_output 1247 d848 bd d7 61 jsr print_2hex ; minute 1248 d84b 86 3a ldaa #': 1249 d84d bd 7f e8 jsr console_output 1250 d850 bd d7 61 jsr print_2hex ; second 1251 d853 bd d7 4b jsr print_space 1252 d856 bd d7 36 jsr print_string ; filename 1253 ;;; Check if entry is a directory and print trailing '/' 1254 d859 fe bc e7 ldx xtemp 1255 d85c a6 00 ldaa ,x 1256 d85e 85 40 bita #$40 1257 d860 27 05 beq cmd_dir_print2 1258 d862 86 2f ldaa #'/ 1259 d864 bd 7f e8 jsr console_output 1260 cmd_dir_print2: 1261 d867 bd d7 41 jsr print_crlf 1262 d86a 39 rts 1263 1264 ;;; 1265 ;;; Command 'cd' (change work directory) 1266 ;;; 1267 command_cd: 1268 ;;; Move line_pointer to first argument (directory name) 1269 d86b fe bc e0 ldx line_pointer 1270 d86e bd d6 ed jsr str_skp_next 1271 d871 ff bc e0 stx line_pointer 1272 d874 ff bc e2 stx arg_pointer 1273 d877 a6 00 ldaa ,x 1274 d879 26 02 bne *+4 1275 d87b 20 07 bra cmd_cd_root 1276 ;;; Check if it's a "cd root" 1277 d87d ee 00 ldx ,x 1278 d87f 8c 2f 00 cpx #$2f00 ; is argument '/'? 1279 d882 26 18 bne cmd_cd_chk 1280 cmd_cd_root: 1281 d884 fe bc 0c ldx root_dir_beg ; set work dir to root dir 1282 d887 ff bc 10 stx wrk_dir_beg 1283 d88a fe bc 0e ldx root_dir_end 1284 d88d ff bc 12 stx wrk_dir_end 1285 d890 86 2f ldaa #'/ 1286 d892 b7 bc 14 staa wrk_path ; set directory path to root 1287 d895 4f clra 1288 d896 b7 bc 15 staa wrk_path+1 ; end of string 1289 d899 7e d1 e4 jmp prompt 1290 ;;; Check if entry exists 1291 cmd_cd_chk: 1292 d89c bd df f7 jsr find_file_entry 1293 d89f 27 03 beq *+5 1294 d8a1 7e d1 79 jmp error_not_found 1295 d8a4 ff bc e7 stx xtemp 1296 ;;; Verify that entry is a directory and readable 1297 d8a7 a6 00 ldaa ,x 1298 d8a9 85 40 bita #$40 1299 d8ab 26 03 bne *+5 1300 d8ad 7e d1 97 jmp error_denied 1301 d8b0 85 01 bita #$01 1302 d8b2 26 03 bne *+5 1303 d8b4 7e d1 97 jmp error_denied 1304 ;;; Enter directory 1305 d8b7 ec 01 ldd 1,x 1306 d8b9 fd bc 10 std wrk_dir_beg 1307 d8bc ec 03 ldd 3,x 1308 d8be fd bc 12 std wrk_dir_end 1309 ;;; Add directory to current path 1310 d8c1 ce bc 14 ldx #wrk_path 1311 cmd_cd_loop1: 1312 d8c4 a6 00 ldaa ,x 1313 d8c6 27 03 beq cmd_cd_cpy 1314 d8c8 08 inx 1315 d8c9 20 f9 bra cmd_cd_loop1 1316 cmd_cd_cpy: 1317 d8cb ff bc e9 stx xtemp2 1318 d8ce fe bc e7 ldx xtemp 1319 d8d1 c6 10 ldab #16 ; beginning of entry name 1320 d8d3 3a abx 1321 d8d4 ff bc e7 stx xtemp 1322 cmd_cd_loop2: 1323 d8d7 fe bc e7 ldx xtemp 1324 d8da a6 00 ldaa ,x 1325 d8dc 27 14 beq cmd_cd_cpy_end 1326 d8de 08 inx 1327 d8df ff bc e7 stx xtemp 1328 d8e2 fe bc e9 ldx xtemp2 1329 d8e5 a7 00 staa ,x 1330 d8e7 08 inx 1331 d8e8 8c bc 93 cpx #wrk_path_end 1332 d8eb 27 05 beq cmd_cd_cpy_end 1333 d8ed ff bc e9 stx xtemp2 1334 d8f0 20 e5 bra cmd_cd_loop2 1335 cmd_cd_cpy_end: 1336 d8f2 fe bc e9 ldx xtemp2 1337 d8f5 86 2f ldaa #'/ 1338 d8f7 a7 00 staa ,x 1339 d8f9 08 inx 1340 d8fa 6f 00 clr ,x 1341 d8fc 7e d1 e4 jmp prompt 1342 1343 ;;; 1344 ;;; Command 'mkdir' 1345 ;;; 1346 command_mkdir: 1347 ;;; Move line_pointer to first argument (directory name) 1348 d8ff fe bc e0 ldx line_pointer 1349 d902 bd d6 ed jsr str_skp_next 1350 d905 ff bc e0 stx line_pointer 1351 d908 ff bc e2 stx arg_pointer 1352 d90b a6 00 ldaa ,x 1353 d90d 26 03 bne *+5 1354 d90f 7e d1 85 jmp error_argument 1355 ;;; Check if valid file name 1356 d912 fe bc e2 ldx arg_pointer 1357 d915 bd d7 70 jsr validate_filename_arg 1358 d918 25 03 bcs *+5 1359 d91a 7e d1 85 jmp error_argument 1360 ;;; Check if entry already exists 1361 d91d bd df f7 jsr find_file_entry 1362 d920 26 03 bne *+5 1363 d922 7e d1 7f jmp error_exist 1364 ;;; Locate a free directory entry for the directory 1365 d925 bd df c9 jsr find_free_entry ; find empty entry in current directory 1366 d928 27 03 beq *+5 ; any free space left? 1367 d92a 7e d1 8b jmp error_no_space 1368 ;;; Allocate space for directory 1369 d92d 86 08 ldaa #8 ; allocate 8 sectors 1370 d92f bd de de jsr alloc 1371 d932 27 03 beq *+5 ; enough free space left on volume for a directory? 1372 d934 7e d1 8b jmp error_no_space 1373 d937 bd df c9 jsr find_free_entry ; find empty entry in current directory (same as last time) 1374 d93a 27 03 beq *+5 1375 d93c 7e d1 8b jmp error_no_space 1376 ;;; Setup new directory entry 1377 d93f 86 c3 ldaa #$C3 ; set entry to status "in use directory" and XWR 1378 d941 a7 00 staa ,x 1379 d943 fc bc 98 ldd cur_file_beg ; set entry start sector 1380 d946 ed 01 std 1,x 1381 d948 fc bc 9a ldd cur_file_end ; set entry end sector 1382 d94b ed 03 std 3,x 1383 d94d 6f 05 clr 5,x ; write directory entry size (8*512bytes = 4096bytes = 0x1000) 1384 d94f 6f 06 clr 6,x 1385 d951 cc 10 00 ldd #$1000 1386 d954 ed 07 std 7,x 1387 ;;; TODO: write time stamp to entry 1388 d956 fc bc e2 ldd arg_pointer 1389 d959 fd bc e0 std line_pointer 1390 d95c c6 09 ldab #9 ; go to start of time stamp 1391 d95e 3a abx 1392 d95f bd e2 53 jsr rtc_get_time ; write time stamp 1393 d962 c6 07 ldab #7 ; go to start of entry file name 1394 d964 3a abx 1395 d965 c6 1f ldab #31 1396 cmd_mkdir_name: ; copy name char by char 1397 d967 bd d6 7b jsr line_pull_char 1398 d96a 4d tsta 1399 d96b 27 0a beq cmd_mkdir_name_e 1400 d96d 81 20 cmpa #$20 1401 d96f 27 06 beq cmd_mkdir_name_e 1402 d971 a7 00 staa ,x 1403 d973 08 inx 1404 d974 5a decb 1405 d975 26 f0 bne cmd_mkdir_name 1406 cmd_mkdir_name_e: 1407 d977 4f clra 1408 d978 a7 00 staa ,x ; terminate name sting 1409 ;;; Write back directory sector 1410 d97a ce bc ec ldx #sector_buffer 1411 d97d bd e1 ba jsr write_sector 1412 d980 27 03 beq *+5 1413 d982 7e d1 64 jmp error_general 1414 ;;; Init allocated/new directory sectors 1415 d985 ce bc ec ldx #sector_buffer ; clear sector buffer 1416 cmd_mkdir_init1: 1417 d988 6f 00 clr ,x 1418 d98a 08 inx 1419 d98b 8c be eb cpx #sector_buffer+511 1420 d98e 23 f8 bls cmd_mkdir_init1 1421 d990 fe bc 9a ldx cur_file_end ; load allocated/new directory start sector 1422 d993 ff bc 02 stx media_addr_1 1423 cmd_mkdir_init2: ; write allocated/new directory sectors 1424 d996 ce bc ec ldx #sector_buffer 1425 d999 bd e1 ba jsr write_sector 1426 d99c 27 03 beq *+5 1427 d99e 7e d1 64 jmp error_general 1428 d9a1 fe bc 02 ldx media_addr_1 1429 d9a4 09 dex 1430 d9a5 ff bc 02 stx media_addr_1 1431 d9a8 bc bc 98 cpx cur_file_beg 1432 d9ab 22 e9 bhi cmd_mkdir_init2 1433 d9ad 27 e7 beq cmd_mkdir_init2 1434 cmd_mkdir_end: 1435 d9af 7e d1 e4 jmp prompt 1436 1437 ;;; 1438 ;;; Command 'save' 1439 ;;; 1440 command_save: 1441 ;;; Move line_pointer to first argument (file name) 1442 d9b2 fe bc e0 ldx line_pointer 1443 d9b5 bd d6 ed jsr str_skp_next 1444 d9b8 ff bc e0 stx line_pointer 1445 d9bb ff bc e2 stx arg_pointer 1446 d9be a6 00 ldaa ,x 1447 d9c0 26 03 bne *+5 1448 d9c2 7e d1 85 jmp error_argument 1449 ;;; Check if valid file name 1450 d9c5 fe bc e2 ldx arg_pointer 1451 d9c8 bd d7 70 jsr validate_filename_arg 1452 d9cb 25 03 bcs *+5 1453 d9cd 7e d1 85 jmp error_argument 1454 ;;; Check if file already exists 1455 d9d0 bd df f7 jsr find_file_entry 1456 d9d3 26 03 bne *+5 1457 d9d5 7e d1 7f jmp error_exist 1458 ;;; Read begin address 1459 d9d8 fe bc e2 ldx arg_pointer ; move line_pointer to second argument 1460 d9db bd d6 ed jsr str_skp_next 1461 d9de ff bc e0 stx line_pointer 1462 d9e1 a6 00 ldaa ,x 1463 d9e3 26 03 bne *+5 1464 d9e5 7e d1 85 jmp error_argument 1465 d9e8 bd d6 ae jsr line_pull_4hex 1466 d9eb 25 03 bcs *+5 1467 d9ed 7e d1 85 jmp error_argument 1468 d9f0 fe bc e7 ldx xtemp 1469 d9f3 ff bc 9c stx cur_file_saddr 1470 * ldx #xtemp ; DEBUG 1471 * jsr print_4hex ; DEBUG 1472 ;;; Read end address 1473 d9f6 fe bc e0 ldx line_pointer ; move line_pointer to third argument 1474 d9f9 bd d6 ed jsr str_skp_next 1475 d9fc ff bc e0 stx line_pointer 1476 d9ff a6 00 ldaa ,x 1477 da01 26 03 bne *+5 1478 da03 7e d1 85 jmp error_argument 1479 da06 bd d6 ae jsr line_pull_4hex 1480 da09 25 03 bcs *+5 1481 da0b 7e d1 85 jmp error_argument 1482 da0e fe bc e7 ldx xtemp 1483 da11 ff bc 9e stx cur_file_eaddr 1484 * ldx #xtemp ; DEBUG 1485 * jsr print_4hex ; DEBUG 1486 ;;; Locate a free directory entry for the file 1487 da14 bd df c9 jsr find_free_entry ; find empty entry in current directory 1488 da17 27 03 beq *+5 ; any free space left? 1489 da19 7e d1 8b jmp error_no_space 1490 ;;; Determine number of sectors needed for the file 1491 da1c 86 01 ldaa #$01 1492 da1e b7 bc e6 staa temp ; sector counter (start at one sector) 1493 da21 fc bc 9e ldd cur_file_eaddr ; calculate file size 1494 da24 b3 bc 9c subd cur_file_saddr 1495 cmd_save_loop1: 1496 da27 81 01 cmpa #$01 1497 da29 23 08 bls cmd_save_loop1_done ; calculation done? 1498 da2b 83 02 00 subd #512 1499 da2e 7c bc e6 inc temp 1500 da31 20 f4 bra cmd_save_loop1 1501 cmd_save_loop1_done: 1502 ;;; Allocate sectors for the file 1503 * ldx #temp ; DEBUG 1504 * jsr print_2hex ; DEBUG 1505 * jsr print_crlf ; DEBUG 1506 da33 b6 bc e6 ldaa temp ; number of sectors to allocate 1507 da36 bd de de jsr alloc 1508 da39 27 03 beq *+5 ; enough free space left on volume for file? 1509 da3b 7e d1 8b jmp error_no_space 1510 ;;; Setup new directory entry 1511 da3e bd df c9 jsr find_free_entry ; find the empty entry in current directory again 1512 da41 27 03 beq *+5 1513 da43 7e d1 8b jmp error_no_space 1514 da46 86 a3 ldaa #$A3 ; set entry to status "in use file" and -WR 1515 da48 a7 00 staa ,x 1516 da4a fc bc 98 ldd cur_file_beg ; set file start sector 1517 da4d ed 01 std 1,x 1518 da4f fc bc 9a ldd cur_file_end ; set file end sector 1519 da52 ed 03 std 3,x 1520 da54 fc bc 9e ldd cur_file_eaddr ; set file size 1521 da57 b3 bc 9c subd cur_file_saddr 1522 da5a c3 00 01 addd #1 1523 da5d 24 02 bcc cmd_save_size_lsb 1524 da5f 6c 06 inc 6,x 1525 cmd_save_size_lsb: 1526 da61 ed 07 std 7,x 1527 da63 fc bc e2 ldd arg_pointer ; set file name 1528 da66 fd bc e0 std line_pointer 1529 da69 c6 09 ldab #9 ; go to start of time stamp 1530 da6b 3a abx 1531 da6c bd e2 53 jsr rtc_get_time ; write time stamp 1532 da6f c6 07 ldab #7 ; go to start of entry file name 1533 da71 3a abx 1534 da72 c6 1f ldab #31 1535 cmd_save_name: ; copy name into file entry 1536 da74 bd d6 7b jsr line_pull_char 1537 da77 4d tsta 1538 da78 27 0a beq cmd_save_name_done 1539 da7a 81 20 cmpa #$20 1540 da7c 27 06 beq cmd_save_name_done 1541 da7e a7 00 staa ,x 1542 da80 08 inx 1543 da81 5a decb 1544 da82 26 f0 bne cmd_save_name 1545 cmd_save_name_done: 1546 da84 4f clra 1547 da85 a7 00 staa ,x ; terminate name sting 1548 ;;; Write back directory sector 1549 da87 ce bc ec ldx #sector_buffer 1550 da8a bd e1 ba jsr write_sector 1551 da8d 27 03 beq *+5 1552 da8f 7e d1 64 jmp error_general 1553 ;;; Print information 1554 da92 ce d0 91 ldx #txt_saving 1555 da95 bd d7 36 jsr print_string 1556 da98 ce bc 9c ldx #cur_file_saddr 1557 da9b bd d7 6c jsr print_4hex 1558 da9e 86 2d ldaa #'- 1559 daa0 bd 7f e8 jsr console_output 1560 daa3 ce bc 9e ldx #cur_file_eaddr 1561 daa6 bd d7 6c jsr print_4hex 1562 daa9 bd d7 41 jsr print_crlf 1563 ;;; Write file data to data sectors 1564 daac fe bc 98 ldx cur_file_beg ; set first sector to write 1565 daaf ff bc 02 stx media_addr_1 1566 cmd_save_data_loop: 1567 dab2 bd e0 d1 jsr sector_buffer_in ; copy data to buffer 1568 dab5 ce bc ec ldx #sector_buffer 1569 dab8 bd e1 ba jsr write_sector 1570 dabb 27 03 beq *+5 1571 dabd 7e d1 64 jmp error_general 1572 dac0 fe bc 02 ldx media_addr_1 1573 dac3 bc bc 9a cpx cur_file_end ; all data sectors written? 1574 dac6 27 06 beq cmd_save_complete 1575 dac8 08 inx 1576 dac9 ff bc 02 stx media_addr_1 1577 dacc 20 e4 bra cmd_save_data_loop 1578 cmd_save_complete: 1579 dace 7e d1 e4 jmp prompt 1580 1581 ;;; 1582 ;;; Command 'load' 1583 ;;; 1584 command_load: 1585 ;;; Move line_pointer to file name (first argument) 1586 dad1 fe bc e0 ldx line_pointer 1587 dad4 bd d6 ed jsr str_skp_next 1588 dad7 ff bc e0 stx line_pointer 1589 dada ff bc e2 stx arg_pointer 1590 dadd a6 00 ldaa ,x 1591 dadf 26 03 bne *+5 1592 dae1 7e d1 85 jmp error_argument 1593 ;;; Check if valid file name 1594 dae4 bd d7 70 jsr validate_filename_arg 1595 dae7 25 03 bcs *+5 1596 dae9 7e d1 85 jmp error_argument 1597 ;;; Read load address 1598 daec fe bc e2 ldx arg_pointer ; move line_pointer to second argument 1599 daef bd d6 ed jsr str_skp_next 1600 daf2 ff bc e0 stx line_pointer 1601 daf5 a6 00 ldaa ,x 1602 daf7 26 03 bne *+5 1603 daf9 7e d1 85 jmp error_argument 1604 dafc bd d6 ae jsr line_pull_4hex 1605 daff 25 03 bcs *+5 1606 db01 7e d1 85 jmp error_argument 1607 db04 fe bc e7 ldx xtemp 1608 db07 ff bc 9c stx cur_file_saddr 1609 * ldx #xtemp ; DEBUG 1610 * jsr print_4hex ; DEBUG 1611 ;;; Check if file exists 1612 db0a fe bc e2 ldx arg_pointer ; move line_pointer to first argument 1613 db0d ff bc e0 stx line_pointer 1614 db10 bd df f7 jsr find_file_entry ; lookup directory entry 1615 db13 27 03 beq *+5 1616 db15 7e d1 79 jmp error_not_found 1617 ;;; Read directory entry 1618 db18 a6 00 ldaa ,x 1619 db1a 85 01 bita #$01 ; verify that entry is readable 1620 db1c 26 03 bne *+5 1621 db1e 7e d1 97 jmp error_denied 1622 db21 ec 01 ldd 1,x ; get file start sector 1623 db23 fd bc 98 std cur_file_beg 1624 db26 ec 03 ldd 3,x ; get file end sector 1625 db28 fd bc 9a std cur_file_end 1626 ;;; Calculate file memory range 1627 db2b ec 07 ldd 7,x 1628 db2d 83 00 01 subd #1 1629 db30 f3 bc 9c addd cur_file_saddr 1630 db33 fd bc 9e std cur_file_eaddr 1631 ;;; Print information 1632 db36 ce d0 99 ldx #txt_loading 1633 db39 bd d7 36 jsr print_string 1634 db3c ce bc 9c ldx #cur_file_saddr 1635 db3f bd d7 6c jsr print_4hex 1636 db42 86 2d ldaa #'- 1637 db44 bd 7f e8 jsr console_output 1638 db47 ce bc 9e ldx #cur_file_eaddr 1639 db4a bd d7 6c jsr print_4hex 1640 db4d bd d7 41 jsr print_crlf 1641 ;;; Read file data sectors 1642 db50 fe bc 98 ldx cur_file_beg ; set first sector to read 1643 db53 ff bc 02 stx media_addr_1 1644 db56 5f clrb ; no byte skip when reading buffer 1645 cmd_load_data_loop: 1646 db57 ce bc ec ldx #sector_buffer 1647 db5a bd e1 a6 jsr read_sector 1648 db5d 27 03 beq *+5 1649 db5f 7e d1 64 jmp error_general 1650 db62 bd e0 f9 jsr sector_buffer_out ; copy data from buffer 1651 db65 fe bc 02 ldx media_addr_1 1652 db68 bc bc 9a cpx cur_file_end ; all data sectors written? 1653 db6b 27 06 beq cmd_load_complete 1654 db6d 08 inx 1655 db6e ff bc 02 stx media_addr_1 1656 db71 20 e4 bra cmd_load_data_loop 1657 cmd_load_complete: 1658 db73 7e d1 e4 jmp prompt 1659 1660 ;;; 1661 ;;; Command 'run' 1662 ;;; 1663 command_run: 1664 ;;; Check for file in work dir 1665 db76 fe bc 10 ldx wrk_dir_beg 1666 db79 ff bc 94 stx cur_dir_beg 1667 db7c fe bc 12 ldx wrk_dir_end 1668 db7f ff bc 96 stx cur_dir_end 1669 db82 fe bc e0 ldx line_pointer 1670 db85 bd d6 ed jsr str_skp_next 1671 db88 ff bc e0 stx line_pointer 1672 db8b ff bc e2 stx arg_pointer 1673 db8e bd df f7 jsr find_file_entry 1674 db91 27 03 beq *+5 1675 db93 7e d1 79 jmp error_not_found 1676 db96 fc bc e2 ldd arg_pointer 1677 db99 fd bc e0 std line_pointer 1678 db9c 7e e1 21 jmp execute_file 1679 1680 ;;; 1681 ;;; Command 'delete' 1682 ;;; 1683 command_delete: 1684 ;;; Move line_pointer to file name (first argument) 1685 db9f fe bc e0 ldx line_pointer 1686 dba2 bd d6 ed jsr str_skp_next 1687 dba5 ff bc e0 stx line_pointer 1688 dba8 ff bc e2 stx arg_pointer 1689 dbab a6 00 ldaa ,x 1690 dbad 26 03 bne *+5 1691 dbaf 7e d1 85 jmp error_argument 1692 ;;; Check if valid file name 1693 dbb2 bd d7 70 jsr validate_filename_arg 1694 dbb5 25 03 bcs *+5 1695 dbb7 7e d1 85 jmp error_argument 1696 ;;; Check if file exists 1697 dbba bd df f7 jsr find_file_entry ; lookup directory entry 1698 dbbd 27 03 beq *+5 1699 dbbf 7e d1 79 jmp error_not_found 1700 dbc2 a6 00 ldaa ,x ; get entry flags 1701 dbc4 85 02 bita #$02 ; check if writable 1702 dbc6 26 03 bne *+5 1703 dbc8 7e d1 97 jmp error_denied 1704 dbcb 85 40 bita #$40 1705 dbcd 27 16 beq cmd_del_do ; entry is a file - perform delete 1706 dbcf bd e0 3b jsr check_dir_empty ; entry is a directory - check if empty 1707 dbd2 27 03 beq *+5 1708 dbd4 7e d1 91 jmp error_not_empty 1709 dbd7 fe bc e2 ldx arg_pointer ; retore line_pointer (point to file name) 1710 dbda ff bc e0 stx line_pointer 1711 dbdd bd df f7 jsr find_file_entry ; lookup directory entry again 1712 dbe0 27 03 beq *+5 1713 dbe2 7e d1 79 jmp error_not_found 1714 cmd_del_do: 1715 dbe5 ec 01 ldd 1,x ; file start sector 1716 dbe7 fd bc 98 std cur_file_beg 1717 dbea ec 03 ldd 3,x ; file end sector 1718 dbec fd bc 9a std cur_file_end 1719 ;;; Clear directory entry for file 1720 dbef 86 40 ldaa #64 1721 cmd_del_clear_entry: 1722 dbf1 6f 00 clr ,x 1723 dbf3 08 inx 1724 dbf4 4a deca 1725 dbf5 26 fa bne cmd_del_clear_entry 1726 ;;; write back directory sector 1727 dbf7 ce bc ec ldx #sector_buffer 1728 dbfa bd e1 ba jsr write_sector 1729 dbfd 27 03 beq *+5 1730 dbff 7e d1 64 jmp error_general 1731 ;;; Free allocated sectors 1732 * ldx #cur_file_beg ; DEBUG 1733 * jsr print_4hex ; DEBUG 1734 * ldx #cur_file_end ; DEBUG 1735 * jsr print_4hex ; DEBUG 1736 * jsr print_crlf ; DEBUG 1737 dc02 bd df 81 jsr dealloc 1738 dc05 27 03 beq *+5 1739 dc07 7e d1 64 jmp error_general 1740 dc0a 7e d1 e4 jmp prompt 1741 1742 ;;; 1743 ;;; Command 'rename' 1744 ;;; 1745 command_rename: 1746 ;;; Move line_pointer to old file name (first argument) 1747 dc0d fe bc e0 ldx line_pointer 1748 dc10 bd d6 ed jsr str_skp_next 1749 dc13 ff bc e0 stx line_pointer 1750 dc16 ff bc e2 stx arg_pointer 1751 dc19 a6 00 ldaa ,x 1752 dc1b 26 03 bne *+5 1753 dc1d 7e d1 85 jmp error_argument 1754 ;;; Check if valid file name 1755 dc20 bd d7 70 jsr validate_filename_arg 1756 dc23 25 03 bcs *+5 1757 dc25 7e d1 85 jmp error_argument 1758 ;;; Move line_pointer to new file name (second argument) 1759 dc28 fe bc e2 ldx arg_pointer 1760 dc2b bd d6 ed jsr str_skp_next 1761 dc2e a6 00 ldaa ,x 1762 dc30 26 03 bne *+5 1763 dc32 7e d1 85 jmp error_argument 1764 ;;; Check if valid file name 1765 dc35 bd d7 70 jsr validate_filename_arg 1766 dc38 25 03 bcs *+5 1767 dc3a 7e d1 85 jmp error_argument 1768 ;;; Check if new entry name exists 1769 dc3d fe bc e2 ldx arg_pointer 1770 dc40 bd d6 ed jsr str_skp_next 1771 dc43 ff bc e0 stx line_pointer 1772 dc46 bd df f7 jsr find_file_entry 1773 dc49 26 03 bne *+5 1774 dc4b 7e d1 7f jmp error_exist 1775 ;;; Check if old entry name exists 1776 dc4e fe bc e2 ldx arg_pointer 1777 dc51 ff bc e0 stx line_pointer 1778 dc54 bd df f7 jsr find_file_entry 1779 dc57 27 03 beq *+5 1780 dc59 7e d1 79 jmp error_not_found 1781 ;;; Check if file is writable 1782 dc5c a6 00 ldaa ,x 1783 dc5e 85 02 bita #$02 1784 dc60 26 03 bne *+5 1785 dc62 7e d1 97 jmp error_denied 1786 ;;; Update directory entry name 1787 dc65 3c pshx 1788 dc66 fe bc e2 ldx arg_pointer ; go to second argument 1789 dc69 bd d6 ed jsr str_skp_next 1790 dc6c ff bc e0 stx line_pointer 1791 dc6f 38 pulx 1792 dc70 c6 10 ldab #16 ; go to start of entry file name 1793 dc72 3a abx 1794 dc73 c6 1f ldab #31 1795 cmd_rename_name: ; copy name char by char 1796 dc75 bd d6 7b jsr line_pull_char 1797 dc78 4d tsta 1798 dc79 27 0a beq cmd_rename_name_e 1799 dc7b 81 20 cmpa #$20 1800 dc7d 27 06 beq cmd_rename_name_e 1801 dc7f a7 00 staa ,x 1802 dc81 08 inx 1803 dc82 5a decb 1804 dc83 26 f0 bne cmd_rename_name 1805 cmd_rename_name_e: 1806 dc85 4f clra 1807 dc86 a7 00 staa ,x ; terminate name sting 1808 ;;; Write back directory sector 1809 dc88 ce bc ec ldx #sector_buffer 1810 dc8b bd e1 ba jsr write_sector 1811 dc8e 27 03 beq *+5 1812 dc90 7e d1 64 jmp error_general 1813 dc93 7e d1 e4 jmp prompt 1814 1815 ;;; 1816 ;;; Command 'attr' 1817 ;;; 1818 command_attr: 1819 ;;; Move line_pointer to file name (first argument) 1820 dc96 fe bc e0 ldx line_pointer 1821 dc99 bd d6 ed jsr str_skp_next 1822 dc9c ff bc e0 stx line_pointer 1823 dc9f ff bc e2 stx arg_pointer 1824 dca2 a6 00 ldaa ,x 1825 dca4 26 03 bne *+5 1826 dca6 7e d1 85 jmp error_argument 1827 ;;; Check if valid file name 1828 dca9 bd d7 70 jsr validate_filename_arg 1829 dcac 25 03 bcs *+5 1830 dcae 7e d1 85 jmp error_argument 1831 ;;; Check if file exists 1832 dcb1 bd df f7 jsr find_file_entry ; lookup directory entry 1833 dcb4 27 03 beq *+5 1834 dcb6 7e d1 79 jmp error_not_found 1835 dcb9 ff bc e7 stx xtemp ; save entry pointer 1836 ;;; Read attributes 1837 dcbc fe bc e2 ldx arg_pointer 1838 dcbf bd d6 ed jsr str_skp_next 1839 dcc2 a6 00 ldaa ,x 1840 dcc4 26 03 bne *+5 1841 dcc6 7e d1 85 jmp error_argument 1842 dcc9 5f clrb ; attribute storage 1843 cmd_attr_arg_loop: 1844 dcca a6 00 ldaa ,x 1845 dccc 27 1d beq cmd_attr_arg_loop_done 1846 dcce 84 df anda #$df ; to upper case 1847 dcd0 81 52 cmpa #'R 1848 dcd2 27 0b beq cmd_attr_set_r 1849 dcd4 81 57 cmpa #'W 1850 dcd6 27 0b beq cmd_attr_set_w 1851 dcd8 81 58 cmpa #'X 1852 dcda 27 0b beq cmd_attr_set_x 1853 cmd_attr_arg_loop_next: 1854 dcdc 08 inx 1855 dcdd 20 eb bra cmd_attr_arg_loop 1856 cmd_attr_set_r: 1857 dcdf ca 01 orab #$01 1858 dce1 20 f9 bra cmd_attr_arg_loop_next 1859 cmd_attr_set_w: 1860 dce3 ca 02 orab #$02 1861 dce5 20 f5 bra cmd_attr_arg_loop_next 1862 cmd_attr_set_x: 1863 dce7 ca 04 orab #$04 1864 dce9 20 f1 bra cmd_attr_arg_loop_next 1865 cmd_attr_arg_loop_done: 1866 ;;; Update directory entry 1867 dceb fe bc e7 ldx xtemp 1868 dcee a6 00 ldaa ,x 1869 dcf0 84 f8 anda #$F8 1870 dcf2 a7 00 staa ,x 1871 dcf4 ea 00 orab ,x 1872 dcf6 e7 00 stab ,x 1873 ;;; Write back directory sector 1874 dcf8 ce bc ec ldx #sector_buffer 1875 dcfb bd e1 ba jsr write_sector 1876 dcfe 27 03 beq *+5 1877 dd00 7e d1 64 jmp error_general 1878 dd03 7e d1 e4 jmp prompt 1879 1880 ;;; 1881 ;;; Command 'touch' 1882 ;;; 1883 command_touch: 1884 ;;; Move line_pointer to file name (first argument) 1885 dd06 fe bc e0 ldx line_pointer 1886 dd09 bd d6 ed jsr str_skp_next 1887 dd0c ff bc e0 stx line_pointer 1888 dd0f ff bc e2 stx arg_pointer 1889 dd12 a6 00 ldaa ,x 1890 dd14 26 03 bne *+5 1891 dd16 7e d1 85 jmp error_argument 1892 ;;; Check if valid file name 1893 dd19 bd d7 70 jsr validate_filename_arg 1894 dd1c 25 03 bcs *+5 1895 dd1e 7e d1 85 jmp error_argument 1896 ;;; Check if entry exists 1897 dd21 fe bc e2 ldx arg_pointer 1898 dd24 ff bc e0 stx line_pointer 1899 dd27 bd df f7 jsr find_file_entry 1900 dd2a 27 03 beq *+5 1901 dd2c 7e d1 79 jmp error_not_found 1902 ;;; Check if file is writable 1903 dd2f a6 00 ldaa ,x 1904 dd31 85 02 bita #$02 1905 dd33 26 03 bne *+5 1906 dd35 7e d1 97 jmp error_denied 1907 ;;; Update directory entry 1908 dd38 c6 09 ldab #9 ; go to start of time stamp 1909 dd3a 3a abx 1910 dd3b bd e2 53 jsr rtc_get_time ; write time stamp 1911 ;;; Write back directory sector 1912 dd3e ce bc ec ldx #sector_buffer 1913 dd41 bd e1 ba jsr write_sector 1914 dd44 27 03 beq *+5 1915 dd46 7e d1 64 jmp error_general 1916 dd49 7e d1 e4 jmp prompt 1917 1918 ;;; 1919 ;;; Command 'time' 1920 ;;; 1921 command_time: 1922 ;;; Verify checksum 1923 dd4c 86 47 ldaa #$47 1924 dd4e bb bf f8 adda ram_time+0 1925 dd51 bb bf f9 adda ram_time+1 1926 dd54 bb bf fa adda ram_time+2 1927 dd57 bb bf fb adda ram_time+3 1928 dd5a bb bf fc adda ram_time+4 1929 dd5d bb bf fd adda ram_time+5 1930 dd60 bb bf fe adda ram_time+6 1931 dd63 b1 bf ff cmpa ram_time+7 1932 dd66 27 03 beq command_time_print 1933 dd68 7e d1 e4 jmp prompt 1934 command_time_print 1935 dd6b ce bc ec ldx #sector_buffer 1936 dd6e bd e2 53 jsr rtc_get_time 1937 1938 dd71 ce bc ec ldx #sector_buffer 1939 dd74 bd d7 6c jsr print_4hex 1940 dd77 86 2d ldaa #'- 1941 dd79 bd 7f e8 jsr console_output 1942 dd7c bd d7 61 jsr print_2hex 1943 dd7f 86 2d ldaa #'- 1944 dd81 bd 7f e8 jsr console_output 1945 dd84 bd d7 61 jsr print_2hex 1946 1947 dd87 bd d7 4b jsr print_space 1948 1949 dd8a bd d7 61 jsr print_2hex 1950 dd8d 86 3a ldaa #': 1951 dd8f bd 7f e8 jsr console_output 1952 dd92 bd d7 61 jsr print_2hex 1953 dd95 86 3a ldaa #': 1954 dd97 bd 7f e8 jsr console_output 1955 dd9a bd d7 61 jsr print_2hex 1956 1957 dd9d bd d7 41 jsr print_crlf 1958 dda0 7e d1 e4 jmp prompt 1959 1960 ;;; 1961 ;;; Command 'settime' 1962 ;;; 1963 command_settime: 1964 ;;; Read YEAR 1965 dda3 fe bc e0 ldx line_pointer 1966 dda6 bd d6 ed jsr str_skp_next 1967 dda9 ff bc e0 stx line_pointer 1968 ddac a6 00 ldaa ,x 1969 ddae 26 03 bne *+5 1970 ddb0 7e de 98 jmp command_settime_format 1971 ddb3 bd d6 ae jsr line_pull_4hex 1972 ddb6 25 03 bcs *+5 1973 ddb8 7e de 98 jmp command_settime_format 1974 ddbb fe bc e7 ldx xtemp 1975 ddbe ff bc ec stx sector_buffer 1976 ;;; Read MONTH 1977 ddc1 fe bc e0 ldx line_pointer 1978 ddc4 bd d6 ed jsr str_skp_next 1979 ddc7 ff bc e0 stx line_pointer 1980 ddca a6 00 ldaa ,x 1981 ddcc 26 03 bne *+5 1982 ddce 7e de 98 jmp command_settime_format 1983 ddd1 bd d6 8c jsr line_pull_2hex 1984 ddd4 25 03 bcs *+5 1985 ddd6 7e de 98 jmp command_settime_format 1986 ddd9 b6 bc e6 ldaa temp 1987 dddc b7 bc ee staa sector_buffer+2 1988 ;;; Read DAY 1989 dddf fe bc e0 ldx line_pointer 1990 dde2 bd d6 ed jsr str_skp_next 1991 dde5 ff bc e0 stx line_pointer 1992 dde8 a6 00 ldaa ,x 1993 ddea 26 03 bne *+5 1994 ddec 7e de 98 jmp command_settime_format 1995 ddef bd d6 8c jsr line_pull_2hex 1996 ddf2 25 03 bcs *+5 1997 ddf4 7e de 98 jmp command_settime_format 1998 ddf7 b6 bc e6 ldaa temp 1999 ddfa b7 bc ef staa sector_buffer+3 2000 ;;; Read HOURS 2001 ddfd fe bc e0 ldx line_pointer 2002 de00 bd d6 ed jsr str_skp_next 2003 de03 ff bc e0 stx line_pointer 2004 de06 a6 00 ldaa ,x 2005 de08 26 03 bne *+5 2006 de0a 7e de 98 jmp command_settime_format 2007 de0d bd d6 8c jsr line_pull_2hex 2008 de10 25 03 bcs *+5 2009 de12 7e de 98 jmp command_settime_format 2010 de15 b6 bc e6 ldaa temp 2011 de18 b7 bc f0 staa sector_buffer+4 2012 ;;; Read MINUTES 2013 de1b fe bc e0 ldx line_pointer 2014 de1e bd d6 ed jsr str_skp_next 2015 de21 ff bc e0 stx line_pointer 2016 de24 a6 00 ldaa ,x 2017 de26 26 03 bne *+5 2018 de28 7e de 98 jmp command_settime_format 2019 de2b bd d6 8c jsr line_pull_2hex 2020 de2e 25 03 bcs *+5 2021 de30 7e de 98 jmp command_settime_format 2022 de33 b6 bc e6 ldaa temp 2023 de36 b7 bc f1 staa sector_buffer+5 2024 ;;; Read SECONDS 2025 de39 fe bc e0 ldx line_pointer 2026 de3c bd d6 ed jsr str_skp_next 2027 de3f ff bc e0 stx line_pointer 2028 de42 a6 00 ldaa ,x 2029 de44 26 03 bne *+5 2030 de46 7e de 98 jmp command_settime_format 2031 de49 bd d6 8c jsr line_pull_2hex 2032 de4c 25 03 bcs *+5 2033 de4e 7e de 98 jmp command_settime_format 2034 de51 b6 bc e6 ldaa temp 2035 de54 b7 bc f2 staa sector_buffer+6 2036 2037 * ldx #sector_buffer ; DEBUG 2038 * jsr print_4hex ; DEBUG 2039 * jsr print_2hex ; DEBUG 2040 * jsr print_2hex ; DEBUG 2041 * jsr print_2hex ; DEBUG 2042 * jsr print_2hex ; DEBUG 2043 * jsr print_2hex ; DEBUG 2044 2045 de57 ce bc ec ldx #sector_buffer 2046 de5a bd e2 d5 jsr rtc_set_time 2047 2048 ;;; Update ram_time + checksum 2049 de5d a6 01 ldaa 1,x 2050 de5f b7 bf f9 staa ram_time+1 2051 de62 a6 02 ldaa 2,x 2052 de64 b7 bf fa staa ram_time+2 2053 de67 a6 03 ldaa 3,x 2054 de69 b7 bf fb staa ram_time+3 2055 de6c a6 04 ldaa 4,x 2056 de6e b7 bf fc staa ram_time+4 2057 de71 a6 05 ldaa 5,x 2058 de73 b7 bf fd staa ram_time+5 2059 de76 a6 06 ldaa 6,x 2060 de78 b7 bf fe staa ram_time+6 2061 de7b 86 47 ldaa #$47 2062 de7d bb bf f8 adda ram_time+0 2063 de80 bb bf f9 adda ram_time+1 2064 de83 bb bf fa adda ram_time+2 2065 de86 bb bf fb adda ram_time+3 2066 de89 bb bf fc adda ram_time+4 2067 de8c bb bf fd adda ram_time+5 2068 de8f bb bf fe adda ram_time+6 2069 de92 b7 bf ff staa ram_time+7 2070 2071 de95 7e dd 4c jmp command_time 2072 command_settime_format: 2073 de98 ce d0 c7 ldx #txt_help_settime 2074 de9b bd d7 36 jsr print_string 2075 de9e 7e d1 e4 jmp prompt 2076 2077 ;;; 2078 ;;; Command 'monitor' 2079 ;;; 2080 command_monitor: 2081 dea1 bd d1 2b jsr var_checksum_calc 2082 dea4 b7 bc eb staa var_checksum 2083 dea7 7e c0 00 jmp monitor_return 2084 2085 ;;; 2086 ;;; Command 'help' 2087 ;;; 2088 command_help: 2089 deaa ce d0 bb ldx #txt_help 2090 dead bd d7 36 jsr print_string 2091 deb0 5f clrb 2092 deb1 ce d2 43 ldx #command_table 2093 deb4 ff bc e7 stx xtemp 2094 command_help_loop: 2095 deb7 fe bc e7 ldx xtemp 2096 deba 6d 00 tst ,x 2097 debc 27 1a beq command_help_end 2098 debe ee 00 ldx ,x 2099 dec0 bd d7 4b jsr print_space 2100 dec3 bd d7 36 jsr print_string 2101 dec6 5c incb 2102 dec7 c5 03 bitb #3 2103 dec9 26 03 bne *+5 2104 decb bd d7 41 jsr print_crlf 2105 dece fe bc e7 ldx xtemp 2106 ded1 08 inx 2107 ded2 08 inx 2108 ded3 ff bc e7 stx xtemp 2109 ded6 20 df bra command_help_loop 2110 command_help_end: 2111 ded8 bd d7 41 jsr print_crlf 2112 dedb 7e d1 e4 jmp prompt 2113 2114 ;;; 2115 ;;; Find and allocate free sectors 2116 ;;; IN: Number of sectors to allocate in A 2117 ;;; OUT: Z set on OK 2118 ;;; Error code in A 2119 ;;; Beginning of sector sequence in cur_file_beg 2120 ;;; End of sector sequence in cur_file_end 2121 ;;; 2122 alloc: 2123 dede b7 bc e6 staa temp 2124 dee1 fe bc 04 ldx volume_beg ; set up volume sector counter 2125 dee4 ff bc 98 stx cur_file_beg 2126 dee7 fe bc 08 ldx alloc_beg ; set up allocation start sector 2127 deea ff bc 02 stx media_addr_1 2128 alloc_sector_read: 2129 * ldx #media_addr_1 ; DEBUG 2130 * jsr print_4hex ; DEBUG 2131 deed ce bc ec ldx #sector_buffer ; read allocation sector 2132 def0 bd e1 a6 jsr read_sector 2133 def3 27 01 beq *+3 2134 def5 39 rts 2135 ;;; Find sector gap 2136 def6 ce bc ec ldx #sector_buffer 2137 alloc_sector_find_gap: 2138 def9 a6 00 ldaa ,x 2139 defb 27 11 beq alloc_sector_found_gap ; sector entry is free 2140 defd fc bc 98 ldd cur_file_beg ; increase sector pointer 2141 df00 c3 00 01 addd #1 2142 df03 fd bc 98 std cur_file_beg 2143 df06 08 inx ; increse sector table pointer 2144 df07 8c be ec cpx #sector_buffer+512 2145 df0a 27 35 beq alloc_sector_read_next 2146 df0c 20 eb bra alloc_sector_find_gap 2147 ;;; Free sector found - check gap length 2148 alloc_sector_found_gap: 2149 df0e fc bc 98 ldd cur_file_beg 2150 df11 fd bc 9a std cur_file_end 2151 alloc_sector_gap: 2152 df14 a6 00 ldaa ,x 2153 df16 26 11 bne alloc_sector_gap_end ; sector entry not free - end of gap 2154 df18 fc bc 9a ldd cur_file_end ; increase sector pointer 2155 df1b c3 00 01 addd #1 2156 df1e fd bc 9a std cur_file_end 2157 df21 08 inx ; increase sector table pointer 2158 df22 8c be ec cpx #sector_buffer+512 2159 df25 27 02 beq alloc_sector_gap_end 2160 df27 20 eb bra alloc_sector_gap 2161 alloc_sector_gap_end: 2162 df29 fc bc 9a ldd cur_file_end 2163 df2c b3 bc 98 subd cur_file_beg 2164 df2f 4d tsta 2165 df30 26 21 bne alloc_sector_gap_ok ; gap over 256 sectors? 2166 df32 f1 bc e6 cmpb temp ; gap under 256 sectors but long enough? 2167 df35 22 1c bhi alloc_sector_gap_ok 2168 df37 27 1a beq alloc_sector_gap_ok 2169 ;;; Gap not log enough 2170 df39 fc bc 9a ldd cur_file_end 2171 df3c fd bc 98 std cur_file_beg 2172 df3f 20 b8 bra alloc_sector_find_gap ; look for next gap 2173 ;;; Read next allocation sector 2174 alloc_sector_read_next: 2175 df41 fe bc 02 ldx media_addr_1 ; prepare for next sector 2176 df44 08 inx 2177 df45 bc bc 0a cpx alloc_end 2178 df48 22 06 bhi alloc_sectors_full 2179 df4a ff bc 02 stx media_addr_1 2180 df4d 7e de ed jmp alloc_sector_read 2181 alloc_sectors_full: 2182 df50 86 f2 ldaa #$F2 ; error - allocation failed 2183 df52 39 rts 2184 ;;; Gap long enough found 2185 alloc_sector_gap_ok: 2186 df53 fc bc 9a ldd cur_file_end ; adjust sector pointer 2187 df56 83 00 01 subd #1 2188 df59 fd bc 9a std cur_file_end 2189 df5c 09 dex ; adjust sector table pointer 2190 ;;; Mark sectors in table 2191 df5d fc bc 9a ldd cur_file_end 2192 df60 fd bc 98 std cur_file_beg 2193 alloc_sector_table: 2194 df63 6c 00 inc ,x 2195 df65 7a bc e6 dec temp 2196 df68 27 0c beq alloc_sector_table_done 2197 df6a 09 dex 2198 df6b fc bc 98 ldd cur_file_beg 2199 df6e 83 00 01 subd #1 2200 df71 fd bc 98 std cur_file_beg 2201 df74 20 ed bra alloc_sector_table 2202 alloc_sector_table_done: 2203 df76 ce bc ec ldx #sector_buffer ; write back allocation sector 2204 df79 bd e1 ba jsr write_sector 2205 df7c 27 01 beq *+3 2206 df7e 39 rts 2207 * jsr print_crlf ; DEBUG 2208 * ldx #cur_file_beg ; DEBUG 2209 * jsr print_4hex ; DEBUG 2210 * ldx #cur_file_end ; DEBUG 2211 * jsr print_4hex ; DEBUG 2212 * ldx #temp ; DEBUG 2213 * jsr print_2hex ; DEBUG 2214 * jsr print_crlf ; DEBUG 2215 ;;; Allocation OK 2216 df7f 4f clra 2217 df80 39 rts 2218 2219 ;;; 2220 ;;; Free allocated sectors 2221 ;;; IN: Start sector in cur_file_beg 2222 ;;; End sector in cur_file_end 2223 ;;; OUT: Z set on OK 2224 ;;; Error code in A 2225 ;;; 2226 dealloc: 2227 ;;; Calculate allocation sector 2228 df81 fc bc 98 ldd cur_file_beg 2229 df84 fe bc 08 ldx alloc_beg 2230 dealloc_calc1: 2231 df87 81 01 cmpa #$01 ; D-reg under 511? 2232 df89 23 06 bls dealloc_calc1_found 2233 df8b 83 02 00 subd #512 2234 df8e 08 inx 2235 df8f 20 f6 bra dealloc_calc1 ; is it the next allocation sector? 2236 ;;; Read allocation sector 2237 dealloc_calc1_found: 2238 df91 fd bc e7 std xtemp 2239 df94 ff bc 02 stx media_addr_1 ; prepare to read allocation sector 2240 df97 ce bc ec ldx #sector_buffer 2241 df9a bd e1 a6 jsr read_sector ; read allocation sector 2242 df9d 27 01 beq *+3 2243 df9f 39 rts 2244 ;;; Find first sector in allocation table 2245 dfa0 fc bc e7 ldd xtemp ; retore D 2246 dfa3 c3 bc ec addd #sector_buffer ; D now points to first sector in table 2247 dfa6 18 xgdx 2248 ;;; Calculate number of sectors to free 2249 dfa7 fc bc 9a ldd cur_file_end 2250 dfaa b3 bc 98 subd cur_file_beg 2251 ;;; Clear sectors in table 2252 dealloc_loop1: 2253 dfad 6f 00 clr ,x 2254 dfaf 5d tstb 2255 dfb0 27 09 beq dealloc_loop1_done 2256 dfb2 08 inx 2257 dfb3 8c be eb cpx #sector_buffer+511 2258 dfb6 22 0e bhi dealloc_error ; end of table error 2259 dfb8 5a decb 2260 dfb9 20 f2 bra dealloc_loop1 2261 ;;; Write back allocation sector 2262 dealloc_loop1_done: 2263 dfbb ce bc ec ldx #sector_buffer 2264 dfbe bd e1 ba jsr write_sector ; write back allocation sector 2265 dfc1 27 01 beq *+3 2266 dfc3 39 rts 2267 dfc4 4f clra 2268 dfc5 39 rts 2269 dealloc_error: 2270 dfc6 86 f2 ldaa #$F2 ; error - deallocation failed 2271 dfc8 39 rts 2272 2273 ;;; 2274 ;;; Find free directory entry 2275 ;;; OUT: Z set on OK 2276 ;;; A set to error code 2277 ;;; X points to entry in sector_buffer 2278 ;;; media_addr_[3:0] point to sector LBA 2279 ;;; 2280 find_free_entry: 2281 dfc9 fe bc 94 ldx cur_dir_beg 2282 find_free_loop1: 2283 dfcc bc bc 96 cpx cur_dir_end ; compare with end of current directory 2284 dfcf 22 23 bhi find_free_full ; end if we have looped through entire directory 2285 dfd1 ff bc 02 stx media_addr_1 2286 dfd4 ce bc ec ldx #sector_buffer 2287 dfd7 bd e1 a6 jsr read_sector ; read next sector of directory 2288 dfda 27 01 beq *+3 2289 dfdc 39 rts 2290 dfdd ce bc ec ldx #sector_buffer 2291 find_free_loop2: 2292 dfe0 a6 00 ldaa ,x 2293 dfe2 26 02 bne find_free_gonext 2294 dfe4 4f clra ; no error code 2295 dfe5 39 rts 2296 find_free_gonext: 2297 dfe6 c6 40 ldab #64 ; within current sector 2298 dfe8 3a abx 2299 dfe9 8c be ac cpx #sector_buffer+448 2300 dfec 23 f2 bls find_free_loop2 ; goto next entry in sector 2301 dfee fe bc 02 ldx media_addr_1 2302 dff1 08 inx 2303 dff2 20 d8 bra find_free_loop1 ; goto next sector in directory 2304 find_free_full: 2305 dff4 86 f8 ldaa #$F8 ; error - directory is full 2306 dff6 39 rts 2307 2308 ;;; 2309 ;;; Find file in directory 2310 ;;; IN: file name pointed at by line_pointer 2311 ;;; OUT: Z set on OK 2312 ;;; A set to error code 2313 ;;; X points to entry in sector_buffer 2314 ;;; media_addr_[3:0] point to sector LBA 2315 ;;; 2316 find_file_entry: 2317 dff7 fe bc e0 ldx line_pointer ; save line pointer for multiple compares 2318 dffa ff bc e7 stx xtemp 2319 dffd fe bc 94 ldx cur_dir_beg 2320 find_file_loop1: 2321 e000 bc bc 96 cpx cur_dir_end ; compare with end of current directory 2322 e003 22 33 bhi find_file_not ; end if we have looped through entire directory 2323 e005 ff bc 02 stx media_addr_1 2324 e008 ce bc ec ldx #sector_buffer 2325 e00b bd e1 a6 jsr read_sector ; read next sector of directory 2326 e00e 27 01 beq *+3 2327 e010 39 rts 2328 e011 ce bc ec ldx #sector_buffer 2329 find_file_loop2: 2330 e014 a6 00 ldaa ,x 2331 e016 27 12 beq find_file_gonext 2332 e018 3c pshx 2333 e019 c6 10 ldab #16 ; go to start of file name 2334 e01b 3a abx 2335 e01c fc bc e7 ldd xtemp 2336 e01f fd bc e0 std line_pointer 2337 e022 bd d7 1e jsr string_compare 2338 e025 38 pulx 2339 e026 26 02 bne find_file_gonext 2340 e028 4f clra ; no error code 2341 e029 39 rts 2342 find_file_gonext: 2343 e02a c6 40 ldab #64 ; within current sector 2344 e02c 3a abx 2345 e02d 8c be ac cpx #sector_buffer+448 2346 e030 23 e2 bls find_file_loop2 ; goto next entry in sector 2347 e032 fe bc 02 ldx media_addr_1 2348 e035 08 inx 2349 e036 20 c8 bra find_file_loop1 ; goto next sector in directory 2350 find_file_not: 2351 e038 86 f9 ldaa #$F9 ; error - file not found 2352 e03a 39 rts 2353 2354 ;;; 2355 ;;; Check if a directory entry is empty 2356 ;;; IN: X pointer to directory entry to check 2357 ;;; OUT: Z set if directory is empty 2358 ;;; A set to error code 2359 ;;; 2360 check_dir_empty: 2361 e03b ec 01 ldd 1,x 2362 e03d fd bc e7 std xtemp ; directory start sector 2363 e040 ec 03 ldd 3,x 2364 e042 fd bc 02 std media_addr_1 ; directiry end sector 2365 check_dir_empty1: 2366 ;;; Read directory sector 2367 e045 ce bc ec ldx #sector_buffer 2368 e048 bd e1 a6 jsr read_sector 2369 e04b 27 01 beq *+3 2370 e04d 39 rts 2371 ;;; Check if sector is empty (all bytes == $00) 2372 e04e ce bc ec ldx #sector_buffer 2373 check_dir_empty2: 2374 e051 6d 00 tst ,x 2375 e053 26 16 bne check_dir_empty_fail 2376 e055 08 inx 2377 e056 8c be eb cpx #sector_buffer+511 2378 e059 23 f6 bls check_dir_empty2 2379 ;;; Have we cehcked all sectors? 2380 e05b fe bc 02 ldx media_addr_1 2381 e05e 09 dex 2382 e05f ff bc 02 stx media_addr_1 2383 e062 bc bc e7 cpx xtemp 2384 e065 22 de bhi check_dir_empty1 2385 e067 27 dc beq check_dir_empty1 2386 ;;; If we get here all sectors in directoru are empty 2387 e069 4f clra 2388 e06a 39 rts 2389 check_dir_empty_fail: 2390 e06b 86 f5 ldaa #$F5 ; error - directory not empty 2391 e06d 39 rts 2392 2393 ;;; 2394 ;;; Open volume 2395 ;;; 2396 open_volume: 2397 ;;; Read volume header 2398 e06e 7f bc 00 clr media_addr_3 2399 e071 7f bc 01 clr media_addr_2 2400 e074 7f bc 02 clr media_addr_1 2401 e077 7f bc 03 clr media_addr_0 2402 e07a ce bc ec ldx #sector_buffer 2403 e07d bd e1 a6 jsr read_sector ; read first sector of drive 2404 e080 26 4c bne open_volume_error 2405 ;;; Verify magic word + version 2406 e082 fe bc ec ldx vol_magic 2407 e085 8c 4d 43 cpx #$4D43 ; "MC" 2408 e088 26 44 bne open_volume_error 2409 e08a fe bc ee ldx vol_magic+2 2410 e08d 8c 46 53 cpx #$4653 ; "FS" 2411 e090 26 3c bne open_volume_error 2412 e092 b6 bc f0 ldaa vol_version 2413 e095 81 02 cmpa #$02 ; version 2 2414 e097 26 35 bne open_volume_error 2415 ;;; Extract root dir info 2416 e099 fe bc f1 ldx vol_beg 2417 e09c ff bc 04 stx volume_beg ; pointer to beginning of volume 2418 e09f fe bc f3 ldx vol_end 2419 e0a2 ff bc 06 stx volume_end ; pointer to end of volume 2420 e0a5 fe bd 1b ldx vol_root_beg 2421 e0a8 ff bc 0c stx root_dir_beg ; pointer to beginning of root dir 2422 e0ab ff bc 10 stx wrk_dir_beg ; pointer to beginning of work dir 2423 e0ae fe bd 1d ldx vol_root_end 2424 e0b1 ff bc 0e stx root_dir_end ; pointer to end of root dir 2425 e0b4 ff bc 12 stx wrk_dir_end ; pointer to end of work dir 2426 e0b7 fe bd 17 ldx vol_alloc_beg 2427 e0ba ff bc 08 stx alloc_beg ; pointer to beginning of allocation table 2428 e0bd fe bd 19 ldx vol_alloc_end 2429 e0c0 ff bc 0a stx alloc_end ; pointer to end of allocation table 2430 ;;; Setup path string 2431 e0c3 86 2f ldaa #'/ 2432 e0c5 b7 bc 14 staa wrk_path ; set directory path to root 2433 e0c8 4f clra 2434 e0c9 b7 bc 15 staa wrk_path+1 ; end of string 2435 e0cc 4f clra 2436 e0cd 39 rts 2437 open_volume_error: 2438 e0ce 86 f1 ldaa #$F1 ; ID not found 2439 e0d0 39 rts 2440 2441 ;;; 2442 ;;; Routine for copying file data to sector buffer 2443 ;;; Copy stops when sector is full or cur_file_eaddr reached 2444 ;;; IN: file range in cur_file_saddr & cur_file_eaddr 2445 ;;; OUT: data in file_buffer 2446 ;;; updated cur_file_saddr 2447 ;;; 2448 sector_buffer_in: 2449 e0d1 ce bc ec ldx #sector_buffer 2450 e0d4 ff bc e7 stx xtemp ; sector buffer pointer 2451 sector_buffer_in_loop: 2452 e0d7 fe bc 9c ldx cur_file_saddr 2453 e0da a6 00 ldaa ,x 2454 e0dc 08 inx 2455 e0dd ff bc 9c stx cur_file_saddr 2456 e0e0 fe bc e7 ldx xtemp 2457 e0e3 a7 00 staa ,x 2458 e0e5 08 inx 2459 e0e6 ff bc e7 stx xtemp 2460 e0e9 8c be ec cpx #sector_buffer+512 ; end of sector fuffer? 2461 e0ec 27 0a beq sector_buffer_in_done 2462 e0ee fe bc 9c ldx cur_file_saddr 2463 e0f1 bc bc 9e cpx cur_file_eaddr ; end of file? 2464 e0f4 22 02 bhi sector_buffer_in_done 2465 e0f6 20 df bra sector_buffer_in_loop 2466 sector_buffer_in_done: 2467 e0f8 39 rts 2468 2469 ;;; 2470 ;;; Routine for copying file data from sector buffer 2471 ;;; Copy stops at end of sector or cur_file_eaddr reached 2472 ;;; IN: file range in cur_file_saddr & cur_file_eaddr 2473 ;;; leading bytes to skip in B acc (set to 0 for no skip) 2474 ;;; OUT: data in memory 2475 ;;; updated cur_file_saddr 2476 ;;; 2477 sector_buffer_out: 2478 e0f9 ce bc ec ldx #sector_buffer 2479 e0fc 3a abx ; bytes to skip 2480 e0fd 5f clrb ; skip no more 2481 e0fe ff bc e7 stx xtemp ; sector buffer pointer 2482 sector_buffer_out_loop: 2483 e101 fe bc e7 ldx xtemp 2484 e104 a6 00 ldaa ,x 2485 e106 08 inx 2486 e107 ff bc e7 stx xtemp 2487 e10a fe bc 9c ldx cur_file_saddr 2488 e10d a7 00 staa ,x 2489 e10f bc bc 9e cpx cur_file_eaddr ; end of file? 2490 e112 27 0c beq sector_buffer_out_done 2491 e114 08 inx 2492 e115 ff bc 9c stx cur_file_saddr 2493 e118 fe bc e7 ldx xtemp 2494 e11b 8c be ec cpx #sector_buffer+512 ; end of sector buffer? 2495 e11e 26 e1 bne sector_buffer_out_loop 2496 sector_buffer_out_done: 2497 e120 39 rts 2498 2499 ;;; 2500 ;;; Execute file at file pointer at X 2501 ;;; 2502 execute_file: 2503 e121 a6 00 ldaa ,x 2504 e123 84 a5 anda #$A5 ; check if readable and executable file 2505 e125 81 a5 cmpa #$A5 2506 e127 27 03 beq *+5 2507 e129 7e d1 97 jmp error_denied 2508 e12c ec 01 ldd 1,x ; get file start sector 2509 e12e fd bc 98 std cur_file_beg 2510 e131 fd bc 02 std media_addr_1 2511 e134 ec 03 ldd 3,x ; get file end sector 2512 e136 fd bc 9a std cur_file_end 2513 e139 ec 07 ldd 7,x ; get file size 2514 e13b 83 00 01 subd #1 2515 e13e fd bc 9e std cur_file_eaddr ; store in eaddr for now 2516 ;;; Load first sector of file 2517 e141 ce bc ec ldx #sector_buffer 2518 e144 bd e1 a6 jsr read_sector 2519 e147 27 03 beq *+5 2520 e149 7e d1 64 jmp error_general 2521 e14c ce bc ec ldx #sector_buffer 2522 e14f ec 00 ldd ,x ; read magic number 2523 e151 81 47 cmpa #$47 ; check for $47 2524 e153 27 03 beq *+5 2525 e155 7e d1 9d jmp error_not_exec 2526 e158 5d tstb ; check for $00 2527 e159 27 03 beq *+5 2528 e15b 7e d1 9d jmp error_not_exec 2529 e15e ec 02 ldd 2,x ; read load address 2530 e160 fd bc 9c std cur_file_saddr 2531 e163 ec 04 ldd 4,x ; read entry address 2532 e165 fd bc e9 std xtemp2 2533 e168 fc bc 9e ldd cur_file_eaddr ; calculate end address 2534 e16b f3 bc 9c addd cur_file_saddr 2535 e16e 83 00 02 subd #2 2536 e171 fd bc 9e std cur_file_eaddr 2537 * ldx #cur_file_saddr ; DEBUG 2538 * jsr print_4hex ; DEBUG 2539 * jsr print_space ; DEBUG 2540 * ldx #cur_file_eaddr ; DEBUG 2541 * jsr print_4hex ; DEBUG 2542 ;;; Load file into memory 2543 e174 c6 06 ldab #6 ; skip first 6 bytes of file (exec header) 2544 execute_file_loop: 2545 e176 ce bc ec ldx #sector_buffer 2546 e179 bd e1 a6 jsr read_sector 2547 e17c 27 03 beq *+5 2548 e17e 7e d1 64 jmp error_general 2549 e181 bd e0 f9 jsr sector_buffer_out 2550 e184 fe bc 02 ldx media_addr_1 2551 e187 bc bc 9a cpx cur_file_end ; all data sectors written? 2552 e18a 27 06 beq execute_file_loop_ok 2553 e18c 08 inx 2554 e18d ff bc 02 stx media_addr_1 2555 e190 20 e4 bra execute_file_loop 2556 execute_file_loop_ok: 2557 ;;; Execute loaded file 2558 * jsr print_crlf ; DEBUG 2559 e192 bd d1 2b jsr var_checksum_calc ; generate variable checksum 2560 e195 b7 bc eb staa var_checksum 2561 ;;; Load argument pointer and jump to program 2562 e198 fc bc e0 ldd line_pointer 2563 e19b fe bc e9 ldx xtemp2 2564 e19e 3c pshx ; push program start address to stack 2565 e19f fe bc e0 ldx line_pointer 2566 e1a2 fc bc e0 ldd line_pointer 2567 e1a5 39 rts ; jump to program address 2568 2569 ;;; 2570 ;;; Read sector at media_addr_[3:0] store at X 2571 ;;; Z set on OK read. Error code in A 2572 ;;; 2573 read_sector: 2574 e1a6 bd e1 e9 jsr cf_wait 2575 e1a9 bd e2 02 jsr cf_set_lba 2576 e1ac 86 01 ldaa #1 2577 e1ae b7 9f d2 staa cf_reg_2 ; number of sectors to read 2578 e1b1 86 20 ldaa #cf_cmd_read 2579 e1b3 b7 9f d7 staa cf_reg_7 ; issue read command 2580 e1b6 7e e2 1f jmp cf_read_data ; read data routine 2581 e1b9 39 rts 2582 2583 ;;; 2584 ;;; Write sector at media_addr_[3:0] stored at X 2585 ;;; Z set on OK write. Error code in A 2586 ;;; 2587 write_sector: 2588 e1ba bd e1 e9 jsr cf_wait 2589 e1bd bd e2 02 jsr cf_set_lba 2590 e1c0 86 01 ldaa #1 2591 e1c2 b7 9f d2 staa cf_reg_2 ; number of sectors to write 2592 e1c5 86 30 ldaa #cf_cmd_write 2593 e1c7 b7 9f d7 staa cf_reg_7 ; issue write command 2594 e1ca 7e e2 39 jmp cf_write_data ; write data routine 2595 e1cd 39 rts 2596 2597 ;;; 2598 ;;; Initialize CF 2599 ;;; 2600 cf_init: 2601 e1ce 86 04 ldaa #cf_cmd_reset ; reset command 2602 e1d0 b7 9f d7 staa cf_reg_7 2603 e1d3 bd e1 e9 jsr cf_wait 2604 e1d6 86 e0 ldaa #$E0 ; LBA3=0, MASTER, MODE=LBA 2605 e1d8 b7 9f d6 staa cf_reg_6 2606 e1db 86 01 ldaa #$01 ; 8-bit transfers 2607 e1dd b7 9f d1 staa cf_reg_1 2608 e1e0 86 ef ldaa #$EF ; set-feature command 2609 e1e2 b7 9f d7 staa cf_reg_7 2610 e1e5 bd e1 e9 jsr cf_wait 2611 e1e8 39 rts 2612 2613 2614 ;;; 2615 ;;; Wait for CF ready 2616 ;;; 2617 cf_wait: 2618 e1e9 b6 9f d7 ldaa cf_reg_7 2619 e1ec 84 80 anda #$80 ; mask out BUSY bit 2620 e1ee 81 00 cmpa #$00 2621 e1f0 26 f7 bne cf_wait 2622 e1f2 39 rts 2623 2624 ;;; 2625 ;;; Check for CF error 2626 ;;; Z set on OK 2627 ;;; Error code in A 2628 ;;; bit 7 - Bad block detected 2629 ;;; bit 6 - Uncorrectable data error 2630 ;;; bit 5 - Media changed 2631 ;;; bit 4 - ID not found 2632 ;;; bit 3 - Aborted command 2633 ;;; bit 2 - Media change requested 2634 ;;; bit 1 - Track 0 not found 2635 ;;; bit 0 - Addressmask not found 2636 ;;; 2637 cf_check_error: 2638 e1f3 b6 9f d7 ldaa cf_reg_7 2639 e1f6 84 01 anda #$01 ; mask out ERROR bit 2640 e1f8 81 00 cmpa #0 2641 e1fa 27 04 beq cf_no_error 2642 e1fc b6 9f d1 ldaa cf_reg_1 2643 e1ff 39 rts 2644 cf_no_error: 2645 e200 4f clra 2646 e201 39 rts 2647 2648 ;;; 2649 ;;; CF set LBA 2650 ;;; 2651 cf_set_lba: 2652 e202 b6 bc 03 ldaa media_addr_0 ; LBA byte 0 2653 e205 b7 9f d3 staa cf_reg_3 2654 e208 b6 bc 02 ldaa media_addr_1 ; LBA byte 1 2655 e20b b7 9f d4 staa cf_reg_4 2656 e20e b6 bc 01 ldaa media_addr_2 ; LBA byte 2 2657 e211 b7 9f d5 staa cf_reg_5 2658 e214 b6 bc 00 ldaa media_addr_3 ; LBA byte 3 2659 e217 84 0f anda #%00001111 ; mask out LBA bits 2660 e219 8a e0 oraa #%11100000 ; set mode LBA and master device 2661 e21b b7 9f d6 staa cf_reg_6 2662 e21e 39 rts 2663 2664 ;;; 2665 ;;; Read data from CF 2666 ;;; Z set on OK 2667 ;;; error code in A 2668 ;;; 2669 cf_read_data: 2670 e21f bd e1 e9 jsr cf_wait 2671 e222 b6 9f d7 ldaa cf_reg_7 2672 e225 84 08 anda #$08 ; mask out DRQ bit 2673 e227 81 08 cmpa #$08 2674 e229 26 0c bne cf_read_data_e 2675 e22b b6 9f d0 ldaa cf_reg_0 ; read data byte 2676 e22e a7 00 staa ,X 2677 e230 08 inx 2678 e231 bd e1 f3 jsr cf_check_error 2679 e234 27 e9 beq cf_read_data 2680 e236 39 rts 2681 cf_read_data_e: 2682 e237 4f clra 2683 e238 39 rts 2684 2685 ;;; 2686 ;;; Write data to CF 2687 ;;; Z set on OK 2688 ;;; error code in A 2689 ;;; 2690 cf_write_data: 2691 e239 bd e1 e9 jsr cf_wait 2692 e23c b6 9f d7 ldaa cf_reg_7 2693 e23f 84 08 anda #$08 ; mask out DRQ bit 2694 e241 81 08 cmpa #$08 2695 e243 26 0c bne cf_write_data_e 2696 e245 a6 00 ldaa ,X 2697 e247 b7 9f d0 staa cf_reg_0 ; write data byte 2698 e24a 08 inx 2699 e24b bd e1 f3 jsr cf_check_error 2700 e24e 27 e9 beq cf_write_data 2701 e250 39 rts 2702 cf_write_data_e: 2703 e251 4f clra 2704 e252 39 rts 2705 2706 ;;; 2707 ;;; Get ISO 8601 time stamp from RTC and store at X 2708 ;;; 2709 rtc_get_time: 2710 e253 36 psha 2711 e254 37 pshb 2712 rtc_get_time_loop: 2713 ;;; Loop until two identical time stamps have been read 2714 e255 bd e2 5e jsr rtc_get_time_sample 2715 e258 5d tstb 2716 e259 26 fa bne rtc_get_time_loop 2717 e25b 33 pulb 2718 e25c 32 pula 2719 e25d 39 rts 2720 rtc_get_time_sample: 2721 e25e 5f clrb 2722 ;;; Read SECONDS 2723 e25f 3c pshx 2724 e260 ce 9f c0 ldx #rtc_reg_s1 2725 e263 bd e2 c7 jsr rtc_read_8bit 2726 e266 38 pulx 2727 e267 a1 06 cmpa 6,x 2728 e269 27 01 beq *+3 2729 e26b 5c incb 2730 e26c a7 06 staa 6,x 2731 ;;; Read MINUTES 2732 e26e 3c pshx 2733 e26f ce 9f c2 ldx #rtc_reg_mi1 2734 e272 bd e2 c7 jsr rtc_read_8bit 2735 e275 38 pulx 2736 e276 84 7f anda #$7f 2737 e278 a1 05 cmpa 5,x 2738 e27a 27 01 beq *+3 2739 e27c 5c incb 2740 e27d a7 05 staa 5,x 2741 ;;; Read HOURS 2742 e27f 3c pshx 2743 e280 ce 9f c4 ldx #rtc_reg_h1 2744 e283 bd e2 c7 jsr rtc_read_8bit 2745 e286 38 pulx 2746 e287 84 3f anda #$3f 2747 e289 a1 04 cmpa 4,x 2748 e28b 27 01 beq *+3 2749 e28d 5c incb 2750 e28e a7 04 staa 4,x 2751 ;;; Read DAY 2752 e290 3c pshx 2753 e291 ce 9f c6 ldx #rtc_reg_d1 2754 e294 bd e2 c7 jsr rtc_read_8bit 2755 e297 38 pulx 2756 e298 84 3f anda #$3f 2757 e29a a1 03 cmpa 3,x 2758 e29c 27 01 beq *+3 2759 e29e 5c incb 2760 e29f a7 03 staa 3,x 2761 ;;; Read MONTH 2762 e2a1 3c pshx 2763 e2a2 ce 9f c8 ldx #rtc_reg_mo1 2764 e2a5 bd e2 c7 jsr rtc_read_8bit 2765 e2a8 38 pulx 2766 e2a9 84 1f anda #$1f 2767 e2ab a1 02 cmpa 2,x 2768 e2ad 27 01 beq *+3 2769 e2af 5c incb 2770 e2b0 a7 02 staa 2,x 2771 ;;; Read YEAR 2772 e2b2 3c pshx 2773 e2b3 ce 9f ca ldx #rtc_reg_y1 2774 e2b6 bd e2 c7 jsr rtc_read_8bit 2775 e2b9 38 pulx 2776 e2ba a1 01 cmpa 1,x 2777 e2bc 27 01 beq *+3 2778 e2be 5c incb 2779 e2bf a7 01 staa 1,x 2780 ;;; Read CENTURY 2781 e2c1 b6 bf f8 ldaa ram_time+0 2782 e2c4 a7 00 staa 0,x 2783 e2c6 39 rts 2784 ;;; Helper funtion to assemble two RTC nibs to one byte 2785 rtc_read_8bit: 2786 e2c7 37 pshb 2787 e2c8 a6 01 ldaa 1,x 2788 e2ca 48 asla 2789 e2cb 48 asla 2790 e2cc 48 asla 2791 e2cd 48 asla 2792 e2ce e6 00 ldab 0,x 2793 e2d0 c4 0f andb #$0f 2794 e2d2 1b aba 2795 e2d3 33 pulb 2796 e2d4 39 rts 2797 2798 ;;; 2799 ;;; Set ISO 8601 time stamp to RTC stored at X 2800 ;;; 2801 rtc_set_time: 2802 ;;; Stop RTC 2803 e2d5 86 07 ldaa #$07 2804 e2d7 b7 9f cf staa rtc_reg_cf 2805 e2da 4f clra 2806 e2db b7 9f cd staa rtc_reg_cd 2807 ;;; Set CENTURY 2808 e2de a6 00 ldaa 0,x 2809 e2e0 b7 bf f8 staa ram_time+0 2810 ;;; Set YEAR 2811 e2e3 a6 01 ldaa 1,x 2812 e2e5 3c pshx 2813 e2e6 ce 9f ca ldx #rtc_reg_y1 2814 e2e9 bd e3 25 jsr rtc_write_8bit 2815 e2ec 38 pulx 2816 ;;; Set MONTH 2817 e2ed a6 02 ldaa 2,x 2818 e2ef 3c pshx 2819 e2f0 ce 9f c8 ldx #rtc_reg_mo1 2820 e2f3 bd e3 25 jsr rtc_write_8bit 2821 e2f6 38 pulx 2822 ;;; Set DAY 2823 e2f7 a6 03 ldaa 3,x 2824 e2f9 3c pshx 2825 e2fa ce 9f c6 ldx #rtc_reg_d1 2826 e2fd bd e3 25 jsr rtc_write_8bit 2827 e300 38 pulx 2828 ;;; Set HOURS 2829 e301 a6 04 ldaa 4,x 2830 e303 3c pshx 2831 e304 ce 9f c4 ldx #rtc_reg_h1 2832 e307 bd e3 25 jsr rtc_write_8bit 2833 e30a 38 pulx 2834 ;;; Set MINUTES 2835 e30b a6 05 ldaa 5,x 2836 e30d 3c pshx 2837 e30e ce 9f c2 ldx #rtc_reg_mi1 2838 e311 bd e3 25 jsr rtc_write_8bit 2839 e314 38 pulx 2840 ;;; Set SECONDS 2841 e315 a6 06 ldaa 6,x 2842 e317 3c pshx 2843 e318 ce 9f c0 ldx #rtc_reg_s1 2844 e31b bd e3 25 jsr rtc_write_8bit 2845 e31e 38 pulx 2846 ;;; Start RTC 2847 e31f 86 04 ldaa #$04 2848 e321 b7 9f cf staa rtc_reg_cf 2849 e324 39 rts 2850 ;;; Helper funtion to assemble two RTC nibs to one byte 2851 rtc_write_8bit: 2852 e325 37 pshb 2853 e326 16 tab 2854 e327 44 lsra 2855 e328 44 lsra 2856 e329 44 lsra 2857 e32a 44 lsra 2858 e32b a7 01 staa 1,x 2859 e32d c4 0f andb #$0f 2860 e32f e7 00 stab 0,x 2861 e331 33 pulb 2862 e332 39 rts 2863 2864 ;;; 2865 ;;; Update ram_time 2866 ;;; 2867 update_ram_time: 2868 e333 86 47 ldaa #$47 2869 e335 bb bf f8 adda ram_time+0 2870 e338 bb bf f9 adda ram_time+1 2871 e33b bb bf fa adda ram_time+2 2872 e33e bb bf fb adda ram_time+3 2873 e341 bb bf fc adda ram_time+4 2874 e344 bb bf fd adda ram_time+5 2875 e347 bb bf fe adda ram_time+6 2876 e34a b1 bf ff cmpa ram_time+7 2877 e34d 26 21 bne ram_time_fail 2878 2879 e34f ce bf f8 ldx #ram_time 2880 e352 bd e2 53 jsr rtc_get_time 2881 e355 86 47 ldaa #$47 2882 e357 bb bf f8 adda ram_time+0 2883 e35a bb bf f9 adda ram_time+1 2884 e35d bb bf fa adda ram_time+2 2885 e360 bb bf fb adda ram_time+3 2886 e363 bb bf fc adda ram_time+4 2887 e366 bb bf fd adda ram_time+5 2888 e369 bb bf fe adda ram_time+6 2889 e36c b7 bf ff staa ram_time+7 2890 e36f 39 rts 2891 ram_time_fail: 2892 e370 ce d0 a2 ldx #txt_time_not_set 2893 e373 bd d7 36 jsr print_string 2894 e376 39 rts 2895 2896 ;;; 2897 ;;; Program variables 2898 ;;; 2899 bc00 org $bc00 ; beginning of OS RAM 2900 bc00 beg_of_vars: equ * ; beginning of variables 2901 bc00 media_addr_3: rmb 1 ; sector address MSB 2902 bc01 media_addr_2: rmb 1 ; sector address 2903 bc02 media_addr_1: rmb 1 ; sector address 2904 bc03 media_addr_0: rmb 1 ; sector address LSB 2905 bc04 volume_beg: rmb 2 ; first sector of volume 2906 bc06 volume_end: rmb 2 ; last sector of volume 2907 bc08 alloc_beg: rmb 2 ; first sector of allocation table 2908 bc0a alloc_end: rmb 2 ; last sector of allocation table 2909 bc0c root_dir_beg: rmb 2 ; first sector of root directory 2910 bc0e root_dir_end: rmb 2 ; last sector of root directory 2911 bc10 wrk_dir_beg: rmb 2 ; first sector of work directory 2912 bc12 wrk_dir_end: rmb 2 ; last sector of work directory 2913 bc14 wrk_path: rmb 128 ; path to work directory 2914 bc93 wrk_path_end: equ *-1 ; end of work dir path 2915 bc94 cur_dir_beg: rmb 2 ; first sector of current directory 2916 bc96 cur_dir_end: rmb 2 ; last sector of current directory 2917 bc98 cur_file_beg: rmb 2 ; first sector of current file 2918 bc9a cur_file_end: rmb 2 ; last sector of current file 2919 bc9c cur_file_saddr: rmb 2 ; first address of current file 2920 bc9e cur_file_eaddr: rmb 2 ; last address of current file 2921 bca0 line_buffer: rmb 64 ; console line buffer 2922 bcdf line_end: equ *-1 ; end of console line buffer 2923 bce0 line_pointer: rmb 2 ; pointer whitin line_buffer 2924 bce2 arg_pointer: rmb 2 ; pointer to command argument 2925 bce4 ext_fcb: rmb 2 ; pointer or external file control block 2926 bce6 temp: rmb 1 ; temporary storage 2927 bce7 xtemp: rmb 2 ; temporary storage 2928 bce9 xtemp2: rmb 2 ; temporary storage 2929 bcea end_of_vars: equ *-1 ; end of variables 2930 bceb var_checksum: rmb 1 ; variable checksum 2931 2932 ;;; 2933 ;;; Sector buffer 2934 ;;; 2935 sector_buffer: 2936 bcec rmb 512 2937 2938 ;;; 2939 ;;; RAM time stamp with checksum 2940 ;;; 2941 bff8 org $bff8 2942 ram_time: 2943 bff8 rmb 7 ; ISO 8601 time stamp 2944 bfff rmb 1 ; Time stamp checksum 2945 2946 ;;; 2947 ;;; Volume header pointers 2948 ;;; 2949 bcec org sector_buffer 2950 bcec vol_magic: rmb 4 ; file system ID = "MCFS" 2951 bcf0 vol_version: rmb 1 ; file system version = $02 2952 bcf1 vol_beg: rmb 2 ; first sector of partition 2953 bcf3 vol_end: rmb 2 ; last sector of partition 2954 bcf5 vol_id: rmb 2 ; volume ID 2955 bcf7 vol_name: rmb 32 ; volume label (zero terminated) 2956 bd17 vol_alloc_beg: rmb 2 ; first sector of allocation table 2957 bd19 vol_alloc_end: rmb 2 ; last sector of allocation table (up to 16 sectors) 2958 bd1b vol_root_beg: rmb 2 ; first sector of root dir 2959 bd1d vol_root_end: rmb 2 ; last sector of root dir 2960 2961 2962 ;;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 2963 ;;; Definition of volume header - first sector of file system 2964 ;;; 2965 ;;; 4 byte - file system magic ID = "MCFS" 2966 ;;; 1 byte - file system version = $02 2967 ;;; 2 byte - first sector of partition 2968 ;;; 2 byte - last sector of partition 2969 ;;; 2 byte - volume ID 2970 ;;; 32 byte - volume label (zero terminated) 2971 ;;; 2 byte - first sector of allocation table 2972 ;;; 2 byte - last sector of allocation table 2973 ;;; 2 byte - first sector of root dir 2974 ;;; 2 byte - last sector of root dir 2975 2976 2977 ;;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 2978 ;;; Definition of directry entry - 64 bytes each / 8 per sector (only 48 bytes used, rest is zero) 2979 ;;; (Timestamp is ISO 8601) 2980 ;;; 2981 ;;; 1 byte - flags [INUSE DIR FILE 0 0 0 X W R] (initially set to $00 for empty entry. DIR & FILE can not both be set) 2982 ;;; 2 byte - first sector 2983 ;;; 2 byte - last sector 2984 ;;; 4 byte - size 2985 ;;; 2 byte - date year (BCD) 2986 ;;; 1 byte - date month (BCD) 2987 ;;; 1 byte - date day (BCD) 2988 ;;; 1 byte - time hours (BCD) 2989 ;;; 1 byte - time minutes (BCD) 2990 ;;; 1 byte - time seconds (BCD) 2991 ;;; 32 byte - name (zero terminated) 2992 ;;; 16 byte - reserved for future use, set to zero 2993 2994 2995 ;;; # # # # # # # # # # # # # # # # # # # 2996 ;;; Definition of executable file format 2997 ;;; 2998 ;;; 2 byte - magic number = $4700 2999 ;;; 2 byte - load address 3000 ;;; 2 byte - entry address 3001 ;;; n byte - program data 3002 3003 3004 ;;; # # # # # # # # # # # # # # # # 3005 ;;; Definition of command blocks 3006 ;;; 3007 ;;; # # # # # # # # # # 3008 ;;; Check file entry 3009 ;;; 3010 ;;; 1 byte - command $01 3011 ;;; 1 byte - error code 3012 ;;; 2 byte - pointer to null terminated file name 3013 ;;; 1 byte - file flags [INUSE DIR FILE 0 0 0 X W R] 3014 ;;; 2 byte - number of sectors 3015 ;;; 4 byte - file size 3016 ;;; 2 byte - entry date year 3017 ;;; 1 byte - entry date month 3018 ;;; 1 byte - entry date day 3019 ;;; 1 byte - entry time hours 3020 ;;; 1 byte - entry time minutes 3021 ;;; 1 byte - entry time seconds 3022 ;;; 3023 ;;; # # # # # # # # # # 3024 ;;; Rename file 3025 ;;; 3026 ;;; 1 byte - command $07 3027 ;;; 1 byte - error code 3028 ;;; 2 byte - pointer to null terminated file name - from 3029 ;;; 2 byte - pointer to null terminated file name - to 3030 ;;; 3031 ;;; # # # # # # # # # # 3032 ;;; Delete file 3033 ;;; 3034 ;;; 1 byte - command $08 3035 ;;; 1 byte - error code 3036 ;;; 2 byte - pointer to null terminated file name 3037 ;;; 3038 ;;; # # # # # # 3039 ;;; Load file 3040 ;;; 3041 ;;; 1 byte - command $10 3042 ;;; 1 byte - error code 3043 ;;; 2 byte - pointer to null terminated file name 3044 ;;; 2 byte - destination address 3045 ;;; 3046 ;;; # # # # # # # # # # 3047 ;;; Load file sector 3048 ;;; 3049 ;;; 1 byte - command $11 3050 ;;; 1 byte - error code 3051 ;;; 2 byte - pointer to null terminated file name 3052 ;;; 2 byte - destination address 3053 ;;; 2 byte - sector to load (from zero to end of file) 3054 ;;; 3055 ;;; # # # # # # 3056 ;;; Save file 3057 ;;; 3058 ;;; 1 byte - command $20 3059 ;;; 1 byte - error code 3060 ;;; 2 byte - pointer to null terminated file name 3061 ;;; 2 byte - begin address 3062 ;;; 2 byte - end address 3063 ;;; 1 byte - file flags [0 0 0 0 0 0 X W R] 3064 ;;; 3065 ;;; # # # # # # # # # # 3066 ;;; (Save file sector) 3067 ;;; 3068 ;;; 1 byte - command $21 3069 ;;; 1 byte - error code 3070 ;;; 2 byte - pointer to null terminated file name 3071 ;;; 2 byte - source address 3072 ;;; 2 byte - sector to save (from zero to end of file) 3073 ;;; Number of errors 0