2010-09-25 17:46:12 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xmlwriter.h>
|
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gdk/gdk.h>
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
|
|
|
#include "gtk_config.h"
|
|
|
|
#include "gtk_s9x.h"
|
|
|
|
#include "gtk_sound.h"
|
|
|
|
#include "gtk_display.h"
|
|
|
|
|
2017-05-07 01:39:01 +02:00
|
|
|
static int
|
|
|
|
directory_exists (const char *directory)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
|
|
|
|
dir = opendir (directory);
|
|
|
|
|
|
|
|
if (dir)
|
|
|
|
{
|
|
|
|
closedir (dir);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
char *
|
|
|
|
get_config_dir (void)
|
|
|
|
{
|
2017-05-07 01:39:01 +02:00
|
|
|
char *home_dir = NULL,
|
|
|
|
*classic_config_dir = NULL,
|
|
|
|
*xdg_config_dir = NULL,
|
|
|
|
*xdg_snes9x_dir = NULL;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
/* Find config directory */
|
2017-05-07 01:39:01 +02:00
|
|
|
home_dir = getenv ("HOME");
|
2017-05-07 01:43:36 +02:00
|
|
|
xdg_config_dir = getenv ("XDG_CONFIG_HOME");
|
2017-05-07 01:39:01 +02:00
|
|
|
|
|
|
|
if (!home_dir && !xdg_config_dir)
|
|
|
|
{
|
|
|
|
return strdup (".snes9x");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!xdg_config_dir)
|
|
|
|
{
|
|
|
|
xdg_snes9x_dir = (char *) malloc (strlen (home_dir) + 16);
|
|
|
|
sprintf (xdg_snes9x_dir, "%s/.config/snes9x", home_dir);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xdg_snes9x_dir = (char *) malloc (strlen (xdg_config_dir) + 9);
|
|
|
|
sprintf (xdg_snes9x_dir, "%s/snes9x", xdg_config_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
classic_config_dir = (char *) malloc (strlen (home_dir) + 9);
|
|
|
|
sprintf (classic_config_dir, "%s/.snes9x", home_dir);
|
|
|
|
|
|
|
|
char *config_dir;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2017-05-07 01:39:01 +02:00
|
|
|
if (directory_exists (classic_config_dir) && !directory_exists(xdg_snes9x_dir))
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2017-05-07 01:39:01 +02:00
|
|
|
free (xdg_snes9x_dir);
|
|
|
|
config_dir = classic_config_dir;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-07 01:39:01 +02:00
|
|
|
free (classic_config_dir);
|
|
|
|
config_dir = xdg_snes9x_dir;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2017-05-07 01:39:01 +02:00
|
|
|
return config_dir;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
get_config_file_name (void)
|
|
|
|
{
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
filename = get_config_dir ();
|
|
|
|
|
|
|
|
filename = (char *) realloc (filename, strlen (filename) + 12);
|
|
|
|
strcat (filename, "/snes9x.xml");
|
|
|
|
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xml_out_string (xmlTextWriterPtr xml, const char *name, const char *value)
|
|
|
|
{
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST ("option"));
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST ("name"), BAD_CAST (name));
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST ("value"), BAD_CAST (value));
|
|
|
|
xmlTextWriterEndElement (xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xml_out_int (xmlTextWriterPtr xml, const char *name, int value)
|
|
|
|
{
|
|
|
|
char string[1024];
|
|
|
|
snprintf (string, 1024, "%d", value);
|
|
|
|
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "option");
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "name", BAD_CAST name);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "value", BAD_CAST string);
|
|
|
|
xmlTextWriterEndElement (xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xml_out_float (xmlTextWriterPtr xml, const char *name, float value)
|
|
|
|
{
|
|
|
|
char string[1024];
|
|
|
|
snprintf (string, 1024, "%f", value);
|
|
|
|
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "option");
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "name", BAD_CAST name);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "value", BAD_CAST string);
|
|
|
|
xmlTextWriterEndElement (xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xml_out_binding (xmlTextWriterPtr xml, const char *name, unsigned int value)
|
|
|
|
{
|
|
|
|
char string[1024];
|
|
|
|
snprintf (string, 1024, "%u", value);
|
|
|
|
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST ("binding"));
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST ("name"), BAD_CAST (name));
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST ("binding"), BAD_CAST (string));
|
|
|
|
xmlTextWriterEndElement (xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
S9xParsePortConfig (ConfigFile &conf, int pass)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Snes9xConfig::Snes9xConfig (void)
|
|
|
|
{
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
joystick = NULL;
|
2010-10-21 03:55:59 +02:00
|
|
|
joystick_threshold = 40;
|
2010-09-25 17:46:12 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
opengl_activated = FALSE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::load_defaults (void)
|
|
|
|
{
|
|
|
|
full_screen_on_open = 0;
|
|
|
|
change_display_resolution = 0;
|
|
|
|
xrr_index = 0;
|
|
|
|
scale_to_fit = 1;
|
|
|
|
maintain_aspect_ratio = 0;
|
|
|
|
aspect_ratio = 0;
|
|
|
|
scale_method = 0;
|
|
|
|
overscan = 0;
|
|
|
|
save_sram_after_secs = 0;
|
|
|
|
rom_loaded = 0;
|
|
|
|
multithreading = 0;
|
|
|
|
hw_accel = 0;
|
|
|
|
allow_opengl = 0;
|
|
|
|
allow_xv = 0;
|
|
|
|
allow_xrandr = 0;
|
|
|
|
force_inverted_byte_order = FALSE;
|
2011-01-24 00:07:22 +01:00
|
|
|
hires_effect = HIRES_NORMAL;
|
2010-09-25 17:46:12 +02:00
|
|
|
pause_emulation_on_switch = 0;
|
|
|
|
num_threads = 2;
|
|
|
|
mute_sound = FALSE;
|
2016-08-02 17:31:05 +02:00
|
|
|
mute_sound_turbo = FALSE;
|
2010-09-25 17:46:12 +02:00
|
|
|
fullscreen = FALSE;
|
|
|
|
ui_visible = TRUE;
|
2010-09-26 11:19:15 +02:00
|
|
|
statusbar_visible = FALSE;
|
2010-09-25 17:46:12 +02:00
|
|
|
default_esc_behavior = 1;
|
|
|
|
prevent_screensaver = FALSE;
|
|
|
|
sound_driver = 0;
|
2010-09-26 11:19:15 +02:00
|
|
|
sound_buffer_size = 32;
|
2010-09-25 17:46:12 +02:00
|
|
|
sound_playback_rate = 5;
|
|
|
|
sound_input_rate = 31950;
|
2018-05-02 23:53:54 +02:00
|
|
|
auto_input_rate = TRUE;
|
2010-09-25 17:46:12 +02:00
|
|
|
last_directory[0] = '\0';
|
|
|
|
window_width = -1;
|
|
|
|
window_height = -1;
|
|
|
|
preferences_width = -1;
|
|
|
|
preferences_height = -1;
|
2010-09-26 11:19:15 +02:00
|
|
|
sram_directory[0] = '\0';
|
|
|
|
export_directory[0] = '\0';
|
|
|
|
savestate_directory[0] = '\0';
|
|
|
|
cheat_directory[0] = '\0';
|
|
|
|
patch_directory[0] = '\0';
|
2010-09-25 17:46:12 +02:00
|
|
|
screensaver_needs_reset = FALSE;
|
|
|
|
ntsc_setup = snes_ntsc_composite;
|
|
|
|
ntsc_scanline_intensity = 1;
|
|
|
|
scanline_filter_intensity = 0;
|
2010-11-18 13:31:27 +01:00
|
|
|
bilinear_filter = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
netplay_activated = FALSE;
|
|
|
|
netplay_server_up = FALSE;
|
|
|
|
netplay_is_server = FALSE;
|
|
|
|
netplay_sync_reset = TRUE;
|
|
|
|
netplay_send_rom = FALSE;
|
|
|
|
netplay_default_port = 6096;
|
|
|
|
netplay_max_frame_loss = 10;
|
|
|
|
netplay_last_rom [0] = '\0';
|
|
|
|
netplay_last_host [0] = '\0';
|
|
|
|
netplay_last_port = 6096;
|
2010-10-30 16:21:26 +02:00
|
|
|
modal_dialogs = 1;
|
2018-04-26 18:15:20 +02:00
|
|
|
S9xCheatsEnable ();
|
2016-10-09 04:33:34 +02:00
|
|
|
|
|
|
|
rewind_granularity = 5;
|
|
|
|
rewind_buffer_size = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
sync_to_vblank = 1;
|
|
|
|
use_pbos = 1;
|
|
|
|
pbo_format = 0;
|
|
|
|
npot_textures = FALSE;
|
2010-09-26 11:19:15 +02:00
|
|
|
use_shaders = 0;
|
|
|
|
fragment_shader[0] = '\0';
|
|
|
|
vertex_shader[0] = '\0';
|
|
|
|
sync_every_frame = FALSE;
|
2010-09-25 17:46:12 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Snes9X Variables */
|
|
|
|
Settings.MouseMaster = TRUE;
|
|
|
|
Settings.SuperScopeMaster = TRUE;
|
|
|
|
Settings.JustifierMaster = TRUE;
|
|
|
|
Settings.MultiPlayer5Master = TRUE;
|
|
|
|
Settings.UpAndDown = FALSE;
|
|
|
|
Settings.AutoSaveDelay = 0;
|
|
|
|
Settings.SkipFrames = AUTO_FRAMERATE;
|
|
|
|
Settings.Transparency = TRUE;
|
|
|
|
Settings.DisplayFrameRate = FALSE;
|
|
|
|
Settings.SixteenBitSound = TRUE;
|
|
|
|
Settings.Stereo = TRUE;
|
|
|
|
Settings.ReverseStereo = FALSE;
|
|
|
|
Settings.SoundPlaybackRate = 32000;
|
|
|
|
Settings.StopEmulation = TRUE;
|
|
|
|
Settings.FrameTimeNTSC = 16667;
|
|
|
|
Settings.FrameTimePAL = 20000;
|
|
|
|
Settings.SupportHiRes = true;
|
|
|
|
Settings.FrameTime = Settings.FrameTimeNTSC;
|
|
|
|
Settings.BlockInvalidVRAMAccessMaster = TRUE;
|
|
|
|
Settings.SoundSync = 1;
|
2018-05-03 00:44:22 +02:00
|
|
|
Settings.DynamicRateControl = FALSE;
|
2017-11-24 20:03:24 +01:00
|
|
|
Settings.DynamicRateLimit = 5;
|
2010-09-25 17:46:12 +02:00
|
|
|
Settings.HDMATimingHack = 100;
|
2018-05-08 00:03:06 +02:00
|
|
|
Settings.SuperFXClockMultiplier = 100;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
Settings.NetPlay = FALSE;
|
|
|
|
NetPlay.Paused = FALSE;
|
|
|
|
NetPlay.MaxFrameSkip = 10;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
memset (pad, 0, sizeof (JoypadBinding) * NUM_JOYPADS);
|
|
|
|
memset (shortcut, 0, sizeof (Binding) * NUM_EMU_LINKS);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xConfig::joystick_register_centers (void)
|
|
|
|
{
|
|
|
|
for (int i = 0; joystick[i] != NULL; i++)
|
|
|
|
joystick[i]->register_centers ();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xConfig::flush_joysticks (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; joystick[i] != NULL; i++)
|
|
|
|
joystick[i]->flush ();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xConfig::set_joystick_mode (int mode)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; joystick[i] != NULL; i++)
|
|
|
|
joystick[i]->mode = mode;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::save_config_file (void)
|
|
|
|
{
|
|
|
|
xmlTextWriterPtr xml;
|
|
|
|
char *filename;
|
|
|
|
char buffer[256];
|
|
|
|
|
|
|
|
filename = get_config_file_name ();
|
|
|
|
xml = xmlNewTextWriterFilename (filename, 0);
|
|
|
|
free (filename);
|
|
|
|
|
|
|
|
xmlTextWriterSetIndent (xml, 1);
|
|
|
|
|
|
|
|
xmlTextWriterStartDocument (xml, NULL, NULL, NULL);
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "snes9x");
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "preferences");
|
|
|
|
|
|
|
|
xml_out_int (xml, "full_screen_on_open", full_screen_on_open);
|
|
|
|
xml_out_int (xml, "change_display_resolution", change_display_resolution);
|
|
|
|
xml_out_int (xml, "video_mode", xrr_index);
|
|
|
|
xml_out_int (xml, "scale_to_fit", scale_to_fit);
|
|
|
|
xml_out_int (xml, "maintain_aspect_ratio", maintain_aspect_ratio);
|
|
|
|
xml_out_int (xml, "aspect_ratio", aspect_ratio);
|
|
|
|
xml_out_int (xml, "scale_method", scale_method);
|
|
|
|
xml_out_int (xml, "overscan", overscan);
|
2011-01-23 23:25:46 +01:00
|
|
|
xml_out_int (xml, "hires_effect", hires_effect);
|
2010-09-25 17:46:12 +02:00
|
|
|
xml_out_int (xml, "force_inverted_byte_order", force_inverted_byte_order);
|
|
|
|
xml_out_int (xml, "multithreading", multithreading);
|
|
|
|
xml_out_string (xml, "last_directory", last_directory);
|
2010-09-26 11:19:15 +02:00
|
|
|
xml_out_string (xml, "sram_directory", sram_directory);
|
|
|
|
xml_out_string (xml, "savestate_directory", savestate_directory);
|
|
|
|
xml_out_string (xml, "cheat_directory", cheat_directory);
|
|
|
|
xml_out_string (xml, "patch_directory", patch_directory);
|
|
|
|
xml_out_string (xml, "export_directory", export_directory);
|
2010-09-25 17:46:12 +02:00
|
|
|
xml_out_int (xml, "window_width", window_width);
|
|
|
|
xml_out_int (xml, "window_height", window_height);
|
|
|
|
xml_out_int (xml, "preferences_width", preferences_width);
|
|
|
|
xml_out_int (xml, "preferences_height", preferences_height);
|
|
|
|
xml_out_int (xml, "pause_emulation_on_switch", pause_emulation_on_switch);
|
|
|
|
xml_out_int (xml, "num_threads", num_threads);
|
|
|
|
xml_out_int (xml, "default_esc_behavior", default_esc_behavior);
|
|
|
|
xml_out_int (xml, "prevent_screensaver", prevent_screensaver);
|
|
|
|
if (default_esc_behavior != ESC_TOGGLE_MENUBAR)
|
|
|
|
xml_out_int (xml, "fullscreen", 0);
|
|
|
|
else
|
|
|
|
xml_out_int (xml, "fullscreen", fullscreen);
|
|
|
|
xml_out_int (xml, "ui_visible", ui_visible);
|
|
|
|
xml_out_int (xml, "statusbar_visible", statusbar_visible);
|
2010-10-30 16:21:26 +02:00
|
|
|
xml_out_int (xml, "modal_dialogs", modal_dialogs);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
xml_out_float (xml, "ntsc_hue", ntsc_setup.hue);
|
|
|
|
xml_out_float (xml, "ntsc_saturation", ntsc_setup.saturation);
|
|
|
|
xml_out_float (xml, "ntsc_contrast", ntsc_setup.contrast);
|
|
|
|
xml_out_float (xml, "ntsc_brightness", ntsc_setup.brightness);
|
|
|
|
xml_out_float (xml, "ntsc_sharpness", ntsc_setup.sharpness);
|
|
|
|
xml_out_float (xml, "ntsc_artifacts", ntsc_setup.artifacts);
|
|
|
|
xml_out_float (xml, "ntsc_gamma", ntsc_setup.gamma);
|
|
|
|
xml_out_float (xml, "ntsc_bleed", ntsc_setup.bleed);
|
|
|
|
xml_out_float (xml, "ntsc_fringing", ntsc_setup.fringing);
|
|
|
|
xml_out_float (xml, "ntsc_resolution", ntsc_setup.resolution);
|
|
|
|
xml_out_int (xml, "ntsc_merge_fields", ntsc_setup.merge_fields);
|
|
|
|
xml_out_int (xml, "ntsc_scanline_intensity", ntsc_scanline_intensity);
|
|
|
|
xml_out_int (xml, "scanline_filter_intensity", scanline_filter_intensity);
|
|
|
|
xml_out_int (xml, "hw_accel", hw_accel);
|
2010-11-18 13:31:27 +01:00
|
|
|
xml_out_int (xml, "bilinear_filter", bilinear_filter);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2016-10-09 04:33:34 +02:00
|
|
|
xml_out_int (xml, "rewind_buffer_size", rewind_buffer_size);
|
|
|
|
xml_out_int (xml, "rewind_granularity", rewind_granularity);
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
xml_out_int (xml, "sync_to_vblank", sync_to_vblank);
|
2010-09-26 11:19:15 +02:00
|
|
|
xml_out_int (xml, "sync_every_frame", sync_every_frame);
|
2010-09-25 17:46:12 +02:00
|
|
|
xml_out_int (xml, "use_pbos", use_pbos);
|
|
|
|
xml_out_int (xml, "pbo_format", pbo_format);
|
|
|
|
xml_out_int (xml, "npot_textures", npot_textures);
|
2010-09-26 11:19:15 +02:00
|
|
|
xml_out_int (xml, "use_shaders", use_shaders);
|
|
|
|
xml_out_string (xml, "fragment_shader", fragment_shader);
|
2010-09-25 17:46:12 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
xml_out_int (xml, "joystick_threshold", joystick_threshold);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
xml_out_int (xml, "netplay_is_server", netplay_is_server);
|
|
|
|
xml_out_int (xml, "netplay_sync_reset", netplay_sync_reset);
|
|
|
|
xml_out_int (xml, "netplay_send_rom", netplay_send_rom);
|
|
|
|
xml_out_int (xml, "netplay_default_port", netplay_default_port);
|
|
|
|
xml_out_int (xml, "netplay_max_frame_loss", netplay_max_frame_loss);
|
|
|
|
xml_out_int (xml, "netplay_last_port", netplay_last_port);
|
|
|
|
xml_out_string (xml, "netplay_last_rom", netplay_last_rom);
|
|
|
|
xml_out_string (xml, "netplay_last_host", netplay_last_host);
|
|
|
|
|
|
|
|
xml_out_int (xml, "mute_sound", mute_sound);
|
2016-08-02 17:31:05 +02:00
|
|
|
xml_out_int (xml, "mute_sound_turbo", mute_sound_turbo);
|
2010-09-25 17:46:12 +02:00
|
|
|
xml_out_int (xml, "sound_buffer_size", sound_buffer_size);
|
|
|
|
xml_out_int (xml, "sound_driver", sound_driver);
|
|
|
|
xml_out_int (xml, "sound_input_rate", sound_input_rate);
|
|
|
|
xml_out_int (xml, "sound_sync", Settings.SoundSync);
|
2017-11-20 20:06:13 +01:00
|
|
|
xml_out_int (xml, "dynamic_rate_control", Settings.DynamicRateControl);
|
|
|
|
xml_out_int (xml, "dynamic_rate_limit", Settings.DynamicRateLimit);
|
2018-05-03 00:43:32 +02:00
|
|
|
xml_out_int (xml, "auto_input_rate", auto_input_rate);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
/* Snes9X core-stored variables */
|
|
|
|
xml_out_int (xml, "transparency", Settings.Transparency);
|
|
|
|
xml_out_int (xml, "show_frame_rate", Settings.DisplayFrameRate);
|
|
|
|
xml_out_int (xml, "frameskip", Settings.SkipFrames);
|
|
|
|
xml_out_int (xml, "save_sram_after_secs", Settings.AutoSaveDelay);
|
|
|
|
xml_out_int (xml, "16bit_sound", Settings.SixteenBitSound);
|
|
|
|
xml_out_int (xml, "stereo", Settings.Stereo);
|
|
|
|
xml_out_int (xml, "reverse_stereo", Settings.ReverseStereo);
|
|
|
|
xml_out_int (xml, "playback_rate", gui_config->sound_playback_rate);
|
|
|
|
xml_out_int (xml, "block_invalid_vram_access", Settings.BlockInvalidVRAMAccessMaster);
|
2018-05-08 00:03:06 +02:00
|
|
|
xml_out_int (xml, "superfx_clock_multiplier", Settings.SuperFXClockMultiplier);
|
2010-09-25 17:46:12 +02:00
|
|
|
xml_out_int (xml, "upanddown", Settings.UpAndDown);
|
|
|
|
|
|
|
|
xmlTextWriterEndElement (xml); /* preferences */
|
|
|
|
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "controls");
|
|
|
|
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
for (int i = 0; joystick[i]; i++)
|
|
|
|
{
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "calibration");
|
|
|
|
snprintf (buffer, 256, "%d", i);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "joystick", BAD_CAST buffer);
|
|
|
|
|
|
|
|
for (int j = 0; j < joystick[i]->num_axes; j++)
|
|
|
|
{
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "axis");
|
|
|
|
|
|
|
|
snprintf (buffer, 256, "%d", j);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "number", BAD_CAST buffer);
|
|
|
|
|
|
|
|
snprintf (buffer, 256, "%d", joystick[i]->calibration[j].min);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "min", BAD_CAST buffer);
|
|
|
|
|
|
|
|
snprintf (buffer, 256, "%d", joystick[i]->calibration[j].max);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "max", BAD_CAST buffer);
|
|
|
|
|
|
|
|
snprintf (buffer, 256, "%d", joystick[i]->calibration[j].center);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "center", BAD_CAST buffer);
|
|
|
|
|
|
|
|
xmlTextWriterEndElement (xml); /* axis */
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlTextWriterEndElement (xml); /* Calibration */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_JOYPADS; i++)
|
|
|
|
{
|
|
|
|
Binding *joypad = (Binding *) &pad[i];
|
|
|
|
|
|
|
|
xmlTextWriterStartElement (xml, BAD_CAST "joypad");
|
|
|
|
snprintf (buffer, 256, "%d", i);
|
|
|
|
xmlTextWriterWriteAttribute (xml, BAD_CAST "number", BAD_CAST buffer);
|
|
|
|
|
|
|
|
for (int j = 0; j < NUM_JOYPAD_LINKS; j++)
|
|
|
|
{
|
|
|
|
xml_out_binding (xml, b_links[j].snes9x_name, joypad[j].hex ());
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlTextWriterEndElement (xml); /* joypad */
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++)
|
|
|
|
{
|
|
|
|
xml_out_binding (xml,
|
|
|
|
b_links[i].snes9x_name,
|
|
|
|
shortcut[i - NUM_JOYPAD_LINKS].hex ());
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlTextWriterEndElement (xml); /* controls */
|
|
|
|
xmlTextWriterEndElement (xml); /* snes9x */
|
|
|
|
xmlTextWriterEndDocument (xml);
|
|
|
|
|
|
|
|
xmlFreeTextWriter (xml);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::set_option (const char *name, const char *value)
|
|
|
|
{
|
|
|
|
if (!strcasecmp (name, "full_screen_on_open"))
|
|
|
|
{
|
|
|
|
full_screen_on_open = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "change_display_resolution"))
|
|
|
|
{
|
|
|
|
change_display_resolution = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "video_mode"))
|
|
|
|
{
|
2018-04-29 01:36:40 +02:00
|
|
|
xrr_index = atoi (value);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "scale_to_fit"))
|
|
|
|
{
|
|
|
|
scale_to_fit = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "maintain_aspect_ratio"))
|
|
|
|
{
|
|
|
|
maintain_aspect_ratio = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "aspect_ratio"))
|
|
|
|
{
|
|
|
|
aspect_ratio = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "force_hires"))
|
|
|
|
{
|
2011-01-23 23:25:46 +01:00
|
|
|
/* Deprecated */
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "hires_effect"))
|
|
|
|
{
|
|
|
|
hires_effect = atoi (value);
|
|
|
|
hires_effect = CLAMP (hires_effect, 0, 2);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "scale_method"))
|
|
|
|
{
|
|
|
|
scale_method = atoi (value);
|
2010-09-26 11:19:15 +02:00
|
|
|
#ifdef USE_HQ2X
|
2010-09-25 17:46:12 +02:00
|
|
|
if (scale_method >= NUM_FILTERS)
|
|
|
|
scale_method = 0;
|
2010-09-26 11:19:15 +02:00
|
|
|
#else
|
|
|
|
if (scale_method >= NUM_FILTERS - 3)
|
|
|
|
scale_method = 0;
|
|
|
|
#endif /* USE_HQ2X */
|
2015-01-28 15:24:35 +01:00
|
|
|
#ifdef USE_XBRZ
|
|
|
|
if (scale_method >= NUM_FILTERS)
|
|
|
|
scale_method = 0;
|
|
|
|
#else
|
|
|
|
if (scale_method >= NUM_FILTERS - 3)
|
|
|
|
scale_method = 0;
|
|
|
|
#endif /* USE_XBRZ */
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "multithreading"))
|
|
|
|
{
|
|
|
|
multithreading = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "hw_accel"))
|
|
|
|
{
|
|
|
|
hw_accel = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "use_opengl"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (atoi (value) == 1)
|
|
|
|
hw_accel = HWA_OPENGL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "bilinear_filter"))
|
|
|
|
{
|
|
|
|
bilinear_filter = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sync_to_vblank"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
sync_to_vblank = atoi (value);
|
2010-09-26 11:19:15 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sync_every_frame"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
sync_every_frame = atoi (value);
|
2010-09-25 17:46:12 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "use_pbos"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
use_pbos = atoi (value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "pbo_format"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
pbo_format = atoi (value);
|
|
|
|
pbo_format = CLAMP (pbo_format, 0, 2);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "npot_textures"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
npot_textures = atoi (value);
|
2010-09-26 11:19:15 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "use_shaders"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
use_shaders = atoi (value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "fragment_shader"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
strncpy (fragment_shader, value, PATH_MAX);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "vertex_shader"))
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
2010-10-22 04:18:56 +02:00
|
|
|
/* Deprecated */
|
2010-09-25 17:46:12 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "joystick_threshold"))
|
|
|
|
{
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
joystick_threshold = atoi (value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "data_location"))
|
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
/* Deprecated */
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "save_sram_after_secs"))
|
|
|
|
{
|
|
|
|
Settings.AutoSaveDelay = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "pause_emulation_on_switch"))
|
|
|
|
{
|
|
|
|
pause_emulation_on_switch = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "transparency"))
|
|
|
|
{
|
|
|
|
Settings.Transparency = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "show_frame_rate"))
|
|
|
|
{
|
|
|
|
Settings.DisplayFrameRate = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "frameskip"))
|
|
|
|
{
|
|
|
|
Settings.SkipFrames = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_emulation"))
|
|
|
|
{
|
|
|
|
mute_sound = !(atoi (value));
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "mute_sound"))
|
|
|
|
{
|
|
|
|
mute_sound = atoi (value);
|
|
|
|
}
|
2016-08-02 17:31:05 +02:00
|
|
|
else if (!strcasecmp (name, "mute_sound_turbo"))
|
|
|
|
{
|
|
|
|
mute_sound_turbo = atoi (value);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
else if (!strcasecmp (name, "16bit_sound"))
|
|
|
|
{
|
|
|
|
Settings.SixteenBitSound = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "stereo"))
|
|
|
|
{
|
|
|
|
Settings.Stereo = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "reverse_stereo"))
|
|
|
|
{
|
|
|
|
Settings.ReverseStereo = atoi (value);
|
|
|
|
}
|
2017-11-20 20:06:13 +01:00
|
|
|
else if (!strcasecmp (name, "dynamic_rate_control"))
|
|
|
|
{
|
|
|
|
Settings.DynamicRateControl = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "dynamic_rate_limit"))
|
|
|
|
{
|
|
|
|
Settings.DynamicRateLimit = atoi (value);
|
2017-11-24 20:03:24 +01:00
|
|
|
Settings.DynamicRateLimit = CLAMP (Settings.DynamicRateLimit, 1, 1000);
|
2017-11-20 20:06:13 +01:00
|
|
|
}
|
2018-05-03 00:43:32 +02:00
|
|
|
else if (!strcasecmp (name, "auto_input_rate"))
|
|
|
|
{
|
|
|
|
auto_input_rate = atoi (value);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
else if (!strcasecmp (name, "gaussian_interpolation"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "envelope_reading"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_echo"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "master_volume"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "playback_rate"))
|
|
|
|
{
|
|
|
|
sound_playback_rate = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_decoder"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "hdma"))
|
|
|
|
{
|
2010-11-28 23:28:55 +01:00
|
|
|
/* Deprecated */
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
2018-05-08 00:03:06 +02:00
|
|
|
else if (!strcasecmp (name, "superfx_clock_multiplier"))
|
|
|
|
{
|
|
|
|
Settings.SuperFXClockMultiplier = atoi (value);
|
|
|
|
Settings.SuperFXClockMultiplier = CLAMP (Settings.SuperFXClockMultiplier, 50, 400);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
else if (!strcasecmp (name, "speedhacks"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "overscan"))
|
|
|
|
{
|
|
|
|
overscan = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "last_directory"))
|
|
|
|
{
|
|
|
|
strncpy (last_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "custom_sram_directory"))
|
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
strncpy (sram_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sram_directory"))
|
|
|
|
{
|
|
|
|
strncpy (sram_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "savestate_directory"))
|
|
|
|
{
|
|
|
|
strncpy (savestate_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "cheat_directory"))
|
|
|
|
{
|
|
|
|
strncpy (cheat_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "patch_directory"))
|
|
|
|
{
|
|
|
|
strncpy (patch_directory, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "export_directory"))
|
|
|
|
{
|
|
|
|
strncpy (export_directory, value, PATH_MAX);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
2010-10-30 16:21:26 +02:00
|
|
|
else if (!strcasecmp (name, "modal_dialogs"))
|
|
|
|
{
|
|
|
|
modal_dialogs = atoi (value) ? 1 : 0;
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
else if (!strcasecmp (name, "window_width"))
|
|
|
|
{
|
|
|
|
window_width = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "window_height"))
|
|
|
|
{
|
|
|
|
window_height = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "preferences_width"))
|
|
|
|
{
|
|
|
|
preferences_width = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "preferences_height"))
|
|
|
|
{
|
|
|
|
preferences_height = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_format"))
|
|
|
|
{
|
|
|
|
/* Deprecated */
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_hue"))
|
|
|
|
{
|
|
|
|
ntsc_setup.hue = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_saturation"))
|
|
|
|
{
|
|
|
|
ntsc_setup.saturation = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_contrast"))
|
|
|
|
{
|
|
|
|
ntsc_setup.contrast = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_brightness"))
|
|
|
|
{
|
|
|
|
ntsc_setup.brightness = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_sharpness"))
|
|
|
|
{
|
|
|
|
ntsc_setup.sharpness = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_warping"))
|
|
|
|
{
|
|
|
|
/* Deprecated */
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_artifacts"))
|
|
|
|
{
|
|
|
|
ntsc_setup.artifacts = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_gamma"))
|
|
|
|
{
|
|
|
|
ntsc_setup.gamma = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_fringing"))
|
|
|
|
{
|
|
|
|
ntsc_setup.fringing = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_bleed"))
|
|
|
|
{
|
|
|
|
ntsc_setup.bleed = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_resolution"))
|
|
|
|
{
|
|
|
|
ntsc_setup.resolution = (float) atof (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_merge_fields"))
|
|
|
|
{
|
|
|
|
ntsc_setup.merge_fields = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ntsc_scanline_intensity"))
|
|
|
|
{
|
|
|
|
ntsc_scanline_intensity = CLAMP (atoi (value), 0, 4);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "scanline_filter_intensity"))
|
|
|
|
{
|
|
|
|
scanline_filter_intensity = CLAMP (atoi (value), 0, 3);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "num_threads"))
|
|
|
|
{
|
|
|
|
num_threads = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_is_server"))
|
|
|
|
{
|
|
|
|
netplay_is_server = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_sync_reset"))
|
|
|
|
{
|
|
|
|
netplay_sync_reset = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_send_rom"))
|
|
|
|
{
|
|
|
|
netplay_send_rom = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_default_port"))
|
|
|
|
{
|
|
|
|
netplay_default_port = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_max_frame_loss"))
|
|
|
|
{
|
|
|
|
netplay_max_frame_loss = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_last_port"))
|
|
|
|
{
|
|
|
|
netplay_last_port = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_last_rom"))
|
|
|
|
{
|
|
|
|
strncpy (netplay_last_rom, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "netplay_last_host"))
|
|
|
|
{
|
|
|
|
strncpy (netplay_last_host, value, PATH_MAX);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "fullscreen"))
|
|
|
|
{
|
|
|
|
fullscreen = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "ui_visible"))
|
|
|
|
{
|
|
|
|
ui_visible = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "statusbar_visible"))
|
|
|
|
{
|
|
|
|
statusbar_visible = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "default_esc_behavior"))
|
|
|
|
{
|
|
|
|
default_esc_behavior = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_buffer_size"))
|
|
|
|
{
|
|
|
|
sound_buffer_size = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_input_rate"))
|
|
|
|
{
|
|
|
|
sound_input_rate = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_driver"))
|
|
|
|
{
|
|
|
|
sound_driver = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "prevent_screensaver"))
|
|
|
|
{
|
|
|
|
prevent_screensaver = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "force_inverted_byte_order"))
|
|
|
|
{
|
|
|
|
force_inverted_byte_order = atoi (value);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "block_invalid_vram_access"))
|
|
|
|
{
|
|
|
|
Settings.BlockInvalidVRAMAccessMaster = CLAMP (atoi (value), 0, 1);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "upanddown"))
|
|
|
|
{
|
|
|
|
Settings.UpAndDown = CLAMP (atoi (value), 0, 1);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "sound_sync"))
|
|
|
|
{
|
|
|
|
Settings.SoundSync = atoi (value) ? 1 : 0;
|
|
|
|
}
|
2016-10-09 04:33:34 +02:00
|
|
|
else if (!strcasecmp (name, "rewind_buffer_size"))
|
|
|
|
{
|
|
|
|
rewind_buffer_size = CLAMP (atoi (value), 0, 2000);
|
|
|
|
}
|
|
|
|
else if (!strcasecmp (name, "rewind_granularity"))
|
|
|
|
{
|
|
|
|
rewind_granularity = CLAMP (atoi (value), 0, 600);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf (stderr, _("bad option name: %s\n"), name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_option (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlAttrPtr attr = NULL;
|
|
|
|
char *name, *value;
|
|
|
|
|
|
|
|
/* Find name string */
|
|
|
|
for (attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "name"))
|
|
|
|
{
|
|
|
|
name = (char *) attr->children->content;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attr)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Find value string */
|
|
|
|
for (attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "value"))
|
|
|
|
{
|
|
|
|
value = (char *) attr->children->content;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attr)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return set_option (name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_binding (xmlNodePtr node, int joypad_number)
|
|
|
|
{
|
|
|
|
char *name = NULL;
|
|
|
|
char *type = NULL;
|
|
|
|
Binding b;
|
|
|
|
|
|
|
|
for (xmlAttrPtr attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "name"))
|
|
|
|
name = (char *) attr->children->content;
|
|
|
|
|
|
|
|
else if (!xmlStrcasecmp (attr->name, BAD_CAST "binding"))
|
|
|
|
type = (char *) attr->children->content;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = Binding ((unsigned int) strtoul (type, NULL, 10));
|
|
|
|
|
|
|
|
if (joypad_number > -1 && joypad_number < NUM_JOYPAD_LINKS)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < NUM_JOYPAD_LINKS; i++)
|
|
|
|
{
|
|
|
|
if (!strcasecmp (b_links[i].snes9x_name, name))
|
|
|
|
{
|
|
|
|
Binding *buttons = (Binding *) &pad[joypad_number];
|
|
|
|
|
|
|
|
if (b.is_key () || b.is_joy ())
|
|
|
|
buttons[i] = b;
|
|
|
|
else
|
|
|
|
buttons[i].clear ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++)
|
|
|
|
{
|
|
|
|
if (!strcasecmp (b_links[i].snes9x_name, name))
|
|
|
|
{
|
|
|
|
if (b.is_key () || b.is_joy ())
|
|
|
|
shortcut[i - NUM_JOYPAD_LINKS] = b;
|
|
|
|
else
|
|
|
|
shortcut[i - NUM_JOYPAD_LINKS].clear ();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_joypad (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlAttrPtr attr;
|
|
|
|
int joypad_number = -1;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
/* Try to read joypad number */
|
|
|
|
for (attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "number"))
|
|
|
|
{
|
|
|
|
joypad_number = atoi ((char *) attr->children->content);
|
|
|
|
|
|
|
|
if (joypad_number < 0 || joypad_number > (NUM_JOYPADS - 1))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (xmlNodePtr i = node->children; i; i = i->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "binding"))
|
|
|
|
{
|
|
|
|
retval = parse_binding (i, joypad_number) || retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_axis (xmlNodePtr node, int joynum)
|
|
|
|
{
|
|
|
|
xmlAttrPtr attr;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
int number = -1, min = -32767, max = 32767, center = 0;
|
|
|
|
|
|
|
|
for (attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "number"))
|
|
|
|
{
|
|
|
|
number = atoi ((char *) attr->children->content);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!xmlStrcasecmp (attr->name, BAD_CAST "min"))
|
|
|
|
{
|
|
|
|
min = atoi ((char *) attr->children->content);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!xmlStrcasecmp (attr->name, BAD_CAST "max"))
|
|
|
|
{
|
|
|
|
max = atoi ((char *) attr->children->content);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!xmlStrcasecmp (attr->name, BAD_CAST "center"))
|
|
|
|
{
|
|
|
|
center = atoi ((char *) attr->children->content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (number >= 0 && number < joystick[joynum]->num_axes)
|
|
|
|
{
|
|
|
|
joystick[joynum]->calibration[number].min = min;
|
|
|
|
joystick[joynum]->calibration[number].max = max;
|
|
|
|
joystick[joynum]->calibration[number].center = center;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_calibration (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlAttrPtr attr;
|
|
|
|
int joynum = -1;
|
|
|
|
int num_joysticks = 0;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
for (num_joysticks = 0; joystick[num_joysticks]; num_joysticks++)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
for (attr = node->properties; attr; attr = attr->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (attr->name, BAD_CAST "joystick"))
|
|
|
|
{
|
|
|
|
joynum = atoi ((char *) attr->children->content);
|
|
|
|
|
|
|
|
if (joynum < 0 || joynum >= num_joysticks)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (xmlNodePtr i = node->children; i; i = i->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "axis"))
|
|
|
|
{
|
|
|
|
retval = parse_axis (i, joynum) | retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_preferences (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlNodePtr i = NULL;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
for (i = node->children; i; i = i->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "option"))
|
|
|
|
retval = parse_option (i) || retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_controls (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
for (xmlNodePtr i = node->children; i; i = i->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "joypad"))
|
|
|
|
retval = parse_joypad (i) || retval;
|
|
|
|
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "binding"))
|
|
|
|
retval = parse_binding (i, -1) || retval;
|
|
|
|
|
|
|
|
#ifdef USE_JOYSTICK
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "calibration"))
|
|
|
|
retval = parse_calibration (i) || retval;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::parse_snes9x (xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlNodePtr i = NULL;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
if (xmlStrcasecmp (node->name, BAD_CAST "snes9x"))
|
|
|
|
{
|
|
|
|
fprintf (stderr, _("failure to read snes9x node"));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = node->children; i; i = i->next)
|
|
|
|
{
|
|
|
|
if (!xmlStrcasecmp (i->name, BAD_CAST "preferences"))
|
|
|
|
{
|
|
|
|
retval = parse_preferences (i) || retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!xmlStrcasecmp (i->name, BAD_CAST "controls"))
|
|
|
|
{
|
|
|
|
retval = parse_controls (i) || retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xConfig::load_config_file (void)
|
|
|
|
{
|
|
|
|
struct stat file_info;
|
|
|
|
char *pathname;
|
|
|
|
xmlDoc *xml_doc = NULL;
|
|
|
|
xmlNodePtr xml_root = NULL;
|
|
|
|
|
|
|
|
load_defaults ();
|
|
|
|
|
|
|
|
pathname = get_config_dir ();
|
|
|
|
|
|
|
|
if (stat (pathname, &file_info))
|
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
if (mkdir (pathname, 0755))
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
_("Couldn't create config directory: %s\n"),
|
|
|
|
pathname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2010-09-26 11:19:15 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
chmod (pathname, 0755);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
free (pathname);
|
|
|
|
|
|
|
|
pathname = get_config_file_name ();
|
|
|
|
|
|
|
|
if (stat (pathname, &file_info))
|
|
|
|
{
|
|
|
|
save_config_file ();
|
|
|
|
}
|
|
|
|
|
|
|
|
xml_doc = xmlReadFile (pathname, NULL, 0);
|
|
|
|
|
|
|
|
if (!xml_doc)
|
|
|
|
{
|
|
|
|
fprintf (stderr, _("Couldn't open config file: %s\n"), pathname);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
free (pathname);
|
|
|
|
|
|
|
|
xml_root = xmlDocGetRootElement (xml_doc);
|
|
|
|
|
|
|
|
parse_snes9x (xml_root);
|
|
|
|
|
2010-10-22 04:18:56 +02:00
|
|
|
xmlFreeDoc (xml_doc);
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xConfig::rebind_keys (void)
|
|
|
|
{
|
|
|
|
s9xcommand_t cmd;
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
S9xUnmapAllControls ();
|
|
|
|
|
|
|
|
for (int joypad_i = 0; joypad_i < NUM_JOYPADS; joypad_i++ )
|
|
|
|
{
|
|
|
|
Binding *bin = (Binding *) &pad[joypad_i];
|
|
|
|
|
|
|
|
for (int button_i = 0; button_i < NUM_JOYPAD_LINKS; button_i++)
|
|
|
|
{
|
|
|
|
snprintf (buf,
|
|
|
|
256,
|
|
|
|
"Joypad%d %s",
|
|
|
|
(joypad_i % 5) + 1,
|
|
|
|
b_links[button_i].snes9x_name);
|
|
|
|
|
|
|
|
cmd = S9xGetPortCommandT (buf);
|
|
|
|
|
|
|
|
S9xMapButton (bin[button_i].base_hex (), cmd, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++)
|
|
|
|
{
|
|
|
|
snprintf (buf, 256, "%s", b_links[i].snes9x_name);
|
|
|
|
cmd = S9xGetPortCommandT (buf);
|
|
|
|
S9xMapButton (shortcut[i - NUM_JOYPAD_LINKS].base_hex (),
|
|
|
|
cmd,
|
|
|
|
FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd = S9xGetPortCommandT ("Pointer Mouse1+Superscope+Justifier1");
|
|
|
|
S9xMapPointer (BINDING_MOUSE_POINTER, cmd, TRUE);
|
|
|
|
|
|
|
|
cmd = S9xGetPortCommandT ("{Mouse1 L,Superscope Fire,Justifier1 Trigger}");
|
|
|
|
S9xMapButton (BINDING_MOUSE_BUTTON0, cmd, FALSE);
|
|
|
|
|
|
|
|
cmd = S9xGetPortCommandT ("{Justifier1 AimOffscreen Trigger,Superscope AimOffscreen}");
|
|
|
|
S9xMapButton (BINDING_MOUSE_BUTTON1, cmd, FALSE);
|
|
|
|
|
|
|
|
cmd = S9xGetPortCommandT ("{Mouse1 R,Superscope Cursor,Justifier1 Start}");
|
|
|
|
S9xMapButton (BINDING_MOUSE_BUTTON2, cmd, FALSE);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xConfig::reconfigure (void)
|
|
|
|
{
|
|
|
|
rebind_keys ();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|