1 |
|
/* |
2 |
|
* main_beos.cpp - Emulation core, BeOS implementation |
3 |
|
* |
4 |
< |
* SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig |
4 |
> |
* SheepShaver (C) 1997-2004 Christian Bauer and Marc Hellwig |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
88 |
|
#include "macos_util.h" |
89 |
|
#include "rom_patches.h" |
90 |
|
#include "user_strings.h" |
91 |
+ |
#include "thunks.h" |
92 |
|
|
93 |
|
#include "sheep_driver.h" |
94 |
|
|
117 |
|
const char RAM_AREA_NAME[] = "Macintosh RAM"; |
118 |
|
const char ROM_AREA_NAME[] = "Macintosh ROM"; |
119 |
|
const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; |
120 |
< |
|
121 |
< |
const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area |
121 |
< |
|
122 |
< |
const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data |
123 |
< |
const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data |
124 |
< |
const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area |
120 |
> |
const char DR_EMULATOR_AREA_NAME[] = "Macintosh DR Emulator"; |
121 |
> |
const char SHEEP_AREA_NAME[] = "SheepShaver Virtual Stack"; |
122 |
|
|
123 |
|
const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack |
124 |
|
|
125 |
|
const uint32 MSG_START = 'strt'; // Emulator start message |
126 |
|
|
127 |
|
|
131 |
– |
// Emulator Data |
132 |
– |
struct EmulatorData { |
133 |
– |
uint32 v[0x400]; |
134 |
– |
}; |
135 |
– |
|
136 |
– |
|
137 |
– |
// Kernel Data |
138 |
– |
struct KernelData { |
139 |
– |
uint32 v[0x400]; |
140 |
– |
EmulatorData ed; |
141 |
– |
}; |
142 |
– |
|
143 |
– |
|
128 |
|
// Application object |
129 |
|
class SheepShaver : public BApplication { |
130 |
|
public: |
143 |
|
// Initialize other variables |
144 |
|
sheep_fd = -1; |
145 |
|
emulator_data = NULL; |
146 |
< |
kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = -1; |
146 |
> |
kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = dr_emulator_area = -1; |
147 |
|
emul_thread = nvram_thread = tick_thread = -1; |
148 |
|
ReadyForSignals = false; |
149 |
|
AllowQuitting = true; |
191 |
|
area_id rom_area; // ROM area ID |
192 |
|
area_id ram_area; // RAM area ID |
193 |
|
area_id dr_cache_area; // DR Cache area ID |
194 |
+ |
area_id dr_emulator_area; // DR Emulator area ID |
195 |
|
|
196 |
|
struct sigaction sigusr1_action; // Interrupt signal (of emulator thread) |
197 |
|
struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) |
215 |
|
uint32 KernelDataAddr; // Address of Kernel Data |
216 |
|
uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM |
217 |
|
uint32 DRCacheAddr; // Address of DR Cache |
218 |
+ |
uint32 DREmulatorAddr; // Address of DR Emulator |
219 |
|
uint32 PVR; // Theoretical PVR |
220 |
|
int64 CPUClockSpeed; // Processor clock speed (Hz) |
221 |
|
int64 BusClockSpeed; // Bus clock speed (Hz) |
222 |
+ |
int64 TimebaseSpeed; // Timebase clock speed (Hz) |
223 |
|
system_info SysInfo; // System information |
224 |
+ |
uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) |
225 |
+ |
uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) |
226 |
|
|
227 |
|
static void *sig_stack = NULL; // Stack for signal handlers |
228 |
|
static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler |
229 |
+ |
uint32 SheepMem::page_size; // Size of a native page |
230 |
+ |
uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros |
231 |
+ |
uintptr SheepMem::base; // Address of SheepShaver data |
232 |
+ |
uintptr SheepMem::proc; // Bottom address of SheepShave procedures |
233 |
+ |
uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) |
234 |
+ |
static area_id SheepMemArea; // SheepShaver data area ID |
235 |
|
|
236 |
|
|
237 |
|
// Prototypes |
303 |
|
} |
304 |
|
CPUClockSpeed = SysInfo.cpu_clock_speed; |
305 |
|
BusClockSpeed = SysInfo.bus_clock_speed; |
306 |
+ |
TimebaseSpeed = BusClockSpeed / 4; |
307 |
|
|
308 |
|
// Delete old areas |
309 |
|
area_id old_kernel_area = find_area(KERNEL_AREA_NAME); |
321 |
|
area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME); |
322 |
|
if (old_dr_cache_area > 0) |
323 |
|
delete_area(old_dr_cache_area); |
324 |
+ |
area_id old_dr_emulator_area = find_area(DR_EMULATOR_AREA_NAME); |
325 |
+ |
if (old_dr_emulator_area > 0) |
326 |
+ |
delete_area(old_dr_emulator_area); |
327 |
|
|
328 |
|
// Read preferences |
329 |
|
int argc = 0; |
371 |
|
void SheepShaver::StartEmulator(void) |
372 |
|
{ |
373 |
|
char str[256]; |
374 |
+ |
int16 i16; |
375 |
|
|
376 |
|
// Open sheep driver and remap low memory |
377 |
|
sheep_fd = open("/dev/sheep", 0); |
412 |
|
} |
413 |
|
D(bug("Kernel Data 2 area %ld at %p\n", kernel_area2, kernel_data2)); |
414 |
|
|
415 |
+ |
// Create area for SheepShaver data |
416 |
+ |
if (!SheepMem::Init()) { |
417 |
+ |
sprintf(str, GetString(STR_NO_SHEEP_MEM_AREA_ERR), strerror(SheepMemArea), SheepMemArea); |
418 |
+ |
ErrorAlert(str); |
419 |
+ |
PostMessage(B_QUIT_REQUESTED); |
420 |
+ |
return; |
421 |
+ |
} |
422 |
+ |
|
423 |
|
// Create area for Mac RAM |
424 |
|
RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary |
425 |
|
if (RAMSize < 8*1024*1024) { |
435 |
|
PostMessage(B_QUIT_REQUESTED); |
436 |
|
return; |
437 |
|
} |
438 |
< |
D(bug("RAM area %ld at %p\n", ram_area, RAMBase)); |
438 |
> |
RAMBaseHost = (uint8 *)RAMBase |
439 |
> |
D(bug("RAM area %ld at %p\n", ram_area, RAMBaseHost)); |
440 |
|
|
441 |
|
// Create area and load Mac ROM |
442 |
|
try { |
470 |
|
} |
471 |
|
D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr)); |
472 |
|
|
473 |
+ |
// Create area for DR Emulator |
474 |
+ |
DREmulatorAddr = DR_EMULATOR_BASE; |
475 |
+ |
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); |
476 |
+ |
if (dr_emulator_area < 0) { |
477 |
+ |
sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_emulator_area), dr_emulator_area); |
478 |
+ |
ErrorAlert(str); |
479 |
+ |
PostMessage(B_QUIT_REQUESTED); |
480 |
+ |
return; |
481 |
+ |
} |
482 |
+ |
D(bug("DR Emulator area %ld at %p\n", dr_emulator_area, DREmulatorAddr)); |
483 |
+ |
|
484 |
|
// Load NVRAM |
485 |
|
XPRAMInit(); |
486 |
|
|
487 |
|
// Set boot volume |
488 |
< |
drive = PrefsFindInt32("bootdrive"); |
488 |
> |
i16 = PrefsFindInt32("bootdrive"); |
489 |
|
XPRAM[0x1378] = i16 >> 8; |
490 |
|
XPRAM[0x1379] = i16 & 0xff; |
491 |
< |
driver = PrefsFindInt32("bootdriver"); |
491 |
> |
i16 = PrefsFindInt32("bootdriver"); |
492 |
|
XPRAM[0x137a] = i16 >> 8; |
493 |
|
XPRAM[0x137b] = i16 & 0xff; |
494 |
|
|
501 |
|
boot_globs[1] = htonl(RAMSize); |
502 |
|
boot_globs[2] = htonl((uint32)-1); // End of bank table |
503 |
|
|
504 |
+ |
// Init thunks |
505 |
+ |
if (!InitThunks()) { |
506 |
+ |
PostMessage(B_QUIT_REQUESTED); |
507 |
+ |
return; |
508 |
+ |
} |
509 |
+ |
|
510 |
|
// Init drivers |
511 |
|
SonyInit(); |
512 |
|
DiskInit(); |
546 |
|
|
547 |
|
// Clear caches (as we loaded and patched code) and write protect ROM |
548 |
|
#if !EMULATED_PPC |
549 |
< |
clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); |
549 |
> |
clear_caches(ROMBaseHost, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); |
550 |
|
#endif |
551 |
|
set_area_protection(rom_area, B_READ_AREA); |
552 |
|
|
603 |
|
WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR |
604 |
|
WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch |
605 |
|
WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode) |
606 |
+ |
WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0 |
607 |
|
#if !EMULATED_PPC |
608 |
|
WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator |
609 |
|
WriteMacInt32(XLM_ETHER_INIT, *(uint32 *)InitStreamModule); // DLPI ethernet driver functions |
700 |
|
DiskExit(); |
701 |
|
SonyExit(); |
702 |
|
|
703 |
+ |
// Delete thunks |
704 |
+ |
ThunksExit(); |
705 |
+ |
|
706 |
+ |
// Delete SheepShaver globals |
707 |
+ |
SheepMem::Exit(); |
708 |
+ |
|
709 |
+ |
// Delete DR Emulator area |
710 |
+ |
if (dr_emulator_area >= 0) |
711 |
+ |
delete_area(dr_emulator_area); |
712 |
+ |
|
713 |
|
// Delete DR Cache area |
714 |
|
if (dr_cache_area >= 0) |
715 |
|
delete_area(dr_cache_area); |
754 |
|
|
755 |
|
void SheepShaver::init_rom(void) |
756 |
|
{ |
757 |
+ |
// Size of a native page |
758 |
+ |
page_size = B_PAGE_SIZE; |
759 |
+ |
|
760 |
|
// Create area for ROM |
761 |
< |
void *rom_addr = (void *)ROM_BASE; |
762 |
< |
rom_area = create_area(ROM_AREA_NAME, &rom_addr, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); |
761 |
> |
ROMBaseHost = (uint8 *)ROM_BASE; |
762 |
> |
rom_area = create_area(ROM_AREA_NAME, (void **)&ROMBaseHost, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); |
763 |
|
if (rom_area < 0) |
764 |
|
throw area_error(); |
765 |
|
D(bug("ROM area %ld at %p\n", rom_area, rom_addr)); |
1301 |
|
|
1302 |
|
|
1303 |
|
/* |
1264 |
– |
* Execute PPC code from EMUL_OP routine (real mode switch) |
1265 |
– |
*/ |
1266 |
– |
|
1267 |
– |
void ExecutePPC(void (*func)()) |
1268 |
– |
{ |
1269 |
– |
RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, func); |
1270 |
– |
M68kRegisters r; |
1271 |
– |
Execute68k((uint32)&desc, &r); |
1272 |
– |
} |
1273 |
– |
|
1274 |
– |
|
1275 |
– |
/* |
1304 |
|
* Quit emulator (must only be called from main thread) |
1305 |
|
*/ |
1306 |
|
|
1341 |
|
* Make code executable |
1342 |
|
*/ |
1343 |
|
|
1344 |
< |
void MakeExecutable(int dummy, void *start, uint32 length) |
1344 |
> |
void MakeExecutable(int dummy, uint32 start, uint32 length) |
1345 |
|
{ |
1346 |
< |
if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE))) |
1346 |
> |
if ((start >= ROM_BASE) && (start < (ROM_BASE + ROM_SIZE))) |
1347 |
|
return; |
1348 |
< |
clear_caches(start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); |
1348 |
> |
clear_caches((void *)start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); |
1349 |
|
} |
1350 |
|
|
1351 |
|
|
1355 |
|
|
1356 |
|
void PatchAfterStartup(void) |
1357 |
|
{ |
1358 |
< |
ExecutePPC(VideoInstallAccel); |
1358 |
> |
ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL); |
1359 |
|
InstallExtFS(); |
1360 |
|
} |
1361 |
|
|
1364 |
|
* NVRAM watchdog thread (saves NVRAM every minute) |
1365 |
|
*/ |
1366 |
|
|
1367 |
< |
static status_t SheepShaver::nvram_func(void *arg) |
1367 |
> |
status_t SheepShaver::nvram_func(void *arg) |
1368 |
|
{ |
1369 |
|
SheepShaver *obj = (SheepShaver *)arg; |
1370 |
|
|
1603 |
|
if (InterruptFlags & INTFLAG_VIA) { |
1604 |
|
ClearInterruptFlag(INTFLAG_VIA); |
1605 |
|
ADBInterrupt(); |
1606 |
< |
ExecutePPC(VideoVBL); |
1606 |
> |
ExecuteNative(NATIVE_VIDEO_VBL); |
1607 |
|
} |
1608 |
|
} |
1609 |
|
#endif |
2098 |
|
} |
2099 |
|
|
2100 |
|
|
2101 |
+ |
/* |
2102 |
+ |
* Helpers to share 32-bit addressable data with MacOS |
2103 |
+ |
*/ |
2104 |
+ |
|
2105 |
+ |
bool SheepMem::Init(void) |
2106 |
+ |
{ |
2107 |
+ |
// Delete old area |
2108 |
+ |
area_id old_sheep_area = find_area(SHEEP_AREA_NAME); |
2109 |
+ |
if (old_sheep_area > 0) |
2110 |
+ |
delete_area(old_sheep_area); |
2111 |
+ |
|
2112 |
+ |
// Create area for SheepShaver data |
2113 |
+ |
proc = base = 0x60000000; |
2114 |
+ |
SheepMemArea = create_area(SHEEP_AREA_NAME, (void **)&base, B_BASE_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); |
2115 |
+ |
if (SheepMemArea < 0) |
2116 |
+ |
return false; |
2117 |
+ |
|
2118 |
+ |
// Create read-only area with all bits set to 0 |
2119 |
+ |
static const uint8 const_zero_page[4096] = {0,}; |
2120 |
+ |
zero_page = const_zero_page; |
2121 |
+ |
|
2122 |
+ |
D(bug("SheepShaver area %ld at %p\n", SheepMemArea, base)); |
2123 |
+ |
data = base + size; |
2124 |
+ |
return true; |
2125 |
+ |
} |
2126 |
+ |
|
2127 |
+ |
void SheepMem::Exit(void) |
2128 |
+ |
{ |
2129 |
+ |
if (SheepMemArea >= 0) |
2130 |
+ |
delete_area(SheepMemArea); |
2131 |
+ |
} |
2132 |
+ |
|
2133 |
+ |
|
2134 |
|
/* |
2135 |
|
* Display error alert |
2136 |
|
*/ |