{"id":250,"date":"2008-11-24T00:13:56","date_gmt":"2008-11-24T00:13:56","guid":{"rendered":"http:\/\/tlindner.macmess.org\/?page_id=250"},"modified":"2020-04-25T17:09:39","modified_gmt":"2020-04-25T17:09:39","slug":"single-density-disks","status":"publish","type":"page","link":"https:\/\/tlindner.macmess.org\/?page_id=250","title":{"rendered":"Single Density Disks"},"content":{"rendered":"<p>Back in May of 2007 Philip Pemberton asked on the classic computer mailing list for some diagnostic information from single density floppy disks. He said he was building custom hardware to read floppy disks and needed some data.<\/p>\n<p>He was specifically looking for raw Catweasel output. The testhist command from cw2dmk can record this information to a file.<\/p>\n<p>This presented a opportunity for me. Though I didn&#8217;t own any single density disks I did own a computer that could create, read and write them. The CoCo hardware supported it, but I needed to modify the software to achieve it.<\/p>\n<p>The Color Computer floppy disk card by Tandy\/Radio Shack (and third party compatible cards) did have a density select register that it passed to the flopper disk controller. But that bit also controlled a second function in the card: the NMI enable flag. The card used the MPU&#8217;s NMI interrupt to signal the end of a disk operation. This, used in combination with a separate halt flag, allowed the CoCo&#8217;s read\/write software kernel to be very compact and fast. Fast enough to allow the CoCo to access double density disk&#8217;s reliably despite the 0.89 Mhz clock speed of the MPU.<\/p>\n<p>In double density\/Halt\/NMI mode the CoCo&#8217;s MPU would pass a byte to\/from the floppy disk controller and this would cause it to trigger the halt line on the MPU. When the controller was ready for another byte it would release the MPU from its halt mode and another byte would be passed. This would continue until the end of the transfer when an NMI interrupt was triggered. This is what would stop the MPU&#8217;s data passing loop.<\/p>\n<p>In single density mode the NMI functionality in the floppy card is disabled. But there should be sufficient time to poll the controller for the interrupt request signal. I was not sure how to write such a loop. After a few unsuccessful attempts I gave up. I had heard the Flex operating system started life using a single density disk format and decided to try to find an example single density read\/write loop from that operating system. It turns out the Flex users group has a lot of information on-line and it was relatively easy to find the loop I was looking for. I discovered the software loop polled for both the interrupt request and data request signals. So even the halt functionality of the card wasn&#8217;t needed in single density mode.<\/p>\n<p>So now it was time to write a patch for RSDOS to support single density. Since this was only an experiment I decided to only patch the lower levels of RSDOS: DSKINI and DSKCON. This is the code that actually does data transfer. RSDOS also contains higher level code for reading\/writing files (both executable and data). I did not modify them. Trying to read and write files after this patch will cause errors.<\/p>\n<p>First I had to decide on the on disk sector layout. I choose 9 256 byte sectors, numbered 1 thru 9, on each track for 35 tracks. The I wrote the following program which patches RSDOS version 1.1:<\/p>\n<p><pre>\norg $7000<\/p>\n<ul>\n<li>patch DSKINI for SD\n<\/pre>\nChange the loop constructs in DSKINI to end at sector 9 instead of 18.\n<pre>\nlda #$09\nsta $d5c5\nsta $d5c9\nsta $d5d2\nsta $d67b\nsta $d6bc\n<\/pre>\nChange track start from 32 bytes of 0x4E to 32 bytes of 0xFF\n<pre>\nlda #$ff\nsta $d696\n<\/pre>\nChange track end from 200 bytes of 0x4E to 200 bytes of 0xFF\n<pre>\nsta $d6c1\n<\/pre>\nNew track table ends with 8 blocks not 9.\n<pre>\nlda #$08\nsta $d6b5\n<\/pre>\nInsert the address of the new track table into DSKINI.\n<pre>\nldd #nt\nstd $d6a4\n<\/pre>\nChange program to jump to our new DSKINI write routine.\n<pre>\nlda #$7e\nsta $d646\nldd #write\nstd $d647\n<\/pre>\nNow we patch DSKCON.<\/li>\n<\/ul>\n<p>OR in single density (instead of double density) mode\n<pre><\/p>\n<ul>\n<li>patch DSKCON for SD\nlda #$0\nsta $d775\n<\/pre>\nDon&#8217;t turn on halt mode\n<pre>\nlda #$00\nsta $d840\n<\/pre>\nPatch DSKCON to jump to new write and read loops\n<pre>\nlda #$7e\nsta $d86b\nsta $d881\nldd #wdsk\nstd $d86c\nldd #rdsk\nstd $d882\nrts\n<\/pre>\nNew writing routine for DSKINI\n<pre>\nwrite   anda    #$4f\nsta $ff40   Turn off halting, double density and NMI\nw0  ldb ,x+ Read byte from track buffer\nw1  lda $ff48   Get FDC status\nrora        Roll <em>busy<\/em> bit into carry flag\nbcc w3  If not <em>busy<\/em>, then branch out of loop\nrora        Roll <em>data request<\/em> bit into carry flag\nbcs w2  If ready for data, branch to write instruction\nbra w1  Branch back to test status again.\nw2  stb ,y  Write data to FDC\nbra w0  Branch back to get new byte\nw3  jmp $d64f done, jmp back to DSKINI\n<\/pre>\nNew writing routine for DSKCON\n<pre>\nwdsk    ldb ,x+ Load byte from transfer buffer\nstb $ff4b   Write it to FDC\nwd1 lda ,u  Get status\nrora        Roll <em>busy<\/em> bit into carry flag\nlbcc    $d88b   If not <em>busy<\/em>, branch to end loop\nrora        Roll <em>data request<\/em> bit into carry flag\nbcs wdsk    If data requested, get new byte from transfer buffer\nbra wd1 Brach to check status again\n<\/pre>\nNew reading routine for DSKCON\n<pre>\nrdsk    ldb $ff4b   Load byte from FDC\nstb ,x+ Store byte to transfer buffer\nrd1 lda ,u  Get status\nrora        Roll <em>busy<\/em> bit into carry flag\nlbcc    $d88b   If not <em>busy<\/em>, branch to end loop\nrora        Roll <em>data request<\/em> bit into carry flag\nbcs rdsk    If data requested, get new byte from transfer buffer\nbra rd1 Brach to check status again\n<\/pre>\nNew disk format table\n<pre>\nnt  fcb 3, $0   Sync field\nfcb 3, $0\nfcb 1, $FE  ID Address Mark<\/li>\n<li>Track, side and sector numbers are inserted here\nfcb 1, 1    Sector Size (256 byte sectors)\nfcb 1, $f7  CRC Request\nfcb 11, $ff GAP II (Post-ID Gap)\nfcb 6, $0   Sync Field\nfcb 1, $fb  Data Address Mark (AM2)\nfcb 0, $ff  Data Field (256 bytes)\nfcb 1, $f7  CRC Request\nfcb 27, $ff Gap III (Post Gap Data)\nend\n<\/pre><\/li>\n<\/ul>\n<p>Running the above patch will allow you to use BASIC&#8217;s DSKINI command to format a single density disk. And use BASIC&#8217;s DSKI$ and DSKO$ to read and write sectors.<\/p>","protected":false},"excerpt":{"rendered":"<p>Back in May of 2007 Philip Pemberton asked on the classic computer mailing list for some diagnostic information from single density floppy disks. He said he was building custom hardware to read floppy disks and needed some data. He was &hellip; <a href=\"https:\/\/tlindner.macmess.org\/?page_id=250\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-250","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/pages\/250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=250"}],"version-history":[{"count":5,"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/pages\/250\/revisions"}],"predecessor-version":[{"id":655,"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=\/wp\/v2\/pages\/250\/revisions\/655"}],"wp:attachment":[{"href":"https:\/\/tlindner.macmess.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}