diff --git a/SheepShaver/src/BeOS/main_beos.cpp b/SheepShaver/src/BeOS/main_beos.cpp index 286a1ce8..542e266e 100644 --- a/SheepShaver/src/BeOS/main_beos.cpp +++ b/SheepShaver/src/BeOS/main_beos.cpp @@ -117,6 +117,7 @@ const char KERNEL_AREA2_NAME[] = "Macintosh Kernel Data 2"; const char RAM_AREA_NAME[] = "Macintosh RAM"; const char ROM_AREA_NAME[] = "Macintosh ROM"; const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; +const char DR_EMULATOR_AREA_NAME[] = "Macintosh DR Emulator"; const char SHEEP_AREA_NAME[] = "SheepShaver Virtual Stack"; const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack @@ -142,7 +143,7 @@ public: // Initialize other variables sheep_fd = -1; emulator_data = NULL; - kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = -1; + kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = dr_emulator_area = -1; emul_thread = nvram_thread = tick_thread = -1; ReadyForSignals = false; AllowQuitting = true; @@ -190,6 +191,7 @@ private: area_id rom_area; // ROM area ID area_id ram_area; // RAM area ID area_id dr_cache_area; // DR Cache area ID + area_id dr_emulator_area; // DR Emulator area ID struct sigaction sigusr1_action; // Interrupt signal (of emulator thread) struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) @@ -213,6 +215,7 @@ uint32 RAMSize; // Size of Mac RAM uint32 KernelDataAddr; // Address of Kernel Data uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM uint32 DRCacheAddr; // Address of DR Cache +uint32 DREmulatorAddr; // Address of DR Emulator uint32 PVR; // Theoretical PVR int64 CPUClockSpeed; // Processor clock speed (Hz) int64 BusClockSpeed; // Bus clock speed (Hz) @@ -313,6 +316,9 @@ void SheepShaver::ReadyToRun(void) area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME); if (old_dr_cache_area > 0) delete_area(old_dr_cache_area); + area_id old_dr_emulator_area = find_area(DR_EMULATOR_AREA_NAME); + if (old_dr_emulator_area > 0) + delete_area(old_dr_emulator_area); // Read preferences int argc = 0; @@ -403,7 +409,7 @@ void SheepShaver::StartEmulator(void) // Create area for SheepShaver data if (!SheepMem::Init()) { - sprintf(str, GetString(STR_NO_SHEEP_MEM_AREA_ERR)); + sprintf(str, GetString(STR_NO_SHEEP_MEM_AREA_ERR), strerror(SheepMemArea), SheepMemArea); ErrorAlert(str); PostMessage(B_QUIT_REQUESTED); return; @@ -458,6 +464,17 @@ void SheepShaver::StartEmulator(void) } D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr)); + // Create area for DR Emulator + DREmulatorAddr = DR_EMULATOR_BASE; + dr_emulator_area = create_area(DR_EMULATOR_AREA_NAME, (void **)&DREmulatorAddr, B_EXACT_ADDRESS, DR_EMULATOR_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (dr_emulator_area < 0) { + sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_emulator_area), dr_emulator_area); + ErrorAlert(str); + PostMessage(B_QUIT_REQUESTED); + return; + } + D(bug("DR Emulator area %ld at %p\n", dr_emulator_area, DREmulatorAddr)); + // Load NVRAM XPRAMInit(); @@ -683,6 +700,10 @@ void SheepShaver::Quit(void) // Delete SheepShaver globals SheepMem::Exit(); + // Delete DR Emulator area + if (dr_emulator_area >= 0) + delete_area(dr_emulator_area); + // Delete DR Cache area if (dr_cache_area >= 0) delete_area(dr_cache_area); diff --git a/SheepShaver/src/BeOS/user_strings_beos.cpp b/SheepShaver/src/BeOS/user_strings_beos.cpp index 38fbb311..033db9de 100644 --- a/SheepShaver/src/BeOS/user_strings_beos.cpp +++ b/SheepShaver/src/BeOS/user_strings_beos.cpp @@ -40,6 +40,9 @@ user_string_def platform_strings[] = { {STR_NET_CONFIG_MODIFY_WARN, "To enable Ethernet networking for SheepShaver, your network configuration has to be modified and the network restarted. Do you want this to be done now (selecting \"Cancel\" will disable Ethernet under SheepShaver)?."}, {STR_NET_ADDON_INIT_FAILED, "SheepShaver net server add-on found\nbut there seems to be no network hardware.\nPlease check your network preferences."}, {STR_NET_ADDON_CLONE_FAILED, "Cloning of the network transfer area failed."}, + {STR_NO_SHEEP_MEM_AREA_ERR, "Cannot create SheepShaver Globals area: %s (%08x)."}, + {STR_NO_DR_CACHE_AREA_ERR, "Cannot create DR Cache area: %s (%08x)."}, + {STR_NO_DR_EMULATOR_AREA_ERR, "Cannot create DR Emulator area: %s (%08x)."}, {-1, NULL} // End marker }; diff --git a/SheepShaver/src/BeOS/user_strings_beos.h b/SheepShaver/src/BeOS/user_strings_beos.h index a3ce5d76..98c7d8e2 100644 --- a/SheepShaver/src/BeOS/user_strings_beos.h +++ b/SheepShaver/src/BeOS/user_strings_beos.h @@ -29,7 +29,9 @@ enum { STR_NET_CONFIG_MODIFY_WARN, STR_NET_ADDON_INIT_FAILED, STR_NET_ADDON_CLONE_FAILED, - STR_NO_SHEEP_MEM_AREA_ERR + STR_NO_SHEEP_MEM_AREA_ERR, + STR_NO_DR_CACHE_AREA_ERR, + STR_NO_DR_EMULATOR_AREA_ERR }; #endif diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp index b955a0f9..54eb670a 100644 --- a/SheepShaver/src/Unix/main_unix.cpp +++ b/SheepShaver/src/Unix/main_unix.cpp @@ -265,6 +265,7 @@ uint32 RAMBase; // Base address of Mac RAM uint32 RAMSize; // Size of Mac RAM uint32 KernelDataAddr; // Address of Kernel Data uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM +uint32 DRCacheAddr; // Address of DR Cache uint32 PVR; // Theoretical PVR int64 CPUClockSpeed; // Processor clock speed (Hz) int64 BusClockSpeed; // Bus clock speed (Hz) @@ -282,6 +283,8 @@ static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped static int kernel_area = -1; // SHM ID of Kernel Data area static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped +static bool dr_cache_area_mapped = false; // Flag: Mac DR Cache mmap()ped +static bool dr_emulator_area_mapped = false;// Flag: Mac DR Emulator mmap()ped static KernelData *kernel_data; // Pointer to Kernel Data static EmulatorData *emulator_data; @@ -597,6 +600,22 @@ int main(int argc, char **argv) KernelDataAddr = KERNEL_DATA_BASE; D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data)); + // Create area for DR Cache + if (vm_acquire_fixed((void *)DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) { + sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } + dr_emulator_area_mapped = true; + if (vm_acquire_fixed((void *)DR_CACHE_BASE, DR_CACHE_SIZE) < 0) { + sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } + dr_cache_area_mapped = true; + DRCacheAddr = DR_CACHE_BASE; + D(bug("DR Cache at %p\n", DRCacheAddr)); + // Create area for SheepShaver data if (!SheepMem::Init()) { sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); @@ -1023,6 +1042,12 @@ static void Quit(void) if (rom_area_mapped) vm_release((char *)ROM_BASE, ROM_AREA_SIZE); + // Delete DR cache areas + if (dr_emulator_area_mapped) + vm_release((void *)DR_EMULATOR_BASE, DR_EMULATOR_SIZE); + if (dr_cache_area_mapped) + vm_release((void *)DR_CACHE_BASE, DR_CACHE_SIZE); + // Delete Kernel Data area if (kernel_area >= 0) { shmdt((void *)KERNEL_DATA_BASE); diff --git a/SheepShaver/src/Unix/user_strings_unix.cpp b/SheepShaver/src/Unix/user_strings_unix.cpp index 296b7c56..e08149de 100644 --- a/SheepShaver/src/Unix/user_strings_unix.cpp +++ b/SheepShaver/src/Unix/user_strings_unix.cpp @@ -38,6 +38,8 @@ user_string_def platform_strings[] = { {STR_KD2_SHMAT_ERR, "Cannot map second Kernel Data area: %s."}, {STR_ROM_MMAP_ERR, "Cannot map ROM: %s."}, {STR_RAM_MMAP_ERR, "Cannot map RAM: %s."}, + {STR_DR_CACHE_MMAP_ERR, "Cannot map DR Cache: %s."}, + {STR_DR_EMULATOR_MMAP_ERR, "Cannot map DR Emulator: %s."}, {STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."}, {STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s). It seems that you need a newer kernel."}, {STR_SIGSEGV_INSTALL_ERR, "Cannot install SIGSEGV handler: %s."}, diff --git a/SheepShaver/src/Unix/user_strings_unix.h b/SheepShaver/src/Unix/user_strings_unix.h index 8dfd29bc..f57dc530 100644 --- a/SheepShaver/src/Unix/user_strings_unix.h +++ b/SheepShaver/src/Unix/user_strings_unix.h @@ -29,6 +29,8 @@ enum { STR_KD2_SHMAT_ERR, STR_ROM_MMAP_ERR, STR_RAM_MMAP_ERR, + STR_DR_CACHE_MMAP_ERR, + STR_DR_EMULATOR_MMAP_ERR, STR_SHEEP_MEM_MMAP_ERR, STR_SIGALTSTACK_ERR, STR_SIGSEGV_INSTALL_ERR, diff --git a/SheepShaver/src/emul_op.cpp b/SheepShaver/src/emul_op.cpp index bcd61946..44ad9137 100644 --- a/SheepShaver/src/emul_op.cpp +++ b/SheepShaver/src/emul_op.cpp @@ -287,15 +287,18 @@ void EmulOp(M68kRegisters *r, uint32 pc, int selector) TimerReset(); MacOSUtilReset(); AudioReset(); -#if 0 - printf("DR activated\n"); - WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation - WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE); - WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE); - WriteMacInt32(KernelDataAddr + 0x1b00, DR_CACHE_BASE + 0x10000); - memcpy((void *)(DR_CACHE_BASE + 0x10000), (void *)(ROM_BASE + 0x370000), 0x10000); - clear_caches((void *)(DR_CACHE_BASE + 0x10000), 0x10000, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); -#endif + + // Enable DR emulator from NewWorld ROMs + if (ROMType == ROMTYPE_NEWWORLD) { + D(bug("DR activated\n")); + WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation + WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE); + WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE); + WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE); + WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE); + memcpy((void *)DR_EMULATOR_BASE, (void *)(ROM_BASE + 0x370000), DR_EMULATOR_SIZE); + MakeExecutable(0, (void *)DR_EMULATOR_BASE, DR_EMULATOR_SIZE); + } break; case OP_IRQ: // Level 1 interrupt diff --git a/SheepShaver/src/include/cpu_emulation.h b/SheepShaver/src/include/cpu_emulation.h index 7c5c3900..83ef4c0c 100644 --- a/SheepShaver/src/include/cpu_emulation.h +++ b/SheepShaver/src/include/cpu_emulation.h @@ -31,6 +31,8 @@ const uintptr ROM_BASE = 0x40800000; // Base address of ROM const uint32 ROM_SIZE = 0x400000; // Size of ROM file const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area const uintptr ROM_END = ROM_BASE + ROM_SIZE; // End of ROM +const uintptr DR_EMULATOR_BASE = 0x68070000; // Address of DR emulator code +const uint32 DR_EMULATOR_SIZE = 0x10000; // Size of DR emulator code const uintptr DR_CACHE_BASE = 0x69000000; // Address of DR cache const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache diff --git a/SheepShaver/src/rom_patches.cpp b/SheepShaver/src/rom_patches.cpp index 015d05b5..f59c2ce5 100644 --- a/SheepShaver/src/rom_patches.cpp +++ b/SheepShaver/src/rom_patches.cpp @@ -1058,7 +1058,7 @@ static bool patch_nanokernel_boot(void) static bool patch_68k_emul(void) { uint32 *lp; - uint32 base; + uint32 base, loc; // Overwrite twi instructions static const uint8 twi_dat[] = {0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0x0f, 0xff, 0x00, 0x02}; @@ -1266,12 +1266,21 @@ static bool patch_68k_emul(void) return false; dr_found: lp++; - *lp = htonl(0x48000000 + 0xf000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b DR_CACHE_BASE+0x1f000 - lp = (uint32 *)(ROM_BASE + 0x37f000); - *lp++ = htonl(0x3c000000 + ((ROM_BASE + 0x46d0a4) >> 16)); // lis r0,xxx - *lp++ = htonl(0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff)); // ori r0,r0,xxx - *lp++ = htonl(0x7c0903a6); // mtctr r0 - *lp = htonl(POWERPC_BCTR); // bctr + loc = (uint32)lp - ROM_BASE; + if ((base = powerpc_branch_target(ROM_BASE + loc)) == 0) base = ROM_BASE + loc; + static const uint8 dr_ret_dat[] = {0x80, 0xbf, 0x08, 0x14, 0x53, 0x19, 0x4d, 0xac, 0x7c, 0xa8, 0x03, 0xa6}; + if ((base = find_rom_data(base - ROM_BASE, 0x380000, dr_ret_dat, sizeof(dr_ret_dat))) == 0) return false; + D(bug("dr_ret %08lx\n", base)); + if (base != loc) { + // OldWorld ROMs contain an absolute branch + D(bug(" patching absolute branch at %08x\n", (uint32)lp - ROM_BASE)); + *lp = htonl(0x48000000 + 0xf000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b DR_CACHE_BASE+0x1f000 + lp = (uint32 *)(ROM_BASE + 0x37f000); + *lp++ = htonl(0x3c000000 + ((ROM_BASE + base) >> 16)); // lis r0,xxx + *lp++ = htonl(0x60000000 + ((ROM_BASE + base) & 0xffff)); // ori r0,r0,xxx + *lp++ = htonl(0x7c0803a6); // mtlr r0 + *lp = htonl(POWERPC_BLR); // blr + } return true; }