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