Dreamcast mouse emulation

This commit is contained in:
Flyinghead 2018-09-18 09:27:16 +02:00
parent 2081a0c21b
commit 8a2684ff55
7 changed files with 308 additions and 60 deletions

View File

@ -85,8 +85,10 @@ int numberOfControl = cfgLoadInt("players", "nb", 1);
for (int i = 0; i < numberOfControl; i++){
mcfg_Create(MDT_SegaController, i, 5);
}
if (numberOfControl < 4)
mcfg_Create(MDT_Keyboard, numberOfControl, 5);
if (settings.input.DCKeyboard && numberOfControl < 4)
mcfg_Create(MDT_Keyboard, numberOfControl++, 5);
if (settings.input.DCMouse != 0 && numberOfControl < 4)
mcfg_Create(MDT_Mouse, numberOfControl++, 5);
mcfg_Create(MDT_SegaVMU,0,0);
mcfg_Create(MDT_SegaVMU,0,1);

View File

@ -1005,6 +1005,97 @@ struct maple_keyboard : maple_base
}
};
u32 mo_buttons = 0xFFFFFFFF;
f32 mo_x_delta;
f32 mo_y_delta;
f32 mo_wheel_delta;
struct maple_mouse : maple_base
{
static u16 mo_cvt(f32 delta)
{
delta+=0x200;
if (delta<=0)
delta=0;
else if (delta>0x3FF)
delta=0x3FF;
return (u16) delta;
}
virtual u32 dma(u32 cmd)
{
switch (cmd)
{
case MDC_DeviceRequest:
//caps
//4
w32(MFID_9_Mouse);
//struct data
//3*4
w32(0x00060700); // Mouse, 2 buttons, 4 axes
w32(0);
w32(0);
//1 area code
w8(0xFF);
//1 direction
w8(0);
// Product name (30)
for (u32 i = 0; i < 30; i++)
{
w8((u8)maple_sega_mouse_name[i]);
}
// License (60)
for (u32 i = 0; i < 60; i++)
{
w8((u8)maple_sega_brand[i]);
}
// Low-consumption standby current (2)
w16(0x0069);
// Maximum current consumption (2)
w16(0x0120);
return MDRS_DeviceStatus;
case MDCF_GetCondition:
w32(MFID_9_Mouse);
//struct data
//int32 buttons ; digital buttons bitfield (little endian)
w32(mo_buttons);
//int16 axis1 ; horizontal movement (0-$3FF) (little endian)
w16(mo_cvt(mo_x_delta));
//int16 axis2 ; vertical movement (0-$3FF) (little endian)
w16(mo_cvt(mo_y_delta));
//int16 axis3 ; mouse wheel movement (0-$3FF) (little endian)
w16(mo_cvt(mo_wheel_delta));
//int16 axis4 ; ? movement (0-$3FF) (little endian)
w16(mo_cvt(0));
//int16 axis5 ; ? movement (0-$3FF) (little endian)
w16(mo_cvt(0));
//int16 axis6 ; ? movement (0-$3FF) (little endian)
w16(mo_cvt(0));
//int16 axis7 ; ? movement (0-$3FF) (little endian)
w16(mo_cvt(0));
//int16 axis8 ; ? movement (0-$3FF) (little endian)
w16(mo_cvt(0));
mo_x_delta=0;
mo_y_delta=0;
mo_wheel_delta = 0;
return MDRS_DataTransfer;
default:
printf("Mouse: unknown MAPLE COMMAND %d\n", cmd);
return MDRE_UnknownCmd;
}
}
};
extern u16 kcode[4];
extern s8 joyx[4],joyy[4];
extern u8 rt[4], lt[4];
@ -1472,6 +1563,10 @@ maple_device* maple_Create(MapleDeviceType type)
rv = new maple_keyboard();
break;
case MDT_Mouse:
rv = new maple_mouse();
break;
case MDT_NaomiJamma:
rv = new maple_naomi_jamma();
break;

View File

@ -8,6 +8,7 @@ enum MapleDeviceType
MDT_Microphone,
MDT_PurupuruPack,
MDT_Keyboard,
MDT_Mouse,
MDT_NaomiJamma,

View File

