ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Windows/main_windows.cpp
Revision: 1.8
Committed: 2005-03-17T23:48:50Z (19 years, 2 months ago) by gbeauche
Branch: MAIN
Changes since 1.7: +4 -2 lines
Log Message:
Always set RAM_BASE to 0x20000000 for now as there could be some weird
problems depending on the amount of memory requested. Also fix
initialization of the system dependent timers. Remove unixism.

File Contents

# Content
1 /*
2 * main_windows.cpp - Emulation core, Windows implementation
3 *
4 * SheepShaver (C) 1997-2005 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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <SDL.h>
27
28 #include "sysdeps.h"
29 #include "main.h"
30 #include "version.h"
31 #include "prefs.h"
32 #include "prefs_editor.h"
33 #include "cpu_emulation.h"
34 #include "emul_op.h"
35 #include "xlowmem.h"
36 #include "xpram.h"
37 #include "timer.h"
38 #include "adb.h"
39 #include "video.h"
40 #include "sys.h"
41 #include "macos_util.h"
42 #include "rom_patches.h"
43 #include "user_strings.h"
44 #include "vm_alloc.h"
45 #include "sigsegv.h"
46 #include "util_windows.h"
47
48 #define DEBUG 0
49 #include "debug.h"
50
51 #ifdef ENABLE_MON
52 #include "mon.h"
53 #endif
54
55
56 // Constants
57 const char ROM_FILE_NAME[] = "ROM";
58 const char ROM_FILE_NAME2[] = "Mac OS ROM";
59
60 const uintptr RAM_BASE = 0x20000000; // Base address of RAM
61 const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
62
63
64 // Global variables (exported)
65 uint32 RAMBase; // Base address of Mac RAM
66 uint32 RAMSize; // Size of Mac RAM
67 uint32 KernelDataAddr; // Address of Kernel Data
68 uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
69 uint32 DRCacheAddr; // Address of DR Cache
70 uint32 PVR; // Theoretical PVR
71 int64 CPUClockSpeed; // Processor clock speed (Hz)
72 int64 BusClockSpeed; // Bus clock speed (Hz)
73 int64 TimebaseSpeed; // Timebase clock speed (Hz)
74 uint8 *RAMBaseHost; // Base address of Mac RAM (host address space)
75 uint8 *ROMBaseHost; // Base address of Mac ROM (host address space)
76
77
78 // Global variables
79 static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
80 static int kernel_area = -1; // SHM ID of Kernel Data area
81 static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped
82 static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped
83 static bool dr_cache_area_mapped = false; // Flag: Mac DR Cache mmap()ped
84 static bool dr_emulator_area_mapped = false;// Flag: Mac DR Emulator mmap()ped
85 static KernelData *kernel_data; // Pointer to Kernel Data
86 static EmulatorData *emulator_data;
87
88 static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
89 static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed
90 static volatile bool nvram_thread_cancel; // Flag: Cancel NVRAM thread
91 static HANDLE nvram_thread = NULL; // NVRAM watchdog
92 static bool tick_thread_active = false; // Flag: MacOS thread installed
93 static volatile bool tick_thread_cancel; // Flag: Cancel 60Hz thread
94 static HANDLE tick_thread = NULL; // 60Hz thread
95 static HANDLE emul_thread = NULL; // MacOS thread
96 static uintptr sig_stack = 0; // Stack for PowerPC interrupt routine
97
98 uint32 SheepMem::page_size; // Size of a native page
99 uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros
100 uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data
101 uintptr SheepMem::proc; // Bottom address of SheepShave procedures
102 uintptr SheepMem::data; // Top of SheepShaver data (stack like storage)
103
104
105 // Prototypes
106 static bool kernel_data_init(void);
107 static void kernel_data_exit(void);
108 static void Quit(void);
109 static DWORD WINAPI nvram_func(void *arg);
110 static DWORD WINAPI tick_func(void *arg);
111
112 static void jump_to_rom(uint32 entry);
113 extern void emul_ppc(uint32 start);
114 extern void init_emul_ppc(void);
115 extern void exit_emul_ppc(void);
116 sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
117
118
119 /*
120 * Return signal stack base
121 */
122
123 uintptr SignalStackBase(void)
124 {
125 return sig_stack + SIG_STACK_SIZE;
126 }
127
128
129 /*
130 * Memory management helpers
131 */
132
133 static inline int vm_mac_acquire(uint32 addr, uint32 size)
134 {
135 return vm_acquire_fixed(Mac2HostAddr(addr), size);
136 }
137
138 static inline int vm_mac_release(uint32 addr, uint32 size)
139 {
140 return vm_release(Mac2HostAddr(addr), size);
141 }
142
143
144 /*
145 * Main program
146 */
147
148 static void usage(const char *prg_name)
149 {
150 printf("Usage: %s [OPTION...]\n", prg_name);
151 printf("\nUnix options:\n");
152 printf(" --display STRING\n X display to use\n");
153 PrefsPrintUsage();
154 exit(0);
155 }
156
157 int main(int argc, char **argv)
158 {
159 char str[256];
160 int16 i16;
161 HANDLE rom_fh;
162 const char *rom_path;
163 uint32 rom_size;
164 DWORD actual;
165 uint8 *rom_tmp;
166
167 // Initialize variables
168 RAMBase = 0;
169
170 // Print some info
171 printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
172 printf(" %s\n", GetString(STR_ABOUT_TEXT2));
173
174 // Read preferences
175 PrefsInit(argc, argv);
176
177 // Parse command line arguments
178 for (int i=1; i<argc; i++) {
179 if (strcmp(argv[i], "--help") == 0) {
180 usage(argv[0]);
181 } else if (argv[i][0] == '-') {
182 fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
183 usage(argv[0]);
184 }
185 }
186
187 // Initialize SDL system
188 int sdl_flags = 0;
189 #ifdef USE_SDL_VIDEO
190 sdl_flags |= SDL_INIT_VIDEO;
191 #endif
192 #ifdef USE_SDL_AUDIO
193 sdl_flags |= SDL_INIT_AUDIO;
194 #endif
195 assert(sdl_flags != 0);
196 if (SDL_Init(sdl_flags) == -1) {
197 char str[256];
198 sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError());
199 ErrorAlert(str);
200 goto quit;
201 }
202 atexit(SDL_Quit);
203
204 #ifdef ENABLE_MON
205 // Initialize mon
206 mon_init();
207 #endif
208
209 // Install SIGSEGV handler for CPU emulator
210 if (!sigsegv_install_handler(sigsegv_handler)) {
211 sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
212 ErrorAlert(str);
213 goto quit;
214 }
215
216 // Initialize VM system
217 vm_init();
218
219 // Get system info
220 PVR = 0x00040000; // Default: 604
221 CPUClockSpeed = 100000000; // Default: 100MHz
222 BusClockSpeed = 100000000; // Default: 100MHz
223 TimebaseSpeed = 25000000; // Default: 25MHz
224 PVR = 0x000c0000; // Default: 7400 (with AltiVec)
225 D(bug("PVR: %08x (assumed)\n", PVR));
226
227 // Init system routines
228 SysInit();
229
230 // Show preferences editor
231 if (!PrefsFindBool("nogui"))
232 if (!PrefsEditor())
233 goto quit;
234
235 // Create Low Memory area (0x0000..0x3000)
236 if (vm_mac_acquire(0, 0x3000) < 0) {
237 sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
238 ErrorAlert(str);
239 goto quit;
240 }
241 lm_area_mapped = true;
242
243 // Create areas for Kernel Data
244 if (!kernel_data_init())
245 goto quit;
246 kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE);
247 emulator_data = &kernel_data->ed;
248 KernelDataAddr = KERNEL_DATA_BASE;
249 D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE));
250 D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed)));
251
252 // Create area for DR Cache
253 if (vm_mac_acquire(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) {
254 sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno));
255 ErrorAlert(str);
256 goto quit;
257 }
258 dr_emulator_area_mapped = true;
259 if (vm_mac_acquire(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) {
260 sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno));
261 ErrorAlert(str);
262 goto quit;
263 }
264 dr_cache_area_mapped = true;
265 DRCacheAddr = (uint32)Mac2HostAddr(DR_CACHE_BASE);
266 D(bug("DR Cache at %p (%08x)\n", DRCacheAddr, DR_CACHE_BASE));
267
268 // Create area for SheepShaver data
269 if (!SheepMem::Init()) {
270 sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
271 ErrorAlert(str);
272 goto quit;
273 }
274
275 // Create area for Mac ROM
276 if (vm_mac_acquire(ROM_BASE, ROM_AREA_SIZE) < 0) {
277 sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
278 ErrorAlert(str);
279 goto quit;
280 }
281 ROMBaseHost = Mac2HostAddr(ROM_BASE);
282 rom_area_mapped = true;
283 D(bug("ROM area at %p (%08x)\n", ROMBaseHost, ROM_BASE));
284
285 // Create area for Mac RAM
286 RAMSize = PrefsFindInt32("ramsize");
287 if (RAMSize < 8*1024*1024) {
288 WarningAlert(GetString(STR_SMALL_RAM_WARN));
289 RAMSize = 8*1024*1024;
290 }
291
292 if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) {
293 sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
294 ErrorAlert(str);
295 goto quit;
296 }
297 RAMBaseHost = Mac2HostAddr(RAM_BASE);
298 RAMBase = RAM_BASE;
299 ram_area_mapped = true;
300 D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase));
301
302 if (RAMBase > ROM_BASE) {
303 ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR));
304 goto quit;
305 }
306
307 // Load Mac ROM
308 rom_path = PrefsFindString("rom");
309 rom_fh = CreateFile(rom_path ? rom_path : ROM_FILE_NAME,
310 GENERIC_READ, 0, NULL, OPEN_EXISTING,
311 FILE_ATTRIBUTE_NORMAL, NULL);
312
313 if (rom_fh == INVALID_HANDLE_VALUE) {
314 rom_fh = CreateFile(rom_path ? rom_path : ROM_FILE_NAME2,
315 GENERIC_READ, 0, NULL, OPEN_EXISTING,
316 FILE_ATTRIBUTE_NORMAL, NULL);
317
318 if (rom_fh == INVALID_HANDLE_VALUE) {
319 ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
320 goto quit;
321 }
322 }
323 printf(GetString(STR_READING_ROM_FILE));
324 rom_size = GetFileSize(rom_fh, NULL);
325 rom_tmp = new uint8[ROM_SIZE];
326 ReadFile(rom_fh, (void *)rom_tmp, ROM_SIZE, &actual, NULL);
327 CloseHandle(rom_fh);
328
329 // Decode Mac ROM
330 if (!DecodeROM(rom_tmp, actual)) {
331 if (rom_size != 4*1024*1024) {
332 ErrorAlert(GetString(STR_ROM_SIZE_ERR));
333 goto quit;
334 } else {
335 ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
336 goto quit;
337 }
338 }
339 delete[] rom_tmp;
340
341 // Initialize native timers
342 timer_init();
343
344 // Initialize everything
345 if (!InitAll())
346 goto quit;
347 D(bug("Initialization complete\n"));
348
349 // Write protect ROM
350 vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ);
351
352 // Start 60Hz thread
353 tick_thread_cancel = false;
354 tick_thread_active = ((tick_thread = create_thread(tick_func)) != NULL);
355 SetThreadPriority(tick_thread, THREAD_PRIORITY_ABOVE_NORMAL);
356 D(bug("Tick thread installed (%ld)\n", tick_thread));
357
358 // Start NVRAM watchdog thread
359 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
360 nvram_thread_cancel = false;
361 nvram_thread_active = ((nvram_thread = create_thread(nvram_func, NULL)) != NULL);
362 SetThreadPriority(nvram_thread, THREAD_PRIORITY_BELOW_NORMAL);
363 D(bug("NVRAM thread installed (%ld)\n", nvram_thread));
364
365 // Get my thread ID and jump to ROM boot routine
366 emul_thread = GetCurrentThread();
367 D(bug("Jumping to ROM\n"));
368 jump_to_rom(ROM_BASE + 0x310000);
369 D(bug("Returned from ROM\n"));
370
371 quit:
372 Quit();
373 return 0;
374 }
375
376
377 /*
378 * Cleanup and quit
379 */
380
381 static void Quit(void)
382 {
383 // Exit PowerPC emulation
384 exit_emul_ppc();
385
386 // Stop 60Hz thread
387 if (tick_thread_active) {
388 tick_thread_cancel = true;
389 wait_thread(tick_thread);
390 }
391
392 // Stop NVRAM watchdog thread
393 if (nvram_thread_active) {
394 nvram_thread_cancel = true;
395 wait_thread(nvram_thread);
396 }
397
398 // Deinitialize everything
399 ExitAll();
400
401 // Delete SheepShaver globals
402 SheepMem::Exit();
403
404 // Delete RAM area
405 if (ram_area_mapped)
406 vm_mac_release(RAM_BASE, RAMSize);
407
408 // Delete ROM area
409 if (rom_area_mapped)
410 vm_mac_release(ROM_BASE, ROM_AREA_SIZE);
411
412 // Delete DR cache areas
413 if (dr_emulator_area_mapped)
414 vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
415 if (dr_cache_area_mapped)
416 vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE);
417
418 // Delete Kernel Data area
419 kernel_data_exit();
420
421 // Delete Low Memory area
422 if (lm_area_mapped)
423 vm_mac_release(0, 0x3000);
424
425 // Exit system routines
426 SysExit();
427
428 // Exit preferences
429 PrefsExit();
430
431 #ifdef ENABLE_MON
432 // Exit mon
433 mon_exit();
434 #endif
435
436 exit(0);
437 }
438
439
440 /*
441 * Initialize Kernel Data segments
442 */
443
444 static HANDLE kernel_handle; // Shared memory handle for Kernel Data
445 static DWORD allocation_granule; // Minimum size of allocateable are (64K)
446 static DWORD kernel_area_size; // Size of Kernel Data area
447
448 static bool kernel_data_init(void)
449 {
450 char str[256];
451 SYSTEM_INFO si;
452 GetSystemInfo(&si);
453 allocation_granule = si.dwAllocationGranularity;
454 kernel_area_size = (KERNEL_AREA_SIZE + allocation_granule - 1) & -allocation_granule;
455
456 char rcs[10];
457 LPVOID kernel_addr;
458 kernel_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, kernel_area_size, NULL);
459 if (kernel_handle == NULL) {
460 sprintf(rcs, "%d", GetLastError());
461 sprintf(str, GetString(STR_KD_SHMGET_ERR), rcs);
462 ErrorAlert(str);
463 return false;
464 }
465 kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule);
466 if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) {
467 sprintf(rcs, "%d", GetLastError());
468 sprintf(str, GetString(STR_KD_SHMAT_ERR), rcs);
469 ErrorAlert(str);
470 return false;
471 }
472 kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule);
473 if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) {
474 sprintf(rcs, "%d", GetLastError());
475 sprintf(str, GetString(STR_KD2_SHMAT_ERR), rcs);
476 ErrorAlert(str);
477 return false;
478 }
479 return true;
480 }
481
482
483 /*
484 * Deallocate Kernel Data segments
485 */
486
487 static void kernel_data_exit(void)
488 {
489 if (kernel_handle) {
490 UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule));
491 UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule));
492 CloseHandle(kernel_handle);
493 }
494 }
495
496
497 /*
498 * Jump into Mac ROM, start 680x0 emulator
499 */
500
501 void jump_to_rom(uint32 entry)
502 {
503 init_emul_ppc();
504 emul_ppc(entry);
505 }
506
507
508 /*
509 * Quit emulator (cause return from jump_to_rom)
510 */
511
512 void QuitEmulator(void)
513 {
514 Quit();
515 }
516
517
518 /*
519 * Pause/resume emulator
520 */
521
522 void PauseEmulator(void)
523 {
524 SuspendThread(emul_thread);
525 }
526
527 void ResumeEmulator(void)
528 {
529 ResumeThread(emul_thread);
530 }
531
532
533 /*
534 * Dump 68k registers
535 */
536
537 void Dump68kRegs(M68kRegisters *r)
538 {
539 // Display 68k registers
540 for (int i=0; i<8; i++) {
541 printf("d%d: %08x", i, r->d[i]);
542 if (i == 3 || i == 7)
543 printf("\n");
544 else
545 printf(", ");
546 }
547 for (int i=0; i<8; i++) {
548 printf("a%d: %08x", i, r->a[i]);
549 if (i == 3 || i == 7)
550 printf("\n");
551 else
552 printf(", ");
553 }
554 }
555
556
557 /*
558 * Make code executable
559 */
560
561 void MakeExecutable(int dummy, uint32 start, uint32 length)
562 {
563 if ((start >= ROM_BASE) && (start < (ROM_BASE + ROM_SIZE)))
564 return;
565 FlushCodeCache(start, start + length);
566 }
567
568
569 /*
570 * NVRAM watchdog thread (saves NVRAM every minute)
571 */
572
573 static void nvram_watchdog(void)
574 {
575 if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
576 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
577 SaveXPRAM();
578 }
579 }
580
581 static DWORD nvram_func(void *arg)
582 {
583 while (!nvram_thread_cancel) {
584 for (int i=0; i<60 && !nvram_thread_cancel; i++)
585 Delay_usec(999999); // Only wait 1 second so we quit promptly when nvram_thread_cancel becomes true
586 nvram_watchdog();
587 }
588 return 0;
589 }
590
591
592 /*
593 * 60Hz thread (really 60.15Hz)
594 */
595
596 static DWORD tick_func(void *arg)
597 {
598 int tick_counter = 0;
599 uint64 start = GetTicks_usec();
600 int64 ticks = 0;
601 uint64 next = GetTicks_usec();
602
603 while (!tick_thread_cancel) {
604
605 // Wait
606 next += 16625;
607 int64 delay = next - GetTicks_usec();
608 if (delay > 0)
609 Delay_usec(delay);
610 else if (delay < -16625)
611 next = GetTicks_usec();
612 ticks++;
613
614 // Pseudo Mac 1Hz interrupt, update local time
615 if (++tick_counter > 60) {
616 tick_counter = 0;
617 WriteMacInt32(0x20c, TimerDateTime());
618 }
619
620 // Trigger 60Hz interrupt
621 if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
622 SetInterruptFlag(INTFLAG_VIA);
623 TriggerInterrupt();
624 }
625 }
626
627 uint64 end = GetTicks_usec();
628 D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
629 return 0;
630 }
631
632
633 /*
634 * Mutexes
635 */
636
637 struct B2_mutex {
638 mutex_t m;
639 };
640
641 B2_mutex *B2_create_mutex(void)
642 {
643 return new B2_mutex;
644 }
645
646 void B2_lock_mutex(B2_mutex *mutex)
647 {
648 mutex->m.lock();
649 }
650
651 void B2_unlock_mutex(B2_mutex *mutex)
652 {
653 mutex->m.unlock();
654 }
655
656 void B2_delete_mutex(B2_mutex *mutex)
657 {
658 delete mutex;
659 }
660
661
662 /*
663 * Interrupt flags (must be handled atomically!)
664 */
665
666 volatile uint32 InterruptFlags = 0;
667 static mutex_t intflags_mutex;
668
669 void SetInterruptFlag(uint32 flag)
670 {
671 intflags_mutex.lock();
672 InterruptFlags |= flag;
673 intflags_mutex.unlock();
674 }
675
676 void ClearInterruptFlag(uint32 flag)
677 {
678 intflags_mutex.lock();
679 InterruptFlags &= ~flag;
680 intflags_mutex.unlock();
681 }
682
683
684 /*
685 * Disable interrupts
686 */
687
688 void DisableInterrupt(void)
689 {
690 WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) + 1);
691 }
692
693
694 /*
695 * Enable interrupts
696 */
697
698 void EnableInterrupt(void)
699 {
700 WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) - 1);
701 }
702
703
704 /*
705 * Helpers to share 32-bit addressable data with MacOS
706 */
707
708 bool SheepMem::Init(void)
709 {
710 // Size of a native page
711 page_size = vm_get_page_size();
712
713 // Allocate SheepShaver globals
714 proc = base;
715 if (vm_mac_acquire(base, size) < 0)
716 return false;
717
718 // Allocate page with all bits set to 0, right in the middle
719 // This is also used to catch undesired overlaps between proc and data areas
720 zero_page = proc + (size / 2);
721 Mac_memset(zero_page, 0, page_size);
722 if (vm_protect(Mac2HostAddr(zero_page), page_size, VM_PAGE_READ) < 0)
723 return false;
724
725 // Allocate alternate stack for PowerPC interrupt routine
726 sig_stack = base + size;
727 if (vm_mac_acquire(sig_stack, SIG_STACK_SIZE) < 0)
728 return false;
729
730 data = base + size;
731 return true;
732 }
733
734 void SheepMem::Exit(void)
735 {
736 if (data) {
737 // Delete SheepShaver globals
738 vm_mac_release(base, size);
739
740 // Delete alternate stack for PowerPC interrupt routine
741 vm_mac_release(sig_stack, SIG_STACK_SIZE);
742 }
743 }
744
745
746 /*
747 * Get the main window handle
748 */
749
750 #ifdef USE_SDL_VIDEO
751 #include <SDL_syswm.h>
752 static HWND GetMainWindowHandle(void)
753 {
754 SDL_SysWMinfo wmInfo;
755 wmInfo.version.major = SDL_MAJOR_VERSION;
756 wmInfo.version.minor = SDL_MINOR_VERSION;
757 wmInfo.version.patch = SDL_PATCHLEVEL;
758 return SDL_GetWMInfo(&wmInfo) ? wmInfo.window : NULL;
759 }
760 #endif
761
762
763 /*
764 * Display alert
765 */
766
767 static void display_alert(int title_id, const char *text, int flags)
768 {
769 HWND hMainWnd = GetMainWindowHandle();
770 MessageBox(hMainWnd, text, GetString(title_id), MB_OK | flags);
771 }
772
773
774 /*
775 * Display error alert
776 */
777
778 void ErrorAlert(const char *text)
779 {
780 if (PrefsFindBool("nogui"))
781 return;
782
783 VideoQuitFullScreen();
784 display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP);
785 }
786
787
788 /*
789 * Display warning alert
790 */
791
792 void WarningAlert(const char *text)
793 {
794 if (PrefsFindBool("nogui"))
795 return;
796
797 display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONINFORMATION);
798 }
799
800
801 /*
802 * Display choice alert
803 */
804
805 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
806 {
807 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
808 return false; //!!
809 }