| 40 |
#include "audio_defs.h" |
#include "audio_defs.h" |
| 41 |
#include "serial.h" |
#include "serial.h" |
| 42 |
#include "macos_util.h" |
#include "macos_util.h" |
| 43 |
|
#include "thunks.h" |
| 44 |
|
|
| 45 |
#define DEBUG 0 |
#define DEBUG 0 |
| 46 |
#include "debug.h" |
#include "debug.h" |
| 59 |
|
|
| 60 |
|
|
| 61 |
// Other ROM addresses |
// Other ROM addresses |
| 62 |
const uint32 CHECK_LOAD_PATCH_SPACE = 0x2f7f00; |
const uint32 CHECK_LOAD_PATCH_SPACE = 0x2fcf00; |
| 63 |
const uint32 PUT_SCRAP_PATCH_SPACE = 0x2f7f80; |
const uint32 PUT_SCRAP_PATCH_SPACE = 0x2fcf80; |
| 64 |
const uint32 GET_SCRAP_PATCH_SPACE = 0x2f7fc0; |
const uint32 GET_SCRAP_PATCH_SPACE = 0x2fcfc0; |
| 65 |
const uint32 ADDR_MAP_PATCH_SPACE = 0x2f8000; |
const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd100; |
| 66 |
|
|
| 67 |
// Global variables |
// Global variables |
| 68 |
int ROMType; // ROM type |
int ROMType; // ROM type |
| 125 |
D(bug("Offset Type Name\n")); |
D(bug("Offset Type Name\n")); |
| 126 |
while (parcel_offset != 0) { |
while (parcel_offset != 0) { |
| 127 |
const uint32 *parcel_data = (uint32 *)(src + parcel_offset); |
const uint32 *parcel_data = (uint32 *)(src + parcel_offset); |
| 128 |
parcel_offset = ntohl(parcel_data[0]); |
uint32 next_offset = ntohl(parcel_data[0]); |
| 129 |
uint32 parcel_type = ntohl(parcel_data[1]); |
uint32 parcel_type = ntohl(parcel_data[1]); |
| 130 |
D(bug("%08x %c%c%c%c %s\n", parcel_offset, |
D(bug("%08x %c%c%c%c %s\n", parcel_offset, |
| 131 |
(parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff, |
(parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff, |
| 132 |
(parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6])); |
(parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6])); |
| 133 |
if (parcel_type == FOURCC('r','o','m',' ')) { |
if (parcel_type == FOURCC('r','o','m',' ')) { |
| 134 |
uint32 lzss_offset = ntohl(parcel_data[2]); |
uint32 lzss_offset = ntohl(parcel_data[2]); |
| 135 |
uint32 lzss_size = ((uint32)src + parcel_offset) - ((uint32)parcel_data + lzss_offset); |
uint32 lzss_size = ((uintptr)src + next_offset) - ((uintptr)parcel_data + lzss_offset); |
| 136 |
decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size); |
decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size); |
| 137 |
} |
} |
| 138 |
|
parcel_offset = next_offset; |
| 139 |
} |
} |
| 140 |
} |
} |
| 141 |
|
|
| 270 |
|
|
| 271 |
|
|
| 272 |
/* |
/* |
| 273 |
|
* Return target of branch instruction specified at ADDR, or 0 if |
| 274 |
|
* there is no such instruction |
| 275 |
|
*/ |
| 276 |
|
|
| 277 |
|
static uint32 powerpc_branch_target(uintptr addr) |
| 278 |
|
{ |
| 279 |
|
uint32 opcode = ntohl(*(uint32 *)addr); |
| 280 |
|
uint32 primop = opcode >> 26; |
| 281 |
|
uint32 target = 0; |
| 282 |
|
|
| 283 |
|
if (primop == 18) { // Branch |
| 284 |
|
target = opcode & 0x3fffffc; |
| 285 |
|
if (target & 0x2000000) |
| 286 |
|
target |= 0xfc000000; |
| 287 |
|
if ((opcode & 2) == 0) |
| 288 |
|
target += addr; |
| 289 |
|
} |
| 290 |
|
else if (primop == 16) { // Branch Conditional |
| 291 |
|
target = (int32)(int16)(opcode & 0xfffc); |
| 292 |
|
if ((opcode & 2) == 0) |
| 293 |
|
target += addr; |
| 294 |
|
} |
| 295 |
|
return target; |
| 296 |
|
} |
| 297 |
|
|
| 298 |
|
|
| 299 |
|
/* |
| 300 |
|
* Search ROM for instruction branching to target address, return 0 if none found |
| 301 |
|
*/ |
| 302 |
|
|
| 303 |
|
static uint32 find_rom_powerpc_branch(uint32 start, uint32 end, uint32 target) |
| 304 |
|
{ |
| 305 |
|
for (uint32 addr = start; addr < end; addr += 4) { |
| 306 |
|
if (powerpc_branch_target(ROM_BASE + addr) == ROM_BASE + target) |
| 307 |
|
return addr; |
| 308 |
|
} |
| 309 |
|
return 0; |
| 310 |
|
} |
| 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 |
* List of audio sifters installed in ROM and System file |
| 331 |
*/ |
*/ |
| 332 |
|
|
| 505 |
0x4e, 0x75 // rts |
0x4e, 0x75 // rts |
| 506 |
}; |
}; |
| 507 |
|
|
| 508 |
#ifdef __linux__ |
static uint32 long_ptr; |
|
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}; |
|
|
static uint32 serial_prime_out_tvect[2] = {(uint32)SerialPrimeOut, 0}; |
|
|
static uint32 serial_control_tvect[2] = {(uint32)SerialControl, 0}; |
|
|
static uint32 serial_status_tvect[2] = {(uint32)SerialStatus, 0}; |
|
|
static uint32 serial_close_tvect[2] = {(uint32)SerialClose, 0}; |
|
|
#endif |
|
| 509 |
|
|
| 510 |
static const uint32 ain_driver[] = { // .AIn driver header |
static void SetLongBase(uint32 addr) |
| 511 |
0x4d000000, 0x00000000, |
{ |
| 512 |
0x00200040, 0x00600080, |
long_ptr = addr; |
| 513 |
0x00a0042e, 0x41496e00, |
} |
| 514 |
0x00000000, 0x00000000, |
|
| 515 |
0xaafe0700, 0x00000000, |
static void Long(uint32 value) |
| 516 |
0x00000000, 0x00179822, |
{ |
| 517 |
#ifdef __linux__ |
WriteMacInt32(long_ptr, value); |
| 518 |
0x00010004, (uint32)serial_nothing_tvect, |
long_ptr += 4; |
| 519 |
#else |
} |
| 520 |
0x00010004, (uint32)SerialNothing, |
|
| 521 |
#endif |
static void gen_ain_driver(uintptr addr) |
| 522 |
0x00000000, 0x00000000, |
{ |
| 523 |
0xaafe0700, 0x00000000, |
SetLongBase(addr); |
| 524 |
0x00000000, 0x00179822, |
|
| 525 |
#ifdef __linux__ |
// .AIn driver header |
| 526 |
0x00010004, (uint32)serial_prime_in_tvect, |
Long(0x4d000000); Long(0x00000000); |
| 527 |
#else |
Long(0x00200040); Long(0x00600080); |
| 528 |
0x00010004, (uint32)SerialPrimeIn, |
Long(0x00a0042e); Long(0x41496e00); |
| 529 |
#endif |
Long(0x00000000); Long(0x00000000); |
| 530 |
0x00000000, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 531 |
0xaafe0700, 0x00000000, |
Long(0x00000000); Long(0x00179822); |
| 532 |
0x00000000, 0x00179822, |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); |
| 533 |
#ifdef __linux__ |
Long(0x00000000); Long(0x00000000); |
| 534 |
0x00010004, (uint32)serial_control_tvect, |
Long(0xaafe0700); Long(0x00000000); |
| 535 |
#else |
Long(0x00000000); Long(0x00179822); |
| 536 |
0x00010004, (uint32)SerialControl, |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN)); |
| 537 |
#endif |
Long(0x00000000); Long(0x00000000); |
| 538 |
0x00000000, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 539 |
0xaafe0700, 0x00000000, |
Long(0x00000000); Long(0x00179822); |
| 540 |
0x00000000, 0x00179822, |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); |
| 541 |
#ifdef __linux__ |
Long(0x00000000); Long(0x00000000); |
| 542 |
0x00010004, (uint32)serial_status_tvect, |
Long(0xaafe0700); Long(0x00000000); |
| 543 |
#else |
Long(0x00000000); Long(0x00179822); |
| 544 |
0x00010004, (uint32)SerialStatus, |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); |
| 545 |
#endif |
Long(0x00000000); Long(0x00000000); |
| 546 |
0x00000000, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 547 |
0xaafe0700, 0x00000000, |
Long(0x00000000); Long(0x00179822); |
| 548 |
0x00000000, 0x00179822, |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); |
| 549 |
#ifdef __linux__ |
Long(0x00000000); Long(0x00000000); |
|
0x00010004, (uint32)serial_nothing_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialNothing, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
| 550 |
}; |
}; |
| 551 |
|
|
| 552 |
static const uint32 aout_driver[] = { // .AOut driver header |
static void gen_aout_driver(uintptr addr) |
| 553 |
0x4d000000, 0x00000000, |
{ |
| 554 |
0x00200040, 0x00600080, |
SetLongBase(addr); |
| 555 |
0x00a0052e, 0x414f7574, |
|
| 556 |
0x00000000, 0x00000000, |
// .AOut driver header |
| 557 |
0xaafe0700, 0x00000000, |
Long(0x4d000000); Long(0x00000000); |
| 558 |
0x00000000, 0x00179822, |
Long(0x00200040); Long(0x00600080); |
| 559 |
#ifdef __linux__ |
Long(0x00a0052e); Long(0x414f7574); |
| 560 |
0x00010004, (uint32)serial_open_tvect, |
Long(0x00000000); Long(0x00000000); |
| 561 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 562 |
0x00010004, (uint32)SerialOpen, |
Long(0x00000000); Long(0x00179822); |
| 563 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN)); |
| 564 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 565 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 566 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 567 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT)); |
| 568 |
0x00010004, (uint32)serial_prime_out_tvect, |
Long(0x00000000); Long(0x00000000); |
| 569 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 570 |
0x00010004, (uint32)SerialPrimeOut, |
Long(0x00000000); Long(0x00179822); |
| 571 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); |
| 572 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 573 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 574 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 575 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); |
| 576 |
0x00010004, (uint32)serial_control_tvect, |
Long(0x00000000); Long(0x00000000); |
| 577 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 578 |
0x00010004, (uint32)SerialControl, |
Long(0x00000000); Long(0x00179822); |
| 579 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE)); |
| 580 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_status_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialStatus, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_close_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialClose, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
| 581 |
}; |
}; |
| 582 |
|
|
| 583 |
static const uint32 bin_driver[] = { // .BIn driver header |
static void gen_bin_driver(uintptr addr) |
| 584 |
0x4d000000, 0x00000000, |
{ |
| 585 |
0x00200040, 0x00600080, |
SetLongBase(addr); |
| 586 |
0x00a0042e, 0x42496e00, |
|
| 587 |
0x00000000, 0x00000000, |
// .BIn driver header |
| 588 |
0xaafe0700, 0x00000000, |
Long(0x4d000000); Long(0x00000000); |
| 589 |
0x00000000, 0x00179822, |
Long(0x00200040); Long(0x00600080); |
| 590 |
#ifdef __linux__ |
Long(0x00a0042e); Long(0x42496e00); |
| 591 |
0x00010004, (uint32)serial_nothing_tvect, |
Long(0x00000000); Long(0x00000000); |
| 592 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 593 |
0x00010004, (uint32)SerialNothing, |
Long(0x00000000); Long(0x00179822); |
| 594 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); |
| 595 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 596 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 597 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 598 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN)); |
| 599 |
0x00010004, (uint32)serial_prime_in_tvect, |
Long(0x00000000); Long(0x00000000); |
| 600 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 601 |
0x00010004, (uint32)SerialPrimeIn, |
Long(0x00000000); Long(0x00179822); |
| 602 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); |
| 603 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 604 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 605 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 606 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); |
| 607 |
0x00010004, (uint32)serial_control_tvect, |
Long(0x00000000); Long(0x00000000); |
| 608 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 609 |
0x00010004, (uint32)SerialControl, |
Long(0x00000000); Long(0x00179822); |
| 610 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); |
| 611 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_status_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialStatus, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_nothing_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialNothing, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
| 612 |
}; |
}; |
| 613 |
|
|
| 614 |
static const uint32 bout_driver[] = { // .BOut driver header |
static void gen_bout_driver(uintptr addr) |
| 615 |
0x4d000000, 0x00000000, |
{ |
| 616 |
0x00200040, 0x00600080, |
SetLongBase(addr); |
| 617 |
0x00a0052e, 0x424f7574, |
|
| 618 |
0x00000000, 0x00000000, |
// .BOut driver header |
| 619 |
0xaafe0700, 0x00000000, |
Long(0x4d000000); Long(0x00000000); |
| 620 |
0x00000000, 0x00179822, |
Long(0x00200040); Long(0x00600080); |
| 621 |
#ifdef __linux__ |
Long(0x00a0052e); Long(0x424f7574); |
| 622 |
0x00010004, (uint32)serial_open_tvect, |
Long(0x00000000); Long(0x00000000); |
| 623 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 624 |
0x00010004, (uint32)SerialOpen, |
Long(0x00000000); Long(0x00179822); |
| 625 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN)); |
| 626 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 627 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 628 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 629 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT)); |
| 630 |
0x00010004, (uint32)serial_prime_out_tvect, |
Long(0x00000000); Long(0x00000000); |
| 631 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 632 |
0x00010004, (uint32)SerialPrimeOut, |
Long(0x00000000); Long(0x00179822); |
| 633 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); |
| 634 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
| 635 |
0xaafe0700, 0x00000000, |
Long(0xaafe0700); Long(0x00000000); |
| 636 |
0x00000000, 0x00179822, |
Long(0x00000000); Long(0x00179822); |
| 637 |
#ifdef __linux__ |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); |
| 638 |
0x00010004, (uint32)serial_control_tvect, |
Long(0x00000000); Long(0x00000000); |
| 639 |
#else |
Long(0xaafe0700); Long(0x00000000); |
| 640 |
0x00010004, (uint32)SerialControl, |
Long(0x00000000); Long(0x00179822); |
| 641 |
#endif |
Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE)); |
| 642 |
0x00000000, 0x00000000, |
Long(0x00000000); Long(0x00000000); |
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_status_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialStatus, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
|
0xaafe0700, 0x00000000, |
|
|
0x00000000, 0x00179822, |
|
|
#ifdef __linux__ |
|
|
0x00010004, (uint32)serial_close_tvect, |
|
|
#else |
|
|
0x00010004, (uint32)SerialClose, |
|
|
#endif |
|
|
0x00000000, 0x00000000, |
|
| 643 |
}; |
}; |
| 644 |
|
|
| 645 |
static const uint8 adbop_patch[] = { // Call ADBOp() completion procedure |
static const uint8 adbop_patch[] = { // Call ADBOp() completion procedure |
| 666 |
|
|
| 667 |
|
|
| 668 |
/* |
/* |
| 669 |
|
* Copy PowerPC code to ROM image and reverse bytes if necessary |
| 670 |
|
*/ |
| 671 |
|
|
| 672 |
|
static inline void memcpy_powerpc_code(void *dst, const void *src, size_t len) |
| 673 |
|
{ |
| 674 |
|
#ifdef WORDS_BIGENDIAN |
| 675 |
|
(void)memcpy(dst, src, len); |
| 676 |
|
#else |
| 677 |
|
uint32 *d = (uint32 *)dst; |
| 678 |
|
uint32 *s = (uint32 *)src; |
| 679 |
|
for (int i = 0; i < len/4; i++) |
| 680 |
|
d[i] = htonl(s[i]); |
| 681 |
|
#endif |
| 682 |
|
} |
| 683 |
|
|
| 684 |
|
|
| 685 |
|
/* |
| 686 |
* Install ROM patches (RAMBase and KernelDataAddr must be set) |
* Install ROM patches (RAMBase and KernelDataAddr must be set) |
| 687 |
*/ |
*/ |
| 688 |
|
|
| 705 |
ROMType = ROMTYPE_ZANZIBAR; |
ROMType = ROMTYPE_ZANZIBAR; |
| 706 |
else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12)) |
else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12)) |
| 707 |
ROMType = ROMTYPE_GAZELLE; |
ROMType = ROMTYPE_GAZELLE; |
| 708 |
|
else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gossamer", 13)) |
| 709 |
|
ROMType = ROMTYPE_GOSSAMER; |
| 710 |
else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8)) |
else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8)) |
| 711 |
ROMType = ROMTYPE_NEWWORLD; |
ROMType = ROMTYPE_NEWWORLD; |
| 712 |
else |
else |
| 713 |
return false; |
return false; |
| 714 |
|
|
| 715 |
|
// Check that other ROM addresses point to really free regions |
| 716 |
|
if (!check_rom_patch_space(CHECK_LOAD_PATCH_SPACE, 0x40)) |
| 717 |
|
return false; |
| 718 |
|
if (!check_rom_patch_space(PUT_SCRAP_PATCH_SPACE, 0x40)) |
| 719 |
|
return false; |
| 720 |
|
if (!check_rom_patch_space(GET_SCRAP_PATCH_SPACE, 0x40)) |
| 721 |
|
return false; |
| 722 |
|
if (!check_rom_patch_space(ADDR_MAP_PATCH_SPACE - 10 * 4, 0x100)) |
| 723 |
|
return false; |
| 724 |
|
|
| 725 |
// Apply patches |
// Apply patches |
| 726 |
if (!patch_nanokernel_boot()) return false; |
if (!patch_nanokernel_boot()) return false; |
| 727 |
if (!patch_68k_emul()) return false; |
if (!patch_68k_emul()) return false; |
| 754 |
static bool patch_nanokernel_boot(void) |
static bool patch_nanokernel_boot(void) |
| 755 |
{ |
{ |
| 756 |
uint32 *lp; |
uint32 *lp; |
| 757 |
|
uint32 base, loc; |
| 758 |
|
|
| 759 |
// ROM boot structure patches |
// ROM boot structure patches |
| 760 |
lp = (uint32 *)(ROM_BASE + 0x30d000); |
lp = (uint32 *)(ROM_BASE + 0x30d000); |
| 767 |
lp[0xfd8 >> 2] = htonl(ROM_BASE + 0x2a); // 68k reset vector |
lp[0xfd8 >> 2] = htonl(ROM_BASE + 0x2a); // 68k reset vector |
| 768 |
|
|
| 769 |
// Skip SR/BAT/SDR init |
// Skip SR/BAT/SDR init |
| 770 |
if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_NEWWORLD) { |
loc = 0x310000; |
| 771 |
lp = (uint32 *)(ROM_BASE + 0x310000); |
if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_GOSSAMER || ROMType == ROMTYPE_NEWWORLD) { |
| 772 |
|
lp = (uint32 *)(ROM_BASE + loc); |
| 773 |
*lp++ = htonl(POWERPC_NOP); |
*lp++ = htonl(POWERPC_NOP); |
| 774 |
*lp = htonl(0x38000000); |
*lp = htonl(0x38000000); |
| 775 |
} |
} |
| 776 |
static const uint32 sr_init_loc[] = {0x3101b0, 0x3101b0, 0x3101b0, 0x3101ec, 0x310200}; |
static const uint8 sr_init_dat[] = {0x35, 0x4a, 0xff, 0xfc, 0x7d, 0x86, 0x50, 0x2e}; |
| 777 |
lp = (uint32 *)(ROM_BASE + 0x310008); |
if ((base = find_rom_data(0x3101b0, 0x3105b0, sr_init_dat, sizeof(sr_init_dat))) == 0) return false; |
| 778 |
*lp = htonl(0x48000000 | (sr_init_loc[ROMType] - 8) & 0xffff); // b ROM_BASE+0x3101b0 |
D(bug("sr_init %08lx\n", base)); |
| 779 |
lp = (uint32 *)(ROM_BASE + sr_init_loc[ROMType]); |
lp = (uint32 *)(ROM_BASE + loc + 8); |
| 780 |
|
*lp = htonl(0x48000000 | ((base - loc - 8) & 0x3fffffc)); // b ROM_BASE+0x3101b0 |
| 781 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 782 |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA); // lwz r1,(pointer to Kernel Data) |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA); // lwz r1,(pointer to Kernel Data) |
| 783 |
*lp++ = htonl(0x3da0dead); // lis r13,0xdead (start of kernel memory) |
*lp++ = htonl(0x3da0dead); // lis r13,0xdead (start of kernel memory) |
| 784 |
*lp++ = htonl(0x3dc00010); // lis r14,0x0010 (size of page table) |
*lp++ = htonl(0x3dc00010); // lis r14,0x0010 (size of page table) |
| 785 |
*lp = htonl(0x3de00010); // lis r15,0x0010 (size of kernel memory) |
*lp = htonl(0x3de00010); // lis r15,0x0010 (size of kernel memory) |
| 786 |
|
|
| 787 |
// Don't read PVR |
// Don't read PVR |
| 788 |
static const uint32 pvr_loc[] = {0x3103b0, 0x3103b4, 0x3103b4, 0x310400, 0x310438}; |
static const uint8 pvr_read_dat[] = {0x7d, 0x9f, 0x42, 0xa6}; |
| 789 |
lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]); |
if ((base = find_rom_data(0x3103b0, 0x3108b0, pvr_read_dat, sizeof(pvr_read_dat))) == 0) return false; |
| 790 |
|
D(bug("pvr_read %08lx\n", base)); |
| 791 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 792 |
*lp = htonl(0x81800000 + XLM_PVR); // lwz r12,(theoretical PVR) |
*lp = htonl(0x81800000 + XLM_PVR); // lwz r12,(theoretical PVR) |
| 793 |
|
|
| 794 |
// Set CPU specific data (even if ROM doesn't have support for that CPU) |
// Set CPU specific data (even if ROM doesn't have support for that CPU) |
|
lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]); |
|
| 795 |
if (ntohl(lp[6]) != 0x2c0c0001) |
if (ntohl(lp[6]) != 0x2c0c0001) |
| 796 |
return false; |
return false; |
| 797 |
uint32 ofs = ntohl(lp[7]) & 0xffff; |
uint32 ofs = ntohl(lp[7]) & 0xffff; |
| 798 |
D(bug("ofs %08lx\n", ofs)); |
D(bug("ofs %08lx\n", ofs)); |
| 799 |
lp[8] = htonl((ntohl(lp[8]) & 0xffff) | 0x48000000); // beq -> b |
lp[8] = htonl((ntohl(lp[8]) & 0xffff) | 0x48000000); // beq -> b |
| 800 |
uint32 loc = (ntohl(lp[8]) & 0xffff) + (uint32)(lp+8) - ROM_BASE; |
loc = (ntohl(lp[8]) & 0xffff) + (uint32)(lp+8) - ROM_BASE; |
| 801 |
D(bug("loc %08lx\n", loc)); |
D(bug("loc %08lx\n", loc)); |
| 802 |
lp = (uint32 *)(ROM_BASE + ofs + 0x310000); |
lp = (uint32 *)(ROM_BASE + ofs + 0x310000); |
| 803 |
switch (PVR >> 16) { |
switch (PVR >> 16) { |
| 912 |
} |
} |
| 913 |
|
|
| 914 |
// Don't set SPRG3, don't test MQ |
// Don't set SPRG3, don't test MQ |
| 915 |
lp = (uint32 *)(ROM_BASE + loc + 0x20); |
static const uint8 sprg3_mq_dat[] = {0x7d, 0x13, 0x43, 0xa6, 0x3d, 0x00, 0x00, 0x04, 0x7d, 0x00, 0x03, 0xa6, 0x39, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0xa6}; |
| 916 |
*lp++ = htonl(POWERPC_NOP); |
if ((base = find_rom_data(loc + 0x20, loc + 0x60, sprg3_mq_dat, sizeof(sprg3_mq_dat))) == 0) return false; |
| 917 |
lp++; |
D(bug("sprg3/mq %08lx\n", base)); |
| 918 |
*lp++ = htonl(POWERPC_NOP); |
lp = (uint32 *)(ROM_BASE + base); |
| 919 |
lp++; |
lp[0] = htonl(POWERPC_NOP); |
| 920 |
*lp = htonl(POWERPC_NOP); |
lp[2] = htonl(POWERPC_NOP); |
| 921 |
|
lp[4] = htonl(POWERPC_NOP); |
| 922 |
|
|
| 923 |
// Don't read MSR |
// Don't read MSR |
| 924 |
lp = (uint32 *)(ROM_BASE + loc + 0x40); |
static const uint8 msr_dat[] = {0x7d, 0xc0, 0x00, 0xa6}; |
| 925 |
|
if ((base = find_rom_data(loc + 0x40, loc + 0x80, msr_dat, sizeof(msr_dat))) == 0) return false; |
| 926 |
|
D(bug("msr %08lx\n", base)); |
| 927 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 928 |
*lp = htonl(0x39c00000); // li r14,0 |
*lp = htonl(0x39c00000); // li r14,0 |
| 929 |
|
|
| 930 |
// Don't write to DEC |
// Don't write to DEC |
| 934 |
D(bug("loc %08lx\n", loc)); |
D(bug("loc %08lx\n", loc)); |
| 935 |
|
|
| 936 |
// Don't set SPRG3 |
// Don't set SPRG3 |
| 937 |
lp = (uint32 *)(ROM_BASE + loc + 0x2c); |
static const uint8 sprg3_dat[] = {0x39, 0x21, 0x03, 0x60, 0x7d, 0x33, 0x43, 0xa6, 0x39, 0x01, 0x04, 0x20}; |
| 938 |
|
if ((base = find_rom_data(0x310000, 0x314000, sprg3_dat, sizeof(sprg3_dat))) == 0) return false; |
| 939 |
|
D(bug("sprg3 %08lx\n", base + 4)); |
| 940 |
|
lp = (uint32 *)(ROM_BASE + base + 4); |
| 941 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 942 |
|
|
| 943 |
// Don't read PVR |
// Don't read PVR |
| 944 |
static const uint32 pvr_ofs[] = {0x138, 0x138, 0x138, 0x140, 0x148}; |
static const uint8 pvr_read2_dat[] = {0x7e, 0xff, 0x42, 0xa6, 0x56, 0xf7, 0x84, 0x3e}; |
| 945 |
lp = (uint32 *)(ROM_BASE + loc + pvr_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) == 0) return false; |
| 946 |
|
D(bug("pvr_read2 %08lx\n", base)); |
| 947 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 948 |
*lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) |
*lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) |
| 949 |
lp = (uint32 *)(ROM_BASE + loc + 0x170); |
if ((base = find_rom_data(base + 4, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) != 0) { |
| 950 |
if (ntohl(*lp) == 0x7eff42a6) // NewWorld ROM |
D(bug("pvr_read2 %08lx\n", base)); |
| 951 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 952 |
*lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) |
*lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) |
| 953 |
lp = (uint32 *)(ROM_BASE + 0x313134); |
} |
| 954 |
if (ntohl(*lp) == 0x7e5f42a6) |
static const uint8 pvr_read3_dat[] = {0x7e, 0x5f, 0x42, 0xa6, 0x56, 0x52, 0x84, 0x3e}; |
| 955 |
*lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) |
if ((base = find_rom_data(0x310000, 0x320000, pvr_read3_dat, sizeof(pvr_read3_dat))) != 0) { |
| 956 |
lp = (uint32 *)(ROM_BASE + 0x3131f4); |
D(bug("pvr_read3 %08lx\n", base)); |
| 957 |
if (ntohl(*lp) == 0x7e5f42a6) // NewWorld ROM |
lp = (uint32 *)(ROM_BASE + base); |
| 958 |
*lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) |
*lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) |
| 959 |
|
} |
| 960 |
|
static const uint8 pvr_read4_dat[] = {0x7d, 0x3f, 0x42, 0xa6, 0x55, 0x29, 0x84, 0x3e}; |
| 961 |
|
if ((base = find_rom_data(0x310000, 0x320000, pvr_read4_dat, sizeof(pvr_read4_dat))) != 0) { |
| 962 |
|
D(bug("pvr_read4 %08lx\n", base)); |
| 963 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 964 |
|
*lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR) |
| 965 |
|
} |
| 966 |
|
|
| 967 |
// Don't read SDR1 |
// Don't read SDR1 |
| 968 |
static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c}; |
static const uint8 sdr1_read_dat[] = {0x7d, 0x19, 0x02, 0xa6, 0x55, 0x16, 0x81, 0xde}; |
| 969 |
lp = (uint32 *)(ROM_BASE + loc + sdr1_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, sdr1_read_dat, sizeof(sdr1_read_dat))) == 0) return false; |
| 970 |
|
D(bug("sdr1_read %08lx\n", base)); |
| 971 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 972 |
*lp++ = htonl(0x3d00dead); // lis r8,0xdead (pointer to page table) |
*lp++ = htonl(0x3d00dead); // lis r8,0xdead (pointer to page table) |
| 973 |
*lp++ = htonl(0x3ec0001f); // lis r22,0x001f (size of page table) |
*lp++ = htonl(0x3ec0001f); // lis r22,0x001f (size of page table) |
| 974 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 975 |
|
|
| 976 |
// Don't clear page table |
// Don't clear page table, don't invalidate TLB |
| 977 |
static const uint32 pgtb_ofs[] = {0x198, 0x198, 0x198, 0x1a0, 0x1c4}; |
static const uint8 pgtb_clear_dat[] = {0x36, 0xd6, 0xff, 0xfc, 0x7e, 0xe8, 0xb1, 0x2e, 0x41, 0x81, 0xff, 0xf8}; |
| 978 |
lp = (uint32 *)(ROM_BASE + loc + pgtb_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, pgtb_clear_dat, sizeof(pgtb_clear_dat))) == 0) return false; |
| 979 |
|
D(bug("pgtb_clear %08lx\n", base + 4)); |
| 980 |
|
lp = (uint32 *)(ROM_BASE + base + 4); |
| 981 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 982 |
|
D(bug("tblie %08lx\n", base + 12)); |
| 983 |
// Don't invalidate TLB |
lp = (uint32 *)(ROM_BASE + base + 12); |
|
static const uint32 tlb_ofs[] = {0x1a0, 0x1a0, 0x1a0, 0x1a8, 0x1cc}; |
|
|
lp = (uint32 *)(ROM_BASE + loc + tlb_ofs[ROMType]); |
|
| 984 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 985 |
|
|
| 986 |
// Don't create RAM descriptor table |
// Don't create RAM descriptor table |
| 987 |
static const uint32 desc_ofs[] = {0x350, 0x350, 0x350, 0x358, 0x37c}; |
static const uint8 desc_create_dat[] = {0x97, 0xfd, 0x00, 0x04, 0x3b, 0xff, 0x10, 0x00, 0x4b, 0xff, 0xff, 0xdc}; |
| 988 |
lp = (uint32 *)(ROM_BASE + loc + desc_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, desc_create_dat, sizeof(desc_create_dat))) == 0) return false; |
| 989 |
|
D(bug("desc_create %08lx\n", base)) |
| 990 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 991 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 992 |
|
|
| 993 |
// Don't load SRs and BATs |
// Don't load SRs and BATs |
| 994 |
static const uint32 sr_ofs[] = {0x3d8, 0x3d8, 0x3d8, 0x3e0, 0x404}; |
static const uint8 sr_load[] = {0x7c, 0x00, 0x04, 0xac, 0x83, 0x9d, 0x00, 0x00, 0x93, 0x81, 0x05, 0xe8}; |
| 995 |
lp = (uint32 *)(ROM_BASE + loc + sr_ofs[ROMType]); |
if ((loc = find_rom_data(0x310000, 0x320000, sr_load, sizeof(sr_load))) == 0) return false; |
| 996 |
|
static const uint8 sr_load_caller[] = {0x3e, 0xd6, 0xff, 0xff, 0x41, 0x81, 0xff, 0xdc, 0xb2, 0xc8, 0x00, 0x02}; |
| 997 |
|
if ((base = find_rom_data(0x310000, 0x320000, sr_load_caller, sizeof(sr_load_caller))) == 0) return false; |
| 998 |
|
if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false; |
| 999 |
|
D(bug("sr_load %08lx, called from %08lx\n", loc, base)); |
| 1000 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 1001 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 1002 |
|
|
| 1003 |
// Don't mess with SRs |
// Don't mess with SRs |
| 1004 |
static const uint32 sr2_ofs[] = {0x312118, 0x312118, 0x312118, 0x312118, 0x3121b4}; |
static const uint8 sr_load2_dat[] = {0x83, 0xa1, 0x05, 0xe8, 0x57, 0x7c, 0x3e, 0x78, 0x7f, 0xbd, 0xe0, 0x2e}; |
| 1005 |
lp = (uint32 *)(ROM_BASE + sr2_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, sr_load2_dat, sizeof(sr_load2_dat))) == 0) return false; |
| 1006 |
|
D(bug("sr_load2 %08lx\n", base)); |
| 1007 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 1008 |
*lp = htonl(POWERPC_BLR); |
*lp = htonl(POWERPC_BLR); |
| 1009 |
|
|
| 1010 |
// Don't check performance monitor |
// Don't check performance monitor |
| 1011 |
static const uint32 pm_ofs[] = {0x313148, 0x313148, 0x313148, 0x313148, 0x313218}; |
static const uint8 pm_check_dat[] = {0x7e, 0x58, 0xeb, 0xa6, 0x7e, 0x53, 0x90, 0xf8, 0x7e, 0x78, 0xea, 0xa6}; |
| 1012 |
lp = (uint32 *)(ROM_BASE + pm_ofs[ROMType]); |
if ((base = find_rom_data(0x310000, 0x320000, pm_check_dat, sizeof(pm_check_dat))) == 0) return false; |
| 1013 |
while (ntohl(*lp) != 0x7e58eba6) lp++; |
D(bug("pm_check %08lx\n", base)); |
| 1014 |
*lp++ = htonl(POWERPC_NOP); |
lp = (uint32 *)(ROM_BASE + base); |
| 1015 |
while (ntohl(*lp) != 0x7e78eaa6) lp++; |
|
| 1016 |
*lp++ = htonl(POWERPC_NOP); |
static const int spr_check_list[] = { |
| 1017 |
while (ntohl(*lp) != 0x7e59eba6) lp++; |
952 /* mmcr0 */, 953 /* pmc1 */, 954 /* pmc2 */, 955 /* sia */, |
| 1018 |
*lp++ = htonl(POWERPC_NOP); |
956 /* mmcr1 */, 957 /* pmc3 */, 958 /* pmc4 */, 959 /* sda */ |
| 1019 |
while (ntohl(*lp) != 0x7e79eaa6) lp++; |
}; |
| 1020 |
*lp++ = htonl(POWERPC_NOP); |
|
| 1021 |
while (ntohl(*lp) != 0x7e5aeba6) lp++; |
for (int i = 0; i < sizeof(spr_check_list)/sizeof(spr_check_list[0]); i++) { |
| 1022 |
*lp++ = htonl(POWERPC_NOP); |
int spr = spr_check_list[i]; |
| 1023 |
while (ntohl(*lp) != 0x7e7aeaa6) lp++; |
uint32 mtspr = 0x7e4003a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6); |
| 1024 |
*lp++ = htonl(POWERPC_NOP); |
uint32 mfspr = 0x7e6002a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6); |
| 1025 |
while (ntohl(*lp) != 0x7e5beba6) lp++; |
for (int ofs = 0; ofs < 64; ofs++) { |
| 1026 |
*lp++ = htonl(POWERPC_NOP); |
if (ntohl(lp[ofs]) == mtspr) { |
| 1027 |
while (ntohl(*lp) != 0x7e7beaa6) lp++; |
if (ntohl(lp[ofs + 2]) != mfspr) |
| 1028 |
*lp++ = htonl(POWERPC_NOP); |
return false; |
| 1029 |
while (ntohl(*lp) != 0x7e5feba6) lp++; |
D(bug(" SPR%d %08lx\n", spr, base + 4*ofs)); |
| 1030 |
*lp++ = htonl(POWERPC_NOP); |
lp[ofs] = htonl(POWERPC_NOP); |
| 1031 |
while (ntohl(*lp) != 0x7e7feaa6) lp++; |
lp[ofs + 2] = htonl(POWERPC_NOP); |
| 1032 |
*lp++ = htonl(POWERPC_NOP); |
} |
| 1033 |
while (ntohl(*lp) != 0x7e5ceba6) lp++; |
} |
| 1034 |
*lp++ = htonl(POWERPC_NOP); |
} |
|
while (ntohl(*lp) != 0x7e7ceaa6) lp++; |
|
|
*lp++ = htonl(POWERPC_NOP); |
|
|
while (ntohl(*lp) != 0x7e5deba6) lp++; |
|
|
*lp++ = htonl(POWERPC_NOP); |
|
|
while (ntohl(*lp) != 0x7e7deaa6) lp++; |
|
|
*lp++ = htonl(POWERPC_NOP); |
|
|
while (ntohl(*lp) != 0x7e5eeba6) lp++; |
|
|
*lp++ = htonl(POWERPC_NOP); |
|
|
while (ntohl(*lp) != 0x7e7eeaa6) lp++; |
|
|
*lp++ = htonl(POWERPC_NOP); |
|
| 1035 |
|
|
| 1036 |
// Jump to 68k emulator |
// Jump to 68k emulator |
| 1037 |
static const uint32 jump68k_ofs[] = {0x40c, 0x40c, 0x40c, 0x414, 0x438}; |
static const uint8 jump68k_dat[] = {0x7d, 0x92, 0x43, 0xa6, 0x7d, 0x5a, 0x03, 0xa6, 0x7d, 0x7b, 0x03, 0xa6}; |
| 1038 |
lp = (uint32 *)(ROM_BASE + loc + jump68k_ofs[ROMType]); |
if ((loc = find_rom_data(0x310000, 0x320000, jump68k_dat, sizeof(jump68k_dat))) == 0) return false; |
| 1039 |
|
static const uint8 jump68k_caller_dat[] = {0x85, 0x13, 0x00, 0x08, 0x56, 0xbf, 0x50, 0x3e, 0x63, 0xff, 0x0c, 0x00}; |
| 1040 |
|
if ((base = find_rom_data(0x310000, 0x320000, jump68k_caller_dat, sizeof(jump68k_caller_dat))) == 0) return false; |
| 1041 |
|
if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false; |
| 1042 |
|
D(bug("jump68k %08lx, called from %08lx\n", loc, base)); |
| 1043 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 1044 |
*lp++ = htonl(0x80610634); // lwz r3,0x0634(r1) (pointer to Emulator Data) |
*lp++ = htonl(0x80610634); // lwz r3,0x0634(r1) (pointer to Emulator Data) |
| 1045 |
*lp++ = htonl(0x8081119c); // lwz r4,0x119c(r1) (pointer to opcode table) |
*lp++ = htonl(0x8081119c); // lwz r4,0x119c(r1) (pointer to opcode table) |
| 1046 |
*lp++ = htonl(0x80011184); // lwz r0,0x1184(r1) (pointer to emulator init routine) |
*lp++ = htonl(0x80011184); // lwz r0,0x1184(r1) (pointer to emulator init routine) |
| 1060 |
uint32 base; |
uint32 base; |
| 1061 |
|
|
| 1062 |
// Overwrite twi instructions |
// Overwrite twi instructions |
| 1063 |
static const uint32 twi_loc[] = {0x36e680, 0x36e6c0, 0x36e6c0, 0x36e6c0, 0x36e740}; |
static const uint8 twi_dat[] = {0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0x0f, 0xff, 0x00, 0x02}; |
| 1064 |
base = twi_loc[ROMType]; |
if ((base = find_rom_data(0x36e600, 0x36ea00, twi_dat, sizeof(twi_dat))) == 0) return false; |
| 1065 |
|
D(bug("twi %08lx\n", base)); |
| 1066 |
lp = (uint32 *)(ROM_BASE + base); |
lp = (uint32 *)(ROM_BASE + base); |
| 1067 |
*lp++ = htonl(0x48000000 + 0x36f900 - base); // b 0x36f900 (Emulator start) |
*lp++ = htonl(0x48000000 + 0x36f900 - base); // b 0x36f900 (Emulator start) |
| 1068 |
*lp++ = htonl(0x48000000 + 0x36fa00 - base - 4); // b 0x36fa00 (Mixed mode) |
*lp++ = htonl(0x48000000 + 0x36fa00 - base - 4); // b 0x36fa00 (Mixed mode) |
| 1082 |
*lp = htonl(POWERPC_ILLEGAL); |
*lp = htonl(POWERPC_ILLEGAL); |
| 1083 |
|
|
| 1084 |
#if EMULATED_PPC |
#if EMULATED_PPC |
| 1085 |
// Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes |
// Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes |
| 1086 |
lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3)); |
lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3)); |
| 1087 |
*lp++ = htonl(POWERPC_EMUL_OP); |
*lp++ = htonl(POWERPC_EMUL_OP); |
| 1088 |
*lp++ = htonl(0x4bf66e80); // b 0x366084 |
*lp++ = htonl(0x4bf66e80); // b 0x366084 |
| 1089 |
*lp++ = htonl(POWERPC_EMUL_OP | 1); |
*lp++ = htonl(POWERPC_EMUL_OP | 1); |
| 1090 |
*lp++ = htonl(0x4bf66e78); // b 0x366084 |
*lp++ = htonl(0x4bf66e78); // b 0x366084 |
| 1091 |
|
*lp++ = htonl(POWERPC_EMUL_OP | 2); |
| 1092 |
|
*lp++ = htonl(0x4bf66e70); // b 0x366084 |
| 1093 |
for (int i=0; i<OP_MAX; i++) { |
for (int i=0; i<OP_MAX; i++) { |
| 1094 |
*lp++ = htonl(POWERPC_EMUL_OP | (i + 2)); |
*lp++ = htonl(POWERPC_EMUL_OP | (i + 3)); |
| 1095 |
*lp++ = htonl(0x4bf66e70 - i*8); // b 0x366084 |
*lp++ = htonl(0x4bf66e68 - i*8); // b 0x366084 |
| 1096 |
} |
} |
| 1097 |
#else |
#else |
| 1098 |
// Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes |
// Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes |
| 1101 |
*lp++ = htonl(0x4bf705fc); // b 0x36f800 |
*lp++ = htonl(0x4bf705fc); // b 0x36f800 |
| 1102 |
*lp++ = htonl(0x80000000 + XLM_EXEC_RETURN_PROC); // lwz r0,XLM_EXEC_RETURN_PROC |
*lp++ = htonl(0x80000000 + XLM_EXEC_RETURN_PROC); // lwz r0,XLM_EXEC_RETURN_PROC |
| 1103 |
*lp++ = htonl(0x4bf705f4); // b 0x36f800 |
*lp++ = htonl(0x4bf705f4); // b 0x36f800 |
| 1104 |
|
*lp++ = htonl(0x00dead00); // Let SheepShaver crash, since |
| 1105 |
|
*lp++ = htonl(0x00beef00); // no native opcode is available |
| 1106 |
for (int i=0; i<OP_MAX; i++) { |
for (int i=0; i<OP_MAX; i++) { |
| 1107 |
*lp++ = htonl(0x38a00000 + i); // li r5,OP_* |
*lp++ = htonl(0x38a00000 + i); // li r5,OP_* |
| 1108 |
*lp++ = htonl(0x4bf705f4 - i*8); // b 0x36f808 |
*lp++ = htonl(0x4bf705ec - i*8); // b 0x36f808 |
| 1109 |
} |
} |
| 1110 |
|
|
| 1111 |
// Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP |
// Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP |
| 1121 |
// Extra routine for 68k emulator start |
// Extra routine for 68k emulator start |
| 1122 |
lp = (uint32 *)(ROM_BASE + 0x36f900); |
lp = (uint32 *)(ROM_BASE + 0x36f900); |
| 1123 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
| 1124 |
|
#if EMULATED_PPC |
| 1125 |
|
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
| 1126 |
|
#else |
| 1127 |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
| 1128 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
| 1129 |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
| 1130 |
|
#endif |
| 1131 |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
| 1132 |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
| 1133 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
| 1155 |
// Extra routine for Mixed Mode |
// Extra routine for Mixed Mode |
| 1156 |
lp = (uint32 *)(ROM_BASE + 0x36fa00); |
lp = (uint32 *)(ROM_BASE + 0x36fa00); |
| 1157 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
| 1158 |
|
#if EMULATED_PPC |
| 1159 |
|
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
| 1160 |
|
#else |
| 1161 |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
| 1162 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
| 1163 |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
| 1164 |
|
#endif |
| 1165 |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
| 1166 |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
| 1167 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
| 1187 |
*lp = htonl(0x4e800020); // blr |
*lp = htonl(0x4e800020); // blr |
| 1188 |
|
|
| 1189 |
// Extra routine for Reset/FC1E opcode |
// Extra routine for Reset/FC1E opcode |
| 1190 |
lp = (uint32 *)(ROM_BASE + 0x36fc00); |
lp = (uint32 *)(ROM_BASE + 0x36fb00); |
| 1191 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
| 1192 |
|
#if EMULATED_PPC |
| 1193 |
|
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
| 1194 |
|
#else |
| 1195 |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
| 1196 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
| 1197 |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
| 1198 |
|
#endif |
| 1199 |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
| 1200 |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
| 1201 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
| 1212 |
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
| 1213 |
*lp++ = htonl(0x7d8802a6); // mflr r12 |
*lp++ = htonl(0x7d8802a6); // mflr r12 |
| 1214 |
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
| 1215 |
*lp++ = htonl(0x814105f4); // lwz r10,0x05f8(r1) |
*lp++ = htonl(0x814105f8); // lwz r10,0x05f8(r1) |
| 1216 |
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
| 1217 |
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
| 1218 |
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
| 1223 |
// Extra routine for FE0A opcode (QuickDraw 3D needs this) |
// Extra routine for FE0A opcode (QuickDraw 3D needs this) |
| 1224 |
lp = (uint32 *)(ROM_BASE + 0x36fc00); |
lp = (uint32 *)(ROM_BASE + 0x36fc00); |
| 1225 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
*lp++ = htonl(0x7c2903a6); // mtctr r1 |
| 1226 |
|
#if EMULATED_PPC |
| 1227 |
|
*lp++ = htonl(NativeOpcode(NATIVE_DISABLE_INTERRUPT)); |
| 1228 |
|
#else |
| 1229 |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
*lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST |
| 1230 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
*lp++ = htonl(0x38210001); // addi r1,r1,1 |
| 1231 |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
*lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST |
| 1232 |
|
#endif |
| 1233 |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
*lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA |
| 1234 |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
*lp++ = htonl(0x90c10018); // stw r6,0x18(r1) |
| 1235 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
*lp++ = htonl(0x7cc902a6); // mfctr r6 |
| 1246 |
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
*lp++ = htonl(0x80e10660); // lwz r7,$0660(r1) |
| 1247 |
*lp++ = htonl(0x7d8802a6); // mflr r12 |
*lp++ = htonl(0x7d8802a6); // mflr r12 |
| 1248 |
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
*lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000 |
| 1249 |
*lp++ = htonl(0x814105f4); // lwz r10,0x05fc(r1) |
*lp++ = htonl(0x814105fc); // lwz r10,0x05fc(r1) |
| 1250 |
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
*lp++ = htonl(0x7d4803a6); // mtlr r10 |
| 1251 |
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
*lp++ = htonl(0x7d8a6378); // mr r10,r12 |
| 1252 |
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
*lp++ = htonl(0x3d600002); // lis r11,0x0002 |
| 1282 |
static bool patch_nanokernel(void) |
static bool patch_nanokernel(void) |
| 1283 |
{ |
{ |
| 1284 |
uint32 *lp; |
uint32 *lp; |
| 1285 |
|
uint32 base, loc; |
| 1286 |
|
|
| 1287 |
// Patch Mixed Mode trap |
// Patch Mixed Mode trap |
| 1288 |
lp = (uint32 *)(ROM_BASE + 0x313c90); // Don't translate virtual->physical |
static const uint8 virt2phys_dat[] = {0x7d, 0x1b, 0x43, 0x78, 0x3b, 0xa1, 0x03, 0x20}; |
| 1289 |
while (ntohl(*lp) != 0x3ba10320) lp++; |
if ((base = find_rom_data(0x313000, 0x314000, virt2phys_dat, sizeof(virt2phys_dat))) == 0) return false; |
| 1290 |
lp++; |
D(bug("virt2phys %08lx\n", base + 8)); |
| 1291 |
*lp++ = htonl(0x7f7fdb78); // mr r31,r27 |
lp = (uint32 *)(ROM_BASE + base + 8); // Don't translate virtual->physical |
| 1292 |
lp++; |
lp[0] = htonl(0x7f7fdb78); // mr r31,r27 |
| 1293 |
*lp = htonl(POWERPC_NOP); |
lp[2] = htonl(POWERPC_NOP); |
| 1294 |
|
|
| 1295 |
lp = (uint32 *)(ROM_BASE + 0x313c3c); // Don't activate PPC exception table |
static const uint8 ppc_excp_tbl_dat[] = {0x39, 0x01, 0x04, 0x20, 0x7d, 0x13, 0x43, 0xa6}; |
| 1296 |
while (ntohl(*lp) != 0x39010420) lp++; |
if ((base = find_rom_data(0x313000, 0x314000, ppc_excp_tbl_dat, sizeof(ppc_excp_tbl_dat))) == 0) return false; |
| 1297 |
|
D(bug("ppc_excp_tbl %08lx\n", base)); |
| 1298 |
|
lp = (uint32 *)(ROM_BASE + base); // Don't activate PPC exception table |
| 1299 |
*lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE |
*lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE |
| 1300 |
*lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE |
*lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE |
| 1301 |
|
|
| 1302 |
lp = (uint32 *)(ROM_BASE + 0x312e88); // Don't modify MSR to turn on FPU |
static const uint8 save_fpu_dat[] = {0x7d, 0x00, 0x00, 0xa6, 0x61, 0x08, 0x20, 0x00, 0x7d, 0x00, 0x01, 0x24}; |
| 1303 |
while (ntohl(*lp) != 0x556b04e2) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, save_fpu_dat, sizeof(save_fpu_dat))) == 0) return false; |
| 1304 |
lp -= 4; |
D(bug("save_fpu %08lx\n", base)); |
| 1305 |
|
lp = (uint32 *)(ROM_BASE + base); // Don't modify MSR to turn on FPU |
| 1306 |
|
if (ntohl(lp[4]) != 0x556b04e2) return false; |
| 1307 |
|
loc = ROM_BASE + base; |
| 1308 |
|
#if 1 |
| 1309 |
|
// FIXME: is that really intended? |
| 1310 |
*lp++ = htonl(POWERPC_NOP); |
*lp++ = htonl(POWERPC_NOP); |
| 1311 |
lp++; |
lp++; |
| 1312 |
*lp++ = htonl(POWERPC_NOP); |
*lp++ = htonl(POWERPC_NOP); |
| 1313 |
lp++; |
lp++; |
| 1314 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 1315 |
|
#else |
| 1316 |
|
lp[0] = htonl(POWERPC_NOP); |
| 1317 |
|
lp[1] = htonl(POWERPC_NOP); |
| 1318 |
|
lp[2] = htonl(POWERPC_NOP); |
| 1319 |
|
lp[3] = htonl(POWERPC_NOP); |
| 1320 |
|
#endif |
| 1321 |
|
|
| 1322 |
lp = (uint32 *)(ROM_BASE + 0x312b3c); // Always save FPU state |
static const uint8 save_fpu_caller_dat[] = {0x93, 0xa6, 0x01, 0xec, 0x93, 0xc6, 0x01, 0xf4, 0x93, 0xe6, 0x01, 0xfc, 0x40}; |
| 1323 |
while (ntohl(*lp) != 0x81010668) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, save_fpu_caller_dat, sizeof(save_fpu_caller_dat))) == 0) return false; |
| 1324 |
lp--; |
D(bug("save_fpu_caller %08lx\n", base + 12)); |
| 1325 |
|
if (powerpc_branch_target(ROM_BASE + base + 12) != loc) return false; |
| 1326 |
|
lp = (uint32 *)(ROM_BASE + base + 12); // Always save FPU state |
| 1327 |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88 |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88 |
| 1328 |
|
|
| 1329 |
lp = (uint32 *)(ROM_BASE + 0x312b44); // Don't read DEC |
static const uint8 mdec_dat[] = {0x7f, 0xf6, 0x02, 0xa6, 0x2c, 0x08, 0x00, 0x00, 0x93, 0xe1, 0x06, 0x68, 0x7d, 0x16, 0x03, 0xa6}; |
| 1330 |
while (ntohl(*lp) != 0x7ff602a6) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, mdec_dat, sizeof(mdec_dat))) == 0) return false; |
| 1331 |
*lp = htonl(0x3be00000); // li r31,0 |
D(bug("mdec %08lx\n", base)); |
| 1332 |
|
lp = (uint32 *)(ROM_BASE + base); // Don't modify DEC |
| 1333 |
lp = (uint32 *)(ROM_BASE + 0x312b50); // Don't write DEC |
lp[0] = htonl(0x3be00000); // li r31,0 |
|
while (ntohl(*lp) != 0x7d1603a6) lp++; |
|
| 1334 |
#if 1 |
#if 1 |
| 1335 |
*lp++ = htonl(POWERPC_NOP); |
lp[3] = htonl(POWERPC_NOP); |
| 1336 |
*lp = htonl(POWERPC_NOP); |
lp[4] = htonl(POWERPC_NOP); |
| 1337 |
#else |
#else |
| 1338 |
*lp++ = htonl(0x39000040); // li r8,0x40 |
lp[3] = htonl(0x39000040); // li r8,0x40 |
| 1339 |
*lp = htonl(0x990600e4); // stb r8,0xe4(r6) |
lp[4] = htonl(0x990600e4); // stb r8,0xe4(r6) |
| 1340 |
#endif |
#endif |
| 1341 |
|
|
| 1342 |
lp = (uint32 *)(ROM_BASE + 0x312b9c); // Always restore FPU state |
static const uint8 restore_fpu_caller_dat[] = {0x81, 0x06, 0x00, 0xf4, 0x81, 0x46, 0x00, 0xfc, 0x7d, 0x09, 0x03, 0xa6, 0x40}; |
| 1343 |
while (ntohl(*lp) != 0x7c00092d) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller_dat, sizeof(restore_fpu_caller_dat))) == 0) return false; |
| 1344 |
lp--; |
D(bug("restore_fpu_caller %08lx\n", base + 12)); |
| 1345 |
|
lp = (uint32 *)(ROM_BASE + base + 12); // Always restore FPU state |
| 1346 |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc |
| 1347 |
|
|
| 1348 |
lp = (uint32 *)(ROM_BASE + 0x312a68); // Don't activate 68k exception table |
static const uint8 m68k_excp_tbl_dat[] = {0x81, 0x21, 0x06, 0x58, 0x39, 0x01, 0x03, 0x60, 0x7d, 0x13, 0x43, 0xa6}; |
| 1349 |
while (ntohl(*lp) != 0x39010360) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, m68k_excp_tbl_dat, sizeof(m68k_excp_tbl_dat))) == 0) return false; |
| 1350 |
|
D(bug("m68k_excp %08lx\n", base + 4)); |
| 1351 |
|
lp = (uint32 *)(ROM_BASE + base + 4); // Don't activate 68k exception table |
| 1352 |
*lp++ = htonl(0x39000000 + MODE_68K); // li r8,MODE_68K |
*lp++ = htonl(0x39000000 + MODE_68K); // li r8,MODE_68K |
| 1353 |
*lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE |
*lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE |
| 1354 |
|
|
| 1355 |
// Patch 68k emulator trap routine |
// Patch 68k emulator trap routine |
| 1356 |
lp = (uint32 *)(ROM_BASE + 0x312994); // Always restore FPU state |
static const uint8 restore_fpu_caller2_dat[] = {0x81, 0x86, 0x00, 0x8c, 0x80, 0x66, 0x00, 0x94, 0x80, 0x86, 0x00, 0x9c, 0x40}; |
| 1357 |
while (ntohl(*lp) != 0x39260040) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller2_dat, sizeof(restore_fpu_caller2_dat))) == 0) return false; |
| 1358 |
lp--; |
D(bug("restore_fpu_caller2 %08lx\n", base + 12)); |
| 1359 |
|
loc = powerpc_branch_target(ROM_BASE + base + 12) - ROM_BASE; |
| 1360 |
|
lp = (uint32 *)(ROM_BASE + base + 12); // Always restore FPU state |
| 1361 |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4 |
*lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4 |
| 1362 |
|
|
| 1363 |
lp = (uint32 *)(ROM_BASE + 0x312dd8); // Don't modify MSR to turn on FPU |
static const uint8 restore_fpu_dat[] = {0x55, 0x68, 0x04, 0xa5, 0x4c, 0x82, 0x00, 0x20, 0x81, 0x06, 0x00, 0xe4}; |
| 1364 |
while (ntohl(*lp) != 0x810600e4) lp++; |
if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_dat, sizeof(restore_fpu_dat))) == 0) return false; |
| 1365 |
lp--; |
D(bug("restore_fpu %08lx\n", base)); |
| 1366 |
|
if (base != loc) return false; |
| 1367 |
|
lp = (uint32 *)(ROM_BASE + base + 4); // Don't modify MSR to turn on FPU |
| 1368 |
*lp++ = htonl(POWERPC_NOP); |
*lp++ = htonl(POWERPC_NOP); |
| 1369 |
lp += 2; |
lp += 2; |
| 1370 |
*lp++ = htonl(POWERPC_NOP); |
*lp++ = htonl(POWERPC_NOP); |
| 1374 |
*lp = htonl(POWERPC_NOP); |
*lp = htonl(POWERPC_NOP); |
| 1375 |
|
|
| 1376 |
// Patch trap return routine |
// Patch trap return routine |
| 1377 |
lp = (uint32 *)(ROM_BASE + 0x312c20); |
static const uint8 trap_return_dat[] = {0x80, 0xc1, 0x00, 0x18, 0x80, 0x21, 0x00, 0x04, 0x4c, 0x00, 0x00, 0x64}; |
| 1378 |
while (ntohl(*lp) != 0x7d5a03a6) lp++; |
if ((base = find_rom_data(0x312000, 0x320000, trap_return_dat, sizeof(trap_return_dat))) == 0) return false; |
| 1379 |
|
D(bug("trap_return %08lx\n", base + 8)); |
| 1380 |
|
lp = (uint32 *)(ROM_BASE + base + 8); // Replace rfi |
| 1381 |
|
*lp = htonl(POWERPC_BCTR); |
| 1382 |
|
|
| 1383 |
|
while (ntohl(*lp) != 0x7d5a03a6) lp--; |
| 1384 |
*lp++ = htonl(0x7d4903a6); // mtctr r10 |
*lp++ = htonl(0x7d4903a6); // mtctr r10 |
| 1385 |
*lp++ = htonl(0x7daff120); // mtcr r13 |
*lp++ = htonl(0x7daff120); // mtcr r13 |
| 1386 |
*lp = htonl(0x48000000 + 0x8000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b ROM_BASE+0x318000 |
*lp = htonl(0x48000000 + ((0x318000 - ((uint32)lp - ROM_BASE)) & 0x03fffffc)); // b ROM_BASE+0x318000 |
| 1387 |
uint32 xlp = ((uint32)(lp+1) - ROM_BASE) & 0xffff; |
uint32 npc = (uint32)(lp + 1) - ROM_BASE; |
|
|
|
|
lp = (uint32 *)(ROM_BASE + 0x312c50); // Replace rfi |
|
|
while (ntohl(*lp) != 0x4c000064) lp++; |
|
|
*lp = htonl(POWERPC_BCTR); |
|
| 1388 |
|
|
| 1389 |
lp = (uint32 *)(ROM_BASE + 0x318000); |
lp = (uint32 *)(ROM_BASE + 0x318000); |
| 1390 |
|
#if EMULATED_PPC |
| 1391 |
|
*lp++ = htonl(NativeOpcode(NATIVE_ENABLE_INTERRUPT)); |
| 1392 |
|
*lp = htonl(0x48000000 + ((npc - 0x318004) & 0x03fffffc)); // b ROM_BASE+0x312c2c |
| 1393 |
|
#else |
| 1394 |
*lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST |
*lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST |
| 1395 |
*lp++ = htonl(0x394affff); // subi r10,r10,1 |
*lp++ = htonl(0x394affff); // subi r10,r10,1 |
| 1396 |
*lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST |
*lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST |
| 1397 |
*lp = htonl(0x48000000 + ((xlp - 0x800c) & 0x03fffffc)); // b ROM_BASE+0x312c2c |
*lp = htonl(0x48000000 + ((npc - 0x31800c) & 0x03fffffc)); // b ROM_BASE+0x312c2c |
| 1398 |
|
#endif |
| 1399 |
|
|
| 1400 |
/* |
/* |
| 1401 |
// Disable FE0A/FE06 opcodes |
// Disable FE0A/FE06 opcodes |
| 1402 |
lp = (uint32 *)(ROM_BASE + 0x3144ac); |
lp = (uint32 *)(ROM_BASE + 0x3144ac); |
| 1416 |
uint32 *lp; |
uint32 *lp; |
| 1417 |
uint16 *wp; |
uint16 *wp; |
| 1418 |
uint8 *bp; |
uint8 *bp; |
| 1419 |
uint32 base; |
uint32 base, loc; |
| 1420 |
|
|
| 1421 |
// Remove 68k RESET instruction |
// Remove 68k RESET instruction |
| 1422 |
static const uint8 reset_dat[] = {0x4e, 0x70}; |
static const uint8 reset_dat[] = {0x4e, 0x70}; |
| 1442 |
// Patch UniversalInfo |
// Patch UniversalInfo |
| 1443 |
if (ROMType == ROMTYPE_NEWWORLD) { |
if (ROMType == ROMTYPE_NEWWORLD) { |
| 1444 |
static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00}; |
static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00}; |
| 1445 |
if ((base = find_rom_data(0x14000, 0x16000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false; |
if ((base = find_rom_data(0x14000, 0x18000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false; |
| 1446 |
D(bug("universal_info %08lx\n", base)); |
D(bug("universal_info %08lx\n", base)); |
| 1447 |
lp = (uint32 *)(ROM_BASE + base - 0x14); |
lp = (uint32 *)(ROM_BASE + base - 0x14); |
| 1448 |
lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); |
lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); |
| 1466 |
lp[0x28 >> 2] = htonl(0x00000861); |
lp[0x28 >> 2] = htonl(0x00000861); |
| 1467 |
lp[0x58 >> 2] = htonl(0x30200000); |
lp[0x58 >> 2] = htonl(0x30200000); |
| 1468 |
lp[0x60 >> 2] = htonl(0x0000003d); |
lp[0x60 >> 2] = htonl(0x0000003d); |
| 1469 |
|
} else if (ROMType == ROMTYPE_GOSSAMER) { |
| 1470 |
|
base = 0x12d20; |
| 1471 |
|
lp = (uint32 *)(ROM_BASE + base - 0x14); |
| 1472 |
|
lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); |
| 1473 |
|
lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo |
| 1474 |
|
lp[0x14 >> 2] = htonl(0x3fff0401); |
| 1475 |
|
lp[0x18 >> 2] = htonl(0x0300001c); |
| 1476 |
|
lp[0x1c >> 2] = htonl(0x000108c4); |
| 1477 |
|
lp[0x24 >> 2] = htonl(0xc301bf26); |
| 1478 |
|
lp[0x28 >> 2] = htonl(0x00000861); |
| 1479 |
|
lp[0x58 >> 2] = htonl(0x30410000); |
| 1480 |
|
lp[0x60 >> 2] = htonl(0x0000003d); |
| 1481 |
} |
} |
| 1482 |
|
|
| 1483 |
// Construct AddrMap for NewWorld ROM |
// Construct AddrMap for NewWorld ROM |
| 1484 |
if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR) { |
if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) { |
| 1485 |
lp = (uint32 *)(ROM_BASE + ADDR_MAP_PATCH_SPACE); |
lp = (uint32 *)(ROM_BASE + ADDR_MAP_PATCH_SPACE); |
| 1486 |
memset(lp - 10, 0, 0x128); |
memset(lp - 10, 0, 0x128); |
| 1487 |
lp[-10] = htonl(0x0300001c); |
lp[-10] = htonl(0x0300001c); |
| 1607 |
*wp++ = htons(M68K_EMUL_OP_XPRAM2); |
*wp++ = htons(M68K_EMUL_OP_XPRAM2); |
| 1608 |
*wp = htons(0x4ed3); // jmp (a3) |
*wp = htons(0x4ed3); // jmp (a3) |
| 1609 |
|
|
| 1610 |
static const uint32 nvram3_loc[] = {0x582f0, 0xa0a0, 0x7e50, 0xa1d0, 0}; |
static const uint8 nvram3_dat[] = {0x4e, 0xd3, 0x06, 0x41, 0x13, 0x00}; |
| 1611 |
wp = (uint16 *)(ROM_BASE + nvram3_loc[ROMType]); |
if ((base = find_rom_data(0x7000, 0xb000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false; |
| 1612 |
|
D(bug("nvram3 %08lx\n", base)); |
| 1613 |
|
wp = (uint16 *)(ROM_BASE + base + 2); |
| 1614 |
|
*wp++ = htons(M68K_EMUL_OP_XPRAM3); |
| 1615 |
|
*wp = htons(0x4ed3); // jmp (a3) |
| 1616 |
|
|
| 1617 |
|
static const uint32 nvram4_loc[] = {0x582f0, 0xa0a0, 0x7e50, 0xa1d0, 0x538d0, 0}; |
| 1618 |
|
wp = (uint16 *)(ROM_BASE + nvram4_loc[ROMType]); |
| 1619 |
*wp++ = htons(0x202f); // move.l 4(sp),d0 |
*wp++ = htons(0x202f); // move.l 4(sp),d0 |
| 1620 |
*wp++ = htons(0x0004); |
*wp++ = htons(0x0004); |
| 1621 |
*wp++ = htons(M68K_EMUL_OP_NVRAM1); |
*wp++ = htons(M68K_EMUL_OP_NVRAM1); |
| 1628 |
*wp = htons(0x0004); |
*wp = htons(0x0004); |
| 1629 |
} |
} |
| 1630 |
|
|
| 1631 |
static const uint32 nvram4_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0}; |
static const uint32 nvram5_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0x53a20, 0}; |
| 1632 |
wp = (uint16 *)(ROM_BASE + nvram4_loc[ROMType]); |
wp = (uint16 *)(ROM_BASE + nvram5_loc[ROMType]); |
| 1633 |
if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) { |
if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) { |
| 1634 |
*wp++ = htons(0x202f); // move.l 4(sp),d0 |
*wp++ = htons(0x202f); // move.l 4(sp),d0 |
| 1635 |
*wp++ = htons(0x0004); |
*wp++ = htons(0x0004); |
| 1657 |
*wp = htons(M68K_NOP); |
*wp = htons(M68K_NOP); |
| 1658 |
|
|
| 1659 |
// Don't initialize SCC (via 0x1ac) |
// Don't initialize SCC (via 0x1ac) |
| 1660 |
static const uint8 scc_init_dat[] = {0x48, 0xe7, 0x38, 0xfe}; |
static const uint8 scc_init_caller_dat[] = {0x21, 0xce, 0x01, 0x08, 0x22, 0x78, 0x0d, 0xd8}; |
| 1661 |
if ((base = find_rom_data(0x190, 0x1f0, scc_init_dat, sizeof(scc_init_dat))) == 0) return false; |
if ((base = find_rom_data(0x180, 0x1f0, scc_init_caller_dat, sizeof(scc_init_caller_dat))) == 0) return false; |
| 1662 |
|
D(bug("scc_init_caller %08lx\n", base + 12)); |
| 1663 |
|
wp = (uint16 *)(ROM_BASE + base + 12); |
| 1664 |
|
loc = ntohs(wp[1]) + ((uintptr)wp - ROM_BASE) + 2; |
| 1665 |
|
static const uint8 scc_init_dat[] = {0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8}; |
| 1666 |
|
if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) == 0) return false; |
| 1667 |
D(bug("scc_init %08lx\n", base)); |
D(bug("scc_init %08lx\n", base)); |
| 1668 |
wp = (uint16 *)(ROM_BASE + base - 2); |
wp = (uint16 *)(ROM_BASE + base); |
|
wp = (uint16 *)(ROM_BASE + ntohs(*wp) + base - 2); |
|
| 1669 |
*wp++ = htons(M68K_EMUL_OP_RESET); |
*wp++ = htons(M68K_EMUL_OP_RESET); |
| 1670 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 1671 |
|
|
| 1810 |
if ((base = find_rom_data(0x13000, 0x20000, gc_mask2_dat, sizeof(gc_mask2_dat))) == 0) return false; |
if ((base = find_rom_data(0x13000, 0x20000, gc_mask2_dat, sizeof(gc_mask2_dat))) == 0) return false; |
| 1811 |
D(bug("gc_mask2 %08lx\n", base)); |
D(bug("gc_mask2 %08lx\n", base)); |
| 1812 |
wp = (uint16 *)(ROM_BASE + base); |
wp = (uint16 *)(ROM_BASE + base); |
| 1813 |
|
if (ROMType == ROMTYPE_GOSSAMER) |
| 1814 |
|
*wp++ = htons(M68K_NOP); |
| 1815 |
for (int i=0; i<5; i++) { |
for (int i=0; i<5; i++) { |
| 1816 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1817 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1819 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1820 |
wp += 2; |
wp += 2; |
| 1821 |
} |
} |
| 1822 |
if (ROMType == ROMTYPE_ZANZIBAR) { |
if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) { |
| 1823 |
for (int i=0; i<6; i++) { |
for (int i=0; i<6; i++) { |
| 1824 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1825 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1845 |
|
|
| 1846 |
// Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them) |
// Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them) |
| 1847 |
static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c}; |
static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c}; |
| 1848 |
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; |
| 1849 |
D(bug("cpu_speed %08lx\n", base)); |
D(bug("cpu_speed %08lx\n", base)); |
| 1850 |
wp = (uint16 *)(ROM_BASE + base); |
wp = (uint16 *)(ROM_BASE + base); |
| 1851 |
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
| 1852 |
*wp++ = htons(CPUClockSpeed / 1000000); |
*wp++ = htons(CPUClockSpeed / 1000000); |
| 1853 |
*wp++ = htons(CPUClockSpeed / 1000000); |
*wp++ = htons(CPUClockSpeed / 1000000); |
| 1854 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 1855 |
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) { |
| 1856 |
D(bug("cpu_speed2 %08lx\n", base)); |
D(bug("cpu_speed2 %08lx\n", base)); |
| 1857 |
wp = (uint16 *)(ROM_BASE + base); |
wp = (uint16 *)(ROM_BASE + base); |
| 1858 |
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
*wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 |
| 1892 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 1893 |
|
|
| 1894 |
// Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8) |
// Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8) |
| 1895 |
if (ROMType == ROMTYPE_NEWWORLD) { |
if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { |
| 1896 |
static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9}; |
static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9}; |
| 1897 |
if ((base = find_rom_data(0x2e0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false; |
if ((base = find_rom_data(0x2a0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false; |
| 1898 |
D(bug("tm_task %08lx\n", base)); |
D(bug("tm_task %08lx\n", base)); |
| 1899 |
wp = (uint16 *)(ROM_BASE + base + 28); |
wp = (uint16 *)(ROM_BASE + base + 28); |
| 1900 |
*wp++ = htons(M68K_NOP); |
*wp++ = htons(M68K_NOP); |
| 1914 |
} |
} |
| 1915 |
|
|
| 1916 |
// Don't read PVR from 0x5fffef80 in DriverServicesLib (via 0x316) |
// Don't read PVR from 0x5fffef80 in DriverServicesLib (via 0x316) |
| 1917 |
if (ROMType != ROMTYPE_NEWWORLD) { |
if (ROMType != ROMTYPE_NEWWORLD && ROMType != ROMTYPE_GOSSAMER) { |
| 1918 |
uint32 dsl_offset = find_rom_resource(FOURCC('n','l','i','b'), -16401); |
uint32 dsl_offset = find_rom_resource(FOURCC('n','l','i','b'), -16401); |
| 1919 |
if (ROMType == ROMTYPE_ZANZIBAR) { |
if (ROMType == ROMTYPE_ZANZIBAR) { |
| 1920 |
static const uint8 dsl_pvr_dat[] = {0x40, 0x82, 0x00, 0x40, 0x38, 0x60, 0xef, 0x80, 0x3c, 0x63, 0x60, 0x00, 0x80, 0x83, 0x00, 0x00, 0x54, 0x84, 0x84, 0x3e}; |
static const uint8 dsl_pvr_dat[] = {0x40, 0x82, 0x00, 0x40, 0x38, 0x60, 0xef, 0x80, 0x3c, 0x63, 0x60, 0x00, 0x80, 0x83, 0x00, 0x00, 0x54, 0x84, 0x84, 0x3e}; |
| 1949 |
*lp = htonl(0x38600000); // li r3,0 |
*lp = htonl(0x38600000); // li r3,0 |
| 1950 |
} |
} |
| 1951 |
|
|
| 1952 |
|
// FIXME: Fake reading from [HpChk]+4 (the callchain reports some function from DriverServicesLib) |
| 1953 |
|
if (1) { |
| 1954 |
|
uint32 hpchk_offset = find_rom_resource(FOURCC('n','l','i','b'), 10); |
| 1955 |
|
static const uint8 hpchk_dat[] = {0x80, 0x80, 0x03, 0x16, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xc4, 0x00, 0x04}; |
| 1956 |
|
if ((base = find_rom_data(hpchk_offset, hpchk_offset + 0x3000, hpchk_dat, sizeof(hpchk_dat))) == 0) return false; |
| 1957 |
|
D(bug("hpchk %08lx\n", base)); |
| 1958 |
|
lp = (uint32 *)(ROM_BASE + base); |
| 1959 |
|
*lp = htonl(0x80800000 + XLM_ZERO_PAGE); // lwz r4,(zero page) |
| 1960 |
|
} |
| 1961 |
|
|
| 1962 |
// Patch Name Registry |
// Patch Name Registry |
| 1963 |
static const uint8 name_reg_dat[] = {0x70, 0xff, 0xab, 0xeb}; |
static const uint8 name_reg_dat[] = {0x70, 0xff, 0xab, 0xeb}; |
| 1964 |
if ((base = find_rom_data(0x300, 0x380, name_reg_dat, sizeof(name_reg_dat))) == 0) return false; |
if ((base = find_rom_data(0x300, 0x380, name_reg_dat, sizeof(name_reg_dat))) == 0) return false; |
| 2010 |
D(bug("scsi_var2 %08lx\n", base)); |
D(bug("scsi_var2 %08lx\n", base)); |
| 2011 |
wp = (uint16 *)(ROM_BASE + base); |
wp = (uint16 *)(ROM_BASE + base); |
| 2012 |
*wp++ = htons(0x7000); // moveq #0,d0 |
*wp++ = htons(0x7000); // moveq #0,d0 |
| 2013 |
*wp = htons(M68K_RTS); // bra |
*wp = htons(M68K_RTS); |
| 2014 |
|
} |
| 2015 |
|
} |
| 2016 |
|
else if (ROMType == ROMTYPE_GOSSAMER) { |
| 2017 |
|
static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00}; |
| 2018 |
|
if ((base = find_rom_data(0x1d700, 0x1d800, scsi_var_dat, sizeof(scsi_var_dat))) != 0) { |
| 2019 |
|
D(bug("scsi_var %08lx\n", base)); |
| 2020 |
|
wp = (uint16 *)(ROM_BASE + base + 12); |
| 2021 |
|
*wp = htons(0x6000); // bra |
| 2022 |
|
} |
| 2023 |
|
|
| 2024 |
|
static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x5a, 0x48, 0xe7, 0x1f, 0x38}; |
| 2025 |
|
if ((base = find_rom_data(0x1d900, 0x1da00, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) { |
| 2026 |
|
D(bug("scsi_var2 %08lx\n", base)); |
| 2027 |
|
wp = (uint16 *)(ROM_BASE + base); |
| 2028 |
|
*wp++ = htons(0x7000); // moveq #0,d0 |
| 2029 |
|
*wp = htons(M68K_RTS); |
| 2030 |
} |
} |
| 2031 |
} |
} |
| 2032 |
#endif |
#endif |
| 2082 |
memcpy((void *)(ROM_BASE + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver)); |
memcpy((void *)(ROM_BASE + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver)); |
| 2083 |
|
|
| 2084 |
// Install serial drivers |
// Install serial drivers |
| 2085 |
memcpy((void *)(ROM_BASE + sony_offset + 0x300), ain_driver, sizeof(ain_driver)); |
gen_ain_driver( ROM_BASE + sony_offset + 0x300); |
| 2086 |
memcpy((void *)(ROM_BASE + sony_offset + 0x400), aout_driver, sizeof(aout_driver)); |
gen_aout_driver(ROM_BASE + sony_offset + 0x400); |
| 2087 |
memcpy((void *)(ROM_BASE + sony_offset + 0x500), bin_driver, sizeof(bin_driver)); |
gen_bin_driver( ROM_BASE + sony_offset + 0x500); |
| 2088 |
memcpy((void *)(ROM_BASE + sony_offset + 0x600), bout_driver, sizeof(bout_driver)); |
gen_bout_driver(ROM_BASE + sony_offset + 0x600); |
| 2089 |
|
|
| 2090 |
// Copy icons to ROM |
// Copy icons to ROM |
| 2091 |
SonyDiskIconAddr = ROM_BASE + sony_offset + 0x800; |
SonyDiskIconAddr = ROM_BASE + sony_offset + 0x800; |
| 2106 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 2107 |
|
|
| 2108 |
// Don't install serial drivers from ROM |
// Don't install serial drivers from ROM |
| 2109 |
if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD) { |
if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { |
| 2110 |
wp = (uint16 *)(ROM_BASE + find_rom_resource(FOURCC('S','E','R','D'), 0)); |
wp = (uint16 *)(ROM_BASE + find_rom_resource(FOURCC('S','E','R','D'), 0)); |
| 2111 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 2112 |
} else { |
} else { |
| 2165 |
wp = (uint16 *)(ROM_BASE + base); |
wp = (uint16 *)(ROM_BASE + base); |
| 2166 |
if (ROMType == ROMTYPE_ZANZIBAR) |
if (ROMType == ROMTYPE_ZANZIBAR) |
| 2167 |
*wp = htons(M68K_RTS); |
*wp = htons(M68K_RTS); |
| 2168 |
else |
else if (ntohs(wp[-4]) == 0x61ff) |
| 2169 |
|
*wp = htons(M68K_RTS); |
| 2170 |
|
else if (ntohs(wp[-2]) == 0x6700) |
| 2171 |
wp[-2] = htons(0x6000); // bra |
wp[-2] = htons(0x6000); // bra |
| 2172 |
|
|
| 2173 |
// Patch PowerOff() |
// Patch PowerOff() |
| 2197 |
|
|
| 2198 |
if (ROMType == ROMTYPE_NEWWORLD) { |
if (ROMType == ROMTYPE_NEWWORLD) { |
| 2199 |
static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26}; |
static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26}; |
| 2200 |
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; |
| 2201 |
D(bug("via_int3 %08lx\n", base)); |
D(bug("via_int3 %08lx\n", base)); |
| 2202 |
wp = (uint16 *)(ROM_BASE + base); // CHRP level 1 handler |
wp = (uint16 *)(ROM_BASE + base); // CHRP level 1 handler |
| 2203 |
*wp++ = htons(M68K_JMP); |
*wp++ = htons(M68K_JMP); |
| 2287 |
{ |
{ |
| 2288 |
D(bug("Installing drivers...\n")); |
D(bug("Installing drivers...\n")); |
| 2289 |
M68kRegisters r; |
M68kRegisters r; |
| 2290 |
uint8 pb[SIZEOF_IOParam]; |
SheepArray<SIZEOF_IOParam> pb_var; |
| 2291 |
|
const uintptr pb = pb_var.addr(); |
| 2292 |
|
|
| 2293 |
|
// Install floppy driver |
| 2294 |
|
if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { |
| 2295 |
|
|
| 2296 |
|
// Force installation of floppy driver with NewWorld and Gossamer ROMs |
| 2297 |
|
r.a[0] = ROM_BASE + sony_offset; |
| 2298 |
|
r.d[0] = (uint32)SonyRefNum; |
| 2299 |
|
Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() |
| 2300 |
|
r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~SonyRefNum * 4); // Get driver handle from Unit Table |
| 2301 |
|
Execute68kTrap(0xa029, &r); // HLock() |
| 2302 |
|
uint32 dce = ReadMacInt32(r.a[0]); |
| 2303 |
|
WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset); |
| 2304 |
|
WriteMacInt16(dce + dCtlFlags, SonyDriverFlags); |
| 2305 |
|
} |
| 2306 |
|
|
| 2307 |
|
#if DISABLE_SCSI && 0 |
| 2308 |
|
// Fake SCSIGlobals |
| 2309 |
|
WriteMacInt32(0xc0c, SheepMem::ZeroPage()); |
| 2310 |
|
#endif |
| 2311 |
|
|
| 2312 |
// Open .Sony driver |
// Open .Sony driver |
| 2313 |
WriteMacInt8((uint32)pb + ioPermssn, 0); |
SheepString sony_str("\005.Sony"); |
| 2314 |
WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\005.Sony"); |
WriteMacInt8(pb + ioPermssn, 0); |
| 2315 |
r.a[0] = (uint32)pb; |
WriteMacInt32(pb + ioNamePtr, sony_str.addr()); |
| 2316 |
|
r.a[0] = pb; |
| 2317 |
Execute68kTrap(0xa000, &r); // Open() |
Execute68kTrap(0xa000, &r); // Open() |
| 2318 |
|
|
| 2319 |
// Install disk driver |
// Install disk driver |
| 2327 |
WriteMacInt16(dce + dCtlFlags, DiskDriverFlags); |
WriteMacInt16(dce + dCtlFlags, DiskDriverFlags); |
| 2328 |
|
|
| 2329 |
// Open disk driver |
// Open disk driver |
| 2330 |
WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\005.Disk"); |
SheepString disk_str("\005.Disk"); |
| 2331 |
r.a[0] = (uint32)pb; |
WriteMacInt32(pb + ioNamePtr, disk_str.addr()); |
| 2332 |
|
r.a[0] = pb; |
| 2333 |
Execute68kTrap(0xa000, &r); // Open() |
Execute68kTrap(0xa000, &r); // Open() |
| 2334 |
|
|
| 2335 |
// Install CD-ROM driver unless nocdrom option given |
// Install CD-ROM driver unless nocdrom option given |
| 2346 |
WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags); |
WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags); |
| 2347 |
|
|
| 2348 |
// Open CD-ROM driver |
// Open CD-ROM driver |
| 2349 |
WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\010.AppleCD"); |
SheepString apple_cd("\010.AppleCD"); |
| 2350 |
r.a[0] = (uint32)pb; |
WriteMacInt32(pb + ioNamePtr, apple_cd.addr()); |
| 2351 |
|
r.a[0] = pb; |
| 2352 |
Execute68kTrap(0xa000, &r); // Open() |
Execute68kTrap(0xa000, &r); // Open() |
| 2353 |
} |
} |
| 2354 |
|
|