mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 12:32:52 +00:00
fix new rumble types ; increase max displayed cheats to 6000
This commit is contained in:
parent
b6aec689fe
commit
f53e1ca4b1
@ -66,7 +66,7 @@ struct config_include_list
|
||||
};
|
||||
|
||||
static config_file_t *config_file_new_internal(
|
||||
const char *path, unsigned depth);
|
||||
const char *path, unsigned depth, config_file_cb_t *cb);
|
||||
|
||||
static int config_sort_compare_func(struct config_entry_list *a,
|
||||
struct config_entry_list *b)
|
||||
@ -267,7 +267,7 @@ static void add_child_list(config_file_t *parent, config_file_t *child)
|
||||
parent->tail = NULL;
|
||||
}
|
||||
|
||||
static void add_sub_conf(config_file_t *conf, char *path)
|
||||
static void add_sub_conf(config_file_t *conf, char *path, config_file_cb_t *cb)
|
||||
{
|
||||
char real_path[PATH_MAX_LENGTH];
|
||||
config_file_t *sub_conf = NULL;
|
||||
@ -314,7 +314,7 @@ static void add_sub_conf(config_file_t *conf, char *path)
|
||||
#endif
|
||||
|
||||
sub_conf = (config_file_t*)
|
||||
config_file_new_internal(real_path, conf->include_depth + 1);
|
||||
config_file_new_internal(real_path, conf->include_depth + 1, cb);
|
||||
if (!sub_conf)
|
||||
return;
|
||||
|
||||
@ -324,7 +324,7 @@ static void add_sub_conf(config_file_t *conf, char *path)
|
||||
}
|
||||
|
||||
static bool parse_line(config_file_t *conf,
|
||||
struct config_entry_list *list, char *line)
|
||||
struct config_entry_list *list, char *line, config_file_cb_t *cb)
|
||||
{
|
||||
char *comment = NULL;
|
||||
char *key_tmp = NULL;
|
||||
@ -351,7 +351,7 @@ static bool parse_line(config_file_t *conf,
|
||||
if (conf->include_depth >= MAX_INCLUDE_DEPTH)
|
||||
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
|
||||
else
|
||||
add_sub_conf(conf, path);
|
||||
add_sub_conf(conf, path, cb);
|
||||
free(path);
|
||||
}
|
||||
goto error;
|
||||
@ -396,18 +396,19 @@ error:
|
||||
}
|
||||
|
||||
static config_file_t *config_file_new_internal(
|
||||
const char *path, unsigned depth)
|
||||
const char *path, unsigned depth, config_file_cb_t *cb)
|
||||
{
|
||||
RFILE *file = NULL;
|
||||
struct config_file *conf = (struct config_file*)malloc(sizeof(*conf));
|
||||
if (!conf)
|
||||
return NULL;
|
||||
|
||||
conf->path = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->includes = NULL;
|
||||
conf->include_depth = 0;
|
||||
conf->path = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->includes = NULL;
|
||||
conf->include_depth = 0;
|
||||
conf->guaranteed_no_duplicates = false ;
|
||||
|
||||
if (!path || !*path)
|
||||
return conf;
|
||||
@ -455,7 +456,7 @@ static config_file_t *config_file_new_internal(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*line && parse_line(conf, list, line))
|
||||
if (*line && parse_line(conf, list, line, cb))
|
||||
{
|
||||
if (conf->entries)
|
||||
conf->tail->next = list;
|
||||
@ -463,6 +464,9 @@ static config_file_t *config_file_new_internal(
|
||||
conf->entries = list;
|
||||
|
||||
conf->tail = list;
|
||||
|
||||
if (cb != NULL && list->key != NULL && list->value != NULL)
|
||||
cb->config_file_new_entry_cb(list->key, list->value) ;
|
||||
}
|
||||
|
||||
free(line);
|
||||
@ -551,11 +555,12 @@ config_file_t *config_file_new_from_string(const char *from_string)
|
||||
if (!from_string)
|
||||
return conf;
|
||||
|
||||
conf->path = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->includes = NULL;
|
||||
conf->include_depth = 0;
|
||||
conf->path = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->includes = NULL;
|
||||
conf->include_depth = 0;
|
||||
conf->guaranteed_no_duplicates = false ;
|
||||
|
||||
lines = string_split(from_string, "\n");
|
||||
if (!lines)
|
||||
@ -580,7 +585,7 @@ config_file_t *config_file_new_from_string(const char *from_string)
|
||||
|
||||
if (line && conf)
|
||||
{
|
||||
if (*line && parse_line(conf, list, line))
|
||||
if (*line && parse_line(conf, list, line, NULL))
|
||||
{
|
||||
if (conf->entries)
|
||||
conf->tail->next = list;
|
||||
@ -600,9 +605,13 @@ config_file_t *config_file_new_from_string(const char *from_string)
|
||||
return conf;
|
||||
}
|
||||
|
||||
config_file_t *config_file_new_with_callback(const char *path, config_file_cb_t *cb)
|
||||
{
|
||||
return config_file_new_internal(path, 0, cb);
|
||||
}
|
||||
config_file_t *config_file_new(const char *path)
|
||||
{
|
||||
return config_file_new_internal(path, 0);
|
||||
return config_file_new_internal(path, 0, NULL);
|
||||
}
|
||||
|
||||
static struct config_entry_list *config_get_entry(const config_file_t *conf,
|
||||
@ -834,7 +843,7 @@ bool config_get_bool(config_file_t *conf, const char *key, bool *in)
|
||||
void config_set_string(config_file_t *conf, const char *key, const char *val)
|
||||
{
|
||||
struct config_entry_list *last = conf->entries;
|
||||
struct config_entry_list *entry = config_get_entry(conf, key, &last);
|
||||
struct config_entry_list *entry = conf->guaranteed_no_duplicates?NULL:config_get_entry(conf, key, &last);
|
||||
|
||||
if (entry && !entry->readonly)
|
||||
{
|
||||
|
@ -58,6 +58,7 @@ struct config_file
|
||||
struct config_entry_list *entries;
|
||||
struct config_entry_list *tail;
|
||||
unsigned include_depth;
|
||||
bool guaranteed_no_duplicates;
|
||||
|
||||
struct config_include_list *includes;
|
||||
};
|
||||
@ -65,6 +66,13 @@ struct config_file
|
||||
|
||||
typedef struct config_file config_file_t;
|
||||
|
||||
struct config_file_cb
|
||||
{
|
||||
void (*config_file_new_entry_cb)(char*, char*);
|
||||
};
|
||||
|
||||
typedef struct config_file_cb config_file_cb_t ;
|
||||
|
||||
/* Config file format
|
||||
* - # are treated as comments. Rest of the line is ignored.
|
||||
* - Format is: key = value. There can be as many spaces as you like in-between.
|
||||
@ -79,6 +87,11 @@ typedef struct config_file config_file_t;
|
||||
* NULL path will create an empty config file. */
|
||||
config_file_t *config_file_new(const char *path);
|
||||
|
||||
/* Loads a config file. Returns NULL if file doesn't exist.
|
||||
* NULL path will create an empty config file.
|
||||
* Includes cb callbacks to run custom code during config file processing.*/
|
||||
config_file_t *config_file_new_with_callback(const char *path, config_file_cb_t *cb);
|
||||
|
||||
/* Load a config file from a string. */
|
||||
config_file_t *config_file_new_from_string(const char *from_string);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <file/config_file.h>
|
||||
#include <file/file_path.h>
|
||||
@ -171,6 +172,8 @@ bool cheat_manager_save(const char *path, const char *cheat_database, bool overw
|
||||
if (!conf)
|
||||
return false;
|
||||
|
||||
conf->guaranteed_no_duplicates = true ;
|
||||
|
||||
config_set_int(conf, "cheats", cheat_manager_state.size);
|
||||
|
||||
for (i = 0; i < cheat_manager_state.size; i++)
|
||||
@ -303,39 +306,118 @@ static void cheat_manager_new(unsigned size)
|
||||
return ;
|
||||
}
|
||||
|
||||
void cheat_manager_load_cb_first_pass(char *key, char *value)
|
||||
{
|
||||
errno = 0 ;
|
||||
|
||||
if (string_is_equal(key, "cheats"))
|
||||
{
|
||||
cheat_manager_state.loading_cheat_size = (unsigned)strtoul(value, NULL, 0);
|
||||
|
||||
if (errno != 0)
|
||||
cheat_manager_state.loading_cheat_size = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
void cheat_manager_load_cb_second_pass(char *key, char *value)
|
||||
{
|
||||
char cheat_num_str[20] ;
|
||||
unsigned cheat_num ;
|
||||
unsigned cheat_idx ;
|
||||
int idx = 0 ;
|
||||
int key_length ;
|
||||
errno = 0 ;
|
||||
|
||||
if (strncmp(key, "cheat", 5) != 0)
|
||||
return ;
|
||||
|
||||
idx = 5 ;
|
||||
key_length = strlen(key) ;
|
||||
|
||||
while (idx < key_length && key[idx] >= '0' && key[idx] <= '9' && idx < 24)
|
||||
{
|
||||
cheat_num_str[idx-5] = key[idx] ;
|
||||
idx++ ;
|
||||
}
|
||||
|
||||
cheat_num_str[idx-5] = '\0' ;
|
||||
|
||||
cheat_num = (unsigned)strtoul(cheat_num_str, NULL, 0); ;
|
||||
|
||||
if (cheat_num+cheat_manager_state.loading_cheat_offset >= cheat_manager_state.size)
|
||||
return ;
|
||||
|
||||
key = key+idx+1 ;
|
||||
|
||||
cheat_idx = cheat_num+cheat_manager_state.loading_cheat_offset ;
|
||||
|
||||
if (string_is_equal(key, "address"))
|
||||
cheat_manager_state.cheats[cheat_idx].address = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "address_bit_position"))
|
||||
cheat_manager_state.cheats[cheat_idx].address_mask = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "big_endian"))
|
||||
cheat_manager_state.cheats[cheat_idx].big_endian = (string_is_equal(value,"true") || string_is_equal(value,"1"));
|
||||
else if (string_is_equal(key, "cheat_type"))
|
||||
cheat_manager_state.cheats[cheat_idx].cheat_type = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "code"))
|
||||
cheat_manager_state.cheats[cheat_idx].code = strdup(value) ;
|
||||
else if (string_is_equal(key, "desc"))
|
||||
cheat_manager_state.cheats[cheat_idx].desc = strdup(value) ;
|
||||
else if (string_is_equal(key, "enable"))
|
||||
cheat_manager_state.cheats[cheat_idx].state = (string_is_equal(value,"true") || string_is_equal(value,"1"));
|
||||
else if (string_is_equal(key, "handler"))
|
||||
cheat_manager_state.cheats[cheat_idx].handler = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "memory_search_size"))
|
||||
cheat_manager_state.cheats[cheat_idx].memory_search_size = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "repeat_add_to_address"))
|
||||
cheat_manager_state.cheats[cheat_idx].repeat_add_to_address = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "repeat_add_to_value"))
|
||||
cheat_manager_state.cheats[cheat_idx].repeat_add_to_value = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "repeat_count"))
|
||||
cheat_manager_state.cheats[cheat_idx].repeat_count = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_port"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_port = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_primary_duration"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_primary_duration = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_primary_strength"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_primary_strength = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_secondary_duration"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_secondary_duration = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_secondary_strength"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_secondary_strength = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_type"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_type = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "rumble_value"))
|
||||
cheat_manager_state.cheats[cheat_idx].rumble_value = (unsigned)strtoul(value, NULL, 0);
|
||||
else if (string_is_equal(key, "value"))
|
||||
cheat_manager_state.cheats[cheat_idx].value = (unsigned)strtoul(value, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
bool cheat_manager_load(const char *path, bool append)
|
||||
{
|
||||
unsigned cheats = 0, i;
|
||||
config_file_t *conf = config_file_new(path);
|
||||
config_file_cb_t cb ;
|
||||
cb.config_file_new_entry_cb = cheat_manager_load_cb_first_pass ;
|
||||
config_file_t *conf = NULL ;
|
||||
unsigned orig_size ;
|
||||
unsigned int* data_ptrs[16] = { NULL};
|
||||
char* keys[16] = {
|
||||
"cheat%u_handler",
|
||||
"cheat%u_memory_search_size",
|
||||
"cheat%u_cheat_type",
|
||||
"cheat%u_value",
|
||||
"cheat%u_address",
|
||||
"cheat%u_address_bit_position",
|
||||
"cheat%u_rumble_type",
|
||||
"cheat%u_rumble_value",
|
||||
"cheat%u_rumble_port",
|
||||
"cheat%u_rumble_primary_strength",
|
||||
"cheat%u_rumble_primary_duration",
|
||||
"cheat%u_rumble_secondary_strength",
|
||||
"cheat%u_rumble_secondary_duration",
|
||||
"cheat%u_repeat_count",
|
||||
"cheat%u_repeat_add_to_value",
|
||||
"cheat%u_repeat_add_to_address",
|
||||
};
|
||||
|
||||
cheat_manager_state.loading_cheat_size = 0 ;
|
||||
|
||||
conf = config_file_new_with_callback(path, &cb);
|
||||
|
||||
if (!conf)
|
||||
return false;
|
||||
|
||||
config_get_uint(conf, "cheats", &cheats);
|
||||
cheats = cheat_manager_state.loading_cheat_size ;
|
||||
|
||||
if (cheats == 0)
|
||||
goto error;
|
||||
|
||||
config_file_free(conf) ;
|
||||
conf = NULL ;
|
||||
|
||||
|
||||
cheat_manager_alloc_if_empty() ;
|
||||
|
||||
if ( append )
|
||||
@ -359,75 +441,25 @@ bool cheat_manager_load(const char *path, bool append)
|
||||
cheat_manager_new(cheats);
|
||||
}
|
||||
|
||||
|
||||
for (i = orig_size; i < cheats; i++)
|
||||
{
|
||||
unsigned j;
|
||||
char desc_key[256];
|
||||
char code_key[256];
|
||||
char enable_key[256];
|
||||
char endian_key[256];
|
||||
char *tmp = NULL;
|
||||
bool tmp_bool = false;
|
||||
|
||||
data_ptrs[0] = &cheat_manager_state.cheats[i].handler;
|
||||
data_ptrs[1] = &cheat_manager_state.cheats[i].memory_search_size;
|
||||
data_ptrs[2] = &cheat_manager_state.cheats[i].cheat_type;
|
||||
data_ptrs[3] = &cheat_manager_state.cheats[i].value;
|
||||
data_ptrs[4] = &cheat_manager_state.cheats[i].address;
|
||||
data_ptrs[5] = &cheat_manager_state.cheats[i].address_mask;
|
||||
data_ptrs[6] = &cheat_manager_state.cheats[i].rumble_type;
|
||||
data_ptrs[7] = &cheat_manager_state.cheats[i].rumble_value;
|
||||
data_ptrs[8] = &cheat_manager_state.cheats[i].rumble_port;
|
||||
data_ptrs[9] = &cheat_manager_state.cheats[i].rumble_primary_strength;
|
||||
data_ptrs[10] = &cheat_manager_state.cheats[i].rumble_primary_duration;
|
||||
data_ptrs[11] = &cheat_manager_state.cheats[i].rumble_secondary_strength;
|
||||
data_ptrs[12] = &cheat_manager_state.cheats[i].rumble_secondary_duration;
|
||||
data_ptrs[13] = &cheat_manager_state.cheats[i].repeat_count;
|
||||
data_ptrs[14] = &cheat_manager_state.cheats[i].repeat_add_to_value;
|
||||
data_ptrs[15] = &cheat_manager_state.cheats[i].repeat_add_to_address;
|
||||
|
||||
endian_key[0] = desc_key[0] = code_key[0] = enable_key[0] = '\0';
|
||||
|
||||
snprintf(desc_key, sizeof(desc_key), "cheat%u_desc", i-orig_size);
|
||||
snprintf(code_key, sizeof(code_key), "cheat%u_code", i-orig_size);
|
||||
snprintf(enable_key, sizeof(enable_key), "cheat%u_enable", i-orig_size);
|
||||
snprintf(endian_key, sizeof(endian_key), "cheat%u_endian", i-orig_size);
|
||||
|
||||
cheat_manager_state.cheats[i].idx = i ;
|
||||
|
||||
cheat_manager_state.cheats[i].desc = NULL ;
|
||||
cheat_manager_state.cheats[i].code = NULL ;
|
||||
cheat_manager_state.cheats[i].state = false ;
|
||||
cheat_manager_state.cheats[i].big_endian = false ;
|
||||
|
||||
if (config_get_string(conf, desc_key, &tmp) && !string_is_empty(tmp))
|
||||
cheat_manager_state.cheats[i].desc = strdup(tmp) ;
|
||||
|
||||
if (config_get_string(conf, code_key, &tmp) && !string_is_empty(tmp))
|
||||
cheat_manager_state.cheats[i].code = strdup(tmp) ;
|
||||
|
||||
if (config_get_bool(conf, enable_key, &tmp_bool))
|
||||
cheat_manager_state.cheats[i].state = tmp_bool;
|
||||
|
||||
if (config_get_bool(conf, endian_key, &tmp_bool))
|
||||
cheat_manager_state.cheats[i].big_endian = tmp_bool;
|
||||
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
cheat_manager_state.cheats[i].cheat_type = CHEAT_TYPE_SET_TO_VALUE ;
|
||||
cheat_manager_state.cheats[i].memory_search_size = 3;
|
||||
for (j = 0 ; j < 16 ; j++ )
|
||||
{
|
||||
char key[50] ;
|
||||
unsigned val = 0;
|
||||
snprintf(key, sizeof(key), keys[j], i-orig_size);
|
||||
|
||||
if ( config_get_uint(conf, key, &val))
|
||||
*(data_ptrs[j]) = val ;
|
||||
}
|
||||
}
|
||||
|
||||
cheat_manager_state.loading_cheat_offset = orig_size ;
|
||||
cb.config_file_new_entry_cb = cheat_manager_load_cb_second_pass ;
|
||||
conf = config_file_new_with_callback(path, &cb);
|
||||
|
||||
if (!conf)
|
||||
return false;
|
||||
|
||||
config_file_free(conf);
|
||||
|
||||
return true;
|
||||
|
@ -77,7 +77,8 @@ enum cheat_rumble_type
|
||||
RUMBLE_TYPE_LT_VALUE,
|
||||
RUMBLE_TYPE_GT_VALUE,
|
||||
RUMBLE_TYPE_INCREASE_BY_VALUE,
|
||||
RUMBLE_TYPE_DECREASE_BY_VALUE
|
||||
RUMBLE_TYPE_DECREASE_BY_VALUE,
|
||||
RUMBLE_TYPE_END_LIST
|
||||
};
|
||||
|
||||
/* Some codes are ridiculously large - over 10000 bytes */
|
||||
@ -178,6 +179,8 @@ struct cheat_manager
|
||||
unsigned browse_address;
|
||||
char working_desc[CHEAT_DESC_SCRATCH_SIZE] ;
|
||||
char working_code[CHEAT_CODE_SCRATCH_SIZE] ;
|
||||
unsigned int loading_cheat_size;
|
||||
unsigned int loading_cheat_offset;
|
||||
};
|
||||
|
||||
typedef struct cheat_manager cheat_manager_t;
|
||||
|
@ -45,7 +45,7 @@ RETRO_BEGIN_DECLS
|
||||
#endif
|
||||
|
||||
#ifndef MAX_CHEAT_COUNTERS
|
||||
#define MAX_CHEAT_COUNTERS 100
|
||||
#define MAX_CHEAT_COUNTERS 6000
|
||||
#endif
|
||||
|
||||
#define MENU_SETTINGS_CORE_INFO_NONE 0xffff
|
||||
|
@ -4670,7 +4670,7 @@ static bool setting_append_list(
|
||||
config_uint_cbs(cheat_manager_state.working_cheat.rumble_type, CHEAT_RUMBLE_TYPE,
|
||||
setting_uint_action_left_default,setting_uint_action_right_default,
|
||||
MENU_ENUM_LABEL_RUMBLE_TYPE_DISABLED,&setting_get_string_representation_uint_as_enum,
|
||||
RUMBLE_TYPE_DISABLED,RUMBLE_TYPE_GT_VALUE,1) ;
|
||||
RUMBLE_TYPE_DISABLED,RUMBLE_TYPE_END_LIST-1,1) ;
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
|
||||
config_uint_cbs(cheat_manager_state.working_cheat.rumble_value, CHEAT_RUMBLE_VALUE,
|
||||
|
Loading…
x
Reference in New Issue
Block a user