From cf22cb032afb155d5bb91b8bde7b55a2c0442c52 Mon Sep 17 00:00:00 2001 From: cebix <> Date: Tue, 3 Jul 2001 15:59:49 +0000 Subject: [PATCH] - added support for platform-independant mutexes, currently only properly implemented under Unix - adb.cpp uses mutexes for thread-safe mouse handling - video_x.cpp: pressing Ctrl-F5 in windowed mode switches to a "grabbed" relative mouse mode, useful for some games - video_x.cpp: fixed some bugs relating to the hotkeys (key releases are no longer treated as hotkeys) --- BasiliskII/ChangeLog | 4 + BasiliskII/src/AmigaOS/main_amiga.cpp | 27 ++++ BasiliskII/src/BeOS/main_beos.cpp | 27 ++++ BasiliskII/src/BeOS/sysdeps.h | 2 - BasiliskII/src/Unix/main_unix.cpp | 87 +++++++++-- BasiliskII/src/Unix/sysdeps.h | 2 - BasiliskII/src/Unix/user_strings_unix.cpp | 2 + BasiliskII/src/Unix/user_strings_unix.h | 4 +- BasiliskII/src/Unix/video_vosf.h | 1 + BasiliskII/src/Unix/video_x.cpp | 181 +++++++++++++++++----- BasiliskII/src/adb.cpp | 76 ++++++--- BasiliskII/src/emul_op.cpp | 1 + BasiliskII/src/include/adb.h | 3 + BasiliskII/src/include/main.h | 7 + BasiliskII/src/main.cpp | 7 + 15 files changed, 356 insertions(+), 75 deletions(-) diff --git a/BasiliskII/ChangeLog b/BasiliskII/ChangeLog index 61afa6fe..04c6e778 100644 --- a/BasiliskII/ChangeLog +++ b/BasiliskII/ChangeLog @@ -3,8 +3,12 @@ V1.0 (snapshot) - and gamma tables - fsave/frestore emulation under AmigaOS and NetBSD/m68k always behaves like a 68882/68040 FPU, eliminating the need for 68060 FPU patches + - added support for platform-independant mutexes, used by adb.cpp for + thread-safe mouse handling - Unix: windowed display mode supports different resolutions and color depth, which can be switched on-the-fly + - Unix: Ctrl-F5 grabs mouse in windowed mode (enhanced compatibility + with games like flight simulators) V0.9 (release 0.9-1) - 31.May 2001 - final adjustments for 0.9 release diff --git a/BasiliskII/src/AmigaOS/main_amiga.cpp b/BasiliskII/src/AmigaOS/main_amiga.cpp index 48f48ab8..2955e041 100644 --- a/BasiliskII/src/AmigaOS/main_amiga.cpp +++ b/BasiliskII/src/AmigaOS/main_amiga.cpp @@ -471,6 +471,33 @@ void FlushCodeCache(void *start, uint32 size) } +/* + * Mutexes + */ + +struct B2_mutex { + int dummy; //!! +}; + +B2_mutex *B2_create_mutex(void) +{ + return new B2_mutex; +} + +void B2_lock_mutex(B2_mutex *mutex) +{ +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + + /* * Interrupt flags (must be handled atomically!) */ diff --git a/BasiliskII/src/BeOS/main_beos.cpp b/BasiliskII/src/BeOS/main_beos.cpp index 818dfef2..bb46595a 100644 --- a/BasiliskII/src/BeOS/main_beos.cpp +++ b/BasiliskII/src/BeOS/main_beos.cpp @@ -468,6 +468,33 @@ void FlushCodeCache(void *start, uint32 size) } +/* + * Mutexes + */ + +struct B2_mutex { + int dummy; //!! +}; + +B2_mutex *B2_create_mutex(void) +{ + return new B2_mutex; +} + +void B2_lock_mutex(B2_mutex *mutex) +{ +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + + /* * Interrupt flags (must be handled atomically!) */ diff --git a/BasiliskII/src/BeOS/sysdeps.h b/BasiliskII/src/BeOS/sysdeps.h index ca8a9bf5..b7c0747d 100644 --- a/BasiliskII/src/BeOS/sysdeps.h +++ b/BasiliskII/src/BeOS/sysdeps.h @@ -124,8 +124,6 @@ static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {*a = v;} #define call_mem_put_func(func, addr, v) ((*func)(addr, v)) #define __inline__ inline #define CPU_EMU_SIZE 0 -#undef USE_MAPPED_MEMORY -#undef CAN_MAP_MEMORY #undef NO_INLINE_MEMORY_ACCESS #undef MD_HAVE_MEM_1_FUNCS #undef USE_COMPILER diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index fa42ac19..36c35cad 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -123,9 +123,15 @@ static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread static pthread_t tick_thread; // 60Hz thread static pthread_attr_t tick_thread_attr; // 60Hz thread attributes -#if EMULATED_68K static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags -#endif +#define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock) +#define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock) + +#else + +#define LOCK_INTFLAGS +#define UNLOCK_INTFLAGS + #endif #if !EMULATED_68K @@ -668,6 +674,7 @@ static void sigint_handler(...) extern void m68k_dumpstate(uaecptr *nextpc); m68k_dumpstate(&nextpc); #endif + VideoQuitFullScreen(); char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); QuitEmulator(); @@ -675,6 +682,65 @@ static void sigint_handler(...) #endif +/* + * Mutexes + */ + +#ifdef HAVE_PTHREADS + +struct B2_mutex { + B2_mutex() { pthread_mutex_init(&m, NULL); } + ~B2_mutex() { pthread_mutex_unlock(&m); pthread_mutex_destroy(&m); } + pthread_mutex_t m; +}; + +B2_mutex *B2_create_mutex(void) +{ + return new B2_mutex; +} + +void B2_lock_mutex(B2_mutex *mutex) +{ + pthread_mutex_lock(&mutex->m); +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ + pthread_mutex_unlock(&mutex->m); +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + +#else + +struct B2_mutex { + int dummy; +}; + +B2_mutex *B2_create_mutex(void) +{ + return new B2_mutex; +} + +void B2_lock_mutex(B2_mutex *mutex) +{ +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + +#endif + + /* * Interrupt flags (must be handled atomically!) */ @@ -684,24 +750,16 @@ uint32 InterruptFlags = 0; #if EMULATED_68K void SetInterruptFlag(uint32 flag) { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&intflag_lock); + LOCK_INTFLAGS; InterruptFlags |= flag; - pthread_mutex_unlock(&intflag_lock); -#else - InterruptFlags |= flag; // Pray that this is an atomic operation... -#endif + UNLOCK_INTFLAGS; } void ClearInterruptFlag(uint32 flag) { -#ifdef HAVE_PTHREADS - pthread_mutex_lock(&intflag_lock); + LOCK_INTFLAGS; InterruptFlags &= ~flag; - pthread_mutex_unlock(&intflag_lock); -#else - InterruptFlags &= ~flag; -#endif + UNLOCK_INTFLAGS; } #endif @@ -1197,6 +1255,7 @@ ill: printf("SIGILL num %d, code %d\n", sig, code); for (int i=0; i<8; i++) printf(" a%d %08x\n", i, state->ss_frame.f_regs[i+8]); + VideoQuitFullScreen(); #ifdef ENABLE_MON char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 61a8a645..9e93936b 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -288,8 +288,6 @@ static inline uae_u32 do_byteswap_16(uae_u32 v) #define ENUMDECL typedef enum #define ENUMNAME(name) name #define write_log printf -#undef USE_MAPPED_MEMORY -#undef CAN_MAP_MEMORY #ifdef X86_ASSEMBLY #define ASM_SYM_FOR_FUNC(a) __asm__(a) diff --git a/BasiliskII/src/Unix/user_strings_unix.cpp b/BasiliskII/src/Unix/user_strings_unix.cpp index cfafdaa4..fb61b135 100644 --- a/BasiliskII/src/Unix/user_strings_unix.cpp +++ b/BasiliskII/src/Unix/user_strings_unix.cpp @@ -75,6 +75,8 @@ user_string_def platform_strings[] = { {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, {STR_MOUSEWHEELLINES_CTRL, "Lines To Scroll"}, + {STR_WINDOW_TITLE_GRABBED, "Basilisk II (mouse grabbed, press Ctrl-F5 to release)"}, + {-1, NULL} // End marker }; diff --git a/BasiliskII/src/Unix/user_strings_unix.h b/BasiliskII/src/Unix/user_strings_unix.h index a69db4d7..4d93c7c9 100644 --- a/BasiliskII/src/Unix/user_strings_unix.h +++ b/BasiliskII/src/Unix/user_strings_unix.h @@ -64,7 +64,9 @@ enum { STR_MOUSEWHEELMODE_CTRL, STR_MOUSEWHEELMODE_PAGE_LAB, STR_MOUSEWHEELMODE_CURSOR_LAB, - STR_MOUSEWHEELLINES_CTRL + STR_MOUSEWHEELLINES_CTRL, + + STR_WINDOW_TITLE_GRABBED }; #endif diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index 04d2d144..0038126d 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -265,6 +265,7 @@ static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_addres extern void m68k_dumpstate(uaecptr *nextpc); m68k_dumpstate(&nextpc); #endif + VideoQuitFullScreen(); #ifdef ENABLE_MON char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index e5b474ed..43f0af41 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -24,6 +24,7 @@ * Ctrl-Tab = suspend DGA mode * Ctrl-Esc = emergency quit * Ctrl-F1 = mount floppy + * Ctrl-F5 = grab mouse (in windowed mode) */ #include "sysdeps.h" @@ -73,7 +74,7 @@ enum { // Constants const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; -static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask; +static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | StructureNotifyMask; static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask; @@ -322,6 +323,11 @@ public: virtual void update_palette(void); virtual void suspend(void) {} virtual void resume(void) {} + virtual void toggle_mouse_grab(void) {} + virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); } + + virtual void grab_mouse(void) {} + virtual void ungrab_mouse(void) {} public: bool init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer) @@ -342,12 +348,20 @@ public: driver_window(const video_mode &mode); ~driver_window(); + void toggle_mouse_grab(void); + void mouse_moved(int x, int y); + + void grab_mouse(void); + void ungrab_mouse(void); + private: GC gc; XImage *img; - bool have_shm; // Flag: SHM extensions available + bool have_shm; // Flag: SHM extensions available XShmSegmentInfo shminfo; Cursor mac_cursor; + bool mouse_grabbed; // Flag: mouse pointer grabbed, using relative mouse mode + int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode) }; static driver_base *drv = NULL; // Pointer to currently used driver object @@ -365,6 +379,8 @@ driver_base::driver_base() driver_base::~driver_base() { + ungrab_mouse(); + if (w) { XUnmapWindow(x_display, w); wait_unmapped(w); @@ -421,14 +437,14 @@ void driver_base::update_palette(void) // Open display driver_window::driver_window(const video_mode &mode) - : gc(0), img(NULL), have_shm(false), mac_cursor(0) + : gc(0), img(NULL), have_shm(false), mouse_grabbed(false), mac_cursor(0) { int width = mode.x, height = mode.y; int aligned_width = (width + 15) & ~15; int aligned_height = (height + 15) & ~15; // Set absolute mouse mode - ADBSetRelMouseMode(false); + ADBSetRelMouseMode(mouse_grabbed); // Create window XSetWindowAttributes wattr; @@ -561,6 +577,84 @@ driver_window::~driver_window() XFreeGC(x_display, gc); } +// Toggle mouse grab +void driver_window::toggle_mouse_grab(void) +{ + if (mouse_grabbed) + ungrab_mouse(); + else + grab_mouse(); +} + +// Grab mouse, switch to relative mouse mode +void driver_window::grab_mouse(void) +{ + int result; + for (int i=0; i<10; i++) { + result = XGrabPointer(x_display, w, True, 0, + GrabModeAsync, GrabModeAsync, w, None, CurrentTime); + if (result != AlreadyGrabbed) + break; + Delay_usec(100000); + } + if (result == GrabSuccess) { + ADBSetRelMouseMode(mouse_grabbed = true); + XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED)); + XSync(x_display, false); + } +} + +// Ungrab mouse, switch to absolute mouse mode +void driver_window::ungrab_mouse(void) +{ + if (mouse_grabbed) { + XUngrabPointer(x_display, CurrentTime); + XStoreName(x_display, w, GetString(STR_WINDOW_TITLE)); + ADBSetRelMouseMode(mouse_grabbed = false); + } +} + +// Mouse moved +void driver_window::mouse_moved(int x, int y) +{ + if (!mouse_grabbed) { + mouse_last_x = x; mouse_last_y = y; + ADBMouseMoved(x, y); + return; + } + + // Warped mouse motion (this code is taken from SDL) + + // Post first mouse event + int width = VideoMonitor.mode.x, height = VideoMonitor.mode.y; + int delta_x = x - mouse_last_x, delta_y = y - mouse_last_y; + mouse_last_x = x; mouse_last_y = y; + ADBMouseMoved(delta_x, delta_y); + + // Only warp the pointer when it has reached the edge + const int MOUSE_FUDGE_FACTOR = 8; + if (x < MOUSE_FUDGE_FACTOR || x > (width - MOUSE_FUDGE_FACTOR) + || y < MOUSE_FUDGE_FACTOR || y > (height - MOUSE_FUDGE_FACTOR)) { + XEvent event; + while (XCheckTypedEvent(x_display, MotionNotify, &event)) { + delta_x = x - mouse_last_x; delta_y = y - mouse_last_y; + mouse_last_x = x; mouse_last_y = y; + ADBMouseMoved(delta_x, delta_y); + } + mouse_last_x = width/2; + mouse_last_y = height/2; + XWarpPointer(x_display, None, w, 0, 0, 0, 0, mouse_last_x, mouse_last_y); + for (int i=0; i<10; i++) { + XMaskEvent(x_display, PointerMotionMask, &event); + if (event.xmotion.x > (mouse_last_x - MOUSE_FUDGE_FACTOR) + && event.xmotion.x < (mouse_last_x + MOUSE_FUDGE_FACTOR) + && event.xmotion.y > (mouse_last_y - MOUSE_FUDGE_FACTOR) + && event.xmotion.y < (mouse_last_y + MOUSE_FUDGE_FACTOR)) + break; + } + } +} + #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA) /* @@ -639,8 +733,8 @@ void driver_dga::resume(void) XMapRaised(x_display, w); wait_mapped(w); XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0); - XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); #ifdef ENABLE_XF86_DGA XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse); XF86DGASetViewPort(x_display, screen, 0, 0); @@ -1465,7 +1559,7 @@ void video_set_palette(uint8 *pal, int num_in) // Recalculate pixel color expansion map if (!IsDirectMode(VideoMonitor.mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) { for (int i=0; i<256; i++) { - int c = i % num_in; // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier) + int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier) ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]); } @@ -1502,10 +1596,11 @@ void video_switch_to_mode(const video_mode &mode) /* - * Translate key event to Mac keycode + * Translate key event to Mac keycode, returns -1 if no keycode was found + * and -2 if the key was recognized as a hotkey */ -static int kc_decode(KeySym ks) +static int kc_decode(KeySym ks, bool key_down) { switch (ks) { case XK_A: case XK_a: return 0x00; @@ -1558,11 +1653,7 @@ static int kc_decode(KeySym ks) case XK_period: case XK_greater: return 0x2f; case XK_slash: case XK_question: return 0x2c; -#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA) - case XK_Tab: if (ctrl_down) {drv->suspend(); return -1;} else return 0x30; -#else - case XK_Tab: return 0x30; -#endif + case XK_Tab: if (ctrl_down) {if (key_down) drv->suspend(); return -2;} else return 0x30; case XK_Return: return 0x24; case XK_space: return 0x31; case XK_BackSpace: return 0x33; @@ -1596,13 +1687,13 @@ static int kc_decode(KeySym ks) case XK_Left: return 0x3b; case XK_Right: return 0x3c; - case XK_Escape: if (ctrl_down) {quit_full_screen = true; emerg_quit = true; return -1;} else return 0x35; + case XK_Escape: if (ctrl_down) {if (key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35; - case XK_F1: if (ctrl_down) {SysMountFirstFloppy(); return -1;} else return 0x7a; + case XK_F1: if (ctrl_down) {if (key_down) SysMountFirstFloppy(); return -2;} else return 0x7a; case XK_F2: return 0x78; case XK_F3: return 0x63; case XK_F4: return 0x76; - case XK_F5: return 0x60; + case XK_F5: if (ctrl_down) {if (key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60; case XK_F6: return 0x61; case XK_F7: return 0x62; case XK_F8: return 0x64; @@ -1650,16 +1741,17 @@ static int kc_decode(KeySym ks) return -1; } -static int event2keycode(XKeyEvent &ev) +static int event2keycode(XKeyEvent &ev, bool key_down) { KeySym ks; - int as; int i = 0; do { ks = XLookupKeysym(&ev, i++); - as = kc_decode(ks); - if (as != -1) + int as = kc_decode(ks, key_down); + if (as >= 0) + return as; + if (as == -2) return as; } while (ks != NoSymbol); @@ -1706,20 +1798,19 @@ static void handle_events(void) } // Mouse moved - case EnterNotify: case MotionNotify: - ADBMouseMoved(event.xmotion.x, event.xmotion.y); + drv->mouse_moved(event.xmotion.x, event.xmotion.y); break; // Keyboard case KeyPress: { - int code; + int code = -1; if (use_keycodes) { - event2keycode(event.xkey); // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; + if (event2keycode(event.xkey, true) != -2) // This is called to process the hotkeys + code = keycode_table[event.xkey.keycode & 0xff]; } else - code = event2keycode(event.xkey); - if (code != -1) { + code = event2keycode(event.xkey, true); + if (code >= 0) { if (!emul_suspended) { if (code == 0x39) { // Caps Lock pressed if (caps_on) { @@ -1741,13 +1832,13 @@ static void handle_events(void) break; } case KeyRelease: { - int code; + int code = -1; if (use_keycodes) { - event2keycode(event.xkey); // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; + if (event2keycode(event.xkey, false) != -2) // This is called to process the hotkeys + code = keycode_table[event.xkey.keycode & 0xff]; } else - code = event2keycode(event.xkey); - if (code != -1 && code != 0x39) { // Don't propagate Caps Lock releases + code = event2keycode(event.xkey, false); + if (code >= 0 && code != 0x39) { // Don't propagate Caps Lock releases ADBKeyUp(code); if (code == 0x36) ctrl_down = false; @@ -2011,7 +2102,8 @@ static void update_display_static(driver_window *drv) static inline void possibly_quit_dga_mode() { - // Quit DGA mode if requested + // Quit DGA mode if requested (something terrible has happened and we + // want to give control back to the user) if (quit_full_screen) { quit_full_screen = false; delete drv; @@ -2019,6 +2111,17 @@ static inline void possibly_quit_dga_mode() } } +static inline void possibly_ungrab_mouse() +{ + // Ungrab mouse if requested (something terrible has happened and we + // want to give control back to the user) + if (quit_full_screen) { + quit_full_screen = false; + if (drv) + drv->ungrab_mouse(); + } +} + static inline void handle_palette_changes(void) { LOCK_PALETTE; @@ -2071,8 +2174,8 @@ static void video_refresh_dga_vosf(void) static void video_refresh_window_vosf(void) { - // Quit DGA mode if requested - possibly_quit_dga_mode(); + // Ungrab mouse if requested + possibly_ungrab_mouse(); // Handle X events handle_events(); @@ -2096,6 +2199,9 @@ static void video_refresh_window_vosf(void) static void video_refresh_window_static(void) { + // Ungrab mouse if requested + possibly_ungrab_mouse(); + // Handle X events handle_events(); @@ -2112,6 +2218,9 @@ static void video_refresh_window_static(void) static void video_refresh_window_dynamic(void) { + // Ungrab mouse if requested + possibly_ungrab_mouse(); + // Handle X events handle_events(); diff --git a/BasiliskII/src/adb.cpp b/BasiliskII/src/adb.cpp index d1e1d96e..ba7ab147 100644 --- a/BasiliskII/src/adb.cpp +++ b/BasiliskII/src/adb.cpp @@ -57,6 +57,32 @@ static uint8 mouse_reg_3[2] = {0x63, 0x01}; // Mouse ADB register 3 static uint8 key_reg_2[2] = {0xff, 0xff}; // Keyboard ADB register 2 static uint8 key_reg_3[2] = {0x62, 0x05}; // Keyboard ADB register 3 +// ADB mouse input state lock (for platforms that use separate input thread) +static B2_mutex *mouse_lock; + + +/* + * Initialize ADB emulation + */ + +void ADBInit(void) +{ + mouse_lock = B2_create_mutex(); +} + + +/* + * Exit ADB emulation + */ + +void ADBExit(void) +{ + if (mouse_lock) { + B2_delete_mutex(mouse_lock); + mouse_lock = NULL; + } +} + /* * ADBOp() replacement @@ -198,11 +224,13 @@ void ADBOp(uint8 op, uint8 *data) void ADBMouseMoved(int x, int y) { + B2_lock_mutex(mouse_lock); if (relative_mouse) { mouse_x += x; mouse_y += y; } else { mouse_x = x; mouse_y = y; } + B2_unlock_mutex(mouse_lock); } @@ -212,7 +240,9 @@ void ADBMouseMoved(int x, int y) void ADBMouseDown(int button) { + B2_lock_mutex(mouse_lock); mouse_button[button] = true; + B2_unlock_mutex(mouse_lock); } @@ -222,7 +252,9 @@ void ADBMouseDown(int button) void ADBMouseUp(int button) { + B2_lock_mutex(mouse_lock); mouse_button[button] = false; + B2_unlock_mutex(mouse_lock); } @@ -280,9 +312,14 @@ void ADBInterrupt(void) return; uint32 tmp_data = adb_base + 0x163; // Temporary storage for faked ADB data - // Get position so that it won't change during processing + // Get mouse state + B2_lock_mutex(mouse_lock); int mx = mouse_x; int my = mouse_y; + if (relative_mouse) + mouse_x = mouse_y = 0; + int mb[3] = {mouse_button[0], mouse_button[1], mouse_button[2]}; + B2_unlock_mutex(mouse_lock); uint32 key_base = adb_base + 4; uint32 mouse_base = adb_base + 16; @@ -290,20 +327,20 @@ void ADBInterrupt(void) if (relative_mouse) { // Mouse movement (relative) and buttons - if (mx != 0 || my != 0 || mouse_button[0] != old_mouse_button[0] || mouse_button[1] != old_mouse_button[1] || mouse_button[2] != old_mouse_button[2]) { + if (mx != 0 || my != 0 || mb[0] != old_mouse_button[0] || mb[1] != old_mouse_button[1] || mb[2] != old_mouse_button[2]) { // Call mouse ADB handler if (mouse_reg_3[1] == 4) { // Extended mouse protocol WriteMacInt8(tmp_data, 3); - WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80)); - WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80)); - WriteMacInt8(tmp_data + 3, ((my >> 3) & 0x70) | ((mx >> 7) & 0x07) | (mouse_button[2] ? 0x08 : 0x88)); + WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mb[0] ? 0 : 0x80)); + WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mb[1] ? 0 : 0x80)); + WriteMacInt8(tmp_data + 3, ((my >> 3) & 0x70) | ((mx >> 7) & 0x07) | (mb[2] ? 0x08 : 0x88)); } else { // 100/200 dpi mode WriteMacInt8(tmp_data, 2); - WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80)); - WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80)); + WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mb[0] ? 0 : 0x80)); + WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mb[1] ? 0 : 0x80)); } r.a[0] = tmp_data; r.a[1] = ReadMacInt32(mouse_base); @@ -312,10 +349,9 @@ void ADBInterrupt(void) r.d[0] = (mouse_reg_3[0] << 4) | 0x0c; // Talk 0 Execute68k(r.a[1], &r); - mouse_x = mouse_y = 0; - old_mouse_button[0] = mouse_button[0]; - old_mouse_button[1] = mouse_button[1]; - old_mouse_button[2] = mouse_button[2]; + old_mouse_button[0] = mb[0]; + old_mouse_button[1] = mb[1]; + old_mouse_button[2] = mb[2]; } } else { @@ -347,21 +383,21 @@ void ADBInterrupt(void) } // Send mouse button events - if (mouse_button[0] != old_mouse_button[0]) { + if (mb[0] != old_mouse_button[0] || mb[1] != old_mouse_button[1] || mb[2] != old_mouse_button[2]) { uint32 mouse_base = adb_base + 16; // Call mouse ADB handler if (mouse_reg_3[1] == 4) { // Extended mouse protocol WriteMacInt8(tmp_data, 3); - WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80); - WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80); - WriteMacInt8(tmp_data + 3, mouse_button[2] ? 0x08 : 0x88); + WriteMacInt8(tmp_data + 1, mb[0] ? 0 : 0x80); + WriteMacInt8(tmp_data + 2, mb[1] ? 0 : 0x80); + WriteMacInt8(tmp_data + 3, mb[2] ? 0x08 : 0x88); } else { // 100/200 dpi mode WriteMacInt8(tmp_data, 2); - WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80); - WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80); + WriteMacInt8(tmp_data + 1, mb[0] ? 0 : 0x80); + WriteMacInt8(tmp_data + 2, mb[1] ? 0 : 0x80); } r.a[0] = tmp_data; r.a[1] = ReadMacInt32(mouse_base); @@ -370,9 +406,9 @@ void ADBInterrupt(void) r.d[0] = (mouse_reg_3[0] << 4) | 0x0c; // Talk 0 Execute68k(r.a[1], &r); - old_mouse_button[0] = mouse_button[0]; - old_mouse_button[1] = mouse_button[1]; - old_mouse_button[2] = mouse_button[2]; + old_mouse_button[0] = mb[0]; + old_mouse_button[1] = mb[1]; + old_mouse_button[2] = mb[2]; } } diff --git a/BasiliskII/src/emul_op.cpp b/BasiliskII/src/emul_op.cpp index 0419e14e..cb5603f0 100644 --- a/BasiliskII/src/emul_op.cpp +++ b/BasiliskII/src/emul_op.cpp @@ -68,6 +68,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r) r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7], r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7], r->sr); + VideoQuitFullScreen(); #ifdef ENABLE_MON char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); diff --git a/BasiliskII/src/include/adb.h b/BasiliskII/src/include/adb.h index ab49412f..e49d7278 100644 --- a/BasiliskII/src/include/adb.h +++ b/BasiliskII/src/include/adb.h @@ -21,6 +21,9 @@ #ifndef ADB_H #define ADB_H +extern void ADBInit(void); +extern void ADBExit(void); + extern void ADBOp(uint8 op, uint8 *data); extern void ADBMouseMoved(int x, int y); diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index ca96adce..93df6638 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -51,6 +51,13 @@ extern void WarningAlert(const char *text); // Display warning alert extern void WarningAlert(int string_id); extern bool ChoiceAlert(const char *text, const char *pos, const char *neg); // Display choice alert +// Mutexes (non-recursive) +struct B2_mutex; +extern B2_mutex *B2_create_mutex(void); +extern void B2_lock_mutex(B2_mutex *mutex); +extern void B2_unlock_mutex(B2_mutex *mutex); +extern void B2_delete_mutex(B2_mutex *mutex); + // Interrupt flags enum { INTFLAG_60HZ = 1, // 60.15Hz VBL diff --git a/BasiliskII/src/main.cpp b/BasiliskII/src/main.cpp index fb1d3ce0..10ab5398 100644 --- a/BasiliskII/src/main.cpp +++ b/BasiliskII/src/main.cpp @@ -33,6 +33,7 @@ #include "serial.h" #include "ether.h" #include "clip.h" +#include "adb.h" #include "rom_patches.h" #include "user_strings.h" #include "prefs.h" @@ -132,6 +133,9 @@ bool InitAll(void) // Init clipboard ClipInit(); + // Init ADB + ADBInit(); + // Init audio AudioInit(); @@ -188,6 +192,9 @@ void ExitAll(void) // Exit audio AudioExit(); + // Exit ADB + ADBExit(); + // Exit clipboard ClipExit();