▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ░▒▓█ rapid1337.com █▓▒░ ╓──────────────────────────────────────────╖ ║ Agile File Loader ║ ╟──────────────────────────────────────────╢ ║ ; Disk routine (pinched from Agile – ║ ║ sorry guys) ║ ╟──────────────────────────────────────────╢ ║ ·· code/agile-file-loader.html ·· ║ ╙──────────────────────────────────────────╜ ============================================================================ Title ..: Agile File Loader Author .: staff Date ...: 2007-06-22 Section : Code ============================================================================ ``` ; Disk routine (pinched from Agile – sorry guys) CIAAPRA EQU $bfe001 Cia A port register A CIABPRB EQU $bfd100 Cia B port register B CIABICR EQU $bfdd00 Cia B interrupt control register CUSTOM EQU $dff000 Custom hardware INTREQR EQU $1e Read interrupt request DSKPTH EQU $20 Disk buffer pointer DSKLEN EQU $24 Disk access length DSKSYNC EQU $7e Disk sync word DMACON EQU $96 Write DMA control INTREQ EQU $9c Write interrupt request ADKCON EQU $9e Write audio and disk controller StepDel EQU $bb7 Step delay (dbf, naughty!) ; a0 is address to load file at, d0 is no. of file FileRead movem.l d0-d7/a0-a6,-(sp) Store registers move.l a0,a1 Copy addr. to load into a1 lea Filename(pc),a0 Get filename in a0 bsr MkName Put d0 (hex) into filename string lea Variables(pc),a6 a6 = Variables base lea CIABPRB,a5 a5 = CIA base (CIABPRB) lea CUSTOM,a4 a4 = custom hardware base move.l a1,20(a6) Store addr. to load in vars clr.w 10(a6) Set ‘no track in buffer’ move.b #%11111111,(a5) All CIABPRB high move.b #%10000111,(a5) SEL0-3 low (all motors now off) move.b #%01111111,(a5) Ready for motors on again bclr #3,(a5) Select drive 0, motor on tst.w 0(a6) } nop } blowed if I know why not.w 0(a6) } clr.l 2(a6) Clear current track and ? clr.l 6(a6) Clear sec. to load, sec.no on track btst #4,CIABICR-CIABPRB(a5) Test index (pointlessly) .wtindx btst #4,CIABICR-CIABPRB(a5) Test index beq.s .wtindx Repeat until one occurs bset #1,(a5) Dir = out towards edge .gttk0 btst #4,CIAAPRA-CIABPRB(A5) Are we at track 0? beq.s .gottk0 .wtrdy BTST #5,CIAAPRA-CIABPRB(A5) Drive ready? bne.s .wtrdy Wait until it is bclr #0,(a5) Set step nop nop nop Wait a few cycles bset #0,(a5) Clear step move.w #StepDel,D0 NAUGHTY – should use CIAs! .stpdel dbf d0,.stpdel Step delay bra.s .gttk0 Repeat until we get to track 0 .gottk0 bsr GetHash Calculate filename’s hash value move.w #880,d0 Root block no. in d0 bsr ReadSec tst.l d7 Was there an error? bne DoneAll Clear up and return if so move.w 18(a6),d0 Filename’s hash offset into d0 move.l (a3,d0.w),d0 Get no. of file header block beq DoneAll If no file, clear up and return .hshchn bsr ReadSec Read sector tst.l d7 Was there an error? bne.s DoneAll If so clear up, return lea $1B0(a3),a2 a2 = pointer to filename in block moveq #0,d0 Byte -> word move.b (a2)+,d0 Get name length byte cmp.w 16(a6),d0 Compare with wanted filename length beq.s .sameln Go on if same lengths .wrongF move.l $1F0(A3),d0 Get next hash chain beq.s DoneAll If none, file not found – return bra.s .hshchn Otherwise follow down the hash chain .sameln subq.w #1,d0 Length -1 for dbf move.l 12(a6),a1 Required filename ptr. in a1 .letlop move.b (a2)+,d1 Get byte from current file’s name cmp.b #”a”-1,d1 Test case (badly) ble.s .isupr Go on if upper case sub.b #32,d1 Else convert to upper case .isupr cmp.b (a1)+,d1 Compare with required filename bne.s .wrongF If different, wrong file dbf d0,.letlop Repeat to compare all letters .loadlp move.l $10(a3),d0 Get first/next data block beq.s DoneAll If none, clean up and return cmp.w #1759,d0 Above valid range? bgt.s DoneAll If so, clean up and return bsr.s ReadSec Otherwise load it tst.l d7 If there was an error bne.s DoneAll then clear up and return lea $200(a3),a0 Get end-of-block pointer in a0 move.l $14(a3),d1 Get checksum long clr.l $14(a3) Clear same long in block move.l a3,a1 Copy block pointer to a1 moveq #0,d0 Clear sum .sumlop add.l (a1)+,d0 Add long to sum cmp.l a0,a1 At end of block blt.s .sumlop Sum all longs neg.l d0 Negate sum eor.l d0,d1 Compare with stored sum bne.s DoneAll If checksum fails, clean up and return move.l $c(a3),d0 Get no. of bytes in this block in d0 subq.w #1,d0 Prepare for dbf lea $18(a3),a1 Get pointer to data in a1 move.l 20(a6),a0 Get address to load at in a0 .cpbyte move.b (a1)+,(a0)+ Copy data as bytes dbf d0,.cpbyte Repeat move.l a0,20(a6) Store new load address bra.s .loadlp Carry on loading ; Routine to switch off motors and return DoneAll move.b #%11111111,(a5) Select everything move.b #%10000111,(a5) All motors off move.b #%11111111,(a5) Left off movem.l (sp)+,d0-d7/a0-a6 Restore registers rte Return ; Routine to read a sector (in d0) from the disk ; Pointer to the loaded sector is returned in a3 ReadSec tst.w 10(a6) Check buffer status bmi.s L701E6 Leave alone if negative move.w #1,10(A6) Otherwise set to 1 (pointless) L701E6 moveq #0,d7 d7 is error flag, none yet move.w d0,6(a6) Store sector to load in vars ext.l d0 word -> long divu #11,d0 sector number… swap d0 …mod 11 move.w d0,8(a6) gives sector on track, store in vars swap d0 recover division result move.l d0,d1 Copy to d1 lsr.w #1,d1 Get cylinder no. in d1.w tst.w 10(a6) Is there a track in the buffer? bpl.s .nedred If not, will have to read one cmp.w 2(a6),d1 Is it the right cylinder? bne.s .nedred If not, will have to read one move.w d0,d2 Copy track no. to d2 and.w #1,d2 Mask to get side cmp.w 4(a6),d2 Is the right side in the buffer? beq L7036E If so, buffer is prepared .nedred bset #2,(a5) Select side 0 clr.w 4(a6) Flag side 0 in vars btst #0,d0 See which side is required beq.s .sideok Go on if 0; side is correct move.w #1,4(a6) Flag side 1 in vars bclr #2,(a5) Select side 1 .sideok move.w d1,d0 Copy d0 to d1 bsr GetTkd0 Go to that track move.w #$7F00,ADKCON(a4) Clear top byte of ADKCON move.w #$9500,ADKCON(a4) MFM, no precomp, wordsync, FAST(MFM) move.w #$4489,DSKSYNC(a4) Standard sync move.l #$23600,a3 Get buffer pointer move.l #$55555555,d6 Get clock value in d6 .fndlst move.l a3,a1 Copy buffer pointer to a1 move.w #2,INTREQ(a4) Clear disk interrupt request move.l a3,DSKPTH(a4) Set disk buffer .watrdy btst #5,CIAAPRA-CIABPRB(a5) Disk ready? bne.s .watrdy Wait until it is move.w #$8210,DMACON(a4) Disk DMA on move.w #$8008,DSKLEN(a4) move.w #$8008,DSKLEN(a4) Read len = sector info only .wtdkdn btst #1,INTREQR+1(a4) Disk DMA done interrupt? beq.s .wtdkdn Wait until one occurs .skpsnc cmp.w #$4489,(a1)+ Compare syncs at (buffer+) beq.s .skpsnc Keep going until past subq.l #2,a1 a1 points to last sync move.l (a1),d0 move.l 4(a1),d1 Get longs of sector info and.l d6,d0 and.l d6,d1 Mask with clock add.l d0,d0 Shift first one left or.l d0,d1 Recombine cmp.b #1,d1 Just before track gap? bne.s .fndlst If not keep looking for last sector move.l a3,DSKPTH(a4) Set buffer pointer again move.w #$8210,DMACON(a4) Ensure disk DMA is still on move.w #$9770,DSKLEN(a4) move.w #$9770,DSKLEN(a4) Now read whole track move.w #2,INTREQ(a4) Clear disk DMA done int. request move.l #$186A0,d1 d1 = quite a long time .wtdmad subq.l #1,d1 Count down bne.s .notstk Go on if not end of count not.l d7 Else flag an error move.w #$4000,DSKLEN(a4) Stop disk DMA rts Return .notstk btst #1,INTREQR+1(A4) Disk DMA done interrupt? beq.s .wtdmad If not, keep counting move.w #$4000,DSKLEN(a4) Stop disk DMA moveq #10,d5 11 sectors to decode move.l a3,a2 Put them back over the buffer move.l a3,a1 Save buffer pointer for later .seclop move.w #$3ff,d0 Amount of space to look for sync in .fndsnc cmp.w #$4489,(a3)+ Look for sync beq.s .gotsc Go on if found it dbf d0,.fndsnc Keep trying not.l d7 If sync missing, flag error rts and return .gotsc cmp.w #$4489,(a3) Looking at sync? bne.s .skpsnk If not, have passed it addq.l #2,a3 Otherwise skip over it .skpsnk movem.l (a3)+,d0-d1 Get two longs and.l d6,d0 and.l d6,d1 And them with clock add.l d0,d0 Shift first one left or.l d1,d0 Recombine lsr.w #8,d0 Shift right for sector number move.w d0,(a2)+ Store sector number over buffer lea $30(a3),a3 Skip sector info; a3 points to data moveq #$7f,d2 128 longs of data to decode .decdat move.l $200(a3),d1 Get second long of data move.l (a3)+,d0 Get first long of data and.l d6,d0 and.l d6,d1 And them with clock add.l d0,d0 Shift first one left or.l d1,d0 Recombine move.l d0,(a2)+ Store over buffer again dbf d2,.decdat Repeat for all data dbf d5,.seclop Repeat for all sectors ; Track is now decoded as sectorno.w, data.b repeated 11 times ; Now bubblesort the sectors into order .bubble move.l a1,a2 Get buffer pointer again moveq #9,d0 10 (sector and next sector)s to compare moveq #0,d1 d1 is count of sectors swapped .cmpsec move.w (a2),d2 Get no. of current sector in d2 cmp.w $202(a2),d2 Compare with no. of next sector blt.s .sortok If less, go on move.l a2,a3 Copy current sec. pointer to a3 move.w #$100,d2 One sector + sector no. words to swap .swpwrd move.w $202(a3),d3 move.w (a3),$202(a3) move.w d3,(a3)+ Swap a word of sector data dbf d2,.swpwrd Repeat addq.w #1,d1 Inc. no. of sectors swapped .sortok lea $202(a2),a2 Get next sector dbf d0,.cmpsec Repeat for 10 (sector and next sector)s tst.w d1 Did we have to swap anything? bne.s .bubble If so, try again lea 2(a1),a2 a2 is pointer to first sector data moveq #10,d0 11 sectors to shift back .seccpy moveq #$7f,d1 128 longs of data in each sector .cpydat move.l (a2)+,(a1)+ Copy longs of data back down buffer dbf d1,.cpydat Repeat for all data addq.l #2,a2 Skip sector no., no longer needed dbf d0,.seccpy Copy other sectors directly after ; At this point, the track is prepared in the buffer, so we just need ; to return a pointer to the sector in a3 L7036E move.l #$23600,a3 Get buffer pointer moveq #9,d0 Constant for shift moveq #0,d1 word -> long move.w 8(a6),d1 Sector no. on track .w into d1 asl.l d0,d1 d1 $xx ones ; stores result in variables GetHash move.l a0,12(a6) Store filename in vars move.l a0,a1 Copy to a1 moveq #0,d0 Clear length counter .getlen tst.b (a1)+ End of filename? beq.s .gotlen Go on if so addq.w #1,d0 Else increase length counter, bra.s .getlen repeat .gotlen move.w d0,d1 Copy filename length to d1 move.w d0,16(a6) Store filename length in vars subq.w #1,d1 Prepare d1 (filename len) for dbf .hshlop mulu #13,d0 d0 = filename length * 13 moveq #0,d2 Clear d2 for byte -> word move.b (a0),d2 Get letter of filename cmp.b #”a”-1,d2 Test case (badly) ble.s .letok If less or equal, is upper case sub.b #32,d2 Otherwise sub 32 to make it upper case .letok move.b d2,(a0)+ Store back in filename add.w d2,d0 Add to hash total in d0 and.w #$7ff,d0 Keep d0 in range dbf d1,.hshlop Repeat for all bytes of filename divu #72,D0 Hash total… swap d0 …mod 72… addq.w #6,d0 …plus 6… asl.w #2,D0 …times 4 move.w d0,18(a6) store in variables rts ; Routine to put the number in d0 into the filename at a0 (“$xx”) MkName move.w d0,d1 Copy fileno. to d1 move.w d1,d2 and d2 lsr.w #4,d2 d2 is upper nibble bsr.s D2toHex convert to hex ascii move.b d2,1(a0) store as first digit of filename move.w d1,d2 move lower nibble into d2 bsr.s D2toHex convert to hex move.b d2,2(a0) store as second nibble rts return ; Routine to convert d2 into hex ascii D2toHex and.w #$f,d2 Only numbers from 0-15 add.w #”0″,d2 Convert to ascii cmp.w #”9″,D2 letter or number? ble.s .digit return if number addq.w #7,d2 else add 7 to convert to letter .digit rts return Variables: dc.w 0 0 = .w dc.w 0 2 = Current track .w dc.w 0 4 = Side in buffer (0/1) .w dc.w 0 6 = sector to load .w dc.w 0 8 = sector no. on track .w dc.w 0 10 = Valid track in buffer .w dc.l 0 12 = Pointer to filename .l dc.w 0 16 = Length of filename in bytes .w dc.w 0 18 = filename’s hash offset .w dc.l 0 20 = Address to load at .l Filename dc.b “$00″,0 Filename to load ``` ---------------------------------------------------------------------------- -- rapid1337.com -- The dumping ground for all things tech // knowledge is the weapon --