ROM hacking in the 68040 Macs

frontein1

Active member
There is a lot of free space in the C610 ROM
Yes sure enough, did a quick test and moved the NETBOOT resource to offset 04 0F 10 (plenty of free space there). Had to adjust the NETBOOT resource header, and also adjust the next resource offset in the ATBOOT resource header. But this did the trick. NETBOOT driver, even though generally unused, is still an available resource going this route.

I'll update the C610 ROM HACKS document I attached earlier with this change; and also with the clean-up of the old NETBOOT resource area to set that all to 00 to clean it up.
 
Last edited:

frontein1

Active member
OK disregard my last two posts. I actually wish I could delete them. But I started rebuilding the resource table in the C&Q 610 ROM, and I realized that the larger ATBOOT driver really was not stepping on the next resource after it. This ROM actually has a handful of bytes not in use in between the two resources. So I went back and edited my document accordingly. Hopefully the next time I post this it will have the fix to support any sized SIMM 128MB or smaller.
 

Attachments

  • C610 ROM HACKS.PDF
    197.3 KB · Views: 7

joevt

Well-known member
OK disregard my last two posts. I actually wish I could delete them. But I started rebuilding the resource table in the C&Q 610 ROM, and I realized that the larger ATBOOT driver really was not stepping on the next resource after it. This ROM actually has a handful of bytes not in use in between the two resources. So I went back and edited my document accordingly. Hopefully the next time I post this it will have the fix to support any sized SIMM 128MB or smaller.

Sorting the addresses of the different parts of the ROM resources dump gets these relationships:
Code:
0x00051c80 offsetToNext         data 'DRVR' (49, ".netBOOT", sysheap, locked, protected)
0x00051ca4 memHeader
0x00051cb0 offsetToData             2164 bytes
0x00052524 offsetToAfter            12 unused bytes
0x00052530 offsetToNext         data 'DRVR' (50, ".ATBOOT", sysheap, locked, protected)
0x00052554 memHeader
0x00052560 offsetToData             17294 bytes
0x000568ee offsetToAfter            2 unused bytes
0x000568f0 offsetToNext         data 'free' (0, "Main", sysheap, locked, protected)
0x00056914 memHeader
0x00056920 offsetToData             640 bytes
0x00056ba0 offsetToAfter            0 unused bytes
0x00056ba0 offsetToNext         data 'PICT' (106, "DiskMode 6", sysheap, locked, protected)
...

.netBOOT seems to have 12 unused bytes after its data.
.ATBOOT has 2 unused bytes after its data.

As you said, since the The LC475/Q605 ATBOOT driver is 4-bytes longer than the C&Q610 DRIVER, using the C&Q610 DRIVER would give 6 unused bytes after the data.

I wonder what resource type 'free' is for? It appears to be 640 bytes of nothing. There are four of these in the rom resources. All with different sizes. Maybe they used to be resources but were removed lazily? If they are unused, they could be removed from the linked list of resources to give you more room for the resource positioned before each. For example, removing 'free' 0 would give .ATBOOT 690 more bytes to work with.
 

Attachments

  • dumpromresources.pl.zip
    5.1 KB · Views: 1

frontein1

Active member
@joevt your dumpromresources is just a fantastic tool, BTW! Wanted to pass along some kudos to you. Thanks for continuing to improve and enhance it.

Those free resources were a surprise to me, too. I first noticed that because a free resource just happened to come after the ATBOOT driver resource. I wonder if this is how Apple reserved free space starting with the 1024KB ROMs? Basically assign them as a free resource with the requisite header. Then they could easily be pegged for future use? Just a theory. I suppose if they wanted to be really smart, they could have bumped the resources right up next to each other. Then left all the free space in one continual area. But that would take work to change the resource table, so there had to be some form of laziness involved :)

So when it comes to the ROM/RAM disk for example, maybe NETBOOT and ATBOOT could be left as-is. But instead, use the free resource at offset 60080. Lots of room in that resource for a custom driver, and actually quite a bit more room than even ATBOOT. Maybe I'll give this a stab next.
 
Last edited:

joevt

Well-known member
So when it comes to the ROM/RAM disk for example, maybe NETBOOT and ATBOOT could be left as-is. But instead, use the free resource at offset 60080. Lots of room in that resource for a custom driver, and actually quite a bit more room than even ATBOOT. Maybe I'll give this a stab next.
Yup, 'free' 2 is the biggest 'free' resource at 14176 bytes.
Code:
// ROM Resource Reference Entry @00060080
//  ComboBits             "01111"
//  offsetToNext          0x0005f430
//  offsetToData          0x000600b0
//  offsetToAfter         0x00063810
//  memHeader             0x000600a4
//  memTag                0xc0
//  memSize               14176
//  memMaster             0x00000254
data 'free' (2, "Main", sysheap, locked, protected) {
...
};
 

frontein1

Active member
Did a quick move of the ROM disk driver to the free resource at offset 60080. Works like a charm, and the original ATBOOT resource is still available. Just gave it the generic name ROMDSK for now.

