--- SheepShaver/src/BeOS/main_beos.cpp 2002/04/21 15:07:08 1.2 +++ SheepShaver/src/BeOS/main_beos.cpp 2004/11/22 21:22:58 1.15 @@ -1,7 +1,7 @@ /* * main_beos.cpp - Emulation core, BeOS implementation * - * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig + * SheepShaver (C) 1997-2004 Christian Bauer and Marc Hellwig * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -88,6 +88,7 @@ #include "macos_util.h" #include "rom_patches.h" #include "user_strings.h" +#include "thunks.h" #include "sheep_driver.h" @@ -116,31 +117,14 @@ const char KERNEL_AREA2_NAME[] = "Macint const char RAM_AREA_NAME[] = "Macintosh RAM"; const char ROM_AREA_NAME[] = "Macintosh ROM"; const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; - -const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area - -const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data -const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data -const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area +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 const uint32 MSG_START = 'strt'; // Emulator start message -// Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - - // Application object class SheepShaver : public BApplication { public: @@ -159,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; @@ -207,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) @@ -230,13 +215,23 @@ 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) +int64 TimebaseSpeed; // Timebase clock speed (Hz) system_info SysInfo; // System information +uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) +uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) static void *sig_stack = NULL; // Stack for signal handlers static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler +uint32 SheepMem::page_size; // Size of a native page +uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros +uintptr SheepMem::base; // Address of SheepShaver data +uintptr SheepMem::proc; // Bottom address of SheepShave procedures +uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) +static area_id SheepMemArea; // SheepShaver data area ID // Prototypes @@ -308,6 +303,7 @@ void SheepShaver::ReadyToRun(void) } CPUClockSpeed = SysInfo.cpu_clock_speed; BusClockSpeed = SysInfo.bus_clock_speed; + TimebaseSpeed = BusClockSpeed / 4; // Delete old areas area_id old_kernel_area = find_area(KERNEL_AREA_NAME); @@ -325,6 +321,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; @@ -372,6 +371,7 @@ void SheepShaver::MessageReceived(BMessa void SheepShaver::StartEmulator(void) { char str[256]; + int16 i16; // Open sheep driver and remap low memory sheep_fd = open("/dev/sheep", 0); @@ -412,6 +412,14 @@ void SheepShaver::StartEmulator(void) } D(bug("Kernel Data 2 area %ld at %p\n", kernel_area2, kernel_data2)); + // Create area for SheepShaver data + if (!SheepMem::Init()) { + sprintf(str, GetString(STR_NO_SHEEP_MEM_AREA_ERR), strerror(SheepMemArea), SheepMemArea); + ErrorAlert(str); + PostMessage(B_QUIT_REQUESTED); + return; + } + // Create area for Mac RAM RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary if (RAMSize < 8*1024*1024) { @@ -427,7 +435,8 @@ void SheepShaver::StartEmulator(void) PostMessage(B_QUIT_REQUESTED); return; } - D(bug("RAM area %ld at %p\n", ram_area, RAMBase)); + RAMBaseHost = (uint8 *)RAMBase + D(bug("RAM area %ld at %p\n", ram_area, RAMBaseHost)); // Create area and load Mac ROM try { @@ -461,14 +470,25 @@ 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(); // Set boot volume - drive = PrefsFindInt32("bootdrive"); + i16 = PrefsFindInt32("bootdrive"); XPRAM[0x1378] = i16 >> 8; XPRAM[0x1379] = i16 & 0xff; - driver = PrefsFindInt32("bootdriver"); + i16 = PrefsFindInt32("bootdriver"); XPRAM[0x137a] = i16 >> 8; XPRAM[0x137b] = i16 & 0xff; @@ -481,6 +501,12 @@ void SheepShaver::StartEmulator(void) boot_globs[1] = htonl(RAMSize); boot_globs[2] = htonl((uint32)-1); // End of bank table + // Init thunks + if (!InitThunks()) { + PostMessage(B_QUIT_REQUESTED); + return; + } + // Init drivers SonyInit(); DiskInit(); @@ -520,7 +546,7 @@ void SheepShaver::StartEmulator(void) // Clear caches (as we loaded and patched code) and write protect ROM #if !EMULATED_PPC - clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); + clear_caches(ROMBaseHost, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); #endif set_area_protection(rom_area, B_READ_AREA); @@ -577,6 +603,7 @@ void SheepShaver::StartEmulator(void) WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode) + WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0 #if !EMULATED_PPC WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator WriteMacInt32(XLM_ETHER_INIT, *(uint32 *)InitStreamModule); // DLPI ethernet driver functions @@ -673,6 +700,16 @@ void SheepShaver::Quit(void) DiskExit(); SonyExit(); + // Delete thunks + ThunksExit(); + + // 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); @@ -717,9 +754,12 @@ void SheepShaver::Quit(void) void SheepShaver::init_rom(void) { + // Size of a native page + page_size = B_PAGE_SIZE; + // Create area for ROM - void *rom_addr = (void *)ROM_BASE; - rom_area = create_area(ROM_AREA_NAME, &rom_addr, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + ROMBaseHost = (uint8 *)ROM_BASE; + rom_area = create_area(ROM_AREA_NAME, (void **)&ROMBaseHost, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); if (rom_area < 0) throw area_error(); D(bug("ROM area %ld at %p\n", rom_area, rom_addr)); @@ -1261,18 +1301,6 @@ void Execute68kTrap(uint16 trap, M68kReg /* - * Execute PPC code from EMUL_OP routine (real mode switch) - */ - -void ExecutePPC(void (*func)()) -{ - RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, func); - M68kRegisters r; - Execute68k((uint32)&desc, &r); -} - - -/* * Quit emulator (must only be called from main thread) */ @@ -1313,11 +1341,11 @@ void Dump68kRegs(M68kRegisters *r) * Make code executable */ -void MakeExecutable(int dummy, void *start, uint32 length) +void MakeExecutable(int dummy, uint32 start, uint32 length) { - if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE))) + if ((start >= ROM_BASE) && (start < (ROM_BASE + ROM_SIZE))) return; - clear_caches(start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); + clear_caches((void *)start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); } @@ -1327,7 +1355,7 @@ void MakeExecutable(int dummy, void *sta void PatchAfterStartup(void) { - ExecutePPC(VideoInstallAccel); + ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL); InstallExtFS(); } @@ -1336,7 +1364,7 @@ void PatchAfterStartup(void) * NVRAM watchdog thread (saves NVRAM every minute) */ -static status_t SheepShaver::nvram_func(void *arg) +status_t SheepShaver::nvram_func(void *arg) { SheepShaver *obj = (SheepShaver *)arg; @@ -1575,7 +1603,7 @@ void SheepShaver::sigusr1_handler(vregs if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); ADBInterrupt(); - ExecutePPC(VideoVBL); + ExecuteNative(NATIVE_VIDEO_VBL); } } #endif @@ -2070,6 +2098,39 @@ rti: } +/* + * Helpers to share 32-bit addressable data with MacOS + */ + +bool SheepMem::Init(void) +{ + // Delete old area + area_id old_sheep_area = find_area(SHEEP_AREA_NAME); + if (old_sheep_area > 0) + delete_area(old_sheep_area); + + // Create area for SheepShaver data + proc = base = 0x60000000; + SheepMemArea = create_area(SHEEP_AREA_NAME, (void **)&base, B_BASE_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (SheepMemArea < 0) + return false; + + // Create read-only area with all bits set to 0 + static const uint8 const_zero_page[4096] = {0,}; + zero_page = const_zero_page; + + D(bug("SheepShaver area %ld at %p\n", SheepMemArea, base)); + data = base + size; + return true; +} + +void SheepMem::Exit(void) +{ + if (SheepMemArea >= 0) + delete_area(SheepMemArea); +} + + /* * Display error alert */