mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-11 10:30:09 +00:00
Add support to decode parcels-based ROMs
- include/rom_patches.h (DecodeROM): Declare. - rom_patches.cpp (DecodeROM): Define. - Unix/main_unix.cpp, BeOS/main_beos.cpp (decode_lzss): Move to... - rom_patches.cpp (decode_lzss): ... here. - Unix/main_unix.cpp (main): Call DecodeROM(). - BeOS/main_beos.cpp (SheepShaver::load_rom): Call DecodeROM().
This commit is contained in:
parent
05d3e990a5
commit
665c64b4aa
@ -736,49 +736,6 @@ void SheepShaver::init_rom(void)
|
||||
* file_read_error: Cannot read ROM file
|
||||
*/
|
||||
|
||||
// Decode LZSS data
|
||||
static void decode_lzss(const uint8 *src, uint8 *dest, int size)
|
||||
{
|
||||
char dict[0x1000];
|
||||
int run_mask = 0, dict_idx = 0xfee;
|
||||
for (;;) {
|
||||
if (run_mask < 0x100) {
|
||||
// Start new run
|
||||
if (--size < 0)
|
||||
break;
|
||||
run_mask = *src++ | 0xff00;
|
||||
}
|
||||
bool bit = run_mask & 1;
|
||||
run_mask >>= 1;
|
||||
if (bit) {
|
||||
// Verbatim copy
|
||||
if (--size < 0)
|
||||
break;
|
||||
int c = *src++;
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
dict_idx &= 0xfff;
|
||||
} else {
|
||||
// Copy from dictionary
|
||||
if (--size < 0)
|
||||
break;
|
||||
int idx = *src++;
|
||||
if (--size < 0)
|
||||
break;
|
||||
int cnt = *src++;
|
||||
idx |= (cnt << 4) & 0xf00;
|
||||
cnt = (cnt & 0x0f) + 3;
|
||||
while (cnt--) {
|
||||
char c = dict[idx++];
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
idx &= 0xfff;
|
||||
dict_idx &= 0xfff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SheepShaver::load_rom(void)
|
||||
{
|
||||
// Get rom file path from preferences
|
||||
@ -807,39 +764,15 @@ void SheepShaver::load_rom(void)
|
||||
|
||||
uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
|
||||
ssize_t actual = file.Read((void *)rom, ROM_SIZE);
|
||||
if (actual == ROM_SIZE) {
|
||||
// Plain ROM image
|
||||
memcpy((void *)ROM_BASE, rom, ROM_SIZE);
|
||||
delete[] rom;
|
||||
} else {
|
||||
if (strncmp((char *)rom, "<CHRP-BOOT>", 11) == 0) {
|
||||
// CHRP compressed ROM image
|
||||
D(bug("CHRP ROM image\n"));
|
||||
uint32 lzss_offset, lzss_size;
|
||||
|
||||
char *s = strstr((char *)rom, "constant lzss-offset");
|
||||
if (s == NULL)
|
||||
throw rom_size_error();
|
||||
s -= 7;
|
||||
if (sscanf(s, "%06lx", &lzss_offset) != 1)
|
||||
throw rom_size_error();
|
||||
s = strstr((char *)rom, "constant lzss-size");
|
||||
if (s == NULL)
|
||||
throw rom_size_error();
|
||||
s -= 7;
|
||||
if (sscanf(s, "%06lx", &lzss_size) != 1)
|
||||
throw rom_size_error();
|
||||
D(bug("Offset of compressed data: %08lx\n", lzss_offset));
|
||||
D(bug("Size of compressed data: %08lx\n", lzss_size));
|
||||
|
||||
D(bug("Uncompressing ROM...\n"));
|
||||
decode_lzss(rom + lzss_offset, (uint8 *)ROM_BASE, lzss_size);
|
||||
delete[] rom;
|
||||
} else if (rom_size != 4*1024*1024)
|
||||
|
||||
// Decode Mac ROM
|
||||
if (!DecodeROM(rom, actual)) {
|
||||
if (rom_size != 4*1024*1024)
|
||||
throw rom_size_error();
|
||||
else
|
||||
throw file_read_error();
|
||||
}
|
||||
delete[] rom;
|
||||
}
|
||||
|
||||
|
||||
|
@ -263,50 +263,6 @@ extern void paranoia_check(void);
|
||||
#endif
|
||||
|
||||
|
||||
// Decode LZSS data
|
||||
static void decode_lzss(const uint8 *src, uint8 *dest, int size)
|
||||
{
|
||||
char dict[0x1000];
|
||||
int run_mask = 0, dict_idx = 0xfee;
|
||||
for (;;) {
|
||||
if (run_mask < 0x100) {
|
||||
// Start new run
|
||||
if (--size < 0)
|
||||
break;
|
||||
run_mask = *src++ | 0xff00;
|
||||
}
|
||||
bool bit = run_mask & 1;
|
||||
run_mask >>= 1;
|
||||
if (bit) {
|
||||
// Verbatim copy
|
||||
if (--size < 0)
|
||||
break;
|
||||
int c = *src++;
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
dict_idx &= 0xfff;
|
||||
} else {
|
||||
// Copy from dictionary
|
||||
if (--size < 0)
|
||||
break;
|
||||
int idx = *src++;
|
||||
if (--size < 0)
|
||||
break;
|
||||
int cnt = *src++;
|
||||
idx |= (cnt << 4) & 0xf00;
|
||||
cnt = (cnt & 0x0f) + 3;
|
||||
while (cnt--) {
|
||||
char c = dict[idx++];
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
idx &= 0xfff;
|
||||
dict_idx &= 0xfff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main program
|
||||
*/
|
||||
@ -540,43 +496,10 @@ int main(int argc, char **argv)
|
||||
rom_tmp = new uint8[ROM_SIZE];
|
||||
actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
|
||||
close(rom_fd);
|
||||
if (actual == ROM_SIZE) {
|
||||
// Plain ROM image
|
||||
memcpy((void *)ROM_BASE, rom_tmp, ROM_SIZE);
|
||||
delete[] rom_tmp;
|
||||
} else {
|
||||
if (strncmp((char *)rom_tmp, "<CHRP-BOOT>", 11) == 0) {
|
||||
// CHRP compressed ROM image
|
||||
D(bug("CHRP ROM image\n"));
|
||||
uint32 lzss_offset, lzss_size;
|
||||
|
||||
char *s = strstr((char *)rom_tmp, "constant lzss-offset");
|
||||
if (s == NULL) {
|
||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||
goto quit;
|
||||
}
|
||||
s -= 7;
|
||||
if (sscanf(s, "%06x", &lzss_offset) != 1) {
|
||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||
goto quit;
|
||||
}
|
||||
s = strstr((char *)rom_tmp, "constant lzss-size");
|
||||
if (s == NULL) {
|
||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||
goto quit;
|
||||
}
|
||||
s -= 7;
|
||||
if (sscanf(s, "%06x", &lzss_size) != 1) {
|
||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||
goto quit;
|
||||
}
|
||||
D(bug("Offset of compressed data: %08x\n", lzss_offset));
|
||||
D(bug("Size of compressed data: %08x\n", lzss_size));
|
||||
|
||||
D(bug("Uncompressing ROM...\n"));
|
||||
decode_lzss(rom_tmp + lzss_offset, (uint8 *)ROM_BASE, lzss_size);
|
||||
delete[] rom_tmp;
|
||||
} else if (rom_size != 4*1024*1024) {
|
||||
|
||||
// Decode Mac ROM
|
||||
if (!DecodeROM(rom_tmp, actual)) {
|
||||
if (rom_size != 4*1024*1024) {
|
||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||
goto quit;
|
||||
} else {
|
||||
@ -584,6 +507,7 @@ int main(int argc, char **argv)
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
delete[] rom_tmp;
|
||||
|
||||
// Load NVRAM
|
||||
XPRAMInit();
|
||||
|
@ -31,6 +31,7 @@ enum {
|
||||
};
|
||||
extern int ROMType;
|
||||
|
||||
extern bool DecodeROM(uint8 *data, uint32 size);
|
||||
extern bool PatchROM(void);
|
||||
extern void InstallDrivers(void);
|
||||
|
||||
|
@ -74,6 +74,129 @@ static bool patch_nanokernel(void);
|
||||
static bool patch_68k(void);
|
||||
|
||||
|
||||
// Decode LZSS data
|
||||
static void decode_lzss(const uint8 *src, uint8 *dest, int size)
|
||||
{
|
||||
char dict[0x1000];
|
||||
int run_mask = 0, dict_idx = 0xfee;
|
||||
for (;;) {
|
||||
if (run_mask < 0x100) {
|
||||
// Start new run
|
||||
if (--size < 0)
|
||||
break;
|
||||
run_mask = *src++ | 0xff00;
|
||||
}
|
||||
bool bit = run_mask & 1;
|
||||
run_mask >>= 1;
|
||||
if (bit) {
|
||||
// Verbatim copy
|
||||
if (--size < 0)
|
||||
break;
|
||||
int c = *src++;
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
dict_idx &= 0xfff;
|
||||
} else {
|
||||
// Copy from dictionary
|
||||
if (--size < 0)
|
||||
break;
|
||||
int idx = *src++;
|
||||
if (--size < 0)
|
||||
break;
|
||||
int cnt = *src++;
|
||||
idx |= (cnt << 4) & 0xf00;
|
||||
cnt = (cnt & 0x0f) + 3;
|
||||
while (cnt--) {
|
||||
char c = dict[idx++];
|
||||
dict[dict_idx++] = c;
|
||||
*dest++ = c;
|
||||
idx &= 0xfff;
|
||||
dict_idx &= 0xfff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode parcels of ROM image (MacOS 9.X and even earlier)
|
||||
void decode_parcels(const uint8 *src, uint8 *dest, int size)
|
||||
{
|
||||
uint32 parcel_offset = 0x14;
|
||||
D(bug("Offset Type Name\n"));
|
||||
while (parcel_offset != 0) {
|
||||
const uint32 *parcel_data = (uint32 *)(src + parcel_offset);
|
||||
parcel_offset = ntohl(parcel_data[0]);
|
||||
uint32 parcel_type = ntohl(parcel_data[1]);
|
||||
D(bug("%08x %c%c%c%c %s\n", parcel_offset,
|
||||
(parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff,
|
||||
(parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6]));
|
||||
if (parcel_type == FOURCC('r','o','m',' ')) {
|
||||
uint32 lzss_offset = ntohl(parcel_data[2]);
|
||||
uint32 lzss_size = ((uint32)src + parcel_offset) - ((uint32)parcel_data + lzss_offset);
|
||||
decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode ROM image, 4 MB plain images or NewWorld images
|
||||
*/
|
||||
|
||||
bool DecodeROM(uint8 *data, uint32 size)
|
||||
{
|
||||
if (size == ROM_SIZE) {
|
||||
// Plain ROM image
|
||||
memcpy((void *)ROM_BASE, data, ROM_SIZE);
|
||||
return true;
|
||||
}
|
||||
else if (strncmp((char *)data, "<CHRP-BOOT>", 11) == 0) {
|
||||
// CHRP compressed ROM image
|
||||
uint32 image_offset, image_size;
|
||||
bool decode_info_ok = false;
|
||||
|
||||
char *s = strstr((char *)data, "constant lzss-offset");
|
||||
if (s != NULL) {
|
||||
// Probably a plain LZSS compressed ROM image
|
||||
if (sscanf(s - 7, "%06x", &image_offset) == 1) {
|
||||
s = strstr((char *)data, "constant lzss-size");
|
||||
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1))
|
||||
decode_info_ok = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Probably a MacOS 9.2.x ROM image
|
||||
s = strstr((char *)data, "constant parcels-offset");
|
||||
if (s != NULL) {
|
||||
if (sscanf(s - 7, "%06x", &image_offset) == 1) {
|
||||
s = strstr((char *)data, "constant parcels-size");
|
||||
if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1))
|
||||
decode_info_ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No valid information to decode the ROM found?
|
||||
if (!decode_info_ok)
|
||||
return false;
|
||||
|
||||
// Check signature, this could be a parcels-based ROM image
|
||||
uint32 rom_signature = ntohl(*(uint32 *)(data + image_offset));
|
||||
if (rom_signature == FOURCC('p','r','c','l')) {
|
||||
D(bug("Offset of parcels data: %08x\n", image_offset));
|
||||
D(bug("Size of parcels data: %08x\n", image_size));
|
||||
decode_parcels(data + image_offset, (uint8 *)ROM_BASE, image_size);
|
||||
}
|
||||
else {
|
||||
D(bug("Offset of compressed data: %08x\n", image_offset));
|
||||
D(bug("Size of compressed data: %08x\n", image_size));
|
||||
decode_lzss(data + image_offset, (uint8 *)ROM_BASE, image_size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search ROM for byte string, return ROM offset (or 0)
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user