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}