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.13 by cebix, 2000-07-13T16:12:32Z vs.
Revision 1.42 by cebix, 2002-01-15T14:58:37Z

# 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   #endif
55  
56   #ifdef ENABLE_XF86_DGA
# Line 70 | Line 71 | struct sigstate {
71   #include "user_strings.h"
72   #include "version.h"
73   #include "main.h"
74 + #include "vm_alloc.h"
75  
76   #ifdef ENABLE_MON
77   # include "mon.h"
# Line 107 | Line 109 | bool TwentyFourBitAddressing;
109   char *x_display_name = NULL;                                            // X11 display name
110   Display *x_display = NULL;                                                      // X11 display handle
111  
112 < static int zero_fd = -1;                                                        // FD of /dev/zero
111 < static bool lm_area_mapped = false;                                     // Flag: Low Memory area mmap()ped
112 < static uint8 last_xpram[256];                                           // Buffer for monitoring XPRAM changes
112 > static uint8 last_xpram[XPRAM_SIZE];                            // Buffer for monitoring XPRAM changes
113  
114   #ifdef HAVE_PTHREADS
115   static pthread_t emul_thread;                                           // Handle of MacOS emulation thread (main thread)
# Line 123 | Line 123 | static volatile bool tick_thread_cancel
123   static pthread_t tick_thread;                                           // 60Hz thread
124   static pthread_attr_t tick_thread_attr;                         // 60Hz thread attributes
125  
126 #if EMULATED_68K
126   static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect InterruptFlags
127 < #endif
127 > #define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock)
128 > #define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock)
129 >
130 > #else
131 >
132 > #define LOCK_INTFLAGS
133 > #define UNLOCK_INTFLAGS
134 >
135   #endif
136  
137   #if !EMULATED_68K
# Line 134 | Line 140 | static struct sigaction sigirq_sa;     // Vi
140   static struct sigaction sigill_sa;      // Illegal instruction
141   static void *sig_stack = NULL;          // Stack for signal handlers
142   uint16 EmulatedSR;                                      // Emulated bits of SR (supervisor bit and interrupt mask)
143 < uint32 ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
143 > #endif
144 >
145 > #if USE_SCRATCHMEM_SUBTERFUGE
146 > uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
147   #endif
148  
149   static struct sigaction timer_sa;       // sigaction used for timer
# Line 149 | Line 158 | static struct sigaction sigint_sa;     // si
158   static void sigint_handler(...);
159   #endif
160  
161 < #ifdef USE_MAPPED_MEMORY
162 < extern char *address_space, *good_address_map;
161 > #if REAL_ADDRESSING
162 > static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
163   #endif
164  
165  
# Line 187 | Line 196 | char *strdup(const char *s)
196   *  Main program
197   */
198  
199 + static void usage(const char *prg_name)
200 + {
201 +        printf("Usage: %s [OPTION...]\n", prg_name);
202 +        printf("\nUnix options:\n");
203 +        printf("  --display STRING\n    X display to use\n");
204 +        printf("  --break ADDRESS\n    set ROM breakpoint\n");
205 +        printf("  --rominfo\n    dump ROM information\n");
206 +        PrefsPrintUsage();
207 +        exit(0);
208 + }
209 +
210   int main(int argc, char **argv)
211   {
212          char str[256];
# Line 201 | Line 221 | int main(int argc, char **argv)
221          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
222          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
223  
224 <        // Parse arguments
224 > #ifdef ENABLE_GTK
225 >        // Init GTK
226 >        gtk_set_locale();
227 >        gtk_init(&argc, &argv);
228 >        x_display_name = gdk_get_display(); // gtk_init() handles and removes the "--display" argument
229 > #endif
230 >
231 >        // Read preferences
232 >        PrefsInit(argc, argv);
233 >
234 >        // Parse command line arguments
235          for (int i=1; i<argc; i++) {
236 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
237 <                        x_display_name = argv[i];
238 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
239 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
240 <                else if (strcmp(argv[i], "-rominfo") == 0)
236 >                if (strcmp(argv[i], "--help") == 0) {
237 >                        usage(argv[0]);
238 >                } else if (strcmp(argv[i], "--display") == 0) {
239 >                        i++;
240 >                        if (i < argc)
241 >                                x_display_name = strdup(argv[i]);
242 >                } else if (strcmp(argv[i], "--break") == 0) {
243 >                        i++;
244 >                        if (i < argc)
245 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
246 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
247                          PrintROMInfo = true;
248 +                } else if (argv[i][0] == '-') {
249 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
250 +                        usage(argv[0]);
251 +                }
252          }
253  
254          // Open display
# Line 225 | Line 265 | int main(int argc, char **argv)
265          XF86DGAForkApp(DefaultScreen(x_display));
266   #endif
267  
228 #ifdef ENABLE_GTK
229        // Init GTK
230        gtk_set_locale();
231        gtk_init(&argc, &argv);
232 #endif
233
234        // Read preferences
235        PrefsInit();
236
268          // Init system routines
269          SysInit();
270  
# Line 242 | Line 273 | int main(int argc, char **argv)
273                  if (!PrefsEditor())
274                          QuitEmulator();
275  
245        // Open /dev/zero
246        zero_fd = open("/dev/zero", O_RDWR);
247        if (zero_fd < 0) {
248                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
249                ErrorAlert(str);
250                QuitEmulator();
251        }
252
276          // Read RAM size
277          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
278          if (RAMSize < 1024*1024) {
# Line 257 | Line 280 | int main(int argc, char **argv)
280                  RAMSize = 1024*1024;
281          }
282  
283 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
284 +        RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
285 + #endif
286 +        
287 +        // Initialize VM system
288 +        vm_init();
289 +
290   #if REAL_ADDRESSING
291 <        // Create Low Memory area (0x0000..0x2000)
292 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
291 >        // Flag: RAM and ROM are contigously allocated from address 0
292 >        bool memory_mapped_from_zero = false;
293 >        
294 >        // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
295 >        // when trying to map a too big chunk of memory starting at address 0
296 > #if defined(OS_solaris) || defined(OS_netbsd)
297 >        const bool can_map_all_memory = false;
298 > #else
299 >        const bool can_map_all_memory = true;
300 > #endif
301 >        
302 >        // Try to allocate all memory from 0x0000, if it is not known to crash
303 >        if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
304 >                D(bug("Could allocate RAM and ROM from 0x0000\n"));
305 >                memory_mapped_from_zero = true;
306 >        }
307 >        
308 >        // Otherwise, just create the Low Memory area (0x0000..0x2000)
309 >        else if (vm_acquire_fixed(0, 0x2000) == 0) {
310 >                D(bug("Could allocate the Low Memory globals\n"));
311 >                lm_area_mapped = true;
312 >        }
313 >        
314 >        // Exit on failure
315 >        else {
316                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
317                  ErrorAlert(str);
318                  QuitEmulator();
319          }
267        lm_area_mapped = true;
320   #endif
321  
322 < #if !EMULATED_68K
322 >        // Create areas for Mac RAM and ROM
323 > #if REAL_ADDRESSING
324 >        if (memory_mapped_from_zero) {
325 >                RAMBaseHost = (uint8 *)0;
326 >                ROMBaseHost = RAMBaseHost + RAMSize;
327 >        }
328 >        else
329 > #endif
330 >        {
331 >                RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
332 >                ROMBaseHost = (uint8 *)vm_acquire(0x100000);
333 >                if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
334 >                        ErrorAlert(STR_NO_MEM_ERR);
335 >                        QuitEmulator();
336 >                }
337 >        }
338 >
339 > #if USE_SCRATCHMEM_SUBTERFUGE
340          // Allocate scratch memory
341 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
342 <        if (ScratchMem == NULL) {
343 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
341 >        ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
342 >        if (ScratchMem == VM_MAP_FAILED) {
343 >                ErrorAlert(STR_NO_MEM_ERR);
344                  QuitEmulator();
345          }
346          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
347   #endif
348  
349 <        // Create areas for Mac RAM and ROM
350 < #if defined(USE_MAPPED_MEMORY)
351 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
352 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
353 <    if ((int)address_space < 0 || (int)good_address_map < 0) {
285 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
286 <                QuitEmulator();
287 <    }
288 <    RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
289 <    ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
290 <        char *nam = tmpnam(NULL);
291 <    int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
292 <        char buffer[4096];
293 <    memset(buffer, 1, sizeof(buffer));
294 <    write(good_address_fd, buffer, sizeof(buffer));
295 <    unlink(nam);
296 <    for (int i=0; i<RAMSize; i+=4096)
297 <        mmap(good_address_map + i, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
298 <    for (int i=0; i<0x80000; i+=4096)
299 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
300 < #else
301 <        RAMBaseHost = new uint8[RAMSize];
302 <        ROMBaseHost = new uint8[0x100000];
349 > #if DIRECT_ADDRESSING
350 >        // RAMBaseMac shall always be zero
351 >        MEMBaseDiff = (uintptr)RAMBaseHost;
352 >        RAMBaseMac = 0;
353 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
354   #endif
355 < #if REAL_ADDRESSING && !EMULATED_68K
355 > #if REAL_ADDRESSING
356          RAMBaseMac = (uint32)RAMBaseHost;
357          ROMBaseMac = (uint32)ROMBaseHost;
358   #endif
359          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
360          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
361 <
361 >        
362          // Get rom file path from preferences
363          const char *rom_path = PrefsFindString("rom");
364  
365          // Load Mac ROM
366          int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
367          if (rom_fd < 0) {
368 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
368 >                ErrorAlert(STR_NO_ROM_FILE_ERR);
369                  QuitEmulator();
370          }
371          printf(GetString(STR_READING_ROM_FILE));
372          ROMSize = lseek(rom_fd, 0, SEEK_END);
373          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
374 <                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
374 >                ErrorAlert(STR_ROM_SIZE_ERR);
375                  close(rom_fd);
376                  QuitEmulator();
377          }
378          lseek(rom_fd, 0, SEEK_SET);
379          if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
380 <                ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
380 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
381                  close(rom_fd);
382                  QuitEmulator();
383          }
# Line 356 | Line 407 | int main(int argc, char **argv)
407                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
408                  CPUType = 2;
409          }
410 <        FPUType = 0;    //!!
410 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
411          TwentyFourBitAddressing = false;
412   #endif
413  
# Line 378 | Line 429 | int main(int argc, char **argv)
429          sig_stack = malloc(SIG_STACK_SIZE);
430          D(bug("Signal stack at %p\n", sig_stack));
431          if (sig_stack == NULL) {
432 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
432 >                ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR);
433                  QuitEmulator();
434          }
435          stack_t new_stack;
# Line 419 | Line 470 | int main(int argc, char **argv)
470   #ifdef ENABLE_MON
471          // Setup SIGINT handler to enter mon
472          sigemptyset(&sigint_sa.sa_mask);
473 <        sigint_sa.sa_handler = sigint_handler;
473 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
474          sigint_sa.sa_flags = 0;
475          sigaction(SIGINT, &sigint_sa, NULL);
476   #endif
477  
478 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
478 > #if defined(HAVE_PTHREADS)
479 >
480 >        // POSIX threads available, start 60Hz thread
481 >        pthread_attr_init(&tick_thread_attr);
482 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
483 >        if (geteuid() == 0) {
484 >                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
485 >                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
486 >                struct sched_param fifo_param;
487 >                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
488 >                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
489 >        }
490 > #endif
491 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
492 >        if (!tick_thread_active) {
493 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
494 >                ErrorAlert(str);
495 >                QuitEmulator();
496 >        }
497 >        D(bug("60Hz thread started\n"));
498 >
499 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
500  
501          // POSIX.4 timers and real-time signals available, start 60Hz timer
502          sigemptyset(&timer_sa.sa_mask);
503 <        timer_sa.sa_sigaction = one_tick;
503 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
504          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
505          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
506                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 455 | Line 527 | int main(int argc, char **argv)
527          }
528          D(bug("60Hz timer started\n"));
529  
458 #elif defined(HAVE_PTHREADS)
459
460        // POSIX threads available, start 60Hz thread
461        pthread_attr_init(&tick_thread_attr);
462 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
463        if (geteuid() == 0) {
464                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
465                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
466                struct sched_param fifo_param;
467                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
468                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
469        }
470 #endif
471        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
472        if (!tick_thread_active) {
473                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
474                ErrorAlert(str);
475                QuitEmulator();
476        }
477        D(bug("60Hz thread started\n"));
478
530   #else
531  
532          // Start 60Hz timer
# Line 497 | Line 548 | int main(int argc, char **argv)
548  
549   #ifdef HAVE_PTHREADS
550          // Start XPRAM watchdog thread
551 <        memcpy(last_xpram, XPRAM, 256);
551 >        memcpy(last_xpram, XPRAM, XPRAM_SIZE);
552          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
553          D(bug("XPRAM thread started\n"));
554   #endif
# Line 524 | Line 575 | void QuitEmulator(void)
575          Exit680x0();
576   #endif
577  
578 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
528 <        // Stop 60Hz timer
529 <        timer_delete(timer);
530 < #elif defined(HAVE_PTHREADS)
578 > #if defined(HAVE_PTHREADS)
579          // Stop 60Hz thread
580          if (tick_thread_active) {
581                  tick_thread_cancel = true;
# Line 536 | Line 584 | void QuitEmulator(void)
584   #endif
585                  pthread_join(tick_thread, NULL);
586          }
587 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
588 +        // Stop 60Hz timer
589 +        timer_delete(timer);
590   #else
591          struct itimerval req;
592          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 557 | Line 608 | void QuitEmulator(void)
608          // Deinitialize everything
609          ExitAll();
610  
611 <        // Delete ROM area
612 <        delete[] ROMBaseHost;
613 <
614 <        // Delete RAM area
615 <        delete[] RAMBaseHost;
611 >        // Free ROM/RAM areas
612 >        if (RAMBaseHost != VM_MAP_FAILED) {
613 >                vm_release(RAMBaseHost, RAMSize);
614 >                RAMBaseHost = NULL;
615 >        }
616 >        if (ROMBaseHost != VM_MAP_FAILED) {
617 >                vm_release(ROMBaseHost, 0x100000);
618 >                ROMBaseHost = NULL;
619 >        }
620  
621 < #if !EMULATED_68K
621 > #if USE_SCRATCHMEM_SUBTERFUGE
622          // Delete scratch memory area
623 <        if (ScratchMem)
624 <                free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
623 >        if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
624 >                vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
625 >                ScratchMem = NULL;
626 >        }
627   #endif
628  
629   #if REAL_ADDRESSING
630          // Delete Low Memory area
631          if (lm_area_mapped)
632 <                munmap((char *)0x0000, 0x2000);
632 >                vm_release(0, 0x2000);
633   #endif
634 <
635 <        // Close /dev/zero
636 <        if (zero_fd > 0)
580 <                close(zero_fd);
634 >        
635 >        // Exit VM wrappers
636 >        vm_exit();
637  
638          // Exit system routines
639          SysExit();
# Line 617 | Line 673 | static void sigint_handler(...)
673          uaecptr nextpc;
674          extern void m68k_dumpstate(uaecptr *nextpc);
675          m68k_dumpstate(&nextpc);
676 < #else
677 <        char *arg[2] = {"rmon", NULL};
678 <        mon(1, arg);
676 > #endif
677 >        VideoQuitFullScreen();
678 >        char *arg[4] = {"mon", "-m", "-r", NULL};
679 >        mon(3, arg);
680          QuitEmulator();
681 + }
682   #endif
683 +
684 +
685 + /*
686 + *  Mutexes
687 + */
688 +
689 + #ifdef HAVE_PTHREADS
690 +
691 + struct B2_mutex {
692 +        B2_mutex() { pthread_mutex_init(&m, NULL); }
693 +        ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); }
694 +        pthread_mutex_t m;
695 + };
696 +
697 + B2_mutex *B2_create_mutex(void)
698 + {
699 +        return new B2_mutex;
700 + }
701 +
702 + void B2_lock_mutex(B2_mutex *mutex)
703 + {
704 +        pthread_mutex_lock(&mutex->m);
705 + }
706 +
707 + void B2_unlock_mutex(B2_mutex *mutex)
708 + {
709 +        pthread_mutex_unlock(&mutex->m);
710 + }
711 +
712 + void B2_delete_mutex(B2_mutex *mutex)
713 + {
714 +        delete mutex;
715 + }
716 +
717 + #else
718 +
719 + struct B2_mutex {
720 +        int dummy;
721 + };
722 +
723 + B2_mutex *B2_create_mutex(void)
724 + {
725 +        return new B2_mutex;
726 + }
727 +
728 + void B2_lock_mutex(B2_mutex *mutex)
729 + {
730 + }
731 +
732 + void B2_unlock_mutex(B2_mutex *mutex)
733 + {
734 + }
735 +
736 + void B2_delete_mutex(B2_mutex *mutex)
737 + {
738 +        delete mutex;
739   }
740 +
741   #endif
742  
743  
# Line 635 | Line 750 | uint32 InterruptFlags = 0;
750   #if EMULATED_68K
751   void SetInterruptFlag(uint32 flag)
752   {
753 < #ifdef HAVE_PTHREADS
639 <        pthread_mutex_lock(&intflag_lock);
753 >        LOCK_INTFLAGS;
754          InterruptFlags |= flag;
755 <        pthread_mutex_unlock(&intflag_lock);
642 < #else
643 <        InterruptFlags |= flag;         // Pray that this is an atomic operation...
644 < #endif
755 >        UNLOCK_INTFLAGS;
756   }
757  
758   void ClearInterruptFlag(uint32 flag)
759   {
760 < #ifdef HAVE_PTHREADS
650 <        pthread_mutex_lock(&intflag_lock);
760 >        LOCK_INTFLAGS;
761          InterruptFlags &= ~flag;
762 <        pthread_mutex_unlock(&intflag_lock);
653 < #else
654 <        InterruptFlags &= ~flag;
655 < #endif
762 >        UNLOCK_INTFLAGS;
763   }
764   #endif
765  
# Line 665 | Line 772 | void TriggerInterrupt(void)
772          raise(SIG_IRQ);
773   #endif
774   }
775 +
776 + void TriggerNMI(void)
777 + {
778 +        // not yet supported
779 + }
780   #endif
781  
782  
# Line 674 | Line 786 | void TriggerInterrupt(void)
786  
787   static void xpram_watchdog(void)
788   {
789 <        if (memcmp(last_xpram, XPRAM, 256)) {
790 <                memcpy(last_xpram, XPRAM, 256);
789 >        if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
790 >                memcpy(last_xpram, XPRAM, XPRAM_SIZE);
791                  SaveXPRAM();
792          }
793   }
# Line 684 | Line 796 | static void xpram_watchdog(void)
796   static void *xpram_func(void *arg)
797   {
798          while (!xpram_thread_cancel) {
799 <                for (int i=0; i<60 && !xpram_thread_cancel; i++) {
800 < #ifdef HAVE_NANOSLEEP
689 <                        struct timespec req = {1, 0};
690 <                        nanosleep(&req, NULL);
691 < #else
692 <                        usleep(1000000);
693 < #endif
694 <                }
799 >                for (int i=0; i<60 && !xpram_thread_cancel; i++)
800 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
801                  xpram_watchdog();
802          }
803          return NULL;
# Line 708 | Line 814 | static void one_second(void)
814          // Pseudo Mac 1Hz interrupt, update local time
815          WriteMacInt32(0x20c, TimerDateTime());
816  
817 +        SetInterruptFlag(INTFLAG_1HZ);
818 +        TriggerInterrupt();
819 +
820   #ifndef HAVE_PTHREADS
821          static int second_counter = 0;
822          if (++second_counter > 60) {
# Line 726 | Line 835 | static void one_tick(...)
835          }
836  
837   #ifndef HAVE_PTHREADS
838 <        // No threads available, perform video refresh from here
838 >        // No threads available, perform video refresh and networking from here
839          VideoRefresh();
840 +        SetInterruptFlag(INTFLAG_ETHER);
841   #endif
842  
843          // Trigger 60Hz interrupt
# Line 740 | Line 850 | static void one_tick(...)
850   #ifdef HAVE_PTHREADS
851   static void *tick_func(void *arg)
852   {
853 +        uint64 start = GetTicks_usec();
854 +        int64 ticks = 0;
855 +        uint64 next = GetTicks_usec();
856          while (!tick_thread_cancel) {
744
745                // Wait
746 #ifdef HAVE_NANOSLEEP
747                struct timespec req = {0, 16625000};
748                nanosleep(&req, NULL);
749 #else
750                usleep(16625);
751 #endif
752
753                // Action
857                  one_tick();
858 +                next += 16625;
859 +                int64 delay = next - GetTicks_usec();
860 +                if (delay > 0)
861 +                        Delay_usec(delay);
862 +                else if (delay < -16625)
863 +                        next = GetTicks_usec();
864 +                ticks++;
865          }
866 +        uint64 end = GetTicks_usec();
867 +        D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
868          return NULL;
869   }
870   #endif
# Line 808 | Line 920 | static void sigill_handler(int sig, int
920  
921   #define STORE_SR(v) \
922          scp->sc_ps = (v) & 0xff; \
923 <        EmulatedSR = (v) & 0x2700; \
923 >        EmulatedSR = (v) & 0xe700; \
924          if (((v) & 0x0700) == 0 && InterruptFlags) \
925                  TriggerInterrupt();
926  
# Line 871 | Line 983 | static void sigill_handler(int sig, int
983                  case 0x007c: {  // ori #xxxx,sr
984                          uint16 sr = GET_SR | pc[1];
985                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
986 <                        EmulatedSR = sr & 0x2700;
986 >                        EmulatedSR = sr & 0xe700;
987                          INC_PC(4);
988                          break;
989                  }
# Line 948 | Line 1060 | static void sigill_handler(int sig, int
1060                  }
1061  
1062                  case 0xf327:    // fsave -(sp)
1063 <                        goto ill;       //!!
1063 >                        regs->a[7] -= 4;
1064 >                        WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1065 >                        scp->sc_sp = regs->a[7];
1066 >                        INC_PC(2);
1067 >                        break;
1068  
1069                  case 0xf35f:    // frestore (sp)+
1070 <                        goto ill;       //!!
1070 >                        regs->a[7] += 4;
1071 >                        scp->sc_sp = regs->a[7];
1072 >                        INC_PC(2);
1073 >                        break;
1074  
1075 <                case 0x4e73: {  // rte (only handles format 0)
1075 >                case 0x4e73: {  // rte
1076                          uint32 a7 = regs->a[7];
1077                          uint16 sr = ReadMacInt16(a7);
1078                          a7 += 2;
1079                          scp->sc_ps = sr & 0xff;
1080 <                        EmulatedSR = sr & 0x2700;
1080 >                        EmulatedSR = sr & 0xe700;
1081                          scp->sc_pc = ReadMacInt32(a7);
1082 <                        a7 += 6;
1083 <                        scp->sc_sp = regs->a[7] = a7;
1082 >                        a7 += 4;
1083 >                        uint16 format = ReadMacInt16(a7) >> 12;
1084 >                        a7 += 2;
1085 >                        static const int frame_adj[16] = {
1086 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1087 >                        };
1088 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1089                          break;
1090                  }
1091  
1092                  case 0x4e7a:    // movec cr,x
1093                          switch (pc[1]) {
970                                case 0x8801:    // movec vbr,a0
971                                        regs->a[0] = 0;
972                                        break;
973                                case 0x9801:    // movec vbr,a1
974                                        regs->a[1] = 0;
975                                        break;
1094                                  case 0x0002:    // movec cacr,d0
1095                                          regs->d[0] = 0x3111;
1096                                          break;
# Line 980 | Line 1098 | static void sigill_handler(int sig, int
1098                                          regs->d[1] = 0x3111;
1099                                          break;
1100                                  case 0x0003:    // movec tc,d0
1101 +                                case 0x0004:    // movec itt0,d0
1102 +                                case 0x0005:    // movec itt1,d0
1103 +                                case 0x0006:    // movec dtt0,d0
1104 +                                case 0x0007:    // movec dtt1,d0
1105 +                                case 0x0806:    // movec urp,d0
1106 +                                case 0x0807:    // movec srp,d0
1107                                          regs->d[0] = 0;
1108                                          break;
1109 +                                case 0x1000:    // movec sfc,d1
1110 +                                case 0x1001:    // movec dfc,d1
1111                                  case 0x1003:    // movec tc,d1
1112 +                                case 0x1801:    // movec vbr,d1
1113                                          regs->d[1] = 0;
1114                                          break;
1115 +                                case 0x8801:    // movec vbr,a0
1116 +                                        regs->a[0] = 0;
1117 +                                        break;
1118 +                                case 0x9801:    // movec vbr,a1
1119 +                                        regs->a[1] = 0;
1120 +                                        break;
1121                                  default:
1122                                          goto ill;
1123                          }
# Line 993 | Line 1126 | static void sigill_handler(int sig, int
1126  
1127                  case 0x4e7b:    // movec x,cr
1128                          switch (pc[1]) {
1129 +                                case 0x1000:    // movec d1,sfc
1130 +                                case 0x1001:    // movec d1,dfc
1131                                  case 0x0801:    // movec d0,vbr
1132 +                                case 0x1801:    // movec d1,vbr
1133                                          break;
1134                                  case 0x0002:    // movec d0,cacr
1135                                  case 0x1002:    // movec d1,cacr
# Line 1027 | Line 1163 | ill:           printf("SIGILL num %d, code %d\n",
1163                          for (int i=0; i<8; i++)
1164                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1165  
1166 +                        VideoQuitFullScreen();
1167   #ifdef ENABLE_MON
1168 <                        char *arg[2] = {"rmon", NULL};
1169 <                        mon(1, arg);
1168 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1169 >                        mon(3, arg);
1170   #endif
1171                          QuitEmulator();
1172                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines