ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/main_macosx.mm
(Generate patch)

Comparing BasiliskII/src/MacOSX/main_macosx.mm (file contents):
Revision 1.7 by nigel, 2003-03-26T00:26:38Z vs.
Revision 1.14 by nigel, 2005-09-19T07:49:12Z

# Line 5 | Line 5
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
8 > *  Basilisk II (C) 1997-2005 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
# Line 21 | Line 21
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
24 >
25 > #import <AppKit/AppKit.h>
26 > #undef check
27 >
28 > #define PTHREADS        // Why is this here?
29   #include "sysdeps.h"
30  
31   #ifdef HAVE_PTHREADS
# Line 32 | Line 36
36   # include <sys/mman.h>
37   #endif
38  
39 + #include <string>
40 + using std::string;
41 +
42   #include "cpu_emulation.h"
43   #include "macos_util_macosx.h"
44   #include "main.h"
45   #include "prefs.h"
46   #include "prefs_editor.h"
47   #include "rom_patches.h"
48 + #include "sigsegv.h"
49   #include "sys.h"
42 #include "timer.h"
50   #include "user_strings.h"
51   #include "version.h"
52   #include "video.h"
53   #include "vm_alloc.h"
54   #include "xpram.h"
55  
56 + #if USE_JIT
57 + extern void flush_icache_range(uint32 start, uint32 size);  // from compemu_support.cpp
58 + #endif
59 +
60   #ifdef ENABLE_MON
61   # include "mon.h"
62   #endif
# Line 54 | Line 65
65   #include "debug.h"
66  
67  
57 #import <AppKit/AppKit.h>
58
68   #include "main_macosx.h"                // To bridge between main() and misc. classes
69  
70  
71   // Constants
72   const char ROM_FILE_NAME[] = "ROM";
64 const int SIG_STACK_SIZE = SIGSTKSZ;    // Size of signal stack
73   const int SCRATCH_MEM_SIZE = 0x10000;   // Size of scratch memory area
74  
75  
# Line 70 | Line 78 | int CPUType;
78   bool CPUIs68060;
79   int FPUType;
80   bool TwentyFourBitAddressing;
81 + bool ThirtyThreeBitAddressing = false;
82  
83  
84   // Global variables
# Line 91 | Line 100 | static pthread_mutex_t intflag_lock = PT
100   uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
101   #endif
102  
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
103   #ifdef ENABLE_MON
104   static struct sigaction sigint_sa;      // sigaction for SIGINT handler
105   static void sigint_handler(...);
# Line 106 | Line 110 | static bool lm_area_mapped = false;    // F
110   #endif
111  
112  
113 + /*
114 + *  Map memory that can be accessed from the Mac side
115 + */
116 +
117 + void *vm_acquire_mac(size_t size)
118 + {
119 +        void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT);
120 +        if (m == NULL) {
121 +                ThirtyThreeBitAddressing = false;
122 +                m = vm_acquire(size);
123 +        }
124 +        return m;
125 + }
126 +
127 +
128 + /*
129 + *  SIGSEGV handler
130 + */
131 +
132 + static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address,
133 +                                                                                sigsegv_address_t fault_instruction)
134 + {
135 + #if ENABLE_VOSF
136 +        // Handle screen fault
137 +        extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t);
138 +        if (Screen_fault_handler(fault_address, fault_instruction))
139 +                return SIGSEGV_RETURN_SUCCESS;
140 + #endif
141 +
142 + #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
143 +        // Ignore writes to ROM
144 +        if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize)
145 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
146 +
147 +        // Ignore all other faults, if requested
148 +        if (PrefsFindBool("ignoresegv"))
149 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
150 + #endif
151 +
152 +        return SIGSEGV_RETURN_FAILURE;
153 + }
154 +
155 +
156 + /*
157 + *  Dump state when everything went wrong after a SEGV
158 + */
159 +
160 + static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
161 + {
162 +        fprintf(stderr, "Caught SIGSEGV at address %p", fault_address);
163 +        if (fault_instruction != SIGSEGV_INVALID_PC)
164 +                fprintf(stderr, " [IP=%p]", fault_instruction);
165 +        fprintf(stderr, "\n");
166 +        uaecptr nextpc;
167 +        extern void m68k_dumpstate(uaecptr *nextpc);
168 +        m68k_dumpstate(&nextpc);
169 + #if USE_JIT && JIT_DEBUG
170 +        extern void compiler_dumpstate(void);
171 +        compiler_dumpstate();
172 + #endif
173 +        VideoQuitFullScreen();
174 + #ifdef ENABLE_MON
175 +        char *arg[4] = {"mon", "-m", "-r", NULL};
176 +        mon(3, arg);
177 +        QuitEmulator();
178 + #endif
179 + }
180 +
181  
182   /*
183   *  Main program
# Line 116 | Line 188 | static void usage(const char *prg_name)
188          printf("Usage: %s [OPTION...]\n", prg_name);
189          printf("\nUnix options:\n");
190          printf("  --help\n    display this usage message\n");
191 +        printf("  --config FILE\n    read/write configuration from/to FILE\n");
192          printf("  --break ADDRESS\n    set ROM breakpoint\n");
193          printf("  --rominfo\n    dump ROM information\n");
194 +        LoadPrefs(); // read the prefs file so PrefsPrintUsage() will print the correct default values
195          PrefsPrintUsage();
196          exit(0);
197   }
# Line 134 | Line 208 | int main(int argc, char **argv)
208          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
209          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
210  
137        // Read preferences
138        PrefsInit(argc, argv);
139
211          // Parse command line arguments
212          for (int i=1; i<argc; i++) {
213                  if (strcmp(argv[i], "--help") == 0) {
# Line 147 | Line 218 | int main(int argc, char **argv)
218                          i++;
219                          if (i < argc)
220                                  ROMBreakpoint = strtol(argv[i], NULL, 0);
221 +                } else if (strcmp(argv[i], "--config") == 0) {
222 +                        argv[i++] = NULL;
223 +                        if (i < argc) {
224 +                                extern string UserPrefsPath; // from prefs_unix.cpp
225 +                                UserPrefsPath = argv[i];
226 +                                argv[i] = NULL;
227 +                        }
228                  } else if (strcmp(argv[i], "--rominfo") == 0) {
229                          PrintROMInfo = true;
230                  } else if (argv[i][0] == '-') {
# Line 155 | Line 233 | int main(int argc, char **argv)
233                  }
234          }
235  
236 +        // Read preferences
237 +        PrefsInit(argc, argv);
238 +
239          // Init system routines
240          SysInit();
241  
# Line 179 | Line 260 | bool InitEmulator (void)
260          char str[256];
261  
262  
263 +        // Install the handler for SIGSEGV
264 +        if (!sigsegv_install_handler(sigsegv_handler)) {
265 +                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
266 +                ErrorAlert(str);
267 +                QuitEmulator();
268 +        }
269 +
270 +        // Register dump state function when we got mad after a segfault
271 +        sigsegv_set_dump_state(sigsegv_dump_state);
272 +
273          // Read RAM size
274          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
275          if (RAMSize < 1024*1024) {
# Line 199 | Line 290 | bool InitEmulator (void)
290          
291          // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
292          // when trying to map a too big chunk of memory starting at address 0
293 < #if defined(OS_solaris) || defined(OS_netbsd)
293 > #if defined(OS_solaris) || defined(OS_netbsd) || defined(PAGEZERO_HACK)
294          const bool can_map_all_memory = false;
295   #else
296          const bool can_map_all_memory = true;
# Line 210 | Line 301 | bool InitEmulator (void)
301                  D(bug("Could allocate RAM and ROM from 0x0000\n"));
302                  memory_mapped_from_zero = true;
303          }
304 <        
304 >
305 > #ifndef PAGEZERO_HACK
306          // Otherwise, just create the Low Memory area (0x0000..0x2000)
307          else if (vm_acquire_fixed(0, 0x2000) == 0) {
308                  D(bug("Could allocate the Low Memory globals\n"));
# Line 223 | Line 315 | bool InitEmulator (void)
315                  ErrorAlert(str);
316                  QuitEmulator();
317          }
318 + #endif
319   #else
320          *str = 0;               // Eliminate unused variable warning
321 < #endif
321 > #endif /* REAL_ADDRESSING */
322  
323          // Create areas for Mac RAM and ROM
324   #if REAL_ADDRESSING
# Line 236 | Line 329 | bool InitEmulator (void)
329          else
330   #endif
331          {
332 <                RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
333 <                ROMBaseHost = (uint8 *)vm_acquire(0x100000);
334 <                if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
332 > #ifdef USE_33BIT_ADDRESSING
333 >                // Speculatively enables 33-bit addressing
334 >                ThirtyThreeBitAddressing = true;
335 > #endif
336 >                uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000);
337 >                if (ram_rom_area == VM_MAP_FAILED) {
338                          ErrorAlert(STR_NO_MEM_ERR);
339                          QuitEmulator();
340                  }
341 +                RAMBaseHost = ram_rom_area;
342 +                ROMBaseHost = RAMBaseHost + RAMSize;
343          }
344  
345   #if USE_SCRATCHMEM_SUBTERFUGE
# Line 330 | Line 428 | void QuitEmuNoExit()
428  
429          // Free ROM/RAM areas
430          if (RAMBaseHost != VM_MAP_FAILED) {
431 <                vm_release(RAMBaseHost, RAMSize);
431 >                vm_release(RAMBaseHost, RAMSize + 0x100000);
432                  RAMBaseHost = NULL;
433          }
336        if (ROMBaseHost != VM_MAP_FAILED) {
337                vm_release(ROMBaseHost, 0x100000);
338                ROMBaseHost = NULL;
339        }
434  
435   #if USE_SCRATCHMEM_SUBTERFUGE
436          // Delete scratch memory area
# Line 364 | Line 458 | void QuitEmuNoExit()
458  
459   void QuitEmulator(void)
460   {
367        extern  NSApplication *NSApp;
368
369
461          QuitEmuNoExit();
462  
463          // Stop run loop?
# Line 383 | Line 474 | void QuitEmulator(void)
474  
475   void FlushCodeCache(void *start, uint32 size)
476   {
477 + #if USE_JIT
478 +    if (UseJIT)
479 +                flush_icache_range((uintptr)start, size);
480 + #endif
481   }
482  
483  
# Line 404 | Line 499 | static void sigint_handler(...)
499   #endif
500  
501  
502 + #ifdef HAVE_PTHREADS
503 + /*
504 + *  Pthread configuration
505 + */
506 +
507 + void Set_pthread_attr(pthread_attr_t *attr, int priority)
508 + {
509 +        pthread_attr_init(attr);
510 + #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
511 +        // Some of these only work for superuser
512 +        if (geteuid() == 0) {
513 +                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
514 +                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
515 +                struct sched_param fifo_param;
516 +                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO)
517 +                                                                         + sched_get_priority_max(SCHED_FIFO))
518 +                                                                         / 2 + priority);
519 +                pthread_attr_setschedparam(attr, &fifo_param);
520 +        }
521 +        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
522 + #ifdef PTHREAD_SCOPE_BOUND_NP
523 +            // If system scope is not available (eg. we're not running
524 +            // with CAP_SCHED_MGT capability on an SGI box), try bound
525 +            // scope.  It exposes pthread scheduling to the kernel,
526 +            // without setting realtime priority.
527 +            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
528 + #endif
529 +        }
530 + #endif
531 + }
532 + #endif // HAVE_PTHREADS
533 +
534 +
535   /*
536   *  Mutexes
537   */
# Line 411 | Line 539 | static void sigint_handler(...)
539   #ifdef HAVE_PTHREADS
540  
541   struct B2_mutex {
542 <        B2_mutex() { pthread_mutex_init(&m, NULL); }
543 <        ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); }
542 >        B2_mutex() {
543 >                pthread_mutexattr_t attr;
544 >                pthread_mutexattr_init(&attr);
545 >                // Initialize the mutex for priority inheritance --
546 >                // required for accurate timing.
547 > #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
548 >                pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
549 > #endif
550 > #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
551 >                pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
552 > #endif
553 > #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
554 >                pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
555 > #endif
556 >                pthread_mutex_init(&m, &attr);
557 >                pthread_mutexattr_destroy(&attr);
558 >        }
559 >        ~B2_mutex() {
560 >                pthread_mutex_trylock(&m);      // Make sure it's locked before
561 >                pthread_mutex_unlock(&m);       // unlocking it.
562 >                pthread_mutex_destroy(&m);
563 >        }
564          pthread_mutex_t m;
565   };
566  
# Line 495 | Line 643 | void ErrorAlert(const char *text)
643          NSString *error  = [NSString stringWithCString: text];
644          NSString *button = [NSString stringWithCString: GetString(STR_QUIT_BUTTON) ];
645  
498 //      If we have a full screen mode, quit it here?
499
646          NSLog(error);
647 +        if ( PrefsFindBool("nogui") )
648 +                return;
649 +        VideoQuitFullScreen();
650          NSRunCriticalAlertPanel(title, error, button, nil, nil);
651   }
652  
# Line 514 | Line 663 | void WarningAlert(const char *text)
663          NSString *button  = [NSString stringWithCString: GetString(STR_OK_BUTTON) ];
664  
665          NSLog(warning);
666 +        if ( PrefsFindBool("nogui") )
667 +                return;
668 +        VideoQuitFullScreen();
669          NSRunAlertPanel(title, warning, button, nil, nil);
670   }
671  
# Line 530 | Line 682 | bool ChoiceAlert(const char *text, const
682          NSString *yes     = [NSString stringWithCString: pos];
683          NSString *no      = [NSString stringWithCString: neg];
684  
533        NSLog(warning);
685          return NSRunInformationalAlertPanel(title, warning, yes, no, nil);
686   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines