--- SheepShaver/src/rom_patches.cpp 2002/02/04 16:58:13 1.1.1.1 +++ SheepShaver/src/rom_patches.cpp 2003/09/29 20:30:19 1.9 @@ -74,6 +74,130 @@ 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); + uint32 next_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); + } + parcel_offset = next_offset; + } +} + + +/* + * 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) */ @@ -323,7 +447,17 @@ static const uint8 cdrom_driver[] = { // 0x4e, 0x75 // rts }; -#ifdef __linux__ +#if EMULATED_PPC +#define SERIAL_TRAMPOLINES 1 +static uint32 serial_nothing_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_NOTHING), 0}; +static uint32 serial_open_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_OPEN), 0}; +static uint32 serial_prime_in_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_PRIME_IN), 0}; +static uint32 serial_prime_out_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_PRIME_OUT), 0}; +static uint32 serial_control_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_CONTROL), 0}; +static uint32 serial_status_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_STATUS), 0}; +static uint32 serial_close_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_CLOSE), 0}; +#elif defined(__linux__) +#define SERIAL_TRAMPOLINES 1 static uint32 serial_nothing_tvect[2] = {(uint32)SerialNothing, 0}; static uint32 serial_open_tvect[2] = {(uint32)SerialOpen, 0}; static uint32 serial_prime_in_tvect[2] = {(uint32)SerialPrimeIn, 0}; @@ -340,7 +474,7 @@ static const uint32 ain_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -348,7 +482,7 @@ static const uint32 ain_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_in_tvect, #else 0x00010004, (uint32)SerialPrimeIn, @@ -356,7 +490,7 @@ static const uint32 ain_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -364,7 +498,7 @@ static const uint32 ain_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -372,7 +506,7 @@ static const uint32 ain_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -387,7 +521,7 @@ static const uint32 aout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_open_tvect, #else 0x00010004, (uint32)SerialOpen, @@ -395,7 +529,7 @@ static const uint32 aout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_out_tvect, #else 0x00010004, (uint32)SerialPrimeOut, @@ -403,7 +537,7 @@ static const uint32 aout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -411,7 +545,7 @@ static const uint32 aout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -419,7 +553,7 @@ static const uint32 aout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_close_tvect, #else 0x00010004, (uint32)SerialClose, @@ -434,7 +568,7 @@ static const uint32 bin_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -442,7 +576,7 @@ static const uint32 bin_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_in_tvect, #else 0x00010004, (uint32)SerialPrimeIn, @@ -450,7 +584,7 @@ static const uint32 bin_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -458,7 +592,7 @@ static const uint32 bin_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -466,7 +600,7 @@ static const uint32 bin_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -481,7 +615,7 @@ static const uint32 bout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_open_tvect, #else 0x00010004, (uint32)SerialOpen, @@ -489,7 +623,7 @@ static const uint32 bout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_out_tvect, #else 0x00010004, (uint32)SerialPrimeOut, @@ -497,7 +631,7 @@ static const uint32 bout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -505,7 +639,7 @@ static const uint32 bout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -513,7 +647,7 @@ static const uint32 bout_driver[] = { // 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_close_tvect, #else 0x00010004, (uint32)SerialClose, @@ -545,6 +679,23 @@ static const uint8 adbop_patch[] = { // /* + * Copy PowerPC code to ROM image and reverse bytes if necessary + */ + +static inline void memcpy_powerpc_code(void *dst, const void *src, size_t len) +{ +#ifdef WORDS_BIGENDIAN + (void)memcpy(dst, src, len); +#else + uint32 *d = (uint32 *)dst; + uint32 *s = (uint32 *)src; + for (int i = 0; i < len/4; i++) + d[i] = htonl(s[i]); +#endif +} + + +/* * Install ROM patches (RAMBase and KernelDataAddr must be set) */ @@ -791,6 +942,9 @@ static bool patch_nanokernel_boot(void) lp = (uint32 *)(ROM_BASE + 0x3131f4); if (ntohl(*lp) == 0x7e5f42a6) // NewWorld ROM *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) + lp = (uint32 *)(ROM_BASE + 0x314600); + if (ntohl(*lp) == 0x7d3f42a6) + *lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR) // Don't read SDR1 static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c}; @@ -903,15 +1057,17 @@ static bool patch_68k_emul(void) *lp = htonl(POWERPC_ILLEGAL); #if EMULATED_PPC - // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes + // Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3)); *lp++ = htonl(POWERPC_EMUL_OP); *lp++ = htonl(0x4bf66e80); // b 0x366084 *lp++ = htonl(POWERPC_EMUL_OP | 1); *lp++ = htonl(0x4bf66e78); // b 0x366084 + *lp++ = htonl(POWERPC_EMUL_OP | 2); + *lp++ = htonl(0x4bf66e70); // b 0x366084 for (int i=0; i> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); @@ -1592,14 +1772,14 @@ static bool patch_68k(void) // Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them) static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c}; - if ((base = find_rom_data(0x6000, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false; + if ((base = find_rom_data(0x6000, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false; D(bug("cpu_speed %08lx\n", base)); wp = (uint16 *)(ROM_BASE + base); *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 *wp++ = htons(CPUClockSpeed / 1000000); *wp++ = htons(CPUClockSpeed / 1000000); *wp = htons(M68K_RTS); - if ((base = find_rom_data(base, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) { + if ((base = find_rom_data(base, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) { D(bug("cpu_speed2 %08lx\n", base)); wp = (uint16 *)(ROM_BASE + base); *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 @@ -1803,10 +1983,10 @@ static bool patch_68k(void) memcpy((void *)(ROM_BASE + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver)); // Install serial drivers - memcpy((void *)(ROM_BASE + sony_offset + 0x300), ain_driver, sizeof(ain_driver)); - memcpy((void *)(ROM_BASE + sony_offset + 0x400), aout_driver, sizeof(aout_driver)); - memcpy((void *)(ROM_BASE + sony_offset + 0x500), bin_driver, sizeof(bin_driver)); - memcpy((void *)(ROM_BASE + sony_offset + 0x600), bout_driver, sizeof(bout_driver)); + memcpy_powerpc_code((void *)(ROM_BASE + sony_offset + 0x300), ain_driver, sizeof(ain_driver)); + memcpy_powerpc_code((void *)(ROM_BASE + sony_offset + 0x400), aout_driver, sizeof(aout_driver)); + memcpy_powerpc_code((void *)(ROM_BASE + sony_offset + 0x500), bin_driver, sizeof(bin_driver)); + memcpy_powerpc_code((void *)(ROM_BASE + sony_offset + 0x600), bout_driver, sizeof(bout_driver)); // Copy icons to ROM SonyDiskIconAddr = ROM_BASE + sony_offset + 0x800; @@ -1886,7 +2066,9 @@ static bool patch_68k(void) wp = (uint16 *)(ROM_BASE + base); if (ROMType == ROMTYPE_ZANZIBAR) *wp = htons(M68K_RTS); - else + else if (ntohs(wp[-4]) == 0x61ff) + *wp = htons(M68K_RTS); + else if (ntohs(wp[-2]) == 0x6700) wp[-2] = htons(0x6000); // bra // Patch PowerOff() @@ -1916,7 +2098,7 @@ static bool patch_68k(void) if (ROMType == ROMTYPE_NEWWORLD) { static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26}; - if ((base = find_rom_data(0x15000, 0x18000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false; + if ((base = find_rom_data(0x15000, 0x19000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false; D(bug("via_int3 %08lx\n", base)); wp = (uint16 *)(ROM_BASE + base); // CHRP level 1 handler *wp++ = htons(M68K_JMP); @@ -2008,6 +2190,26 @@ void InstallDrivers(void) M68kRegisters r; uint8 pb[SIZEOF_IOParam]; + // Install floppy driver + if (ROMType == ROMTYPE_NEWWORLD) { + + // Force installation of floppy driver with NewWorld ROMs + r.a[0] = ROM_BASE + sony_offset; + r.d[0] = (uint32)SonyRefNum; + Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() + r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~SonyRefNum * 4); // Get driver handle from Unit Table + Execute68kTrap(0xa029, &r); // HLock() + uint32 dce = ReadMacInt32(r.a[0]); + WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset); + WriteMacInt16(dce + dCtlFlags, SonyDriverFlags); + } + +#if DISABLE_SCSI && 0 + // Fake SCSIGlobals + static const uint8 fake_scsi_globals[32] = {0,}; + WriteMacInt32(0xc0c, (uint32)fake_scsi_globals); +#endif + // Open .Sony driver WriteMacInt8((uint32)pb + ioPermssn, 0); WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\005.Sony");