@ -225,19 +225,85 @@ extern u8 kb_shift; // shift keys pressed (bitmask)
extern u8 kb_led; // leds currently lit
extern u8 kb_key[6]; // normal keys pressed
extern u32 mo_buttons;
extern f32 mo_x_delta;
extern f32 mo_y_delta;
extern f32 mo_wheel_delta;
static bool capturing_mouse;
static Cursor empty_cursor = None;
static Cursor create_empty_cursor()
{
if (empty_cursor == None)
{
Display *display = (Display*)x11_disp;
char data[] = { 0 };
XColor color;
color.red = color.green = color.blue = 0;
Pixmap pixmap = XCreateBitmapFromData(display, DefaultRootWindow(display),
data, 1, 1);
if (pixmap)
{
empty_cursor = XCreatePixmapCursor(display, pixmap, pixmap, &color, &color, 0, 0);
XFreePixmap(display, pixmap);
}
}
return empty_cursor;
}
static void destroy_empty_cursor()
{
if (empty_cursor != None)
{
XFreeCursor((Display*)x11_disp, empty_cursor);
empty_cursor = None;
}
}
static void x11_capture_mouse()
{
x11_window_set_text("Reicast - mouse capture");
capturing_mouse = true;
Cursor cursor = create_empty_cursor();
Display *display = (Display*)x11_disp;
Window window = (Window)x11_win;
XDefineCursor(display, window, cursor);
XGrabPointer(display, window, False,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
}
static void x11_uncapture_mouse()
{
x11_window_set_text("Reicast");
capturing_mouse = false;
Display *display = (Display*)x11_disp;
Window window = (Window)x11_win;
XUndefineCursor(display, window);
XUngrabPointer(display, CurrentTime);
}
void input_x11_handle()
{
if (x11_win && x11_keyboard_input)
{
if (!x11_win || (!x11_keyboard_input && !settings.input.DCKeyboard && !settings.input.DCMouse))
return;
//Handle X11
XEvent e;
if(XCheckWindowEvent((Display*)x11_disp, (Window)x11_win, KeyPressMask | KeyReleaseMask, &e))
while (XCheckWindowEvent((Display*)x11_disp, (Window)x11_win,
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
| PointerMotionMask | FocusChangeMask,
&e))
{
switch(e.type)
{
case KeyPress:
case KeyRelease:
{
// Dreamcast keyboard emulation
if (e.xkey.keycode == KEY_LSHIFT || e.xkey.keycode == KEY_RSHIFT)
if (e.type == KeyRelease)
@ -287,8 +353,25 @@ void input_x11_handle()
}
}
if (settings.input.DCMouse)
{
// Start/stop mouse capture with Left Ctrl + Left Alt
if (e.type == KeyPress
&& ((e.xkey.keycode == KEY_LALT && (e.xkey.state & ControlMask))
|| (e.xkey.keycode == KEY_LCTRL && (e.xkey.state & Mod1Mask))))
{
capturing_mouse = !capturing_mouse;
if (capturing_mouse)
x11_capture_mouse();
else
x11_uncapture_mouse();
}
}
if (x11_keyboard_input)
{
// Normal keyboard handling
if (e.type == KeyRelease && e.xkey.keycode == KEY_ESC)
if (e.type == KeyRelease && e.xkey.keycode == KEY_ESC
&& !(e.xkey.state & (ControlMask | ShiftMask | Mod1Mask)))
{
dc_stop();
}
@ -345,9 +428,64 @@ void input_x11_handle()
printf("KEY: %d -> %d: %d\n", e.xkey.keycode, dc_key, x11_dc_buttons );
#endif
}
break;
}
}
break;
case FocusOut:
{
if (capturing_mouse)
x11_uncapture_mouse();
capturing_mouse = false;
}
break;
case ButtonPress:
case ButtonRelease:
{
u32 button_mask = 0;
if (e.xbutton.button == Button1)
button_mask = 1 << 2;
else if (e.xbutton.button == Button2)
button_mask = 1 << 1;
if (button_mask)
{
if (e.type == ButtonPress)
mo_buttons &= ~button_mask;
else
mo_buttons |= button_mask;
}
}
// FALL THROUGH
case MotionNotify:
{
static int prev_x = -1;
static int prev_y = -1;
if (settings.input.DCMouse)
{
if (prev_x != -1)
mo_x_delta += (f32)(e.xmotion.x - prev_x) * settings.input.MouseSensitivity / 1000.f;
if (prev_y != -1)
mo_y_delta += (f32)(e.xmotion.y - prev_y) * settings.input.MouseSensitivity / 1000.f;
if (capturing_mouse && (abs(x11_width / 2 - e.xmotion.x) > 10 || abs(x11_height / 2 - e.xmotion.y) > 10))
{
prev_x = x11_width / 2;
prev_y = x11_height / 2;
XWarpPointer((Display*)x11_disp, None, (Window)x11_win, 0, 0, 0, 0,
prev_x, prev_y);
}
else
{
prev_x = e.xmotion.x;
prev_y = e.xmotion.y;
}
}
}
break;
}
}
}
@ -488,6 +626,8 @@ void x11_window_create()
// Add to these for handling other events
sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
if (settings.input.DCMouse)
sWA.event_mask |= PointerMotionMask | FocusChangeMask;
ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
x11_width = cfgLoadInt("x11", "width", DEFAULT_WINDOW_WIDTH);

View File

@ -4,7 +4,6 @@ extern void* x11_glc;
extern void input_x11_init();
extern void event_x11_handle();
extern void input_x11_handle();
extern void event_x11_handle();
extern void x11_window_create();
extern void x11_window_set_text(const char* text);
extern void x11_window_destroy();
@ -69,6 +68,7 @@ const int KEY_LSHIFT = 50;
const int KEY_RSHIFT = 62;
const int KEY_LCTRL = 37;
const int KEY_RCTRL = 105;
const int KEY_LALT = 64;
const int KEY_F1 = 67;
const int KEY_F2 = 68;

View File

@ -329,6 +329,10 @@ void LoadSettings()
settings.reios.ElfFile = cfgLoadStr("reios", "ElfFile", "");
settings.validate.OpenGlChecks = cfgLoadInt("validate", "OpenGlChecks", 0) != 0;
settings.input.DCKeyboard = cfgLoadInt("input", "DCKeyboard", 1);
settings.input.DCMouse = cfgLoadInt("input", "DCMouse", 0);
settings.input.MouseSensitivity = cfgLoadInt("input", "MouseSensitivity", 100);
#else
// TODO Expose this with JNI
settings.rend.Clipping = 1;

View File

@ -739,6 +739,12 @@ struct settings_t
struct {
bool OpenGlChecks;
} validate;
struct {
bool DCKeyboard;
bool DCMouse;
u32 MouseSensitivity;
} input;
};
extern settings_t settings;