mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-26 16:31:11 +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
|
* 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)
|
void SheepShaver::load_rom(void)
|
||||||
{
|
{
|
||||||
// Get rom file path from preferences
|
// 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
|
uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
|
||||||
ssize_t actual = file.Read((void *)rom, ROM_SIZE);
|
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");
|
// Decode Mac ROM
|
||||||
if (s == NULL)
|
if (!DecodeROM(rom, actual)) {
|
||||||
throw rom_size_error();
|
if (rom_size != 4*1024*1024)
|
||||||
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)
|
|
||||||
throw rom_size_error();
|
throw rom_size_error();
|
||||||
else
|
else
|
||||||
throw file_read_error();
|
throw file_read_error();
|
||||||
}
|
}
|
||||||
|
delete[] rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -263,50 +263,6 @@ extern void paranoia_check(void);
|
|||||||
#endif
|
#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
|
* Main program
|
||||||
*/
|
*/
|
||||||
@ -540,43 +496,10 @@ int main(int argc, char **argv)
|
|||||||
rom_tmp = new uint8[ROM_SIZE];
|
rom_tmp = new uint8[ROM_SIZE];
|
||||||
actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
|
actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
|
||||||
close(rom_fd);
|
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");
|
// Decode Mac ROM
|
||||||
if (s == NULL) {
|
if (!DecodeROM(rom_tmp, actual)) {
|
||||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
if (rom_size != 4*1024*1024) {
|
||||||
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) {
|
|
||||||
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
ErrorAlert(GetString(STR_ROM_SIZE_ERR));
|
||||||
goto quit;
|
goto quit;
|
||||||
} else {
|
} else {
|
||||||
@ -584,6 +507,7 @@ int main(int argc, char **argv)
|
|||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delete[] rom_tmp;
|
||||||
|
|
||||||
// Load NVRAM
|
// Load NVRAM
|
||||||
XPRAMInit();
|
XPRAMInit();
|
||||||
|
@ -31,6 +31,7 @@ enum {
|
|||||||
};
|
};
|
||||||
extern int ROMType;
|
extern int ROMType;
|
||||||
|
|
||||||
|
extern bool DecodeROM(uint8 *data, uint32 size);
|
||||||
extern bool PatchROM(void);
|
extern bool PatchROM(void);
|
||||||
extern void InstallDrivers(void);
|
extern void InstallDrivers(void);
|
||||||
|
|
||||||
|
@ -74,6 +74,129 @@ static bool patch_nanokernel(void);
|
|||||||
static bool patch_68k(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)
|
* Search ROM for byte string, return ROM offset (or 0)
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user