843 lines
24 KiB
C
843 lines
24 KiB
C
/* src/psp/config.c: Configuration data management for PSP
|
|
Copyright 2009 Andrew Church
|
|
|
|
This file is part of Yabause.
|
|
|
|
Yabause is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Yabause is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Yabause; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
#include "config.h"
|
|
#include "psp-sh2.h"
|
|
#include "psp-video.h"
|
|
#include "sh2.h"
|
|
|
|
/*************************************************************************/
|
|
/****************************** Local data *******************************/
|
|
/*************************************************************************/
|
|
|
|
/* Configuration file name (always stored in program directory) */
|
|
#define PATH_INI "yabause.ini"
|
|
|
|
/* Data file paths */
|
|
static char path_bios[256] = "bios.bin";
|
|
static char path_cd[256] = "cd.iso";
|
|
static char path_bup[256] = "backup.bin";
|
|
|
|
/* General settings */
|
|
static int start_in_emu = 0;
|
|
static int use_me = 0;
|
|
static uint32_t me_writeback_period = 1;
|
|
static uint32_t me_uncached_boundary = 0x800;
|
|
static int bup_autosave = 1;
|
|
|
|
/* Button configuration */
|
|
static uint32_t button[6] = {
|
|
[CONFIG_BUTTON_A] = PSP_CTRL_CROSS,
|
|
[CONFIG_BUTTON_B] = PSP_CTRL_CIRCLE,
|
|
[CONFIG_BUTTON_C] = 0,
|
|
[CONFIG_BUTTON_X] = PSP_CTRL_SQUARE,
|
|
[CONFIG_BUTTON_Y] = PSP_CTRL_TRIANGLE,
|
|
[CONFIG_BUTTON_Z] = 0,
|
|
};
|
|
|
|
/* Module selections */
|
|
static int module_sh2 = SH2CORE_PSP;
|
|
static int module_video = VIDCORE_PSP;
|
|
|
|
/* Display settings */
|
|
static int cache_textures = 1;
|
|
static int smooth_textures = 0;
|
|
static int smooth_hires = 0;
|
|
static int enable_rotate = 1;
|
|
static int optimize_rotate = 1;
|
|
static int frameskip_auto = 0;
|
|
static int frameskip_num = 0;
|
|
static int frameskip_interlace = 1;
|
|
static int frameskip_rotate = 1;
|
|
static int show_fps = 0;
|
|
|
|
static uint32_t sh2_optimizations = SH2_OPTIMIZE_ASSUME_SAFE_DIVISION
|
|
| SH2_OPTIMIZE_BRANCH_TO_RTS
|
|
| SH2_OPTIMIZE_FOLD_SUBROUTINES
|
|
| SH2_OPTIMIZE_LOCAL_ACCESSES
|
|
| SH2_OPTIMIZE_LOCAL_POINTERS
|
|
| SH2_OPTIMIZE_MAC_NOSAT
|
|
| SH2_OPTIMIZE_POINTERS
|
|
| SH2_OPTIMIZE_POINTERS_MAC
|
|
| SH2_OPTIMIZE_STACK;
|
|
/* All known optimization flags (so we can leave newly-implemented flags at
|
|
* their default values when loading the config file) */
|
|
#define SH2_KNOWN_OPTIMIZATIONS (SH2_OPTIMIZE_ASSUME_SAFE_DIVISION \
|
|
| SH2_OPTIMIZE_BRANCH_TO_RTS \
|
|
| SH2_OPTIMIZE_FOLD_SUBROUTINES \
|
|
| SH2_OPTIMIZE_LOCAL_ACCESSES \
|
|
| SH2_OPTIMIZE_LOCAL_POINTERS \
|
|
| SH2_OPTIMIZE_MAC_NOSAT \
|
|
| SH2_OPTIMIZE_POINTERS \
|
|
| SH2_OPTIMIZE_POINTERS_MAC \
|
|
| SH2_OPTIMIZE_STACK)
|
|
|
|
/* Deciline (precise timing) mode flag */
|
|
static int deciline_mode = 0;
|
|
/* Audio sync flag */
|
|
static int audio_sync = 1;
|
|
/* Clock sync flag */
|
|
static int clock_sync = 1;
|
|
/* Start-from-fixed-time flag */
|
|
static int clock_fixed_time = 0;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/* Local function declarations */
|
|
|
|
static int parse_string(const char *file, int line, const char *name,
|
|
const char *text, char *buffer, unsigned int bufsize);
|
|
static int parse_int(const char *file, int line, const char *name,
|
|
const char *text, int *value_ret);
|
|
static int parse_uint32(const char *file, int line, const char *name,
|
|
const char *text, uint32_t *value_ret);
|
|
|
|
/*************************************************************************/
|
|
/************************** Interface functions **************************/
|
|
/*************************************************************************/
|
|
|
|
/**
|
|
* config_load: Load configuration data from the configuration file.
|
|
* Invalid data is ignored, and options not specified in the configuration
|
|
* file are left unchanged.
|
|
*
|
|
* [Parameters]
|
|
* None
|
|
* [Return value]
|
|
* None
|
|
*/
|
|
void config_load(void)
|
|
{
|
|
/* Open the configuration file, aborting if it's not available */
|
|
FILE *f = fopen(PATH_INI, "r");
|
|
if (!f) {
|
|
perror("fopen(" PATH_INI ")");
|
|
return;
|
|
}
|
|
|
|
/* Read the entire file in at once and close the file pointer */
|
|
char *filebuf;
|
|
if (fseek(f, 0, SEEK_END) < 0) {
|
|
perror("fseek(SEEK_END)");
|
|
close_and_return:
|
|
fclose(f);
|
|
return;
|
|
}
|
|
long filesize = ftell(f);
|
|
if (filesize < 0) {
|
|
perror("ftell()");
|
|
goto close_and_return;
|
|
}
|
|
if (fseek(f, 0, SEEK_SET) < 0) {
|
|
perror("fseek(SEEK_SET)");
|
|
goto close_and_return;
|
|
}
|
|
filebuf = malloc(filesize+1); // Leave space for a trailing \0
|
|
if (!filebuf) {
|
|
fprintf(stderr, "No memory for config file buffer (%ld bytes)\n",
|
|
filesize);
|
|
goto close_and_return;
|
|
}
|
|
if (fread(filebuf, filesize, 1, f) != 1) {
|
|
fprintf(stderr, "Failed to read config file\n");
|
|
free(filebuf);
|
|
goto close_and_return;
|
|
}
|
|
fclose(f);
|
|
filebuf[filesize] = 0;
|
|
|
|
/* Parse each line of the configuration file; lines are of the form
|
|
* name=value
|
|
* with no spaces permitted on either side of the "=". We take care
|
|
* to treat names as case-insensitive and to support any of "\r",
|
|
* "\r\n" or "\n" as a line terminator, in case people edit the file
|
|
* on their own. */
|
|
|
|
char *s, *eol;
|
|
int line;
|
|
for (s = filebuf, line = 1; *s; s = eol, line++) {
|
|
|
|
eol = s + strcspn(s, "\r\n");
|
|
if (*eol == '\r') {
|
|
*eol++ = 0;
|
|
}
|
|
if (*eol == '\n') {
|
|
*eol++ = 0;
|
|
}
|
|
char *name = s;
|
|
char *value = strchr(s, '=');
|
|
if (!value) {
|
|
fprintf(stderr, "%s:%d: Missing `='\n", PATH_INI, line);
|
|
continue;
|
|
}
|
|
*value++ = 0;
|
|
|
|
if (stricmp(name, "path_bios") == 0) {
|
|
parse_string(PATH_INI, line, name, value,
|
|
path_bios, sizeof(path_bios));
|
|
|
|
} else if (stricmp(name, "path_cd") == 0) {
|
|
parse_string(PATH_INI, line, name, value,
|
|
path_cd, sizeof(path_cd));
|
|
|
|
} else if (stricmp(name, "path_bup") == 0) {
|
|
parse_string(PATH_INI, line, name, value,
|
|
path_bup, sizeof(path_bup));
|
|
|
|
} else if (stricmp(name, "start_in_emu") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &start_in_emu);
|
|
|
|
} else if (stricmp(name, "use_me") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &use_me);
|
|
|
|
} else if (stricmp(name, "me_writeback_period") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value, &me_writeback_period);
|
|
if (!me_writeback_period
|
|
|| (me_writeback_period & (me_writeback_period - 1))
|
|
) {
|
|
fprintf(stderr, "config_load(): Invalid value %u for"
|
|
" me_writeback_period (must be a power of 2)\n",
|
|
me_writeback_period);
|
|
me_writeback_period = 1;
|
|
}
|
|
|
|
} else if (stricmp(name, "me_uncached_boundary") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value, &me_uncached_boundary);
|
|
if (me_uncached_boundary > 0x80000) {
|
|
me_uncached_boundary = 0x80000;
|
|
}
|
|
|
|
} else if (stricmp(name, "bup_autosave") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &bup_autosave);
|
|
|
|
} else if (stricmp(name, "button.A") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_A]);
|
|
|
|
} else if (stricmp(name, "button.B") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_B]);
|
|
|
|
} else if (stricmp(name, "button.C") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_C]);
|
|
|
|
} else if (stricmp(name, "button.X") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_X]);
|
|
|
|
} else if (stricmp(name, "button.Y") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_Y]);
|
|
|
|
} else if (stricmp(name, "button.Z") == 0) {
|
|
parse_uint32(PATH_INI, line, name, value,&button[CONFIG_BUTTON_Z]);
|
|
|
|
} else if (stricmp(name, "module_sh2") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &module_sh2);
|
|
|
|
} else if (stricmp(name, "module_video") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &module_video);
|
|
|
|
} else if (stricmp(name, "cache_textures") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &cache_textures);
|
|
|
|
} else if (stricmp(name, "smooth_textures") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &smooth_textures);
|
|
|
|
} else if (stricmp(name, "smooth_hires") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &smooth_hires);
|
|
|
|
} else if (stricmp(name, "enable_rotate") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &enable_rotate);
|
|
|
|
} else if (stricmp(name, "optimize_rotate") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &optimize_rotate);
|
|
|
|
} else if (stricmp(name, "frameskip_auto") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &frameskip_auto);
|
|
|
|
} else if (stricmp(name, "frameskip_num") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &frameskip_num);
|
|
if (frameskip_num < 0) {
|
|
frameskip_num = 0;
|
|
} else if (frameskip_num > 9) {
|
|
frameskip_num = 9;
|
|
}
|
|
|
|
} else if (stricmp(name, "frameskip_interlace") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &frameskip_interlace);
|
|
|
|
} else if (stricmp(name, "frameskip_rotate") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &frameskip_rotate);
|
|
|
|
} else if (stricmp(name, "show_fps") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &show_fps);
|
|
|
|
} else if (stricmp(name, "sh2_optimizations") == 0) {
|
|
uint32_t newval = strtoul(value, &s, 10);
|
|
if (*s != '/') {
|
|
fprintf(stderr, "%s:%d: Bad format for `%s' value\n",
|
|
PATH_INI, line, name);
|
|
continue;
|
|
}
|
|
uint32_t mask = strtoul(s+1, &s, 10);
|
|
if (*s) {
|
|
fprintf(stderr, "%s:%d: Bad format for `%s' value\n",
|
|
PATH_INI, line, name);
|
|
continue;
|
|
}
|
|
sh2_optimizations &= ~mask;
|
|
sh2_optimizations |= newval & mask;
|
|
|
|
} else if (stricmp(name, "deciline_mode") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &deciline_mode);
|
|
|
|
} else if (stricmp(name, "audio_sync") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &audio_sync);
|
|
|
|
} else if (stricmp(name, "clock_sync") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &clock_sync);
|
|
|
|
} else if (stricmp(name, "clock_fixed_time") == 0) {
|
|
parse_int(PATH_INI, line, name, value, &clock_fixed_time);
|
|
|
|
} else {
|
|
fprintf(stderr, "%s:%d: Unknown configuration variable `%s'\n",
|
|
PATH_INI, line, name);
|
|
|
|
}
|
|
|
|
} // for (s = filebuf, line = 1; *s; s = eol, line++)
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* config_save: Save the current configuration to the configuration file.
|
|
*
|
|
* [Parameters]
|
|
* None
|
|
* [Return value]
|
|
* Nonzero on success, zero on error
|
|
*/
|
|
int config_save(void)
|
|
{
|
|
FILE *f = fopen(PATH_INI, "w");
|
|
if (!f) {
|
|
perror("fopen(" PATH_INI ")");
|
|
return 0;
|
|
}
|
|
|
|
if (fprintf(f, "path_bios=%s\n", path_bios ) < 0
|
|
|| fprintf(f, "path_cd=%s\n", path_cd ) < 0
|
|
|| fprintf(f, "path_bup=%s\n", path_bup ) < 0
|
|
|| fprintf(f, "start_in_emu=%d\n", start_in_emu ) < 0
|
|
|| fprintf(f, "use_me=%d\n", use_me ) < 0
|
|
|| fprintf(f, "me_writeback_period=%u\n", me_writeback_period ) < 0
|
|
|| fprintf(f, "me_uncached_boundary=%u\n", me_uncached_boundary ) < 0
|
|
|| fprintf(f, "bup_autosave=%d\n", bup_autosave ) < 0
|
|
|| fprintf(f, "button.A=%u\n", button[CONFIG_BUTTON_A]) < 0
|
|
|| fprintf(f, "button.B=%u\n", button[CONFIG_BUTTON_B]) < 0
|
|
|| fprintf(f, "button.C=%u\n", button[CONFIG_BUTTON_C]) < 0
|
|
|| fprintf(f, "button.X=%u\n", button[CONFIG_BUTTON_X]) < 0
|
|
|| fprintf(f, "button.Y=%u\n", button[CONFIG_BUTTON_Y]) < 0
|
|
|| fprintf(f, "button.Z=%u\n", button[CONFIG_BUTTON_Z]) < 0
|
|
|| fprintf(f, "module_sh2=%d\n", module_sh2 ) < 0
|
|
|| fprintf(f, "module_video=%d\n", module_video ) < 0
|
|
|| fprintf(f, "cache_textures=%d\n", cache_textures ) < 0
|
|
|| fprintf(f, "smooth_textures=%d\n", smooth_textures ) < 0
|
|
|| fprintf(f, "smooth_hires=%d\n", smooth_hires ) < 0
|
|
|| fprintf(f, "enable_rotate=%d\n", enable_rotate ) < 0
|
|
|| fprintf(f, "optimize_rotate=%d\n", optimize_rotate ) < 0
|
|
|| fprintf(f, "frameskip_auto=%d\n", frameskip_auto ) < 0
|
|
|| fprintf(f, "frameskip_num=%d\n", frameskip_num ) < 0
|
|
|| fprintf(f, "frameskip_interlace=%d\n", frameskip_interlace ) < 0
|
|
|| fprintf(f, "frameskip_rotate=%d\n", frameskip_rotate ) < 0
|
|
|| fprintf(f, "show_fps=%d\n", show_fps ) < 0
|
|
|| fprintf(f, "sh2_optimizations=%u/%u\n", sh2_optimizations,
|
|
SH2_KNOWN_OPTIMIZATIONS) < 0
|
|
|| fprintf(f, "deciline_mode=%d\n", deciline_mode ) < 0
|
|
|| fprintf(f, "audio_sync=%d\n", audio_sync ) < 0
|
|
|| fprintf(f, "clock_sync=%d\n", clock_sync ) < 0
|
|
|| fprintf(f, "clock_fixed_time=%d\n", clock_fixed_time ) < 0
|
|
) {
|
|
perror("fprintf(" PATH_INI ",...)");
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
if (fclose(f) < 0) {
|
|
perror("fclose(" PATH_INI ")");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/**
|
|
* config_get_*: Retrieve the current value of a configuration variable.
|
|
*
|
|
* [Parameters]
|
|
* id: Button ID (only for config_get_button())
|
|
* [Return value]
|
|
* Current value of configuration variable
|
|
*/
|
|
|
|
const char *config_get_path_bios(void)
|
|
{
|
|
return path_bios;
|
|
}
|
|
|
|
const char *config_get_path_cd(void)
|
|
{
|
|
return path_cd;
|
|
}
|
|
|
|
const char *config_get_path_bup(void)
|
|
{
|
|
return path_bup;
|
|
}
|
|
|
|
int config_get_start_in_emu(void)
|
|
{
|
|
return start_in_emu;
|
|
}
|
|
|
|
int config_get_use_me(void)
|
|
{
|
|
return use_me;
|
|
}
|
|
|
|
uint32_t config_get_me_writeback_period(void)
|
|
{
|
|
return me_writeback_period;
|
|
}
|
|
|
|
uint32_t config_get_me_uncached_boundary(void)
|
|
{
|
|
return me_uncached_boundary;
|
|
}
|
|
|
|
int config_get_bup_autosave(void)
|
|
{
|
|
return bup_autosave;
|
|
}
|
|
|
|
uint32_t config_get_button(ConfigButtonID id)
|
|
{
|
|
PRECOND(id >= CONFIG_BUTTON_A && id <= CONFIG_BUTTON_Z, return 0);
|
|
return button[id];
|
|
}
|
|
|
|
int config_get_module_sh2(void)
|
|
{
|
|
return module_sh2;
|
|
}
|
|
|
|
int config_get_module_video(void)
|
|
{
|
|
return module_video;
|
|
}
|
|
|
|
int config_get_cache_textures(void)
|
|
{
|
|
return cache_textures;
|
|
}
|
|
|
|
int config_get_smooth_textures(void)
|
|
{
|
|
return smooth_textures;
|
|
}
|
|
|
|
int config_get_smooth_hires(void)
|
|
{
|
|
return smooth_hires;
|
|
}
|
|
|
|
int config_get_enable_rotate(void)
|
|
{
|
|
return enable_rotate;
|
|
}
|
|
|
|
int config_get_optimize_rotate(void)
|
|
{
|
|
return optimize_rotate;
|
|
}
|
|
|
|
int config_get_frameskip_auto(void)
|
|
{
|
|
return frameskip_auto;
|
|
}
|
|
|
|
int config_get_frameskip_num(void)
|
|
{
|
|
return frameskip_num;
|
|
}
|
|
|
|
int config_get_frameskip_interlace(void)
|
|
{
|
|
return frameskip_interlace;
|
|
}
|
|
|
|
int config_get_frameskip_rotate(void)
|
|
{
|
|
return frameskip_rotate;
|
|
}
|
|
|
|
int config_get_show_fps(void)
|
|
{
|
|
return show_fps;
|
|
}
|
|
|
|
uint32_t config_get_sh2_optimizations(void)
|
|
{
|
|
return sh2_optimizations;
|
|
}
|
|
|
|
int config_get_deciline_mode(void)
|
|
{
|
|
return deciline_mode;
|
|
}
|
|
|
|
int config_get_audio_sync(void)
|
|
{
|
|
return audio_sync;
|
|
}
|
|
|
|
int config_get_clock_sync(void)
|
|
{
|
|
return clock_sync;
|
|
}
|
|
|
|
int config_get_clock_fixed_time(void)
|
|
{
|
|
return clock_fixed_time;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* config_set_*: Set the value of a configuration variable.
|
|
*
|
|
* [Parameters]
|
|
* id: Button ID (only for config_get_button())
|
|
* value: New value for configuration variable
|
|
* [Return value]
|
|
* Nonzero on success, zero on error
|
|
*/
|
|
|
|
int config_set_path_bios(const char *value)
|
|
{
|
|
PRECOND(value != NULL, return 0);
|
|
if (strlen(value) > sizeof(path_bios) - 1) {
|
|
fprintf(stderr, "config_set_path_bios(): Value too long (max %d"
|
|
" characters): %s\n", sizeof(path_bios) - 1, value);
|
|
return 0;
|
|
}
|
|
strcpy(path_bios, value); // Safe
|
|
return 1;
|
|
}
|
|
|
|
int config_set_path_cd(const char *value)
|
|
{
|
|
PRECOND(value != NULL, return 0);
|
|
if (strlen(value) > sizeof(path_cd) - 1) {
|
|
fprintf(stderr, "config_set_path_cd(): Value too long (max %d"
|
|
" characters): %s\n", sizeof(path_cd) - 1, value);
|
|
return 0;
|
|
}
|
|
strcpy(path_cd, value); // Safe
|
|
return 1;
|
|
}
|
|
|
|
int config_set_path_bup(const char *value)
|
|
{
|
|
PRECOND(value != NULL, return 0);
|
|
if (strlen(value) > sizeof(path_bup) - 1) {
|
|
fprintf(stderr, "config_set_path_bup(): Value too long (max %d"
|
|
" characters): %s\n", sizeof(path_bup) - 1, value);
|
|
return 0;
|
|
}
|
|
strcpy(path_bup, value); // Safe
|
|
return 1;
|
|
}
|
|
|
|
int config_set_start_in_emu(int value)
|
|
{
|
|
start_in_emu = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_use_me(int value)
|
|
{
|
|
use_me = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_me_writeback_period(uint32_t value)
|
|
{
|
|
if (value == 0 || (value & (value-1))) {
|
|
fprintf(stderr, "config_set_me_writeback_period(): Invalid period %u"
|
|
" (must be a power of 2)\n", value);
|
|
return 0;
|
|
}
|
|
me_writeback_period = value;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_me_uncached_boundary(uint32_t value)
|
|
{
|
|
if (value > 0x80000) {
|
|
fprintf(stderr, "config_set_me_uncached_boundary(): Invalid boundary"
|
|
" %u (maximum %u)\n", value, 0x80000);
|
|
return 0;
|
|
}
|
|
me_uncached_boundary = value;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_bup_autosave(int value)
|
|
{
|
|
bup_autosave = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_button(ConfigButtonID id, uint32_t value)
|
|
{
|
|
PRECOND(id >= CONFIG_BUTTON_A && id <= CONFIG_BUTTON_Z, return 0);
|
|
button[id] = value;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_module_sh2(int value)
|
|
{
|
|
module_sh2 = value;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_module_video(int value)
|
|
{
|
|
module_video = value;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_cache_textures(int value)
|
|
{
|
|
cache_textures = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_smooth_textures(int value)
|
|
{
|
|
smooth_textures = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_smooth_hires(int value)
|
|
{
|
|
smooth_hires = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_enable_rotate(int value)
|
|
{
|
|
enable_rotate = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_optimize_rotate(int value)
|
|
{
|
|
optimize_rotate = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_frameskip_auto(int value)
|
|
{
|
|
frameskip_auto = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_frameskip_num(int value)
|
|
{
|
|
if (value < 0) {
|
|
frameskip_num = 0;
|
|
} else if (value > 9) {
|
|
frameskip_num = 9;
|
|
} else {
|
|
frameskip_num = value;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int config_set_frameskip_interlace(int value)
|
|
{
|
|
frameskip_interlace = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_frameskip_rotate(int value)
|
|
{
|
|
frameskip_rotate = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_show_fps(int value)
|
|
{
|
|
show_fps = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_sh2_optimizations(uint32_t value)
|
|
{
|
|
sh2_optimizations = value & SH2_KNOWN_OPTIMIZATIONS;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_deciline_mode(int value)
|
|
{
|
|
deciline_mode = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_audio_sync(int value)
|
|
{
|
|
audio_sync = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_clock_sync(int value)
|
|
{
|
|
clock_sync = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
int config_set_clock_fixed_time(int value)
|
|
{
|
|
clock_fixed_time = value ? 1 : 0;
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/**************************** Local routines *****************************/
|
|
/*************************************************************************/
|
|
|
|
/**
|
|
* parse_string: Parse a string-type configuration entry.
|
|
*
|
|
* [Parameters]
|
|
* file: Name of configuration file (for error messages)
|
|
* line: Line number in configuration file (for error messages)
|
|
* name: Configuration entry name (for error messages)
|
|
* text: Configuration value text
|
|
* buffer: Buffer into which to store string value
|
|
* bufsize: Size of buffer (maximum string length + 1)
|
|
* [Return value]
|
|
* Nonzero on success, zero on error
|
|
*/
|
|
static int parse_string(const char *file, int line, const char *name,
|
|
const char *text, char *buffer, unsigned int bufsize)
|
|
{
|
|
PRECOND(text != NULL, return 0);
|
|
PRECOND(buffer != NULL, return 0);
|
|
|
|
if (strlen(text) > bufsize - 1) {
|
|
fprintf(stderr, "%s:%d: String for `%s' too long (max %d"
|
|
" characters)\n", file, line, name, bufsize - 1);
|
|
return 0;
|
|
}
|
|
strcpy(buffer, text); // Safe
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* parse_int: Parse an integer-type configuration entry.
|
|
*
|
|
* [Parameters]
|
|
* file: Name of configuration file (for error messages)
|
|
* line: Line number in configuration file (for error messages)
|
|
* name: Configuration entry name (for error messages)
|
|
* text: Configuration value text
|
|
* value_ret: Pointer to variable into which to store integer value
|
|
* [Return value]
|
|
* Nonzero on success, zero on error
|
|
*/
|
|
static int parse_int(const char *file, int line, const char *name,
|
|
const char *text, int *value_ret)
|
|
{
|
|
PRECOND(text != NULL, return 0);
|
|
PRECOND(value_ret != NULL, return 0);
|
|
|
|
char *s;
|
|
int newval = strtol(text, &s, 10);
|
|
if (*s) {
|
|
fprintf(stderr, "%s:%d: Value for `%s' must be a number\n",
|
|
file, line, name);
|
|
return 0;
|
|
}
|
|
*value_ret = newval;
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* parse_uint32: Parse a 32-bit unsigned integer configuration entry.
|
|
*
|
|
* [Parameters]
|
|
* file: Name of configuration file (for error messages)
|
|
* line: Line number in configuration file (for error messages)
|
|
* name: Configuration entry name (for error messages)
|
|
* text: Configuration value text
|
|
* value_ret: Pointer to variable into which to store integer value
|
|
* [Return value]
|
|
* Nonzero on success, zero on error
|
|
*/
|
|
static int parse_uint32(const char *file, int line, const char *name,
|
|
const char *text, uint32_t *value_ret)
|
|
{
|
|
PRECOND(text != NULL, return 0);
|
|
PRECOND(value_ret != NULL, return 0);
|
|
|
|
char *s;
|
|
uint32_t newval = strtoul(text, &s, 10);
|
|
if (*s) {
|
|
fprintf(stderr, "%s:%d: Value for `%s' must be a nonnegative number\n",
|
|
file, line, name);
|
|
return 0;
|
|
}
|
|
*value_ret = newval;
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-file-style: "stroustrup"
|
|
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vim: expandtab shiftwidth=4:
|
|
*/
|