1 |
|
/* |
2 |
|
* rom_patches.cpp - ROM patches |
3 |
|
* |
4 |
< |
* SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig |
4 |
> |
* SheepShaver (C) 1997-2004 Christian Bauer and Marc Hellwig |
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 |
62 |
|
const uint32 CHECK_LOAD_PATCH_SPACE = 0x2fcf00; |
63 |
|
const uint32 PUT_SCRAP_PATCH_SPACE = 0x2fcf80; |
64 |
|
const uint32 GET_SCRAP_PATCH_SPACE = 0x2fcfc0; |
65 |
< |
const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd000; |
65 |
> |
const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd100; |
66 |
|
|
67 |
|
// Global variables |
68 |
|
int ROMType; // ROM type |
311 |
|
|
312 |
|
|
313 |
|
/* |
314 |
+ |
* Check that requested ROM patch space is really available |
315 |
+ |
*/ |
316 |
+ |
|
317 |
+ |
static bool check_rom_patch_space(uint32 base, uint32 size) |
318 |
+ |
{ |
319 |
+ |
size = (size + 3) & -4; |
320 |
+ |
for (int i = 0; i < size; i += 4) { |
321 |
+ |
uint32 x = ntohl(*(uint32 *)(ROM_BASE + base + i)); |
322 |
+ |
if (x != 0x6b636b63 && x != 0) |
323 |
+ |
return false; |
324 |
+ |
} |
325 |
+ |
return true; |
326 |
+ |
} |
327 |
+ |
|
328 |
+ |
|
329 |
+ |
/* |
330 |
|
* List of audio sifters installed in ROM and System file |
331 |
|
*/ |
332 |
|
|
713 |
|
return false; |
714 |
|
|
715 |
|
// Check that other ROM addresses point to really free regions |
716 |
< |
if (ntohl(*(uint32 *)(ROM_BASE + CHECK_LOAD_PATCH_SPACE)) != 0x6b636b63) |
716 |
> |
if (!check_rom_patch_space(CHECK_LOAD_PATCH_SPACE, 0x40)) |
717 |
|
return false; |
718 |
< |
if (ntohl(*(uint32 *)(ROM_BASE + PUT_SCRAP_PATCH_SPACE)) != 0x6b636b63) |
718 |
> |
if (!check_rom_patch_space(PUT_SCRAP_PATCH_SPACE, 0x40)) |
719 |
|
return false; |
720 |
< |
if (ntohl(*(uint32 *)(ROM_BASE + GET_SCRAP_PATCH_SPACE)) != 0x6b636b63) |
720 |
> |
if (!check_rom_patch_space(GET_SCRAP_PATCH_SPACE, 0x40)) |
721 |
|
return false; |
722 |
< |
if (ntohl(*(uint32 *)(ROM_BASE + ADDR_MAP_PATCH_SPACE)) != 0x6b636b63) |
722 |
> |
if (!check_rom_patch_space(ADDR_MAP_PATCH_SPACE - 10 * 4, 0x100)) |
723 |
|
return false; |
724 |
|
|
725 |
|
// Apply patches |
871 |
|
lp[8] = htonl(0x00800002); // TLB total size/TLB assoc |
872 |
|
break; |
873 |
|
// case 11: // X704? |
874 |
< |
case 12: // ??? |
874 |
> |
case 12: // 7400, 7410 |
875 |
> |
case 0x800c: |
876 |
|
lp[0] = htonl(0x1000); // Page size |
877 |
|
lp[1] = htonl(0x8000); // Data cache size |
878 |
|
lp[2] = htonl(0x8000); // Inst cache size |
1058 |
|
static bool patch_68k_emul(void) |
1059 |
|
{ |
1060 |
|
uint32 *lp; |
1061 |
< |
uint32 base; |
1061 |
> |
uint32 base, loc; |
1062 |
|
|
1063 |
|
// Overwrite twi instructions |
1064 |
|
static const uint8 twi_dat[] = {0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0x0f, 0xff, 0x00, 0x02}; |
1122 |
|
// Extra routine for 68k emulator start |
1123 |
|
lp = (uint32 *)(ROM_BASE + 0x36f900); |
1124 |
|
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
1108 |
– |
#if EMULATED_PPC |
1109 |
– |
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
1110 |
– |
#else |
1125 |
|
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
1126 |
|
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
1127 |
|
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
1114 |
– |
#endif |
1128 |
|
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
1129 |
|
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
1130 |
|
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
1152 |
|
// Extra routine for Mixed Mode |
1153 |
|
lp = (uint32 *)(ROM_BASE + 0x36fa00); |
1154 |
|
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
1142 |
– |
#if EMULATED_PPC |
1143 |
– |
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
1144 |
– |
#else |
1155 |
|
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
1156 |
|
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
1157 |
|
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
1148 |
– |
#endif |
1158 |
|
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
1159 |
|
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
1160 |
|
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
1182 |
|
// Extra routine for Reset/FC1E opcode |
1183 |
|
lp = (uint32 *)(ROM_BASE + 0x36fb00); |
1184 |
|
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
1176 |
– |
#if EMULATED_PPC |
1177 |
– |
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
1178 |
– |
#else |
1185 |
|
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
1186 |
|
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
1187 |
|
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
1182 |
– |
#endif |
1188 |
|
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
1189 |
|
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
1190 |
|
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
1212 |
|
// Extra routine for FE0A opcode (QuickDraw 3D needs this) |
1213 |
|
lp = (uint32 *)(ROM_BASE + 0x36fc00); |
1214 |
|
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
1210 |
– |
#if EMULATED_PPC |
1211 |
– |
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
1212 |
– |
#else |
1215 |
|
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
1216 |
|
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
1217 |
|
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
1216 |
– |
#endif |
1218 |
|
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
1219 |
|
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
1220 |
|
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
1250 |
|
return false; |
1251 |
|
dr_found: |
1252 |
|
lp++; |
1253 |
< |
*lp = htonl(0x48000000 + 0xf000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b DR_CACHE_BASE+0x1f000 |
1254 |
< |
lp = (uint32 *)(ROM_BASE + 0x37f000); |
1255 |
< |
*lp++ = htonl(0x3c000000 + ((ROM_BASE + 0x46d0a4) >> 16)); // lis r0,xxx |
1256 |
< |
*lp++ = htonl(0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff)); // ori r0,r0,xxx |
1257 |
< |
*lp++ = htonl(0x7c0903a6); // mtctr r0 |
1258 |
< |
*lp = htonl(POWERPC_BCTR); // bctr |
1253 |
> |
loc = (uint32)lp - ROM_BASE; |
1254 |
> |
if ((base = powerpc_branch_target(ROM_BASE + loc)) == 0) base = ROM_BASE + loc; |
1255 |
> |
static const uint8 dr_ret_dat[] = {0x80, 0xbf, 0x08, 0x14, 0x53, 0x19, 0x4d, 0xac, 0x7c, 0xa8, 0x03, 0xa6}; |
1256 |
> |
if ((base = find_rom_data(base - ROM_BASE, 0x380000, dr_ret_dat, sizeof(dr_ret_dat))) == 0) return false; |
1257 |
> |
D(bug("dr_ret %08lx\n", base)); |
1258 |
> |
if (base != loc) { |
1259 |
> |
// OldWorld ROMs contain an absolute branch |
1260 |
> |
D(bug(" patching absolute branch at %08x\n", (uint32)lp - ROM_BASE)); |
1261 |
> |
*lp = htonl(0x48000000 + 0xf000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b DR_CACHE_BASE+0x1f000 |
1262 |
> |
lp = (uint32 *)(ROM_BASE + 0x37f000); |
1263 |
> |
*lp++ = htonl(0x3c000000 + ((ROM_BASE + base) >> 16)); // lis r0,xxx |
1264 |
> |
*lp++ = htonl(0x60000000 + ((ROM_BASE + base) & 0xffff)); // ori r0,r0,xxx |
1265 |
> |
*lp++ = htonl(0x7c0803a6); // mtlr r0 |
1266 |
> |
*lp = htonl(POWERPC_BLR); // blr |
1267 |
> |
} |
1268 |
|
return true; |
1269 |
|
} |
1270 |
|
|
1381 |
|
uint32 npc = (uint32)(lp + 1) - ROM_BASE; |
1382 |
|
|
1383 |
|
lp = (uint32 *)(ROM_BASE + 0x318000); |
1374 |
– |
#if EMULATED_PPC |
1375 |
– |
*lp++ = htonl(NativeOpcode(NATIVE_ENABLE_INTERRUPT)); |
1376 |
– |
*lp = htonl(0x48000000 + ((npc - 0x318004) & 0x03fffffc)); // b ROM_BASE+0x312c2c |
1377 |
– |
#else |
1384 |
|
*lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST |
1385 |
|
*lp++ = htonl(0x394affff); // subi r10,r10,1 |
1386 |
|
*lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST |
1387 |
|
*lp = htonl(0x48000000 + ((npc - 0x31800c) & 0x03fffffc)); // b ROM_BASE+0x312c2c |
1382 |
– |
#endif |
1388 |
|
|
1389 |
|
/* |
1390 |
|
// Disable FE0A/FE06 opcodes |
1651 |
|
D(bug("scc_init_caller %08lx\n", base + 12)); |
1652 |
|
wp = (uint16 *)(ROM_BASE + base + 12); |
1653 |
|
loc = ntohs(wp[1]) + ((uintptr)wp - ROM_BASE) + 2; |
1654 |
< |
static const uint8 scc_init_dat[] = {0x08, 0x38, 0x00, 0x03, 0x0d, 0xd3, 0x67, 0x12, 0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8}; |
1655 |
< |
if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) != loc) return false; |
1654 |
> |
static const uint8 scc_init_dat[] = {0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8}; |
1655 |
> |
if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) == 0) return false; |
1656 |
|
D(bug("scc_init %08lx\n", base)); |
1657 |
|
wp = (uint16 *)(ROM_BASE + base); |
1658 |
|
*wp++ = htons(M68K_EMUL_OP_RESET); |
2216 |
|
lp = (uint32 *)(ROM_BASE + ntohl(*lp)); |
2217 |
|
lp[0xa9fd & 0x3ff] = htonl(GET_SCRAP_PATCH_SPACE); |
2218 |
|
|
2214 |
– |
#if __BEOS__ |
2219 |
|
// Patch SynchIdleTime() |
2220 |
|
if (PrefsFindBool("idlewait")) { |
2221 |
|
wp = (uint16 *)(ROM_BASE + find_rom_trap(0xabf7) + 4); // SynchIdleTime() |
2222 |
|
D(bug("SynchIdleTime at %08lx\n", wp)); |
2223 |
< |
if (ntohs(*wp) == 0x2078) { |
2223 |
> |
if (ntohs(*wp) == 0x2078) { // movea.l ExpandMem,a0 |
2224 |
|
*wp++ = htons(M68K_EMUL_OP_IDLE_TIME); |
2225 |
|
*wp = htons(M68K_NOP); |
2226 |
< |
} else { |
2226 |
> |
} |
2227 |
> |
else if (ntohs(*wp) == 0x70fe) // moveq #-2,d0 |
2228 |
> |
*wp++ = htons(M68K_EMUL_OP_IDLE_TIME_2); |
2229 |
> |
else { |
2230 |
|
D(bug("SynchIdleTime patch not installed\n")); |
2231 |
|
} |
2232 |
|
} |
2226 |
– |
#endif |
2233 |
|
|
2234 |
|
// Construct list of all sifters used by sound components in ROM |
2235 |
|
D(bug("Searching for sound components with type sdev in ROM\n")); |
2294 |
|
WriteMacInt16(dce + dCtlFlags, SonyDriverFlags); |
2295 |
|
} |
2296 |
|
|
2297 |
< |
#if DISABLE_SCSI && 0 |
2297 |
> |
#if DISABLE_SCSI && HAVE_SIGSEGV_SKIP_INSTRUCTION |
2298 |
|
// Fake SCSIGlobals |
2299 |
|
WriteMacInt32(0xc0c, SheepMem::ZeroPage()); |
2300 |
|
#endif |