RetroArch/cheats.c

430 lines
9.6 KiB
C
Raw Normal View History

2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2014-01-01 00:50:59 +00:00
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
2015-01-07 16:46:50 +00:00
* Copyright (C) 2011-2015 - Daniel De Matteis
2011-04-17 11:30:59 +00:00
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software: you can redistribute it and/or modify it under the terms
2011-04-17 11:30:59 +00:00
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
2012-04-21 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
2011-04-17 11:30:59 +00:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
2012-04-21 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch.
2011-04-17 11:30:59 +00:00
* If not, see <http://www.gnu.org/licenses/>.
*/
2015-09-04 19:11:00 +00:00
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <file/config_file.h>
2015-01-19 18:00:26 +00:00
#include <file/file_path.h>
2014-10-21 05:58:58 +00:00
#include <compat/strl.h>
#include <compat/posix_string.h>
2011-04-17 11:30:59 +00:00
2015-10-27 17:52:34 +00:00
#include "cheats.h"
2015-09-04 19:11:00 +00:00
#include "general.h"
#include "runloop.h"
#include "dynamic.h"
2015-11-23 11:03:38 +00:00
#include "verbosity.h"
2015-09-04 19:11:00 +00:00
2011-09-05 15:57:30 +00:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_CHEEVOS
2015-10-27 17:52:34 +00:00
#include "cheevos.h"
#endif
2015-09-06 01:51:08 +00:00
struct item_cheat
{
char *desc;
bool state;
char *code;
};
struct cheat_manager
{
struct item_cheat *cheats;
unsigned ptr;
unsigned size;
unsigned buf_size;
};
2015-12-01 02:29:32 +00:00
static cheat_manager_t *cheat_manager_state;
unsigned cheat_manager_get_buf_size(void)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return 0;
return handle->buf_size;
}
2015-12-01 01:55:07 +00:00
unsigned cheat_manager_get_size(void)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return 0;
return handle->size;
}
2011-04-17 11:30:59 +00:00
void cheat_manager_apply_cheats(void)
2011-09-05 15:57:30 +00:00
{
2015-01-09 14:33:58 +00:00
unsigned i, idx = 0;
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2014-10-20 22:14:38 +00:00
if (!handle)
return;
core.retro_cheat_reset();
2015-01-09 14:33:58 +00:00
for (i = 0; i < handle->size; i++)
2011-09-05 15:57:30 +00:00
{
if (handle->cheats[i].state)
core.retro_cheat_set(idx++, true, handle->cheats[i].code);
2011-09-05 15:57:30 +00:00
}
#ifdef HAVE_CHEEVOS
cheevos_apply_cheats(idx != 0);
#endif
2011-09-05 15:57:30 +00:00
}
2015-12-01 01:55:07 +00:00
void cheat_manager_set_code(unsigned i, const char *str)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return;
handle->cheats[i].code = strdup(str);
handle->cheats[i].state = true;
}
2015-01-19 18:00:26 +00:00
/**
* cheat_manager_save:
* @path : Path to cheats file (relative path).
*
* Saves cheats to file on disk.
*
* Returns: true (1) if successful, otherwise false (0).
**/
2015-12-01 01:46:43 +00:00
bool cheat_manager_save(const char *path)
2015-01-19 18:00:26 +00:00
{
bool ret;
unsigned i;
2015-06-12 21:14:55 +00:00
config_file_t *conf = NULL;
char buf[PATH_MAX_LENGTH] = {0};
char cheats_file[PATH_MAX_LENGTH] = {0};
settings_t *settings = config_get_ptr();
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-01-19 18:00:26 +00:00
2015-03-20 19:43:22 +00:00
fill_pathname_join(buf, settings->cheat_database,
2015-01-19 18:00:26 +00:00
path, sizeof(buf));
fill_pathname_noext(cheats_file, buf, ".cht", sizeof(cheats_file));
conf = config_file_new(cheats_file);
if (!conf)
conf = config_file_new(NULL);
if (!conf)
return false;
if (!handle)
2015-01-27 14:35:31 +00:00
{
config_file_free(conf);
2015-01-19 18:00:26 +00:00
return false;
2015-01-27 14:35:31 +00:00
}
2015-01-19 18:00:26 +00:00
config_set_int(conf, "cheats", handle->size);
for (i = 0; i < handle->size; i++)
{
2015-06-12 21:14:55 +00:00
char key[64] = {0};
char desc_key[256] = {0};
char code_key[256] = {0};
char enable_key[256] = {0};
2015-01-19 18:00:26 +00:00
snprintf(key, sizeof(key), "cheat%u", i);
snprintf(desc_key, sizeof(desc_key), "cheat%u_desc", i);
snprintf(code_key, sizeof(code_key), "cheat%u_code", i);
snprintf(enable_key, sizeof(enable_key), "cheat%u_enable", i);
if (handle->cheats[i].desc)
config_set_string(conf, desc_key, handle->cheats[i].desc);
else
config_set_string(conf, desc_key, handle->cheats[i].code);
config_set_string(conf, code_key, handle->cheats[i].code);
config_set_bool(conf, enable_key, handle->cheats[i].state);
}
ret = config_file_write(conf, cheats_file);
config_file_free(conf);
return ret;
}
2015-12-01 02:00:31 +00:00
bool cheat_manager_load(const char *path)
{
unsigned cheats = 0, i;
2015-12-01 02:00:31 +00:00
cheat_manager_t *cheat;
config_file_t *conf = config_file_new(path);
if (!conf)
2015-12-01 02:00:31 +00:00
return false;
config_get_uint(conf, "cheats", &cheats);
if (cheats == 0)
2015-12-01 02:00:31 +00:00
return false;
cheat = cheat_manager_new(cheats);
if (!cheat)
2015-12-01 02:00:31 +00:00
return false;
for (i = 0; i < cheats; i++)
{
2015-06-12 21:14:55 +00:00
char key[64] = {0};
char desc_key[256] = {0};
char code_key[256] = {0};
char enable_key[256] = {0};
char *tmp = NULL;
bool tmp_bool = false;
snprintf(key, sizeof(key), "cheat%u", i);
snprintf(desc_key, sizeof(desc_key), "cheat%u_desc", i);
snprintf(code_key, sizeof(code_key), "cheat%u_code", i);
snprintf(enable_key, sizeof(enable_key), "cheat%u_enable", i);
if (config_get_string(conf, desc_key, &tmp))
cheat->cheats[i].desc = strdup(tmp);
if (config_get_string(conf, code_key, &tmp))
cheat->cheats[i].code = strdup(tmp);
if (config_get_bool(conf, enable_key, &tmp_bool))
cheat->cheats[i].state = tmp_bool;
if (tmp)
free(tmp);
}
config_file_free(conf);
2015-12-01 02:29:32 +00:00
cheat_manager_state = cheat;
2015-12-01 02:00:31 +00:00
return true;
}
cheat_manager_t *cheat_manager_new(unsigned size)
{
unsigned i;
2015-01-09 14:33:58 +00:00
cheat_manager_t *handle = (cheat_manager_t*)
calloc(1, sizeof(struct cheat_manager));
if (!handle)
return NULL;
2015-06-12 21:14:55 +00:00
handle->buf_size = size;
handle->size = size;
handle->cheats = (struct item_cheat*)
calloc(handle->buf_size, sizeof(struct item_cheat));
if (!handle->cheats)
{
handle->buf_size = 0;
handle->size = 0;
handle->cheats = NULL;
return handle;
}
for (i = 0; i < handle->size; i++)
{
handle->cheats[i].desc = NULL;
handle->cheats[i].code = NULL;
handle->cheats[i].state = false;
}
return handle;
}
2015-12-01 01:55:07 +00:00
bool cheat_manager_realloc(unsigned new_size)
{
unsigned i;
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
if (!handle)
return false;
if (!handle->cheats)
handle->cheats = (struct item_cheat*)
calloc(new_size, sizeof(struct item_cheat));
else
handle->cheats = (struct item_cheat*)
realloc(handle->cheats, new_size * sizeof(struct item_cheat));
if (!handle->cheats)
{
handle->buf_size = handle->size = 0;
handle->cheats = NULL;
return false;
}
handle->buf_size = new_size;
handle->size = new_size;
for (i = 0; i < handle->size; i++)
{
handle->cheats[i].desc = NULL;
handle->cheats[i].code = NULL;
handle->cheats[i].state = false;
}
return true;
}
2015-12-01 02:00:31 +00:00
void cheat_manager_free(void)
2011-04-17 11:30:59 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2011-04-17 11:30:59 +00:00
if (!handle)
return;
if (handle->cheats)
{
2015-09-28 16:22:27 +00:00
unsigned i;
for (i = 0; i < handle->size; i++)
2011-04-17 11:30:59 +00:00
{
free(handle->cheats[i].desc);
2011-04-17 13:58:18 +00:00
free(handle->cheats[i].code);
2011-04-17 11:30:59 +00:00
}
free(handle->cheats);
}
free(handle);
}
void cheat_manager_update(cheat_manager_t *handle, unsigned handle_idx)
2011-04-17 14:53:19 +00:00
{
2015-12-07 14:32:14 +00:00
char msg[256];
2015-01-09 14:33:58 +00:00
if (!handle)
return;
2014-09-02 03:32:04 +00:00
snprintf(msg, sizeof(msg), "Cheat: #%u [%s]: %s",
handle_idx, handle->cheats[handle_idx].state ? "ON" : "OFF",
(handle->cheats[handle_idx].desc) ?
(handle->cheats[handle_idx].desc) : (handle->cheats[handle_idx].code)
);
2015-12-07 14:32:14 +00:00
runloop_msg_queue_push(msg, 1, 180, true);
2012-04-21 21:25:32 +00:00
RARCH_LOG("%s\n", msg);
2011-04-17 14:53:19 +00:00
}
2015-12-01 02:03:33 +00:00
void cheat_manager_toggle_index(unsigned i)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return;
handle->cheats[i].state = !handle->cheats[i].state;
cheat_manager_update(handle, i);
}
2011-09-05 15:57:30 +00:00
2011-04-17 11:30:59 +00:00
void cheat_manager_toggle(cheat_manager_t *handle)
{
if (!handle)
return;
2011-04-17 11:30:59 +00:00
handle->cheats[handle->ptr].state ^= true;
cheat_manager_apply_cheats();
cheat_manager_update(handle, handle->ptr);
2011-04-17 14:53:19 +00:00
}
void cheat_manager_index_next(cheat_manager_t *handle)
{
if (!handle)
return;
2015-01-09 14:33:58 +00:00
2011-04-17 14:53:19 +00:00
handle->ptr = (handle->ptr + 1) % handle->size;
cheat_manager_update(handle, handle->ptr);
2011-04-17 14:53:19 +00:00
}
void cheat_manager_index_prev(cheat_manager_t *handle)
{
if (!handle)
return;
2011-04-17 14:53:19 +00:00
if (handle->ptr == 0)
handle->ptr = handle->size - 1;
else
handle->ptr--;
cheat_manager_update(handle, handle->ptr);
2011-04-17 11:30:59 +00:00
}
2015-09-06 01:51:08 +00:00
2015-12-01 01:49:27 +00:00
const char *cheat_manager_get_code(unsigned i)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return NULL;
return handle->cheats[i].code;
}
const char *cheat_manager_get_desc(unsigned i)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return NULL;
return handle->cheats[i].desc;
}
2015-12-01 01:49:27 +00:00
bool cheat_manager_get_code_state(unsigned i)
2015-09-06 01:51:08 +00:00
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-09-06 01:51:08 +00:00
if (!handle)
return false;
return handle->cheats[i].state;
}
void cheat_manager_state_checks(
bool cheat_index_plus_pressed,
bool cheat_index_minus_pressed,
bool cheat_toggle_pressed)
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
if (!handle)
return;
if (cheat_index_plus_pressed)
2015-12-01 02:29:32 +00:00
cheat_manager_index_next(handle);
else if (cheat_index_minus_pressed)
2015-12-01 02:29:32 +00:00
cheat_manager_index_prev(handle);
else if (cheat_toggle_pressed)
2015-12-01 02:29:32 +00:00
cheat_manager_toggle(handle);
}
void cheat_manager_state_free(void)
{
2015-12-01 02:00:31 +00:00
cheat_manager_free();
2015-12-01 02:29:32 +00:00
cheat_manager_state = NULL;
}
bool cheat_manager_alloc_if_empty(void)
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *handle = cheat_manager_state;
2015-12-01 02:29:32 +00:00
if (!handle)
{
2015-12-01 02:29:32 +00:00
cheat_manager_t *tmp = cheat_manager_new(0);
2015-12-01 02:29:32 +00:00
if (!tmp)
return false;
2015-12-01 02:29:32 +00:00
cheat_manager_state = tmp;
}
return true;
}