mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 19:29:18 +00:00
- 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)
This commit is contained in:
parent
6aff4fb327
commit
cf22cb032a
@ -3,8 +3,12 @@ V1.0 (snapshot) - <date>
|
||||
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
|
||||
|
@ -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!)
|
||||
*/
|
||||
|
@ -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!)
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user