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 |
+ |
parcel_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 |
+ |
} |
138 |
+ |
} |
139 |
+ |
|
140 |
+ |
|
141 |
+ |
/* |
142 |
+ |
* Decode ROM image, 4 MB plain images or NewWorld images |
143 |
+ |
*/ |
144 |
+ |
|
145 |
+ |
bool DecodeROM(uint8 *data, uint32 size) |
146 |
+ |
{ |
147 |
+ |
if (size == ROM_SIZE) { |
148 |
+ |
// Plain ROM image |
149 |
+ |
memcpy((void *)ROM_BASE, data, ROM_SIZE); |
150 |
+ |
return true; |
151 |
+ |
} |
152 |
+ |
else if (strncmp((char *)data, "<CHRP-BOOT>", 11) == 0) { |
153 |
+ |
// CHRP compressed ROM image |
154 |
+ |
uint32 image_offset, image_size; |
155 |
+ |
bool decode_info_ok = false; |
156 |
+ |
|
157 |
+ |
char *s = strstr((char *)data, "constant lzss-offset"); |
158 |
+ |
if (s != NULL) { |
159 |
+ |
// Probably a plain LZSS compressed ROM image |
160 |
+ |
if (sscanf(s - 7, "%06x", &image_offset) == 1) { |
161 |
+ |
s = strstr((char *)data, "constant lzss-size"); |
162 |
+ |
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) |
163 |
+ |
decode_info_ok = true; |
164 |
+ |
} |
165 |
+ |
} |
166 |
+ |
else { |
167 |
+ |
// Probably a MacOS 9.2.x ROM image |
168 |
+ |
s = strstr((char *)data, "constant parcels-offset"); |
169 |
+ |
if (s != NULL) { |
170 |
+ |
if (sscanf(s - 7, "%06x", &image_offset) == 1) { |
171 |
+ |
s = strstr((char *)data, "constant parcels-size"); |
172 |
+ |
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) |
173 |
+ |
decode_info_ok = true; |
174 |
+ |
} |
175 |
+ |
} |
176 |
+ |
} |
177 |
+ |
|
178 |
+ |
// No valid information to decode the ROM found? |
179 |
+ |
if (!decode_info_ok) |
180 |
+ |
return false; |
181 |
+ |
|
182 |
+ |
// Check signature, this could be a parcels-based ROM image |
183 |
+ |
uint32 rom_signature = ntohl(*(uint32 *)(data + image_offset)); |
184 |
+ |
if (rom_signature == FOURCC('p','r','c','l')) { |
185 |
+ |
D(bug("Offset of parcels data: %08x\n", image_offset)); |
186 |
+ |
D(bug("Size of parcels data: %08x\n", image_size)); |
187 |
+ |
decode_parcels(data + image_offset, (uint8 *)ROM_BASE, image_size); |
188 |
+ |
} |
189 |
+ |
else { |
190 |
+ |
D(bug("Offset of compressed data: %08x\n", image_offset)); |
191 |
+ |
D(bug("Size of compressed data: %08x\n", image_size)); |
192 |
+ |
decode_lzss(data + image_offset, (uint8 *)ROM_BASE, image_size); |
193 |
+ |
} |
194 |
+ |
return true; |
195 |
+ |
} |
196 |
+ |
return false; |
197 |
+ |
} |
198 |
+ |
|
199 |
+ |
|
200 |
|
/* |
201 |
|
* Search ROM for byte string, return ROM offset (or 0) |
202 |
|
*/ |