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++){
|
for (int i = 0; i < numberOfControl; i++){
|
||||||
mcfg_Create(MDT_SegaController, i, 5);
|
mcfg_Create(MDT_SegaController, i, 5);
|
||||||
}
|
}
|
||||||
if (numberOfControl < 4)
|
if (settings.input.DCKeyboard && numberOfControl < 4)
|
||||||
mcfg_Create(MDT_Keyboard, numberOfControl, 5);
|
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,0);
|
||||||
mcfg_Create(MDT_SegaVMU,0,1);
|
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 u16 kcode[4];
|
||||||
extern s8 joyx[4],joyy[4];
|
extern s8 joyx[4],joyy[4];
|
||||||
extern u8 rt[4], lt[4];
|
extern u8 rt[4], lt[4];
|
||||||
|
@ -1472,6 +1563,10 @@ maple_device* maple_Create(MapleDeviceType type)
|
||||||
rv = new maple_keyboard();
|
rv = new maple_keyboard();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MDT_Mouse:
|
||||||
|
rv = new maple_mouse();
|
||||||
|
break;
|
||||||
|
|
||||||
case MDT_NaomiJamma:
|
case MDT_NaomiJamma:
|
||||||
rv = new maple_naomi_jamma();
|
rv = new maple_naomi_jamma();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -8,6 +8,7 @@ enum MapleDeviceType
|
||||||
MDT_Microphone,
|
MDT_Microphone,
|
||||||
MDT_PurupuruPack,
|
MDT_PurupuruPack,
|
||||||
MDT_Keyboard,
|
MDT_Keyboard,
|
||||||
|
MDT_Mouse,
|
||||||
|
|
||||||
MDT_NaomiJamma,
|
MDT_NaomiJamma,
|
||||||
|
|
||||||
|
|
|
@ -225,19 +225,85 @@ extern u8 kb_shift; // shift keys pressed (bitmask)
|
||||||
extern u8 kb_led; // leds currently lit
|
extern u8 kb_led; // leds currently lit
|
||||||
extern u8 kb_key[6]; // normal keys pressed
|
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()
|
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))
|
//Handle X11
|
||||||
|
XEvent e;
|
||||||
|
|
||||||
|
while (XCheckWindowEvent((Display*)x11_disp, (Window)x11_win,
|
||||||
|
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
|
||||||
|
| PointerMotionMask | FocusChangeMask,
|
||||||
|
&e))
|
||||||
|
{
|
||||||
|
switch(e.type)
|
||||||
{
|
{
|
||||||
switch(e.type)
|
case KeyPress:
|
||||||
{
|
case KeyRelease:
|
||||||
case KeyPress:
|
{
|
||||||
case KeyRelease:
|
|
||||||
// Dreamcast keyboard emulation
|
// Dreamcast keyboard emulation
|
||||||
if (e.xkey.keycode == KEY_LSHIFT || e.xkey.keycode == KEY_RSHIFT)
|
if (e.xkey.keycode == KEY_LSHIFT || e.xkey.keycode == KEY_RSHIFT)
|
||||||
if (e.type == KeyRelease)
|
if (e.type == KeyRelease)
|
||||||
|
@ -287,66 +353,138 @@ void input_x11_handle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal keyboard handling
|
if (settings.input.DCMouse)
|
||||||
if (e.type == KeyRelease && e.xkey.keycode == KEY_ESC)
|
|
||||||
{
|
{
|
||||||
dc_stop();
|
// 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
|
||||||
|
&& !(e.xkey.state & (ControlMask | ShiftMask | Mod1Mask)))
|
||||||
|
{
|
||||||
|
dc_stop();
|
||||||
|
}
|
||||||
#ifndef RELEASE
|
#ifndef RELEASE
|
||||||
else if (e.xkey.keycode == KEY_F10)
|
else if (e.xkey.keycode == KEY_F10)
|
||||||
{
|
{
|
||||||
// Dump the next frame into a file
|
// Dump the next frame into a file
|
||||||
dump_frame_switch = e.type == KeyPress;
|
dump_frame_switch = e.type == KeyPress;
|
||||||
}
|
}
|
||||||
#elif FEAT_HAS_NIXPROF
|
#elif FEAT_HAS_NIXPROF
|
||||||
else if (e.type == KeyRelease && e.xkey.keycode == KEY_F10)
|
else if (e.type == KeyRelease && e.xkey.keycode == KEY_F10)
|
||||||
{
|
{
|
||||||
if (sample_Switch(3000)) {
|
if (sample_Switch(3000)) {
|
||||||
printf("Starting profiling\n");
|
printf("Starting profiling\n");
|
||||||
} else {
|
} else {
|
||||||
printf("Stopping profiling\n");
|
printf("Stopping profiling\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else if (e.type == KeyRelease && e.xkey.keycode == KEY_F11)
|
else if (e.type == KeyRelease && e.xkey.keycode == KEY_F11)
|
||||||
{
|
|
||||||
x11_fullscreen = !x11_fullscreen;
|
|
||||||
x11_window_set_fullscreen(x11_fullscreen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int dc_key = x11_keymap[e.xkey.keycode];
|
|
||||||
|
|
||||||
if (dc_key == DC_AXIS_LT)
|
|
||||||
{
|
{
|
||||||
if (e.type == KeyPress)
|
x11_fullscreen = !x11_fullscreen;
|
||||||
lt[0] = 255;
|
x11_window_set_fullscreen(x11_fullscreen);
|
||||||
else
|
|
||||||
lt[0] = 0;
|
|
||||||
}
|
|
||||||
else if (dc_key == DC_AXIS_RT)
|
|
||||||
{
|
|
||||||
if (e.type == KeyPress)
|
|
||||||
rt[0] = 255;
|
|
||||||
else
|
|
||||||
rt[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.type == KeyPress)
|
|
||||||
{
|
|
||||||
kcode[0] &= ~dc_key;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kcode[0] |= dc_key;
|
int dc_key = x11_keymap[e.xkey.keycode];
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
if (dc_key == DC_AXIS_LT)
|
||||||
printf("KEY: %d -> %d: %d\n", e.xkey.keycode, dc_key, x11_dc_buttons );
|
{
|
||||||
#endif
|
if (e.type == KeyPress)
|
||||||
|
lt[0] = 255;
|
||||||
|
else
|
||||||
|
lt[0] = 0;
|
||||||
|
}
|
||||||
|
else if (dc_key == DC_AXIS_RT)
|
||||||
|
{
|
||||||
|
if (e.type == KeyPress)
|
||||||
|
rt[0] = 255;
|
||||||
|
else
|
||||||
|
rt[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.type == KeyPress)
|
||||||
|
{
|
||||||
|
kcode[0] &= ~dc_key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kcode[0] |= dc_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
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
|
// Add to these for handling other events
|
||||||
sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
|
sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
|
||||||
|
if (settings.input.DCMouse)
|
||||||
|
sWA.event_mask |= PointerMotionMask | FocusChangeMask;
|
||||||
ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
|
ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
|
||||||
|
|
||||||
x11_width = cfgLoadInt("x11", "width", DEFAULT_WINDOW_WIDTH);
|
x11_width = cfgLoadInt("x11", "width", DEFAULT_WINDOW_WIDTH);
|
||||||
|
|
|
@ -4,7 +4,6 @@ extern void* x11_glc;
|
||||||
extern void input_x11_init();
|
extern void input_x11_init();
|
||||||
extern void event_x11_handle();
|
extern void event_x11_handle();
|
||||||
extern void input_x11_handle();
|
extern void input_x11_handle();
|
||||||
extern void event_x11_handle();
|
|
||||||
extern void x11_window_create();
|
extern void x11_window_create();
|
||||||
extern void x11_window_set_text(const char* text);
|
extern void x11_window_set_text(const char* text);
|
||||||
extern void x11_window_destroy();
|
extern void x11_window_destroy();
|
||||||
|
@ -69,6 +68,7 @@ const int KEY_LSHIFT = 50;
|
||||||
const int KEY_RSHIFT = 62;
|
const int KEY_RSHIFT = 62;
|
||||||
const int KEY_LCTRL = 37;
|
const int KEY_LCTRL = 37;
|
||||||
const int KEY_RCTRL = 105;
|
const int KEY_RCTRL = 105;
|
||||||
|
const int KEY_LALT = 64;
|
||||||
|
|
||||||
const int KEY_F1 = 67;
|
const int KEY_F1 = 67;
|
||||||
const int KEY_F2 = 68;
|
const int KEY_F2 = 68;
|
||||||
|
|
|
@ -329,6 +329,10 @@ void LoadSettings()
|
||||||
settings.reios.ElfFile = cfgLoadStr("reios", "ElfFile", "");
|
settings.reios.ElfFile = cfgLoadStr("reios", "ElfFile", "");
|
||||||
|
|
||||||
settings.validate.OpenGlChecks = cfgLoadInt("validate", "OpenGlChecks", 0) != 0;
|
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
|
#else
|
||||||
// TODO Expose this with JNI
|
// TODO Expose this with JNI
|
||||||
settings.rend.Clipping = 1;
|
settings.rend.Clipping = 1;
|
||||||
|
|
|
@ -739,6 +739,12 @@ struct settings_t
|
||||||
struct {
|
struct {
|
||||||
bool OpenGlChecks;
|
bool OpenGlChecks;
|
||||||
} validate;
|
} validate;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool DCKeyboard;
|
||||||
|
bool DCMouse;
|
||||||
|
u32 MouseSensitivity;
|
||||||
|
} input;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern settings_t settings;
|
extern settings_t settings;
|
||||||
|
|
Loading…
Reference in New Issue