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.66 by gbeauche, 2005-06-06T19:39:36Z vs.
Revision 1.82 by asvitkine, 2012-04-01T15:05:55Z

# Line 1 | Line 1
1   /*
2   *  main_unix.cpp - Startup code for Unix
3   *
4 < *  Basilisk II (C) 1997-2005 Christian Bauer
4 > *  Basilisk II (C) 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 65 | Line 65 | struct sigstate {
65  
66   #ifdef ENABLE_XF86_DGA
67   # include <X11/Xutil.h>
68 < # include <X11/extensions/xf86dga.h>
68 > # include <X11/extensions/Xxf86dga.h>
69   #endif
70  
71   #include <string>
# Line 86 | Line 86 | using std::string;
86   #include "main.h"
87   #include "vm_alloc.h"
88   #include "sigsegv.h"
89 + #include "rpc.h"
90  
91   #if USE_JIT
92 < extern void flush_icache_range(uint32 start, uint32 size); // from compemu_support.cpp
92 > extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp
93   #endif
94  
95   #ifdef ENABLE_MON
# Line 123 | Line 124 | int CPUType;
124   bool CPUIs68060;
125   int FPUType;
126   bool TwentyFourBitAddressing;
126 bool ThirtyThreeBitAddressing = false;
127  
128  
129   // Global variables
# Line 192 | Line 192 | static void sigint_handler(...);
192   static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
193   #endif
194  
195 + static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI
196 + static const char *gui_connection_path = NULL;  // GUI connection identifier
197 +
198  
199   // Prototypes
200   static void *xpram_func(void *arg);
# Line 223 | Line 226 | char *strdup(const char *s)
226  
227  
228   /*
229 < *  Map memory that can be accessed from the Mac side
229 > *  Helpers to map memory that can be accessed from the Mac side
230   */
231  
232 + // NOTE: VM_MAP_32BIT is only used when compiling a 64-bit JIT on specific platforms
233   void *vm_acquire_mac(size_t size)
234   {
235 <        void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT);
236 <        if (m == NULL) {
237 <                ThirtyThreeBitAddressing = false;
238 <                m = vm_acquire(size);
239 <        }
240 <        return m;
235 >        return vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT);
236 > }
237 >
238 > static int vm_acquire_mac_fixed(void *addr, size_t size)
239 > {
240 >        return vm_acquire_fixed(addr, size, VM_MAP_DEFAULT | VM_MAP_32BIT);
241   }
242  
243  
# Line 241 | Line 245 | void *vm_acquire_mac(size_t size)
245   *  SIGSEGV handler
246   */
247  
248 < static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
248 > static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip)
249   {
250 +        const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip);
251   #if ENABLE_VOSF
252          // Handle screen fault
253 <        extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t);
254 <        if (Screen_fault_handler(fault_address, fault_instruction))
253 >        extern bool Screen_fault_handler(sigsegv_info_t *sip);
254 >        if (Screen_fault_handler(sip))
255                  return SIGSEGV_RETURN_SUCCESS;
256   #endif
257  
# Line 267 | Line 272 | static sigsegv_return_t sigsegv_handler(
272   *  Dump state when everything went wrong after a SEGV
273   */
274  
275 < static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
275 > static void sigsegv_dump_state(sigsegv_info_t *sip)
276   {
277 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
278 +        const sigsegv_address_t fault_instruction = sigsegv_get_fault_instruction_address(sip);
279          fprintf(stderr, "Caught SIGSEGV at address %p", fault_address);
280 <        if (fault_instruction != SIGSEGV_INVALID_PC)
280 >        if (fault_instruction != SIGSEGV_INVALID_ADDRESS)
281                  fprintf(stderr, " [IP=%p]", fault_instruction);
282          fprintf(stderr, "\n");
283   #if EMULATED_68K
# Line 284 | Line 291 | static void sigsegv_dump_state(sigsegv_a
291   #endif
292          VideoQuitFullScreen();
293   #ifdef ENABLE_MON
294 <        char *arg[4] = {"mon", "-m", "-r", NULL};
294 >        const char *arg[4] = {"mon", "-m", "-r", NULL};
295          mon(3, arg);
296   #endif
297          QuitEmulator();
# Line 292 | Line 299 | static void sigsegv_dump_state(sigsegv_a
299  
300  
301   /*
302 + *  Update virtual clock and trigger interrupts if necessary
303 + */
304 +
305 + #ifdef USE_CPU_EMUL_SERVICES
306 + static uint64 n_check_ticks = 0;
307 + static uint64 emulated_ticks_start = 0;
308 + static uint64 emulated_ticks_count = 0;
309 + static int64 emulated_ticks_current = 0;
310 + static int32 emulated_ticks_quantum = 1000;
311 + int32 emulated_ticks = emulated_ticks_quantum;
312 +
313 + void cpu_do_check_ticks(void)
314 + {
315 + #if DEBUG
316 +        n_check_ticks++;
317 + #endif
318 +
319 +        uint64 now;
320 +        static uint64 next = 0;
321 +        if (next == 0)
322 +                next = emulated_ticks_start = GetTicks_usec();
323 +
324 +        // Update total instructions count
325 +        if (emulated_ticks <= 0) {
326 +                emulated_ticks_current += (emulated_ticks_quantum - emulated_ticks);
327 +                // XXX: can you really have a machine fast enough to overflow
328 +                // a 63-bit m68k instruction counter within 16 ms?
329 +                if (emulated_ticks_current < 0) {
330 +                        printf("WARNING: Overflowed 63-bit m68k instruction counter in less than 16 ms!\n");
331 +                        goto recalibrate_quantum;
332 +                }
333 +        }
334 +
335 +        // Check for interrupt opportunity
336 +        now = GetTicks_usec();
337 +        if (next < now) {
338 +                one_tick();
339 +                do {
340 +                        next += 16625;
341 +                } while (next < now);
342 +                emulated_ticks_count++;
343 +
344 +                // Recalibrate 1000 Hz quantum every 10 ticks
345 +                static uint64 last = 0;
346 +                if (last == 0)
347 +                        last = now;
348 +                else if (now - last > 166250) {
349 +                  recalibrate_quantum:
350 +                        emulated_ticks_quantum = ((uint64)emulated_ticks_current * 1000) / (now - last);
351 +                        emulated_ticks_current = 0;
352 +                        last = now;
353 +                }
354 +        }
355 +
356 +        // Update countdown
357 +        if (emulated_ticks <= 0)
358 +                emulated_ticks += emulated_ticks_quantum;
359 + }
360 + #endif
361 +
362 +
363 + /*
364   *  Main program
365   */
366  
# Line 305 | Line 374 | static void usage(const char *prg_name)
374                  "  --break ADDRESS\n    set ROM breakpoint\n"
375                  "  --rominfo\n    dump ROM information\n", prg_name
376          );
377 <        LoadPrefs(); // read the prefs file so PrefsPrintUsage() will print the correct default values
377 >        LoadPrefs(NULL); // read the prefs file so PrefsPrintUsage() will print the correct default values
378          PrefsPrintUsage();
379          exit(0);
380   }
381  
382   int main(int argc, char **argv)
383   {
384 +        const char *vmdir = NULL;
385          char str[256];
386  
387          // Initialize variables
# Line 334 | Line 404 | int main(int argc, char **argv)
404                          if (i < argc)
405                                  x_display_name = strdup(argv[i]);
406   #endif
407 +                } else if (strcmp(argv[i], "--gui-connection") == 0) {
408 +                        argv[i++] = NULL;
409 +                        if (i < argc) {
410 +                                gui_connection_path = argv[i];
411 +                                argv[i] = NULL;
412 +                        }
413                  } else if (strcmp(argv[i], "--break") == 0) {
414                          argv[i++] = NULL;
415                          if (i < argc) {
# Line 367 | Line 443 | int main(int argc, char **argv)
443                  }
444          }
445  
446 +        // Connect to the external GUI
447 +        if (gui_connection_path) {
448 +                if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
449 +                        fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
450 +                        return 1;
451 +                }
452 +        }
453 +
454   #ifdef ENABLE_GTK
455 +        if (!gui_connection) {
456   #ifdef HAVE_GNOMEUI
457 <        // Init GNOME/GTK
458 <        char version[16];
459 <        sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
460 <        gnome_init("Basilisk II", version, argc, argv);
457 >                // Init GNOME/GTK
458 >                char version[16];
459 >                sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
460 >                gnome_init("Basilisk II", version, argc, argv);
461   #else
462 <        // Init GTK
463 <        gtk_set_locale();
464 <        gtk_init(&argc, &argv);
462 >                // Init GTK
463 >                gtk_set_locale();
464 >                gtk_init(&argc, &argv);
465   #endif
466 +        }
467   #endif
468  
469          // Read preferences
470 <        PrefsInit(argc, argv);
470 >        PrefsInit(vmdir, argc, argv);
471  
472          // Any command line arguments left?
473          for (int i=1; i<argc; i++) {
# Line 430 | Line 516 | int main(int argc, char **argv)
516          SysInit();
517  
518          // Show preferences editor
519 <        if (!PrefsFindBool("nogui"))
519 >        if (!gui_connection && !PrefsFindBool("nogui"))
520                  if (!PrefsEditor())
521                          QuitEmulator();
522  
# Line 450 | Line 536 | int main(int argc, char **argv)
536                  WarningAlert(GetString(STR_SMALL_RAM_WARN));
537                  RAMSize = 1024*1024;
538          }
539 +        if (RAMSize > 1023*1024*1024)                                           // Cap to 1023MB (APD crashes at 1GB)
540 +                RAMSize = 1023*1024*1024;
541  
542   #if REAL_ADDRESSING || DIRECT_ADDRESSING
543          RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
# Line 461 | Line 549 | int main(int argc, char **argv)
549   #if REAL_ADDRESSING
550          // Flag: RAM and ROM are contigously allocated from address 0
551          bool memory_mapped_from_zero = false;
552 <        
553 <        // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
554 <        // when trying to map a too big chunk of memory starting at address 0
555 < #if defined(OS_solaris) || defined(OS_netbsd) || defined(PAGEZERO_HACK)
556 <        const bool can_map_all_memory = false;
469 < #else
552 >
553 >        // Make sure to map RAM & ROM at address 0 only on platforms that
554 >        // supports linker scripts to relocate the Basilisk II executable
555 >        // above 0x70000000
556 > #if HAVE_LINKER_SCRIPT
557          const bool can_map_all_memory = true;
558 + #else
559 +        const bool can_map_all_memory = false;
560   #endif
561          
562          // Try to allocate all memory from 0x0000, if it is not known to crash
563 <        if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
563 >        if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) {
564                  D(bug("Could allocate RAM and ROM from 0x0000\n"));
565                  memory_mapped_from_zero = true;
566          }
567          
568   #ifndef PAGEZERO_HACK
569          // Otherwise, just create the Low Memory area (0x0000..0x2000)
570 <        else if (vm_acquire_fixed(0, 0x2000) == 0) {
570 >        else if (vm_acquire_mac_fixed(0, 0x2000) == 0) {
571                  D(bug("Could allocate the Low Memory globals\n"));
572                  lm_area_mapped = true;
573          }
# Line 501 | Line 590 | int main(int argc, char **argv)
590          else
591   #endif
592          {
593 < #ifdef USE_33BIT_ADDRESSING
594 <                // Speculatively enables 33-bit addressing
506 <                ThirtyThreeBitAddressing = true;
507 < #endif
508 <                RAMBaseHost = (uint8 *)vm_acquire_mac(RAMSize);
509 <                ROMBaseHost = (uint8 *)vm_acquire_mac(0x100000);
510 <                if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
593 >                uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000);
594 >                if (ram_rom_area == VM_MAP_FAILED) {    
595                          ErrorAlert(STR_NO_MEM_ERR);
596                          QuitEmulator();
597                  }
598 +                RAMBaseHost = ram_rom_area;
599 +                ROMBaseHost = RAMBaseHost + RAMSize;
600          }
601  
602   #if USE_SCRATCHMEM_SUBTERFUGE
603          // Allocate scratch memory
604 <        ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
604 >        ScratchMem = (uint8 *)vm_acquire_mac(SCRATCH_MEM_SIZE);
605          if (ScratchMem == VM_MAP_FAILED) {
606                  ErrorAlert(STR_NO_MEM_ERR);
607                  QuitEmulator();
# Line 530 | Line 616 | int main(int argc, char **argv)
616          ROMBaseMac = Host2MacAddr(ROMBaseHost);
617   #endif
618   #if REAL_ADDRESSING
619 <        RAMBaseMac = (uint32)RAMBaseHost;
620 <        ROMBaseMac = (uint32)ROMBaseHost;
619 >        RAMBaseMac = Host2MacAddr(RAMBaseHost);
620 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
621   #endif
622          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
623          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
# Line 545 | Line 631 | int main(int argc, char **argv)
631                  ErrorAlert(STR_NO_ROM_FILE_ERR);
632                  QuitEmulator();
633          }
634 <        printf(GetString(STR_READING_ROM_FILE));
634 >        printf("%s", GetString(STR_READING_ROM_FILE));
635          ROMSize = lseek(rom_fd, 0, SEEK_END);
636          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
637                  ErrorAlert(STR_ROM_SIZE_ERR);
# Line 589 | Line 675 | int main(int argc, char **argv)
675   #endif
676  
677          // Initialize everything
678 <        if (!InitAll())
678 >        if (!InitAll(vmdir))
679                  QuitEmulator();
680          D(bug("Initialization complete\n"));
681  
# Line 652 | Line 738 | int main(int argc, char **argv)
738          sigaction(SIGINT, &sigint_sa, NULL);
739   #endif
740  
741 + #ifndef USE_CPU_EMUL_SERVICES
742   #if defined(HAVE_PTHREADS)
743  
744          // POSIX threads available, start 60Hz thread
# Line 715 | Line 802 | int main(int argc, char **argv)
802          setitimer(ITIMER_REAL, &req, NULL);
803  
804   #endif
805 + #endif
806  
807 < #ifdef HAVE_PTHREADS
807 > #ifdef USE_PTHREADS_SERVICES
808          // Start XPRAM watchdog thread
809          memcpy(last_xpram, XPRAM, XPRAM_SIZE);
810          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
# Line 745 | Line 833 | void QuitEmulator(void)
833          Exit680x0();
834   #endif
835  
836 < #if defined(HAVE_PTHREADS)
836 > #if defined(USE_CPU_EMUL_SERVICES)
837 >        // Show statistics
838 >        uint64 emulated_ticks_end = GetTicks_usec();
839 >        D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n",
840 >                  (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start),
841 >                  emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks));
842 > #elif defined(USE_PTHREADS_SERVICES)
843          // Stop 60Hz thread
844          if (tick_thread_active) {
845                  tick_thread_cancel = true;
# Line 764 | Line 858 | void QuitEmulator(void)
858          setitimer(ITIMER_REAL, &req, NULL);
859   #endif
860  
861 < #ifdef HAVE_PTHREADS
861 > #ifdef USE_PTHREADS_SERVICES
862          // Stop XPRAM watchdog thread
863          if (xpram_thread_active) {
864                  xpram_thread_cancel = true;
# Line 780 | Line 874 | void QuitEmulator(void)
874  
875          // Free ROM/RAM areas
876          if (RAMBaseHost != VM_MAP_FAILED) {
877 <                vm_release(RAMBaseHost, RAMSize);
877 >                vm_release(RAMBaseHost, RAMSize + 0x100000);
878                  RAMBaseHost = NULL;
785        }
786        if (ROMBaseHost != VM_MAP_FAILED) {
787                vm_release(ROMBaseHost, 0x100000);
879                  ROMBaseHost = NULL;
880          }
881  
# Line 817 | Line 908 | void QuitEmulator(void)
908                  XCloseDisplay(x_display);
909   #endif
910  
911 +        // Notify GUI we are about to leave
912 +        if (gui_connection) {
913 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
914 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
915 +        }
916 +
917          exit(0);
918   }
919  
# Line 830 | Line 927 | void FlushCodeCache(void *start, uint32
927   {
928   #if USE_JIT
929      if (UseJIT)
930 <                flush_icache_range((uintptr)start, size);
930 >                flush_icache_range((uint8 *)start, size);
931   #endif
932   #if !EMULATED_68K && defined(__NetBSD__)
933          m68k_sync_icache(start, size);
# Line 851 | Line 948 | static void sigint_handler(...)
948          m68k_dumpstate(&nextpc);
949   #endif
950          VideoQuitFullScreen();
951 <        char *arg[4] = {"mon", "-m", "-r", NULL};
951 >        const char *arg[4] = {"mon", "-m", "-r", NULL};
952          mon(3, arg);
953          QuitEmulator();
954   }
# Line 1021 | Line 1118 | static void xpram_watchdog(void)
1118          }
1119   }
1120  
1121 < #ifdef HAVE_PTHREADS
1121 > #ifdef USE_PTHREADS_SERVICES
1122   static void *xpram_func(void *arg)
1123   {
1124          while (!xpram_thread_cancel) {
# Line 1046 | Line 1143 | static void one_second(void)
1143          SetInterruptFlag(INTFLAG_1HZ);
1144          TriggerInterrupt();
1145  
1146 < #ifndef HAVE_PTHREADS
1146 > #ifndef USE_PTHREADS_SERVICES
1147          static int second_counter = 0;
1148          if (++second_counter > 60) {
1149                  second_counter = 0;
# Line 1063 | Line 1160 | static void one_tick(...)
1160                  one_second();
1161          }
1162  
1163 < #if !defined(HAVE_PTHREADS) && !defined(USE_SDL_VIDEO)
1164 <        // No threads available, perform video refresh and networking from here
1163 > #ifndef USE_PTHREADS_SERVICES
1164 >        // Threads not used to trigger interrupts, perform video refresh from here
1165          VideoRefresh();
1166 + #endif
1167 +
1168 + #ifndef HAVE_PTHREADS
1169 +        // No threads available, perform networking from here
1170          SetInterruptFlag(INTFLAG_ETHER);
1171   #endif
1172  
# Line 1076 | Line 1177 | static void one_tick(...)
1177          }
1178   }
1179  
1180 < #ifdef HAVE_PTHREADS
1180 > #ifdef USE_PTHREADS_SERVICES
1181   static void *tick_func(void *arg)
1182   {
1183          uint64 start = GetTicks_usec();
# Line 1093 | Line 1194 | static void *tick_func(void *arg)
1194                  ticks++;
1195          }
1196          uint64 end = GetTicks_usec();
1197 <        D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1197 >        D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1198          return NULL;
1199   }
1200   #endif
# Line 1453 | Line 1554 | void display_alert(int title_id, int pre
1554  
1555   void ErrorAlert(const char *text)
1556   {
1557 +        if (gui_connection) {
1558 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1559 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1560 +                        return;
1561 +        }
1562   #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1563          if (PrefsFindBool("nogui") || x_display == NULL) {
1564                  printf(GetString(STR_SHELL_ERROR_PREFIX), text);
# Line 1472 | Line 1578 | void ErrorAlert(const char *text)
1578  
1579   void WarningAlert(const char *text)
1580   {
1581 +        if (gui_connection) {
1582 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1583 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1584 +                        return;
1585 +        }
1586   #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1587          if (PrefsFindBool("nogui") || x_display == NULL) {
1588                  printf(GetString(STR_SHELL_WARNING_PREFIX), text);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines