; ; IFFscan - IFF file scanner - Jim Butterfield. January 12/90. ; Exec library calls _LVOOpenLibrary EQU -$228 _LVOCloseLibrary EQU -$19E _LVOSetSignal EQU -$132 ; DOS library calls _LVOSeek EQU -$42 _LVOOutput EQU -$3C _LVOWrite EQU -$30 _LVORead EQU -$2A _LVOClose EQU -$24 _LVOOpen EQU -$1E ; BufSize EQU 10 ;-- Initial setup: Startup move.l a0,a4 ; Remember ptr to argument line. cf MOVEA move.b #0,-$1(a0,d0.W) ; binary zero at end lea dosname(pc),a1 ; Name 'dos.library'. clr.l d0 ; Any version (0) move.l $4,a6 ; Using Exec library jsr _LVOOpenLibrary(a6) ; Open Dos library. move.l d0,a6 ; Remember DosBase ptr. tst.l d0 ; Check for error (d0=0 means beq.s StartupQuit ; dos not opened) bsr.s DOSinit move.l a6,a1 ;-Specify Dos library in a1; move.l $4,a6 ; then using Exec library, jsr _LVOCloseLibrary(a6) ; close Dos library. StartupQuit rts ; End of Program ; ;-- Get CLI outhandle: DOSinit jsr _LVOOutput(a6) ; get CLI outhandle, move.l d0,d7 ; & then remember it. ; ; -- Skin leading spaces: skipspc move.l a4,d1 ; filename start cmp.b #$20,(a4)+ ; space? beq.s skipspc move.l #1005,d2 ; MODE_OLDFILE (for reading) jsr _LVOOpen(a6) move.l d0,d6 ; file inhandle beq.s FileNot ; no good, quit link a5,#-$1C bsr.s ScanFile ; the main job unlk a5 move.l d6,d1 ; use the handle.. jsr _LVOClose(a6) ; to close the file DOSquit rts ; exit program. FileNot move.l d7,d1 ; handle lea FNF.MSG(pc),a0 move.l a0,d2 moveq #FNFlen,d3 jmp _LVOWrite(a6) ; ; DOS is open and we have our in/out handles. ; Global stack definitions FileP EQU -$4 DosBase EQU -$8 Type EQU -$C Abort EQU -$10 String EQU -$1C ; 12 byte work area ; Look for 'FORM' or other drawer types ScanFile: move.l a6,DosBase(a5) moveq #1,d4 ; start at Level 1 moveq #0,d0 move.l d0,Abort(a5) ; Ctrl-C trap move.l d0,FileP(a5) ; file position=start bsr ReadType tst.l d5 ; is it a drawer? bne.s GotDrawer ; yes, exit ; First four characters are not valid type. Give up. move.l d7,d1 ;output handle lea NotIFF.MSG(pc),a0 ;message to move.l a0,d2 ; buffer moveq #NotIFFlen,d3 ;length jsr _LVOWrite(a6) bra.s SFexit ; GotDrawer bsr.s DoBlock ; recursive analysis job tst.l Abort(a5) beq.s SFexit move.l d7,d1 ;output handle lea CtrlCMess(pc),a0 ;message to move.l a0,d2 ; buffer moveq #3,d3 ;length jsr _LVOWrite(a6) SFexit rts ; job complete ; D4=Recursion level D5=Drawer Flag ; D6=Inhandle (file) D7=Outhandle (screen) ; A4=Local Stack Frame ; A5=Global Stack Frame A6=DosLibrary ; BSize EQU -4 CSize EQU -8 FileF EQU -12 XType EQU -$10 DoBlock link a4,#-$10 ; local variables ; read Size of this block move.l d6,d1 ; input file handle lea BSize(a4),a2 ; input buff (stack) address move.l a2,d2 ; .. to D2 for read moveq #4,d3 ; read 4 characters add.l d3,FileP(a5) ; record file position jsr _LVORead(a6) ; read 'em move.l (a2),d0 ; take raw size addq.l #1,d0 ; round up to even value and.b #$fe,d0 move.l d0,CSize(a4) ; store rounded value move.l FileP(a5),d1 ; start point this chunk add.l d1,d0 ; log end point this chunk move.l d0,FileF(a4) tst.w d5 ; a drawer? beq.s NotDraw1 ; read subType of the drawer move.l d6,d1 ; input file handle lea XType(a4),a0 ; input buff (stack) address move.l a0,d2 ; .. to D2 for read moveq #4,d3 ; read 4 characters add.l d3,FileP(a5) ; record file position jsr _LVORead(a6) ; read 'em ; print drawer Type subType bsr ShowType move.l d7,d1 ;output handle lea Spaces(PC),a0 ;message to move.l a0,d2 ; buffer moveq #1,d3 ;length=1 space jsr _LVOWrite(a6) move.l d7,d1 ;output handle lea XType(a4),a0 ;message to move.l a0,d2 ; buffer moveq #4,d3 ;length jsr _LVOWrite(a6) move.l d7,d1 ;output handle lea NewLine(PC),a0 ;message to move.l a0,d2 ; buffer moveq #1,d3 ;length=1 char jsr _LVOWrite(a6) ; Scan through size of drawer. First, Check CTL-C NotDraw1 move.l 4,a6 ; set Exec libr moveq #0,d0 move.l #$1000,d1 jsr _LVOSetSignal(a6) ;test CTRL-C move.l DosBase(a5),a6 ;restore DOS libr and.l #$1000,d0 or.l d0,Abort(a5) tst.l Abort(a5) bne.s EndSect move.l FileP(a5),d0 cmp.l FileF(a4),d0 bcc.s EndSect tst.w d5 ; a drawer? beq.s NotDraw2 ; Analyze drawer for sub elements - get Type! bsr.s ReadType ; recurse .. look inside outer drawer addq #1,d4 bsr DoBlock subq #1,d4 moveq #1,d5 ; restore old drawer type! bra.s NotDraw1 ; found a non-drawer .. report it and position ; print Type NotDraw2 bsr.s ShowType move.l d7,d1 ;output handle lea NewLine(PC),a0 ;message to move.l a0,d2 ; buffer moveq #1,d3 ;length=1 char jsr _LVOWrite(a6) ; now position to FileP(a5)+CSize(a4) move.l d6,d1 ;input handle move.l FileF(a4),d2 ;new position move.l d2,FileP(a5) ; synchronize moveq #-1,d3 ;offset from start.file jsr _LVOSeek(a6) bra.s NotDraw1 EndSect unlk a4 rts ; read Type and identify if drawer ReadType move.l d6,d1 ; input file handle lea Type(a5),a2 ; input buff (stack) address move.l a2,d2 ; .. to D2 for read moveq #4,d3 ; read 4 characters add.l d3,FileP(a5) ; record file position jsr _LVORead(a6) ; read 'em ; Look for 'FORM' or other drawer types moveq #1,d5 ; drawer? moveq #0,d0 ; zero table count lea Ttab,a0 ; start of table move.l (a2),d1 RTloop cmp.l 0(a0,d0.w),d1 ; is it drawer? beq.s DrawerGot ; yes, exit addq.w #4,d0 ; try next type cmp.w #Ttlen,d0 ; any more? bne.s RTloop ; yes, try it moveq #0,d5 ; not a drawer DrawerGot rts ; print Type.. ShowType move.l d7,d1 ;output handle lea Spaces(PC),a0 ;message to move.l a0,d2 ; buffer move.l d4,d3 ; (Level) number of spaces jsr _LVOWrite(a6) move.l d7,d1 ;output handle lea Type(a5),a0 ;message to move.l a0,d2 ; buffer moveq #4,d3 ;length jsr _LVOWrite(a6) move.l BSize(a4),d0 ; size of block ; MakeAscii lea String(a5),a1 ; Address of string moveq #11,d2 ; size of string DigLoop swap d0 ; hi/lo swap moveq #0,d1 move.w d0,d1 beq.s Skipper divu #10,d1 Skipper move.w d1,d0 swap d0 move.w d0,d1 divu #10,d1 move.w d1,d0 swap d1 or.b #$30,d1 move.b d1,0(a1,d2.w) tst.l d0 dbeq d2,DigLoop lea 0(a1,d2.w),a0 move.b #$20,-(a0) move.l d7,d1 ; outhandle moveq #13,d3 ; max string size sub.b d2,d3 ; less unused move.l a0,d2 ; num string address ; d2 string position, d3 length jsr _LVOWrite(a6) rts Ttab dc.b 'FORM' dc.b 'CAT ' dc.b 'LIST' dc.b 'PROP' Ttlen EQU *-Ttab FNF.MSG dc.b 'File not found.',$a FNFlen EQU *-FNF.MSG NotIFF.MSG dc.b 'Not an IFF file!',$a NotIFFlen EQU *-NotIFF.MSG Spaces dc.b ' ' dosname dc.b 'dos.library',0 CtrlCMess dc.b '^C' NewLine dc.b $0a end