diff --git a/README.md b/README.md index af755ff6..0c17c45d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ +# ReGBA-RG350 + +GBA emulator for RG350 console + +This is my personal fork of the GBA emulator for RG350 console. +I added external gamepad support. + +More information: +* [Demonstrational video](https://youtu.be/A8kiZaQG-84) + + +--------------------------------- + TempGBA version 1.45, 2013-09-14 A Game Boy Advance emulator for the Supercard DSTWO. diff --git a/source/opendingux/Makefile b/source/opendingux/Makefile index a40dbab1..b9c81e67 100644 --- a/source/opendingux/Makefile +++ b/source/opendingux/Makefile @@ -27,12 +27,17 @@ DEFS := -DGCW_ZERO -DMIPS_XBURST \ -DSCREEN_WIDTH=320 -DSCREEN_HEIGHT=240 \ -DGIT_VERSION=$(shell git describe --always) +ifdef PLAYGO + DEFS += -DPLAYGO + DEFS += -DUSE_MMAP +else ifdef RG350 DEFS += -DRG350 DEFS += -DUSE_MMAP else DEFS += -DLOAD_ALL_ROM endif +endif HAS_MIPS32R2 := $(shell echo | $(CC) -dM -E - |grep _MIPS_ARCH_MIPS32R2) ifneq ($(HAS_MIPS32R2),) DEFS += -DMIPS_32R2 diff --git a/source/opendingux/data/manual-en.txt b/source/opendingux/data/manual-en.txt index 7155d36b..2378c04f 100644 --- a/source/opendingux/data/manual-en.txt +++ b/source/opendingux/data/manual-en.txt @@ -48,8 +48,8 @@ In the Main Menu or any submenu containing options, you can press the Select key - Input Settings - > GBA buttons: Press A on one of these, and you can set a new button on your device to be used for triggering it on the GBA. These mappings are mandatory; you cannot have a mapping such that nothing on your device can trigger a GBA button. However, you can set multiple GBA buttons to be triggered by one on your device. > Rapid-fire buttons: These mappings are optional; you can press A, then two buttons at once to clear them. Rapid-fire buttons press and release their GBA button at 30 Hz: they are pressed for 1/60 of a second, then unpressed for the same time. -> Analog sensitivity (GCW Zero only): This setting controls how far the analog nub needs to go to trigger a direction. The analog nub can be used to navigate the menus with this sensitivity as well. -> Analog in-game binding (GCW Zero only): "None" does not allow the analog nub to be passed through to the GBA game, but allows it to be used for hotkeys. "GBA D-pad" allows the analog nub to be passed to the GBA according to the sensitivity setting, as well as hotkeys. +> Analogs sensitivity (GCW Zero only): This setting controls how far the analog nub needs to go to trigger a direction. The analog nub can be used to navigate the menus with this sensitivity as well. +> L-Analog in-game binding (GCW Zero only): "None" does not allow the analog nub to be passed through to the GBA game, but allows it to be used for hotkeys. "GBA D-pad" allows the analog nub to be passed to the GBA according to the sensitivity setting, as well as hotkeys. - Hotkeys - Press A on these, and you can set a new combination of buttons on your device to be used during emulation to trigger each function, or B to clear the binding. diff --git a/source/opendingux/data/manual-es.txt b/source/opendingux/data/manual-es.txt index c45982c7..ce73a877 100644 --- a/source/opendingux/data/manual-es.txt +++ b/source/opendingux/data/manual-es.txt @@ -48,8 +48,8 @@ En el Menú Principal o cualquier submenú que contenga opciones, se puede pulsa - Ajustes de entrada (Input Settings) - > GBA buttons: Presione A en uno de ellos para establecer un nuevo botón en el dispositivo para ser utilizado en la GBA. Estas asignaciones son obligatorias, no se puede tener una asignación tal que no haya ningun botón asignado. Sin embargo, se puede configurar un solo boton que active múltiples botones en la GBA. > Rapid-fire buttons: Estas asignaciones son opcionales, se pueden pulsar A, y luego dos botones a la vez para eliminarlas. Los botones de disparo rápido (Turbo) pulsan y sueltan el botón de GBA a 30 Hz: son presionados durante 1/60 de segundo, entonces se sueltan durante el mismo tiempo. -> Analog sensitivity (Sólo GCW Zero): Este ajuste controla cuanto tiene que moverse el stick analógico para activar una dirección. El stick analógico se puede utilizar para navegar por los menús con esta sensibilidad también. -> Analog in-game binding (Sólo GCW Zero): "None" no permite controlar el juego de GBA con el stick analógico, pero permite que sea utilizado para teclas de acceso rápido. "GBA D-pad" permite controlar el juego de GBA con el stick analógico de acuerdo con el ajuste de la sensibilidad, así como teclas de acceso rápido. +> Analogs sensitivity (Sólo GCW Zero): Este ajuste controla cuanto tiene que moverse el stick analógico para activar una dirección. El stick analógico se puede utilizar para navegar por los menús con esta sensibilidad también. +> L-Analog in-game binding (Sólo GCW Zero): "None" no permite controlar el juego de GBA con el stick analógico, pero permite que sea utilizado para teclas de acceso rápido. "GBA D-pad" permite controlar el juego de GBA con el stick analógico de acuerdo con el ajuste de la sensibilidad, así como teclas de acceso rápido. - Teclas de Acceso Rápido (Hotkeys) - Presione A en ellos, y se puede establecer una nueva combinación de botones en el dispositivo para activar cada función durante la emulación, o B para borrar la asignación. diff --git a/source/opendingux/data/manual-fr.txt b/source/opendingux/data/manual-fr.txt index fa3dca8e..87cf902c 100644 --- a/source/opendingux/data/manual-fr.txt +++ b/source/opendingux/data/manual-fr.txt @@ -47,8 +47,8 @@ Dans le Menu Principal ou tout sous-menu comportant des options, vous pouvez app - Réglages d'entrée (Input Settings) - > Boutons GBA: Appuyez sur A sur une de ces options et vous pouvez affecter un nouveau bouton sur votre dispositif à celui de la GBA. Ces affectations sont obligatoires; il est impossible de ne rien affecter à un certain bouton de la GBA. Par contre, vous pouvez affecter le même bouton sur votre dispositif à plusieurs boutons de la GBA. > Boutons de tir rapide (Rapid-fire): Ces affectations sont facultatives; vous pouvez appuyer sur A, puis sur deux boutons à la fois pour les effacer. Les boutons de tir rapide pressent et relâchent un bouton à 30 Hz: le bouton est pressé pendant 1/60 de seconde, puis relâché pendant ce même temps. -> Analog sensitivity (GCW Zero seulement): Cette option contrôle la sensibilité du stick analogique, soit la quantité de mouvement requise dans une direction. Vous pouvez aussi utiliser le stick analogique pour naviguer dans le menu avec cette valeur de sensibilité. -> Analog in-game binding (GCW Zero seulement): "None" ne permet pas au stick analogique de contrôler le pavé directionnel de la GBA, seulement d'être utilisé pour des raccourcis. "GBA D-pad" permet au stick analogique de déclencher le pavé directionnel de la GBA ainsi que les raccourcis. +> Analogs sensitivity (GCW Zero seulement): Cette option contrôle la sensibilité du stick analogique, soit la quantité de mouvement requise dans une direction. Vous pouvez aussi utiliser le stick analogique pour naviguer dans le menu avec cette valeur de sensibilité. +> L-Analog in-game binding (GCW Zero seulement): "None" ne permet pas au stick analogique de contrôler le pavé directionnel de la GBA, seulement d'être utilisé pour des raccourcis. "GBA D-pad" permet au stick analogique de déclencher le pavé directionnel de la GBA ainsi que les raccourcis. - Raccourcis (Hotkeys) - Appuyez sur A sur une de ces options et vous pouvez affecter une nouvelle combinaison de boutons sur votre dispositif pour déclencher chaque fonction, ou bien B pour effacer l'affectation. diff --git a/source/opendingux/draw.c b/source/opendingux/draw.c index 02912d72..84643e2e 100644 --- a/source/opendingux/draw.c +++ b/source/opendingux/draw.c @@ -61,7 +61,7 @@ static struct timespec LastProgressUpdate; void init_video() { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO /*| SDL_INIT_JOYSTICK*/) < 0) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { printf("Failed to initialize SDL !!\n"); return; // for debug diff --git a/source/opendingux/gui.c b/source/opendingux/gui.c index 9f3a5d17..c9388be4 100644 --- a/source/opendingux/gui.c +++ b/source/opendingux/gui.c @@ -406,22 +406,31 @@ static void SavedStateMenuEnd(struct Menu* ActiveMenu) // -- Custom display -- static char* OpenDinguxButtonText[OPENDINGUX_BUTTON_COUNT] = { + TOP_FACE_BUTTON_NAME, // (GCW Y, A320 or RG350 X) + "A", + "B", + LEFT_FACE_BUTTON_NAME, // (GCW X, A320 or RG350 Y) "L", "R", - "D-pad Down", + "L2", + "R2", + "Select", + "Start", + "L3", + "R3", "D-pad Up", - "D-pad Left", "D-pad Right", - "Start", - "Select", - "B", - "A", - LEFT_FACE_BUTTON_NAME, - TOP_FACE_BUTTON_NAME, - "Analog Down", - "Analog Up", - "Analog Left", - "Analog Right", + "D-pad Down", + "D-pad Left", + "POWER", + "L-Analog Down", + "L-Analog Up", + "L-Analog Left", + "L-Analog Right", + "R-Analog Down", + "R-Analog Up", + "R-Analog Left", + "R-Analog Right", }; /* @@ -573,22 +582,31 @@ static void SavedStateUpdatePreview(struct Menu* ActiveMenu) // -- Custom saving -- static char OpenDinguxButtonSave[OPENDINGUX_BUTTON_COUNT] = { - 'L', - 'R', - 'v', // D-pad directions. - '^', - '<', - '>', // (end) - 'S', - 's', - 'B', + 'X', // Using the SNES/DS/A320 mapping, this is the upper face button. 'A', + 'B', 'Y', // Using the SNES/DS/A320 mapping, this is the left face button. - 'X', // Using the SNES/DS/A320 mapping, this is the upper face button. - 'd', // Analog nub directions (GCW Zero). - 'u', - 'l', - 'r', // (end) + 'L', + 'R', + '+', // L2 + '-', // R2 + 's', // Select + 'S', // Start + '1', // L3 + '2', // R3 + '^', // D-pad directions. + '>', + 'v', + '<', // (end) + 'M', // Menu/Power + 'd', // L-analog down + 'u', // L-analog up + 'l', // L-analog left + 'r', // L-analog right + '3', // R-analog down + '4', // R-analog up + '5', // R-analog left + '6', // R-analog right }; static void LoadMappingFunction(struct MenuEntry* ActiveMenuEntry, char* Value) @@ -1302,20 +1320,20 @@ static struct MenuEntry InputMenu_RapidB = { #ifdef GCW_ZERO static struct MenuEntry PerGameInputMenu_AnalogSensitivity = { - ENTRY_OPTION("analog_sensitivity", "Analog sensitivity", &PerGameAnalogSensitivity), + ENTRY_OPTION("analog_sensitivity", "Analogs sensitivity", &PerGameAnalogSensitivity), .ChoiceCount = 6, .Choices = { { "No override", "" }, { "Very low", "lowest" }, { "Low", "low" }, { "Medium", "medium" }, { "High", "high" }, { "Very high", "highest" } } }; static struct MenuEntry InputMenu_AnalogSensitivity = { - ENTRY_OPTION("analog_sensitivity", "Analog sensitivity", &AnalogSensitivity), + ENTRY_OPTION("analog_sensitivity", "Analogs sensitivity", &AnalogSensitivity), .ChoiceCount = 5, .Choices = { { "Very low", "lowest" }, { "Low", "low" }, { "Medium", "medium" }, { "High", "high" }, { "Very high", "highest" } } }; static struct MenuEntry PerGameInputMenu_AnalogAction = { - ENTRY_OPTION("analog_action", "Analog in-game binding", &PerGameAnalogAction), + ENTRY_OPTION("analog_action", "L-Analog in-game binding", &PerGameAnalogAction), .ChoiceCount = 3, .Choices = { { "No override", "" }, { "None", "none" }, { "GBA D-pad", "dpad" } } }; static struct MenuEntry InputMenu_AnalogAction = { - ENTRY_OPTION("analog_action", "Analog in-game binding", &AnalogAction), + ENTRY_OPTION("analog_action", "L-Analog in-game binding", &AnalogAction), .ChoiceCount = 2, .Choices = { { "None", "none" }, { "GBA D-pad", "dpad" } } }; #endif diff --git a/source/opendingux/od-input.c b/source/opendingux/od-input.c index a2f2c3c3..57b37d27 100644 --- a/source/opendingux/od-input.c +++ b/source/opendingux/od-input.c @@ -32,35 +32,58 @@ uint32_t AnalogAction = 0; uint_fast8_t FastForwardFrameskipControl = 0; -//static SDL_Joystick* Joystick; - -static bool JoystickInitialised = false; +// 0 for native analog sticks, 1 for extra joystick (USB) +static SDL_Joystick *Joysticks[2]; +static bool JoysticksInitialised[2] = {false, false}; // Mandatory remapping for OpenmDingux keys. Each OpenmDingux key maps to a // key on the keyboard, but not all keys on the keyboard map to these. // They are not in GBA bitfield order in this array. uint32_t OpenDinguxKeys[OPENDINGUX_BUTTON_COUNT] = { + SDLK_SPACE, // Upper face button (GCW Y, A320/RG350 X) + SDLK_LCTRL, // Right face button (A) + SDLK_LALT, // Lower face button (B) + SDLK_LSHIFT, // Left face button (GCW X, A320/RG350 Y) SDLK_TAB, // L SDLK_BACKSPACE, // R - SDLK_DOWN, // Down +#ifdef RG350 + SDLK_PAGEUP, // RG350: L2 + SDLK_PAGEDOWN, // RG350: R2 +#elif defined PLAYGO + SDLK_RSHIFT, // PLAYGO: L2 + SDLK_RALT, // PLAYGO: R2 +#else + 0, // no L2 + 0, // no R2 +#endif + SDLK_ESCAPE, // Select + SDLK_RETURN, // Start +#ifdef RG350 + SDLK_KP_DIVIDE, // RG350: L3 + SDLK_KP_PERIOD, // RG350: R3 +#else + 0, // no L3 + 0, // no R3 +#endif SDLK_UP, // Up - SDLK_LEFT, // Left SDLK_RIGHT, // Right - SDLK_RETURN, // Start - SDLK_ESCAPE, // Select - SDLK_LALT, // Lower face button (B) - SDLK_LCTRL, // Right face button (A) - SDLK_LSHIFT, // Left face button (GCW X, A320 Y) - SDLK_SPACE, // Upper face button (GCW Y, A320 X) - 0, - 0, - 0, - 0, + SDLK_DOWN, // Down + SDLK_LEFT, // Left #ifdef RG350 - SDLK_HOME, // RG359: Quick flick of Power + SDLK_HOME, // RG350: Quick flick of Power +#elif defined PLAYGO + SDLK_RCTRL, // PLAYGO: Menu face button #else SDLK_3, // GCW: Quick flick of Power #endif + 0, // Left analog down + 0, // Left analog up + 0, // Left analog left + 0, // Left analog right + 0, // Right analog down + 0, // Right analog up + 0, // Right analog left + 0, // Right analog right }; // These must be OpenDingux buttons at the bit suitable for the ReGBA_Buttons @@ -130,12 +153,12 @@ enum OpenDingux_Buttons Hotkeys[5] = { // pressed. For example, when the user keeps a direction pressed but also // presses A, start ignoring the direction. enum OpenDingux_Buttons MenuKeys[7] = { - OPENDINGUX_BUTTON_FACE_RIGHT, // Select/Enter button - OPENDINGUX_BUTTON_FACE_DOWN, // Cancel/Leave button - OPENDINGUX_BUTTON_DOWN | OPENDINGUX_ANALOG_DOWN, // Menu navigation - OPENDINGUX_BUTTON_UP | OPENDINGUX_ANALOG_UP, - OPENDINGUX_BUTTON_RIGHT | OPENDINGUX_ANALOG_RIGHT, - OPENDINGUX_BUTTON_LEFT | OPENDINGUX_ANALOG_LEFT, + OPENDINGUX_BUTTON_FACE_RIGHT, // Select/Enter button + OPENDINGUX_BUTTON_FACE_DOWN, // Cancel/Leave button + OPENDINGUX_BUTTON_DOWN | OPENDINGUX_L_ANALOG_DOWN, // Menu navigation + OPENDINGUX_BUTTON_UP | OPENDINGUX_L_ANALOG_UP, + OPENDINGUX_BUTTON_RIGHT | OPENDINGUX_L_ANALOG_RIGHT, + OPENDINGUX_BUTTON_LEFT | OPENDINGUX_L_ANALOG_LEFT, OPENDINGUX_BUTTON_SELECT, }; @@ -156,6 +179,44 @@ enum GUI_Action MenuKeysToGUI[7] = { // FutureButtons alows any number of state changes per button. static enum OpenDingux_Buttons LastButtons = 0, CurButtons = 0, FutureButtons = 0; +// but_index is the index of the pressed button in the OpenDinguxKeys array +static void ButtonPress(uint_fast8_t but_index) +{ + FutureButtons |= 1 << but_index; + if ((LastButtons & (1 << but_index)) == (CurButtons & (1 << but_index))) + CurButtons |= 1 << but_index; +} + +// but_index is the index of the release button in the OpenDinguxKeys array +static void ButtonRelease(uint_fast8_t but_index) +{ + FutureButtons &= ~(1 << but_index); + if ((LastButtons & (1 << but_index)) == (CurButtons & (1 << but_index))) + CurButtons &= ~(1 << but_index); +} + +static void ReadLeftStick(uint_fast8_t js) +{ + int16_t Threshold = (4 - ResolveSetting(AnalogSensitivity, PerGameAnalogSensitivity)) * 7808 + 1024; + int16_t x, y; + x = GetAxis(js, JS_AXIS_LEFT_HORIZONTAL), y = GetAxis(js, JS_AXIS_LEFT_VERTICAL); + if (x > Threshold) CurButtons |= OPENDINGUX_L_ANALOG_RIGHT; + else if (x < -Threshold) CurButtons |= OPENDINGUX_L_ANALOG_LEFT; + if (y > Threshold) CurButtons |= OPENDINGUX_L_ANALOG_DOWN; + else if (y < -Threshold) CurButtons |= OPENDINGUX_L_ANALOG_UP; +} + +static void ReadRightStick(uint_fast8_t js) +{ + int16_t Threshold = (4 - ResolveSetting(AnalogSensitivity, PerGameAnalogSensitivity)) * 7808 + 1024; + int16_t x, y; + x = GetAxis(js, JS_AXIS_RIGHT_HORIZONTAL), y = GetAxis(js, JS_AXIS_RIGHT_VERTICAL); + if (x > Threshold) CurButtons |= OPENDINGUX_R_ANALOG_RIGHT; + else if (x < -Threshold) CurButtons |= OPENDINGUX_R_ANALOG_LEFT; + if (y > Threshold) CurButtons |= OPENDINGUX_R_ANALOG_DOWN; + else if (y < -Threshold) CurButtons |= OPENDINGUX_R_ANALOG_UP; +} + static void UpdateOpenDinguxButtons() { SDL_Event ev; @@ -165,13 +226,12 @@ static void UpdateOpenDinguxButtons() { switch (ev.type) { + // -- handling native buttons -- case SDL_KEYDOWN: for (i = 0; i < sizeof(OpenDinguxKeys) / sizeof(OpenDinguxKeys[0]); i++) if (ev.key.keysym.sym == OpenDinguxKeys[i]) { - FutureButtons |= 1 << i; - if ((LastButtons & (1 << i)) == (CurButtons & (1 << i))) - CurButtons |= 1 << i; + ButtonPress(i); break; } break; @@ -179,25 +239,53 @@ static void UpdateOpenDinguxButtons() for (i = 0; i < sizeof(OpenDinguxKeys) / sizeof(OpenDinguxKeys[0]); i++) if (ev.key.keysym.sym == OpenDinguxKeys[i]) { - FutureButtons &= ~(1 << i); - if ((LastButtons & (1 << i)) == (CurButtons & (1 << i))) - CurButtons &= ~(1 << i); + ButtonRelease(i); break; } break; + + // -- handling USB joystick buttons -- + case SDL_JOYBUTTONDOWN: + ButtonPress(ev.jbutton.button); + break; + case SDL_JOYBUTTONUP: + ButtonRelease(ev.jbutton.button); + break; + + // -- handling USB joystick D-pad (HAT) -- + case SDL_JOYHATMOTION: + // reset hat + ButtonRelease(OPENDINGUX_BUTTON_INDEX_UP); + ButtonRelease(OPENDINGUX_BUTTON_INDEX_RIGHT); + ButtonRelease(OPENDINGUX_BUTTON_INDEX_DOWN); + ButtonRelease(OPENDINGUX_BUTTON_INDEX_LEFT); + // get pressed direction(s) + if (ev.jhat.value & SDL_HAT_UP) ButtonPress(OPENDINGUX_BUTTON_INDEX_UP); + if (ev.jhat.value & SDL_HAT_RIGHT) ButtonPress(OPENDINGUX_BUTTON_INDEX_RIGHT); + if (ev.jhat.value & SDL_HAT_DOWN) ButtonPress(OPENDINGUX_BUTTON_INDEX_DOWN); + if (ev.jhat.value & SDL_HAT_LEFT) ButtonPress(OPENDINGUX_BUTTON_INDEX_LEFT); + break; + default: break; } } - CurButtons &= ~(OPENDINGUX_ANALOG_LEFT | OPENDINGUX_ANALOG_RIGHT - | OPENDINGUX_ANALOG_UP | OPENDINGUX_ANALOG_DOWN); - int16_t X = GetHorizontalAxisValue(), Y = GetVerticalAxisValue(), - Threshold = (4 - ResolveSetting(AnalogSensitivity, PerGameAnalogSensitivity)) * 7808 + 1024; - if (X > Threshold) CurButtons |= OPENDINGUX_ANALOG_RIGHT; - else if (X < -Threshold) CurButtons |= OPENDINGUX_ANALOG_LEFT; - if (Y > Threshold) CurButtons |= OPENDINGUX_ANALOG_DOWN; - else if (Y < -Threshold) CurButtons |= OPENDINGUX_ANALOG_UP; + // -- handling analog sticks -- + + // clean left and right analog bits + CurButtons &= ~(OPENDINGUX_L_ANALOG_LEFT | OPENDINGUX_L_ANALOG_RIGHT + | OPENDINGUX_L_ANALOG_UP | OPENDINGUX_L_ANALOG_DOWN); + CurButtons &= ~(OPENDINGUX_R_ANALOG_LEFT | OPENDINGUX_R_ANALOG_RIGHT + | OPENDINGUX_R_ANALOG_UP | OPENDINGUX_R_ANALOG_DOWN); + + // native joystick + ReadLeftStick(0); + ReadRightStick(0); + + // usb joytick + ReadLeftStick(1); + ReadRightStick(1); } static bool IsFastForwardToggled = false; @@ -290,10 +378,10 @@ enum ReGBA_Buttons ReGBA_GetPressedButtons() } if (ResolveSetting(AnalogAction, PerGameAnalogAction) == 1) { - if (LastButtons & OPENDINGUX_ANALOG_LEFT) Result |= REGBA_BUTTON_LEFT; - if (LastButtons & OPENDINGUX_ANALOG_RIGHT) Result |= REGBA_BUTTON_RIGHT; - if (LastButtons & OPENDINGUX_ANALOG_UP) Result |= REGBA_BUTTON_UP; - if (LastButtons & OPENDINGUX_ANALOG_DOWN) Result |= REGBA_BUTTON_DOWN; + if (LastButtons & OPENDINGUX_L_ANALOG_LEFT) Result |= REGBA_BUTTON_LEFT; + if (LastButtons & OPENDINGUX_L_ANALOG_RIGHT) Result |= REGBA_BUTTON_RIGHT; + if (LastButtons & OPENDINGUX_L_ANALOG_UP) Result |= REGBA_BUTTON_UP; + if (LastButtons & OPENDINGUX_L_ANALOG_DOWN) Result |= REGBA_BUTTON_DOWN; } if ((Result & REGBA_BUTTON_LEFT) && (Result & REGBA_BUTTON_RIGHT)) @@ -325,12 +413,12 @@ bool IsImpossibleHotkey(enum OpenDingux_Buttons Hotkey) if ((Hotkey & (OPENDINGUX_BUTTON_UP | OPENDINGUX_BUTTON_DOWN)) == (OPENDINGUX_BUTTON_UP | OPENDINGUX_BUTTON_DOWN)) return true; #if defined DINGOO_A320 - if (Hotkey & (OPENDINGUX_ANALOG_LEFT | OPENDINGUX_ANALOG_RIGHT | OPENDINGUX_ANALOG_UP | OPENDINGUX_ANALOG_DOWN)) + if (Hotkey & (OPENDINGUX_L_ANALOG_LEFT | OPENDINGUX_L_ANALOG_RIGHT | OPENDINGUX_L_ANALOG_UP | OPENDINGUX_L_ANALOG_DOWN)) return true; #elif defined GCW_ZERO - if ((Hotkey & (OPENDINGUX_ANALOG_LEFT | OPENDINGUX_ANALOG_RIGHT)) == (OPENDINGUX_ANALOG_LEFT | OPENDINGUX_ANALOG_RIGHT)) + if ((Hotkey & (OPENDINGUX_L_ANALOG_LEFT | OPENDINGUX_L_ANALOG_RIGHT)) == (OPENDINGUX_L_ANALOG_LEFT | OPENDINGUX_L_ANALOG_RIGHT)) return true; - if ((Hotkey & (OPENDINGUX_ANALOG_UP | OPENDINGUX_ANALOG_DOWN)) == (OPENDINGUX_ANALOG_UP | OPENDINGUX_ANALOG_DOWN)) + if ((Hotkey & (OPENDINGUX_L_ANALOG_UP | OPENDINGUX_L_ANALOG_DOWN)) == (OPENDINGUX_L_ANALOG_UP | OPENDINGUX_L_ANALOG_DOWN)) return true; #endif return false; @@ -346,35 +434,23 @@ enum OpenDingux_Buttons GetPressedOpenDinguxButtons() return LastButtons & ~OPENDINGUX_BUTTON_MENU; } -static void EnsureJoystick() +static void EnsureJoystick(uint_fast8_t js) { - // if (!JoystickInitialised) - // { - // JoystickInitialised = true; - // Joystick = SDL_JoystickOpen(0); - // if (Joystick == NULL) - // { - // ReGBA_Trace("I: Joystick #0 could not be opened"); - // } - // } -} - -int16_t GetHorizontalAxisValue() -{ - // EnsureJoystick(); - // if (Joystick != NULL) - // return SDL_JoystickGetAxis(Joystick, 0); - // else - return 0; + if (!JoysticksInitialised[js]) + { + JoysticksInitialised[js] = true; + Joysticks[js] = SDL_JoystickOpen(js); + if (Joysticks[js] == NULL) + { + ReGBA_Trace("I: Joystick could not be opened"); + } + } } -int16_t GetVerticalAxisValue() +int16_t GetAxis(uint_fast8_t js, enum Joystick_Stick_Axis axis) { - // EnsureJoystick(); - // if (Joystick != NULL) - // return SDL_JoystickGetAxis(Joystick, 1); - // else - return 0; + EnsureJoystick(js); + return (Joysticks[js] != NULL) ? SDL_JoystickGetAxis(Joysticks[js], axis) : 0; } enum GUI_ActionRepeatState diff --git a/source/opendingux/od-input.h b/source/opendingux/od-input.h index 409a107f..b66ac06b 100644 --- a/source/opendingux/od-input.h +++ b/source/opendingux/od-input.h @@ -20,27 +20,46 @@ #ifndef __OD_INPUT_H__ #define __OD_INPUT_H__ -#define OPENDINGUX_BUTTON_COUNT 17 +#define OPENDINGUX_BUTTON_COUNT 25 // These must be in the order defined in OpenDinguxKeys in od-input.c. +// The order of the buttons 0 to 15 must not change because these must also +// match the codes of the SDL joystick buttons (USB joystick) enum OpenDingux_Buttons { - OPENDINGUX_BUTTON_L = 0x00001, - OPENDINGUX_BUTTON_R = 0x00002, - OPENDINGUX_BUTTON_DOWN = 0x00004, - OPENDINGUX_BUTTON_UP = 0x00008, - OPENDINGUX_BUTTON_LEFT = 0x00010, - OPENDINGUX_BUTTON_RIGHT = 0x00020, - OPENDINGUX_BUTTON_START = 0x00040, - OPENDINGUX_BUTTON_SELECT = 0x00080, - OPENDINGUX_BUTTON_FACE_DOWN = 0x00100, - OPENDINGUX_BUTTON_FACE_RIGHT = 0x00200, - OPENDINGUX_BUTTON_FACE_LEFT = 0x00400, - OPENDINGUX_BUTTON_FACE_UP = 0x00800, - OPENDINGUX_ANALOG_DOWN = 0x01000, - OPENDINGUX_ANALOG_UP = 0x02000, - OPENDINGUX_ANALOG_LEFT = 0x04000, - OPENDINGUX_ANALOG_RIGHT = 0x08000, - OPENDINGUX_BUTTON_MENU = 0x10000, + OPENDINGUX_BUTTON_FACE_UP = 1 << 0, + OPENDINGUX_BUTTON_FACE_RIGHT = 1 << 1, + OPENDINGUX_BUTTON_FACE_DOWN = 1 << 2, + OPENDINGUX_BUTTON_FACE_LEFT = 1 << 3, + OPENDINGUX_BUTTON_L = 1 << 4, + OPENDINGUX_BUTTON_R = 1 << 5, + OPENDINGUX_BUTTON_L2 = 1 << 6, + OPENDINGUX_BUTTON_R2 = 1 << 7, + OPENDINGUX_BUTTON_SELECT = 1 << 8, + OPENDINGUX_BUTTON_START = 1 << 9, + OPENDINGUX_BUTTON_L3 = 1 << 10, + OPENDINGUX_BUTTON_R3 = 1 << 11, + OPENDINGUX_BUTTON_UP = 1 << 12, + OPENDINGUX_BUTTON_RIGHT = 1 << 13, + OPENDINGUX_BUTTON_DOWN = 1 << 14, + OPENDINGUX_BUTTON_LEFT = 1 << 15, + OPENDINGUX_BUTTON_MENU = 1 << 16, + OPENDINGUX_L_ANALOG_DOWN = 1 << 17, + OPENDINGUX_L_ANALOG_UP = 1 << 18, + OPENDINGUX_L_ANALOG_LEFT = 1 << 19, + OPENDINGUX_L_ANALOG_RIGHT = 1 << 20, + OPENDINGUX_R_ANALOG_DOWN = 1 << 21, + OPENDINGUX_R_ANALOG_UP = 1 << 22, + OPENDINGUX_R_ANALOG_LEFT = 1 << 23, + OPENDINGUX_R_ANALOG_RIGHT = 1 << 24, +}; + +// we need the following indexes to get input from the USB joystick +// those must match the indexes of the array OpenDinguxKeys +enum OpenDingux_Buttons_Index { + OPENDINGUX_BUTTON_INDEX_UP = 12, + OPENDINGUX_BUTTON_INDEX_RIGHT = 13, + OPENDINGUX_BUTTON_INDEX_DOWN = 14, + OPENDINGUX_BUTTON_INDEX_LEFT = 15, }; enum GUI_Action { @@ -54,6 +73,13 @@ enum GUI_Action { GUI_ACTION_ALTERNATE, }; +enum Joystick_Stick_Axis { + JS_AXIS_LEFT_HORIZONTAL = 0, + JS_AXIS_LEFT_VERTICAL = 1, + JS_AXIS_RIGHT_HORIZONTAL = 2, + JS_AXIS_RIGHT_VERTICAL = 3, +}; + // 0 if not fast-forwarding. // Otherwise, the amount of frames to skip per rendered frame. // 1 amounts to targetting 200% real-time; @@ -86,18 +112,12 @@ extern uint32_t AnalogAction; extern uint_fast8_t FastForwardFrameskipControl; /* - * Gets the current value of the analog horizontal axis. - * Returns: - * A value between -32768 (left) and 32767 (right). - */ -extern int16_t GetHorizontalAxisValue(); - -/* - * Gets the current value of the analog vertical axis. + * Gets the current value of an analog axis. + * Use js = 0 for native joystick or js = 1 for an extra USB joystick. * Returns: - * A value between -32768 (up) and 32767 (down). + * A value between -32768 (left/up) and 32767 (right/down). */ -extern int16_t GetVerticalAxisValue(); +extern int16_t GetAxis(uint_fast8_t js, enum Joystick_Stick_Axis axis); /* * Reads the buttons pressed at the time of the function call on the input @@ -118,7 +138,8 @@ extern int16_t GetVerticalAxisValue(); */ extern enum GUI_Action GetGUIAction(); -#if defined GCW_ZERO +// X and Y labels are inverted in some devices +#if defined(GCW_ZERO) && !defined(RG350) # define LEFT_FACE_BUTTON_NAME "X" # define TOP_FACE_BUTTON_NAME "Y" #else