Low level floppy read code example (DMA loader)

All 680x0 related coding posts in this section please.

Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team

Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2978
Joined: Mon Feb 20, 2012 4:42 pm

Low level floppy read code example (DMA loader)

Postby AtariZoll » Fri Mar 14, 2014 2:35 pm

This example accessing floppy 2-sidewise, by alternating sides - what is better than going through 1 side in order, then reading other side, since less floppy step is required.
Whole routine is pretty short, so may use in game loaders for instance. There is depacking support too, without need for extra buffer - it calculates loading address according to unpacked length, loads to destination area, and depacks without overwriting packed data.
4 byte long filenames are used - I made this code for game Power Drift, 1 floppy version, suing original names. So, 1 file record is 8 bytes long.
May use only 4 byte long records table - then instead file name, file number must be given - little modded code is needed then to get LS and sector count.
Or simplest is to give straight LS and sector count to loader for each file by caller.

Code: Select all

*Hardware registers:

gpip equ  $fffffa01

dmal    equ $ffff860d
dmam equ $ffff860b
dmah   equ $ffff8609

fdcc    equ $ffff8604
dmac  equ $ffff8606

* Subrutine for loading from floppy

* params :  a0 - dest,
* d0 long filename - 4 chars always, capital

   movem.l   d1-d6/a2-a4,-(sp)
   move.l   a0,a4   * Save dest

   lea   catc(pc),a1
   moveq   #92,d1   * 93 files total - just example

seefl   cmp.l   (a1),d0
   beq.s   gotIt
   addq.l   #8,a1
   dbf   d1,seefl
   moveq   #-34,d0    * File not found - should never happen

   movem.l   (sp)+,d1-d6/a2-a4

* need d2 - track, d3 - SS ,  d4 - count

* Here 2-sidewise loading ! :

gotIt    moveq   #0,d2
   moveq   #0,d4
   move.w   4(a1),d2   * LS of file start, next 2 bytes are unpacked length
   move.w   12(a1),d4
   sub.w   d2,d4    * Sector count
   move.b   #$FD,d6
* d2 holds now logical sector (2 sides, alternating), d4 holds sector count for load

* Determine side :

   divu          #20,d2
   move.l   d2,d3   * Track in d2
   swap   d3      * SS
   cmp.b   #10,d3
   bcs.s   sidA
   move.b   #$FC,d6
   sub.b   #10,d3   

   addq.w   #1,d3    * SS

   jsr   readPrep.w

* Calc load address, considering depacking process :

   moveq   #0,d5
   move.w   6(a1),d5    * Unpacked len  -  max 65535 , otherwise need different records
* Load to address of target + unpacked len - packed len +512 

   addq.w   #1,d5
   bclr     #0,d5   * make it even

   add.l   d5,a0
   lea       512(a0),a0
   move.l   d4,d5
   lsl.w     #4,d5
   lsl.l       #5,d5
   sub.l     d5,a0

   move.l   a0,-(sp)

nexS    jsr   read1s.w    * reading 1 sector
* Here should check d0 - for possible errors

   subq.w   #1,d4
   beq.s   ldEnd

   lea   512(a0),a0
   addq.w   #1,d3
   cmp.w   #11,d3   * 10 sector/track
   bne.s   nexS
   moveq   #1,d3

* Need to flip side here :
   eor.b   #1,d6
   cmp.b   #$FD,d6
   bne.s   noTraI
   addq.w   #1,d2
   jsr   readPrep.w   

   bra.s       nexS


   move.l   (sp)+,a1
   lea   32(a1),a1

   bsr   depak3

* By need call floppy deselect here - but it is done in Vblank usually
toRea   moveq   #0,d0
   movem.l   (sp)+,d1-d6/a2-a4

catc   incbin   "CAF"   * 752 bytes - for 93 files

depak3   clr.l d0
   moveq    #6,d4
   moveq    #$3f,d5   *for masking bits 5-0

* Bit meaning:  7 - if set it's back referrer , if 0 then bits
* 6-0 give count of literals to copy
* if all bits are 0 it is terminator