It appears that pretty much all the 1024KB ROMs have these free resources. Might be a good strategy to commandeer these for the ROM disk drivers instead of NETBOOT and/or ATBOOT. But for the 512KB ROMs that really isn't an option.
 

Attachments

  • DUMPROMRESOURCES.txt
    1.4 MB · Views: 3
  • FREE RESOURCE FOR ROM DISK.jpg
    FREE RESOURCE FOR ROM DISK.jpg
    139.3 KB · Views: 7

frontein1

Active member
@joevt I do have a question, not sure if you can answer though. I am writing a new ROM/RAM disk driver from scratch, and in the Resource Header for drivers in the ROM, I am curious what the purpose bytes 33, 34, 35 and 36 are for?

1747060106650.png
 

zigzagjoe

Well-known member
@joevt I do have a question, not sure if you can answer though. I am writing a new ROM/RAM disk driver from scratch, and in the Resource Header for drivers in the ROM, I am curious what the purpose bytes 33, 34, 35 and 36 are for?

View attachment 86597
Looks to me like that's padding bytes to longword align following fields.

You may find this useful, while not primarily intended as a RAMDisk driver I did implement that as an example: https://github.com/ZigZagJoe/Mac-StorageCard-DeclROM
 

joevt

Well-known member
@joevt I do have a question, not sure if you can answer though. I am writing a new ROM/RAM disk driver from scratch, and in the Resource Header for drivers in the ROM, I am curious what the purpose bytes 33, 34, 35 and 36 are for?
That code excerpt is from ResourceMgr.a in the supermario GitHub repository.

The following line for calculating the aligned address on or after the w address:
where g(w) = w + ((4 - (w mod 4)) mod 4)
can be rewritten using bitwise operations like this:
where g(w) = (w + 3) & ~3

The resource name is variable length. The 4 byte alignment is required for the memory block header. Since the the resource name is variable length, the alignment may not always be at byte 33 and the length of the alignment may be 0,1,2, or 3 bytes, never 4 bytes.

