From 665c64b4aa673e8e78acf8451cc685a77e87e14b Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 21 Apr 2002 15:07:09 +0000 Subject: [PATCH] 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(). --- SheepShaver/src/BeOS/main_beos.cpp | 77 ++-------------- SheepShaver/src/Unix/main_unix.cpp | 86 ++---------------- SheepShaver/src/include/rom_patches.h | 1 + SheepShaver/src/rom_patches.cpp | 123 ++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 153 deletions(-) diff --git a/SheepShaver/src/BeOS/main_beos.cpp b/SheepShaver/src/BeOS/main_beos.cpp index d0fa5185..7abc6c03 100644 --- a/SheepShaver/src/BeOS/main_beos.cpp +++ b/SheepShaver/src/BeOS/main_beos.cpp @@ -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, "", 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; } diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp index 3816fba4..dec62d3b 100644 --- a/SheepShaver/src/Unix/main_unix.cpp +++ b/SheepShaver/src/Unix/main_unix.cpp @@ -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, "", 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(); diff --git a/SheepShaver/src/include/rom_patches.h b/SheepShaver/src/include/rom_patches.h index c0916410..299d2e58 100644 --- a/SheepShaver/src/include/rom_patches.h +++ b/SheepShaver/src/include/rom_patches.h @@ -31,6 +31,7 @@ enum { }; extern int ROMType; +extern bool DecodeROM(uint8 *data, uint32 size); extern bool PatchROM(void); extern void InstallDrivers(void); diff --git a/SheepShaver/src/rom_patches.cpp b/SheepShaver/src/rom_patches.cpp index 5db990f7..0e788405 100644 --- a/SheepShaver/src/rom_patches.cpp +++ b/SheepShaver/src/rom_patches.cpp @@ -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, "", 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) */