ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/main_macosx.mm
Revision: 1.7
Committed: 2003-03-26T00:26:38Z (21 years, 2 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-13
Changes since 1.6: +2 -2 lines
Log Message:
Repair QuitEmulator replacement macro.
(we was incorrectly returning after the call to InitAll() )

File Contents

# Content
1 /*
2 * $Id: main_macosx.mm,v 1.6 2003/03/25 01:44:16 nigel Exp $
3 *
4 * main_macosx.mm - Startup code for MacOS X
5 * Based (in a small way) on the default main.m,
6 and on Basilisk's main_unix.cpp
7 *
8 * Basilisk II (C) 1997-2002 Christian Bauer
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 #define PTHREADS
25 #include "sysdeps.h"
26
27 #ifdef HAVE_PTHREADS
28 # include <pthread.h>
29 #endif
30
31 #if REAL_ADDRESSING || DIRECT_ADDRESSING
32 # include <sys/mman.h>
33 #endif
34
35 #include "cpu_emulation.h"
36 #include "macos_util_macosx.h"
37 #include "main.h"
38 #include "prefs.h"
39 #include "prefs_editor.h"
40 #include "rom_patches.h"
41 #include "sys.h"
42 #include "timer.h"
43 #include "user_strings.h"
44 #include "version.h"
45 #include "video.h"
46 #include "vm_alloc.h"
47 #include "xpram.h"
48
49 #ifdef ENABLE_MON
50 # include "mon.h"
51 #endif
52
53 #define DEBUG 0
54 #include "debug.h"
55
56
57 #import <AppKit/AppKit.h>
58
59 #include "main_macosx.h" // To bridge between main() and misc. classes
60
61
62 // Constants
63 const char ROM_FILE_NAME[] = "ROM";
64 const int SIG_STACK_SIZE = SIGSTKSZ; // Size of signal stack
65 const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area
66
67
68 // CPU and FPU type, addressing mode
69 int CPUType;
70 bool CPUIs68060;
71 int FPUType;
72 bool TwentyFourBitAddressing;
73
74
75 // Global variables
76
77 #ifdef HAVE_PTHREADS
78
79 static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags
80 #define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock)
81 #define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock)
82
83 #else
84
85 #define LOCK_INTFLAGS
86 #define UNLOCK_INTFLAGS
87
88 #endif
89
90 #if USE_SCRATCHMEM_SUBTERFUGE
91 uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes
92 #endif
93
94 #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
95 #define SIG_TIMER SIGRTMIN
96 static timer_t timer; // 60Hz timer
97 #endif
98
99 #ifdef ENABLE_MON
100 static struct sigaction sigint_sa; // sigaction for SIGINT handler
101 static void sigint_handler(...);
102 #endif
103
104 #if REAL_ADDRESSING
105 static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
106 #endif
107
108
109
110 /*
111 * Main program
112 */
113
114 static void usage(const char *prg_name)
115 {
116 printf("Usage: %s [OPTION...]\n", prg_name);
117 printf("\nUnix options:\n");
118 printf(" --help\n display this usage message\n");
119 printf(" --break ADDRESS\n set ROM breakpoint\n");
120 printf(" --rominfo\n dump ROM information\n");
121 PrefsPrintUsage();
122 exit(0);
123 }
124
125 int main(int argc, char **argv)
126 {
127 // Initialize variables
128 RAMBaseHost = NULL;
129 ROMBaseHost = NULL;
130 srand(time(NULL));
131 tzset();
132
133 // Print some info
134 printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
135 printf(" %s\n", GetString(STR_ABOUT_TEXT2));
136
137 // Read preferences
138 PrefsInit(argc, argv);
139
140 // Parse command line arguments
141 for (int i=1; i<argc; i++) {
142 if (strcmp(argv[i], "--help") == 0) {
143 usage(argv[0]);
144 } else if (strncmp(argv[i], "-psn_", 5) == 0) {// OS X process identifier
145 i++;
146 } else if (strcmp(argv[i], "--break") == 0) {
147 i++;
148 if (i < argc)
149 ROMBreakpoint = strtol(argv[i], NULL, 0);
150 } else if (strcmp(argv[i], "--rominfo") == 0) {
151 PrintROMInfo = true;
152 } else if (argv[i][0] == '-') {
153 fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
154 usage(argv[0]);
155 }
156 }
157
158 // Init system routines
159 SysInit();
160
161 // Open display, attach to window server,
162 // load pre-instantiated classes from MainMenu.nib, start run loop
163 int i = NSApplicationMain(argc, (const char **)argv);
164 // We currently never get past here, because QuitEmulator() does an exit()
165
166 // Exit system routines
167 SysExit();
168
169 // Exit preferences
170 PrefsExit();
171
172 return i;
173 }
174
175 #define QuitEmulator() { QuitEmuNoExit() ; return NO; }
176
177 bool InitEmulator (void)
178 {
179 char str[256];
180
181
182 // Read RAM size
183 RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
184 if (RAMSize < 1024*1024) {
185 WarningAlert(GetString(STR_SMALL_RAM_WARN));
186 RAMSize = 1024*1024;
187 }
188
189 #if REAL_ADDRESSING || DIRECT_ADDRESSING
190 RAMSize = RAMSize & -getpagesize(); // Round down to page boundary
191 #endif
192
193 // Initialize VM system
194 vm_init();
195
196 #if REAL_ADDRESSING
197 // Flag: RAM and ROM are contigously allocated from address 0
198 bool memory_mapped_from_zero = false;
199
200 // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
201 // when trying to map a too big chunk of memory starting at address 0
202 #if defined(OS_solaris) || defined(OS_netbsd)
203 const bool can_map_all_memory = false;
204 #else
205 const bool can_map_all_memory = true;
206 #endif
207
208 // Try to allocate all memory from 0x0000, if it is not known to crash
209 if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
210 D(bug("Could allocate RAM and ROM from 0x0000\n"));
211 memory_mapped_from_zero = true;
212 }
213
214 // Otherwise, just create the Low Memory area (0x0000..0x2000)
215 else if (vm_acquire_fixed(0, 0x2000) == 0) {
216 D(bug("Could allocate the Low Memory globals\n"));
217 lm_area_mapped = true;
218 }
219
220 // Exit on failure
221 else {
222 sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
223 ErrorAlert(str);
224 QuitEmulator();
225 }
226 #else
227 *str = 0; // Eliminate unused variable warning
228 #endif
229
230 // Create areas for Mac RAM and ROM
231 #if REAL_ADDRESSING
232 if (memory_mapped_from_zero) {
233 RAMBaseHost = (uint8 *)0;
234 ROMBaseHost = RAMBaseHost + RAMSize;
235 }
236 else
237 #endif
238 {
239 RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
240 ROMBaseHost = (uint8 *)vm_acquire(0x100000);
241 if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
242 ErrorAlert(STR_NO_MEM_ERR);
243 QuitEmulator();
244 }
245 }
246
247 #if USE_SCRATCHMEM_SUBTERFUGE
248 // Allocate scratch memory
249 ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
250 if (ScratchMem == VM_MAP_FAILED) {
251 ErrorAlert(STR_NO_MEM_ERR);
252 QuitEmulator();
253 }
254 ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block
255 #endif
256
257 #if DIRECT_ADDRESSING
258 // RAMBaseMac shall always be zero
259 MEMBaseDiff = (uintptr)RAMBaseHost;
260 RAMBaseMac = 0;
261 ROMBaseMac = Host2MacAddr(ROMBaseHost);
262 #endif
263 #if REAL_ADDRESSING
264 RAMBaseMac = (uint32)RAMBaseHost;
265 ROMBaseMac = (uint32)ROMBaseHost;
266 #endif
267 D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
268 D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
269
270 // Get rom file path from preferences
271 const char *rom_path = PrefsFindString("rom");
272 if ( ! rom_path )
273 WarningAlert("No rom pathname set. Trying ./ROM");
274
275 // Load Mac ROM
276 int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
277 if (rom_fd < 0) {
278 ErrorAlert(STR_NO_ROM_FILE_ERR);
279 QuitEmulator();
280 }
281 printf(GetString(STR_READING_ROM_FILE));
282 ROMSize = lseek(rom_fd, 0, SEEK_END);
283 if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
284 ErrorAlert(STR_ROM_SIZE_ERR);
285 close(rom_fd);
286 QuitEmulator();
287 }
288 lseek(rom_fd, 0, SEEK_SET);
289 if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
290 ErrorAlert(STR_ROM_FILE_READ_ERR);
291 close(rom_fd);
292 QuitEmulator();
293 }
294
295
296 // Initialize everything
297 if (!InitAll())
298 QuitEmulator();
299 D(bug("Initialization complete\n"));
300
301
302 #ifdef ENABLE_MON
303 // Setup SIGINT handler to enter mon
304 sigemptyset(&sigint_sa.sa_mask);
305 sigint_sa.sa_handler = (void (*)(int))sigint_handler;
306 sigint_sa.sa_flags = 0;
307 sigaction(SIGINT, &sigint_sa, NULL);
308 #endif
309
310
311 return YES;
312 }
313
314 #undef QuitEmulator()
315
316
317 /*
318 * Quit emulator
319 */
320
321 void QuitEmuNoExit()
322 {
323 D(bug("QuitEmulator\n"));
324
325 // Exit 680x0 emulation
326 Exit680x0();
327
328 // Deinitialize everything
329 ExitAll();
330
331 // Free ROM/RAM areas
332 if (RAMBaseHost != VM_MAP_FAILED) {
333 vm_release(RAMBaseHost, RAMSize);
334 RAMBaseHost = NULL;
335 }
336 if (ROMBaseHost != VM_MAP_FAILED) {
337 vm_release(ROMBaseHost, 0x100000);
338 ROMBaseHost = NULL;
339 }
340
341 #if USE_SCRATCHMEM_SUBTERFUGE
342 // Delete scratch memory area
343 if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
344 vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
345 ScratchMem = NULL;
346 }
347 #endif
348
349 #if REAL_ADDRESSING
350 // Delete Low Memory area
351 if (lm_area_mapped)
352 vm_release(0, 0x2000);
353 #endif
354
355 // Exit VM wrappers
356 vm_exit();
357
358 // Exit system routines
359 SysExit();
360
361 // Exit preferences
362 PrefsExit();
363 }
364
365 void QuitEmulator(void)
366 {
367 extern NSApplication *NSApp;
368
369
370 QuitEmuNoExit();
371
372 // Stop run loop?
373 [NSApp terminate: nil];
374
375 exit(0);
376 }
377
378
379 /*
380 * Code was patched, flush caches if neccessary (i.e. when using a real 680x0
381 * or a dynamically recompiling emulator)
382 */
383
384 void FlushCodeCache(void *start, uint32 size)
385 {
386 }
387
388
389 /*
390 * SIGINT handler, enters mon
391 */
392
393 #ifdef ENABLE_MON
394 static void sigint_handler(...)
395 {
396 uaecptr nextpc;
397 extern void m68k_dumpstate(uaecptr *nextpc);
398 m68k_dumpstate(&nextpc);
399 VideoQuitFullScreen();
400 char *arg[4] = {"mon", "-m", "-r", NULL};
401 mon(3, arg);
402 QuitEmulator();
403 }
404 #endif
405
406
407 /*
408 * Mutexes
409 */
410
411 #ifdef HAVE_PTHREADS
412
413 struct B2_mutex {
414 B2_mutex() { pthread_mutex_init(&m, NULL); }
415 ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); }
416 pthread_mutex_t m;
417 };
418
419 B2_mutex *B2_create_mutex(void)
420 {
421 return new B2_mutex;
422 }
423
424 void B2_lock_mutex(B2_mutex *mutex)
425 {
426 pthread_mutex_lock(&mutex->m);
427 }
428
429 void B2_unlock_mutex(B2_mutex *mutex)
430 {
431 pthread_mutex_unlock(&mutex->m);
432 }
433
434 void B2_delete_mutex(B2_mutex *mutex)
435 {
436 delete mutex;
437 }
438
439 #else
440
441 struct B2_mutex {
442 int dummy;
443 };
444
445 B2_mutex *B2_create_mutex(void)
446 {
447 return new B2_mutex;
448 }
449
450 void B2_lock_mutex(B2_mutex *mutex)
451 {
452 }
453
454 void B2_unlock_mutex(B2_mutex *mutex)
455 {
456 }
457
458 void B2_delete_mutex(B2_mutex *mutex)
459 {
460 delete mutex;
461 }
462
463 #endif
464
465
466 /*
467 * Interrupt flags (must be handled atomically!)
468 */
469
470 uint32 InterruptFlags = 0;
471
472 void SetInterruptFlag(uint32 flag)
473 {
474 LOCK_INTFLAGS;
475 InterruptFlags |= flag;
476 UNLOCK_INTFLAGS;
477 }
478
479 void ClearInterruptFlag(uint32 flag)
480 {
481 LOCK_INTFLAGS;
482 InterruptFlags &= ~flag;
483 UNLOCK_INTFLAGS;
484 }
485
486
487 /*
488 * Display error alert
489 */
490
491 void ErrorAlert(const char *text)
492 {
493 NSString *title = [NSString stringWithCString:
494 GetString(STR_ERROR_ALERT_TITLE) ];
495 NSString *error = [NSString stringWithCString: text];
496 NSString *button = [NSString stringWithCString: GetString(STR_QUIT_BUTTON) ];
497
498 // If we have a full screen mode, quit it here?
499
500 NSLog(error);
501 NSRunCriticalAlertPanel(title, error, button, nil, nil);
502 }
503
504
505 /*
506 * Display warning alert
507 */
508
509 void WarningAlert(const char *text)
510 {
511 NSString *title = [NSString stringWithCString:
512 GetString(STR_WARNING_ALERT_TITLE) ];
513 NSString *warning = [NSString stringWithCString: text];
514 NSString *button = [NSString stringWithCString: GetString(STR_OK_BUTTON) ];
515
516 NSLog(warning);
517 NSRunAlertPanel(title, warning, button, nil, nil);
518 }
519
520
521 /*
522 * Display choice alert
523 */
524
525 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
526 {
527 NSString *title = [NSString stringWithCString:
528 GetString(STR_WARNING_ALERT_TITLE) ];
529 NSString *warning = [NSString stringWithCString: text];
530 NSString *yes = [NSString stringWithCString: pos];
531 NSString *no = [NSString stringWithCString: neg];
532
533 NSLog(warning);
534 return NSRunInformationalAlertPanel(title, warning, yes, no, nil);
535 }