Programming:A simple disc formatter using BDOS functions
From CPCWiki - THE Amstrad CPC encyclopedia!
;; A simple disc formatter which uses the BDOS functions. ;; ;; This example will work on CPC and CPC+. ;; ;; Format program supports: ;; - 40 track single sided disc drive ONLY ;; - Vendor and Data formats ONLY ;; ;; Comment Nworc, 23.02.2022: ;; This code is useful as a learning experience, but be careful not to use it in a productive environment, because ;; the formatting routine formats the sectors consecutively (e.g. C1 C2 C3 C4 ... for Data format). While this works, ;; read and write performance is poor on a disk with such a format, as the disk needs to spin 9 times to write a full ;; track instead of just 2 turns if the format would be interleaved. The format_track method need be changed to produce ;; an interleaved format (e.g. C1 C6 C2 C7 ... for Data format) in order to fix this. Changing that is a nice exercise. org &2000 nolist write"format.bin" ;;------------------------------------------ ;; operating system functions used .kl_find_command equ &bcd4 .txt_output equ &bb5a .bdos_set_message equ 1 .bdos_format equ 6 .bdos_move_track equ 7 .bdos_set_retry_count equ 9 .bdos_get_status equ 8 .bdos_select_format equ 3 .km_read_char equ &bb09 .km_wait_char equ &bb06 ;;------------------------------------------ ;; offsets into our data .DRIVE equ 0 .TRACK equ 1 .SECTOR_ID equ 2 ;;------------------------------------------ ;; search roms to find commands required for format ld hl,disc_command call kl_find_command ret nc ld hl,format_command call kl_find_command ret nc ld (format_cmd_data),hl ld a,c ld (format_cmd_data+2),a ld hl,select_format_command call kl_find_command ret nc ld (select_format_cmd_data),hl ld a,c ld (select_format_cmd_data+2),a ld hl,move_track_command call kl_find_command ret nc ld (move_track_cmd_data),hl ld a,c ld (move_track_cmd_data+2),a ld hl,set_retry_count_command call kl_find_command ret nc ld (set_retry_count_cmd_data),hl ld a,c ld (set_retry_count_cmd_data+2),a ld hl,set_message_command call kl_find_command ret nc ld (set_message_cmd_data),hl ld a,c ld (set_message_cmd_data+2),a ;;------------------------------------------ ld ix,data ;; display format question ld hl,format_type_txt call print .copy2 call flush_keyboard call km_wait_char and &df cp "V" ld c,&41 jr z,copy3 cp "D" ld c,&c1 jr z,copy3 ld a,7 call txt_output jp copy2 .copy3 call txt_output ld (ix+SECTOR_ID),c call crlf ;; display drive question ld hl,sel_drive_txt call print ld hl,drive_txt call print ;; ask user to select drive call get_drive ld (ix+DRIVE),c ld hl,insert_disc_txt call print ld a,(ix+DRIVE) add a,"A" call txt_output ld hl,any_key_txt call print call flush_keyboard call km_wait_char ;; select the format (initialises some of the XDPB parameters that are required ;; by the format function) ld a,(ix+SECTOR_ID) call do_select_format ;; do format ld b,40 xor a .format_disc ld (ix+TRACK),a push af push bc ld hl,format_track_txt call print call disp_track call format_track pop bc pop af inc a djnz format_disc ret ;;------------------------------------ ;; remove all characters from keyboard input buffer .flush_keyboard call km_read_char jr nc,flush_keyboard ret ;;------------------------------------ ;; Exit: C = drive index .get_drive ;; remove keys from keyboard buffer call flush_keyboard ;; wait for next character from keyboard call km_wait_char ;; convert to upper case and &df cp "A" ld c,0 jr z,gd2 cp "B" ld c,1 jr z,gd2 ;; error (beep) ld a,7 call txt_output jr get_drive .gd2 call txt_output call crlf ret ;;------------------------- ;; display CR,LF control codes (go to next line) .crlf ld a,13 call txt_output ld a,10 call txt_output ret ;;------------------------------------- ;; display a message starting at memory address pointed to by HL. ;; (message is terminated with 0 character) .print ld a,(hl) inc hl or a ret z call txt_output jr print ;;---------------------------------------------- ;; output the number of the current track to the screen .disp_track ld a,(ix+TRACK) call print_decimal ret ;;---------------------------------------------- ;; display a decimal number to the screen .print_decimal ld e,1 ld b,100 call print_decimal_digit ld b,10 call print_decimal_digit dec e ld b,1 .print_decimal_digit ld c,0 .dd sub b jr c,dd2 inc c jr dd .dd2 add a,b push af ld a,e or a ld a,c jr z,dd4 or a jr z,dd5 dec e .dd4 add a,"0" call txt_output .dd5 pop af ret ;;------------------------------------- .do_set_retry_count push ix rst 3 defw set_retry_count_cmd_data pop ix ret .do_move_track push ix rst 3 defw move_track_cmd_data pop ix ret .do_format push ix rst 3 defw format_cmd_data pop ix ret .do_select_format push ix rst 3 defw select_format_cmd_data pop ix ret .do_set_message push ix rst 3 defw set_message_cmd_data pop ix ret ;;---------------------------------------------- .format_track ;; setup format data ld hl,format_data push hl ld b,9 ld a,(ix+SECTOR_ID) ld c,(ix+TRACK) .wt1 ld (hl),c inc hl ld (hl),0 inc hl ld (hl),a inc hl ld (hl),2 inc hl inc a djnz wt1 pop hl ld e,(ix+DRIVE) ld d,(ix+TRACK) call do_move_track ld e,(ix+DRIVE) ld d,(ix+TRACK) call do_format ret ;;------------------------------------- .disc_command defb "DIS","C"+&80 .format_command defb bdos_format+&80 .select_format_command defb bdos_select_format+&80 .move_track_command defb bdos_move_track+&80 .set_retry_count_command defb bdos_set_retry_count+&80 .set_message_command defb bdos_set_message+&80 ;;------------------------------------- .format_cmd_data defw 0 defb 0 .select_format_cmd_data defw 0 defb 0 .move_track_cmd_data defw 0 defb 0 .set_retry_count_cmd_data defw 0 defb 0 .set_message_cmd_data defw 0 defb 0 ;;-------------------------------------- .format_type_txt defb "Vendor or Data (V or D):",0 .sel_drive_txt defb "Drive ",0 .drive_txt defb "(A or B):",0 .insert_disc_txt defb "Insert disc into drive ",0 .any_key_txt defb " and press any key",13,10,0 .format_track_txt defb 13,"Format track ",0 .data defs 16 .format_data defs 9*4