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:
gbeauche 2002-04-21 15:07:09 +00:00
parent 05d3e990a5
commit 665c64b4aa
4 changed files with 134 additions and 153 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -31,6 +31,7 @@ enum {
};
extern int ROMType;
extern bool DecodeROM(uint8 *data, uint32 size);
extern bool PatchROM(void);
extern void InstallDrivers(void);

View File

@ -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)
*/