singe/io/input.cpp
2019-11-11 14:53:02 -06:00

1150 lines
31 KiB
C++

/*
* input.cpp
*
* Copyright (C) 2001 Matt Ownby
*
* This file is part of DAPHNE, a laserdisc arcade game emulator
*
* DAPHNE is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DAPHNE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Handles SDL input functions (low-level keyboard/joystick input)
#ifdef WIN32
#include <windows.h> // for ScreenToClient -- rdg
#endif
#include "SDL_syswm.h"
#include <time.h>
#include "input.h"
#include "conout.h"
#include "homedir.h"
#include "../video/video.h"
#include "../video/SDL_Console.h"
#include "../daphne.h"
#include "../timer/timer.h"
#include "../game/game.h"
//#include "../game/thayers.h"
#include "../game/singe.h" // by RDG2010
#include "../ldp-out/ldp.h"
#include "fileparse.h"
#include "../manymouse/manymouse.h" // by RDG
#ifdef UNIX
#include <fcntl.h> // for non-blocking i/o
#endif
#include <queue> // STL queue for coin queue
using namespace std;
// Win32 doesn't use strcasecmp, it uses stricmp (lame)
#ifdef WIN32
#define strcasecmp stricmp
#endif
const int JOY_AXIS_MID = (int) (32768 * (0.75)); // how far they have to move the joystick before it 'grabs'
SDL_Joystick *G_joystick = NULL; // pointer to joystick object
bool g_use_joystick = true; // use a joystick by default
bool g_consoledown = false; // whether the console is down or not
bool g_alt_pressed = false; // whether the ALT key is presssed (for ALT-Enter combo)
unsigned int idle_timer; // added by JFA for -idleexit
const double STICKY_COIN_SECONDS = 0.125; // how many seconds a coin acceptor is forced to be "depressed" and how many seconds it is forced to be "released"
Uint32 g_sticky_coin_cycles = 0; // STICKY_COIN_SECONDS * get_cpu_hz(0), cannot be calculated statically
queue<struct coin_input> g_coin_queue; // keeps track of coin input to guarantee that coins don't get missed if the cpu is busy (during seeks for example)
Uint64 g_last_coin_cycle_used = 0; // the cycle value that our last coin press used
static int available_mice = 0; //rdg
static ManyMouseEvent mm_event;
static int bolGrab = false;
#define SDL_MOUSE 100
#define MANY_MOUSE 200
static int g_mouse_mode = SDL_MOUSE;
// the ASCII key words that the parser looks at for the key values
// NOTE : these are in a specific order, corresponding to the enum in daphne.h
const char *g_key_names[] =
{
"KEY_UP", "KEY_LEFT", "KEY_DOWN", "KEY_RIGHT", "KEY_START1", "KEY_START2", "KEY_BUTTON1",
"KEY_BUTTON2", "KEY_BUTTON3", "KEY_COIN1", "KEY_COIN2", "KEY_SKILL1", "KEY_SKILL2",
"KEY_SKILL3", "KEY_SERVICE", "KEY_TEST", "KEY_RESET", "KEY_SCREENSHOT", "KEY_QUIT", "KEY_PAUSE",
"KEY_CONSOLE", "KEY_TILT"
};
// default key assignments, in case .ini file is missing
// Notice each switch can have two keys assigned to it
// NOTE : These are in a specific order, corresponding to the enum in daphne.h
int g_key_defs[SWITCH_COUNT][2] =
{
{ SDLK_UP, SDLK_KP8 }, // up
{ SDLK_LEFT, SDLK_KP4 }, // left
{ SDLK_DOWN, SDLK_KP2 }, // down
{ SDLK_RIGHT, SDLK_KP6 }, // right
{ SDLK_1, 0 }, // 1 player start
{ SDLK_2, 0 }, // 2 player start
{ SDLK_SPACE, SDLK_LCTRL }, // action button 1
{ SDLK_LALT, 0 }, // action button 2
{ SDLK_LSHIFT, 0 }, // action button 3
{ SDLK_5, SDLK_c }, // coin chute left
{ SDLK_6, 0 }, // coin chute right
{ SDLK_KP_DIVIDE, 0 }, // skill easy
{ SDLK_KP_MULTIPLY, 0 }, // skill medium
{ SDLK_KP_MINUS, 0 }, // skill hard
{ SDLK_9, 0 }, // service coin
{ SDLK_F2, 0 }, // test mode
{ SDLK_F3, 0 }, // reset cpu
{ SDLK_F12, SDLK_F11 }, // take screenshot
{ SDLK_ESCAPE, SDLK_q }, // Quit DAPHNE
{ SDLK_p, 0 }, // pause game
{ SDLK_BACKQUOTE, 0 }, // toggle console
{ SDLK_t, 0 }, // Tilt/Slam switch
};
////////////
#ifndef GP2X
// added by Russ
// global button mapping array. just hardcoded room for 10 buttons max
int joystick_buttons_map[10] = {
SWITCH_BUTTON1, // button 1
SWITCH_BUTTON2, // button 2
SWITCH_BUTTON3, // button 3
SWITCH_BUTTON1, // button 4
SWITCH_COIN1, // button 5
SWITCH_START1, // button 6
SWITCH_BUTTON1, // button 7
SWITCH_BUTTON1, // button 8
SWITCH_BUTTON1, // button 9
SWITCH_BUTTON1, // button 10
};
#else
// button mapping for gp2x
int joystick_buttons_map[18] =
{
SWITCH_UP, // 0 (up)
SWITCH_UP, // 1 (up-left)
SWITCH_LEFT, // 2 (left)
SWITCH_DOWN, // 3 (down-left)
SWITCH_DOWN, // 4 (down)
SWITCH_DOWN, // 5 (down-right)
SWITCH_RIGHT, // 6 (right)
SWITCH_UP, // 7 (up-right)
SWITCH_START1, // 8 (start)
SWITCH_COIN1, // 9 (select)
SWITCH_QUIT, // 10 (left)
SWITCH_PAUSE, // 11 (right)
SWITCH_BUTTON1, // 12 (A)
SWITCH_BUTTON2, // 13 (B)
SWITCH_BUTTON3, // 14 (X)
SWITCH_CONSOLE, // 15 (Y)
SWITCH_BUTTON1, // 16 is vol +
SWITCH_BUTTON1 // 17 is vol -
};
#endif
// Mouse button to key mappings
// Added by ScottD for Singe
int mouse_buttons_map[6] =
{
SWITCH_BUTTON1, // 0 (Left Button)
SWITCH_BUTTON3, // 1 (Middle Button)
SWITCH_BUTTON2, // 2 (Right Button)
SWITCH_BUTTON1, // 3 (Wheel Up)
SWITCH_BUTTON2, // 4 (Wheel Down)
SWITCH_MOUSE_DISCONNECT // this is a dummy value so SDL mouse array matches Many Mouse array
};
// ManyMouse button mapping to be backwards compatible with Scott's original.
/*
int mouse_buttons_map[6] =
{
SWITCH_BUTTON3, // 0 (Left Button)
SWITCH_BUTTON1, // 1 (Right Button)
SWITCH_BUTTON2, // 2 (Middle Up)
SWITCH_MOUSE_SCROLL_UP, // 4 (Wheel UP)
SWITCH_MOUSE_SCROLL_DOWN, // 3 (Wheel Down)
SWITCH_MOUSE_DISCONNECT
};
*/
////////////
void CFG_Keys()
{
struct mpo_io *io;
string cur_line = "";
string key_name = "", sval1 = "", sval2 = "", sval3 = "", eq_sign = "";
int val1 = 0, val2 = 0, val3 = 0;
// bool done = false;
// find where the dapinput ini file is (if the file doesn't exist, this string will be empty)
string strDapInput = g_homedir.find_file("dapinput.ini", true);
io = mpo_open(strDapInput.c_str(), MPO_OPEN_READONLY);
if (io)
{
printline("Remapping input ...");
cur_line = "";
// read lines until we find the keyboard header or we hit EOF
while (strcasecmp(cur_line.c_str(), "[KEYBOARD]") != 0)
{
read_line(io, cur_line);
if (io->eof)
{
printline("CFG_Keys() : never found [KEYBOARD] header, aborting");
break;
}
}
// go until we hit EOF, or we break inside this loop (which is the expected behavior)
while (!io->eof)
{
// if we read in something besides a blank line
if (read_line(io, cur_line) > 0)
{
bool corrupt_file = true; // we use this to avoid doing multiple if/else/break statements
// if we are able to read in the key name
if (find_word(cur_line.c_str(), key_name, cur_line))
{
if (strcasecmp(key_name.c_str(), "END") == 0) break; // if we hit the 'END' keyword, we're done
// equals sign
if (find_word(cur_line.c_str(), eq_sign, cur_line) && (eq_sign == "="))
{
if (find_word(cur_line.c_str(), sval1, cur_line))
{
if (find_word(cur_line.c_str(), sval2, cur_line))
{
if (find_word(cur_line.c_str(), sval3, cur_line))
{
val1 = atoi(sval1.c_str());
val2 = atoi(sval2.c_str());
val3 = atoi(sval3.c_str());
corrupt_file = false; // looks like we're good
bool found_match = false;
for (int i = 0; i < SWITCH_COUNT; i++)
{
// if we can match up a key name (see list above) ...
if (strcasecmp(key_name.c_str(), g_key_names[i])==0)
{
g_key_defs[i][0] = val1;
g_key_defs[i][1] = val2;
// if zero then no mapping necessary, just use default, if any
if (val3 > 0) joystick_buttons_map[val3 - 1] = i;
found_match = true;
break;
}
}
// if the key line was unknown
if (!found_match)
{
cur_line = "CFG_Keys() : Unrecognized key name " + key_name;
printline(cur_line.c_str());
corrupt_file = true;
}
}
else printline("CFG_Keys() : Expected 3 integers, only found 2");
}
else printline("CFG_Keys() : Expected 3 integers, only found 1");
}
else printline("CFG_Keys() : Expected 3 integers, found none");
} // end equals sign
else printline("CFG_Keys() : Expected an '=' sign, didn't find it");
} // end if we found key_name
else printline("CFG_Keys() : Weird unexpected error happened"); // this really shouldn't ever happen
if (corrupt_file)
{
printline("CFG_Keys() : input remapping file was not in proper format, so we are aborting");
break;
}
} // end if we didn't find a blank line
// else it's a blank line so we just ignore it
} // end while not EOF
mpo_close(io);
} // end if file was opened successfully
}
// By RDG == ManyMouse code follows
static void ManyMouse_Init_Mice(void)
{
printline("Using ManyMouse for mice input.");
available_mice = ManyMouse_Init();
g_game->set_mice_detected(available_mice);
if (available_mice > MAX_MICE)
available_mice = MAX_MICE;
if (available_mice <= 0)
printline("No mice detected!\n");
else
{
int i;
char s1[255];
if (available_mice == 1)
printline("Only 1 mouse found.");
else
{
sprintf(s1,"Found %d mice devices:",available_mice);
printline(s1);
}
for (i = 0; i < available_mice; i++)
{
const char *name = ManyMouse_DeviceName(i);
strncpy(mice[i].name, name, sizeof (mice[i].name));
mice[i].name[sizeof (mice[i].name) - 1] = '\0';
mice[i].connected = 1;
sprintf(s1,"#%d: %s", i, mice[i].name);
printline(s1);
}
SDL_WM_GrabInput(SDL_GRAB_ON);
}
}
static void ManyMouse_Update_Mice()
{
while (ManyMouse_PollEvent(&mm_event))
{
Mouse *mouse;
if (mm_event.device >= (unsigned int) available_mice)
continue;
mouse = &mice[mm_event.device];
if (mm_event.type == MANYMOUSE_EVENT_RELMOTION)
{
if (mm_event.item == 0)
mouse->relx += mm_event.value;
else if (mm_event.item == 1)
mouse->rely += mm_event.value;
if (mouse->relx < 0) mouse->relx = 0;
else if (mouse->relx >= get_video_width()) mouse->relx = get_video_width();
if (mouse->rely < 0) mouse->rely = 0;
else if (mouse->rely >= get_video_height()) mouse->rely = get_video_height();
g_game->OnMouseMotion(mouse->x, mouse->y, mouse->relx, mouse->rely, mm_event.device);
}
else if (mm_event.type == MANYMOUSE_EVENT_ABSMOTION)
{
float val = (float) (mm_event.value - mm_event.minval);
float maxval = (float) (mm_event.maxval - mm_event.minval);
if (mm_event.item == 0)
//mouse->x = (val / maxval) * screen_w;
mouse->x = mm_event.value;
else if (mm_event.item == 1)
//mouse->y = (val / maxval) * screen_h;
mouse->y = mm_event.value;
g_game->OnMouseMotion(mouse->x, mouse->y, mouse->relx, mouse->rely, mm_event.device);
/*
LPPOINT absPoint = new POINT;
// Access to SDL's OS specific structure.
SDL_SysWMinfo windowInfo;
SDL_VERSION(&windowInfo.version);
if(SDL_GetWMInfo(&windowInfo))
{
// Retrieve the Windows handle to the SDL window.
HWND handle = windowInfo.window;
if (mm_event.item == 0)
{
absPoint->x = mm_event.value;
absPoint->y = 0;
//if (ClientToScreen(handle, absPoint) != 0)
MapWindowPoints(NULL, handle,absPoint,2);
mouse->x = absPoint->x;
}
/*
else if (mm_event.item == 1)
{
absPoint.y = mm_event.value;
if (ScreenToClient(handle,LPPOINT) absPoint.y) == 0)
mouse->y = absPoint.y;
}
}
*/
}
else if (mm_event.type == MANYMOUSE_EVENT_BUTTON)
{
if (mm_event.item < 32)
{
if (mm_event.value == 1) // 0 == release, 1 == pressed
{
input_enable((Uint8)mouse_buttons_map[mm_event.item], mm_event.device);
mouse->buttons |= (1 << mm_event.item);
}
else
{
input_disable((Uint8)mouse_buttons_map[mm_event.item], mm_event.device);
mouse->buttons &= ~(1 << mm_event.item);
}
}
}
else if (mm_event.type == MANYMOUSE_EVENT_SCROLL)
{
if (mm_event.item == 0) // vertical scroll wheel
{
if (mm_event.value > 0) // scroll up
input_disable(SWITCH_MOUSE_SCROLL_UP, mm_event.device);
else // scroll down
input_disable(SWITCH_MOUSE_SCROLL_DOWN, mm_event.device);
}
}
else if (mm_event.type == MANYMOUSE_EVENT_DISCONNECT)
{
mice[mm_event.device].connected = 0;
input_disable(SWITCH_MOUSE_DISCONNECT, mm_event.device);
}
}
}
////// end manymouse implementation
int SDL_input_init()
// initializes the keyboard (and joystick if one is present)
// returns 1 if successful, 0 on error
// NOTE: Video has to be initialized BEFORE this is or else it won't work
{
int result = 0;
// make sure the coin queue is empty (it should be, this is just a safety check)
while (!g_coin_queue.empty())
{
g_coin_queue.pop();
}
g_sticky_coin_cycles = 0;//(Uint32) (STICKY_COIN_SECONDS * get_cpu_hz(0)); // only needs to be calculated once
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0)
{
// if joystick usage is enabled
if (g_use_joystick)
{
// if there is at least 1 joystick and we are authorized to use the joystick for input
if (SDL_NumJoysticks() > 0)
{
G_joystick = SDL_JoystickOpen(0); // FIXME: right now we automatically choose the first joystick
if (G_joystick != NULL)
{
printline("Joystick #0 was successfully opened");
}
else
{
printline("Error opening joystick!");
}
}
else
{
printline("No joysticks detected");
}
}
// notify user that their attempt to disable the joystick is successful
else
{
printline("Joystick usage disabled");
}
CFG_Keys(); // NOTE : for some freak reason, this should not be done BEFORE the joystick is initialized, I don't know why!
result = 1;
}
else
{
printline("Input initialization failed!");
}
idle_timer = refresh_ms_time(); // added by JFA for -idleexit
#ifdef UNIX
// enable non-blocking stdin (see conin.cpp UNIX stdin stuff)
/*int iRes =*/ fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
#endif
/*
// if the mouse is disabled, then filter mouse events out ...
if (!g_game->get_mouse_enabled())
{
FilterMouseEvents(true);
}
*/
// Manymouse implementation by RDG
if (!g_game->get_mouse_enabled())
{
FilterMouseEvents(true);
if (g_game->get_mouse_enabled()) ManyMouse_Init_Mice();
}
else
FilterMouseEvents(false);
return(result);
}
void FilterMouseEvents(bool bFilteredOut)
{
int iState = SDL_ENABLE;
if (bFilteredOut)
{
iState = SDL_IGNORE;
}
SDL_EventState(SDL_MOUSEMOTION, iState);
SDL_EventState(SDL_MOUSEBUTTONDOWN, iState);
SDL_EventState(SDL_MOUSEBUTTONUP, iState);
}
// does any shutting down necessary
// 1 = success, 0 = failure
int SDL_input_shutdown(void)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if ((g_game->get_mouse_enabled()) && (g_mouse_mode == MANY_MOUSE)) ManyMouse_Quit();
return(1);
}
// checks to see if there is incoming input, and acts on it
void SDL_check_input()
{
SDL_Event event;
while ((SDL_PollEvent (&event)) && (!get_quitflag()))
{
// if they press the tilda key to bring down the console
// this is somewhat of a hacked if statement but I can't see
// a better way based on the SDL_Console API ...
if ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_BACKQUOTE))
{
// we must not bring down the console if blitting is not allowed
if (g_ldp->is_blitting_allowed())
{
#ifdef CPU_DEBUG
toggle_console();
#endif
}
}
// if we've got the console down, process events
else if (g_consoledown)
{
ConsoleEvents(&event);
}
// else handle events normally
else
{
process_event(&event);
}
}
if (g_game->get_mouse_enabled() && (g_mouse_mode == MANY_MOUSE)) ManyMouse_Update_Mice();
check_console_refresh();
// added by JFA for -idleexit
if (get_idleexit() > 0 && elapsed_ms_time(idle_timer) > get_idleexit()) set_quitflag();
// if the coin queue has something entered into it
if (!g_coin_queue.empty())
{
struct coin_input coin = g_coin_queue.front(); // examine the next element in the queue to be considered
// NOTE : when cpu timers are flushed, the coin queue is automatically "reshuffled"
// so it is safe not to check to see whether the cpu timers were flushed here
// if it's safe to activate the coin
//if (get_total_cycles_executed(0) > coin.cycles_when_to_enable)
{
// if we're supposed to enable this coin
if (coin.coin_enabled)
{
g_game->input_enable(coin.coin_val, NOMOUSE);
}
// else we are supposed to disable this coin
else
{
g_game->input_disable(coin.coin_val, NOMOUSE);
}
g_coin_queue.pop(); // remove coin entry from queue
}
// else it's not safe to activate the coin, so we just wait
}
// else the coin queue is empty, so we needn't do anything ...
}
#ifdef CPU_DEBUG
void toggle_console()
{
if (get_console_initialized())
{
// if console is down, get rid of it
if (g_consoledown)
{
g_consoledown = false;
SDL_EnableUNICODE(0);
display_repaint();
}
// if console is not down, display it
else
{
g_consoledown = true;
SDL_EnableUNICODE(1);
}
}
}
#endif
// processes incoming input
void process_event(SDL_Event *event)
{
unsigned int i = 0;
// by RDG2010
// make things easier to read...
SDLKey keyPressed = event->key.keysym.sym;
switch (event->type)
{
case SDL_KEYDOWN:
reset_idle(); // added by JFA for -idleexit
// by RDG2010
// Get SINGE full access to keyboard input (like Thayers)
{
singe *l_singe = dynamic_cast<singe *>(g_game);
if (l_singe) l_singe->process_keydown(keyPressed, g_key_defs);
}
break;
case SDL_KEYUP:
// MPO : since con_getkey doesn't catch the key up event, we shouldn't call reset_idle here.
//reset_idle(); // added by JFA for -idleexit
// by RDG2010
// Get SINGE full access to keyboard input (like Thayers)
if (keyPressed == SDLK_g)
{
if ((g_game->get_mouse_enabled()) && (g_mouse_mode == MANY_MOUSE))
{
bolGrab = !bolGrab;
if (bolGrab)
{
SDL_WM_GrabInput(SDL_GRAB_ON);
ManyMouse_Quit();
ManyMouse_Init_Mice();
}
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
}
else
{
singe *l_singe = dynamic_cast<singe *>(g_game);
if (l_singe) l_singe->process_keyup(keyPressed, g_key_defs);
}
break;
case SDL_JOYAXISMOTION:
//reset_idle(); // added by JFA for -idleexit
// reset_idle removed here because the analog controls were registering
// even when the joystick was not in use. Joystick buttons still reset the idle.
process_joystick_motion(event);
break;
case SDL_JOYHATMOTION:
// only process events for the first hat
if ( event->jhat.hat == 0 )
{
reset_idle();
process_joystick_hat_motion(event);
}
break;
case SDL_JOYBUTTONDOWN:
reset_idle(); // added by JFA for -idleexit
// added by Russ
// loop through buttons and look for a press
for (i = 0; i < (sizeof(joystick_buttons_map) / sizeof(int)); i++) {
if (event->jbutton.button == i) {
input_enable((Uint8) joystick_buttons_map[i], NOMOUSE);
break;
}
}
break;
case SDL_JOYBUTTONUP:
reset_idle(); // added by JFA for -idleexit
// added by Russ
for (i = 0; i < (sizeof(joystick_buttons_map) / sizeof(int)); i++) {
if (event->jbutton.button == i) {
input_disable((Uint8) joystick_buttons_map[i], NOMOUSE);
break;
}
}
break;
/*
case SDL_MOUSEBUTTONDOWN:
// added by ScottD
// loop through buttons and look for a press
for (i = 0; i < (sizeof(mouse_buttons_map) / sizeof(int)); i++) {
if (event->button.button == i) {
input_enable((Uint8)mouse_buttons_map[i]);
break;
}
}
break;
case SDL_MOUSEBUTTONUP:
// added by ScottD
for (i = 0; i < (sizeof(mouse_buttons_map) / sizeof(int)); i++) {
if (event->button.button == i) {
input_disable((Uint8)mouse_buttons_map[i]);
break;
}
}
break;
case SDL_MOUSEMOTION:
// added by ScottD
g_game->OnMouseMotion(event->motion.x, event->motion.y, event->motion.xrel, event->motion.yrel);
break;
*/
case SDL_QUIT:
// if they are trying to close the window
set_quitflag();
break;
default:
break;
}
if (g_game->get_mouse_enabled() && (g_mouse_mode == SDL_MOUSE))
{
switch (event->type)
{
case SDL_MOUSEBUTTONDOWN:
// added by ScottD
// loop through buttons and look for a press
for (i = 0; i < (sizeof(mouse_buttons_map) / sizeof(int)); i++) {
if (event->button.button == i) {
//input_enable((Uint8)mouse_buttons_map[i]);
g_game->input_enable((Uint8)mouse_buttons_map[i], NOMOUSE);
break;
}
}
break;
case SDL_MOUSEBUTTONUP:
// added by ScottD
for (i = 0; i < (sizeof(mouse_buttons_map) / sizeof(int)); i++) {
if (event->button.button == i) {
//input_disable((Uint8)mouse_buttons_map[i]);
g_game->input_disable((Uint8)mouse_buttons_map[i], NOMOUSE);
break;
}
}
break;
case SDL_MOUSEMOTION:
// added by ScottD
g_game->OnMouseMotion(event->motion.x, event->motion.y, event->motion.xrel, event->motion.yrel, NOMOUSE); // Last parameter is for ManyMouse use only.
break;
}
}
// added by JFA for -idleexit
if (get_idleexit() > 0 && elapsed_ms_time(idle_timer) > get_idleexit()) set_quitflag();
}
// if a key is pressed, we go here
void process_keydown(SDLKey key)
{
// go through each key def (defined in enum in daphne.h) and check to see if the key entered matches
// If we have a match, the switch to be used is the value of the index "move"
for (Uint8 move = 0; move < SWITCH_COUNT; move++)
{
if ((key == g_key_defs[move][0]) || (key == g_key_defs[move][1]))
{
input_enable(move, NOMOUSE);
}
}
// check for ALT-ENTER here
if ((key == SDLK_LALT) || (key == SDLK_RALT))
{
g_alt_pressed = true;
}
else if ((key == SDLK_RETURN) && (g_alt_pressed))
{
vid_toggle_fullscreen();
}
// end ALT-ENTER check
}
// if a key is released, we go here
void process_keyup(SDLKey key)
{
// go through each key def (defined in enum in daphne.h) and check to see if the key entered matches
// If we have a match, the switch to be used is the value of the index "move"
for (Uint8 move = 0; move < SWITCH_COUNT; move++)
{
if ((key == g_key_defs[move][0]) || (key == g_key_defs[move][1]))
{
input_disable(move, NOMOUSE);
}
}
// if they are releasing an ALT key
if ((key == SDLK_LALT) || (key == SDLK_RALT))
{
g_alt_pressed = false;
}
}
// processes movements of the joystick
void process_joystick_motion(SDL_Event *event)
{
static int x_axis_in_use = 0; // true if joystick is left or right
static int y_axis_in_use = 0; // true if joystick is up or down
// if they are moving along the verticle axis
if (event->jaxis.axis == 1)
{
// if they're moving up
if (event->jaxis.value < -JOY_AXIS_MID)
{
input_enable(SWITCH_UP, NOMOUSE);
y_axis_in_use = 1;
}
// if they're moving down
else if (event->jaxis.value > JOY_AXIS_MID)
{
input_enable(SWITCH_DOWN, NOMOUSE);
y_axis_in_use = 1;
}
// if they just barely stopped moving up or down
else if (y_axis_in_use == 1)
{
input_disable(SWITCH_UP, NOMOUSE);
input_disable(SWITCH_DOWN, NOMOUSE);
y_axis_in_use = 0;
}
} // end verticle axis
// horizontal axis
else
{
// if they're moving right
if (event->jaxis.value > JOY_AXIS_MID)
{
input_enable(SWITCH_RIGHT, NOMOUSE);
x_axis_in_use = 1;
}
// if they're moving left
else if (event->jaxis.value < -JOY_AXIS_MID)
{
input_enable(SWITCH_LEFT, NOMOUSE);
x_axis_in_use = 1;
}
// if they just barely stopped moving right or left
else if (x_axis_in_use == 1)
{
input_disable(SWITCH_RIGHT, NOMOUSE);
input_disable(SWITCH_LEFT, NOMOUSE);
x_axis_in_use = 0;
}
} // end horizontal axis
}
// processes movement of the joystick hat
void process_joystick_hat_motion(SDL_Event *event)
{
static Uint8 prev_hat_position = SDL_HAT_CENTERED;
if ( ( event->jhat.value & SDL_HAT_UP ) && !( prev_hat_position & SDL_HAT_UP ) )
{
// hat moved to the up position
input_enable(SWITCH_UP, NOMOUSE);
}
else if ( !( event->jhat.value & SDL_HAT_UP ) && ( prev_hat_position & SDL_HAT_UP ) )
{
// up hat released
input_disable(SWITCH_UP, NOMOUSE);
}
if ( ( event->jhat.value & SDL_HAT_RIGHT ) && !( prev_hat_position & SDL_HAT_RIGHT ) )
{
// hat moved to the right position
input_enable(SWITCH_RIGHT, NOMOUSE);
}
else if ( !( event->jhat.value & SDL_HAT_RIGHT ) && ( prev_hat_position & SDL_HAT_RIGHT ) )
{
// right hat released
input_disable(SWITCH_RIGHT, NOMOUSE);
}
if ( ( event->jhat.value & SDL_HAT_DOWN ) && !( prev_hat_position & SDL_HAT_DOWN ) )
{
// hat moved to the down position
input_enable(SWITCH_DOWN, NOMOUSE);
}
else if ( !( event->jhat.value & SDL_HAT_DOWN ) && ( prev_hat_position & SDL_HAT_DOWN ) )
{
// down hat released
input_disable(SWITCH_DOWN, NOMOUSE);
}
if ( ( event->jhat.value & SDL_HAT_LEFT ) && !( prev_hat_position & SDL_HAT_LEFT ) )
{
// hat moved to the left position
input_enable(SWITCH_LEFT, NOMOUSE);
}
else if ( !( event->jhat.value & SDL_HAT_LEFT ) && ( prev_hat_position & SDL_HAT_LEFT ) )
{
// left hat released
input_disable(SWITCH_LEFT, NOMOUSE);
}
prev_hat_position = event->jhat.value;
}
// functions to help us avoid 'extern' statements
bool get_consoledown()
{
return (g_consoledown);
}
void set_consoledown (bool value)
{
g_consoledown = value;
}
// draws console if it's down and if there's been enough of a delay
void check_console_refresh()
{
static unsigned int console_refresh = 0;
const unsigned int refresh_every = 125; // refreshes console every (this many) ms
if (g_consoledown)
{
if (elapsed_ms_time(console_refresh) > refresh_every)
{
DrawConsole();
vid_blit(get_screen_blitter(), 0, 0);
vid_flip();
console_refresh = refresh_ms_time();
}
}
}
// if user has pressed a key/moved the joystick/pressed a button
void input_enable(Uint8 move, int mouseID)
{
// first test universal input, then pass unknown input on to the game driver
switch (move)
{
default:
g_game->input_enable(move, mouseID);
break;
case SWITCH_RESET:
g_game->reset();
break;
case SWITCH_SCREENSHOT:
g_ldp->request_screenshot();
break;
case SWITCH_PAUSE:
if (g_game->get_pause_key_flag()) // rdg
g_game->toggle_game_pause();
break;
case SWITCH_QUIT:
set_quitflag();
break;
case SWITCH_COIN1:
case SWITCH_COIN2:
// coin inputs are buffered to ensure that they are not dropped while the cpu is busy (such as during a seek)
// therefore if the input is coin1 or coin2 AND we are using a real cpu (and not a program such as seektest)
//if (get_cpu_hz(0) > 0)
{
add_coin_to_queue(true, move);
}
break;
case SWITCH_CONSOLE:
// we must not bring down the console if blitting is not allowed
if (g_ldp->is_blitting_allowed())
{
#ifdef CPU_DEBUG
toggle_console();
#endif
}
break;
}
}
// if user has released a key/released a button/moved joystick back to center position
void input_disable(Uint8 move, int mouseID)
{
// don't send reset or screenshots key-ups to the individual games because they will return warnings that will alarm users
if ((move != SWITCH_RESET) && (move != SWITCH_SCREENSHOT) && (move != SWITCH_QUIT)
&& (move != SWITCH_PAUSE))
{
// coin inputs are buffered to ensure that they are not dropped while the cpu is busy (such as during a seek)
// therefore if the input is coin1 or coin2 AND we are using a real cpu (and not a program such as seektest)
//if (((move == SWITCH_COIN1) || (move == SWITCH_COIN2)) && (get_cpu_hz(0) > 0))
if ((move == SWITCH_COIN1) || (move == SWITCH_COIN2))
{
add_coin_to_queue(false, move);
}
else
{
g_game->input_disable(move, mouseID);
}
}
// else do nothing
}
inline void add_coin_to_queue(bool enabled, Uint8 val)
{
Uint64 total_cycles = 0;//get_total_cycles_executed(0);
struct coin_input coin;
coin.coin_enabled = enabled;
coin.coin_val = val;
// make sure that we are >= to the total cycles executed otherwise coin insertions will be really quick
if (g_last_coin_cycle_used < total_cycles)
{
g_last_coin_cycle_used = total_cycles;
}
g_last_coin_cycle_used += g_sticky_coin_cycles; // advance to the next safe slot
coin.cycles_when_to_enable = g_last_coin_cycle_used; // and assign this safe slot to this current coin
g_coin_queue.push(coin); // add the coin to the queue ...
}
// added by JFA for -idleexit
void reset_idle(void)
{
static bool bSoundOn = false;
// At this time, the only way the sound will be muted is if -startsilent was passed via command line.
// So the first key press should always unmute the sound.
if (!bSoundOn)
{
bSoundOn = true;
set_sound_mute(false);
}
idle_timer = refresh_ms_time();
}
// end edit
// primarily to disable joystick use if user wishes not to use one
void set_use_joystick(bool val)
{
g_use_joystick = val;
}
bool set_mouse_mode(int thisMode)
{
bool result = false;
if (g_game->get_mouse_enabled())
{
if (g_mouse_mode == MANY_MOUSE) ManyMouse_Quit();
if (thisMode == MANY_MOUSE || thisMode == SDL_MOUSE)
{
g_mouse_mode = thisMode;
result = true;
memset(mouse_buttons_map, 0, 6); // Erase array
if (thisMode == SDL_MOUSE)
{
mouse_buttons_map[0] = SWITCH_BUTTON1; // 0 (Left Button)
mouse_buttons_map[1] = SWITCH_BUTTON3; // 1 (Middle Button)
mouse_buttons_map[2] = SWITCH_BUTTON2; // 2 (Right Button)
mouse_buttons_map[3] = SWITCH_BUTTON1; // 3 (Wheel Up)
mouse_buttons_map[4] = SWITCH_BUTTON2; // 4 (Wheel Down)
mouse_buttons_map[5] = SWITCH_MOUSE_DISCONNECT; // Dummy value so array matches in both branches.
}
else
{
mouse_buttons_map[0] = SWITCH_BUTTON3; // 0 (Left Button)
mouse_buttons_map[1] = SWITCH_BUTTON1; // 1 (Middle Button)
mouse_buttons_map[2] = SWITCH_BUTTON2; // 2 (Right Button)
mouse_buttons_map[3] = SWITCH_MOUSE_SCROLL_UP; // 3 (Wheel Up)
mouse_buttons_map[4] = SWITCH_MOUSE_SCROLL_DOWN; // 4 (Wheel Down)
mouse_buttons_map[5] = SWITCH_MOUSE_DISCONNECT; // 4 (Wheel Down)
ManyMouse_Init_Mice();
} // end if
} // end if
} // end if
return result;
}