ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/main_macosx.mm
Revision: 1.4
Committed: 2002-10-31T08:54:21Z (21 years, 7 months ago) by nigel
Branch: MAIN
Changes since 1.3: +3 -1 lines
Log Message:
Eliminate compile warning

File Contents

# Content
1 /*
2 * $Id: main_macosx.mm,v 1.3 2002/10/29 14:27:00 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
273 // Load Mac ROM
274 int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
275 if (rom_fd < 0) {
276 ErrorAlert(STR_NO_ROM_FILE_ERR);
277 QuitEmulator();
278 }
279 printf(GetString(STR_READING_ROM_FILE));
280 ROMSize = lseek(rom_fd, 0, SEEK_END);
281 if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
282 ErrorAlert(STR_ROM_SIZE_ERR);
283 close(rom_fd);
284 QuitEmulator();
285 }
286 lseek(rom_fd, 0, SEEK_SET);
287 if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
288 ErrorAlert(STR_ROM_FILE_READ_ERR);
289 close(rom_fd);
290 QuitEmulator();
291 }
292
293
294 // Initialize everything
295 if (!InitAll())
296 QuitEmulator();
297 D(bug("Initialization complete\n"));
298
299
300 #ifdef ENABLE_MON
301 // Setup SIGINT handler to enter mon
302 sigemptyset(&sigint_sa.sa_mask);
303 sigint_sa.sa_handler = (void (*)(int))sigint_handler;
304 sigint_sa.sa_flags = 0;
305 sigaction(SIGINT, &sigint_sa, NULL);
306 #endif
307
308
309 return YES;
310 }
311
312 #undef QuitEmulator()
313
314
315 /*
316 * Quit emulator
317 */
318
319 void QuitEmuNoExit()
320 {
321 extern NSApplication *NSApp;
322
323
324 D(bug("QuitEmulator\n"));
325
326 // Exit 680x0 emulation
327 Exit680x0();
328
329 // Deinitialize everything
330 ExitAll();
331
332 // Free ROM/RAM areas
333 if (RAMBaseHost != VM_MAP_FAILED) {
334 vm_release(RAMBaseHost, RAMSize);
335 RAMBaseHost = NULL;
336 }
337 if (ROMBaseHost != VM_MAP_FAILED) {
338 vm_release(ROMBaseHost, 0x100000);
339 ROMBaseHost = NULL;
340 }
341
342 #if USE_SCRATCHMEM_SUBTERFUGE
343 // Delete scratch memory area
344 if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
345 vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
346 ScratchMem = NULL;
347 }
348 #endif
349
350 #if REAL_ADDRESSING
351 // Delete Low Memory area
352 if (lm_area_mapped)
353 vm_release(0, 0x2000);
354 #endif
355
356 // Exit VM wrappers
357 vm_exit();
358
359 // Exit system routines
360 SysExit();
361
362 // Exit preferences
363 PrefsExit();
364
365 // Stop run loop
366 [NSApp terminate: nil];
367 }
368
369 void QuitEmulator(void)
370 {
371 QuitEmuNoExit();
372 exit(0);
373 }
374
375
376 /*
377 * Code was patched, flush caches if neccessary (i.e. when using a real 680x0
378 * or a dynamically recompiling emulator)
379 */
380
381 void FlushCodeCache(void *start, uint32 size)
382 {
383 }
384
385
386 /*
387 * SIGINT handler, enters mon
388 */
389
390 #ifdef ENABLE_MON
391 static void sigint_handler(...)
392 {
393 uaecptr nextpc;
394 extern void m68k_dumpstate(uaecptr *nextpc);
395 m68k_dumpstate(&nextpc);
396 VideoQuitFullScreen();
397 char *arg[4] = {"mon", "-m", "-r", NULL};
398 mon(3, arg);
399 QuitEmulator();
400 }
401 #endif
402
403
404 /*
405 * Mutexes
406 */
407
408 #ifdef HAVE_PTHREADS
409
410 struct B2_mutex {
411 B2_mutex() { pthread_mutex_init(&m, NULL); }
412 ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); }
413 pthread_mutex_t m;
414 };
415
416 B2_mutex *B2_create_mutex(void)
417 {
418 return new B2_mutex;
419 }
420
421 void B2_lock_mutex(B2_mutex *mutex)
422 {
423 pthread_mutex_lock(&mutex->m);
424 }
425
426 void B2_unlock_mutex(B2_mutex *mutex)
427 {
428 pthread_mutex_unlock(&mutex->m);
429 }
430
431 void B2_delete_mutex(B2_mutex *mutex)
432 {
433 delete mutex;
434 }
435
436 #else
437
438 struct B2_mutex {
439 int dummy;
440 };
441
442 B2_mutex *B2_create_mutex(void)
443 {
444 return new B2_mutex;
445 }
446
447 void B2_lock_mutex(B2_mutex *mutex)
448 {
449 }
450
451 void B2_unlock_mutex(B2_mutex *mutex)
452 {
453 }
454
455 void B2_delete_mutex(B2_mutex *mutex)
456 {
457 delete mutex;
458 }
459
460 #endif
461
462
463 /*
464 * Interrupt flags (must be handled atomically!)
465 */
466
467 uint32 InterruptFlags = 0;
468
469 void SetInterruptFlag(uint32 flag)
470 {
471 LOCK_INTFLAGS;
472 InterruptFlags |= flag;
473 UNLOCK_INTFLAGS;
474 }
475
476 void ClearInterruptFlag(uint32 flag)
477 {
478 LOCK_INTFLAGS;
479 InterruptFlags &= ~flag;
480 UNLOCK_INTFLAGS;
481 }
482
483
484 /*
485 * Display error alert
486 */
487
488 void ErrorAlert(const char *text)
489 {
490 NSString *title = [NSString stringWithCString:
491 GetString(STR_ERROR_ALERT_TITLE) ];
492 NSString *error = [NSString stringWithCString: text];
493 NSString *button = [NSString stringWithCString: GetString(STR_QUIT_BUTTON) ];
494
495 // If we have a full screen mode, quit it here?
496
497 NSLog(error);
498 NSRunCriticalAlertPanel(title, error, button, nil, nil);
499 }
500
501
502 /*
503 * Display warning alert
504 */
505
506 void WarningAlert(const char *text)
507 {
508 NSString *title = [NSString stringWithCString:
509 GetString(STR_WARNING_ALERT_TITLE) ];
510 NSString *warning = [NSString stringWithCString: text];
511 NSString *button = [NSString stringWithCString: GetString(STR_OK_BUTTON) ];
512
513 NSLog(warning);
514 NSRunAlertPanel(title, warning, button, nil, nil);
515 }
516
517
518 /*
519 * Display choice alert
520 */
521
522 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
523 {
524 NSString *title = [NSString stringWithCString:
525 GetString(STR_WARNING_ALERT_TITLE) ];
526 NSString *warning = [NSString stringWithCString: text];
527 NSString *yes = [NSString stringWithCString: pos];
528 NSString *no = [NSString stringWithCString: neg];
529
530 NSLog(warning);
531 return NSRunInformationalAlertPanel(title, warning, yes, no, nil);
532 }