#include #include #include #include #include #include #include #include #include #include #include #include "gtk_config.h" #include "gtk_s9x.h" #include "gtk_sound.h" #include "gtk_display.h" char * get_config_dir (void) { char *homedir, *configdir; /* Find config directory */ homedir = getenv ("HOME"); if (!homedir) { configdir = strdup (".snes9x"); } else { configdir = (char *) malloc (strlen (homedir) + 9); sprintf (configdir, "%s/.snes9x", homedir); } return configdir; } 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; joystick_threshold = 40; #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; xrr_width = 0; xrr_height = 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; force_hires = 0; pause_emulation_on_switch = 0; num_threads = 2; mute_sound = FALSE; fullscreen = FALSE; ui_visible = TRUE; statusbar_visible = FALSE; default_esc_behavior = 1; prevent_screensaver = FALSE; sound_driver = 0; sound_buffer_size = 32; sound_playback_rate = 5; sound_input_rate = 31950; last_directory[0] = '\0'; window_width = -1; window_height = -1; preferences_width = -1; preferences_height = -1; sram_directory[0] = '\0'; export_directory[0] = '\0'; savestate_directory[0] = '\0'; cheat_directory[0] = '\0'; patch_directory[0] = '\0'; screensaver_needs_reset = FALSE; ntsc_setup = snes_ntsc_composite; ntsc_scanline_intensity = 1; scanline_filter_intensity = 0; bilinear_filter = 0; 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; modal_dialogs = 1; #ifdef USE_OPENGL sync_to_vblank = 1; use_pbos = 1; pbo_format = 0; npot_textures = FALSE; use_shaders = 0; fragment_shader[0] = '\0'; vertex_shader[0] = '\0'; sync_every_frame = FALSE; #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.DisableHDMA = 0; Settings.StopEmulation = TRUE; Settings.DisableIRQ = FALSE; Settings.FrameTimeNTSC = 16667; Settings.FrameTimePAL = 20000; Settings.SupportHiRes = true; Settings.FrameTime = Settings.FrameTimeNTSC; Settings.BlockInvalidVRAMAccessMaster = TRUE; Settings.SoundSync = 1; Settings.HDMATimingHack = 100; #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, "video_mode_width", xrr_width); xml_out_int (xml, "video_mode_height", xrr_height); 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); xml_out_int (xml, "force_hires", force_hires); 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); 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); 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); xml_out_int (xml, "modal_dialogs", modal_dialogs); 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); xml_out_int (xml, "bilinear_filter", bilinear_filter); #ifdef USE_OPENGL xml_out_int (xml, "sync_to_vblank", sync_to_vblank); xml_out_int (xml, "sync_every_frame", sync_every_frame); xml_out_int (xml, "use_pbos", use_pbos); xml_out_int (xml, "pbo_format", pbo_format); xml_out_int (xml, "npot_textures", npot_textures); xml_out_int (xml, "use_shaders", use_shaders); xml_out_string (xml, "fragment_shader", fragment_shader); #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); 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); /* 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, "hdma", !(Settings.DisableHDMA)); xml_out_int (xml, "block_invalid_vram_access", Settings.BlockInvalidVRAMAccessMaster); 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")) { } else if (!strcasecmp (name, "video_mode_width")) { xrr_width = atoi (value); } else if (!strcasecmp (name, "video_mode_height")) { xrr_height = atoi (value); } 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")) { force_hires = atoi (value); } else if (!strcasecmp (name, "scale_method")) { scale_method = atoi (value); #ifdef USE_HQ2X if (scale_method >= NUM_FILTERS) scale_method = 0; #else if (scale_method >= NUM_FILTERS - 3) scale_method = 0; #endif /* USE_HQ2X */ } 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); #endif } else if (!strcasecmp (name, "sync_every_frame")) { #ifdef USE_OPENGL sync_every_frame = atoi (value); #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); #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 /* Deprecated */ #endif } else if (!strcasecmp (name, "joystick_threshold")) { #ifdef USE_JOYSTICK joystick_threshold = atoi (value); #endif } else if (!strcasecmp (name, "data_location")) { /* Deprecated */ } 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); } 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); } 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")) { Settings.DisableHDMA = !(atoi (value)); } 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")) { 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); } else if (!strcasecmp (name, "modal_dialogs")) { modal_dialogs = atoi (value) ? 1 : 0; } 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; } 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)) { if (mkdir (pathname, 0755)) { fprintf (stderr, _("Couldn't create config directory: %s\n"), pathname); return -1; } } else { chmod (pathname, 0755); } 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); xmlFreeDoc (xml_doc); 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; }