FakeFinder
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 Fools 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, dont 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 cant 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, its sometimes hard to build a useful emergency boot diskette. If your hard-drive wont 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 isnt 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 whats 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 Aint 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 cant 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 dont 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 dont 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 compilers 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 tomorrows 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