1 |
|
/* |
2 |
|
* rom_patches.cpp - ROM patches |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2000 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2008 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
40 |
|
|
41 |
|
// Global variables |
42 |
|
uint32 UniversalInfo; // ROM offset of UniversalInfo |
43 |
< |
uint32 PutScrapPatch; // Mac address of PutScrap() patch |
43 |
> |
uint32 PutScrapPatch = 0; // Mac address of PutScrap() patch |
44 |
> |
uint32 GetScrapPatch = 0; // Mac address of GetScrap() patch |
45 |
|
uint32 ROMBreakpoint = 0; // ROM offset of breakpoint (0 = disabled, 0x2310 = CritError) |
46 |
|
bool PrintROMInfo = false; // Flag: print ROM information in PatchROM() |
47 |
+ |
bool PatchHWBases = true; // Flag: patch hardware base addresses |
48 |
|
|
49 |
< |
static uint32 sony_offset; // ROM offset of .Sony driver |
50 |
< |
static uint32 serd_offset; // ROM offset of SERD resource (serial drivers) |
51 |
< |
static uint32 microseconds_offset; // ROM offset of Microseconds() replacement routine |
49 |
> |
static uint32 sony_offset; // ROM offset of .Sony driver |
50 |
> |
static uint32 serd_offset; // ROM offset of SERD resource (serial drivers) |
51 |
> |
static uint32 microseconds_offset; // ROM offset of Microseconds() replacement routine |
52 |
> |
static uint32 debugutil_offset; // ROM offset of DebugUtil() replacement routine |
53 |
|
|
54 |
|
// Prototypes |
55 |
|
uint16 ROMVersion; |
56 |
|
|
57 |
+ |
/* |
58 |
+ |
* Macros used to extract one of the 16-bit words from a 32-bit word value |
59 |
+ |
*/ |
60 |
+ |
|
61 |
+ |
#define HiWord(X) (((X) >> 16) & 0xffff) |
62 |
+ |
#define LoWord(X) ((X) & 0xffff) |
63 |
+ |
|
64 |
|
|
65 |
|
/* |
66 |
|
* Search ROM for byte string, return ROM offset (or 0) |
280 |
|
printf("Universal Table at %08x:\n", q); |
281 |
|
printf("Offset\t ID\tHWCfg\tROM85\tModel\n"); |
282 |
|
printf("------------------------------------------------\n"); |
283 |
< |
while (ofs = ReadMacInt32(ROMBaseMac + q)) { |
283 |
> |
while ((ofs = ReadMacInt32(ROMBaseMac + q))) { |
284 |
|
print_universal_info(ROMBaseMac + ofs + q); |
285 |
|
q += 4; |
286 |
|
} |
703 |
|
|
704 |
|
void InstallDrivers(uint32 pb) |
705 |
|
{ |
706 |
< |
D(bug("InstallDrivers\n")); |
706 |
> |
D(bug("InstallDrivers, pb %08x\n", pb)); |
707 |
|
M68kRegisters r; |
708 |
|
|
709 |
|
// Install Microseconds() replacement routine |
711 |
|
r.d[0] = 0xa093; |
712 |
|
Execute68kTrap(0xa247, &r); // SetOSTrapAddress() |
713 |
|
|
714 |
+ |
// Install DebugUtil() replacement routine |
715 |
+ |
r.a[0] = ROMBaseMac + debugutil_offset; |
716 |
+ |
r.d[0] = 0xa08d; |
717 |
+ |
Execute68kTrap(0xa247, &r); // SetOSTrapAddress() |
718 |
+ |
|
719 |
|
// Install disk driver |
720 |
|
r.a[0] = ROMBaseMac + sony_offset + 0x100; |
721 |
|
r.d[0] = (uint32)DiskRefNum; |
827 |
|
// Read version |
828 |
|
ROMVersion = ntohs(*(uint16 *)(ROMBaseHost + 8)); |
829 |
|
|
830 |
< |
#if REAL_ADDRESSING |
831 |
< |
// Real addressing mode requires a 32-bit clean ROM |
830 |
> |
#if REAL_ADDRESSING || DIRECT_ADDRESSING |
831 |
> |
// Real and direct addressing modes require a 32-bit clean ROM |
832 |
|
return ROMVersion == ROM_VERSION_32; |
833 |
|
#else |
834 |
|
// Virtual addressing mode works with 32-bit clean Mac II ROMs and Classic ROMs |
945 |
|
*wp++ = htons(M68K_RTS); |
946 |
|
microseconds_offset = (uint8 *)wp - ROMBaseHost; |
947 |
|
*wp++ = htons(M68K_EMUL_OP_MICROSECONDS); |
948 |
+ |
*wp++ = htons(M68K_RTS); |
949 |
+ |
|
950 |
+ |
// Replace DebugUtil |
951 |
+ |
debugutil_offset = (uint8 *)wp - ROMBaseHost; |
952 |
+ |
*wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); |
953 |
|
*wp = htons(M68K_RTS); |
954 |
|
|
955 |
|
// Replace SCSIDispatch() |
999 |
|
*wp++ = htons(M68K_NOP); |
1000 |
|
*wp = htons(M68K_NOP); |
1001 |
|
|
1002 |
< |
wp = (uint16 *)(ROMBaseHost + 0x2be8); // 60Hz handler (handles everything) |
1002 |
> |
wp = (uint16 *)(ROMBaseHost + 0x2be4); // 60Hz handler (handles everything) |
1003 |
> |
*wp++ = htons(M68K_NOP); |
1004 |
> |
*wp++ = htons(M68K_NOP); |
1005 |
|
*wp++ = htons(M68K_EMUL_OP_IRQ); |
1006 |
|
*wp++ = htons(0x4a80); // tst.l d0 |
1007 |
|
*wp = htons(0x67f4); // beq 0x402be2 |
1032 |
|
bp = ROMBaseHost + UniversalInfo + 18; // productKind |
1033 |
|
*bp = PrefsFindInt32("modelid"); |
1034 |
|
|
1035 |
+ |
#if !ROM_IS_WRITE_PROTECTED |
1036 |
+ |
#if defined(USE_SCRATCHMEM_SUBTERFUGE) |
1037 |
+ |
// Set hardware base addresses to scratch memory area |
1038 |
+ |
if (PatchHWBases) { |
1039 |
+ |
extern uint8 *ScratchMem; |
1040 |
+ |
const uint32 ScratchMemBase = Host2MacAddr(ScratchMem); |
1041 |
+ |
|
1042 |
+ |
D(bug("LMGlob\tOfs/4\tBase\n")); |
1043 |
+ |
base = ROMBaseMac + UniversalInfo + ReadMacInt32(ROMBaseMac + UniversalInfo); // decoderInfoPtr |
1044 |
+ |
wp = (uint16 *)(ROMBaseHost + 0x94a); |
1045 |
+ |
while (*wp != 0xffff) { |
1046 |
+ |
int16 ofs = ntohs(*wp++); // offset in decoderInfo (/4) |
1047 |
+ |
int16 lmg = ntohs(*wp++); // address of LowMem global |
1048 |
+ |
D(bug("0x%04x\t%d\t0x%08x\n", lmg, ofs, ReadMacInt32(base + ofs*4))); |
1049 |
+ |
|
1050 |
+ |
// Fake address only if this is not the ASC base |
1051 |
+ |
if (lmg != 0xcc0) |
1052 |
+ |
WriteMacInt32(base + ofs*4, ScratchMemBase); |
1053 |
+ |
} |
1054 |
+ |
} |
1055 |
+ |
#else |
1056 |
+ |
#error System specific handling for writable ROM is required here |
1057 |
+ |
#endif |
1058 |
+ |
#endif |
1059 |
+ |
|
1060 |
|
// Make FPU optional |
1061 |
|
if (FPUType == 0) { |
1062 |
|
bp = ROMBaseHost + UniversalInfo + 22; // defaultRSRCs |
1239 |
|
*wp = htons(M68K_RTS); |
1240 |
|
|
1241 |
|
// Fake CPU speed test (SetupTimeK) |
1242 |
+ |
// *** increased jl : MacsBug uses TimeDBRA for kbd repeat timing |
1243 |
|
wp = (uint16 *)(ROMBaseHost + 0x800); |
1244 |
|
*wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA |
1245 |
< |
*wp++ = htons(100); |
1245 |
> |
*wp++ = htons(10000); |
1246 |
|
*wp++ = htons(0x0d00); |
1247 |
|
*wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA |
1248 |
< |
*wp++ = htons(100); |
1248 |
> |
*wp++ = htons(10000); |
1249 |
|
*wp++ = htons(0x0d02); |
1250 |
|
*wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA |
1251 |
< |
*wp++ = htons(100); |
1251 |
> |
*wp++ = htons(10000); |
1252 |
|
*wp++ = htons(0x0b24); |
1253 |
|
*wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA |
1254 |
< |
*wp++ = htons(100); |
1254 |
> |
*wp++ = htons(10000); |
1255 |
|
*wp++ = htons(0x0cea); |
1256 |
|
*wp = htons(M68K_RTS); |
1257 |
|
|
1258 |
|
#if REAL_ADDRESSING |
1259 |
|
// Move system zone to start of Mac RAM |
1260 |
< |
lp = (uint32 *)(ROMBaseHost + 0x50a); |
1261 |
< |
*lp++ = htonl(RAMBaseMac); |
1262 |
< |
*lp = htonl(RAMBaseMac + 0x1800); |
1260 |
> |
wp = (uint16 *)(ROMBaseHost + 0x50a); |
1261 |
> |
*wp++ = htons(HiWord(RAMBaseMac + 0x2000)); |
1262 |
> |
*wp++ = htons(LoWord(RAMBaseMac + 0x2000)); |
1263 |
> |
*wp++ = htons(HiWord(RAMBaseMac + 0x3800)); |
1264 |
> |
*wp = htons(LoWord(RAMBaseMac + 0x3800)); |
1265 |
|
#endif |
1266 |
|
|
1267 |
|
#if !ROM_IS_WRITE_PROTECTED |
1268 |
< |
#if defined(AMIGA) |
1268 |
> |
#if defined(USE_SCRATCHMEM_SUBTERFUGE) |
1269 |
|
// Set fake handle at 0x0000 to scratch memory area (so broken Mac programs won't write into Mac ROM) |
1270 |
< |
extern uint32 ScratchMem; |
1270 |
> |
extern uint8 *ScratchMem; |
1271 |
> |
const uint32 ScratchMemBase = Host2MacAddr(ScratchMem); |
1272 |
|
wp = (uint16 *)(ROMBaseHost + 0xccaa); |
1273 |
|
*wp++ = htons(0x203c); // move.l #ScratchMem,d0 |
1274 |
< |
*wp++ = htons(ScratchMem >> 16); |
1275 |
< |
*wp = htons(ScratchMem); |
1274 |
> |
*wp++ = htons(ScratchMemBase >> 16); |
1275 |
> |
*wp = htons(ScratchMemBase); |
1276 |
|
#else |
1277 |
|
#error System specific handling for writable ROM is required here |
1278 |
|
#endif |
1284 |
|
*wp++ = htons(M68K_NOP); |
1285 |
|
*wp = htons(M68K_NOP); |
1286 |
|
#endif |
1287 |
< |
|
1287 |
> |
|
1288 |
> |
#if REAL_ADDRESSING && !defined(AMIGA) |
1289 |
> |
// gb-- Temporary hack to get rid of crashes in Speedometer |
1290 |
> |
wp = (uint16 *)(ROMBaseHost + 0xdba2); |
1291 |
> |
if (ntohs(*wp) == 0x662c) // bne.b #$2c |
1292 |
> |
*wp = htons(0x602c); // bra.b #$2c |
1293 |
> |
#endif |
1294 |
> |
|
1295 |
|
// Don't write to VIA in InitTimeMgr |
1296 |
|
wp = (uint16 *)(ROMBaseHost + 0xb0e2); |
1297 |
|
*wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4 |
1487 |
|
if (ROMSize > 0x80000) { |
1488 |
|
|
1489 |
|
// BlockMove() |
1490 |
< |
static const uint8 ptest_dat[] = {0xa0, 0x8d, 0x0c, 0x81, 0x00, 0x00, 0x0c, 0x00, 0x6d, 0x06, 0x4e, 0x71, 0xf4, 0xf8}; |
1491 |
< |
base = find_rom_data(0x87000, 0x87800, ptest_dat, sizeof(ptest_dat)); |
1492 |
< |
D(bug("ptest %08lx\n", base)); |
1490 |
> |
static const uint8 bmove_dat[] = {0x20, 0x5f, 0x22, 0x5f, 0x0c, 0x38, 0x00, 0x04, 0x01, 0x2f}; |
1491 |
> |
base = find_rom_data(0x87000, 0x87800, bmove_dat, sizeof(bmove_dat)); |
1492 |
> |
D(bug("block_move %08lx\n", base)); |
1493 |
|
if (base) { // ROM15/22/23/26/27/32 |
1494 |
< |
wp = (uint16 *)(ROMBaseHost + base + 8); |
1495 |
< |
*wp = htons(M68K_NOP); |
1494 |
> |
wp = (uint16 *)(ROMBaseHost + base + 4); |
1495 |
> |
*wp++ = htons(M68K_EMUL_OP_BLOCK_MOVE); |
1496 |
> |
*wp++ = htons(0x7000); |
1497 |
> |
*wp = htons(M68K_RTS); |
1498 |
|
} |
1499 |
|
|
1500 |
|
// SANE |
1521 |
|
} |
1522 |
|
|
1523 |
|
// Patch .EDisk driver (don't scan for EDisks in the area ROMBase..0xe00000) |
1524 |
< |
uint32 edisk_offset = find_rom_resource('DRVR', 51); |
1524 |
> |
uint32 edisk_offset = find_rom_resource(FOURCC('D','R','V','R'), 51); |
1525 |
|
if (edisk_offset) { |
1526 |
|
static const uint8 edisk_dat[] = {0xd5, 0xfc, 0x00, 0x01, 0x00, 0x00, 0xb5, 0xfc, 0x00, 0xe0, 0x00, 0x00}; |
1527 |
|
base = find_rom_data(edisk_offset, edisk_offset + 0x10000, edisk_dat, sizeof(edisk_dat)); |
1534 |
|
} |
1535 |
|
|
1536 |
|
// Replace .Sony driver |
1537 |
< |
sony_offset = find_rom_resource('DRVR', 4); |
1537 |
> |
sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4); |
1538 |
|
D(bug("sony %08lx\n", sony_offset)); |
1539 |
|
memcpy(ROMBaseHost + sony_offset, sony_driver, sizeof(sony_driver)); |
1540 |
|
|
1553 |
|
memcpy(ROMBaseHost + sony_offset + 0xa00, CDROMIcon, sizeof(CDROMIcon)); |
1554 |
|
|
1555 |
|
// Install SERD patch and serial drivers |
1556 |
< |
serd_offset = find_rom_resource('SERD', 0); |
1556 |
> |
serd_offset = find_rom_resource(FOURCC('S','E','R','D'), 0); |
1557 |
|
D(bug("serd %08lx\n", serd_offset)); |
1558 |
|
wp = (uint16 *)(ROMBaseHost + serd_offset + 12); |
1559 |
|
*wp++ = htons(M68K_EMUL_OP_SERD); |
1586 |
|
*wp++ = htons(M68K_RTS); |
1587 |
|
microseconds_offset = (uint8 *)wp - ROMBaseHost; |
1588 |
|
*wp++ = htons(M68K_EMUL_OP_MICROSECONDS); |
1589 |
+ |
*wp++ = htons(M68K_RTS); |
1590 |
+ |
|
1591 |
+ |
// Replace DebugUtil |
1592 |
+ |
debugutil_offset = (uint8 *)wp - ROMBaseHost; |
1593 |
+ |
*wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); |
1594 |
|
*wp = htons(M68K_RTS); |
1595 |
|
|
1596 |
|
// Replace SCSIDispatch() |
1626 |
|
*wp++ = htons(base >> 16); |
1627 |
|
*wp = htons(base & 0xffff); |
1628 |
|
|
1629 |
< |
#if EMULATED_68K |
1630 |
< |
// Replace BlockMove() |
1631 |
< |
wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa02e)); // BlockMove() |
1632 |
< |
*wp++ = htons(M68K_EMUL_OP_BLOCK_MOVE); |
1633 |
< |
*wp++ = htons(0x7000); |
1634 |
< |
*wp = htons(M68K_RTS); |
1635 |
< |
#endif |
1629 |
> |
// Install GetScrap() patch for clipboard data exchange (the patch is activated by EMUL_OP_INSTALL_DRIVERS) |
1630 |
> |
GetScrapPatch = ROMBaseMac + sony_offset + 0xd00; |
1631 |
> |
base = ROMBaseMac + find_rom_trap(0xa9fd); |
1632 |
> |
wp = (uint16 *)(ROMBaseHost + sony_offset + 0xd00); |
1633 |
> |
*wp++ = htons(M68K_EMUL_OP_GET_SCRAP); |
1634 |
> |
*wp++ = htons(M68K_JMP); |
1635 |
> |
*wp++ = htons(base >> 16); |
1636 |
> |
*wp = htons(base & 0xffff); |
1637 |
|
|
1638 |
|
// Look for double PACK 4 resources |
1639 |
< |
if ((base = find_rom_resource('PACK', 4)) == 0) return false; |
1640 |
< |
if ((base = find_rom_resource('PACK', 4, true)) == 0 && FPUType == 0) |
1639 |
> |
if ((base = find_rom_resource(FOURCC('P','A','C','K'), 4)) == 0) return false; |
1640 |
> |
if ((base = find_rom_resource(FOURCC('P','A','C','K'), 4, true)) == 0 && FPUType == 0) |
1641 |
|
printf("WARNING: This ROM seems to require an FPU\n"); |
1642 |
|
|
1643 |
|
// Patch VIA interrupt handler |
1648 |
|
*wp++ = htons(M68K_NOP); |
1649 |
|
*wp = htons(M68K_NOP); |
1650 |
|
|
1651 |
< |
wp = (uint16 *)(ROMBaseHost + 0xa29a); // 60Hz handler (handles everything) |
1651 |
> |
wp = (uint16 *)(ROMBaseHost + 0xa296); // 60Hz handler (handles everything) |
1652 |
> |
*wp++ = htons(M68K_NOP); |
1653 |
> |
*wp++ = htons(M68K_NOP); |
1654 |
|
*wp++ = htons(M68K_EMUL_OP_IRQ); |
1655 |
|
*wp++ = htons(0x4a80); // tst.l d0 |
1656 |
|
*wp = htons(0x67f4); // beq 0x4080a294 |