First pass at input mapping

This commit is contained in:
Jeffrey Pfau 2014-07-23 00:06:44 -07:00
parent f55d085162
commit 3051143fa3
8 changed files with 144 additions and 59 deletions

84
src/gba/gba-input.c Normal file
View File

@ -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;
}

17
src/gba/gba-input.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
};

View File

@ -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);

View File

@ -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;
}

View File

@ -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;