mirror of https://github.com/mgba-emu/mgba.git
First pass at input mapping
This commit is contained in:
parent
f55d085162
commit
3051143fa3
|
@ -0,0 +1,84 @@
|
||||||
|
#include "gba-input.h"
|
||||||
|
|
||||||
|
struct GBAInputMapImpl {
|
||||||
|
int* map;
|
||||||
|
uint32_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GBAInputMapInit(struct GBAInputMap* map) {
|
||||||
|
map->maps = 0;
|
||||||
|
map->numMaps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBAInputMapDeinit(struct GBAInputMap* map) {
|
||||||
|
size_t m;
|
||||||
|
for (m = 0; m < map->numMaps; ++m) {
|
||||||
|
free(map->maps[m].map);
|
||||||
|
}
|
||||||
|
free(map->maps);
|
||||||
|
map->maps = 0;
|
||||||
|
map->numMaps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GBAKey GBAInputMapKey(struct GBAInputMap* map, uint32_t type, int key) {
|
||||||
|
size_t m;
|
||||||
|
struct GBAInputMapImpl* impl = 0;
|
||||||
|
for (m = 0; m < map->numMaps; ++m) {
|
||||||
|
if (map->maps[m].type == type) {
|
||||||
|
impl = &map->maps[m];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!impl || !impl->map) {
|
||||||
|
return GBA_KEY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (m = 0; m < GBA_KEY_MAX; ++m) {
|
||||||
|
if (impl->map[m] == key) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GBA_KEY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBAInputBindKey(struct GBAInputMap* map, uint32_t type, int key, enum GBAKey input) {
|
||||||
|
struct GBAInputMapImpl* impl = 0;
|
||||||
|
if (map->numMaps == 0) {
|
||||||
|
map->maps = malloc(sizeof(*map->maps));
|
||||||
|
map->numMaps = 1;
|
||||||
|
impl = &map->maps[0];
|
||||||
|
impl->type = type;
|
||||||
|
impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
|
||||||
|
} else {
|
||||||
|
size_t m;
|
||||||
|
for (m = 0; m < map->numMaps; ++m) {
|
||||||
|
if (map->maps[m].type == type) {
|
||||||
|
impl = &map->maps[m];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!impl) {
|
||||||
|
size_t m;
|
||||||
|
for (m = 0; m < map->numMaps; ++m) {
|
||||||
|
if (!map->maps[m].type) {
|
||||||
|
impl = &map->maps[m];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (impl) {
|
||||||
|
impl->type = type;
|
||||||
|
impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
|
||||||
|
} else {
|
||||||
|
map->maps = realloc(map->maps, sizeof(*map->maps) * map->numMaps * 2);
|
||||||
|
for (m = map->numMaps * 2 - 1; m > map->numMaps; --m) {
|
||||||
|
map->maps[m].type = 0;
|
||||||
|
map->maps[m].map = 0;
|
||||||
|
}
|
||||||
|
impl = &map->maps[m];
|
||||||
|
impl->type = type;
|
||||||
|
impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl->map[input] = key;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef GBA_INPUT_H
|
||||||
|
#define GBA_INPUT_H
|
||||||
|
|
||||||
|
#include "gba.h"
|
||||||
|
|
||||||
|
struct GBAInputMap {
|
||||||
|
struct GBAInputMapImpl* maps;
|
||||||
|
size_t numMaps;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GBAInputMapInit(struct GBAInputMap*);
|
||||||
|
void GBAInputMapDeinit(struct GBAInputMap*);
|
||||||
|
|
||||||
|
enum GBAKey GBAInputMapKey(struct GBAInputMap*, uint32_t type, int key);
|
||||||
|
void GBAInputBindKey(struct GBAInputMap*, uint32_t type, int key, enum GBAKey input);
|
||||||
|
|
||||||
|
#endif
|
|
@ -390,6 +390,8 @@ void GBAThreadJoin(struct GBAThread* threadContext) {
|
||||||
}
|
}
|
||||||
free(threadContext->rewindBuffer);
|
free(threadContext->rewindBuffer);
|
||||||
|
|
||||||
|
GBAInputMapDeinit(&threadContext->inputMap);
|
||||||
|
|
||||||
if (threadContext->rom) {
|
if (threadContext->rom) {
|
||||||
threadContext->rom->close(threadContext->rom);
|
threadContext->rom->close(threadContext->rom);
|
||||||
threadContext->rom = 0;
|
threadContext->rom = 0;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include "gba.h"
|
#include "gba.h"
|
||||||
|
#include "gba-input.h"
|
||||||
|
|
||||||
#include "util/threading.h"
|
#include "util/threading.h"
|
||||||
#include "platform/commandline.h"
|
#include "platform/commandline.h"
|
||||||
|
@ -56,6 +57,7 @@ struct GBAThread {
|
||||||
struct VFile* patch;
|
struct VFile* patch;
|
||||||
const char* fname;
|
const char* fname;
|
||||||
int activeKeys;
|
int activeKeys;
|
||||||
|
struct GBAInputMap inputMap;
|
||||||
|
|
||||||
// Run-time options
|
// Run-time options
|
||||||
int frameskip;
|
int frameskip;
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum GBAKey {
|
||||||
GBA_KEY_DOWN = 7,
|
GBA_KEY_DOWN = 7,
|
||||||
GBA_KEY_R = 8,
|
GBA_KEY_R = 8,
|
||||||
GBA_KEY_L = 9,
|
GBA_KEY_L = 9,
|
||||||
|
GBA_KEY_MAX,
|
||||||
GBA_KEY_NONE = -1
|
GBA_KEY_NONE = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@ int main(int argc, char** argv) {
|
||||||
renderer.audio.samples = context.audioBuffers;
|
renderer.audio.samples = context.audioBuffers;
|
||||||
GBASDLInitAudio(&renderer.audio);
|
GBASDLInitAudio(&renderer.audio);
|
||||||
|
|
||||||
|
renderer.events.bindings = &context.inputMap;
|
||||||
|
GBASDLInitEvents(&renderer.events);
|
||||||
|
|
||||||
GBAThreadStart(&context);
|
GBAThreadStart(&context);
|
||||||
|
|
||||||
_GBASDLRunloop(&context, &renderer);
|
_GBASDLRunloop(&context, &renderer);
|
||||||
|
@ -118,7 +121,6 @@ static int _GBASDLInit(struct GLSoftwareRenderer* renderer) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GBASDLInitEvents(&renderer->events);
|
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#define GUI_MOD KMOD_CTRL
|
#define GUI_MOD KMOD_CTRL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SDL_BINDING_KEY 0x53444C4B
|
||||||
|
#define SDL_BINDING_BUTTON 0x53444C42
|
||||||
|
|
||||||
bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -21,6 +24,24 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_z, GBA_KEY_A);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_x, GBA_KEY_B);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_a, GBA_KEY_L);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_s, GBA_KEY_R);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_RETURN, GBA_KEY_START);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_BACKSPACE, GBA_KEY_SELECT);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_UP, GBA_KEY_UP);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_DOWN, GBA_KEY_DOWN);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_LEFT, GBA_KEY_LEFT);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_KEY, SDLK_RIGHT, GBA_KEY_RIGHT);
|
||||||
|
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 2, GBA_KEY_A);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 1, GBA_KEY_B);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 6, GBA_KEY_L);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 7, GBA_KEY_R);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 8, GBA_KEY_START);
|
||||||
|
GBAInputBindKey(context->bindings, SDL_BINDING_BUTTON, 9, GBA_KEY_SELECT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,64 +50,25 @@ void GBASDLDeinitEvents(struct GBASDLEvents* context) {
|
||||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GBAKey GBASDLMapButtonToKey(int button) {
|
|
||||||
// Sorry, hardcoded to my gamepad for now
|
|
||||||
switch (button) {
|
|
||||||
case 2:
|
|
||||||
return GBA_KEY_A;
|
|
||||||
case 1:
|
|
||||||
return GBA_KEY_B;
|
|
||||||
case 6:
|
|
||||||
return GBA_KEY_L;
|
|
||||||
case 7:
|
|
||||||
return GBA_KEY_R;
|
|
||||||
case 8:
|
|
||||||
return GBA_KEY_START;
|
|
||||||
case 9:
|
|
||||||
return GBA_KEY_SELECT;
|
|
||||||
default:
|
|
||||||
return GBA_KEY_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _pauseAfterFrame(struct GBAThread* context) {
|
static void _pauseAfterFrame(struct GBAThread* context) {
|
||||||
context->frameCallback = 0;
|
context->frameCallback = 0;
|
||||||
GBAThreadPauseFromThread(context);
|
GBAThreadPauseFromThread(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents* sdlContext, const struct SDL_KeyboardEvent* event) {
|
static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents* sdlContext, const struct SDL_KeyboardEvent* event) {
|
||||||
enum GBAKey key = 0;
|
enum GBAKey key = GBA_KEY_NONE;
|
||||||
|
if (!event->keysym.mod) {
|
||||||
|
key = GBAInputMapKey(&context->inputMap, SDL_BINDING_KEY, event->keysym.sym);
|
||||||
|
}
|
||||||
|
if (key != GBA_KEY_NONE) {
|
||||||
|
if (event->type == SDL_KEYDOWN) {
|
||||||
|
context->activeKeys |= 1 << key;
|
||||||
|
} else {
|
||||||
|
context->activeKeys &= ~(1 << key);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (event->keysym.sym) {
|
switch (event->keysym.sym) {
|
||||||
case SDLK_z:
|
|
||||||
key = GBA_KEY_A;
|
|
||||||
break;
|
|
||||||
case SDLK_x:
|
|
||||||
key = GBA_KEY_B;
|
|
||||||
break;
|
|
||||||
case SDLK_a:
|
|
||||||
key = GBA_KEY_L;
|
|
||||||
break;
|
|
||||||
case SDLK_s:
|
|
||||||
key = GBA_KEY_R;
|
|
||||||
break;
|
|
||||||
case SDLK_RETURN:
|
|
||||||
key = GBA_KEY_START;
|
|
||||||
break;
|
|
||||||
case SDLK_BACKSPACE:
|
|
||||||
key = GBA_KEY_SELECT;
|
|
||||||
break;
|
|
||||||
case SDLK_UP:
|
|
||||||
key = GBA_KEY_UP;
|
|
||||||
break;
|
|
||||||
case SDLK_DOWN:
|
|
||||||
key = GBA_KEY_DOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_LEFT:
|
|
||||||
key = GBA_KEY_LEFT;
|
|
||||||
break;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
key = GBA_KEY_RIGHT;
|
|
||||||
break;
|
|
||||||
case SDLK_F11:
|
case SDLK_F11:
|
||||||
if (event->type == SDL_KEYDOWN && context->debugger) {
|
if (event->type == SDL_KEYDOWN && context->debugger) {
|
||||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
||||||
|
@ -192,17 +174,11 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->type == SDL_KEYDOWN) {
|
|
||||||
context->activeKeys |= 1 << key;
|
|
||||||
} else {
|
|
||||||
context->activeKeys &= ~(1 << key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBASDLHandleJoyButton(struct GBAThread* context, const struct SDL_JoyButtonEvent* event) {
|
static void _GBASDLHandleJoyButton(struct GBAThread* context, const struct SDL_JoyButtonEvent* event) {
|
||||||
enum GBAKey key = 0;
|
enum GBAKey key = 0;
|
||||||
key = GBASDLMapButtonToKey(event->button);
|
key = GBAInputMapKey(&context->inputMap, SDL_BINDING_BUTTON, event->button);
|
||||||
if (key == GBA_KEY_NONE) {
|
if (key == GBA_KEY_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
struct GBASDLEvents {
|
struct GBASDLEvents {
|
||||||
|
struct GBAInputMap* bindings;
|
||||||
SDL_Joystick* joystick;
|
SDL_Joystick* joystick;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
|
|
Loading…
Reference in New Issue