Dreamcast mouse emulation
This commit is contained in:
parent
2081a0c21b
commit
8a2684ff55
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -8,6 +8,7 @@ enum MapleDeviceType
|
|||
MDT_Microphone,
|
||||
MDT_PurupuruPack,
|
||||
MDT_Keyboard,
|
||||
MDT_Mouse,
|
||||
|
||||
MDT_NaomiJamma,
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -739,6 +739,12 @@ struct settings_t
|
|||
struct {
|
||||
bool OpenGlChecks;
|
||||
} validate;
|
||||
|
||||
struct {
|
||||
bool DCKeyboard;
|
||||
bool DCMouse;
|
||||
u32 MouseSensitivity;
|
||||
} input;
|
||||
};
|
||||
|
||||
extern settings_t settings;
|
||||
|
|
Loading…
Reference in New Issue