A memory block header is the structure that precedes every pointer in the system or application heap.
Since resources are handles, the memory block header has a memTag field with the relocatable bit set (nRelTag), and a memMaster field (handle32 or handle24 depending on 24/32 bit addressing) which is a back pointer to a master pointer in a masters memory block. This is a ROM resource so it also has the nRelTag bit set (which means it is HLock'ed.

You may have to follow the InitResources function of ResourceMgr.a in the supermario repository to see how the rom resources get put into the heap. ROZInit creates a read-only zone for the rom resources (a separate heap?). Some stuff has to be setup in RAM to point to the ROM resources?

@joevt yes I've been looking at your sample RAM disk driver as well. @Jockelill pointed that out to me a little bit ago :)
You are referring to the Apple sample code found at the Apple Documentation archive:
https://developer.apple.com/library/archive/navigation/#section=Platforms&topic=macOS
https://developer.apple.com/library/archive/samplecode/RAMDisk/Introduction/Intro.html

I'm not sure how it will work as a rom resource. I guess a INIT or DRVR resource will be loaded automatically and then they can do all the work to make the RAM disk? The ROM resources that you dumped do include other 'DRVR' and 'INIT' resources so it should work. The 'cdev' will remain a separate file? I don't know what the UI of that looks like.
 

adespoton

Well-known member
Yes, pretty sure these are alignment.
Came here to say this; oddly, I can't find the documentation that stated it.

AI isn't much more help:
In classic MacOS, the "free" resource type was used to indicate unused space within a resource fork. The resource fork was a structured part of a file that stored various elements like icons, window shapes, and menu definitions. The "free" type helped manage memory by marking areas that could be allocated for new resources. It was essentially a way for the system to track available space within the resource fork, ensuring efficient use of storage. Pretty clever, right?
The interesting bit though is it's unsupported assertion that the "free" resources blocked out memory sections that could later be filled with other resources without affecting memory alignment of later resources -- which is exactly what we're doing here!
 

cheesestraws

Well-known member
Came here to say this; oddly, I can't find the documentation that stated it.

It's in the SuperMario source code (https://github.com/elliotnunn/super...02-09/Toolbox/ResourceMgr/ResourceMgr.a#L1147)

Code:
;_______________________________________________________________________________
;
; Routine:        ROZInit (utility)
;
; Arguments:    A0        (output.L)        Handle to the Map in the ROZ
;                A2        (output.L)        Pointer to the Map up in the ROM
;                RomMapHndl (output.L)    Handle to the Map in the ROZ
;
; unchanged:    A3-A7,D1-D7
; trashes:        A1-A2,D0
;
; Called By:    InitResources
; Calls:        _BlockMove, _InitZone, _NewHandle, _NewPtr
;
; Function:     Builds a new zone in the system heap.  This zone is a Read Only
;                Zone.  The size of the new zone can be calculated by the fomula:
;
;<A291/29oct86> bbm memory manager is now long word aligned, which changes ROZinit.
;<C396/4dec86>    agh Make master pointer size 8 bytes for use with UNIX 32 bit
;                    memory mgr.
;
;_______________________________________________________________________________
;
;        Size = zoneheader + zonefooter + longwordalignbias + slop
;                + (12 + block of 4 master pointers)
;                + (12 + size of master pointer block) + (12 + size of map)
;        Size = 52 + 12 + 12 + (12 + 32) + (12 + sizempb) + (12 + sizemap) + slop            <c396>
;        Size = 144 + sizebmp + sizemap    + slop                                                <c396>
;        Size = $90 + 8*X + Y+slop        ; (where X = number of rsrc's                         <c396>
;        Size = 8*(#$18 + X) + Y         ;     and Y = size the map)                            <c396>
;
;The old stucture of the ROM is as follows:
;        ROMRsrcStart:    (long)            ; offset to Rom Rsrc stuff
;        Rom Rsrc Stuff
;            X:            (2)        number of rsrc's in rom
;            Y:            (2)        size of rom rsrc map in rom
;            Map:        (Y)        the rom map
;            rsrc's:        (x)        the rsrc's
;
;The new stucture of the ROM is as follows:
;        RomBase   
;            1A            (4)        offset to Rom Resource Structure Table
;
;        Rom Resource Structure Table
;            0            (4)        offset to first Resource Entry
;            4            (1)        maximum valid index in parameter ram [v]
;            5            (1)        Size of Combo Bit Field (v)
;            6            (2)        Version
;            8            (2)        Size of memory block header
;
;        Hiram Resource Entry (all are offsets from base of rom)
;            0            (v)        combo bits
;            v            (4)        link to next Resource
;            v+4            (4)        offset to data for this rsrc
;            v+8            (4)        Resource Type
;            v+C            (2)        Resource ID
;            v+E            (1)        Resource Attributes
;            v+F            (1)        length of Resource name [n]
;            v+$10        (n)        Resource name
;            v+$10+n        (0-3)    align 4
;            g(v+$10+n)    (8/12)    memory block header
;            g(v+$10+n)+8 (y)    Resource Data [or g(v+C+n) + 12, depending on which mem mgr]
;            x+y            (0-3)    align 4
;
;                where g(w) = w + ((4 - (w mod 4)) mod 4)
;
;_______________________________________________________________________________
 

frontein1

Active member
No, they're referring to @zigzagjoe's RAM disk example declrom. Confusion in the joe department, I think.
Yes my bad, I'm still learning all the names in this community :) @zigzagjoe was the Joe I was referring to.

Thanks all, this is all very helpful. And in a way so cool to get into 68K programming. A much younger version of me is very jealous right now.

You may have to follow the InitResources function of ResourceMgr.a in the supermario repository to see how the rom resources get put into the heap. ROZInit creates a read-only zone for the rom resources (a separate heap?). Some stuff has to be setup in RAM to point to the ROM resources?
My new driver is pretty close. But I am having an issue getting it added to the drive queue. So I am going to start jumping more into the supermario repository, since I haven't quite done that yet.
 
Last edited:

joevt

Well-known member
My new driver is pretty close. But I am having an issue getting it added to the drive queue. So I am going to start jumping more into the supermario repository, since I haven't quite done that yet.
There's a driver unit table for the list of drivers. TradDriverLoaderLib is used to load drivers.

The drive queue is the list of disk devices.

Function main in the RAM disk sample code INIT uses TradDriverLoaderLib to load the driver DRVR and then add a drive to the drive queue that uses that driver.

So, I think you just need to work on the INIT?

https://developer.apple.com/library/archive/technotes/dv/dv_06.html
https://developer.apple.com/library/archive/technotes/dv/dv_23.html
https://developer.apple.com/library/archive/qa/dv/dv27.html
https://developer.apple.com/library/archive/samplecode/TradDriverLoaderLib/Introduction/Intro.html
https://developer.apple.com/library/archive/samplecode/RAMDisk/Introduction/Intro.html
 

cheesestraws

Well-known member
My new driver is pretty close. But I am having an issue getting it added to the drive queue. So I am going to start jumping more into the supermario repository, since I haven't quite done that yet.

The general idiom would be to add your drive queue entry in the driver's Open, I think. What problems are you having?
 

joevt

Well-known member
An INIT isn't going to be much use inside the ROM, nor will it assist much in adding an element to the drive queue...
It's a INIT ROM resource. There are INIT ROM resources in the ROM. Does something load those other INITs but not new INITs?

Same question for DRVR ROM resources. Does something load all of them (run's their Open routine) or are they loaded specifically?

I guess the question is, what ROM resources are loaded and executed? Do you have to modify something to get your INIT or DRVR ROM resource to execute?
 

frontein1

Active member
Well, the ROM I am using to test with is the LC475/Q605. Offset 1278 is the named resource that the INITNETBOOT routine attempts to open automatically. So I believe this takes care of executing the Open routine.

My issue is with within the Open routine, getting the drive added to the queue. I am sure this is user error on my part 😜, just need to learn a bit more about how the class Mac handles the drive queue. All the information shared here is just what I needed.
 
Last edited:
Top