Ahh, back in cosy main:
– looks much easier now after that crazy MMU stuff in the previous part, right?
The next subroutine called is proc32
. In the complete source code (reminder: Available at GitHub) I commented that with “works (get some RSC strings)“… and well, that sums it up pretty good.
proc32
loads (i.e. creates handles) from the resource-fork, e.g. the icons used in the menu-bar and several error-messages like “This application must run on the 68030 processor, please quit all other 68040 applications and re-run this application.“. That’s it. Boring…
That boredom instantly changes when we get to the next subroutine proc43
located at 0x29DA…
I did it my way…
One fascinating thing about classic Mac OS is how easy it is to patch system calls, aka Toolbox traps. For example in the previous post we came about _BlockMove
, which is a Toolbox call to copy an amount of RAM from A to B.
For example you have just read this article about a faster BlockMove method, you’re totally free to patch (read: replace) _BlockMove with your speedier version and automatically use this throughout your application – or even system-wide, if you’ve created an INIT… [If you want to know all about it… here’s a book for you]
And that’s what proc43
heavily does. Because it’s a long subroutine (230 lines) so I will give you just one example – the inline comments should do…
2BE2: MOVE #$A02E,D0 ; BlockMove 2BE6: _GetTrapAddress newOS ; (D0/trapNum:Word):A0\ProcPtr 2BE8: MOVE.L A0,$270(A5) ; oldBlockmove 2BEC: LEA data42,A0 ; myBlockMove 2BF0: TST.B MMU32bit ; loMem global "current address mode" 2BF4: BNE.S lae_70 ; skip if 32bit clean machine else 2BF6: LEA data43,A0 ; use a different entry for dirty machines 2BFA: lae_70 MOVE.L A0,$274(A5) ; save routine pointer to $274(A5) 2BFE: LEA data41,A0 ; DC.L 0000 0000 2C02: MOVE.L $270(A5),(A0) ; save oldBlockmove vector into there 2C06: MOVE.L #$A02E,D0 ; BlockMove 2C0C: LEA data40,A0 ; aaaand replace it by myBlockmove 2C10: _SetTrapAddress newOS; (A0/trapAddr:ProcPtr; D0/trapNum:Word)
This is the sum up what else being done:
- Save all debugger vectors into A5-world locations (suspicious. I sense Macsbug killing…)
- Load the PACK4 resource, that’s the Floating Point emulation package (aka SANE) if no FPU found
- Check & read several system Gestalt codes into A5-world (0x2AAC-0x2B44)
- Patch several Toolbox traps
- SwapMMUMode replaced by
data19
- VM_Displatch by
data22
- Pack4 by
data10
- Pack5 by
data11
- BlockMove by
data40
- jClearCache by
myClearCache
- GetNextEvent by
myGetNextEvent
- GetResource by
myGetResource
- SCSIdispatch by
mySCSIdispatch
- DrawMenuBar by
myDrawMB
- LoadSeg by
data31
- UnLoadSeg by
data32
- HWPriv by
data33
- vStdExit by
data34
- SwapMMUMode replaced by
So far, so many. Then there’s some RAM copying going on, of which I’m currently not quite sure what it is good for (0x2CAC-0x2CD8) 💡 .
Finally, the myShutdown
routine is installed into the Shutdown Manager, i.e. it will executed before the Mac is powered down/restarting (it simply switches the host back to its own 68030). After that, RTS into main…
“There and back again…”
Barely back in main, a JSR 12(A6)
warps us into MacII_4th
, the last of the four handlers every supported system has.
This loads specific data from the FPSP into RAM (namely IDs 0x12C and 0x12D).
Finally a special floppy driver is installed (myFloppyDrvr
@ 0x954) which IMHO just differs from the original in handling the ‘040 caches correctly. That was that and back to main…
The next sub-routine in line is chkATalkVer
. I can rightfully name that routine because it’s short and crystal clear: Figure out if AppleTalk is installed, and if true, return its version in D0 (and also write it into A5-world). C’est ca…
This is the end…
It’s getting ugly (for now)… proc42
will be called – the last subroutine in main before my SE/30 crashes and burns 😥
The first few lines (0x28F4-0x293C) are comparably harmless. They are working around a bug in System 7.1 which was corrected in 2/17/92 according to some dark sources (“Corrected value of timeSCSIDB from 0DA6 to 0B24”).
After that, proc38
(0x293C) is called which again calls proc39
and something’s done with the TimeManager, not really sure what’s exactly going on, but it feels like a timing-benchmark heavily using InsTime
, PrimeTime
and RmvTime
Toolbox calls.
[hold yer breath] Then we’re getting closer to the flat line… The stack is filled with these parameters:
2940: CLR.L -(A7) ;PUSH.L 00000000 2942: CLR.L -(A7) ;PUSH.L 00000000 2944: CLR.L -(A7) ;PUSH.L 00000000 2946: PUSH.L #$80008000 ; 80008000 294C: CLR.L -(A7) ;PUSH.L 00000000 294E: PUSH.L #64 ; 00000040 2954: PUSH.L #1 ; 00000001
and SpeedProc
is called…
…To be continued 😉
P.S: I changed course (again) and started to investigate more into the C040’s hardware. The more I understand of the INIT/CP workings the more I can’t fight the idea that it really might be a hardware timing issue.