Enable Apple DR emulator from NewWorld ROMs only.

This commit is contained in:
gbeauche 2004-05-31 09:04:44 +00:00
parent d048916fda
commit 7bc86b27ee
9 changed files with 88 additions and 19 deletions

View File

@ -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);

View File

@ -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
};

View File

@ -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

View File

@ -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);

View File

@ -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."},

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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;
}