<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.amstrad-cpc.net/index.php?action=history&amp;feed=atom&amp;title=Programming%3AA_simple_disc_copier_using_BDOS_functions</id>
	<title>Programming:A simple disc copier using BDOS functions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.amstrad-cpc.net/index.php?action=history&amp;feed=atom&amp;title=Programming%3AA_simple_disc_copier_using_BDOS_functions"/>
	<link rel="alternate" type="text/html" href="https://wiki.amstrad-cpc.net/index.php?title=Programming:A_simple_disc_copier_using_BDOS_functions&amp;action=history"/>
	<updated>2026-09-04T00:10:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.amstrad-cpc.net/index.php?title=Programming:A_simple_disc_copier_using_BDOS_functions&amp;diff=35579&amp;oldid=prev</id>
		<title>CPCLER at 20:39, 13 March 2007</title>
		<link rel="alternate" type="text/html" href="https://wiki.amstrad-cpc.net/index.php?title=Programming:A_simple_disc_copier_using_BDOS_functions&amp;diff=35579&amp;oldid=prev"/>
		<updated>2007-03-13T20:39:38Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 20:39, 13 March 2007&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l832&quot;&gt;Line 832:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 832:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;.data_buffer equ $+1&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;.data_buffer equ $+1&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Programming]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>CPCLER</name></author>
	</entry>
	<entry>
		<id>https://wiki.amstrad-cpc.net/index.php?title=Programming:A_simple_disc_copier_using_BDOS_functions&amp;diff=35578&amp;oldid=prev</id>
		<title>CPCLER at 07:38, 13 March 2007</title>
		<link rel="alternate" type="text/html" href="https://wiki.amstrad-cpc.net/index.php?title=Programming:A_simple_disc_copier_using_BDOS_functions&amp;diff=35578&amp;oldid=prev"/>
		<updated>2007-03-13T07:38:50Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
