|
Volume Number: | 12 | |||
Issue Number: | 4 | |||
Column Tag: | Assembler Workshop |
FakeFinder
A tiny file-launching hack for those emergencies...
By Lee David Rimar
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
What with it being April and the call of April Fool’s Day echoing in the breezes, it seems an appropriate time to put before the public this little horror that arrived at our desks a while back. Please bear in mind that when we say, “Kids, don’t try this at home,” this is one case where we mean it. It really does work, but the publisher, editors and staff of MacTech Magazine categorically refuse to stand behind or endorse it in any way, and will not be held responsible for what happens to you or anyone else as a result of your assembling this code or downloading the alternate Finder app. In fact, we can’t even be held responsible for what may happen to you if you read the article! Why not just turn the page now? Hey, I said turn the page! Okay, you asked for it
What It Is and
Why You Might Want It
With current releases of the Mac OS, it’s sometimes hard to build a useful emergency boot diskette. If your hard-drive won’t boot, you can usually use the Disk Tools floppy to bring up your system. But if you want other diagnostic and/or system recovery programs on your “emergency” diskette, there usually isn’t enough space. Enter FakeFinder.
FakeFinder is a tiny program (under 800 bytes) that simply launches other programs. On emergency boot diskettes, FakeFinder replaces the real Finder, and frees a lot of space.
How To Use It
To create an emergency boot disk with FakeFinder:
• Format a diskette and label it Emergency.
• Copy the following file(s) from your Disk Tools diskette to the root directory of Emergency:
1) the System file
2) optional: the Apple CD-ROM Extension
• If your Mac requires any system enablers, copy these also to the root directory of Emergency.
• Copy the “Finder” application from the FakeFinder package to the root directory of Emergency.
You now have a bootable diskette with considerable free space on it. Go ahead and add any other programs you want in the root directory of this disk, anything that will fit. My personal preference is to keep most of what’s on the Disk Tools floppy, and add my tape backup/restore software.
When you reboot with this diskette, FakeFinder loads and creates a File menu with only two items on it: Open and Quit.
To launch any program(s), select Open. This will let you select any applications, aliases to applications, and even a “real” Finder on any mounted drive - including CDs, if you copied the Apple CD-ROM Extension to the diskette.
To shut down your Mac, select Quit, and also quit any other applications you may have launched. Your Mac will then shut down normally.
Limitations
(or, This Ain’t No Swiss Army Knife)
To be so small, FakeFinder leaves a lot of stuff out. The most important limitations:
• No desk accesories/Apple Menu items.
• Without a real Finder present, you can’t use File Sharing.
• Programs needing to find a “Blessed Folder,” containing a real Finder and System, may not work.
The point of FakeFinder was to make it as small as possible, so I don’t plan to solve any of these problems.
By The Way: How Did It Get So Small?
Normally, to create an application this small, you would start in assembly language. But I don’t grok 68K assembler well enough to write anything from the ground up. So I wrote, compiled, linked, and tested FakeFinder using FORTRAN, a language I do know. Then I disassembled the compiler’s output, modified it to reduce the code size, and re-assembled it.
Disclaimers
(or, Anything Free Comes With No Guarantee)
Though FakeFinder works properly on every system I have tested so far, it may not work on tomorrow’s systems. This is because it uses the _Launch trap to sublaunch applications, and Apple says this functionality may go away in future OS releases. If and when that time comes, it will be necessary to rewrite any applications using the sublaunch facility.
References
Macintosh Tech Notes #126, #180, #205 (old numbering system).
MACHINE MC68000 ; system routines used in this module _AppendMenu OPWORD $A933 _DrawMenuBar OPWORD $A937 _ExitToShell OPWORD $A9F4 _FindWindow OPWORD $A92C _HFSDispatch OPWORD $A260 _HiliteMenu OPWORD $A938 _InitCursor OPWORD $A850 _InitDialogs OPWORD $A97B _InitFonts OPWORD $A8FE _InitGraf OPWORD $A86E _InitMenus OPWORD $A930 _InitWindows OPWORD $A912 _InsertMenu OPWORD $A935 _Launch OPWORD $A9F2 _MenuSelect OPWORD $A93D _NewMenu OPWORD $A931 _StdFile OPWORD $A9EA _SetVol OPWORD $A015 _WaitNextEvent OPWORD $A860 START: MAIN ; make a stack, initialize managers, and set up menus link a6,#-664 lea (266,a7),a2 ; qd.grafport move.l a2,(a7) _InitGraf _InitFonts _InitWindows _InitMenus _InitDialogs _InitCursor lea AppleMenu,a2 move.l a2,(a7) move.w #$80,(4,a7) _NewMenu move.l (a7),a3 move.w #0,(a7) move.l a3,(2,a7) _InsertMenu lea FileMenu,a2 move.l a2,(a7) move.w #$81,(4,a7) _NewMenu move.l (a7),a3 move.w #0,(a7) move.l a3,(2,a7) _InsertMenu lea MenuItems,a2 move.l a2,(a7) move.l a3,(4,a7) _AppendMenu _DrawMenuBar sub.l #36,a7 Loop: ; If (.NOT. WaitNextEvent( ; VAL2(-1),event,VAL(15),VAL(0))) Loop move.l #0,(a7) move.l #15,(4,a7) lea (288,a7),a2 move.l a2,(8,a7) move.w #-1,(12,a7) _WaitNextEvent move.b (a7),d3 sub.l #$000e,a7 tst.b d3 beq.s Loop ; If (event.what != mouseDown) Loop move.w (288,a7),d3 cmp.w #1,d3 bne.s Loop ; If (FindWindow( ; VAL(event.where),dummy) != inMenuBar) Loop lea (272,a7),a2 move.l a2,(a7) move.l (298,a7),(4,a7) _FindWindow move.w (a7),d3 sub.l #8,a7 cmp.w #1,d3 bne.s Loop ; pick = MenuSelect(VAL(event.where)) ; Call HiliteMenu(VAL2(0)) move.l (298,a7),(a7) _MenuSelect move.l (a7),d3 move.w #0,(a7) _HiliteMenu sub.l #6,a7 ; If (pick == z'00810001') GetFile ; If (pick != z'00810002') Loop ; Call ExitToShell cmp.l #$810001,d3 beq.s GetFile cmp.l #$810002,d3 bne.s Loop _ExitToShell GetFile: ; Call SFGetFile( ; VAL(coords),0,VAL(0),VAL2(3),types,VAL(0),reply) lea (304,a7),a2 move.l a2,(a7) move.l #0,(4,a7) lea types,a2 move.l a2,(8,a7) move.w #3,(12,a7) move.l #0,(14,a7) move.l #0,(18,a7) move.l #$00400040,(22,a7) move.w #$2,-(a7) _StdFile sub.l #$001a,a7 ; If (.NOT. reply.good) Loop move.b (304,a7),d3 tst.b d3 beq.s final ; myPB.p_ioName = LOC(reply.fName) ; myPB.ioVRefNum = reply.vRefNum ; myPB.ioFDirIndex = 0 ; myPB.ioDirID = 0 ; If (PBGetCatInfoSync(myPB) != 0) Loop lea (314,a7),a2 move.l a2,(478,a7) move.w (310,a7),(482,a7) move.l #0,(488,a7) move.l #0,(508,a7) lea (460,a7),a2 move.l a2,(a7) movea.l (a7)+,a0 move.w #9,d0 _HFSDispatch sub.l #4,a7 tst.w d0 bne.s final ; params.ioCompletion = 0 ; params.ioResult = 0 ; params.p_ioName = 0 ; params.ioVRefNum = reply.vRefNum ; If(PBSetVolSync(params).LT.0) Loop move.l #0,(392,a7) move.w #0,(396,a7) move.l #0,(398,a7) move.w (310,a7),(402,a7) lea (380,a7),a2 move.l a2,(a7) movea.l (a7)+,a0 _SetVol sub.l #4,a7 ; ap.pfName = LOC(reply.fName) ; ap.param = 0 ; ap.LC = z'4C43' ; ap.extBlockLen = 6 ; ap.fFlags = myPB.ioFlFndrInfo.fdFlags ; ap.launchFlags = z'C0000000' lea (314,a7),a2 move.l a2,(568,a7) move.w #0,(572,a7) move.w #$4C43,(574,a7) move.l #6,(576,a7) move.w (500,a7),(580,a7) move.l #$c0000000,(582,a7) ; ignore = launch(ap) lea (568,a7),a2 move.l a2,(a7) movea.l (a7)+,a0 _Launch sub.l #4,a7 final: bra Loop ; some constants embedded in code section types: ; file types for getfile, what you can launch with FakeFinder dc.l $4150504c ; APPL dc.l $464e4452 ; FNDR dc.l $61647270 ; adrp (application aliases) AppleMenu: ; Apple Menu character, for appearances only! dc.b 1 dc.b 20 FileMenu: ; Pascal String “File” dc.b 4 dc.b 70 dc.b 105 dc.b 108 dc.b 101 dc.b 0 ; pad so next lands on even address MenuItems: ; Pascal string “Open;Quit” dc.b 9 dc.b 79 dc.b 112 dc.b 101 dc.b 110 dc.b 59 dc.b 81 dc.b 117 dc.b 105 dc.b 116 ENDMAIN END
- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine