ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/main_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/main_unix.cpp (file contents):
Revision 1.16 by cebix, 2000-07-22T18:12:34Z vs.
Revision 1.43 by cebix, 2002-01-22T17:15:09Z

# Line 1 | Line 1
1   /*
2   *  main_unix.cpp - Startup code for Unix
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 Christian Bauer
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
# Line 30 | Line 30
30   # include <pthread.h>
31   #endif
32  
33 < #if defined(USE_MAPPED_MEMORY) || REAL_ADDRESSING
33 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
34   # include <sys/mman.h>
35   #endif
36  
# Line 50 | Line 50 | struct sigstate {
50  
51   #ifdef ENABLE_GTK
52   # include <gtk/gtk.h>
53 + # include <gdk/gdk.h>
54 + # ifdef HAVE_GNOMEUI
55 + #  include <gnome.h>
56 + # endif
57   #endif
58  
59   #ifdef ENABLE_XF86_DGA
# Line 70 | Line 74 | struct sigstate {
74   #include "user_strings.h"
75   #include "version.h"
76   #include "main.h"
77 + #include "vm_alloc.h"
78  
79   #ifdef ENABLE_MON
80   # include "mon.h"
# Line 107 | Line 112 | bool TwentyFourBitAddressing;
112   char *x_display_name = NULL;                                            // X11 display name
113   Display *x_display = NULL;                                                      // X11 display handle
114  
115 < static int zero_fd = -1;                                                        // FD of /dev/zero
111 < static uint8 last_xpram[256];                                           // Buffer for monitoring XPRAM changes
115 > static uint8 last_xpram[XPRAM_SIZE];                            // Buffer for monitoring XPRAM changes
116  
117   #ifdef HAVE_PTHREADS
118   static pthread_t emul_thread;                                           // Handle of MacOS emulation thread (main thread)
# Line 122 | Line 126 | static volatile bool tick_thread_cancel
126   static pthread_t tick_thread;                                           // 60Hz thread
127   static pthread_attr_t tick_thread_attr;                         // 60Hz thread attributes
128  
125 #if EMULATED_68K
129   static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect InterruptFlags
130 < #endif
130 > #define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock)
131 > #define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock)
132 >
133 > #else
134 >
135 > #define LOCK_INTFLAGS
136 > #define UNLOCK_INTFLAGS
137 >
138   #endif
139  
140   #if !EMULATED_68K
# Line 133 | Line 143 | static struct sigaction sigirq_sa;     // Vi
143   static struct sigaction sigill_sa;      // Illegal instruction
144   static void *sig_stack = NULL;          // Stack for signal handlers
145   uint16 EmulatedSR;                                      // Emulated bits of SR (supervisor bit and interrupt mask)
146 < uint32 ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
146 > #endif
147 >
148 > #if USE_SCRATCHMEM_SUBTERFUGE
149 > uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
150   #endif
151  
152   static struct sigaction timer_sa;       // sigaction used for timer
# Line 152 | Line 165 | static void sigint_handler(...);
165   static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
166   #endif
167  
155 #ifdef USE_MAPPED_MEMORY
156 extern char *address_space, *good_address_map;
157 #endif
158
168  
169   // Prototypes
170   static void *xpram_func(void *arg);
# Line 190 | Line 199 | char *strdup(const char *s)
199   *  Main program
200   */
201  
202 + static void usage(const char *prg_name)
203 + {
204 +        printf("Usage: %s [OPTION...]\n", prg_name);
205 +        printf("\nUnix options:\n");
206 +        printf("  --display STRING\n    X display to use\n");
207 +        printf("  --break ADDRESS\n    set ROM breakpoint\n");
208 +        printf("  --rominfo\n    dump ROM information\n");
209 +        PrefsPrintUsage();
210 +        exit(0);
211 + }
212 +
213   int main(int argc, char **argv)
214   {
215          char str[256];
# Line 204 | Line 224 | int main(int argc, char **argv)
224          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
225          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
226  
227 <        // Parse arguments
227 > #ifdef ENABLE_GTK
228 > #ifdef HAVE_GNOMEUI
229 >        // Init GNOME/GTK
230 >        char version[16];
231 >        sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
232 >        gnome_init("Basilisk II", version, argc, argv);
233 > #else
234 >        // Init GTK
235 >        gtk_set_locale();
236 >        gtk_init(&argc, &argv);
237 > #endif
238 >        x_display_name = gdk_get_display(); // gtk_init() handles and removes the "--display" argument
239 > #endif
240 >
241 >        // Read preferences
242 >        PrefsInit(argc, argv);
243 >
244 >        // Parse command line arguments
245          for (int i=1; i<argc; i++) {
246 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
247 <                        x_display_name = argv[i];
248 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
249 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
250 <                else if (strcmp(argv[i], "-rominfo") == 0)
246 >                if (strcmp(argv[i], "--help") == 0) {
247 >                        usage(argv[0]);
248 >                } else if (strcmp(argv[i], "--display") == 0) {
249 >                        i++;
250 >                        if (i < argc)
251 >                                x_display_name = strdup(argv[i]);
252 >                } else if (strcmp(argv[i], "--break") == 0) {
253 >                        i++;
254 >                        if (i < argc)
255 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
256 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
257                          PrintROMInfo = true;
258 +                } else if (argv[i][0] == '-') {
259 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
260 +                        usage(argv[0]);
261 +                }
262          }
263  
264          // Open display
# Line 228 | Line 275 | int main(int argc, char **argv)
275          XF86DGAForkApp(DefaultScreen(x_display));
276   #endif
277  
231 #ifdef ENABLE_GTK
232        // Init GTK
233        gtk_set_locale();
234        gtk_init(&argc, &argv);
235 #endif
236
237        // Read preferences
238        PrefsInit();
239
278          // Init system routines
279          SysInit();
280  
# Line 245 | Line 283 | int main(int argc, char **argv)
283                  if (!PrefsEditor())
284                          QuitEmulator();
285  
248        // Open /dev/zero
249        zero_fd = open("/dev/zero", O_RDWR);
250        if (zero_fd < 0) {
251                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
252                ErrorAlert(str);
253                QuitEmulator();
254        }
255
286          // Read RAM size
287          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
288          if (RAMSize < 1024*1024) {
# Line 260 | Line 290 | int main(int argc, char **argv)
290                  RAMSize = 1024*1024;
291          }
292  
293 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
294 +        RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
295 + #endif
296 +        
297 +        // Initialize VM system
298 +        vm_init();
299 +
300   #if REAL_ADDRESSING
301 <        // Create Low Memory area (0x0000..0x2000)
302 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
301 >        // Flag: RAM and ROM are contigously allocated from address 0
302 >        bool memory_mapped_from_zero = false;
303 >        
304 >        // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
305 >        // when trying to map a too big chunk of memory starting at address 0
306 > #if defined(OS_solaris) || defined(OS_netbsd)
307 >        const bool can_map_all_memory = false;
308 > #else
309 >        const bool can_map_all_memory = true;
310 > #endif
311 >        
312 >        // Try to allocate all memory from 0x0000, if it is not known to crash
313 >        if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
314 >                D(bug("Could allocate RAM and ROM from 0x0000\n"));
315 >                memory_mapped_from_zero = true;
316 >        }
317 >        
318 >        // Otherwise, just create the Low Memory area (0x0000..0x2000)
319 >        else if (vm_acquire_fixed(0, 0x2000) == 0) {
320 >                D(bug("Could allocate the Low Memory globals\n"));
321 >                lm_area_mapped = true;
322 >        }
323 >        
324 >        // Exit on failure
325 >        else {
326                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
327                  ErrorAlert(str);
328                  QuitEmulator();
329          }
270        lm_area_mapped = true;
330   #endif
331  
332 < #if !EMULATED_68K
332 >        // Create areas for Mac RAM and ROM
333 > #if REAL_ADDRESSING
334 >        if (memory_mapped_from_zero) {
335 >                RAMBaseHost = (uint8 *)0;
336 >                ROMBaseHost = RAMBaseHost + RAMSize;
337 >        }
338 >        else
339 > #endif
340 >        {
341 >                RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
342 >                ROMBaseHost = (uint8 *)vm_acquire(0x100000);
343 >                if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
344 >                        ErrorAlert(STR_NO_MEM_ERR);
345 >                        QuitEmulator();
346 >                }
347 >        }
348 >
349 > #if USE_SCRATCHMEM_SUBTERFUGE
350          // Allocate scratch memory
351 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
352 <        if (ScratchMem == NULL) {
353 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
351 >        ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
352 >        if (ScratchMem == VM_MAP_FAILED) {
353 >                ErrorAlert(STR_NO_MEM_ERR);
354                  QuitEmulator();
355          }
356          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
357   #endif
358  
359 <        // Create areas for Mac RAM and ROM
360 < #if defined(USE_MAPPED_MEMORY)
361 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
362 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
363 <    if ((int)address_space < 0 || (int)good_address_map < 0) {
288 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
289 <                QuitEmulator();
290 <    }
291 <    RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
292 <    ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
293 <        char *nam = tmpnam(NULL);
294 <    int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
295 <        char buffer[4096];
296 <    memset(buffer, 1, sizeof(buffer));
297 <    write(good_address_fd, buffer, sizeof(buffer));
298 <    unlink(nam);
299 <    for (int i=0; i<RAMSize; i+=4096)
300 <        mmap(good_address_map + i, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
301 <    for (int i=0; i<0x80000; i+=4096)
302 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
303 < #else
304 <        RAMBaseHost = new uint8[RAMSize];
305 <        ROMBaseHost = new uint8[0x100000];
359 > #if DIRECT_ADDRESSING
360 >        // RAMBaseMac shall always be zero
361 >        MEMBaseDiff = (uintptr)RAMBaseHost;
362 >        RAMBaseMac = 0;
363 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
364   #endif
365 < #if REAL_ADDRESSING && !EMULATED_68K
365 > #if REAL_ADDRESSING
366          RAMBaseMac = (uint32)RAMBaseHost;
367          ROMBaseMac = (uint32)ROMBaseHost;
368   #endif
369          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
370          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
371 <
371 >        
372          // Get rom file path from preferences
373          const char *rom_path = PrefsFindString("rom");
374  
375          // Load Mac ROM
376          int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
377          if (rom_fd < 0) {
378 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
378 >                ErrorAlert(STR_NO_ROM_FILE_ERR);
379                  QuitEmulator();
380          }
381          printf(GetString(STR_READING_ROM_FILE));
382          ROMSize = lseek(rom_fd, 0, SEEK_END);
383          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
384 <                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
384 >                ErrorAlert(STR_ROM_SIZE_ERR);
385                  close(rom_fd);
386                  QuitEmulator();
387          }
388          lseek(rom_fd, 0, SEEK_SET);
389          if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
390 <                ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
390 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
391                  close(rom_fd);
392                  QuitEmulator();
393          }
# Line 359 | Line 417 | int main(int argc, char **argv)
417                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
418                  CPUType = 2;
419          }
420 <        FPUType = 0;    //!!
420 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
421          TwentyFourBitAddressing = false;
422   #endif
423  
# Line 381 | Line 439 | int main(int argc, char **argv)
439          sig_stack = malloc(SIG_STACK_SIZE);
440          D(bug("Signal stack at %p\n", sig_stack));
441          if (sig_stack == NULL) {
442 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
442 >                ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR);
443                  QuitEmulator();
444          }
445          stack_t new_stack;
# Line 422 | Line 480 | int main(int argc, char **argv)
480   #ifdef ENABLE_MON
481          // Setup SIGINT handler to enter mon
482          sigemptyset(&sigint_sa.sa_mask);
483 <        sigint_sa.sa_handler = sigint_handler;
483 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
484          sigint_sa.sa_flags = 0;
485          sigaction(SIGINT, &sigint_sa, NULL);
486   #endif
487  
488 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
488 > #if defined(HAVE_PTHREADS)
489 >
490 >        // POSIX threads available, start 60Hz thread
491 >        pthread_attr_init(&tick_thread_attr);
492 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
493 >        if (geteuid() == 0) {
494 >                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
495 >                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
496 >                struct sched_param fifo_param;
497 >                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
498 >                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
499 >        }
500 > #endif
501 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
502 >        if (!tick_thread_active) {
503 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
504 >                ErrorAlert(str);
505 >                QuitEmulator();
506 >        }
507 >        D(bug("60Hz thread started\n"));
508 >
509 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
510  
511          // POSIX.4 timers and real-time signals available, start 60Hz timer
512          sigemptyset(&timer_sa.sa_mask);
513 <        timer_sa.sa_sigaction = one_tick;
513 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
514          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
515          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
516                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 458 | Line 537 | int main(int argc, char **argv)
537          }
538          D(bug("60Hz timer started\n"));
539  
461 #elif defined(HAVE_PTHREADS)
462
463        // POSIX threads available, start 60Hz thread
464        pthread_attr_init(&tick_thread_attr);
465 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
466        if (geteuid() == 0) {
467                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
468                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
469                struct sched_param fifo_param;
470                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
471                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
472        }
473 #endif
474        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
475        if (!tick_thread_active) {
476                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
477                ErrorAlert(str);
478                QuitEmulator();
479        }
480        D(bug("60Hz thread started\n"));
481
540   #else
541  
542          // Start 60Hz timer
# Line 500 | Line 558 | int main(int argc, char **argv)
558  
559   #ifdef HAVE_PTHREADS
560          // Start XPRAM watchdog thread
561 <        memcpy(last_xpram, XPRAM, 256);
561 >        memcpy(last_xpram, XPRAM, XPRAM_SIZE);
562          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
563          D(bug("XPRAM thread started\n"));
564   #endif
# Line 527 | Line 585 | void QuitEmulator(void)
585          Exit680x0();
586   #endif
587  
588 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
531 <        // Stop 60Hz timer
532 <        timer_delete(timer);
533 < #elif defined(HAVE_PTHREADS)
588 > #if defined(HAVE_PTHREADS)
589          // Stop 60Hz thread
590          if (tick_thread_active) {
591                  tick_thread_cancel = true;
# Line 539 | Line 594 | void QuitEmulator(void)
594   #endif
595                  pthread_join(tick_thread, NULL);
596          }
597 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
598 +        // Stop 60Hz timer
599 +        timer_delete(timer);
600   #else
601          struct itimerval req;
602          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 560 | Line 618 | void QuitEmulator(void)
618          // Deinitialize everything
619          ExitAll();
620  
621 <        // Delete ROM area
622 <        delete[] ROMBaseHost;
623 <
624 <        // Delete RAM area
625 <        delete[] RAMBaseHost;
621 >        // Free ROM/RAM areas
622 >        if (RAMBaseHost != VM_MAP_FAILED) {
623 >                vm_release(RAMBaseHost, RAMSize);
624 >                RAMBaseHost = NULL;
625 >        }
626 >        if (ROMBaseHost != VM_MAP_FAILED) {
627 >                vm_release(ROMBaseHost, 0x100000);
628 >                ROMBaseHost = NULL;
629 >        }
630  
631 < #if !EMULATED_68K
631 > #if USE_SCRATCHMEM_SUBTERFUGE
632          // Delete scratch memory area
633 <        if (ScratchMem)
634 <                free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
633 >        if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
634 >                vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
635 >                ScratchMem = NULL;
636 >        }
637   #endif
638  
639   #if REAL_ADDRESSING
640          // Delete Low Memory area
641          if (lm_area_mapped)
642 <                munmap((char *)0x0000, 0x2000);
642 >                vm_release(0, 0x2000);
643   #endif
644 <
645 <        // Close /dev/zero
646 <        if (zero_fd > 0)
583 <                close(zero_fd);
644 >        
645 >        // Exit VM wrappers
646 >        vm_exit();
647  
648          // Exit system routines
649          SysExit();
# Line 620 | Line 683 | static void sigint_handler(...)
683          uaecptr nextpc;
684          extern void m68k_dumpstate(uaecptr *nextpc);
685          m68k_dumpstate(&nextpc);
686 < #else
687 <        char *arg[2] = {"rmon", NULL};
688 <        mon(1, arg);
686 > #endif
687 >        VideoQuitFullScreen();
688 >        char *arg[4] = {"mon", "-m", "-r", NULL};
689 >        mon(3, arg);
690          QuitEmulator();
691 + }
692   #endif
693 +
694 +
695 + /*
696 + *  Mutexes
697 + */
698 +
699 + #ifdef HAVE_PTHREADS
700 +
701 + struct B2_mutex {
702 +        B2_mutex() { pthread_mutex_init(&m, NULL); }
703 +        ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); }
704 +        pthread_mutex_t m;
705 + };
706 +
707 + B2_mutex *B2_create_mutex(void)
708 + {
709 +        return new B2_mutex;
710 + }
711 +
712 + void B2_lock_mutex(B2_mutex *mutex)
713 + {
714 +        pthread_mutex_lock(&mutex->m);
715   }
716 +
717 + void B2_unlock_mutex(B2_mutex *mutex)
718 + {
719 +        pthread_mutex_unlock(&mutex->m);
720 + }
721 +
722 + void B2_delete_mutex(B2_mutex *mutex)
723 + {
724 +        delete mutex;
725 + }
726 +
727 + #else
728 +
729 + struct B2_mutex {
730 +        int dummy;
731 + };
732 +
733 + B2_mutex *B2_create_mutex(void)
734 + {
735 +        return new B2_mutex;
736 + }
737 +
738 + void B2_lock_mutex(B2_mutex *mutex)
739 + {
740 + }
741 +
742 + void B2_unlock_mutex(B2_mutex *mutex)
743 + {
744 + }
745 +
746 + void B2_delete_mutex(B2_mutex *mutex)
747 + {
748 +        delete mutex;
749 + }
750 +
751   #endif
752  
753  
# Line 638 | Line 760 | uint32 InterruptFlags = 0;
760   #if EMULATED_68K
761   void SetInterruptFlag(uint32 flag)
762   {
763 < #ifdef HAVE_PTHREADS
642 <        pthread_mutex_lock(&intflag_lock);
763 >        LOCK_INTFLAGS;
764          InterruptFlags |= flag;
765 <        pthread_mutex_unlock(&intflag_lock);
645 < #else
646 <        InterruptFlags |= flag;         // Pray that this is an atomic operation...
647 < #endif
765 >        UNLOCK_INTFLAGS;
766   }
767  
768   void ClearInterruptFlag(uint32 flag)
769   {
770 < #ifdef HAVE_PTHREADS
653 <        pthread_mutex_lock(&intflag_lock);
770 >        LOCK_INTFLAGS;
771          InterruptFlags &= ~flag;
772 <        pthread_mutex_unlock(&intflag_lock);
656 < #else
657 <        InterruptFlags &= ~flag;
658 < #endif
772 >        UNLOCK_INTFLAGS;
773   }
774   #endif
775  
# Line 668 | Line 782 | void TriggerInterrupt(void)
782          raise(SIG_IRQ);
783   #endif
784   }
785 +
786 + void TriggerNMI(void)
787 + {
788 +        // not yet supported
789 + }
790   #endif
791  
792  
# Line 677 | Line 796 | void TriggerInterrupt(void)
796  
797   static void xpram_watchdog(void)
798   {
799 <        if (memcmp(last_xpram, XPRAM, 256)) {
800 <                memcpy(last_xpram, XPRAM, 256);
799 >        if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
800 >                memcpy(last_xpram, XPRAM, XPRAM_SIZE);
801                  SaveXPRAM();
802          }
803   }
# Line 688 | Line 807 | static void *xpram_func(void *arg)
807   {
808          while (!xpram_thread_cancel) {
809                  for (int i=0; i<60 && !xpram_thread_cancel; i++)
810 <                        Delay_usec(1000000);
810 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
811                  xpram_watchdog();
812          }
813          return NULL;
# Line 705 | Line 824 | static void one_second(void)
824          // Pseudo Mac 1Hz interrupt, update local time
825          WriteMacInt32(0x20c, TimerDateTime());
826  
827 <        SetInterruptFlag(INTFLAG_60HZ);
827 >        SetInterruptFlag(INTFLAG_1HZ);
828          TriggerInterrupt();
829  
830   #ifndef HAVE_PTHREADS
# Line 726 | Line 845 | static void one_tick(...)
845          }
846  
847   #ifndef HAVE_PTHREADS
848 <        // No threads available, perform video refresh from here
848 >        // No threads available, perform video refresh and networking from here
849          VideoRefresh();
850 +        SetInterruptFlag(INTFLAG_ETHER);
851   #endif
852  
853          // Trigger 60Hz interrupt
# Line 740 | Line 860 | static void one_tick(...)
860   #ifdef HAVE_PTHREADS
861   static void *tick_func(void *arg)
862   {
863 +        uint64 start = GetTicks_usec();
864 +        int64 ticks = 0;
865          uint64 next = GetTicks_usec();
866          while (!tick_thread_cancel) {
867                  one_tick();
# Line 749 | Line 871 | static void *tick_func(void *arg)
871                          Delay_usec(delay);
872                  else if (delay < -16625)
873                          next = GetTicks_usec();
874 +                ticks++;
875          }
876 +        uint64 end = GetTicks_usec();
877 +        D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
878          return NULL;
879   }
880   #endif
881  
882  
758 /*
759 *  Get current value of microsecond timer
760 */
761
762 uint64 GetTicks_usec(void)
763 {
764 #ifdef HAVE_CLOCK_GETTIME
765        struct timespec t;
766        clock_gettime(CLOCK_REALTIME, &t);
767        return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
768 #else
769        struct timeval t;
770        gettimeofday(&t, NULL);
771        return (uint64)t.tv_sec * 1000000 + t.tv_usec;
772 #endif
773 }
774
775
776 /*
777 *  Delay by specified number of microseconds (<1 second)
778 *  (adapted from SDL_Delay() source)
779 */
780
781 void Delay_usec(uint32 usec)
782 {
783        int was_error;
784 #ifndef __linux__       // Non-Linux implementations need to calculate time left
785        uint64 then, now, elapsed;
786 #endif
787        struct timeval tv;
788
789        // Set the timeout interval - Linux only needs to do this once
790 #ifdef __linux__
791        tv.tv_sec = 0;
792        tv.tv_usec = usec;
793 #else
794        then = GetTicks_usec();
795 #endif
796        do {
797                errno = 0;
798 #ifndef __linux__
799                /* Calculate the time interval left (in case of interrupt) */
800                now = GetTicks_usec();
801                elapsed = now - then;
802                then = now;
803                if (elapsed >= usec)
804                        break;
805                usec -= elapsed;
806                tv.tv_sec = 0;
807                tv.tv_usec = usec;
808 #endif
809                was_error = select(0, NULL, NULL, NULL, &tv);
810        } while (was_error && (errno == EINTR));
811 }
812
813
883   #if !EMULATED_68K
884   /*
885   *  Virtual 68k interrupt handler
# Line 861 | Line 930 | static void sigill_handler(int sig, int
930  
931   #define STORE_SR(v) \
932          scp->sc_ps = (v) & 0xff; \
933 <        EmulatedSR = (v) & 0x2700; \
933 >        EmulatedSR = (v) & 0xe700; \
934          if (((v) & 0x0700) == 0 && InterruptFlags) \
935                  TriggerInterrupt();
936  
# Line 924 | Line 993 | static void sigill_handler(int sig, int
993                  case 0x007c: {  // ori #xxxx,sr
994                          uint16 sr = GET_SR | pc[1];
995                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
996 <                        EmulatedSR = sr & 0x2700;
996 >                        EmulatedSR = sr & 0xe700;
997                          INC_PC(4);
998                          break;
999                  }
# Line 1001 | Line 1070 | static void sigill_handler(int sig, int
1070                  }
1071  
1072                  case 0xf327:    // fsave -(sp)
1073 <                        goto ill;       //!!
1073 >                        regs->a[7] -= 4;
1074 >                        WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1075 >                        scp->sc_sp = regs->a[7];
1076 >                        INC_PC(2);
1077 >                        break;
1078  
1079                  case 0xf35f:    // frestore (sp)+
1080 <                        goto ill;       //!!
1080 >                        regs->a[7] += 4;
1081 >                        scp->sc_sp = regs->a[7];
1082 >                        INC_PC(2);
1083 >                        break;
1084  
1085 <                case 0x4e73: {  // rte (only handles format 0)
1085 >                case 0x4e73: {  // rte
1086                          uint32 a7 = regs->a[7];
1087                          uint16 sr = ReadMacInt16(a7);
1088                          a7 += 2;
1089                          scp->sc_ps = sr & 0xff;
1090 <                        EmulatedSR = sr & 0x2700;
1090 >                        EmulatedSR = sr & 0xe700;
1091                          scp->sc_pc = ReadMacInt32(a7);
1092 <                        a7 += 6;
1093 <                        scp->sc_sp = regs->a[7] = a7;
1092 >                        a7 += 4;
1093 >                        uint16 format = ReadMacInt16(a7) >> 12;
1094 >                        a7 += 2;
1095 >                        static const int frame_adj[16] = {
1096 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1097 >                        };
1098 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1099                          break;
1100                  }
1101  
1102                  case 0x4e7a:    // movec cr,x
1103                          switch (pc[1]) {
1023                                case 0x8801:    // movec vbr,a0
1024                                        regs->a[0] = 0;
1025                                        break;
1026                                case 0x9801:    // movec vbr,a1
1027                                        regs->a[1] = 0;
1028                                        break;
1104                                  case 0x0002:    // movec cacr,d0
1105                                          regs->d[0] = 0x3111;
1106                                          break;
# Line 1033 | Line 1108 | static void sigill_handler(int sig, int
1108                                          regs->d[1] = 0x3111;
1109                                          break;
1110                                  case 0x0003:    // movec tc,d0
1111 +                                case 0x0004:    // movec itt0,d0
1112 +                                case 0x0005:    // movec itt1,d0
1113 +                                case 0x0006:    // movec dtt0,d0
1114 +                                case 0x0007:    // movec dtt1,d0
1115 +                                case 0x0806:    // movec urp,d0
1116 +                                case 0x0807:    // movec srp,d0
1117                                          regs->d[0] = 0;
1118                                          break;
1119 +                                case 0x1000:    // movec sfc,d1
1120 +                                case 0x1001:    // movec dfc,d1
1121                                  case 0x1003:    // movec tc,d1
1122 +                                case 0x1801:    // movec vbr,d1
1123                                          regs->d[1] = 0;
1124                                          break;
1125 +                                case 0x8801:    // movec vbr,a0
1126 +                                        regs->a[0] = 0;
1127 +                                        break;
1128 +                                case 0x9801:    // movec vbr,a1
1129 +                                        regs->a[1] = 0;
1130 +                                        break;
1131                                  default:
1132                                          goto ill;
1133                          }
# Line 1046 | Line 1136 | static void sigill_handler(int sig, int
1136  
1137                  case 0x4e7b:    // movec x,cr
1138                          switch (pc[1]) {
1139 +                                case 0x1000:    // movec d1,sfc
1140 +                                case 0x1001:    // movec d1,dfc
1141                                  case 0x0801:    // movec d0,vbr
1142 +                                case 0x1801:    // movec d1,vbr
1143                                          break;
1144                                  case 0x0002:    // movec d0,cacr
1145                                  case 0x1002:    // movec d1,cacr
# Line 1080 | Line 1173 | ill:           printf("SIGILL num %d, code %d\n",
1173                          for (int i=0; i<8; i++)
1174                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1175  
1176 +                        VideoQuitFullScreen();
1177   #ifdef ENABLE_MON
1178 <                        char *arg[2] = {"rmon", NULL};
1179 <                        mon(1, arg);
1178 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1179 >                        mon(3, arg);
1180   #endif
1181                          QuitEmulator();
1182                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines