News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

A small correction and read/write perforamnce boost for Format disk routine

Started by ikonsgr, 16:41, 22 March 22

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ikonsgr

Hi,

I've made a small correction and a read/write performance tweak of the format disk routine presented here:
https://www.cpcwiki.eu/index.php/Programming:A_simple_disc_formatter_using_BDOS_functions

The new code is this:
;; 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

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

    ld    a,2        ;mode 2
    call    &bc0e
;;------------------------------------------
;; 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

;;------------------------------------------
start:

ld    a,(&1fff)
or    a
jr    z,dis_rom
ld    a,5
ld    bc,&fbd1
out    (c),a

dis_rom:
ld ix,data

;; display format question
ld hl,format_type_txt
call print

.copy2
call flush_keyboard
;call km_wait_char
and &df
cp "S"
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

jp    start
;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
or a
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
    ld    a,(ix+SECTOR_ID)
    cp    &c1
    jr    z,data_order
    ld    de,system_sector_order
    jr    cont_1
data_order:
    ld    de,data_sector_order
cont_1:
push hl
ld b,9
;ld a,(ix+SECTOR_ID)
    ld    a,(de)
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
    inc    de
    ld    a,(de)
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_type_txt
defb 13,10,"System or Data (S 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_sector_order
defb &C1,&C6,&C2,&C7,&C3,&C8,&C4,&C9,&C5

.system_sector_order
defb &41,&46,&42,&47,&43,&48,&44,&49,&45

.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

.data
defs 16

.format_data
defs 9*4

New code is presented with indentation, while old code is remarked with ';'
The corrected error is in the formatted cylinder  represantation, original code after track 9, showed: 19,11,12... or after 19 showed: 29,21,22.
The 2nd modification is for placing sectors in interleaved order instead of sequential. This would give much greater read & write speeds!  ;)
It might be a good idea to upload this into programming area.  :) 

eto

with a little modification, this program will return to basic, when pressing ESC:

cp #fc
ret z

.copy2
call flush_keyboard
;call km_wait_char
cp #fc
ret z
and &df
cp "S"
ld c,&41
jr z,copy3
cp "D"
ld c,&c1
jr z,copy3
ld a,7
call txt_output
jp copy2


Maybe also add it to the drive selection, then it's always safe to exit from this nice little tool.

ikonsgr

Nice mod, eto. I will update the code and add it to USIFAC II format command in the next update  :)

Fran123

I would like it uses a format like   |format,"<drive>","<format>"

eto

Quote from: ikonsgr on 22:44, 02 April 22Nice mod, eto. I will update the code and add it to USIFAC II format command in the next update  :)

I tried to save this as an executable binary. When I run the binary (run "format.bin"), the CPC resets.

With the debugger I see that kl_find_command does not find the command and the RET then leads to a RESET.

Do you know why kl_find_command does not find anything and what needs to be done differently, so that kl_find_command finds the commands?


(I am aware it's not possible to return to BASIC)

eto

Just one more thing: the keyboard-flush routine is actually a "wait for a keypress" routine. It does not clear the buffer.

e.g. when called from BASIC, it could be, that there are still keys in the buffer and the computer does the selections and formats the disc without the user requesting this. Problem is the "jr nc" in the flush routine. It should be "jr c" - and then the wait_char routine makes sense again, which is commented in your code, but not in the original on the Wiki.

Enter this line in BASIC and then hitting return, press s and b => after 3 seconds the machine code is executed and s and b will be recognized as they are still in the buffer.

print "press s and b in the next 3 seconds":for i=1 to 3000:next:call &2000

eto

Quote from: Fran123 on 20:24, 07 April 22I would like it uses a format like   |format,"<drive>","<format>"

What do you want to do with it? I was thinking about adding parameters first too, but then I didn't see where this is more convenient than being asked by the system - and has more risks to do mistakes. The only reason would be, if I will use it in my own program and the utility should run silently.

Fran123

Quote from: eto on 08:06, 08 April 22
Quote from: Fran123 on 20:24, 07 April 22I would like it uses a format like  |format,"<drive>","<format>"

What do you want to do with it? I was thinking about adding parameters first too, but then I didn't see where this is more convenient than being asked by the system - and has more risks to do mistakes. The only reason would be, if I will use it in my own program and the utility should run silently.

anyway, it would be an option.

In windows and linux you can do a lot of tasks with programs and commands

ikonsgr

@eto, what compiler did you use? I used winape's assembler and worked fine. Did you try the original source code too? Mind also, that in order to use the binary from basic, an amsdos header must be added to the binary file. I use cpcdiskxp for that ,by creating a dummy dsk image, add the binary into image,then cpcdiskxp program asks if i want to add header,i confirm, fill out start/execution address, and finally i extract the binary (with the amsdos header) from the dummy dsk image ;-)

eto

Quote from: ikonsgr on 00:34, 09 April 22@eto, what compiler did you use? I used winape's assembler and worked fine. Did you try the original source code too? Mind also, that in order to use the binary from basic, an amsdos header must be added to the binary file. I use cpcdiskxp for that ,by creating a dummy dsk image, add the binary into image,then cpcdiskxp program asks if i want to add header,i confirm, fill out start/execution address, and finally i extract the binary (with the amsdos header) from the dummy dsk image ;-)
I'm using WinApe too. I tried both with writing the BIN directly to disk and also to compile it to RAM and then do a save"format.bin",b,&start,&length,&start.
As long as I load it form BASIC and call &start, it works fine. But when I enter run"format.bin" it resets. I could see in the debugger, that when I run the bin directly, that the kl_find_command doesn't find anything. It works fine, when called from BASIC. 



Powered by SMFPacks Menu Editor Mod