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);
|
||||
|
||||
GBAInputMapDeinit(&threadContext->inputMap);
|
||||
|
||||
if (threadContext->rom) {
|
||||
threadContext->rom->close(threadContext->rom);
|
||||
threadContext->rom = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "common.h"
|
||||
|
||||
#include "gba.h"
|
||||
#include "gba-input.h"
|
||||
|
||||
#include "util/threading.h"
|
||||
#include "platform/commandline.h"
|
||||
|
@ -56,6 +57,7 @@ struct GBAThread {
|
|||
struct VFile* patch;
|
||||
const char* fname;
|
||||
int activeKeys;
|
||||
struct GBAInputMap inputMap;
|
||||
|
||||
// Run-time options
|
||||
int frameskip;
|
||||
|
|
|
@ -57,6 +57,7 @@ enum GBAKey {
|
|||
GBA_KEY_DOWN = 7,
|
||||
GBA_KEY_R = 8,
|
||||
GBA_KEY_L = 9,
|
||||
GBA_KEY_MAX,
|
||||
GBA_KEY_NONE = -1
|
||||
};
|
||||
|
||||
|
|
|
@ -100,6 +100,9 @@ int main(int argc, char** argv) {
|
|||
renderer.audio.samples = context.audioBuffers;
|
||||
GBASDLInitAudio(&renderer.audio);
|
||||
|
||||
renderer.events.bindings = &context.inputMap;
|
||||
GBASDLInitEvents(&renderer.events);
|
||||
|
||||
GBAThreadStart(&context);
|
||||
|
||||
_GBASDLRunloop(&context, &renderer);
|
||||
|
@ -118,7 +121,6 @@ static int _GBASDLInit(struct GLSoftwareRenderer* renderer) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
GBASDLInitEvents(&renderer->events);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#define GUI_MOD KMOD_CTRL
|
||||
#endif
|
||||
|
||||
#define SDL_BINDING_KEY 0x53444C4B
|
||||
#define SDL_BINDING_BUTTON 0x53444C42
|
||||
|
||||
bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
|
||||
return false;
|
||||
|
@ -21,6 +24,24 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
|||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -29,64 +50,25 @@ void GBASDLDeinitEvents(struct GBASDLEvents* context) {
|
|||
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) {
|
||||
context->frameCallback = 0;
|
||||
GBAThreadPauseFromThread(context);
|
||||
}
|
||||
|
||||
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) {
|
||||
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:
|
||||
if (event->type == SDL_KEYDOWN && context->debugger) {
|
||||
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
|
||||
|
@ -192,17 +174,11 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
|||
}
|
||||
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) {
|
||||
enum GBAKey key = 0;
|
||||
key = GBASDLMapButtonToKey(event->button);
|
||||
key = GBAInputMapKey(&context->inputMap, SDL_BINDING_BUTTON, event->button);
|
||||
if (key == GBA_KEY_NONE) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <SDL.h>
|
||||
|
||||
struct GBASDLEvents {
|
||||
struct GBAInputMap* bindings;
|
||||
SDL_Joystick* joystick;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_Window* window;
|
||||
|
|
Loading…
Reference in New Issue