Every resource begins with a 32-bit size field before the resource data itself.
For the CODE
resource data itself I found resource_dasm, which is an open source project on GitHub. It includes these definitions in ResourceFile.cc
:
struct Code0ResourceHeader {
be_uint32_t above_a5_size;
be_uint32_t below_a5_size;
be_uint32_t jump_table_size; // Should be == resource_size - 0x10
be_uint32_t jump_table_offset;
struct MethodEntry {
be_uint16_t offset; // Need to add 4 to this apparently
be_uint16_t push_opcode;
be_int16_t resource_id; // id of target CODE resource
be_uint16_t trap_opcode; // Disassembles as `trap _LoadSeg`
} __attribute__((packed));
MethodEntry entries[0];
} __attribute__((packed));
struct CodeResourceHeader {
be_uint16_t first_jump_table_entry;
be_uint16_t num_jump_table_entries;
} __attribute__((packed));
struct CodeResourceFarHeader {
be_uint16_t entry_offset; // 0xFFFF
be_uint16_t unused; // 0x0000
be_uint32_t near_entry_start_a5_offset;
be_uint32_t near_entry_count;
be_uint32_t far_entry_start_a5_offset;
be_uint32_t far_entry_count;
be_uint32_t a5_relocation_data_offset;
be_uint32_t a5;
be_uint32_t pc_relocation_data_offset;
be_uint32_t load_address;
be_uint32_t reserved; // 0x00000000
} __attribute__((packed));
These are for "standard" CODE
resources. From other bits and pieces I've read, it seems that certain compilers and/or certain apps also contain CODE
resources in their own formats that they must load manually instead of being loaded by the Mac's OS.
So "CODE0" has one format and "CODE" two formats. The normal format for the near model and a special format for the far model. If the first 16-bit field of the CODE
resource is 0xffff
then it's the format for the far model. Otherwise it's in the normal near model format.
The far model is also described with the term "32-bit-everywhere". I think this hints at the earliest Mac operating systems using the high 8 bits of addresses for flags or such since the original 68000 CPU only used 24 bits for addresses. When later 680x0 CPUs came out they used the full 32 bits and the Mac operating system would have adapted to it.
As noted in other comments and answers the structure is documented in Chapter 10, "Classic 68K Runtime Architecture" of "Mac OS Runtime Architectures For System 7 Through Mac OS 9". There's a lot of information in there besides the description of the records in the file. The parts I was looking for are:
For the format of CODE
resource #0:
- Page 10-9, Figure 10-3 "The 'CODE'0 resource"
- Page 10-10, Figure 10-4 "An unloaded jump table entry"
For the format of normal CODE
resources:
- Page 10-12, Figure 10-6 "Near model segment header"
- Page 10-24, Figure 10-11 "The far model segment header"
I can't find where or if this document covers the general format of the resource as beginning with a 32-bit integer size field, so I'm glad I figured that out.
If all you want is to locate the m68k machine code, then:
Iterate through the resources, look for CODE
resources, skipping the one numbered 0. For the others, check the 16-bit field at offset 0x04. If it's 0xffff then the code starts at offset 0x2c, otherwise the code starts at offset 0x08.
Note that execution does not necessarily start at the beginning of the code block, for exported code entry points you need to see the jump table in CODE
0. It seems common for there to be some data before the first code.