2018-11-16 00:42:29 +01:00
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System ( TM ) emulator .
This file is licensed under the Snes9x License .
For further information , consult the LICENSE file in the root directory .
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-25 17:46:12 +02:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <sys/stat.h>
# include "gtk_config.h"
# include "gtk_s9x.h"
# include "gtk_sound.h"
# include "gtk_display.h"
2018-11-02 02:44:06 +01:00
# include "conffile.h"
2010-09-25 17:46:12 +02:00
2018-12-04 00:27:44 +01:00
static bool directory_exists ( std : : string str )
2017-05-07 01:39:01 +02:00
{
DIR * dir ;
2018-12-04 00:27:44 +01:00
dir = opendir ( str . c_str ( ) ) ;
2017-05-07 01:39:01 +02:00
if ( dir )
{
closedir ( dir ) ;
2018-12-04 00:27:44 +01:00
return true ;
2017-05-07 01:39:01 +02:00
}
2018-12-04 00:27:44 +01:00
return false ;
2017-05-07 01:39:01 +02:00
}
2018-11-18 20:08:42 +01:00
std : : string get_config_dir ( )
2010-09-25 17:46:12 +02:00
{
2018-11-18 20:08:42 +01:00
// Find config directory
char * env_home = getenv ( " HOME " ) ;
char * env_xdg_config_home = getenv ( " XDG_CONFIG_HOME " ) ;
2010-09-25 17:46:12 +02:00
2018-11-18 20:08:42 +01:00
if ( ! env_home & & ! env_xdg_config_home )
2017-05-07 01:39:01 +02:00
{
2018-11-18 20:08:42 +01:00
return std : : string ( " .snes9x " ) ;
2017-05-07 01:39:01 +02:00
}
2018-11-18 20:08:42 +01:00
std : : string config ;
std : : string legacy ;
2010-09-25 17:46:12 +02:00
2018-11-18 20:08:42 +01:00
// If XDG_CONFIG_HOME is set, use that, otherwise guess default
if ( ! env_xdg_config_home )
2010-09-25 17:46:12 +02:00
{
2018-11-18 20:08:42 +01:00
( config + = env_home ) + = " /.config/snes9x " ;
( legacy + = env_home ) + = " /.snes9x " ;
2010-09-25 17:46:12 +02:00
}
else
2018-11-18 20:08:42 +01:00
config = std : : string ( env_xdg_config_home ) + " /snes9x " ;
2010-09-25 17:46:12 +02:00
2018-12-04 00:27:44 +01:00
if ( directory_exists ( legacy ) & & ! directory_exists ( config ) )
2018-11-18 20:08:42 +01:00
return legacy ;
return config ;
2010-09-25 17:46:12 +02:00
}
2018-11-18 20:08:42 +01:00
std : : string get_config_file_name ( )
2010-09-25 17:46:12 +02:00
{
2018-11-18 20:08:42 +01:00
return get_config_dir ( ) + " /snes9x.conf " ;
2010-09-25 17:46:12 +02:00
}
2018-11-02 02:44:06 +01:00
void S9xParsePortConfig ( ConfigFile & conf , int pass )
2010-09-25 17:46:12 +02:00
{
}
2018-11-02 02:44:06 +01:00
Snes9xConfig : : Snes9xConfig ( )
2010-09-25 17:46:12 +02:00
{
joystick = NULL ;
2010-10-21 03:55:59 +02:00
joystick_threshold = 40 ;
2010-09-25 17:46:12 +02:00
}
2018-11-02 02:44:06 +01:00
int Snes9xConfig : : load_defaults ( )
2010-09-25 17:46:12 +02:00
{
2018-12-28 23:32:32 +01:00
full_screen_on_open = false ;
change_display_resolution = false ;
2010-09-25 17:46:12 +02:00
xrr_index = 0 ;
2018-12-28 23:32:32 +01:00
scale_to_fit = true ;
maintain_aspect_ratio = true ;
2018-11-02 02:44:06 +01:00
aspect_ratio = 2 ;
2010-09-25 17:46:12 +02:00
scale_method = 0 ;
2018-12-28 23:32:32 +01:00
overscan = false ;
2010-09-25 17:46:12 +02:00
save_sram_after_secs = 0 ;
2018-12-28 23:32:32 +01:00
rom_loaded = false ;
multithreading = false ;
2019-03-21 22:37:00 +01:00
splash_image = SPLASH_IMAGE_PATTERN ;
2010-09-25 17:46:12 +02:00
hw_accel = 0 ;
2018-12-28 23:32:32 +01:00
allow_opengl = false ;
allow_xv = false ;
allow_xrandr = false ;
force_inverted_byte_order = false ;
2011-01-24 00:07:22 +01:00
hires_effect = HIRES_NORMAL ;
2018-12-28 23:32:32 +01:00
pause_emulation_on_switch = false ;
2010-09-25 17:46:12 +02:00
num_threads = 2 ;
2018-12-28 23:32:32 +01:00
mute_sound = false ;
mute_sound_turbo = false ;
fullscreen = false ;
ui_visible = true ;
statusbar_visible = false ;
2010-09-25 17:46:12 +02:00
default_esc_behavior = 1 ;
2018-12-28 23:32:32 +01:00
prevent_screensaver = false ;
2010-09-25 17:46:12 +02:00
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-12-28 23:32:32 +01:00
auto_input_rate = true ;
2018-12-29 01:36:23 +01:00
last_directory . clear ( ) ;
last_shader_directory . clear ( ) ;
2010-09-25 17:46:12 +02:00
window_width = - 1 ;
window_height = - 1 ;
preferences_width = - 1 ;
preferences_height = - 1 ;
2019-01-31 23:33:17 +01:00
shader_parameters_width = - 1 ;
shader_parameters_height = - 1 ;
2019-02-18 03:55:59 +01:00
current_display_tab = 0 ;
2018-12-29 01:36:23 +01:00
sram_directory . clear ( ) ;
export_directory . clear ( ) ;
savestate_directory . clear ( ) ;
cheat_directory . clear ( ) ;
patch_directory . clear ( ) ;
2018-12-28 23:32:32 +01:00
screensaver_needs_reset = false ;
2010-09-25 17:46:12 +02:00
ntsc_setup = snes_ntsc_composite ;
ntsc_scanline_intensity = 1 ;
scanline_filter_intensity = 0 ;
2018-12-28 23:32:32 +01:00
Settings . BilinearFilter = false ;
netplay_activated = false ;
netplay_server_up = false ;
netplay_is_server = false ;
netplay_sync_reset = true ;
netplay_send_rom = false ;
2010-09-25 17:46:12 +02:00
netplay_default_port = 6096 ;
netplay_max_frame_loss = 10 ;
2018-12-29 01:36:23 +01:00
netplay_last_rom . clear ( ) ;
netplay_last_host . clear ( ) ;
2010-09-25 17:46:12 +02:00
netplay_last_port = 6096 ;
2018-12-28 23:32:32 +01:00
modal_dialogs = true ;
2018-11-06 23:30:50 +01:00
current_save_slot = 0 ;
2018-04-26 18:15:20 +02:00
S9xCheatsEnable ( ) ;
2016-10-09 04:33:34 +02:00
rewind_granularity = 5 ;
rewind_buffer_size = 0 ;
2018-12-28 23:32:32 +01:00
Settings . Rewinding = false ;
2010-09-25 17:46:12 +02:00
# ifdef USE_OPENGL
2018-12-28 23:32:32 +01:00
sync_to_vblank = true ;
use_pbos = true ;
2010-09-25 17:46:12 +02:00
pbo_format = 0 ;
2018-12-28 23:32:32 +01:00
npot_textures = false ;
use_shaders = false ;
2018-12-29 01:36:23 +01:00
shader_filename . clear ( ) ;
2019-03-02 22:25:59 +01:00
use_glfinish = false ;
use_sync_control = false ;
2010-09-25 17:46:12 +02:00
# endif
2019-02-18 22:15:28 +01:00
/* Snes9x Variables */
2018-12-28 23:32:32 +01:00
Settings . MouseMaster = true ;
Settings . SuperScopeMaster = true ;
Settings . JustifierMaster = true ;
Settings . MultiPlayer5Master = true ;
Settings . UpAndDown = false ;
2010-09-25 17:46:12 +02:00
Settings . AutoSaveDelay = 0 ;
2018-11-02 02:44:06 +01:00
Settings . SkipFrames = 0 ;
2018-12-28 23:32:32 +01:00
Settings . Transparency = true ;
Settings . DisplayFrameRate = false ;
Settings . SixteenBitSound = true ;
Settings . Stereo = true ;
Settings . ReverseStereo = false ;
2019-02-15 20:06:25 +01:00
Settings . SoundPlaybackRate = 48000 ;
2018-12-28 23:32:32 +01:00
Settings . StopEmulation = true ;
2019-02-27 20:55:19 +01:00
Settings . FrameTimeNTSC = 16639 ;
2010-09-25 17:46:12 +02:00
Settings . FrameTimePAL = 20000 ;
Settings . SupportHiRes = true ;
Settings . FrameTime = Settings . FrameTimeNTSC ;
2018-12-28 23:32:32 +01:00
Settings . BlockInvalidVRAMAccessMaster = true ;
Settings . SoundSync = false ;
Settings . DynamicRateControl = false ;
2017-11-24 20:03:24 +01:00
Settings . DynamicRateLimit = 5 ;
2018-08-06 19:31:07 +02:00
Settings . InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN ;
2010-09-25 17:46:12 +02:00
Settings . HDMATimingHack = 100 ;
2018-05-08 00:03:06 +02:00
Settings . SuperFXClockMultiplier = 100 ;
2018-12-28 23:32:32 +01:00
Settings . NetPlay = false ;
NetPlay . Paused = false ;
2018-12-02 02:58:13 +01:00
NetPlay . MaxFrameSkip = 10 ;
2018-12-28 23:32:32 +01:00
Settings . DisplayPressedKeys = false ;
2018-08-12 02:19:04 +02:00
# ifdef ALLOW_CPU_OVERCLOCK
Settings . MaxSpriteTilesPerLine = 34 ;
Settings . OneClockCycle = 6 ;
Settings . OneSlowClockCycle = 8 ;
Settings . TwoClockCycles = 12 ;
# endif
2010-09-25 17:46:12 +02:00
memset ( pad , 0 , sizeof ( JoypadBinding ) * NUM_JOYPADS ) ;
memset ( shortcut , 0 , sizeof ( Binding ) * NUM_EMU_LINKS ) ;
return 0 ;
}
2018-11-02 02:44:06 +01:00
void Snes9xConfig : : joystick_register_centers ( )
2010-09-25 17:46:12 +02:00
{
for ( int i = 0 ; joystick [ i ] ! = NULL ; i + + )
joystick [ i ] - > register_centers ( ) ;
}
2018-11-02 02:44:06 +01:00
void Snes9xConfig : : flush_joysticks ( )
2010-09-25 17:46:12 +02:00
{
int i ;
for ( i = 0 ; joystick [ i ] ! = NULL ; i + + )
joystick [ i ] - > flush ( ) ;
}
2018-11-02 02:44:06 +01:00
void Snes9xConfig : : set_joystick_mode ( int mode )
2010-09-25 17:46:12 +02:00
{
int i ;
for ( i = 0 ; joystick [ i ] ! = NULL ; i + + )
joystick [ i ] - > mode = mode ;
}
2018-11-02 02:44:06 +01:00
static inline void outbool ( ConfigFile & cf , const char * key , bool value , const char * comment = " " )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
cf . SetBool ( key , value , " true " , " false " , comment ) ;
}
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
int Snes9xConfig : : save_config_file ( )
{
char key [ PATH_MAX ] ;
char buffer [ PATH_MAX ] ;
ConfigFile cf ;
# undef z
# define z "Display::"
outbool ( cf , z " FullscreenOnOpen " , full_screen_on_open , " Set the screen resolution after opening a ROM " ) ;
outbool ( cf , z " ChangeDisplayResolution " , change_display_resolution , " Set the resolution in fullscreen mode " ) ;
cf . SetInt ( z " VideoMode " , xrr_index , " Platform-specific video mode number " ) ;
outbool ( cf , z " ScaleToFit " , scale_to_fit , " Scale the image to fit the window size " ) ;
outbool ( cf , z " MaintainAspectRatio " , maintain_aspect_ratio , " Resize the screen to the proportions set by aspect ratio option " ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " AspectRatio " , aspect_ratio , " 0: uncorrected, 1: uncorrected integer scale, 2: 4:3, 3: 4/3 integer scale, 4: NTSC/PAL, 5: NTSC/PAL integer scale " ) ;
2018-11-02 02:44:06 +01:00
cf . SetInt ( z " SoftwareScaleFilter " , scale_method , " Build-specific number of filter used for software scaling " ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " ScanlineFilterIntensity " , scanline_filter_intensity , " 0: 0%, 1: 12.5%, 2: 25%, 3: 50%, 4: 100% " ) ;
2018-11-02 02:44:06 +01:00
outbool ( cf , z " ShowOverscanArea " , overscan ) ;
cf . SetInt ( z " HiresEffect " , hires_effect , " 0: Downscale to low-res, 1: Leave as-is, 2: Upscale low-res screens " ) ;
cf . SetInt ( z " ForceInvertedByteOrder " , force_inverted_byte_order ) ;
2018-11-06 01:40:16 +01:00
outbool ( cf , z " Multithreading " , multithreading , " Apply filters using multiple threads " ) ;
2018-11-02 02:44:06 +01:00
cf . SetInt ( z " NumberOfThreads " , num_threads ) ;
cf . SetInt ( z " HardwareAcceleration " , hw_accel , " 0: None, 1: OpenGL, 2: XVideo " ) ;
2018-11-06 01:40:16 +01:00
outbool ( cf , z " BilinearFilter " , Settings . BilinearFilter , " Smoothes scaled image " ) ;
2019-03-21 22:37:00 +01:00
cf . SetInt ( z " SplashBackground " , splash_image , " 0: Black, 1: Color bars, 2: Pattern, 3: Blue " ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "NTSC::"
cf . SetString ( z " Hue " , std : : to_string ( ntsc_setup . hue ) ) ;
cf . SetString ( z " Saturation " , std : : to_string ( ntsc_setup . saturation ) ) ;
cf . SetString ( z " Contrast " , std : : to_string ( ntsc_setup . contrast ) ) ;
cf . SetString ( z " Brightness " , std : : to_string ( ntsc_setup . brightness ) ) ;
cf . SetString ( z " Sharpness " , std : : to_string ( ntsc_setup . sharpness ) ) ;
cf . SetString ( z " Artifacts " , std : : to_string ( ntsc_setup . artifacts ) ) ;
cf . SetString ( z " Gamma " , std : : to_string ( ntsc_setup . gamma ) ) ;
cf . SetString ( z " Bleed " , std : : to_string ( ntsc_setup . bleed ) ) ;
cf . SetString ( z " Fringing " , std : : to_string ( ntsc_setup . fringing ) ) ;
cf . SetString ( z " Resolution " , std : : to_string ( ntsc_setup . resolution ) ) ;
2018-11-02 03:10:50 +01:00
outbool ( cf , z " MergeFields " , ntsc_setup . merge_fields ) ;
2018-11-02 02:44:06 +01:00
cf . SetInt ( z " ScanlineIntensity " , ntsc_scanline_intensity ) ;
2016-10-09 04:33:34 +02:00
2010-09-25 17:46:12 +02:00
# ifdef USE_OPENGL
2018-11-02 02:44:06 +01:00
# undef z
# define z "OpenGL::"
outbool ( cf , z " VSync " , sync_to_vblank ) ;
2019-03-02 22:25:59 +01:00
outbool ( cf , z " glFinish " , use_glfinish ) ;
outbool ( cf , z " SyncControl " , use_sync_control ) ;
2018-11-02 02:44:06 +01:00
outbool ( cf , z " UsePixelBufferObjects " , use_pbos ) ;
cf . SetInt ( z " PixelBufferObjectBitDepth " , pbo_format ) ;
outbool ( cf , z " UseNonPowerOfTwoTextures " , npot_textures ) ;
outbool ( cf , z " EnableCustomShaders " , use_shaders ) ;
2018-12-10 22:09:26 +01:00
cf . SetString ( z " ShaderFile " , shader_filename ) ;
2010-09-25 17:46:12 +02:00
# endif
2018-11-02 02:44:06 +01:00
# undef z
# define z "Sound::"
outbool ( cf , z " MuteSound " , mute_sound ) ;
outbool ( cf , z " MuteSoundDuringTurbo " , mute_sound_turbo ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " BufferSize " , sound_buffer_size , " Buffer size in milliseconds " ) ;
2018-11-02 02:44:06 +01:00
cf . SetInt ( z " Driver " , sound_driver ) ;
cf . SetInt ( z " InputRate " , sound_input_rate ) ;
outbool ( cf , z " DynamicRateControl " , Settings . DynamicRateControl ) ;
cf . SetInt ( z " DynamicRateControlLimit " , Settings . DynamicRateLimit ) ;
2018-11-06 01:40:16 +01:00
outbool ( cf , z " AutomaticInputRate " , auto_input_rate , " Guess input rate by asking the monitor what its refresh rate is " ) ;
cf . SetInt ( z " PlaybackRate " , gui_config - > sound_playback_rate , " 1: 8000Hz, 2: 11025Hz, 3: 16000Hz, 4: 22050Hz, 5: 32000Hz, 6: 44100Hz, 7: 48000Hz " ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "Files::"
cf . SetString ( z " LastDirectory " , last_directory ) ;
cf . SetString ( z " LastShaderDirectory " , last_shader_directory ) ;
cf . SetString ( z " SRAMDirectory " , sram_directory ) ;
cf . SetString ( z " SaveStateDirectory " , savestate_directory ) ;
cf . SetString ( z " CheatDirectory " , cheat_directory ) ;
cf . SetString ( z " PatchDirectory " , patch_directory ) ;
cf . SetString ( z " ExportDirectory " , export_directory ) ;
# undef z
# define z "Window State::"
cf . SetInt ( z " MainWidth " , window_width ) ;
cf . SetInt ( z " MainHeight " , window_height ) ;
cf . SetInt ( z " PreferencesWidth " , preferences_width ) ;
cf . SetInt ( z " PreferencesHeight " , preferences_height ) ;
2019-01-31 23:33:17 +01:00
cf . SetInt ( z " ShaderParametersWidth " , shader_parameters_width ) ;
cf . SetInt ( z " ShaderParametersHeight " , shader_parameters_height ) ;
2019-02-18 03:55:59 +01:00
cf . SetInt ( z " CurrentDisplayTab " , current_display_tab ) ;
2018-11-02 02:44:06 +01:00
outbool ( cf , z " UIVisible " , ui_visible ) ;
outbool ( cf , z " StatusBarVisible " , statusbar_visible ) ;
if ( default_esc_behavior ! = ESC_TOGGLE_MENUBAR )
outbool ( cf , z " Fullscreen " , 0 ) ;
else
outbool ( cf , z " Fullscreen " , fullscreen ) ;
# undef z
# define z "Netplay::"
outbool ( cf , z " ActAsServer " , netplay_is_server ) ;
outbool ( cf , z " UseResetToSync " , netplay_sync_reset ) ;
outbool ( cf , z " SendROM " , netplay_send_rom ) ;
cf . SetInt ( z " DefaultPort " , netplay_default_port ) ;
cf . SetInt ( z " MaxFrameLoss " , netplay_max_frame_loss ) ;
cf . SetInt ( z " LastUsedPort " , netplay_last_port ) ;
cf . SetString ( z " LastUsedROM " , netplay_last_rom ) ;
cf . SetString ( z " LastUsedHost " , netplay_last_host ) ;
# undef z
# define z "Behavior::"
outbool ( cf , z " PauseEmulationWhenFocusLost " , pause_emulation_on_switch ) ;
cf . SetInt ( z " DefaultESCKeyBehavior " , default_esc_behavior ) ;
outbool ( cf , z " PreventScreensaver " , prevent_screensaver ) ;
outbool ( cf , z " UseModalDialogs " , modal_dialogs ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " RewindBufferSize " , rewind_buffer_size , " Amount of memory (in MB) to use for rewinding " ) ;
cf . SetInt ( z " RewindGranularity " , rewind_granularity , " Only save rewind snapshots every N frames " ) ;
2018-11-06 23:30:50 +01:00
cf . SetInt ( z " CurrentSaveSlot " , current_save_slot ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "Emulation::"
outbool ( cf , z " EmulateTransparency " , Settings . Transparency ) ;
outbool ( cf , z " DisplayFrameRate " , Settings . DisplayFrameRate ) ;
2018-12-12 23:24:21 +01:00
outbool ( cf , z " DisplayPressedKeys " , Settings . DisplayPressedKeys ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " SpeedControlMethod " , Settings . SkipFrames , " 0: Time the frames to 50 or 60Hz, 1: Same, but skip frames if too slow, 2: Synchronize to the sound buffer, 3: Unlimited, except potentially by vsync " ) ;
2018-11-02 02:44:06 +01:00
cf . SetInt ( z " SaveSRAMEveryNSeconds " , Settings . AutoSaveDelay ) ;
outbool ( cf , z " BlockInvalidVRAMAccess " , Settings . BlockInvalidVRAMAccessMaster ) ;
2018-11-06 01:40:16 +01:00
outbool ( cf , z " AllowDPadContradictions " , Settings . UpAndDown , " Allow the D-Pad to press both up + down at the same time, or left + right " ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "Hacks::"
cf . SetInt ( z " SuperFXClockMultiplier " , Settings . SuperFXClockMultiplier ) ;
2018-11-06 01:40:16 +01:00
cf . SetInt ( z " SoundInterpolationMethod " , Settings . InterpolationMethod , " 0: None, 1: Linear, 2: Gaussian (what the hardware uses), 3: Cubic, 4: Sinc " ) ;
2018-11-02 02:44:06 +01:00
outbool ( cf , z " RemoveSpriteLimit " , Settings . MaxSpriteTilesPerLine = = 34 ? 0 : 1 ) ;
outbool ( cf , z " OverclockCPU " , Settings . OneClockCycle = = 6 ? 0 : 1 ) ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
# undef z
# define z "Input::"
2018-11-08 21:59:24 +01:00
controllers controller = CTL_NONE ;
int8 id [ 4 ] ;
for ( int i = 0 ; i < 2 ; i + + )
{
const char * output_string ;
snprintf ( buffer , PATH_MAX , z " ControllerPort%d " , i ) ;
S9xGetController ( i , & controller , & id [ 0 ] , & id [ 1 ] , & id [ 2 ] , & id [ 3 ] ) ;
switch ( controller )
{
case CTL_JOYPAD :
output_string = " joypad " ;
break ;
case CTL_MOUSE :
output_string = " mouse " ;
break ;
case CTL_SUPERSCOPE :
output_string = " superscope " ;
break ;
case CTL_MP5 :
output_string = " multitap " ;
break ;
case CTL_JUSTIFIER :
output_string = " justifier " ;
break ;
default :
output_string = " none " ;
}
cf . SetString ( buffer , output_string ) ;
}
2018-11-02 03:10:50 +01:00
cf . SetInt ( z " JoystickThreshold " , joystick_threshold ) ;
2018-12-02 02:58:13 +01:00
2018-11-02 02:44:06 +01:00
# undef z
2010-09-25 17:46:12 +02:00
for ( int i = 0 ; i < NUM_JOYPADS ; i + + )
{
Binding * joypad = ( Binding * ) & pad [ i ] ;
for ( int j = 0 ; j < NUM_JOYPAD_LINKS ; j + + )
{
2018-11-02 02:44:06 +01:00
snprintf ( key , PATH_MAX , " Joypad %d::%s " , i , b_links [ j ] . snes9x_name ) ;
2018-11-14 21:51:39 +01:00
joypad [ j ] . to_string ( buffer , false ) ;
2018-11-02 02:44:06 +01:00
cf . SetString ( key , std : : string ( buffer ) ) ;
2010-09-25 17:46:12 +02:00
}
}
for ( int i = NUM_JOYPAD_LINKS ; b_links [ i ] . snes9x_name ; i + + )
{
2018-11-02 02:44:06 +01:00
snprintf ( key , PATH_MAX , " Shortcuts::%s " , b_links [ i ] . snes9x_name ) ;
2018-11-14 21:51:39 +01:00
shortcut [ i - NUM_JOYPAD_LINKS ] . to_string ( buffer , false ) ;
2018-11-02 02:44:06 +01:00
cf . SetString ( key , std : : string ( buffer ) ) ;
2010-09-25 17:46:12 +02:00
}
2018-11-02 03:10:50 +01:00
cf . SetNiceAlignment ( true ) ;
cf . SetShowComments ( true ) ;
2018-11-18 20:08:42 +01:00
cf . SaveTo ( get_config_file_name ( ) . c_str ( ) ) ;
2010-09-25 17:46:12 +02:00
return 0 ;
}
2018-11-02 02:44:06 +01:00
int Snes9xConfig : : load_config_file ( )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
struct stat file_info ;
2018-11-18 20:08:42 +01:00
std : : string path ;
2018-11-02 02:44:06 +01:00
ConfigFile cf ;
char key [ PATH_MAX ] ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
load_defaults ( ) ;
2010-09-25 17:46:12 +02:00
2018-11-18 20:08:42 +01:00
path = get_config_dir ( ) ;
2010-09-25 17:46:12 +02:00
2018-11-18 20:08:42 +01:00
if ( stat ( path . c_str ( ) , & file_info ) )
2010-09-25 17:46:12 +02:00
{
2018-11-18 20:08:42 +01:00
if ( mkdir ( path . c_str ( ) , 0755 ) )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
fprintf ( stderr ,
_ ( " Couldn't create config directory: %s \n " ) ,
2018-11-18 20:08:42 +01:00
path . c_str ( ) ) ;
2018-11-02 02:44:06 +01:00
return - 1 ;
2010-09-25 17:46:12 +02:00
}
}
else
{
2018-11-18 20:08:42 +01:00
chmod ( path . c_str ( ) , 0755 ) ;
2010-09-25 17:46:12 +02:00
}
2018-11-18 20:08:42 +01:00
path = get_config_file_name ( ) ;
2010-09-25 17:46:12 +02:00
2018-11-18 20:08:42 +01:00
if ( stat ( path . c_str ( ) , & file_info ) )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
save_config_file ( ) ;
2010-09-25 17:46:12 +02:00
}
2018-11-18 20:08:42 +01:00
if ( ! cf . LoadFile ( path . c_str ( ) ) )
2018-11-02 02:44:06 +01:00
return - 1 ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
std : : string none ;
2018-12-02 01:54:25 +01:00
# define inbool(key, var) { if (cf.Exists (key)) var = cf.GetBool (key); }
# define inint(key, var) { if (cf.Exists(key)) var = cf.GetInt (key); }
# define infloat(key, var) { if (cf.Exists(key)) var = atof (cf.GetString (key, none).c_str()); }
2018-12-29 01:36:23 +01:00
# define instr(key, var) var = cf.GetString (key, none);
2018-11-02 02:44:06 +01:00
# undef z
# define z "Display::"
inbool ( z " FullscreenOnOpen " , full_screen_on_open ) ;
inbool ( z " ChangeDisplayResolution " , change_display_resolution ) ;
inint ( z " VideoMode " , xrr_index ) ;
inbool ( z " ScaleToFit " , scale_to_fit ) ;
inbool ( z " MaintainAspectRatio " , maintain_aspect_ratio ) ;
inint ( z " AspectRatio " , aspect_ratio ) ;
inint ( z " SoftwareScaleFilter " , scale_method ) ;
inint ( z " ScanlineFilterIntensity " , scanline_filter_intensity ) ;
inbool ( z " ShowOverscanArea " , overscan ) ;
inint ( z " HiresEffect " , hires_effect ) ;
inint ( z " ForceInvertedByteOrder " , force_inverted_byte_order ) ;
inbool ( z " Multithreading " , multithreading ) ;
inint ( z " NumberOfThreads " , num_threads ) ;
inint ( z " HardwareAcceleration " , hw_accel ) ;
inbool ( z " BilinearFilter " , Settings . BilinearFilter ) ;
2019-03-21 22:37:00 +01:00
inint ( z " SplashBackground " , splash_image ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "NTSC::"
infloat ( z " Hue " , ntsc_setup . hue ) ;
infloat ( z " Saturation " , ntsc_setup . saturation ) ;
infloat ( z " Contrast " , ntsc_setup . contrast ) ;
infloat ( z " Brightness " , ntsc_setup . brightness ) ;
infloat ( z " Sharpness " , ntsc_setup . sharpness ) ;
infloat ( z " Artifacts " , ntsc_setup . artifacts ) ;
infloat ( z " Gamma " , ntsc_setup . gamma ) ;
infloat ( z " Bleed " , ntsc_setup . bleed ) ;
infloat ( z " Fringing " , ntsc_setup . fringing ) ;
infloat ( z " Resolution " , ntsc_setup . resolution ) ;
2018-11-02 03:10:50 +01:00
inbool ( z " MergeFields " , ntsc_setup . merge_fields ) ;
2018-11-02 02:44:06 +01:00
inint ( z " ScanlineIntensity " , ntsc_scanline_intensity ) ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
# ifdef USE_OPENGL
# undef z
# define z "OpenGL::"
inbool ( z " VSync " , sync_to_vblank ) ;
2019-03-02 22:25:59 +01:00
inbool ( z " glFinish " , use_glfinish ) ;
inbool ( z " SyncControl " , use_sync_control ) ;
2018-11-02 02:44:06 +01:00
inbool ( z " UsePixelBufferObjects " , use_pbos ) ;
inint ( z " PixelBufferObjectBitDepth " , pbo_format ) ;
inbool ( z " UseNonPowerOfTwoTextures " , npot_textures ) ;
inbool ( z " EnableCustomShaders " , use_shaders ) ;
2018-12-10 22:09:26 +01:00
instr ( z " ShaderFile " , shader_filename ) ;
2010-09-25 17:46:12 +02:00
# endif
2018-11-02 02:44:06 +01:00
# undef z
# define z "Sound::"
inbool ( z " MuteSound " , mute_sound ) ;
inbool ( z " MuteSoundDuringTurbo " , mute_sound_turbo ) ;
inint ( z " BufferSize " , sound_buffer_size ) ;
inint ( z " Driver " , sound_driver ) ;
inint ( z " InputRate " , sound_input_rate ) ;
inbool ( z " DynamicRateControl " , Settings . DynamicRateControl ) ;
inint ( z " DynamicRateControlLimit " , Settings . DynamicRateLimit ) ;
inbool ( z " AutomaticInputRate " , auto_input_rate ) ;
inint ( z " PlaybackRate " , gui_config - > sound_playback_rate ) ;
# undef z
# define z "Files::"
instr ( z " LastDirectory " , last_directory ) ;
instr ( z " LastShaderDirectory " , last_shader_directory ) ;
instr ( z " SRAMDirectory " , sram_directory ) ;
instr ( z " SaveStateDirectory " , savestate_directory ) ;
instr ( z " CheatDirectory " , cheat_directory ) ;
instr ( z " PatchDirectory " , patch_directory ) ;
instr ( z " ExportDirectory " , export_directory ) ;
# undef z
# define z "Window State::"
inint ( z " MainWidth " , window_width ) ;
inint ( z " MainHeight " , window_height ) ;
inint ( z " PreferencesWidth " , preferences_width ) ;
inint ( z " PreferencesHeight " , preferences_height ) ;
2019-01-31 23:33:17 +01:00
inint ( z " ShaderParametersWidth " , shader_parameters_width ) ;
inint ( z " ShaderParametersHeight " , shader_parameters_height ) ;
2019-02-18 03:55:59 +01:00
inint ( z " CurrentDisplayTab " , current_display_tab ) ;
2018-11-02 02:44:06 +01:00
inbool ( z " UIVisible " , ui_visible ) ;
inbool ( z " StatusBarVisible " , statusbar_visible ) ;
inbool ( z " Fullscreen " , fullscreen ) ;
# undef z
# define z "Netplay::"
inbool ( z " ActAsServer " , netplay_is_server ) ;
inbool ( z " UseResetToSync " , netplay_sync_reset ) ;
inbool ( z " SendROM " , netplay_send_rom ) ;
inint ( z " DefaultPort " , netplay_default_port ) ;
inint ( z " MaxFrameLoss " , netplay_max_frame_loss ) ;
inint ( z " LastUsedPort " , netplay_last_port ) ;
instr ( z " LastUsedROM " , netplay_last_rom ) ;
instr ( z " LastUsedHost " , netplay_last_host ) ;
# undef z
# define z "Behavior::"
inbool ( z " PauseEmulationWhenFocusLost " , pause_emulation_on_switch ) ;
inint ( z " DefaultESCKeyBehavior " , default_esc_behavior ) ;
inbool ( z " PreventScreensaver " , prevent_screensaver ) ;
inbool ( z " UseModalDialogs " , modal_dialogs ) ;
2018-11-06 01:40:16 +01:00
inint ( z " RewindBufferSize " , rewind_buffer_size ) ;
inint ( z " RewindGranularity " , rewind_granularity ) ;
2018-11-06 23:30:50 +01:00
inint ( z " CurrentSaveSlot " , current_save_slot ) ;
2018-11-02 02:44:06 +01:00
# undef z
# define z "Emulation::"
inbool ( z " EmulateTransparency " , Settings . Transparency ) ;
inbool ( z " DisplayFrameRate " , Settings . DisplayFrameRate ) ;
2018-12-12 23:24:21 +01:00
inbool ( z " DisplayPressedKeys " , Settings . DisplayPressedKeys ) ;
2018-11-02 02:44:06 +01:00
inint ( z " SpeedControlMethod " , Settings . SkipFrames ) ;
inint ( z " SaveSRAMEveryNSeconds " , Settings . AutoSaveDelay ) ;
inbool ( z " BlockInvalidVRAMAccess " , Settings . BlockInvalidVRAMAccessMaster ) ;
inbool ( z " AllowDPadContradictions " , Settings . UpAndDown ) ;
# undef z
# define z "Hacks::"
inint ( z " SuperFXClockMultiplier " , Settings . SuperFXClockMultiplier ) ;
inint ( z " SoundInterpolationMethod " , Settings . InterpolationMethod ) ;
2018-12-02 02:58:13 +01:00
bool RemoveSpriteLimit = false ;
2018-11-02 02:44:06 +01:00
inbool ( z " RemoveSpriteLimit " , RemoveSpriteLimit ) ;
2018-11-17 19:19:16 +01:00
bool OverclockCPU = false ;
2018-11-02 02:44:06 +01:00
inbool ( z " OverclockCPU " , OverclockCPU ) ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
# undef z
# define z "Input::"
2018-11-08 21:59:24 +01:00
for ( int i = 0 ; i < 2 ; i + + )
{
2018-12-29 01:36:23 +01:00
snprintf ( key , PATH_MAX , z " ControllerPort%d " , i ) ;
std : : string tmp = cf . GetString ( key , " " ) ;
2018-11-08 21:59:24 +01:00
if ( tmp . find ( " joypad " ) ! = std : : string : : npos )
S9xSetController ( i , CTL_JOYPAD , i , 0 , 0 , 0 ) ;
else if ( tmp . find ( " multitap " ) ! = std : : string : : npos )
S9xSetController ( i , CTL_MP5 , i , i + 1 , i + 2 , i + 3 ) ;
else if ( tmp . find ( " superscope " ) ! = std : : string : : npos )
S9xSetController ( i , CTL_SUPERSCOPE , 0 , 0 , 0 , 0 ) ;
else if ( tmp . find ( " mouse " ) ! = std : : string : : npos )
S9xSetController ( i , CTL_MOUSE , i , 0 , 0 , 0 ) ;
2018-12-12 23:46:30 +01:00
else if ( tmp . find ( " none " ) ! = std : : string : : npos )
S9xSetController ( i , CTL_NONE , 0 , 0 , 0 , 0 ) ;
2018-11-08 21:59:24 +01:00
}
2018-11-02 03:10:50 +01:00
inint ( z " JoystickThreshold " , joystick_threshold ) ;
2018-12-02 02:58:13 +01:00
2018-11-08 21:59:24 +01:00
# undef z
2010-09-25 17:46:12 +02:00
2018-12-29 01:36:23 +01:00
std : : string buffer ;
2018-11-02 02:44:06 +01:00
for ( int i = 0 ; i < NUM_JOYPADS ; i + + )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
Binding * joypad = ( Binding * ) & pad [ i ] ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
for ( int j = 0 ; j < NUM_JOYPAD_LINKS ; j + + )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
snprintf ( key , PATH_MAX , " Joypad %d::%s " , i , b_links [ j ] . snes9x_name ) ;
instr ( key , buffer ) ;
2018-12-29 01:36:23 +01:00
joypad [ j ] = Binding ( buffer . c_str ( ) ) ;
2010-09-25 17:46:12 +02:00
}
}
2018-11-02 02:44:06 +01:00
for ( int i = NUM_JOYPAD_LINKS ; b_links [ i ] . snes9x_name ; i + + )
{
snprintf ( key , PATH_MAX , " Shortcuts::%s " , b_links [ i ] . snes9x_name ) ;
instr ( key , buffer ) ;
2018-12-29 01:36:23 +01:00
shortcut [ i - NUM_JOYPAD_LINKS ] = Binding ( buffer . c_str ( ) ) ;
2018-11-02 02:44:06 +01:00
}
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
/* Validation */
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
if ( RemoveSpriteLimit )
Settings . MaxSpriteTilesPerLine = 128 ;
else
Settings . MaxSpriteTilesPerLine = 34 ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
if ( OverclockCPU )
2010-09-25 17:46:12 +02:00
{
2018-11-02 02:44:06 +01:00
Settings . OneClockCycle = 4 ;
Settings . OneSlowClockCycle = 5 ;
Settings . TwoClockCycles = 6 ;
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
else
{
2018-11-02 02:44:06 +01:00
Settings . OneClockCycle = 6 ;
Settings . OneSlowClockCycle = 8 ;
Settings . TwoClockCycles = 12 ;
2010-09-25 17:46:12 +02:00
}
2018-11-02 02:44:06 +01:00
if ( default_esc_behavior ! = ESC_TOGGLE_MENUBAR )
fullscreen = false ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
# ifdef USE_HQ2X
if ( scale_method > = NUM_FILTERS )
scale_method = 0 ;
# else
if ( scale_method > = NUM_FILTERS - 3 )
scale_method = 0 ;
# endif /* USE_HQ2X */
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +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
2018-11-02 02:44:06 +01:00
# ifdef USE_OPENGL
if ( pbo_format ! = 32 )
pbo_format = 16 ;
# endif
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
if ( Settings . SkipFrames = = THROTTLE_SOUND_SYNC )
2018-12-28 23:32:32 +01:00
Settings . SoundSync = true ;
2018-11-02 02:44:06 +01:00
else
2018-12-28 23:32:32 +01:00
Settings . SoundSync = false ;
2010-09-25 17:46:12 +02:00
2018-11-02 02:44:06 +01:00
hires_effect = CLAMP ( hires_effect , 0 , 2 ) ;
Settings . DynamicRateLimit = CLAMP ( Settings . DynamicRateLimit , 1 , 1000 ) ;
Settings . SuperFXClockMultiplier = CLAMP ( Settings . SuperFXClockMultiplier , 50 , 400 ) ;
2018-12-02 02:58:13 +01:00
ntsc_scanline_intensity = MIN ( ntsc_scanline_intensity , 4 ) ;
scanline_filter_intensity = MIN ( scanline_filter_intensity , 3 ) ;
2010-10-22 04:18:56 +02:00
2010-09-25 17:46:12 +02:00
return 0 ;
}
2019-03-21 23:54:27 +01:00
void Snes9xConfig : : rebind_keys ( )
2010-09-25 17:46:12 +02:00
{
s9xcommand_t cmd ;
2019-03-21 23:54:27 +01:00
std : : string string ;
2010-09-25 17:46:12 +02:00
2019-03-21 23:54:27 +01:00
S9xUnmapAllControls ( ) ;
2010-09-25 17:46:12 +02:00
2019-03-21 23:54:27 +01:00
for ( int joypad_i = 0 ; joypad_i < NUM_JOYPADS ; joypad_i + + )
2010-09-25 17:46:12 +02:00
{
2019-03-21 23:54:27 +01:00
Binding * bin = ( Binding * ) & pad [ joypad_i ] ;
2010-09-25 17:46:12 +02:00
for ( int button_i = 0 ; button_i < NUM_JOYPAD_LINKS ; button_i + + )
{
2019-03-21 23:54:27 +01:00
int dupe ;
for ( dupe = button_i + 1 ; dupe < NUM_JOYPAD_LINKS ; dupe + + )
{
if ( bin [ button_i ] . matches ( bin [ dupe ] ) & & bin [ button_i ] . hex ( ) ! = 0 )
{
printf ( " %d: %d matches %d \n " , joypad_i , button_i , dupe ) ;
break ;
}
}
if ( dupe < NUM_JOYPAD_LINKS | | bin [ button_i ] . hex ( ) = = 0 )
continue ;
string + = " Joypad " + std : : to_string ( ( joypad_i % 5 ) + 1 ) + " " ;
string + = b_links [ button_i ] . snes9x_name ;
bool ismulti = false ;
for ( dupe = button_i - 1 ; dupe > 0 ; dupe - - )
{
if ( bin [ button_i ] . matches ( bin [ dupe ] ) )
{
ismulti = true ;
string + = " ,Joypad " + std : : to_string ( ( joypad_i % 5 ) + 1 ) + " " ;
string + = b_links [ dupe ] . snes9x_name ;
}
}
if ( ismulti )
string = std : : string ( " { " ) + string + " } " ;
cmd = S9xGetPortCommandT ( string . c_str ( ) ) ;
S9xMapButton ( bin [ button_i ] . base_hex ( ) , cmd , false ) ;
2010-09-25 17:46:12 +02:00
}
}
for ( int i = NUM_JOYPAD_LINKS ; b_links [ i ] . snes9x_name ; i + + )
{
2019-03-21 23:54:27 +01:00
cmd = S9xGetPortCommandT ( b_links [ i ] . snes9x_name ) ;
S9xMapButton ( shortcut [ i - NUM_JOYPAD_LINKS ] . base_hex ( ) ,
cmd ,
false ) ;
2010-09-25 17:46:12 +02:00
}
2019-03-21 23:54:27 +01:00
cmd = S9xGetPortCommandT ( " Pointer Mouse1+Superscope+Justifier1 " ) ;
S9xMapPointer ( BINDING_MOUSE_POINTER , cmd , true ) ;
2010-09-25 17:46:12 +02:00
2019-03-21 23:54:27 +01:00
cmd = S9xGetPortCommandT ( " {Mouse1 L,Superscope Fire,Justifier1 Trigger} " ) ;
S9xMapButton ( BINDING_MOUSE_BUTTON0 , cmd , false ) ;
2010-09-25 17:46:12 +02:00
2019-03-21 23:54:27 +01:00
cmd = S9xGetPortCommandT ( " {Justifier1 AimOffscreen Trigger,Superscope AimOffscreen} " ) ;
S9xMapButton ( BINDING_MOUSE_BUTTON1 , cmd , false ) ;
2010-09-25 17:46:12 +02:00
2019-03-21 23:54:27 +01:00
cmd = S9xGetPortCommandT ( " {Mouse1 R,Superscope Cursor,Justifier1 Start} " ) ;
S9xMapButton ( BINDING_MOUSE_BUTTON2 , cmd , false ) ;
2010-09-25 17:46:12 +02:00
}