74 |
|
static bool patch_68k(void); |
75 |
|
|
76 |
|
|
77 |
+ |
// Decode LZSS data |
78 |
+ |
static void decode_lzss(const uint8 *src, uint8 *dest, int size) |
79 |
+ |
{ |
80 |
+ |
char dict[0x1000]; |
81 |
+ |
int run_mask = 0, dict_idx = 0xfee; |
82 |
+ |
for (;;) { |
83 |
+ |
if (run_mask < 0x100) { |
84 |
+ |
// Start new run |
85 |
+ |
if (--size < 0) |
86 |
+ |
break; |
87 |
+ |
run_mask = *src++ | 0xff00; |
88 |
+ |
} |
89 |
+ |
bool bit = run_mask & 1; |
90 |
+ |
run_mask >>= 1; |
91 |
+ |
if (bit) { |
92 |
+ |
// Verbatim copy |
93 |
+ |
if (--size < 0) |
94 |
+ |
break; |
95 |
+ |
int c = *src++; |
96 |
+ |
dict[dict_idx++] = c; |
97 |
+ |
*dest++ = c; |
98 |
+ |
dict_idx &= 0xfff; |
99 |
+ |
} else { |
100 |
+ |
// Copy from dictionary |
101 |
+ |
if (--size < 0) |
102 |
+ |
break; |
103 |
+ |
int idx = *src++; |
104 |
+ |
if (--size < 0) |
105 |
+ |
break; |
106 |
+ |
int cnt = *src++; |
107 |
+ |
idx |= (cnt << 4) & 0xf00; |
108 |
+ |
cnt = (cnt & 0x0f) + 3; |
109 |
+ |
while (cnt--) { |
110 |
+ |
char c = dict[idx++]; |
111 |
+ |
dict[dict_idx++] = c; |
112 |
+ |
*dest++ = c; |
113 |
+ |
idx &= 0xfff; |
114 |
+ |
dict_idx &= 0xfff; |
115 |
+ |
} |
116 |
+ |
} |
117 |
+ |
} |
118 |
+ |
} |
119 |
+ |
|
120 |
+ |
// Decode parcels of ROM image (MacOS 9.X and even earlier) |
121 |
+ |
void decode_parcels(const uint8 *src, uint8 *dest, int size) |
122 |
+ |
{ |
123 |
+ |
uint32 parcel_offset = 0x14; |
124 |
+ |
D(bug("Offset Type Name\n")); |
125 |
+ |
while (parcel_offset != 0) { |
126 |
+ |
const uint32 *parcel_data = (uint32 *)(src + parcel_offset); |
127 |
+ |
uint32 next_offset = ntohl(parcel_data[0]); |
128 |
+ |
uint32 parcel_type = ntohl(parcel_data[1]); |
129 |
+ |
D(bug("%08x %c%c%c%c %s\n", parcel_offset, |
130 |
+ |
(parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff, |
131 |
+ |
(parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6])); |
132 |
+ |
if (parcel_type == FOURCC('r','o','m',' ')) { |
133 |
+ |
uint32 lzss_offset = ntohl(parcel_data[2]); |
134 |
+ |
uint32 lzss_size = ((uint32)src + parcel_offset) - ((uint32)parcel_data + lzss_offset); |
135 |
+ |
decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size); |
136 |
+ |
} |
137 |
+ |
parcel_offset = next_offset; |
138 |
+ |
} |
139 |
+ |
} |
140 |
+ |
|
141 |
+ |
|
142 |
+ |
/* |
143 |
+ |
* Decode ROM image, 4 MB plain images or NewWorld images |
144 |
+ |
*/ |
145 |
+ |
|
146 |
+ |
bool DecodeROM(uint8 *data, uint32 size) |
147 |
+ |
{ |
148 |
+ |
if (size == ROM_SIZE) { |
149 |
+ |
// Plain ROM image |
150 |
+ |
memcpy((void *)ROM_BASE, data, ROM_SIZE); |
151 |
+ |
return true; |
152 |
+ |
} |
153 |
+ |
else if (strncmp((char *)data, "<CHRP-BOOT>", 11) == 0) { |
154 |
+ |
// CHRP compressed ROM image |
155 |
+ |
uint32 image_offset, image_size; |
156 |
+ |
bool decode_info_ok = false; |
157 |
+ |
|
158 |
+ |
char *s = strstr((char *)data, "constant lzss-offset"); |
159 |
+ |
if (s != NULL) { |
160 |
+ |
// Probably a plain LZSS compressed ROM image |
161 |
+ |
if (sscanf(s - 7, "%06x", &image_offset) == 1) { |
162 |
+ |
s = strstr((char *)data, "constant lzss-size"); |
163 |
+ |
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) |
164 |
+ |
decode_info_ok = true; |
165 |
+ |
} |
166 |
+ |
} |
167 |
+ |
else { |
168 |
+ |
// Probably a MacOS 9.2.x ROM image |
169 |
+ |
s = strstr((char *)data, "constant parcels-offset"); |
170 |
+ |
if (s != NULL) { |
171 |
+ |
if (sscanf(s - 7, "%06x", &image_offset) == 1) { |
172 |
+ |
s = strstr((char *)data, "constant parcels-size"); |
173 |
+ |
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) |
174 |
+ |
decode_info_ok = true; |
175 |
+ |
} |
176 |
+ |
} |
177 |
+ |
} |
178 |
+ |
|
179 |
+ |
// No valid information to decode the ROM found? |
180 |
+ |
if (!decode_info_ok) |
181 |
+ |
return false; |
182 |
+ |
|
183 |
+ |
// Check signature, this could be a parcels-based ROM image |
184 |
+ |
uint32 rom_signature = ntohl(*(uint32 *)(data + image_offset)); |
185 |
+ |
if (rom_signature == FOURCC('p','r','c','l')) { |
186 |
+ |
D(bug("Offset of parcels data: %08x\n", image_offset)); |
187 |
+ |
D(bug("Size of parcels data: %08x\n", image_size)); |
188 |
+ |
decode_parcels(data + image_offset, (uint8 *)ROM_BASE, image_size); |
189 |
+ |
} |
190 |
+ |
else { |
191 |
+ |
D(bug("Offset of compressed data: %08x\n", image_offset)); |
192 |
+ |
D(bug("Size of compressed data: %08x\n", image_size)); |
193 |
+ |
decode_lzss(data + image_offset, (uint8 *)ROM_BASE, image_size); |
194 |
+ |
} |
195 |
+ |
return true; |
196 |
+ |
} |
197 |
+ |
return false; |
198 |
+ |
} |
199 |
+ |
|
200 |
+ |
|
201 |
|
/* |
202 |
|
* Search ROM for byte string, return ROM offset (or 0) |
203 |
|
*/ |
915 |
|
lp = (uint32 *)(ROM_BASE + 0x3131f4); |
916 |
|
if (ntohl(*lp) == 0x7e5f42a6) // NewWorld ROM |
917 |
|
*lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) |
918 |
+ |
lp = (uint32 *)(ROM_BASE + 0x314600); |
919 |
+ |
if (ntohl(*lp) == 0x7d3f42a6) |
920 |
+ |
*lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR) |
921 |
|
|
922 |
|
// Don't read SDR1 |
923 |
|
static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c}; |
1123 |
|
*lp = htonl(0x4e800020); // blr |
1124 |
|
|
1125 |
|
// Extra routine for Reset/FC1E opcode |
1126 |
< |
lp = (uint32 *)(ROM_BASE + 0x36fc00); |
1126 |
> |
lp = (uint32 *)(ROM_BASE + 0x36fb00); |
1127 |
|
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
1128 |
|
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
1129 |
|
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
1144 |
|
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
1145 |
|
*lp++ = htonl(0x7d8802a6); // mflr r12 |
1146 |
|
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
1147 |
< |
*lp++ = htonl(0x814105f4); // lwz r10,0x05f8(r1) |
1147 |
> |
*lp++ = htonl(0x814105f8); // lwz r10,0x05f8(r1) |
1148 |
|
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
1149 |
|
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
1150 |
|
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
1174 |
|
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
1175 |
|
*lp++ = htonl(0x7d8802a6); // mflr r12 |
1176 |
|
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
1177 |
< |
*lp++ = htonl(0x814105f4); // lwz r10,0x05fc(r1) |
1177 |
> |
*lp++ = htonl(0x814105fc); // lwz r10,0x05fc(r1) |
1178 |
|
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
1179 |
|
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
1180 |
|
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
1341 |
|
// Patch UniversalInfo |
1342 |
|
if (ROMType == ROMTYPE_NEWWORLD) { |
1343 |
|
static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00}; |
1344 |
< |
if ((base = find_rom_data(0x14000, 0x16000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false; |
1344 |
> |
if ((base = find_rom_data(0x14000, 0x18000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false; |
1345 |
|
D(bug("universal_info %08lx\n", base)); |
1346 |
|
lp = (uint32 *)(ROM_BASE + base - 0x14); |
1347 |
|
lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); |
1719 |
|
|
1720 |
|
// Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them) |
1721 |
|
static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c}; |
1722 |
< |
if ((base = find_rom_data(0x6000, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false; |
1722 |
> |
if ((base = find_rom_data(0x6000, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false; |
1723 |
|
D(bug("cpu_speed %08lx\n", base)); |
1724 |
|
wp = (uint16 *)(ROM_BASE + base); |
1725 |
|
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
1726 |
|
*wp++ = htons(CPUClockSpeed / 1000000); |
1727 |
|
*wp++ = htons(CPUClockSpeed / 1000000); |
1728 |
|
*wp = htons(M68K_RTS); |
1729 |
< |
if ((base = find_rom_data(base, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) { |
1729 |
> |
if ((base = find_rom_data(base, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) { |
1730 |
|
D(bug("cpu_speed2 %08lx\n", base)); |
1731 |
|
wp = (uint16 *)(ROM_BASE + base); |
1732 |
|
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
2043 |
|
|
2044 |
|
if (ROMType == ROMTYPE_NEWWORLD) { |
2045 |
|
static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26}; |
2046 |
< |
if ((base = find_rom_data(0x15000, 0x18000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false; |
2046 |
> |
if ((base = find_rom_data(0x15000, 0x19000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false; |
2047 |
|
D(bug("via_int3 %08lx\n", base)); |
2048 |
|
wp = (uint16 *)(ROM_BASE + base); // CHRP level 1 handler |
2049 |
|
*wp++ = htons(M68K_JMP); |