--- BasiliskII/src/rom_patches.cpp 1999/10/03 14:16:25 1.1 +++ BasiliskII/src/rom_patches.cpp 2004/11/15 23:27:43 1.24 @@ -1,7 +1,7 @@ /* * rom_patches.cpp - ROM patches * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2004 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include "disk.h" #include "cdrom.h" #include "video.h" +#include "extfs.h" #include "prefs.h" #include "rom_patches.h" @@ -37,22 +38,29 @@ #include "debug.h" -// Breakpoint -//#define M68K_BREAKPOINT 0x2310 // CritError -//#define M68K_BREAKPOINT 0x1d10 // BootMe - // Global variables -uint32 UniversalInfo; // ROM offset of UniversalInfo -uint32 PutScrapPatch; // Mac address of PutScrap() patch +uint32 UniversalInfo; // ROM offset of UniversalInfo +uint32 PutScrapPatch; // Mac address of PutScrap() patch +uint32 GetScrapPatch = 0; // Mac address of GetScrap() patch +uint32 ROMBreakpoint = 0; // ROM offset of breakpoint (0 = disabled, 0x2310 = CritError) +bool PrintROMInfo = false; // Flag: print ROM information in PatchROM() +bool PatchHWBases = true; // Flag: patch hardware base addresses static uint32 sony_offset; // ROM offset of .Sony driver static uint32 serd_offset; // ROM offset of SERD resource (serial drivers) static uint32 microseconds_offset; // ROM offset of Microseconds() replacement routine -static uint32 memory_dispatch_offset; // ROM offset of MemoryDispatch() replacement routine +static uint32 debugutil_offset; // ROM offset of DebugUtil() replacement routine // Prototypes uint16 ROMVersion; +/* + * Macros used to extract one of the 16-bit words from a 32-bit word value + */ + +#define HiWord(X) (((X) >> 16) & 0xffff) +#define LoWord(X) ((X) & 0xffff) + /* * Search ROM for byte string, return ROM offset (or 0) @@ -83,6 +91,8 @@ static uint32 find_rom_resource(uint32 s if (!cont) rsrc_ptr = x; + else + rsrc_ptr = ReadMacInt32(ROMBaseMac + rsrc_ptr + 8); for (;;) { lp = ROMBaseMac + rsrc_ptr; @@ -141,12 +151,167 @@ again: /* + * Print ROM information to stream, + */ + +static void list_rom_resources(void) +{ + printf("ROM Resources:\n"); + printf("Offset\t Type\tID\tSize\tName\n"); + printf("------------------------------------------------\n"); + + uint32 lp = ROMBaseMac + ReadMacInt32(ROMBaseMac + 0x1a); + uint32 rsrc_ptr = ReadMacInt32(lp); + + for (;;) { + lp = ROMBaseMac + rsrc_ptr; + uint32 data = ReadMacInt32(lp + 12); + + char name[32]; + int name_len = ReadMacInt8(lp + 23), i; + for (i=0; i= 0; i++) + if (MacDesc[i].id == id + 6) { + name = MacDesc[i].name; + break; + } + + printf("%08x %02x\t%04x\t%04x\t%s\n", info - ROMBaseMac, id, hwcfg, rom85, name); +} + +static void list_universal_infos(void) +{ + uint32 ofs = 0x3000; + for (int i=0; i<0x2000; i+=2, ofs+=2) + if (ReadMacInt32(ROMBaseMac + ofs) == 0xdc000505) { + ofs -= 16; + uint32 q; + for (q=ofs; q > 0 && ReadMacInt32(ROMBaseMac + q) != ofs - q; q-=4) ; + if (q > 0) { + printf("Universal Table at %08x:\n", q); + printf("Offset\t ID\tHWCfg\tROM85\tModel\n"); + printf("------------------------------------------------\n"); + while ((ofs = ReadMacInt32(ROMBaseMac + q))) { + print_universal_info(ROMBaseMac + ofs + q); + q += 4; + } + } + break; + } + printf("\n"); +} + +static void print_rom_info(void) +{ + printf("\nROM Info:\n"); + printf("Checksum : %08x\n", ReadMacInt32(ROMBaseMac)); + printf("Version : %04x\n", ROMVersion); + printf("Sub Version : %04x\n", ReadMacInt16(ROMBaseMac + 18)); + printf("Resource Map: %08x\n", ReadMacInt32(ROMBaseMac + 26)); + printf("Trap Tables : %08x\n\n", ReadMacInt32(ROMBaseMac + 34)); + if (ROMVersion == ROM_VERSION_32) { + list_rom_resources(); + list_universal_infos(); + } +} + + +/* * Driver stubs */ static const uint8 sony_driver[] = { // Replacement for .Sony driver // Driver header - SonyDriverFlags >> 8, SonyDriverFlags & 0xff, SonyDriverDelay >> 8, SonyDriverDelay & 0xff, 0x00, 0x00, 0x00, 0x00, + SonyDriverFlags >> 8, SonyDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, 0x00, 0x18, // Open() offset 0x00, 0x1c, // Prime() offset 0x00, 0x20, // Control() offset @@ -194,7 +359,7 @@ static const uint8 sony_driver[] = { // static const uint8 disk_driver[] = { // Generic disk driver // Driver header - DiskDriverFlags >> 8, DiskDriverFlags & 0xff, DiskDriverDelay >> 8, DiskDriverDelay & 0xff, 0x00, 0x00, 0x00, 0x00, + DiskDriverFlags >> 8, DiskDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, 0x00, 0x18, // Open() offset 0x00, 0x1c, // Prime() offset 0x00, 0x20, // Control() offset @@ -242,7 +407,7 @@ static const uint8 disk_driver[] = { // static const uint8 cdrom_driver[] = { // CD-ROM driver // Driver header - CDROMDriverFlags >> 8, CDROMDriverFlags & 0xff, CDROMDriverDelay >> 8, CDROMDriverDelay & 0xff, 0x00, 0x00, 0x00, 0x00, + CDROMDriverFlags >> 8, CDROMDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, 0x00, 0x1c, // Open() offset 0x00, 0x20, // Prime() offset 0x00, 0x24, // Control() offset @@ -538,7 +703,7 @@ static const uint8 adbop_patch[] = { // void InstallDrivers(uint32 pb) { - D(bug("InstallDrivers\n")); + D(bug("InstallDrivers, pb %08x\n", pb)); M68kRegisters r; // Install Microseconds() replacement routine @@ -546,6 +711,11 @@ void InstallDrivers(uint32 pb) r.d[0] = 0xa093; Execute68kTrap(0xa247, &r); // SetOSTrapAddress() + // Install DebugUtil() replacement routine + r.a[0] = ROMBaseMac + debugutil_offset; + r.d[0] = 0xa08d; + Execute68kTrap(0xa247, &r); // SetOSTrapAddress() + // Install disk driver r.a[0] = ROMBaseMac + sony_offset + 0x100; r.d[0] = (uint32)DiskRefNum; @@ -555,7 +725,6 @@ void InstallDrivers(uint32 pb) uint32 dce = ReadMacInt32(r.a[0]); WriteMacInt32(dce + dCtlDriver, ROMBaseMac + sony_offset + 0x100); WriteMacInt16(dce + dCtlFlags, DiskDriverFlags); - WriteMacInt16(dce + dCtlDelay, DiskDriverDelay); // Open disk driver WriteMacInt32(pb + ioNamePtr, ROMBaseMac + sony_offset + 0x112); @@ -574,7 +743,6 @@ void InstallDrivers(uint32 pb) dce = ReadMacInt32(r.a[0]); WriteMacInt32(dce + dCtlDriver, ROMBaseMac + sony_offset + 0x200); WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags); - WriteMacInt16(dce + dCtlDelay, CDROMDriverDelay); // Open CD-ROM driver WriteMacInt32(pb + ioNamePtr, ROMBaseMac + sony_offset + 0x212); @@ -643,11 +811,10 @@ void InstallSERD(void) void PatchAfterStartup(void) { - // Install MemoryDispatch() replacement routine - M68kRegisters r; - r.a[0] = ROMBaseMac + memory_dispatch_offset; - r.d[0] = 0xa05c; - Execute68kTrap(0xa247, &r); // SetOSTrapAddress() +#if SUPPORTS_EXTFS + // Install external file system + InstallExtFS(); +#endif } @@ -660,11 +827,11 @@ bool CheckROM(void) // Read version ROMVersion = ntohs(*(uint16 *)(ROMBaseHost + 8)); -#if REAL_ADDRESSING - // Real addressing mode requires a 32-bit clean ROM +#if REAL_ADDRESSING || DIRECT_ADDRESSING + // Real and direct addressing modes require a 32-bit clean ROM return ROMVersion == ROM_VERSION_32; #else - // Virtual addressing mode works with 32-bit clean Mac II ROMs and Classic ROMs (experimental) + // Virtual addressing mode works with 32-bit clean Mac II ROMs and Classic ROMs return (ROMVersion == ROM_VERSION_CLASSIC) || (ROMVersion == ROM_VERSION_32); #endif } @@ -778,6 +945,11 @@ static bool patch_rom_classic(void) *wp++ = htons(M68K_RTS); microseconds_offset = (uint8 *)wp - ROMBaseHost; *wp++ = htons(M68K_EMUL_OP_MICROSECONDS); + *wp++ = htons(M68K_RTS); + + // Replace DebugUtil + debugutil_offset = (uint8 *)wp - ROMBaseHost; + *wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); *wp = htons(M68K_RTS); // Replace SCSIDispatch() @@ -827,7 +999,9 @@ static bool patch_rom_classic(void) *wp++ = htons(M68K_NOP); *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + 0x2be8); // 60Hz handler (handles everything) + wp = (uint16 *)(ROMBaseHost + 0x2be4); // 60Hz handler (handles everything) + *wp++ = htons(M68K_NOP); + *wp++ = htons(M68K_NOP); *wp++ = htons(M68K_EMUL_OP_IRQ); *wp++ = htons(0x4a80); // tst.l d0 *wp = htons(0x67f4); // beq 0x402be2 @@ -858,6 +1032,31 @@ static bool patch_rom_32(void) bp = ROMBaseHost + UniversalInfo + 18; // productKind *bp = PrefsFindInt32("modelid"); +#if !ROM_IS_WRITE_PROTECTED +#if defined(USE_SCRATCHMEM_SUBTERFUGE) + // Set hardware base addresses to scratch memory area + if (PatchHWBases) { + extern uint8 *ScratchMem; + const uint32 ScratchMemBase = Host2MacAddr(ScratchMem); + + D(bug("LMGlob\tOfs/4\tBase\n")); + base = ROMBaseMac + UniversalInfo + ReadMacInt32(ROMBaseMac + UniversalInfo); // decoderInfoPtr + wp = (uint16 *)(ROMBaseHost + 0x94a); + while (*wp != 0xffff) { + int16 ofs = ntohs(*wp++); // offset in decoderInfo (/4) + int16 lmg = ntohs(*wp++); // address of LowMem global + D(bug("0x%04x\t%d\t0x%08x\n", lmg, ofs, ReadMacInt32(base + ofs*4))); + + // Fake address only if this is not the ASC base + if (lmg != 0xcc0) + WriteMacInt32(base + ofs*4, ScratchMemBase); + } + } +#else +#error System specific handling for writable ROM is required here +#endif +#endif + // Make FPU optional if (FPUType == 0) { bp = ROMBaseHost + UniversalInfo + 22; // defaultRSRCs @@ -1040,36 +1239,40 @@ static bool patch_rom_32(void) *wp = htons(M68K_RTS); // Fake CPU speed test (SetupTimeK) + // *** increased jl : MacsBug uses TimeDBRA for kbd repeat timing wp = (uint16 *)(ROMBaseHost + 0x800); *wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0d00); *wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0d02); *wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0b24); *wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0cea); *wp = htons(M68K_RTS); #if REAL_ADDRESSING // Move system zone to start of Mac RAM - lp = (uint32 *)(ROMBaseHost + 0x50a); - *lp++ = htonl(RAMBaseMac); - *lp = htonl(RAMBaseMac + 0x1800); + wp = (uint16 *)(ROMBaseHost + 0x50a); + *wp++ = htons(HiWord(RAMBaseMac + 0x2000)); + *wp++ = htons(LoWord(RAMBaseMac + 0x2000)); + *wp++ = htons(HiWord(RAMBaseMac + 0x3800)); + *wp = htons(LoWord(RAMBaseMac + 0x3800)); #endif #if !ROM_IS_WRITE_PROTECTED -#if defined(AMIGA) +#if defined(USE_SCRATCHMEM_SUBTERFUGE) // Set fake handle at 0x0000 to scratch memory area (so broken Mac programs won't write into Mac ROM) - extern uint32 ScratchMem; + extern uint8 *ScratchMem; + const uint32 ScratchMemBase = Host2MacAddr(ScratchMem); wp = (uint16 *)(ROMBaseHost + 0xccaa); *wp++ = htons(0x203c); // move.l #ScratchMem,d0 - *wp++ = htons(ScratchMem >> 16); - *wp = htons(ScratchMem); + *wp++ = htons(ScratchMemBase >> 16); + *wp = htons(ScratchMemBase); #else #error System specific handling for writable ROM is required here #endif @@ -1081,7 +1284,14 @@ static bool patch_rom_32(void) *wp++ = htons(M68K_NOP); *wp = htons(M68K_NOP); #endif - + +#if REAL_ADDRESSING && !defined(AMIGA) + // gb-- Temporary hack to get rid of crashes in Speedometer + wp = (uint16 *)(ROMBaseHost + 0xdba2); + if (ntohs(*wp) == 0x662c) // bne.b #$2c + *wp = htons(0x602c); // bra.b #$2c +#endif + // Don't write to VIA in InitTimeMgr wp = (uint16 *)(ROMBaseHost + 0xb0e2); *wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4 @@ -1153,13 +1363,20 @@ static bool patch_rom_32(void) *wp++ = htons(M68K_NOP); *wp = htons(M68K_NOP); - // Fix logical/physical RAM size (CompBootStack) (must be done after InitMemMgr!) - static const uint8 fix_memsize_dat[] = {0x4e, 0x75}; - if ((base = find_rom_data(0x490, 0x4b0, fix_memsize_dat, sizeof(fix_memsize_dat))) == 0) return false; - D(bug("fix_memsize %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); + // Compute boot stack pointer and fix logical/physical RAM size (CompBootStack) (must be done after InitMemMgr!) + wp = (uint16 *)(ROMBaseHost + 0x490); + *wp++ = htons(0x2038); // move.l $10c,d0 + *wp++ = htons(0x010c); + *wp++ = htons(0xd0b8); // add.l $2a6,d0 + *wp++ = htons(0x02a6); + *wp++ = htons(0xe288); // lsr.l #1,d0 + *wp++ = htons(0x0880); // bclr #0,d0 + *wp++ = htons(0x0000); + *wp++ = htons(0x0440); // subi.w #$400,d0 + *wp++ = htons(0x0400); + *wp++ = htons(0x2040); // move.l d0,a0 *wp++ = htons(M68K_EMUL_OP_FIX_MEMSIZE); - *wp = htons(M68K_RTS); + *wp++ = htons(M68K_RTS); static const uint8 fix_memsize2_dat[] = {0x22, 0x30, 0x81, 0xe2, 0x0d, 0xdc, 0xff, 0xba, 0xd2, 0xb0, 0x81, 0xe2, 0x0d, 0xdc, 0xff, 0xec, 0x21, 0xc1, 0x1e, 0xf8}; base = find_rom_data(0x4c000, 0x4c080, fix_memsize2_dat, sizeof(fix_memsize2_dat)); @@ -1270,12 +1487,14 @@ static bool patch_rom_32(void) if (ROMSize > 0x80000) { // BlockMove() - static const uint8 ptest_dat[] = {0xa0, 0x8d, 0x0c, 0x81, 0x00, 0x00, 0x0c, 0x00, 0x6d, 0x06, 0x4e, 0x71, 0xf4, 0xf8}; - base = find_rom_data(0x87000, 0x87800, ptest_dat, sizeof(ptest_dat)); - D(bug("ptest %08lx\n", base)); + static const uint8 bmove_dat[] = {0x20, 0x5f, 0x22, 0x5f, 0x0c, 0x38, 0x00, 0x04, 0x01, 0x2f}; + base = find_rom_data(0x87000, 0x87800, bmove_dat, sizeof(bmove_dat)); + D(bug("block_move %08lx\n", base)); if (base) { // ROM15/22/23/26/27/32 - wp = (uint16 *)(ROMBaseHost + base + 8); - *wp = htons(M68K_NOP); + wp = (uint16 *)(ROMBaseHost + base + 4); + *wp++ = htons(M68K_EMUL_OP_BLOCK_MOVE); + *wp++ = htons(0x7000); + *wp = htons(M68K_RTS); } // SANE @@ -1292,8 +1511,17 @@ static bool patch_rom_32(void) } } + // Don't set MemoryDispatch() to unimplemented trap + static const uint8 memdisp_dat[] = {0x30, 0x3c, 0xa8, 0x9f, 0xa7, 0x46, 0x30, 0x3c, 0xa0, 0x5c, 0xa2, 0x47}; + base = find_rom_data(0x4f100, 0x4f180, memdisp_dat, sizeof(memdisp_dat)); + D(bug("memdisp %08lx\n", base)); + if (base) { // ROM15/22/23/26/27/32 + wp = (uint16 *)(ROMBaseHost + base + 10); + *wp = htons(M68K_NOP); + } + // Patch .EDisk driver (don't scan for EDisks in the area ROMBase..0xe00000) - uint32 edisk_offset = find_rom_resource('DRVR', 51); + uint32 edisk_offset = find_rom_resource(FOURCC('D','R','V','R'), 51); if (edisk_offset) { static const uint8 edisk_dat[] = {0xd5, 0xfc, 0x00, 0x01, 0x00, 0x00, 0xb5, 0xfc, 0x00, 0xe0, 0x00, 0x00}; base = find_rom_data(edisk_offset, edisk_offset + 0x10000, edisk_dat, sizeof(edisk_dat)); @@ -1306,7 +1534,7 @@ static bool patch_rom_32(void) } // Replace .Sony driver - sony_offset = find_rom_resource('DRVR', 4); + sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4); D(bug("sony %08lx\n", sony_offset)); memcpy(ROMBaseHost + sony_offset, sony_driver, sizeof(sony_driver)); @@ -1325,7 +1553,7 @@ static bool patch_rom_32(void) memcpy(ROMBaseHost + sony_offset + 0xa00, CDROMIcon, sizeof(CDROMIcon)); // Install SERD patch and serial drivers - serd_offset = find_rom_resource('SERD', 0); + serd_offset = find_rom_resource(FOURCC('S','E','R','D'), 0); D(bug("serd %08lx\n", serd_offset)); wp = (uint16 *)(ROMBaseHost + serd_offset + 12); *wp++ = htons(M68K_EMUL_OP_SERD); @@ -1358,6 +1586,11 @@ static bool patch_rom_32(void) *wp++ = htons(M68K_RTS); microseconds_offset = (uint8 *)wp - ROMBaseHost; *wp++ = htons(M68K_EMUL_OP_MICROSECONDS); + *wp++ = htons(M68K_RTS); + + // Replace DebugUtil + debugutil_offset = (uint8 *)wp - ROMBaseHost; + *wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); *wp = htons(M68K_RTS); // Replace SCSIDispatch() @@ -1393,11 +1626,19 @@ static bool patch_rom_32(void) *wp++ = htons(base >> 16); *wp = htons(base & 0xffff); - // Install MemoryDispatch() replacement routine (activated in PatchAfterStartup()) - memory_dispatch_offset = sony_offset + 0xc20; - wp = (uint16 *)(ROMBaseHost + memory_dispatch_offset); - *wp++ = htons(M68K_EMUL_OP_MEMORY_DISPATCH); - *wp = htons(M68K_RTS); + // Install GetScrap() patch for clipboard data exchange (the patch is activated by EMUL_OP_INSTALL_DRIVERS) + GetScrapPatch = ROMBaseMac + sony_offset + 0xd00; + base = ROMBaseMac + find_rom_trap(0xa9fd); + wp = (uint16 *)(ROMBaseHost + sony_offset + 0xd00); + *wp++ = htons(M68K_EMUL_OP_GET_SCRAP); + *wp++ = htons(M68K_JMP); + *wp++ = htons(base >> 16); + *wp = htons(base & 0xffff); + + // Look for double PACK 4 resources + if ((base = find_rom_resource(FOURCC('P','A','C','K'), 4)) == 0) return false; + if ((base = find_rom_resource(FOURCC('P','A','C','K'), 4, true)) == 0 && FPUType == 0) + printf("WARNING: This ROM seems to require an FPU\n"); // Patch VIA interrupt handler wp = (uint16 *)(ROMBaseHost + 0x9bc4); // Level 1 handler @@ -1407,7 +1648,9 @@ static bool patch_rom_32(void) *wp++ = htons(M68K_NOP); *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + 0xa29a); // 60Hz handler (handles everything) + wp = (uint16 *)(ROMBaseHost + 0xa296); // 60Hz handler (handles everything) + *wp++ = htons(M68K_NOP); + *wp++ = htons(M68K_NOP); *wp++ = htons(M68K_EMUL_OP_IRQ); *wp++ = htons(0x4a80); // tst.l d0 *wp = htons(0x67f4); // beq 0x4080a294 @@ -1416,11 +1659,9 @@ static bool patch_rom_32(void) bool PatchROM(void) { - // Print ROM info - D(bug("ROM Info:\n")); - D(bug("Checksum: %08lx\n", ReadMacInt32(ROMBaseMac))); - D(bug("Version: %04x\n", ROMVersion)); - D(bug("Sub Version: %04x\n", ReadMacInt16(ROMBaseMac + 18))); + // Print some information about the ROM + if (PrintROMInfo) + print_rom_info(); // Patch ROM depending on version switch (ROMVersion) { @@ -1436,11 +1677,11 @@ bool PatchROM(void) return false; } -#ifdef M68K_BREAKPOINT // Install breakpoint - uint16 *wp = (uint16 *)(ROMBaseHost + M68K_BREAKPOINT); - *wp = htons(M68K_EMUL_BREAK); -#endif + if (ROMBreakpoint) { + uint16 *wp = (uint16 *)(ROMBaseHost + ROMBreakpoint); + *wp = htons(M68K_EMUL_BREAK); + } // Clear caches as we loaded and patched code FlushCodeCache(ROMBaseHost, ROMSize);