src/gba/gba-input.c (view raw)
1#include "gba-input.h"
2
3#include "util/configuration.h"
4
5#include <inttypes.h>
6
7#define SECTION_NAME_MAX 128
8#define KEY_NAME_MAX 32
9#define KEY_VALUE_MAX 16
10
11struct GBAInputMapImpl {
12 int* map;
13 uint32_t type;
14};
15
16static void _loadKey(struct GBAInputMap* map, uint32_t type, const struct Configuration* config, enum GBAKey key, const char* keyName) {
17 char sectionName[SECTION_NAME_MAX];
18 snprintf(sectionName, SECTION_NAME_MAX, "input.%c%c%c%c", type >> 24, type >> 16, type >> 8, type);
19 sectionName[SECTION_NAME_MAX - 1] = '\0';
20
21 char keyKey[KEY_NAME_MAX];
22 snprintf(keyKey, KEY_NAME_MAX, "key%s", keyName);
23 keyKey[KEY_NAME_MAX - 1] = '\0';
24
25 const char* value = ConfigurationGetValue(config, sectionName, keyKey);
26 if (!value) {
27 return;
28 }
29 char* end;
30 long intValue = strtol(value, &end, 10);
31 if (*end) {
32 return;
33 }
34 GBAInputBindKey(map, type, intValue, key);
35}
36
37static void _saveKey(const struct GBAInputMap* map, uint32_t type, struct Configuration* config, enum GBAKey key, const char* keyName) {
38 char sectionName[SECTION_NAME_MAX];
39 snprintf(sectionName, SECTION_NAME_MAX, "input.%c%c%c%c", type >> 24, type >> 16, type >> 8, type);
40 sectionName[SECTION_NAME_MAX - 1] = '\0';
41
42 char keyKey[KEY_NAME_MAX];
43 snprintf(keyKey, KEY_NAME_MAX, "key%s", keyName);
44 keyKey[KEY_NAME_MAX - 1] = '\0';
45
46 int value = GBAInputQueryBinding(map, type, key);
47 char keyValue[KEY_VALUE_MAX];
48 snprintf(keyValue, KEY_VALUE_MAX, "%" PRIi32, value);
49
50 ConfigurationSetValue(config, sectionName, keyKey, keyValue);
51}
52
53void GBAInputMapInit(struct GBAInputMap* map) {
54 map->maps = 0;
55 map->numMaps = 0;
56}
57
58void GBAInputMapDeinit(struct GBAInputMap* map) {
59 size_t m;
60 for (m = 0; m < map->numMaps; ++m) {
61 free(map->maps[m].map);
62 }
63 free(map->maps);
64 map->maps = 0;
65 map->numMaps = 0;
66}
67
68enum GBAKey GBAInputMapKey(const struct GBAInputMap* map, uint32_t type, int key) {
69 size_t m;
70 const struct GBAInputMapImpl* impl = 0;
71 for (m = 0; m < map->numMaps; ++m) {
72 if (map->maps[m].type == type) {
73 impl = &map->maps[m];
74 break;
75 }
76 }
77 if (!impl || !impl->map) {
78 return GBA_KEY_NONE;
79 }
80
81 for (m = 0; m < GBA_KEY_MAX; ++m) {
82 if (impl->map[m] == key) {
83 return m;
84 }
85 }
86 return GBA_KEY_NONE;
87}
88
89void GBAInputBindKey(struct GBAInputMap* map, uint32_t type, int key, enum GBAKey input) {
90 struct GBAInputMapImpl* impl = 0;
91 if (map->numMaps == 0) {
92 map->maps = malloc(sizeof(*map->maps));
93 map->numMaps = 1;
94 impl = &map->maps[0];
95 impl->type = type;
96 impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
97 } else {
98 size_t m;
99 for (m = 0; m < map->numMaps; ++m) {
100 if (map->maps[m].type == type) {
101 impl = &map->maps[m];
102 break;
103 }
104 }
105 }
106 if (!impl) {
107 size_t m;
108 for (m = 0; m < map->numMaps; ++m) {
109 if (!map->maps[m].type) {
110 impl = &map->maps[m];
111 break;
112 }
113 }
114 if (impl) {
115 impl->type = type;
116 impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
117 } else {
118 map->maps = realloc(map->maps, sizeof(*map->maps) * map->numMaps * 2);
119 for (m = map->numMaps * 2 - 1; m > map->numMaps; --m) {
120 map->maps[m].type = 0;
121 map->maps[m].map = 0;
122 }
123 map->numMaps *= 2;
124 impl = &map->maps[m];
125 impl->type = type;
126 impl->map = calloc(GBA_KEY_MAX, sizeof(enum GBAKey));
127 }
128 }
129 impl->map[input] = key;
130}
131
132int GBAInputQueryBinding(const struct GBAInputMap* map, uint32_t type, enum GBAKey input) {
133 if (input >= GBA_KEY_MAX) {
134 return 0;
135 }
136
137 size_t m;
138 const struct GBAInputMapImpl* impl = 0;
139 for (m = 0; m < map->numMaps; ++m) {
140 if (map->maps[m].type == type) {
141 impl = &map->maps[m];
142 break;
143 }
144 }
145 if (!impl || !impl->map) {
146 return 0;
147 }
148
149 return impl->map[input];
150}
151
152void GBAInputMapLoad(struct GBAInputMap* map, uint32_t type, const struct Configuration* config) {
153 _loadKey(map, type, config, GBA_KEY_A, "A");
154 _loadKey(map, type, config, GBA_KEY_B, "B");
155 _loadKey(map, type, config, GBA_KEY_L, "L");
156 _loadKey(map, type, config, GBA_KEY_R, "R");
157 _loadKey(map, type, config, GBA_KEY_START, "Start");
158 _loadKey(map, type, config, GBA_KEY_SELECT, "Select");
159 _loadKey(map, type, config, GBA_KEY_UP, "Up");
160 _loadKey(map, type, config, GBA_KEY_DOWN, "Down");
161 _loadKey(map, type, config, GBA_KEY_LEFT, "Left");
162 _loadKey(map, type, config, GBA_KEY_RIGHT, "Right");
163}
164
165void GBAInputMapSave(const struct GBAInputMap* map, uint32_t type, struct Configuration* config) {
166 _saveKey(map, type, config, GBA_KEY_A, "A");
167 _saveKey(map, type, config, GBA_KEY_B, "B");
168 _saveKey(map, type, config, GBA_KEY_L, "L");
169 _saveKey(map, type, config, GBA_KEY_R, "R");
170 _saveKey(map, type, config, GBA_KEY_START, "Start");
171 _saveKey(map, type, config, GBA_KEY_SELECT, "Select");
172 _saveKey(map, type, config, GBA_KEY_UP, "Up");
173 _saveKey(map, type, config, GBA_KEY_DOWN, "Down");
174 _saveKey(map, type, config, GBA_KEY_LEFT, "Left");
175 _saveKey(map, type, config, GBA_KEY_RIGHT, "Right");
176}