mirror of https://github.com/mgba-emu/mgba.git
544 lines
17 KiB
C
544 lines
17 KiB
C
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
#include "input.h"
|
|
|
|
#include "util/configuration.h"
|
|
#include "util/table.h"
|
|
|
|
#include <inttypes.h>
|
|
|
|
#define SECTION_NAME_MAX 128
|
|
#define KEY_NAME_MAX 32
|
|
#define KEY_VALUE_MAX 16
|
|
#define AXIS_INFO_MAX 12
|
|
|
|
struct GBAInputMapImpl {
|
|
int* map;
|
|
uint32_t type;
|
|
|
|
struct Table axes;
|
|
};
|
|
|
|
struct GBAAxisSave {
|
|
struct Configuration* config;
|
|
const char* sectionName;
|
|
};
|
|
|
|
struct GBAAxisEnumerate {
|
|
void (*handler)(int axis, const struct GBAAxis* description, void* user);
|
|
void* user;
|
|
};
|
|
|
|
const char* GBAKeyNames[] = {
|
|
"A",
|
|
"B",
|
|
"Select",
|
|
"Start",
|
|
"Right",
|
|
"Left",
|
|
"Up",
|
|
"Down",
|
|
"R",
|
|
"L"
|
|
};
|
|
|
|
static void _makeSectionName(char* sectionName, size_t len, uint32_t type) {
|
|
snprintf(sectionName, len, "input.%c%c%c%c", type >> 24, type >> 16, type >> 8, type);
|
|
sectionName[len - 1] = '\0';
|
|
}
|
|
|
|
static bool _getIntValue(const struct Configuration* config, const char* section, const char* key, int* value) {
|
|
const char* strValue = ConfigurationGetValue(config, section, key);
|
|
if (!strValue) {
|
|
return false;
|
|
}
|
|
char* end;
|
|
long intValue = strtol(strValue, &end, 10);
|
|
if (*end) {
|
|
return false;
|
|
}
|
|
*value = intValue;
|
|
return true;
|
|
}
|
|
|
|
static struct GBAInputMapImpl* _lookupMap(struct GBAInputMap* map, uint32_t type) {
|
|
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;
|
|
}
|
|
}
|
|
return impl;
|
|
}
|
|
|
|
static const struct GBAInputMapImpl* _lookupMapConst(const struct GBAInputMap* map, uint32_t type) {
|
|
size_t m;
|
|
const struct GBAInputMapImpl* impl = 0;
|
|
for (m = 0; m < map->numMaps; ++m) {
|
|
if (map->maps[m].type == type) {
|
|
impl = &map->maps[m];
|
|
break;
|
|
}
|
|
}
|
|
return impl;
|
|
}
|
|
|
|
static struct GBAInputMapImpl* _guaranteeMap(struct GBAInputMap* map, uint32_t type) {
|
|
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(int));
|
|
TableInit(&impl->axes, 2, free);
|
|
} else {
|
|
impl = _lookupMap(map, type);
|
|
}
|
|
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(int));
|
|
} 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;
|
|
}
|
|
map->numMaps *= 2;
|
|
impl = &map->maps[m];
|
|
impl->type = type;
|
|
impl->map = calloc(GBA_KEY_MAX, sizeof(int));
|
|
}
|
|
TableInit(&impl->axes, 2, free);
|
|
}
|
|
return impl;
|
|
}
|
|
|
|
static void _loadKey(struct GBAInputMap* map, uint32_t type, const char* sectionName, const struct Configuration* config, enum GBAKey key, const char* keyName) {
|
|
char keyKey[KEY_NAME_MAX];
|
|
snprintf(keyKey, KEY_NAME_MAX, "key%s", keyName);
|
|
keyKey[KEY_NAME_MAX - 1] = '\0';
|
|
|
|
int value;
|
|
if (!_getIntValue(config, sectionName, keyKey, &value)) {
|
|
return;
|
|
}
|
|
GBAInputBindKey(map, type, value, key);
|
|
}
|
|
|
|
static void _loadAxis(struct GBAInputMap* map, uint32_t type, const char* sectionName, const struct Configuration* config, enum GBAKey direction, const char* axisName) {
|
|
char axisKey[KEY_NAME_MAX];
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sValue", axisName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
int value;
|
|
if (!_getIntValue(config, sectionName, axisKey, &value)) {
|
|
return;
|
|
}
|
|
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sAxis", axisName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
int axis;
|
|
const char* strValue = ConfigurationGetValue(config, sectionName, axisKey);
|
|
if (!strValue || !strValue[0]) {
|
|
return;
|
|
}
|
|
char* end;
|
|
axis = strtoul(&strValue[1], &end, 10);
|
|
if (*end) {
|
|
return;
|
|
}
|
|
|
|
const struct GBAAxis* description = GBAInputQueryAxis(map, type, axis);
|
|
struct GBAAxis realDescription = { GBA_KEY_NONE, GBA_KEY_NONE, 0, 0 };
|
|
if (description) {
|
|
realDescription = *description;
|
|
}
|
|
if (strValue[0] == '+') {
|
|
realDescription.deadHigh = value;
|
|
realDescription.highDirection = direction;
|
|
} else if (strValue[0] == '-') {
|
|
realDescription.deadLow = value;
|
|
realDescription.lowDirection = direction;
|
|
}
|
|
GBAInputBindAxis(map, type, axis, &realDescription);
|
|
}
|
|
|
|
static void _saveKey(const struct GBAInputMap* map, uint32_t type, const char* sectionName, struct Configuration* config, enum GBAKey key, const char* keyName) {
|
|
char keyKey[KEY_NAME_MAX];
|
|
snprintf(keyKey, KEY_NAME_MAX, "key%s", keyName);
|
|
keyKey[KEY_NAME_MAX - 1] = '\0';
|
|
|
|
int value = GBAInputQueryBinding(map, type, key);
|
|
char keyValue[KEY_VALUE_MAX];
|
|
snprintf(keyValue, KEY_VALUE_MAX, "%" PRIi32, value);
|
|
|
|
ConfigurationSetValue(config, sectionName, keyKey, keyValue);
|
|
}
|
|
|
|
static void _clearAxis(const char* sectionName, struct Configuration* config, const char* axisName) {
|
|
char axisKey[KEY_NAME_MAX];
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sValue", axisName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
ConfigurationClearValue(config, sectionName, axisKey);
|
|
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sAxis", axisName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
ConfigurationClearValue(config, sectionName, axisKey);
|
|
}
|
|
|
|
static void _saveAxis(uint32_t axis, void* dp, void* up) {
|
|
struct GBAAxisSave* user = up;
|
|
const struct GBAAxis* description = dp;
|
|
|
|
const char* sectionName = user->sectionName;
|
|
|
|
if (description->lowDirection != GBA_KEY_NONE) {
|
|
const char* keyName = GBAKeyNames[description->lowDirection];
|
|
|
|
char axisKey[KEY_NAME_MAX];
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sValue", keyName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
ConfigurationSetIntValue(user->config, sectionName, axisKey, description->deadLow);
|
|
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sAxis", keyName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
|
|
char axisInfo[AXIS_INFO_MAX];
|
|
snprintf(axisInfo, AXIS_INFO_MAX, "-%u", axis);
|
|
axisInfo[AXIS_INFO_MAX - 1] = '\0';
|
|
ConfigurationSetValue(user->config, sectionName, axisKey, axisInfo);
|
|
}
|
|
if (description->highDirection != GBA_KEY_NONE) {
|
|
const char* keyName = GBAKeyNames[description->highDirection];
|
|
|
|
char axisKey[KEY_NAME_MAX];
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sValue", keyName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
ConfigurationSetIntValue(user->config, sectionName, axisKey, description->deadHigh);
|
|
|
|
snprintf(axisKey, KEY_NAME_MAX, "axis%sAxis", keyName);
|
|
axisKey[KEY_NAME_MAX - 1] = '\0';
|
|
|
|
char axisInfo[AXIS_INFO_MAX];
|
|
snprintf(axisInfo, AXIS_INFO_MAX, "+%u", axis);
|
|
axisInfo[AXIS_INFO_MAX - 1] = '\0';
|
|
ConfigurationSetValue(user->config, sectionName, axisKey, axisInfo);
|
|
}
|
|
}
|
|
|
|
void _enumerateAxis(uint32_t axis, void* dp, void* ep) {
|
|
struct GBAAxisEnumerate* enumUser = ep;
|
|
const struct GBAAxis* description = dp;
|
|
enumUser->handler(axis, description, enumUser->user);
|
|
}
|
|
|
|
void _unbindAxis(uint32_t axis, void* dp, void* user) {
|
|
UNUSED(axis);
|
|
enum GBAKey* key = user;
|
|
struct GBAAxis* description = dp;
|
|
if (description->highDirection == *key) {
|
|
description->highDirection = GBA_KEY_NONE;
|
|
}
|
|
if (description->lowDirection == *key) {
|
|
description->lowDirection = GBA_KEY_NONE;
|
|
}
|
|
}
|
|
|
|
static bool _loadAll(struct GBAInputMap* map, uint32_t type, const char* sectionName, const struct Configuration* config) {
|
|
if (!ConfigurationHasSection(config, sectionName)) {
|
|
return false;
|
|
}
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_A, "A");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_B, "B");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_L, "L");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_R, "R");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_START, "Start");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_SELECT, "Select");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_UP, "Up");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_DOWN, "Down");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_LEFT, "Left");
|
|
_loadKey(map, type, sectionName, config, GBA_KEY_RIGHT, "Right");
|
|
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_A, "A");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_B, "B");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_L, "L");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_R, "R");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_START, "Start");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_SELECT, "Select");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_UP, "Up");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_DOWN, "Down");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_LEFT, "Left");
|
|
_loadAxis(map, type, sectionName, config, GBA_KEY_RIGHT, "Right");
|
|
return true;
|
|
}
|
|
|
|
static void _saveAll(const struct GBAInputMap* map, uint32_t type, const char* sectionName, struct Configuration* config) {
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_A, "A");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_B, "B");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_L, "L");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_R, "R");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_START, "Start");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_SELECT, "Select");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_UP, "Up");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_DOWN, "Down");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_LEFT, "Left");
|
|
_saveKey(map, type, sectionName, config, GBA_KEY_RIGHT, "Right");
|
|
|
|
_clearAxis(sectionName, config, "A");
|
|
_clearAxis(sectionName, config, "B");
|
|
_clearAxis(sectionName, config, "L");
|
|
_clearAxis(sectionName, config, "R");
|
|
_clearAxis(sectionName, config, "Start");
|
|
_clearAxis(sectionName, config, "Select");
|
|
_clearAxis(sectionName, config, "Up");
|
|
_clearAxis(sectionName, config, "Down");
|
|
_clearAxis(sectionName, config, "Left");
|
|
_clearAxis(sectionName, config, "Right");
|
|
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl) {
|
|
return;
|
|
}
|
|
struct GBAAxisSave save = {
|
|
config,
|
|
sectionName
|
|
};
|
|
TableEnumerate(&impl->axes, _saveAxis, &save);
|
|
}
|
|
|
|
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) {
|
|
if (map->maps[m].type) {
|
|
free(map->maps[m].map);
|
|
TableDeinit(&map->maps[m].axes);
|
|
}
|
|
}
|
|
free(map->maps);
|
|
map->maps = 0;
|
|
map->numMaps = 0;
|
|
}
|
|
|
|
enum GBAKey GBAInputMapKey(const struct GBAInputMap* map, uint32_t type, int key) {
|
|
size_t m;
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
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;
|
|
}
|
|
|
|
int GBAInputMapKeyBits(const struct GBAInputMap* map, uint32_t type, uint32_t bits, unsigned offset) {
|
|
int keys = 0;
|
|
for (; bits; bits >>= 1, ++offset) {
|
|
if (bits & 1) {
|
|
enum GBAKey key = GBAInputMapKey(map, type, offset);
|
|
if (key == GBA_KEY_NONE) {
|
|
continue;
|
|
}
|
|
keys |= 1 << key;
|
|
}
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
void GBAInputBindKey(struct GBAInputMap* map, uint32_t type, int key, enum GBAKey input) {
|
|
struct GBAInputMapImpl* impl = _guaranteeMap(map, type);
|
|
GBAInputUnbindKey(map, type, input);
|
|
impl->map[input] = key;
|
|
}
|
|
|
|
void GBAInputUnbindKey(struct GBAInputMap* map, uint32_t type, enum GBAKey input) {
|
|
struct GBAInputMapImpl* impl = _lookupMap(map, type);
|
|
if (input < 0 || input >= GBA_KEY_MAX) {
|
|
return;
|
|
}
|
|
if (impl) {
|
|
impl->map[input] = GBA_NO_MAPPING;
|
|
}
|
|
}
|
|
|
|
int GBAInputQueryBinding(const struct GBAInputMap* map, uint32_t type, enum GBAKey input) {
|
|
if (input >= GBA_KEY_MAX) {
|
|
return 0;
|
|
}
|
|
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl || !impl->map) {
|
|
return 0;
|
|
}
|
|
|
|
return impl->map[input];
|
|
}
|
|
|
|
enum GBAKey GBAInputMapAxis(const struct GBAInputMap* map, uint32_t type, int axis, int value) {
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl) {
|
|
return GBA_KEY_NONE;
|
|
}
|
|
struct GBAAxis* description = TableLookup(&impl->axes, axis);
|
|
if (!description) {
|
|
return GBA_KEY_NONE;
|
|
}
|
|
int state = 0;
|
|
if (value < description->deadLow) {
|
|
state = -1;
|
|
} else if (value > description->deadHigh) {
|
|
state = 1;
|
|
}
|
|
if (state > 0) {
|
|
return description->highDirection;
|
|
}
|
|
if (state < 0) {
|
|
return description->lowDirection;
|
|
}
|
|
return GBA_KEY_NONE;
|
|
}
|
|
|
|
int GBAInputClearAxis(const struct GBAInputMap* map, uint32_t type, int axis, int keys) {
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl) {
|
|
return keys;
|
|
}
|
|
struct GBAAxis* description = TableLookup(&impl->axes, axis);
|
|
if (!description) {
|
|
return keys;
|
|
}
|
|
return keys &= ~((1 << description->highDirection) | (1 << description->lowDirection));
|
|
}
|
|
|
|
void GBAInputBindAxis(struct GBAInputMap* map, uint32_t type, int axis, const struct GBAAxis* description) {
|
|
struct GBAInputMapImpl* impl = _guaranteeMap(map, type);
|
|
struct GBAAxis d2 = *description;
|
|
TableEnumerate(&impl->axes, _unbindAxis, &d2.highDirection);
|
|
TableEnumerate(&impl->axes, _unbindAxis, &d2.lowDirection);
|
|
struct GBAAxis* dup = malloc(sizeof(struct GBAAxis));
|
|
*dup = *description;
|
|
TableInsert(&impl->axes, axis, dup);
|
|
}
|
|
|
|
void GBAInputUnbindAxis(struct GBAInputMap* map, uint32_t type, int axis) {
|
|
struct GBAInputMapImpl* impl = _lookupMap(map, type);
|
|
if (impl) {
|
|
TableRemove(&impl->axes, axis);
|
|
}
|
|
}
|
|
|
|
void GBAInputUnbindAllAxes(struct GBAInputMap* map, uint32_t type) {
|
|
struct GBAInputMapImpl* impl = _lookupMap(map, type);
|
|
if (impl) {
|
|
TableClear(&impl->axes);
|
|
}
|
|
}
|
|
|
|
const struct GBAAxis* GBAInputQueryAxis(const struct GBAInputMap* map, uint32_t type, int axis) {
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl) {
|
|
return 0;
|
|
}
|
|
return TableLookup(&impl->axes, axis);
|
|
}
|
|
|
|
void GBAInputEnumerateAxes(const struct GBAInputMap* map, uint32_t type, void (handler(int axis, const struct GBAAxis* description, void* user)), void* user) {
|
|
const struct GBAInputMapImpl* impl = _lookupMapConst(map, type);
|
|
if (!impl) {
|
|
return;
|
|
}
|
|
struct GBAAxisEnumerate enumUser = {
|
|
handler,
|
|
user
|
|
};
|
|
TableEnumerate(&impl->axes, _enumerateAxis, &enumUser);
|
|
}
|
|
|
|
void GBAInputMapLoad(struct GBAInputMap* map, uint32_t type, const struct Configuration* config) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
_loadAll(map, type, sectionName, config);
|
|
}
|
|
|
|
void GBAInputMapSave(const struct GBAInputMap* map, uint32_t type, struct Configuration* config) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
_saveAll(map, type, sectionName, config);
|
|
}
|
|
|
|
bool GBAInputProfileLoad(struct GBAInputMap* map, uint32_t type, const struct Configuration* config, const char* profile) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
|
|
sectionName[SECTION_NAME_MAX - 1] = '\0';
|
|
return _loadAll(map, type, sectionName, config);
|
|
}
|
|
|
|
void GBAInputProfileSave(const struct GBAInputMap* map, uint32_t type, struct Configuration* config, const char* profile) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
|
|
sectionName[SECTION_NAME_MAX - 1] = '\0';
|
|
_saveAll(map, type, sectionName, config);
|
|
}
|
|
|
|
const char* GBAInputGetPreferredDevice(const struct Configuration* config, uint32_t type, int playerId) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
|
|
char deviceId[KEY_NAME_MAX];
|
|
snprintf(deviceId, sizeof(deviceId), "device%i", playerId);
|
|
return ConfigurationGetValue(config, sectionName, deviceId);
|
|
}
|
|
|
|
void GBAInputSetPreferredDevice(struct Configuration* config, uint32_t type, int playerId, const char* deviceName) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
|
|
char deviceId[KEY_NAME_MAX];
|
|
snprintf(deviceId, sizeof(deviceId), "device%i", playerId);
|
|
return ConfigurationSetValue(config, sectionName, deviceId, deviceName);
|
|
}
|
|
|
|
const char* GBAInputGetCustomValue(const struct Configuration* config, uint32_t type, const char* key, const char* profile) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
if (profile) {
|
|
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
|
|
const char* value = ConfigurationGetValue(config, sectionName, key);
|
|
if (value) {
|
|
return value;
|
|
}
|
|
}
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
return ConfigurationGetValue(config, sectionName, key);
|
|
}
|
|
|
|
void GBAInputSetCustomValue(struct Configuration* config, uint32_t type, const char* key, const char* value, const char* profile) {
|
|
char sectionName[SECTION_NAME_MAX];
|
|
if (profile) {
|
|
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
|
|
ConfigurationSetValue(config, sectionName, key, value);
|
|
}
|
|
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
|
|
ConfigurationSetValue(config, sectionName, key, value);
|
|
}
|