From 08a15ff00b32e55a2e93a784e2cdfc6c67602212 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Tue, 30 Nov 2004 23:40:24 +0000 Subject: [PATCH] fully native (no cygwin dep) version of main_windows.cpp --- BasiliskII/src/Windows/main_windows.cpp | 694 ++++++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100755 BasiliskII/src/Windows/main_windows.cpp diff --git a/BasiliskII/src/Windows/main_windows.cpp b/BasiliskII/src/Windows/main_windows.cpp new file mode 100755 index 00000000..07bd7e82 --- /dev/null +++ b/BasiliskII/src/Windows/main_windows.cpp @@ -0,0 +1,694 @@ +/* + * main_windows.cpp - Startup code for Windows + * + * Basilisk II (C) 1997-2004 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +using std::string; + +#include "cpu_emulation.h" +#include "sys.h" +#include "rom_patches.h" +#include "xpram.h" +#include "timer.h" +#include "video.h" +#include "emul_op.h" +#include "prefs.h" +#include "prefs_editor.h" +#include "macos_util.h" +#include "user_strings.h" +#include "version.h" +#include "main.h" +#include "vm_alloc.h" +#include "sigsegv.h" + +#if USE_JIT +extern void flush_icache_range(uint32 start, uint32 size); // from compemu_support.cpp +#endif + +#ifdef ENABLE_MON +# include "mon.h" +#endif + +#define DEBUG 0 +#include "debug.h" + + +// Constants +const char ROM_FILE_NAME[] = "ROM"; +const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area + + +// CPU and FPU type, addressing mode +int CPUType; +bool CPUIs68060; +int FPUType; +bool TwentyFourBitAddressing; +bool ThirtyThreeBitAddressing = false; + + +// Global variables +static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes + +static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed +static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread +static SDL_Thread *xpram_thread = NULL; // XPRAM watchdog + +static bool tick_thread_active = false; // Flag: 60Hz thread installed +static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread +static SDL_Thread *tick_thread; // 60Hz thread + +static SDL_mutex *intflag_lock = NULL; // Mutex to protect InterruptFlags +#define LOCK_INTFLAGS SDL_LockMutex(intflag_lock) +#define UNLOCK_INTFLAGS SDL_UnlockMutex(intflag_lock) + +#if USE_SCRATCHMEM_SUBTERFUGE +uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes +#endif + +#if REAL_ADDRESSING +static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped +#endif + + +// Prototypes +static int xpram_func(void *arg); +static int tick_func(void *arg); +static void one_tick(...); + + +/* + * Ersatz functions + */ + +extern "C" { + +#ifndef HAVE_STRDUP +char *strdup(const char *s) +{ + char *n = (char *)malloc(strlen(s) + 1); + strcpy(n, s); + return n; +} +#endif + +} + + +/* + * Map memory that can be accessed from the Mac side + */ + +void *vm_acquire_mac(size_t size) +{ + void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT); + if (m == NULL) { + ThirtyThreeBitAddressing = false; + m = vm_acquire(size); + } + return m; +} + + +/* + * SIGSEGV handler + */ + +static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction) +{ +#if ENABLE_VOSF + // Handle screen fault + extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t); + if (Screen_fault_handler(fault_address, fault_instruction)) + return SIGSEGV_RETURN_SUCCESS; +#endif + +#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION + // Ignore writes to ROM + if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + + // Ignore all other faults, if requested + if (PrefsFindBool("ignoresegv")) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; +#endif + + return SIGSEGV_RETURN_FAILURE; +} + +/* + * Dump state when everything went wrong after a SEGV + */ + +static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction) +{ + fprintf(stderr, "Caught SIGSEGV at address %p", fault_address); + if (fault_instruction != SIGSEGV_INVALID_PC) + fprintf(stderr, " [IP=%p]", fault_instruction); + fprintf(stderr, "\n"); + uaecptr nextpc; + extern void m68k_dumpstate(uaecptr *nextpc); + m68k_dumpstate(&nextpc); +#if USE_JIT && JIT_DEBUG + extern void compiler_dumpstate(void); + compiler_dumpstate(); +#endif + VideoQuitFullScreen(); +#ifdef ENABLE_MON + char *arg[4] = {"mon", "-m", "-r", NULL}; + mon(3, arg); + QuitEmulator(); +#endif +} + + +/* + * Main program + */ + +static void usage(const char *prg_name) +{ + printf( + "Usage: %s [OPTION...]\n" + "\nUnix options:\n" + " --config FILE\n read/write configuration from/to FILE\n" + " --display STRING\n X display to use\n" + " --break ADDRESS\n set ROM breakpoint\n" + " --rominfo\n dump ROM information\n", prg_name + ); + LoadPrefs(); // read the prefs file so PrefsPrintUsage() will print the correct default values + PrefsPrintUsage(); + exit(0); +} + +int main(int argc, char **argv) +{ + char str[256]; + + // Initialize variables + RAMBaseHost = NULL; + ROMBaseHost = NULL; + srand(time(NULL)); + tzset(); + + // Print some info + printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); + printf(" %s\n", GetString(STR_ABOUT_TEXT2)); + + // Parse command line arguments + for (int i=1; i i) { + k -= i; + for (int j=i+k; jm); +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ + if (mutex) + SDL_UnlockMutex(mutex->m); +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + + +/* + * Interrupt flags (must be handled atomically!) + */ + +uint32 InterruptFlags = 0; + +void SetInterruptFlag(uint32 flag) +{ + LOCK_INTFLAGS; + InterruptFlags |= flag; + UNLOCK_INTFLAGS; +} + +void ClearInterruptFlag(uint32 flag) +{ + LOCK_INTFLAGS; + InterruptFlags &= ~flag; + UNLOCK_INTFLAGS; +} + + +/* + * XPRAM watchdog thread (saves XPRAM every minute) + */ + +static void xpram_watchdog(void) +{ + if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { + memcpy(last_xpram, XPRAM, XPRAM_SIZE); + SaveXPRAM(); + } +} + +static int xpram_func(void *arg) +{ + while (!xpram_thread_cancel) { + for (int i=0; i<60 && !xpram_thread_cancel; i++) + Delay_usec(999999); // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true + xpram_watchdog(); + } + return 0; +} + + +/* + * 60Hz thread (really 60.15Hz) + */ + +static void one_second(void) +{ + // Pseudo Mac 1Hz interrupt, update local time + WriteMacInt32(0x20c, TimerDateTime()); + + SetInterruptFlag(INTFLAG_1HZ); + TriggerInterrupt(); +} + +static void one_tick(...) +{ + static int tick_counter = 0; + if (++tick_counter > 60) { + tick_counter = 0; + one_second(); + } + + // Trigger 60Hz interrupt + if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) { + SetInterruptFlag(INTFLAG_60HZ); + TriggerInterrupt(); + } +} + +static int tick_func(void *arg) +{ + uint64 start = GetTicks_usec(); + int64 ticks = 0; + uint64 next = GetTicks_usec(); + while (!tick_thread_cancel) { + one_tick(); + next += 16625; + int64 delay = next - GetTicks_usec(); + if (delay > 0) + Delay_usec(delay); + else if (delay < -16625) + next = GetTicks_usec(); + ticks++; + } + uint64 end = GetTicks_usec(); + D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); + return 0; +} + + +/* + * Display alert + */ + +#ifdef ENABLE_GTK +static void dl_destroyed(void) +{ + gtk_main_quit(); +} + +static void dl_quit(GtkWidget *dialog) +{ + gtk_widget_destroy(dialog); +} + +void display_alert(int title_id, int prefix_id, int button_id, const char *text) +{ + char str[256]; + sprintf(str, GetString(prefix_id), text); + + GtkWidget *dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id)); + gtk_container_border_width(GTK_CONTAINER(dialog), 5); + gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); + gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL); + + GtkWidget *label = gtk_label_new(str); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); + + GtkWidget *button = gtk_button_new_with_label(GetString(button_id)); + gtk_widget_show(button); + gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); + gtk_widget_grab_default(button); + gtk_widget_show(dialog); + + gtk_main(); +} +#endif + + +/* + * Display error alert + */ + +void ErrorAlert(const char *text) +{ +#if 0 + // TODO: Windows message box + if (PrefsFindBool("nogui")) { + printf(GetString(STR_SHELL_ERROR_PREFIX), text); + return; + } + VideoQuitFullScreen(); + display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text); +#else + printf(GetString(STR_SHELL_ERROR_PREFIX), text); +#endif +} + + +/* + * Display warning alert + */ + +void WarningAlert(const char *text) +{ +#if 0 + // TODO: Windows message box + if (PrefsFindBool("nogui")) { + printf(GetString(STR_SHELL_WARNING_PREFIX), text); + return; + } + display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text); +#else + printf(GetString(STR_SHELL_WARNING_PREFIX), text); +#endif +} + + +/* + * Display choice alert + */ + +bool ChoiceAlert(const char *text, const char *pos, const char *neg) +{ + printf(GetString(STR_SHELL_WARNING_PREFIX), text); + return false; //!! +}