* When bit 7 set, bit 6: if 1 then long distance back given by 2 following byte
*  bit 6: when 0  then short distance given by following 1 byte
*  bits 5-0  count of bytes referred.
*  By short refer.  0 means 3, 1 means 4, etc  up to 66 .
*  By long refer.  0 means 4, 1 means 5, etc  up to 67 .

main3    clr.w d0 *prep for dbf
   move.b (a1)+,d0
   bmi.s back3
   beq.s nom3 *end
   subq.w #1,d0 *compens dbf
litc    move.b (a1)+,(a4)+
   dbf d0,litc
   bra.s main3

nom3   rts

back3   move.b d0,d2
   and.w d5,d2 *d5=$3f
* Test is long or short referrer:
   btst    d4,d0   *test bit 6
   bne.s  longr
   addq.w #2,d2 *compens   
displl   move.b (a1)+,d0 * displac
calcadr   move.l a4,a2
   sub.l d0,a2
baksl   move.b (a2)+,(a4)+
   dbf d2,baksl
   bra.s main3

longr   addq.w #3,d2 *compens
   move.b (a1)+,d0 * displac
   lsl.w  #8,d0   *MSB
   bra.s   displl

* End of C3 depak

* Floppy code self :

read1s     *d2-track, d3 - sector #

* First step if needed
* See FDC track register content :

  move.w #$82,(a2)  *Track register
  bsr delay

  move.w  (a3),d0   * Current track
  cmp.b  d0,d2   * b !
  beq.s noStep

  move.w #$86,(a2)  *Data register
  bsr delay

  move.w d2,(a3) *Track No
  bsr delay
  bsr comand
  move.w #$13,(a3)  *Seek command, steprate 3ms
  bsr comexd 


* Read 1 sector :

   move.l   a0,d0

  move.b d0,dmal.w
  lsr.w #8,d0
  move.b d0,dmam.w
  swap d0
  move.b d0,dmah.w
  move.w #$84,(a2)
  bsr delay
  move.w  d3,(a3)
  bsr delay

  move.w #$90,(a2)
  move.w #$190,(a2)
  move.w #$90,(a2)
  bsr delay
  move.w #1,(a3)  *Block number-one sector of 512
  bsr comand

  move.w #$80,(a3)  * Read sector command
  bsr delay
  bsr comexd


readprep   * in d6 is side flag
  movea.w #$8800,a2
  move.b #14,(a2)
  move.b  (a2),d0
  or.b  #3,d0     * must set to inactive state, side A - otherwise may select bad side !
  and.b   d6,d0    *  $FD   for side A, $FC for side B - both drive A always
  move.b  d0,2(a2)

* Prepare registers for DMA, FDC access
  lea dmac.w,a2  *DMA mode register
  lea fdcc.w,a3  *FDC register(s)

comand move.w #$80,(a2)

delay move.l d7,-(sp)
  moveq #12,d7
dll  dbf d7,dll
  move.l (sp)+,d7

  move.l #300000,d0 * give enough time
cfort  btst #5,gpip.w
  beq.s cef
  subq.l #1,d0
  bne.s cfort
  move.w #$fe,d0 *Drive not ready-usually means-no disk in drive

cef  move.w #$80,(a2)  *Read status     12T
  move.w (a3),d0     *    8T
  btst #4,d0    *  12T
  beq.s de2    *  12T
  move.w #$f8,d0   *RNF   
de2  btst #3,d0     *   12T
  beq.s de3     * 12T
  move.w #$fc,d0  *CRC   
de4   *TOS standard error nummers used.
  rts      *  16T

deselFlo    * deselecting floppy after finished
* by watching motor on in status

  lea dmac.w,a2  *DMA mode register
  lea fdcc.w,a3  *FDC register(s)

readFloS   nop
  move.w #$80,(a2)  *Read status     12T
  bsr   delay
  move.w (a3),d0     *    8T

  btst   #7,d0
  bne.s   readFlos
  movea.w #$8800,a2
  move.b #14,(a2)
  move.b  (a2),d0
  or.b  #$3,d0
  move.b  d0,2(a2)


Famous Schrodinger's cat hypothetical experiment says that cat is dead or alive until we open box and see condition of poor animal, which deserved better logic. Cat is always in some certain state - regardless from is observer able or not to see what the state is.

Social Media


Return to “680x0”

Who is online

Users browsing this forum: No registered users and 4 guests