all repos — mgba @ d75042ea38fbffafdd53d2827421ab4470b47737

mGBA Game Boy Advance Emulator

src/gba/gba-input.c (view raw)

  1#include "gba-input.h"
  2
  3#include "util/configuration.h"
  4
  5#define SECTION_NAME_MAX 128
  6#define KEY_NAME_MAX 32
  7
  8struct GBAInputMapImpl {
  9	int* map;
 10	uint32_t type;
 11};
 12
 13static void _loadKey(struct GBAInputMap* map, uint32_t type, const struct Configuration* config, enum GBAKey key, const char* keyName) {
 14	char sectionName[SECTION_NAME_MAX];
 15	snprintf(sectionName, SECTION_NAME_MAX, "input.%c%c%c%c", type >> 24, type >> 16, type >> 8, type);
 16	sectionName[SECTION_NAME_MAX - 1] = '\0';
 17
 18	char keyKey[KEY_NAME_MAX];
 19	snprintf(keyKey, KEY_NAME_MAX, "key%s", keyName);
 20
 21	const char* value = ConfigurationGetValue(config, sectionName, keyKey);
 22	if (!value) {
 23		return;
 24	}
 25	char* end;
 26	long intValue = strtol(value, &end, 10);
 27	if (*end) {
 28		return;
 29	}
 30	GBAInputBindKey(map, type, intValue, key);
 31}
 32
 33void GBAInputMapInit(struct GBAInputMap* map) {
 34	map->maps = 0;
 35	map->numMaps = 0;
 36}
 37
 38void GBAInputMapDeinit(struct GBAInputMap* map) {
 39	size_t m;
 40	for (m = 0; m < map->numMaps; ++m) {
 41		free(map->maps[m].map);
 42	}
 43	free(map->maps);
 44	map->maps = 0;
 45	map->numMaps = 0;
 46}
 47
 48enum GBAKey GBAInputMapKey(const struct GBAInputMap* map, uint32_t type, int key) {
 49	size_t m;
 50	const struct GBAInputMapImpl* impl = 0;
 51	for (m = 0; m < map->numMaps; ++m) {
 52		if (map->maps[m].type == type) {
 53			impl = &map->maps[m];
 54			break;
 55		}
 56	}
 57	if (!impl || !impl->map) {
 58		return GBA_KEY_NONE;
 59	}
 60
 61	for (m = 0; m < GBA_KEY_MAX; ++m) {
 62		if (impl->map[m] == key) {
 63			return m;
 64		}
 65	}
 66	return GBA_KEY_NONE;
 67}
 68
 69void GBAInputBindKey(struct GBAInputMap* map, uint32_t type, int key, enum GBAKey input) {
 70	struct GBAInputMapImpl* impl = 0;
 71	if (map->numMaps == 0) {
 72		map->maps = malloc(sizeof(*map->maps));
 73		map->numMaps = 1;
 74		impl = &map->maps[0];
 75		impl->type = type;
 76		impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
 77	} else {
 78		size_t m;
 79		for (m = 0; m < map->numMaps; ++m) {
 80			if (map->maps[m].type == type) {
 81				impl = &map->maps[m];
 82				break;
 83			}
 84		}
 85	}
 86	if (!impl) {
 87		size_t m;
 88		for (m = 0; m < map->numMaps; ++m) {
 89			if (!map->maps[m].type) {
 90				impl = &map->maps[m];
 91				break;
 92			}
 93		}
 94		if (impl) {
 95			impl->type = type;
 96			impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
 97		} else {
 98			map->maps = realloc(map->maps, sizeof(*map->maps) * map->numMaps * 2);
 99			for (m = map->numMaps * 2 - 1; m > map->numMaps; --m) {
100				map->maps[m].type = 0;
101				map->maps[m].map = 0;
102			}
103			map->numMaps *= 2;
104			impl = &map->maps[m];
105			impl->type = type;
106			impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
107		}
108	}
109	impl->map[input] = key;
110}
111
112void GBAInputMapLoad(struct GBAInputMap* map, uint32_t type, const struct Configuration* config) {
113	_loadKey(map, type, config, GBA_KEY_A, "A");
114	_loadKey(map, type, config, GBA_KEY_B, "B");
115	_loadKey(map, type, config, GBA_KEY_L, "L");
116	_loadKey(map, type, config, GBA_KEY_R, "R");
117	_loadKey(map, type, config, GBA_KEY_START, "Start");
118	_loadKey(map, type, config, GBA_KEY_SELECT, "Select");
119	_loadKey(map, type, config, GBA_KEY_UP, "Up");
120	_loadKey(map, type, config, GBA_KEY_DOWN, "Down");
121	_loadKey(map, type, config, GBA_KEY_LEFT, "Left");
122	_loadKey(map, type, config, GBA_KEY_RIGHT, "Right");
123}