;; A simple disc copier which uses the BDOS functions.&lt;br /&gt;
;;&lt;br /&gt;
;; This example shows the correct method to access the BDOS functions.&lt;br /&gt;
;; This copier will work on CPC &amp;amp; CPC+.&lt;br /&gt;
;;&lt;br /&gt;
;; Copier supports:&lt;br /&gt;
;; - Vendor and Data format discs ONLY&lt;br /&gt;
;; - 40 track disc drive ONLY&lt;br /&gt;
;; - single sided disc drive ONLY&lt;br /&gt;
;;&lt;br /&gt;
;; Copyprotected discs can&amp;#039;t be copied using this program!&lt;br /&gt;
;; &lt;br /&gt;
&lt;br /&gt;
org &amp;amp;2000&lt;br /&gt;
nolist&lt;br /&gt;
write&amp;quot;copy.bin&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------------------------&lt;br /&gt;
;; operating system functions used&lt;br /&gt;
&lt;br /&gt;
.kl_find_command equ &amp;amp;bcd4&lt;br /&gt;
.txt_output equ &amp;amp;bb5a&lt;br /&gt;
.bdos_set_message equ 1&lt;br /&gt;
.bdos_read_sector equ 4&lt;br /&gt;
.bdos_write_sector equ 5&lt;br /&gt;
.bdos_format equ 6&lt;br /&gt;
.bdos_move_track equ 7&lt;br /&gt;
.bdos_set_retry_count equ 9&lt;br /&gt;
.bdos_get_status equ 8&lt;br /&gt;
.km_read_char equ &amp;amp;bb09&lt;br /&gt;
.km_wait_char equ &amp;amp;bb06&lt;br /&gt;
.bdos_select_format equ 3&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------------------------&lt;br /&gt;
;; offsets into our data buffer for our variables &lt;br /&gt;
&lt;br /&gt;
.SOURCE_DRIVE equ 0&lt;br /&gt;
.DEST_DRIVE equ 1&lt;br /&gt;
.SECTOR_ID equ 2&lt;br /&gt;
.TRACK equ 3&lt;br /&gt;
.CUR_TRACK equ 4&lt;br /&gt;
.CUR_SECTOR equ 5&lt;br /&gt;
.DATA_PTR equ 6&lt;br /&gt;
.PREV_SET_MESSAGE equ 7&lt;br /&gt;
.PREV_RETRY equ 8&lt;br /&gt;
.NUM_TRACKS equ 9&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;=====================================================================&lt;br /&gt;
;; start of copy program&lt;br /&gt;
&lt;br /&gt;
.copy&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; search for commands required for copy&lt;br /&gt;
;;&lt;br /&gt;
;; this is the correct method and will work with CPC and CPC+&lt;br /&gt;
&lt;br /&gt;
ld hl,disc_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
&lt;br /&gt;
;; get address of commands&lt;br /&gt;
ld hl,read_sector_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (read_sector_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (read_sector_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,write_sector_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (write_sector_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (write_sector_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,format_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (format_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (format_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,select_format_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (select_format_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (select_format_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,move_track_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (move_track_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (move_track_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,set_retry_count_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (set_retry_count_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (set_retry_count_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
ld hl,set_message_command&lt;br /&gt;
call kl_find_command&lt;br /&gt;
ret nc&lt;br /&gt;
ld (set_message_cmd_data),hl&lt;br /&gt;
ld a,c&lt;br /&gt;
ld (set_message_cmd_data+2),a&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
ld ix,copy_data&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; get source drive&lt;br /&gt;
&lt;br /&gt;
;; display source drive question&lt;br /&gt;
ld hl,source_drive_txt&lt;br /&gt;
call print&lt;br /&gt;
ld hl,drive_txt&lt;br /&gt;
call print&lt;br /&gt;
&lt;br /&gt;
;; ask user to select drive&lt;br /&gt;
call get_drive&lt;br /&gt;
ld (ix+SOURCE_DRIVE),c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; get dest drive&lt;br /&gt;
&lt;br /&gt;
ld hl,dest_drive_txt&lt;br /&gt;
call print&lt;br /&gt;
ld hl,drive_txt&lt;br /&gt;
call print&lt;br /&gt;
&lt;br /&gt;
;; ask user to select drive&lt;br /&gt;
call get_drive&lt;br /&gt;
ld (ix+DEST_DRIVE),c&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; display insert message(s)&lt;br /&gt;
&lt;br /&gt;
;; display message to insert disc into source drive&lt;br /&gt;
call source_drive_msg&lt;br /&gt;
call crlf&lt;br /&gt;
&lt;br /&gt;
;; same drive used as source and destination?&lt;br /&gt;
ld a,(ix+SOURCE_DRIVE)&lt;br /&gt;
cp (ix+DEST_DRIVE)&lt;br /&gt;
jr z,copy2&lt;br /&gt;
&lt;br /&gt;
;; different drives used as source and destination&lt;br /&gt;
;; display message to insert disc into destination drive&lt;br /&gt;
call dest_drive_msg&lt;br /&gt;
call crlf&lt;br /&gt;
.copy2&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; display ready message&lt;br /&gt;
&lt;br /&gt;
;; display ready text&lt;br /&gt;
ld hl,ready_txt&lt;br /&gt;
call print&lt;br /&gt;
call flush_keyboard&lt;br /&gt;
call km_wait_char&lt;br /&gt;
&lt;br /&gt;
call crlf&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; I have disabled messages and setup a high retry count&lt;br /&gt;
;; so that if there are any errors on the disc, they will&lt;br /&gt;
;; be retried without user intervention.&lt;br /&gt;
&lt;br /&gt;
;; disable display of messages &lt;br /&gt;
ld a,0&lt;br /&gt;
call do_set_message&lt;br /&gt;
;; store old state&lt;br /&gt;
ld (ix+PREV_SET_MESSAGE),a&lt;br /&gt;
&lt;br /&gt;
;; set retry count&lt;br /&gt;
ld a,255&lt;br /&gt;
call do_set_retry_count&lt;br /&gt;
;; store old state&lt;br /&gt;
ld (ix+PREV_RETRY),a&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; detect the format of the disc&lt;br /&gt;
;; will only detect vendor or data formats.&lt;br /&gt;
call detect_format&lt;br /&gt;
jr c,copy5&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; format could not be detected&lt;br /&gt;
ld hl,not_standard_format_txt&lt;br /&gt;
call print&lt;br /&gt;
&lt;br /&gt;
;; quit copy&lt;br /&gt;
ld hl,copy_failed_txt&lt;br /&gt;
call print&lt;br /&gt;
jp exit&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; format was detected&lt;br /&gt;
.copy5&lt;br /&gt;
;; store first sector ID of the format detected&lt;br /&gt;
ld (ix+SECTOR_ID),a&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; select format for source drive&lt;br /&gt;
;; -this will setup the XDPB for the destination drive&lt;br /&gt;
;; -XDPB parameters used by FORMAT and READ/WRITE commands&lt;br /&gt;
&lt;br /&gt;
ld a,(ix+SECTOR_ID)&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
call do_select_format&lt;br /&gt;
&lt;br /&gt;
;; source and destination different?&lt;br /&gt;
ld a,(ix+SOURCE_DRIVE)&lt;br /&gt;
cp (ix+DEST_DRIVE)&lt;br /&gt;
jr z,copy6&lt;br /&gt;
&lt;br /&gt;
;; source and destination are different&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; select format for destination drive&lt;br /&gt;
;; -this will setup the XDPB for the destination drive&lt;br /&gt;
;; -XDPB parameters used by FORMAT and READ/WRITE commands&lt;br /&gt;
&lt;br /&gt;
ld a,(ix+SECTOR_ID)&lt;br /&gt;
ld e,(ix+DEST_DRIVE)&lt;br /&gt;
call do_select_format&lt;br /&gt;
&lt;br /&gt;
.copy6&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
xor a       ;; initial track&lt;br /&gt;
ld (ix+TRACK),a&lt;br /&gt;
&lt;br /&gt;
.copy_disc&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; calculate number of tracks to read/write/format in one go&lt;br /&gt;
;; 7 is the maximum number of tracks to read at one time&lt;br /&gt;
;; because of the limited buffer space&lt;br /&gt;
&lt;br /&gt;
ld a,40&lt;br /&gt;
sub (ix+TRACK)&lt;br /&gt;
cp 7&lt;br /&gt;
jr c,cd3&lt;br /&gt;
ld a,7       ;; maximum number of tracks at one time&lt;br /&gt;
.cd3&lt;br /&gt;
ld (ix+NUM_TRACKS),a&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; read up to 7 tracks of data into the buffer&lt;br /&gt;
&lt;br /&gt;
call read_tracks&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; display message to insert disc if source drive&lt;br /&gt;
;; is the same as the dest drive&lt;br /&gt;
&lt;br /&gt;
;; source same as dest?&lt;br /&gt;
ld a,(ix+SOURCE_DRIVE)&lt;br /&gt;
cp (ix+DEST_DRIVE)&lt;br /&gt;
jr nz,cd2&lt;br /&gt;
&lt;br /&gt;
call clear&lt;br /&gt;
ld hl,insert_dest_txt&lt;br /&gt;
call print&lt;br /&gt;
ld hl,press_key_txt&lt;br /&gt;
call print&lt;br /&gt;
call flush_keyboard&lt;br /&gt;
call km_wait_char&lt;br /&gt;
&lt;br /&gt;
.cd2&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; format and then write the data of the tracks we read&lt;br /&gt;
call write_tracks&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; - store index of last track written (ready for next read)&lt;br /&gt;
;; - test if the last track written is the last track to write&lt;br /&gt;
&lt;br /&gt;
ld a,(ix+CUR_TRACK)&lt;br /&gt;
ld (ix+TRACK),a&lt;br /&gt;
cp 40&lt;br /&gt;
jr z,cd5&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------------------------&lt;br /&gt;
;; display message to insert disc if source drive&lt;br /&gt;
;; is the same as the dest drive&lt;br /&gt;
&lt;br /&gt;
;; source same as dest?&lt;br /&gt;
ld a,(ix+SOURCE_DRIVE)&lt;br /&gt;
cp (ix+DEST_DRIVE)&lt;br /&gt;
jr nz,copy_disc						;; if source is not the same as dest, continue to copy&lt;br /&gt;
&lt;br /&gt;
;; display message&lt;br /&gt;
call clear&lt;br /&gt;
ld hl,insert_source_txt&lt;br /&gt;
call print&lt;br /&gt;
ld hl,press_key_txt&lt;br /&gt;
call print&lt;br /&gt;
call flush_keyboard&lt;br /&gt;
call km_wait_char&lt;br /&gt;
&lt;br /&gt;
;; continue copying&lt;br /&gt;
jr copy_disc&lt;br /&gt;
&lt;br /&gt;
.cd5&lt;br /&gt;
ld hl,copy_complete_txt&lt;br /&gt;
call print&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------&lt;br /&gt;
;; restore parameters that were changed&lt;br /&gt;
&lt;br /&gt;
.exit&lt;br /&gt;
;; restore message display state&lt;br /&gt;
ld a,(ix+PREV_SET_MESSAGE)&lt;br /&gt;
call do_set_message&lt;br /&gt;
&lt;br /&gt;
;; restore retry count&lt;br /&gt;
ld a,(ix+PREV_RETRY)&lt;br /&gt;
call do_set_retry_count&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------&lt;br /&gt;
;; remove all characters from keyboard input buffer&lt;br /&gt;
&lt;br /&gt;
.flush_keyboard&lt;br /&gt;
call km_read_char&lt;br /&gt;
jr nc,flush_keyboard&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;------------------------------------&lt;br /&gt;
;; Exit: C = drive index&lt;br /&gt;
&lt;br /&gt;
.get_drive&lt;br /&gt;
;; remove keys from keyboard buffer&lt;br /&gt;
call flush_keyboard&lt;br /&gt;
;; wait for next character from keyboard&lt;br /&gt;
call km_wait_char&lt;br /&gt;
;; convert to upper case&lt;br /&gt;
and &amp;amp;df&lt;br /&gt;
cp &amp;quot;A&amp;quot;&lt;br /&gt;
ld c,0&lt;br /&gt;
jr z,gd2&lt;br /&gt;
cp &amp;quot;B&amp;quot;&lt;br /&gt;
ld c,1&lt;br /&gt;
jr z,gd2&lt;br /&gt;
;; error (beep)&lt;br /&gt;
ld a,7&lt;br /&gt;
call txt_output&lt;br /&gt;
jr get_drive&lt;br /&gt;
.gd2&lt;br /&gt;
call txt_output&lt;br /&gt;
call crlf&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;-------------------------&lt;br /&gt;
;; clear the current line&lt;br /&gt;
&lt;br /&gt;
.clear&lt;br /&gt;
ld a,13&lt;br /&gt;
call txt_output&lt;br /&gt;
ld a,18&lt;br /&gt;
call txt_output&lt;br /&gt;
ld a,13&lt;br /&gt;
call txt_output&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;-------------------------&lt;br /&gt;
;; display CR,LF control codes (go to next line)&lt;br /&gt;
.crlf&lt;br /&gt;
ld a,13&lt;br /&gt;
call txt_output&lt;br /&gt;
ld a,10&lt;br /&gt;
call txt_output&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;-------------------------&lt;br /&gt;
;; display message to &amp;quot;Insert SOURCE disc into drive x&amp;quot;&lt;br /&gt;
.source_drive_msg&lt;br /&gt;
ld hl,insert_source_txt&lt;br /&gt;
ld a,(ix+SOURCE_DRIVE)&lt;br /&gt;
jr insert2&lt;br /&gt;
&lt;br /&gt;
;;-------------------------&lt;br /&gt;
;; display message to &amp;quot;Insert DEST disc into drive x&amp;quot;&lt;br /&gt;
.dest_drive_msg&lt;br /&gt;
ld hl,insert_dest_txt&lt;br /&gt;
ld a,(ix+DEST_DRIVE)&lt;br /&gt;
.insert2&lt;br /&gt;
push af&lt;br /&gt;
call print&lt;br /&gt;
pop af&lt;br /&gt;
add a,&amp;quot;A&amp;quot;&lt;br /&gt;
call txt_output&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;-------------------------------------&lt;br /&gt;
;; display a message starting at memory address pointed to by HL. &lt;br /&gt;
;; (message is terminated with 0 character)&lt;br /&gt;
&lt;br /&gt;
.print&lt;br /&gt;
ld a,(hl)&lt;br /&gt;
inc hl&lt;br /&gt;
or a&lt;br /&gt;
ret z&lt;br /&gt;
call txt_output&lt;br /&gt;
jr print&lt;br /&gt;
&lt;br /&gt;
;;-------------------------------------&lt;br /&gt;
;; these functions handle the BDOS functions&lt;br /&gt;
;; using the address of the command that was found at initialisation&lt;br /&gt;
;; time&lt;br /&gt;
&lt;br /&gt;
.do_set_retry_count&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw set_retry_count_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
.do_move_track&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw move_track_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
.do_format&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw format_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
.do_select_format&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw select_format_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
.do_read&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw read_sector_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.do_write&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw write_sector_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
.do_set_message&lt;br /&gt;
push ix&lt;br /&gt;
rst 3&lt;br /&gt;
defw set_message_cmd_data&lt;br /&gt;
pop ix&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; detect the format of the disc from track 0 &lt;br /&gt;
;; of source disc&lt;br /&gt;
&lt;br /&gt;
.detect_format&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
call do_move_track&lt;br /&gt;
&lt;br /&gt;
;; attempt to read the first sector of a data formatted&lt;br /&gt;
;; disc&lt;br /&gt;
ld hl,data_buffer&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
ld c,&amp;amp;c1&lt;br /&gt;
call do_read&lt;br /&gt;
ld a,&amp;amp;c1&lt;br /&gt;
ret c&lt;br /&gt;
&lt;br /&gt;
;; attempt to read the first sector of a system formatted&lt;br /&gt;
;; disc&lt;br /&gt;
ld hl,data_buffer&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
ld c,&amp;amp;41&lt;br /&gt;
call do_read&lt;br /&gt;
ld a,&amp;amp;41&lt;br /&gt;
ret c&lt;br /&gt;
or a&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; format current track&lt;br /&gt;
&lt;br /&gt;
.format_track&lt;br /&gt;
&lt;br /&gt;
;; initialise format data&lt;br /&gt;
ld hl,format_data&lt;br /&gt;
push hl&lt;br /&gt;
ld b,9&lt;br /&gt;
ld a,(ix+SECTOR_ID)&lt;br /&gt;
ld c,(ix+CUR_TRACK)&lt;br /&gt;
.ft2 &lt;br /&gt;
ld (hl),c&lt;br /&gt;
inc hl&lt;br /&gt;
ld (hl),0&lt;br /&gt;
inc hl&lt;br /&gt;
ld (hl),a&lt;br /&gt;
inc hl&lt;br /&gt;
ld (hl),2&lt;br /&gt;
inc hl&lt;br /&gt;
inc a&lt;br /&gt;
djnz ft2&lt;br /&gt;
pop hl&lt;br /&gt;
&lt;br /&gt;
;; do the format&lt;br /&gt;
ld e,(ix+DEST_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
call do_format&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; write data to all sectors on current track&lt;br /&gt;
&lt;br /&gt;
.write_track&lt;br /&gt;
ld b,9&lt;br /&gt;
ld a,(ix+SECTOR_ID)&lt;br /&gt;
.wt1 push bc&lt;br /&gt;
push af&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; write data&lt;br /&gt;
ld l,(ix+DATA_PTR)&lt;br /&gt;
ld h,(ix+DATA_PTR+1)&lt;br /&gt;
ld e,(ix+DEST_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
ld c,a&lt;br /&gt;
call do_write&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; update data pointer&lt;br /&gt;
ld l,(ix+DATA_PTR)&lt;br /&gt;
ld h,(ix+DATA_PTR+1)&lt;br /&gt;
ld bc,512&lt;br /&gt;
add hl,bc&lt;br /&gt;
ld (ix+DATA_PTR),l&lt;br /&gt;
ld (ix+DATA_PTR+1),h&lt;br /&gt;
&lt;br /&gt;
pop af&lt;br /&gt;
pop bc&lt;br /&gt;
inc a&lt;br /&gt;
djnz wt1&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; format and write multiple tracks&lt;br /&gt;
&lt;br /&gt;
.write_tracks&lt;br /&gt;
ld a,(ix+TRACK)&lt;br /&gt;
ld (ix+CUR_TRACK),a&lt;br /&gt;
&lt;br /&gt;
ld hl,data_buffer&lt;br /&gt;
ld (ix+DATA_PTR),l&lt;br /&gt;
ld (ix+DATA_PTR+1),h&lt;br /&gt;
&lt;br /&gt;
ld b,(ix+NUM_TRACKS)&lt;br /&gt;
.wts1&lt;br /&gt;
push bc&lt;br /&gt;
&lt;br /&gt;
;; move to track&lt;br /&gt;
ld e,(ix+DEST_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
call do_move_track&lt;br /&gt;
&lt;br /&gt;
;; format it&lt;br /&gt;
ld hl,format_track_txt&lt;br /&gt;
call print&lt;br /&gt;
call disp_track&lt;br /&gt;
&lt;br /&gt;
call format_track&lt;br /&gt;
&lt;br /&gt;
;; write it&lt;br /&gt;
ld hl,write_track_txt&lt;br /&gt;
call print&lt;br /&gt;
call disp_track&lt;br /&gt;
&lt;br /&gt;
call write_track&lt;br /&gt;
&lt;br /&gt;
;; increment track number&lt;br /&gt;
inc (ix+CUR_TRACK)&lt;br /&gt;
&lt;br /&gt;
pop bc&lt;br /&gt;
djnz wts1&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; read data from all sectors on current track&lt;br /&gt;
&lt;br /&gt;
.read_track&lt;br /&gt;
ld b,9&lt;br /&gt;
ld a,(ix+SECTOR_ID)&lt;br /&gt;
.rt1 push bc&lt;br /&gt;
push af&lt;br /&gt;
&lt;br /&gt;
ld l,(ix+DATA_PTR)&lt;br /&gt;
ld h,(ix+DATA_PTR+1)&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
ld c,a&lt;br /&gt;
call do_read&lt;br /&gt;
&lt;br /&gt;
;; update pointer for size of data&lt;br /&gt;
ld l,(ix+DATA_PTR)&lt;br /&gt;
ld h,(ix+DATA_PTR+1)&lt;br /&gt;
ld bc,512&lt;br /&gt;
add hl,bc&lt;br /&gt;
ld (ix+DATA_PTR),l&lt;br /&gt;
ld (ix+DATA_PTR+1),h&lt;br /&gt;
&lt;br /&gt;
pop af&lt;br /&gt;
pop bc&lt;br /&gt;
inc a&lt;br /&gt;
djnz rt1&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; read multiple tracks&lt;br /&gt;
&lt;br /&gt;
.read_tracks&lt;br /&gt;
ld a,(ix+TRACK)&lt;br /&gt;
ld (ix+CUR_TRACK),a&lt;br /&gt;
&lt;br /&gt;
ld hl,data_buffer&lt;br /&gt;
ld (ix+DATA_PTR),l&lt;br /&gt;
ld (ix+DATA_PTR+1),h&lt;br /&gt;
&lt;br /&gt;
ld b,(ix+NUM_TRACKS)&lt;br /&gt;
.rts1&lt;br /&gt;
push bc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ld hl,read_track_txt&lt;br /&gt;
call print&lt;br /&gt;
call disp_track&lt;br /&gt;
&lt;br /&gt;
ld e,(ix+SOURCE_DRIVE)&lt;br /&gt;
ld d,(ix+CUR_TRACK)&lt;br /&gt;
call do_move_track&lt;br /&gt;
&lt;br /&gt;
call read_track&lt;br /&gt;
&lt;br /&gt;
;; increment track number&lt;br /&gt;
inc (ix+CUR_TRACK)&lt;br /&gt;
&lt;br /&gt;
pop bc&lt;br /&gt;
djnz rts1&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; output the number of the current track to the screen&lt;br /&gt;
&lt;br /&gt;
.disp_track&lt;br /&gt;
ld a,(ix+CUR_TRACK)&lt;br /&gt;
call print_decimal&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
;; display a decimal number to the screen &lt;br /&gt;
&lt;br /&gt;
.print_decimal&lt;br /&gt;
ld e,1&lt;br /&gt;
ld b,100&lt;br /&gt;
call print_decimal_digit&lt;br /&gt;
ld b,10&lt;br /&gt;
call print_decimal_digit&lt;br /&gt;
dec e&lt;br /&gt;
ld b,1&lt;br /&gt;
&lt;br /&gt;
.print_decimal_digit&lt;br /&gt;
ld c,0&lt;br /&gt;
.dd&lt;br /&gt;
sub b&lt;br /&gt;
jr c,dd2&lt;br /&gt;
inc c&lt;br /&gt;
jr dd&lt;br /&gt;
.dd2&lt;br /&gt;
add a,b&lt;br /&gt;
push af&lt;br /&gt;
ld a,e&lt;br /&gt;
or a&lt;br /&gt;
ld a,c&lt;br /&gt;
jr z,dd4&lt;br /&gt;
or a&lt;br /&gt;
jr z,dd5&lt;br /&gt;
dec e&lt;br /&gt;
&lt;br /&gt;
.dd4&lt;br /&gt;
add a,&amp;quot;0&amp;quot;&lt;br /&gt;
call txt_output&lt;br /&gt;
.dd5&lt;br /&gt;
pop af&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
.disc_command&lt;br /&gt;
defb &amp;quot;DIS&amp;quot;,&amp;quot;C&amp;quot;+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.read_sector_command&lt;br /&gt;
defb bdos_read_sector+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.write_sector_command&lt;br /&gt;
defb bdos_write_sector+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.format_command&lt;br /&gt;
defb bdos_format+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.select_format_command&lt;br /&gt;
defb bdos_select_format+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.move_track_command&lt;br /&gt;
defb bdos_move_track+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.set_retry_count_command&lt;br /&gt;
defb bdos_set_retry_count+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
.set_message_command&lt;br /&gt;
defb bdos_set_message+&amp;amp;80&lt;br /&gt;
&lt;br /&gt;
;;-------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.format_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.read_sector_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.write_sector_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.select_format_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.move_track_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.set_retry_count_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
.set_message_cmd_data&lt;br /&gt;
defw 0&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
.source_drive_txt&lt;br /&gt;
defb &amp;quot;Source drive &amp;quot;,0&lt;br /&gt;
.dest_drive_txt&lt;br /&gt;
defb &amp;quot;Destination drive &amp;quot;,0&lt;br /&gt;
.drive_txt&lt;br /&gt;
defb &amp;quot;(A or B):&amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
.not_standard_format_txt&lt;br /&gt;
defb &amp;quot;The format of the source disc is not standard.&amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
.copy_failed_txt&lt;br /&gt;
defb 13,10,&amp;quot;Copy failed&amp;quot;,13,10,0&lt;br /&gt;
.copy_complete_txt&lt;br /&gt;
defb 13,10,&amp;quot;Copy complete&amp;quot;,13,10,0&lt;br /&gt;
&lt;br /&gt;
.insert_source_txt&lt;br /&gt;
defb &amp;quot;Insert SOURCE disc into drive &amp;quot;,0&lt;br /&gt;
.insert_dest_txt&lt;br /&gt;
defb &amp;quot;Insert DEST disc into drive &amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
.ready_txt&lt;br /&gt;
defb &amp;quot;Press any key to start copying&amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
.press_key_txt&lt;br /&gt;
defb &amp;quot; and press any key&amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
.read_track_txt&lt;br /&gt;
defb 13,18,13,&amp;quot;Reading   track &amp;quot;,0&lt;br /&gt;
.write_track_txt&lt;br /&gt;
defb 13,18,13,&amp;quot;Writing   track &amp;quot;,0&lt;br /&gt;
.format_track_txt&lt;br /&gt;
defb 13,18,13,&amp;quot;Formating track &amp;quot;,0&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
;; buffer for our variables&lt;br /&gt;
.copy_data&lt;br /&gt;
defs 16&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; temporary buffer used to store formatting data&lt;br /&gt;
&lt;br /&gt;
.format_data&lt;br /&gt;
defs 9*4&lt;br /&gt;
&lt;br /&gt;
;; the sector data is stored from this point onwards&lt;br /&gt;
;;&lt;br /&gt;
;; We read a maximum of 7 tracks, with a maximum of 512 bytes per sector and &lt;br /&gt;
;; a 9 sectors per track. This equates to 512*9*7 = 32256 bytes. There must&lt;br /&gt;
;; be enough space after the program to store this amount of data without&lt;br /&gt;
;; overwriting any system variables or the system jumpblock.&lt;br /&gt;
.data_buffer equ $+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>CPCLER</name></author>
	</entry>
</feed>