2018-11-16 00:31:39 +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
// all windows-specific command line and config file parsing/saving/loading
// this stuff was moved out of wsnes.cpp, to keep things a little tidier
// note:
// if you want to force all users of a new version to have a
// particular setting reset to its given default,
// change the name string of that setting (in WinRegisterConfigItems)
// to something a little different...
// but if it's not in a windows-specific category, make sure you change its name elsewhere too
# include "../port.h"
# include "../snes9x.h"
# include "wsnes9x.h"
# include "wlanguage.h"
# include "../display.h"
# include "../conffile.h"
# include "../spc7110.h"
# include "../gfx.h"
# include "../snapshot.h"
# ifdef NETPLAY_SUPPORT
# include "../netplay.h"
extern SNPServer NPServer ;
# endif
# include <assert.h>
static void WinDeleteRegistryEntries ( ) ;
void WinSetDefaultValues ( ) ;
void WinDeleteRecentGamesList ( ) ;
HANDLE configMutex = NULL ;
2018-01-03 22:28:21 +01:00
extern TCHAR multiRomA [ MAX_PATH ] ; // lazy, should put in sGUI and add init to {0} somewhere
extern TCHAR multiRomB [ MAX_PATH ] ;
2010-09-25 17:46:12 +02:00
void S9xParseArg ( char * * argv , int & i , int argc )
{
if ( strcasecmp ( argv [ i ] , " -restore " ) = = 0 )
{
WinDeleteRegistryEntries ( ) ;
WinSetDefaultValues ( ) ;
}
else if ( strcasecmp ( argv [ i ] , " -hidemenu " ) = = 0 )
{
GUI . HideMenu = true ;
}
else if ( strcasecmp ( argv [ i ] , " -fullscreen " ) = = 0 )
{
GUI . FullScreen = true ;
}
2018-01-03 22:28:21 +01:00
else if ( ! strcasecmp ( argv [ i ] , " -cartb " ) )
{
Settings . Multi = TRUE ; // only used to signal winmain
if ( i + 1 < argc )
{
lstrcpyn ( multiRomB , _tFromChar ( argv [ + + i ] ) , MAX_PATH ) ;
}
}
2010-09-25 17:46:12 +02:00
}
void WinSetDefaultValues ( )
{
// TODO: delete the parts that are already covered by the default values in WinRegisterConfigItems
char temp [ 4 ] ;
strcpy ( temp , " C: \\ " ) ;
GUI . ControllerOption = SNES_JOYPAD ;
GUI . ValidControllerOptions = 0xFFFF ;
GUI . IgnoreNextMouseMove = false ;
GUI . DoubleBuffered = false ;
GUI . FullScreen = false ;
GUI . Stretch = false ;
GUI . FlipCounter = 0 ;
GUI . NumFlipFrames = 1 ;
2018-05-20 18:01:03 +02:00
Settings . BilinearFilter = false ;
2010-09-25 17:46:12 +02:00
GUI . LockDirectories = false ;
GUI . window_maximized = false ;
2010-10-17 02:47:53 +02:00
GUI . EmulatedFullscreen = false ;
2010-09-25 17:46:12 +02:00
WinDeleteRecentGamesList ( ) ;
GUI . SoundChannelEnable = 255 ;
// Tracing options
Settings . TraceDMA = false ;
Settings . TraceHDMA = false ;
Settings . TraceVRAM = false ;
Settings . TraceUnknownRegisters = false ;
Settings . TraceDSP = false ;
// ROM timing options (see also H_Max above)
Settings . PAL = false ;
Settings . FrameTimePAL = 20000 ;
Settings . FrameTimeNTSC = 16667 ;
Settings . FrameTime = 16667 ;
// CPU options
Settings . Paused = false ;
# ifdef NETPLAY_SUPPORT
Settings . Port = 1996 ;
NetPlay . MaxFrameSkip = 10 ;
NetPlay . MaxBehindFrameCount = 10 ;
NPServer . SyncByReset = true ;
NPServer . SendROMImageOnConnect = false ;
# endif
Settings . TakeScreenshot = false ;
GUI . Language = 0 ;
2019-02-12 17:56:01 +01:00
GUI . AllowSoundSync = true ;
2019-12-30 17:03:06 +01:00
GUI . CurrentSaveBank = 0 ;
2010-09-25 17:46:12 +02:00
}
static bool try_save ( const char * fname , ConfigFile & conf ) {
STREAM fp ;
if ( ( fp = OPEN_STREAM ( fname , " w " ) ) ! = NULL ) {
fprintf ( stdout , " Saving config file %s \n " , fname ) ;
CLOSE_STREAM ( fp ) ;
conf . SaveTo ( fname ) ;
return true ;
}
return false ;
}
static bool S9xSaveConfigFile ( ConfigFile & conf ) {
2010-09-25 19:35:19 +02:00
configMutex = CreateMutex ( NULL , FALSE , TEXT ( " Snes9xConfigMutex " ) ) ;
2010-09-25 17:46:12 +02:00
int times = 0 ;
DWORD waitVal = WAIT_TIMEOUT ;
while ( waitVal = = WAIT_TIMEOUT & & + + times < = 150 ) // wait at most 15 seconds
waitVal = WaitForSingleObject ( configMutex , 100 ) ;
// save over the .conf file if it already exists, otherwise save over the .cfg file
std : : string fname ;
fname = S9xGetDirectory ( DEFAULT_DIR ) ;
fname + = SLASH_STR S9X_CONF_FILE_NAME ;
// ensure previous config file is not lost if we crash while writing the new one
std : : string ftemp ;
{
2010-09-25 19:35:19 +02:00
CopyFileA ( fname . c_str ( ) , ( fname + " .autobak " ) . c_str ( ) , FALSE ) ;
2010-09-25 17:46:12 +02:00
ftemp = S9xGetDirectory ( DEFAULT_DIR ) ;
ftemp + = SLASH_STR " config_error " ;
FILE * tempfile = fopen ( ftemp . c_str ( ) , " wb " ) ;
if ( tempfile ) fclose ( tempfile ) ;
}
bool ret = try_save ( fname . c_str ( ) , conf ) ;
remove ( ftemp . c_str ( ) ) ;
remove ( ( fname + " .autobak " ) . c_str ( ) ) ;
ReleaseMutex ( configMutex ) ;
CloseHandle ( configMutex ) ;
return ret ;
}
static void WinDeleteRegistryEntries ( )
{
// WinDeleteRegKey (HKEY_CURRENT_USER, S9X_REG_KEY_BASE);
}
static inline char * SkipSpaces ( char * p )
{
while ( * p & & isspace ( * p ) )
p + + ;
return ( p ) ;
}
2014-03-22 15:07:15 +01:00
const TCHAR * WinParseCommandLineAndLoadConfigFile ( TCHAR * line )
2010-09-25 17:46:12 +02:00
{
// Break the command line up into an array of string pointers, each pointer
// points at a separate word or character sequence enclosed in quotes.
2014-03-22 15:07:15 +01:00
int count = 0 ;
static TCHAR return_filename [ MAX_PATH ] ;
# ifdef UNICODE
// split params into argv
TCHAR * * params = CommandLineToArgvW ( line , & count ) ;
// convert all parameters to utf8
char * * parameters = new char * [ count ] ;
for ( int i = 0 ; i < count ; i + + ) {
int requiredChars = WideCharToMultiByte ( CP_UTF8 , 0 , params [ i ] , - 1 , NULL , 0 , NULL , NULL ) ;
parameters [ i ] = new char [ requiredChars ] ;
WideCharToMultiByte ( CP_UTF8 , 0 , params [ i ] , - 1 , parameters [ i ] , requiredChars , NULL , NULL ) ;
}
LocalFree ( params ) ;
# else
2010-09-25 17:46:12 +02:00
# define MAX_PARAMETERS 100
char * p = line ;
2014-03-22 15:07:15 +01:00
char * parameters [ MAX_PARAMETERS ] ;
2010-09-25 17:46:12 +02:00
while ( count < MAX_PARAMETERS & & * p )
{
p = SkipSpaces ( p ) ;
if ( * p = = ' " ' )
{
p + + ;
parameters [ count + + ] = p ;
while ( * p & & * p ! = ' " ' )
p + + ;
* p + + = 0 ;
}
else
if ( * p = = ' \' ' )
{
p + + ;
parameters [ count + + ] = p ;
while ( * p & & * p ! = ' \' ' )
p + + ;
* p + + = 0 ;
}
else
{
parameters [ count + + ] = p ;
while ( * p & & ! isspace ( * p ) )
p + + ;
if ( ! * p )
break ;
* p + + = 0 ;
}
}
2014-03-22 15:07:15 +01:00
# endif
2010-09-25 19:35:19 +02:00
configMutex = CreateMutex ( NULL , FALSE , TEXT ( " Snes9xConfigMutex " ) ) ;
2010-09-25 17:46:12 +02:00
int times = 0 ;
DWORD waitVal = WAIT_TIMEOUT ;
while ( waitVal = = WAIT_TIMEOUT & & + + times < = 150 ) // wait at most 15 seconds
waitVal = WaitForSingleObject ( configMutex , 100 ) ;
// ensure previous config file is not lost if we crashed while writing a new one
{
std : : string ftemp ;
ftemp = S9xGetDirectory ( DEFAULT_DIR ) ;
ftemp + = SLASH_STR " config_error " ;
FILE * tempfile = fopen ( ftemp . c_str ( ) , " rb " ) ;
if ( tempfile )
{
fclose ( tempfile ) ;
std : : string fname ;
for ( int i = 0 ; i < 2 ; i + + )
{
fname = S9xGetDirectory ( DEFAULT_DIR ) ;
if ( i = = 0 ) fname + = SLASH_STR " snes9x.conf " ;
else if ( i = = 1 ) fname + = SLASH_STR " snes9x.cfg " ;
tempfile = fopen ( ( fname + " .autobak " ) . c_str ( ) , " rb " ) ;
if ( tempfile )
{
fclose ( tempfile ) ;
2010-09-25 19:35:19 +02:00
MoveFileExA ( ( fname + " .autobak " ) . c_str ( ) , fname . c_str ( ) , MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH ) ;
2010-09-25 17:46:12 +02:00
}
}
remove ( ftemp . c_str ( ) ) ;
}
}
S9xLoadConfigFiles ( parameters , count ) ;
ReleaseMutex ( configMutex ) ;
CloseHandle ( configMutex ) ;
2019-12-26 14:57:54 +01:00
// check some additional common help switches
for ( int i = 0 ; i < count ; i + + )
{
if ( ! strcasecmp ( parameters [ i ] , " /? " ) | | ! strcasecmp ( parameters [ i ] , " -h " ) )
S9xUsage ( ) ;
}
2010-09-25 17:46:12 +02:00
const char * rf = S9xParseArgs ( parameters , count ) ;
2014-03-22 15:07:15 +01:00
if ( rf ) // save rom_filename as TCHAR if available
lstrcpy ( return_filename , _tFromChar ( rf ) ) ;
# ifdef UNICODE
// free parameters
for ( int i = 0 ; i < count ; i + + ) {
delete [ ] parameters [ i ] ;
}
delete [ ] parameters ;
# endif
return rf ? return_filename : NULL ;
2010-09-25 17:46:12 +02:00
}
# define S(x) GAMEDEVICE_VK_##x
# define SO(x) GAMEDEVICE_VK_OEM_##x
static const char * keyToString [ 256 ] =
{
" Unassigned " , " LMB " , " RMB " , " Break " , " MMB " , " XMB1 " , " XMB2 " , " 0x07 " ,
S ( BACK ) , S ( TAB ) , " 0x0A " , " 0x0B " , S ( CLEAR ) , S ( RETURN ) , " 0x0E " , " 0x0F " ,
S ( SHIFT ) , S ( CONTROL ) , S ( MENU ) , S ( PAUSE ) , S ( CAPITAL ) , " Kana " , " 0x16 " , " Junja " ,
" Final " , " Kanji " , " 0x1A " , S ( ESCAPE ) , " Convert " , " NonConvert " , " Accept " , " ModeChange " ,
S ( SPACE ) , S ( PRIOR ) , S ( NEXT ) , S ( END ) , S ( HOME ) , S ( LEFT ) , S ( UP ) , S ( RIGHT ) ,
S ( DOWN ) , S ( SELECT ) , S ( PRINT ) , S ( EXECUTE ) , S ( SNAPSHOT ) , S ( INSERT ) , S ( DELETE ) , S ( HELP ) ,
" 0 " , " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " ,
" 8 " , " 9 " , " 0x3A " , " 0x3B " , " 0x3C " , " 0x3D " , " 0x3E " , " 0x3F " ,
" 0x40 " , " A " , " B " , " C " , " D " , " E " , " F " , " G " ,
" H " , " I " , " J " , " K " , " L " , " M " , " N " , " O " ,
" P " , " Q " , " R " , " S " , " T " , " U " , " V " , " W " ,
" X " , " Y " , " Z " , S ( LWIN ) , S ( RWIN ) , S ( APPS ) , " 0x5E " , " Sleep " ,
" Pad0 " , " Pad1 " , " Pad2 " , " Pad3 " , " Pad4 " , " Pad5 " , " Pad6 " , " Pad7 " ,
" Pad8 " , " Pad9 " , S ( MULTIPLY ) , S ( ADD ) , S ( SEPARATOR ) , S ( SUBTRACT ) , S ( DECIMAL ) , S ( DIVIDE ) ,
S ( F1 ) , S ( F2 ) , S ( F3 ) , S ( F4 ) , S ( F5 ) , S ( F6 ) , S ( F7 ) , S ( F8 ) ,
S ( F9 ) , S ( F10 ) , S ( F11 ) , S ( F12 ) , " F13 " , " F14 " , " F15 " , " F16 " ,
" F17 " , " F18 " , " F19 " , " F20 " , " F21 " , " F22 " , " F23 " , " F24 " ,
" 0x88 " , " 0x89 " , " 0x8A " , " 0x8B " , " 0x8C " , " 0x8D " , " 0x8E " , " 0x8F " ,
S ( NUMLOCK ) , S ( SCROLL ) , " PadEqual " , " Masshou " , " Touroku " , " Loya " , " Roya " , " 0x97 " ,
" 0x98 " , " 0x99 " , " 0x9A " , " 0x9B " , " 0x9C " , " 0x9D " , " 0x9E " , " 0x9F " ,
S ( LSHIFT ) , S ( RSHIFT ) , S ( LCONTROL ) , S ( RCONTROL ) , S ( LMENU ) , S ( RMENU ) , " BrowserBack " , " BrowserForward " ,
" BrowserRefresh " , " BrowserStop " , " BrowserSearch " , " BrowserFavorites " , " BrowserHome " , " VolumeMute " , " VolumeDown " , " VolumeUp " ,
" MediaNextTrack " , " MediaPrevTrack " , " MediaStop " , " MediaPlayPause " , " LaunchMail " , " MediaSelect " , " LaunchApp1 " , " LaunchApp2 " ,
" 0xB8 " , " 0xB9 " , " ; " , " + " , " , " , SO ( MINUS ) , " . " , SO ( 2 ) ,
SO ( 3 ) , " 0xC1 " , " 0xC2 " , " 0xC3 " , " 0xC4 " , " 0xC5 " , " 0xC6 " , " 0xC7 " ,
" 0xC8 " , " 0xC9 " , " 0xCA " , " 0xCB " , " 0xCC " , " 0xCD " , " 0xCE " , " 0xCF " ,
" 0xD0 " , " 0xD1 " , " 0xD2 " , " 0xD3 " , " 0xD4 " , " 0xD5 " , " 0xD6 " , " 0xD7 " ,
" 0xD8 " , " 0xD9 " , " 0xDA " , SO ( 4 ) , " Backslash " , SO ( 6 ) , " ' " , " OEM8 " ,
" 0xE0 " , " AX " , " <> " , " ICOHelp " , " ICO00 " , " Process " , " ICOClear " , " Packet " ,
" 0xE8 " , " Reset " , " Jump " , " PA1_2 " , " PA2 " , " PA3 " , " WSCTRL " , " CUSEL " ,
" Attention2 " , " Finish " , " Copy " , " Auto " , " ENLW " , " Backtab " , " Attention " , " CRSEL " ,
" EXSEL " , " EREOF " , " Play " , " Zoom " , " NoName " , " PA1 " , " Clear2 " , " 0xFF "
} ;
static const char * keyToAlternateString [ 256 ] =
{
" none " , " LeftClick " , " RightClick " , " Cancel " , " MiddleClick " , " " , " " , " " , " Back " , " " , " " , " " , " " , " Return " , " " , " " ,
" " , " " , " Menu " , " " , " " , " " , " " , " " , " " , " " , " " , " Escape " , " " , " " , " " , " " ,
" " , " PageUp " , " PageDown " , " " , " " , " " , " " , " " , " " , " " , " PrintScreen " , " " , " " , " Ins " , " Del " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" NumLock " , " ScrollLock " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , SO ( 1 ) , SO ( PLUS ) , SO ( COMMA ) , " Minus " , SO ( PERIOD ) , " ? " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " ,
" " , " " , " " , " oem_pa1 " , " " , " " , " " , " " , " " , " " , " " , " LBracket " , " | " , " RBracket " , SO ( 7 ) , " " ,
" ATTN2 " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " ATTN " , " " ,
" " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " " , " "
} ;
# undef S
# undef SO
// We will maintain our own list of items to put in the config file,
// so that each config item has only one point of change across both saving and loading
// and to allow us to manage custom types of config items, such as virtual key codes represented as strings
enum ConfigItemType {
CIT_BOOL , CIT_INT , CIT_UINT , CIT_STRING , CIT_INVBOOL , CIT_BOOLONOFF , CIT_INVBOOLONOFF , CIT_VKEY , CIT_VKEYMOD
} ;
struct ConfigItem
{
const char * name ;
void * addr ;
int size ;
void * def ;
const char * comment ;
ConfigItemType type ;
ConfigItem ( const char * nname , void * naddr , int nsize , void * ndef , const char * ncomment , ConfigItemType ntype ) {
addr = naddr ; name = nname ; size = nsize ; def = ndef ; comment = ncomment ; type = ntype ;
}
void Get ( ConfigFile & conf ) {
switch ( type )
{
case CIT_BOOL :
case CIT_BOOLONOFF :
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) conf . GetBool ( name , def ! = 0 ) ;
break ;
case CIT_INT :
2019-02-11 17:32:26 +01:00
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) conf . GetInt ( name , PtrToInt ( def ) ) ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) conf . GetInt ( name , PtrToInt ( def ) ) ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) conf . GetInt ( name , PtrToInt ( def ) ) ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) conf . GetInt ( name , PtrToInt ( def ) ) ;
2010-09-25 17:46:12 +02:00
break ;
case CIT_UINT :
2019-02-11 17:32:26 +01:00
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) conf . GetUInt ( name , PtrToUint ( def ) ) ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) conf . GetUInt ( name , PtrToUint ( def ) ) ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) conf . GetUInt ( name , PtrToUint ( def ) ) ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) conf . GetUInt ( name , PtrToUint ( def ) ) ;
2010-09-25 17:46:12 +02:00
break ;
case CIT_STRING :
2010-09-25 19:35:19 +02:00
lstrcpyn ( ( TCHAR * ) addr , _tFromChar ( conf . GetString ( name , reinterpret_cast < const char * > ( def ) ) ) , size - 1 ) ;
( ( TCHAR * ) addr ) [ size - 1 ] = TEXT ( ' \0 ' ) ;
2010-09-25 17:46:12 +02:00
break ;
case CIT_INVBOOL :
case CIT_INVBOOLONOFF :
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) ! conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) ! conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) ! conf . GetBool ( name , def ! = 0 ) ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) ! conf . GetBool ( name , def ! = 0 ) ;
break ;
case CIT_VKEY :
{
2019-02-11 17:32:26 +01:00
uint16 keyNum = ( uint16 ) conf . GetUInt ( name , PtrToUint ( def ) ) ;
2010-09-25 17:46:12 +02:00
const char * keyStr = conf . GetString ( name ) ;
if ( keyStr )
{
for ( int i = 0 ; i < 512 ; i + + )
{
if ( i < 256 ) // keys
{
if ( ! strcasecmp ( keyStr , keyToString [ i ] ) | |
( * keyToAlternateString [ i ] & & ! strcasecmp ( keyStr , keyToAlternateString [ i ] ) ) )
{
keyNum = i ;
break ;
}
}
else // joystick:
{
char temp [ 128 ] ;
extern void TranslateKey ( WORD keyz , char * out ) ;
TranslateKey ( 0x8000 | ( i - 256 ) , temp ) ;
if ( strlen ( keyStr ) > 3 & & ! strcasecmp ( keyStr + 3 , temp + 3 ) )
{
for ( int j = 0 ; j < 16 ; j + + )
{
if ( keyStr [ 2 ] - ' 0 ' = = j | | keyStr [ 2 ] - ' a ' = = j - 10 )
{
keyNum = 0x8000 | ( i - 256 ) | ( j < < 8 ) ;
i = 512 ;
break ;
}
}
}
}
}
}
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) keyNum ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) keyNum ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) keyNum ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) keyNum ;
}
break ;
case CIT_VKEYMOD :
{
uint16 modNum = 0 ;
const char * modStr = conf . GetString ( name ) ;
if ( modStr ) {
if ( strstr ( modStr , " ft " ) | | strstr ( modStr , " FT " ) ) modNum | = CUSTKEY_SHIFT_MASK ;
if ( strstr ( modStr , " tr " ) | | strstr ( modStr , " TR " ) ) modNum | = CUSTKEY_CTRL_MASK ;
if ( strstr ( modStr , " lt " ) | | strstr ( modStr , " LT " ) ) modNum | = CUSTKEY_ALT_MASK ;
}
if ( ! modNum & & ( ! modStr | | strcasecmp ( modStr , " none " ) ) )
2019-02-11 17:32:26 +01:00
modNum = conf . GetUInt ( name , PtrToUint ( def ) ) ;
2010-09-25 17:46:12 +02:00
if ( size = = 1 ) * ( uint8 * ) addr = ( uint8 ) modNum ;
if ( size = = 2 ) * ( uint16 * ) addr = ( uint16 ) modNum ;
if ( size = = 4 ) * ( uint32 * ) addr = ( uint32 ) modNum ;
if ( size = = 8 ) * ( uint64 * ) addr = ( uint64 ) modNum ;
}
break ;
}
// if it had a comment, override our own with it
const char * newComment = conf . GetComment ( name ) ;
if ( newComment & & * newComment )
comment = newComment ;
}
void Set ( ConfigFile & conf ) {
switch ( type )
{
case CIT_BOOL :
if ( size = = 1 ) conf . SetBool ( name , 0 ! = ( * ( uint8 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 2 ) conf . SetBool ( name , 0 ! = ( * ( uint16 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 4 ) conf . SetBool ( name , 0 ! = ( * ( uint32 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 8 ) conf . SetBool ( name , 0 ! = ( * ( uint64 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
break ;
case CIT_BOOLONOFF :
if ( size = = 1 ) conf . SetBool ( name , 0 ! = ( * ( uint8 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 2 ) conf . SetBool ( name , 0 ! = ( * ( uint16 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 4 ) conf . SetBool ( name , 0 ! = ( * ( uint32 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 8 ) conf . SetBool ( name , 0 ! = ( * ( uint64 * ) addr ) , " ON " , " OFF " , comment ) ;
break ;
case CIT_INT :
if ( size = = 1 ) conf . SetInt ( name , ( int32 ) ( * ( uint8 * ) addr ) , comment ) ;
if ( size = = 2 ) conf . SetInt ( name , ( int32 ) ( * ( uint16 * ) addr ) , comment ) ;
if ( size = = 4 ) conf . SetInt ( name , ( int32 ) ( * ( uint32 * ) addr ) , comment ) ;
if ( size = = 8 ) conf . SetInt ( name , ( int32 ) ( * ( uint64 * ) addr ) , comment ) ;
break ;
case CIT_UINT :
if ( size = = 1 ) conf . SetUInt ( name , ( uint32 ) ( * ( uint8 * ) addr ) , 10 , comment ) ;
if ( size = = 2 ) conf . SetUInt ( name , ( uint32 ) ( * ( uint16 * ) addr ) , 10 , comment ) ;
if ( size = = 4 ) conf . SetUInt ( name , ( uint32 ) ( * ( uint32 * ) addr ) , 10 , comment ) ;
if ( size = = 8 ) conf . SetUInt ( name , ( uint32 ) ( * ( uint64 * ) addr ) , 10 , comment ) ;
break ;
case CIT_STRING :
2010-09-25 19:35:19 +02:00
if ( ( TCHAR * ) addr )
conf . SetString ( name , std : : string ( _tToChar ( ( TCHAR * ) addr ) ) , comment ) ;
2010-09-25 17:46:12 +02:00
break ;
case CIT_INVBOOL :
if ( size = = 1 ) conf . SetBool ( name , 0 = = ( * ( uint8 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 2 ) conf . SetBool ( name , 0 = = ( * ( uint16 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 4 ) conf . SetBool ( name , 0 = = ( * ( uint32 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
if ( size = = 8 ) conf . SetBool ( name , 0 = = ( * ( uint64 * ) addr ) , " TRUE " , " FALSE " , comment ) ;
break ;
case CIT_INVBOOLONOFF :
if ( size = = 1 ) conf . SetBool ( name , 0 = = ( * ( uint8 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 2 ) conf . SetBool ( name , 0 = = ( * ( uint16 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 4 ) conf . SetBool ( name , 0 = = ( * ( uint32 * ) addr ) , " ON " , " OFF " , comment ) ;
if ( size = = 8 ) conf . SetBool ( name , 0 = = ( * ( uint64 * ) addr ) , " ON " , " OFF " , comment ) ;
break ;
case CIT_VKEY :
{
uint16 keyNum = 0 ;
if ( size = = 1 ) keyNum = ( uint8 ) ( * ( uint8 * ) addr ) ;
if ( size = = 2 ) keyNum = ( uint16 ) ( * ( uint16 * ) addr ) ;
if ( size = = 4 ) keyNum = ( uint16 ) ( * ( uint32 * ) addr ) ;
if ( size = = 8 ) keyNum = ( uint16 ) ( * ( uint64 * ) addr ) ;
if ( keyNum < 256 ) conf . SetString ( name , keyToString [ keyNum ] , comment ) ;
else if ( keyNum & 0x8000 ) {
char temp [ 128 ] ;
extern void TranslateKey ( WORD keyz , char * out ) ;
TranslateKey ( keyNum , temp ) ;
conf . SetString ( name , temp , comment ) ;
}
else conf . SetUInt ( name , keyNum , 16 , comment ) ;
}
break ;
case CIT_VKEYMOD :
{
uint16 modNum = 0 ;
if ( size = = 1 ) modNum = ( uint8 ) ( * ( uint8 * ) addr ) ;
if ( size = = 2 ) modNum = ( uint16 ) ( * ( uint16 * ) addr ) ;
if ( size = = 4 ) modNum = ( uint16 ) ( * ( uint32 * ) addr ) ;
if ( size = = 8 ) modNum = ( uint16 ) ( * ( uint64 * ) addr ) ;
std : : string modStr ;
if ( modNum & CUSTKEY_CTRL_MASK ) modStr + = " Ctrl " ;
if ( modNum & CUSTKEY_ALT_MASK ) modStr + = " Alt " ;
if ( modNum & CUSTKEY_SHIFT_MASK ) modStr + = " Shift " ;
if ( ! ( modNum & ( CUSTKEY_CTRL_MASK | CUSTKEY_ALT_MASK | CUSTKEY_SHIFT_MASK ) ) ) modStr = " none " ;
else modStr . erase ( modStr . length ( ) - 1 ) ;
conf . SetString ( name , modStr , comment ) ;
}
break ;
}
}
} ;
std : : vector < ConfigItem > configItems ;
// var must be a persistent variable. In the case of strings, it must point to a writeable character array.
2010-09-25 19:35:19 +02:00
# define AddItemC(name, var, def, comment, type) configItems.push_back(ConfigItem((const char*)(CATEGORY "::" name), (void*)(&var), sizeof(var), (void*)(pint)def, (const char*)comment, (ConfigItemType)type))
2010-09-25 17:46:12 +02:00
# define AddItem(name, var, def, type) AddItemC(name,var,def,"",type)
# define AddUInt(name, var, def) AddItem(name,var,def,CIT_UINT)
# define AddInt(name, var, def) AddItem(name,var,def,CIT_INT)
# define AddBool(name, var, def) AddItem(name,var,def,CIT_BOOL)
# define AddBool2(name, var, def) AddItem(name,var,def,CIT_BOOLONOFF)
# define AddInvBool(name, var, def) AddItem(name,var,def,CIT_INVBOOL)
# define AddInvBool2(name, var, def) AddItem(name,var,def,CIT_INVBOOLONOFF)
# define AddVKey(name, var, def) AddItem(name,var,def,CIT_VKEY)
# define AddVKMod(name, var, def) AddItem(name,var,def,CIT_VKEYMOD)
# define AddUIntC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_UINT)
# define AddIntC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INT)
# define AddBoolC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_BOOL)
# define AddBool2C(name, var, def, comment) AddItemC(name,var,def,comment,CIT_BOOLONOFF)
# define AddInvBoolC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INVBOOL)
# define AddInvBool2C(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INVBOOLONOFF)
2010-09-25 19:35:19 +02:00
# define AddStringC(name, var, buflen, def, comment) configItems.push_back(ConfigItem((const char*)(CATEGORY "::" name), (void*)var, buflen, (void*)(pint)def, (const char*)comment, CIT_STRING))
2010-09-25 17:46:12 +02:00
# define AddString(name, var, buflen, def) AddStringC(name, var, buflen, def, "")
static char filterString [ 1024 ] , filterString2 [ 1024 ] , snapVerString [ 256 ] ;
static bool niceAlignment , showComments , readOnlyConfig ;
static int configSort ;
void WinPreSave ( ConfigFile & conf )
{
strcpy ( filterString , " output filter: " ) ;
for ( int i = 0 ; i < NUM_FILTERS ; i + + )
{
static char temp [ 256 ] ;
sprintf ( temp , " %d=%s%c " , i , GetFilterName ( ( RenderFilter ) i ) , i ! = NUM_FILTERS - 1 ? ' , ' : ' ' ) ;
strcat ( filterString , temp ) ;
}
strcpy ( filterString2 , " hi-res output filter: " ) ;
for ( int i = 0 ; i < NUM_FILTERS ; i + + )
{
if ( GetFilterHiResSupport ( ( RenderFilter ) i ) )
{
static char temp [ 256 ] ;
sprintf ( temp , " %d=%s%c " , i , GetFilterName ( ( RenderFilter ) i ) , i ! = NUM_FILTERS - 1 ? ' , ' : ' ' ) ;
strcat ( filterString2 , temp ) ;
}
}
sprintf ( snapVerString , " Snapshot save version. Must be between 1 and %d (inclusive) " , SNAPSHOT_VERSION ) ;
// GetWindowRect (GUI.hWnd, &GUI.window_size);
GUI . window_size . right - = GUI . window_size . left ;
GUI . window_size . bottom - = GUI . window_size . top ;
int extra_width = 2 * ( GetSystemMetrics ( SM_CXBORDER ) +
GetSystemMetrics ( SM_CXDLGFRAME ) ) ;
GUI . window_size . right - = extra_width ;
int extra_height = 2 * ( GetSystemMetrics ( SM_CYBORDER ) +
GetSystemMetrics ( SM_CYDLGFRAME ) ) +
GetSystemMetrics ( SM_CYCAPTION ) +
GetSystemMetrics ( SM_CYMENU ) +
( GUI . HideMenu ? 0 : (
( GUI . window_size . right < = 392 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) + // HACK: accounts for menu wrapping (when width is small)
( GUI . window_size . right < = 208 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) +
( GUI . window_size . right < = 148 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) ) ) ;
GUI . window_size . bottom - = extra_height ;
if ( GUI . window_size . bottom < 10 ) GUI . window_size . bottom = 10 ;
if ( GUI . window_size . right < 10 ) GUI . window_size . right = 10 ;
2018-07-03 22:39:20 +02:00
GUI . customRomDlgSettings . window_size . right - = GUI . customRomDlgSettings . window_size . left ;
GUI . customRomDlgSettings . window_size . bottom - = GUI . customRomDlgSettings . window_size . top ;
2010-09-25 17:46:12 +02:00
conf . DeleteKey ( " Sound::Mono " ) ;
if ( configSort = = 2 )
conf . ClearLines ( ) ;
}
void WinPostSave ( ConfigFile & conf )
{
int extra_width = 2 * ( GetSystemMetrics ( SM_CXBORDER ) +
GetSystemMetrics ( SM_CXDLGFRAME ) ) ;
int extra_height = 2 * ( GetSystemMetrics ( SM_CYBORDER ) +
GetSystemMetrics ( SM_CYDLGFRAME ) ) +
GetSystemMetrics ( SM_CYCAPTION ) +
( GUI . HideMenu ? 0 : ( GetSystemMetrics ( SM_CYMENU ) +
( GUI . window_size . right < = 392 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) + // HACK: accounts for menu wrapping (when width is small)
( GUI . window_size . right < = 208 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) +
( GUI . window_size . right < = 148 ? GetSystemMetrics ( SM_CYMENU ) : 0 ) ) ) ;
GUI . window_size . right + = GUI . window_size . left ;
GUI . window_size . bottom + = GUI . window_size . top ;
GUI . window_size . right + = extra_width ;
GUI . window_size . bottom + = extra_height ;
2018-07-03 22:39:20 +02:00
GUI . customRomDlgSettings . window_size . right + = GUI . customRomDlgSettings . window_size . left ;
GUI . customRomDlgSettings . window_size . bottom + = GUI . customRomDlgSettings . window_size . top ;
2010-09-25 17:46:12 +02:00
}
void WinPostLoad ( ConfigFile & conf )
{
int i ;
if ( Settings . DisplayPressedKeys ) Settings . DisplayPressedKeys = 2 ;
for ( i = 0 ; i < 8 ; i + + ) Joypad [ i + 8 ] . Enabled = Joypad [ i ] . Enabled ;
if ( GUI . MaxRecentGames < 1 ) GUI . MaxRecentGames = 1 ;
if ( GUI . MaxRecentGames > MAX_RECENT_GAMES_LIST_SIZE ) GUI . MaxRecentGames = MAX_RECENT_GAMES_LIST_SIZE ;
2012-03-28 00:18:03 +02:00
if ( GUI . rewindGranularity = = 0 ) GUI . rewindGranularity = 1 ;
2010-09-25 17:46:12 +02:00
bool gap = false ;
for ( i = 0 ; i < MAX_RECENT_GAMES_LIST_SIZE ; i + + ) // remove gaps in recent games list
{
if ( ! * GUI . RecentGames [ i ] )
gap = true ;
else if ( gap )
{
2010-09-25 19:35:19 +02:00
memmove ( GUI . RecentGames [ i - 1 ] , GUI . RecentGames [ i ] , MAX_PATH * sizeof ( TCHAR ) ) ;
* GUI . RecentGames [ i ] = TEXT ( ' \0 ' ) ;
2010-09-25 17:46:12 +02:00
gap = false ;
i = - 1 ;
}
}
2019-04-08 23:54:24 +02:00
if ( Settings . MaxSpriteTilesPerLine ! = 34 & & Settings . MaxSpriteTilesPerLine ! = 128 )
Settings . MaxSpriteTilesPerLine = 34 ;
switch ( Settings . OverclockMode )
{
default :
case 0 :
Settings . OneClockCycle = 6 ;
Settings . OneSlowClockCycle = 8 ;
Settings . TwoClockCycles = 12 ;
break ;
case 1 :
Settings . OneClockCycle = 6 ;
Settings . OneSlowClockCycle = 6 ;
Settings . TwoClockCycles = 12 ;
break ;
case 2 :
Settings . OneClockCycle = 4 ;
Settings . OneSlowClockCycle = 5 ;
Settings . TwoClockCycles = 8 ;
break ;
case 3 :
Settings . OneClockCycle = 3 ;
Settings . OneSlowClockCycle = 4 ;
Settings . TwoClockCycles = 6 ;
break ;
}
2010-09-25 17:46:12 +02:00
ConfigFile : : SetNiceAlignment ( niceAlignment ) ;
ConfigFile : : SetShowComments ( showComments ) ;
ConfigFile : : SetAlphaSort ( configSort = = 2 ) ;
ConfigFile : : SetTimeSort ( configSort = = 1 ) ;
WinPostSave ( conf ) ;
}
void WinPreLoad ( ConfigFile & conf )
{
if ( conf . Exists ( " Config::Sort " ) )
{
if ( conf . GetUInt ( " Config::Sort " ) = = 1 )
{
configSort = 1 ;
ConfigFile : : SetAlphaSort ( configSort = = 2 ) ;
ConfigFile : : SetTimeSort ( configSort = = 1 ) ;
conf . ClearLines ( ) ;
}
}
else
{
conf . DeleteKey ( " Config::Sort " ) ;
}
}
// and now for the important part,
// which determines what goes into and comes out of the config file:
// add all of the things we want to save and load to a list
// (but don't actually save or load anything yet)
void WinRegisterConfigItems ( )
{
# define CATEGORY "Config"
AddBool2C ( " NiceAlignment " , niceAlignment , true , " on to line up the =, :, and # in each section of this config file " ) ;
AddBool2C ( " Comments " , showComments , true , " on to keep comments such as this in this config file. To update/refresh all comments, set this to false and run Snes9x, then set it to true and run Snes9x again. " ) ;
AddUIntC ( " Sort " , configSort , 1 , " ordering within sections: 0=allow reordering, 1=force default order, 2=sort alphabetically " ) ;
AddBoolC ( " Lock " , readOnlyConfig , false , " if true, prevents Snes9x from editing this configuration file (or making it read-only while it is running) " ) ;
# undef CATEGORY
# define CATEGORY "Display"
AddBool2 ( " Transparency " , Settings . Transparency , true ) ;
AddBoolC ( " MessagesInImage " , Settings . AutoDisplayMessages , false , " true to draw text inside the SNES image (will get into AVIs, screenshots, and filters) " ) ;
AddBool2C ( " FrameRate " , Settings . DisplayFrameRate , false , " on to display the framerate (will be inaccurate if AutoMaxSkipFrames is too small) " ) ;
AddBoolC ( " DisplayInput " , Settings . DisplayPressedKeys , false , " true to show which buttons are pressed " ) ;
AddBoolC ( " DisplayFrameCount " , Settings . DisplayMovieFrame , true , " true to show the frame count when a movie is playing " ) ;
# undef CATEGORY
# define CATEGORY "Display\\Win"
2011-12-29 15:49:03 +01:00
AddUIntC ( " OutputMethod " , GUI . outputMethod , 1 , " 0=DirectDraw, 1=Direct3D, 2=OpenGL " ) ;
2010-09-25 17:46:12 +02:00
AddUIntC ( " FilterType " , GUI . Scale , 0 , filterString ) ;
AddUIntC ( " FilterHiRes " , GUI . ScaleHiRes , 0 , filterString2 ) ;
2011-01-30 13:32:06 +01:00
AddBoolC ( " BlendHiRes " , GUI . BlendHiRes , true , " true to horizontally blend Hi-Res images (better transparency effect on filters that do not account for this) " ) ;
2018-06-16 23:35:56 +02:00
AddBoolC ( " NTSCScanlines " , GUI . NTSCScanlines , true , " true to use scanlines with Blargg's NTSC filters " ) ;
2010-09-25 19:35:19 +02:00
AddBoolC ( " ShaderEnabled " , GUI . shaderEnabled , false , " true to use pixel shader (if supported by output method) " ) ;
2011-02-24 01:26:42 +01:00
AddStringC ( " Direct3D:D3DShader " , GUI . D3DshaderFileName , MAX_PATH , " " , " shader filename for Direct3D mode (HLSL effect file or CG shader " ) ;
AddStringC ( " OpenGL:OGLShader " , GUI . OGLshaderFileName , MAX_PATH , " " , " shader filename for OpenGL mode (bsnes-style XML shader or CG shader) " ) ;
2011-05-08 03:39:25 +02:00
AddBoolC ( " OpenGL:DisablePBOs " , GUI . OGLdisablePBOs , false , " do not use PBOs in OpenGL mode, even if the video card supports them " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " ExtendHeight " , GUI . HeightExtend , false , " true to display an extra 15 pixels at the bottom, which few games use. Also increases AVI output size from 256x224 to 256x240. " ) ;
2010-10-17 02:47:53 +02:00
AddBoolC ( " AlwaysCenterImage " , GUI . AlwaysCenterImage , false , " true to center the image even if larger than window " ) ;
2010-09-25 17:46:12 +02:00
AddIntC ( " Window:Width " , GUI . window_size . right , 512 , " 256=1x, 512=2x, 768=3x, 1024=4x, etc. (usually) " ) ;
AddIntC ( " Window:Height " , GUI . window_size . bottom , 448 , " 224=1x, 448=2x, 672=3x, 896=4x, etc. (usually) " ) ;
AddIntC ( " Window:Left " , GUI . window_size . left , 0 , " in pixels from left edge of screen " ) ;
AddIntC ( " Window:Top " , GUI . window_size . top , 0 , " in pixels from top edge of screen " ) ;
AddBool ( " Window:Maximized " , GUI . window_maximized , false ) ;
2018-07-03 22:39:20 +02:00
AddIntC ( " CustomRomDialog:Width " , GUI . customRomDlgSettings . window_size . right , 660 , " " ) ;
AddIntC ( " CustomRomDialog:Height " , GUI . customRomDlgSettings . window_size . bottom , 400 , " " ) ;
AddIntC ( " CustomRomDialog:Left " , GUI . customRomDlgSettings . window_size . left , 50 , " in pixels from left edge of screen " ) ;
AddIntC ( " CustomRomDialog:Top " , GUI . customRomDlgSettings . window_size . top , 50 , " in pixels from top edge of screen " ) ;
AddBool ( " CustomRomDialog:Maximized " , GUI . customRomDlgSettings . window_maximized , false ) ;
AddIntC ( " CustomRomDialog:FolderPaneWidth " , GUI . customRomDlgSettings . folderPaneWidth , 230 , " " ) ;
AddIntC ( " CustomRomDialog:DescColumnWidth " , GUI . customRomDlgSettings . columnDescription , 112 , " " ) ;
AddIntC ( " CustomRomDialog:FilenameColumnWidth " , GUI . customRomDlgSettings . columnFilename , 196 , " " ) ;
AddIntC ( " CustomRomDialog:SizeColumnWidth " , GUI . customRomDlgSettings . columnSize , 67 , " " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " Stretch:Enabled " , GUI . Stretch , true , " true to stretch the game image to fill the window or screen " ) ;
AddBoolC ( " Stretch:MaintainAspectRatio " , GUI . AspectRatio , true , " prevents stretching from changing the aspect ratio " ) ;
2018-06-13 00:50:24 +02:00
AddBoolC ( " Stretch:IntegerScaling " , GUI . IntegerScaling , false , " scales image height to exact integer multiples " ) ;
2010-09-25 17:46:12 +02:00
AddUIntC ( " Stretch:AspectRatioBaseWidth " , GUI . AspectWidth , 256 , " base width for aspect ratio calculation (AR=AspectRatioBaseWidth/224), default is 256 - set to 299 for 4:3 aspect ratio " ) ;
2018-05-20 18:01:03 +02:00
AddBoolC ( " Stretch:BilinearFilter " , Settings . BilinearFilter , true , " allows bilinear filtering of stretching. Depending on your video card and the window size, this may result in a lower framerate. " ) ;
2010-09-25 17:52:32 +02:00
AddBoolC ( " Stretch:LocalVidMem " , GUI . LocalVidMem , true , " determines the location of video memory in DirectDraw mode. May increase or decrease rendering performance, depending on your setup and which filter and stretching options are active. " ) ;
2010-09-25 17:46:12 +02:00
AddBool ( " Fullscreen:Enabled " , GUI . FullScreen , false ) ;
AddUInt ( " Fullscreen:Width " , GUI . FullscreenMode . width , 640 ) ;
AddUInt ( " Fullscreen:Height " , GUI . FullscreenMode . height , 480 ) ;
AddUInt ( " Fullscreen:Depth " , GUI . FullscreenMode . depth , 16 ) ;
AddUInt ( " Fullscreen:RefreshRate " , GUI . FullscreenMode . rate , 60 ) ;
AddBool ( " Fullscreen:DoubleBuffered " , GUI . DoubleBuffered , false ) ;
AddBoolC ( " Fullscreen:EmulateFullscreen " , GUI . EmulateFullscreen , true , " true makes snes9x create a window that spans the entire screen when going fullscreen " ) ;
AddBoolC ( " HideMenu " , GUI . HideMenu , false , " true to auto-hide the menu bar on startup. " ) ;
2010-09-25 17:52:32 +02:00
AddBoolC ( " Vsync " , GUI . Vsync , false , " true to enable Vsync " ) ;
2018-05-05 23:31:54 +02:00
AddBoolC ( " ReduceInputLag " , GUI . ReduceInputLag , false , " true to reduce input lag by hard synchronization " ) ;
2019-03-04 21:42:40 +01:00
AddBoolC ( " DWMSync " , GUI . DWMSync , false , " sync to DWM compositor if it is running " ) ;
2018-01-03 20:40:29 +01:00
AddBoolC ( " FilterMessageFont " , GUI . filterMessagFont , true , " true to filter message font with EPX on 2x/3x scales if MessagesInImage is false) " ) ;
2010-09-25 17:46:12 +02:00
# undef CATEGORY
# define CATEGORY "Settings"
2010-09-25 17:52:32 +02:00
AddUIntC ( " FrameSkip " , Settings . SkipFrames , AUTO_FRAMERATE , " 200=automatic (limits at 50/60 fps), 0=none, 1=skip every other, ... " ) ;
AddUIntC ( " AutoMaxSkipFramesAtOnce " , Settings . AutoMaxSkipFrames , 0 , " most frames to skip at once to maintain speed in automatic mode, don't set to more than 1 or 2 frames because the skipping algorithm isn't very smart " ) ;
2010-09-25 17:46:12 +02:00
AddUIntC ( " TurboFrameSkip " , Settings . TurboSkipFrames , 15 , " how many frames to skip when in fast-forward mode " ) ;
AddUInt ( " AutoSaveDelay " , Settings . AutoSaveDelay , 30 ) ;
2010-09-28 21:25:34 +02:00
AddBool ( " BlockInvalidVRAMAccess " , Settings . BlockInvalidVRAMAccessMaster , true ) ;
2010-09-25 17:46:12 +02:00
AddBool2C ( " SnapshotScreenshots " , Settings . SnapshotScreenshots , true , " on to save the screenshot in each snapshot, for loading-when-paused display " ) ;
AddBoolC ( " MovieTruncateAtEnd " , Settings . MovieTruncate , true , " true to truncate any leftover data in the movie file after the current frame when recording stops " ) ;
AddBoolC ( " MovieNotifyIgnored " , Settings . MovieNotifyIgnored , false , " true to display \" (ignored) \" in the frame counter when recording when the last frame of input was not used by the SNES (such as lag or loading frames) " ) ;
AddBool ( " DisplayWatchedAddresses " , Settings . DisplayWatchedAddresses , true ) ;
AddBool2C ( " WrongMovieStateProtection " , Settings . WrongMovieStateProtection , true , " off to allow states to be loaded for recording from a different movie than they were made in " ) ;
AddUIntC ( " MessageDisplayTime " , Settings . InitialInfoStringTimeout , 120 , " display length of messages, in frames. set to 0 to disable all message text " ) ;
# undef CATEGORY
# define CATEGORY "Settings\\Win"
2012-03-28 00:18:03 +02:00
AddUIntC ( " RewindBufferSize " , GUI . rewindBufferSize , 0 , " rewind buffer size in MB - 0 disables rewind support " ) ;
AddUIntC ( " RewindGranularity " , GUI . rewindGranularity , 1 , " rewind granularity - rewind takes a snapshot each x frames " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " PauseWhenInactive " , GUI . InactivePause , TRUE , " true to pause Snes9x when it is not the active window " ) ;
AddBoolC ( " CustomRomOpenDialog " , GUI . CustomRomOpen , false , " false to use standard Windows open dialog for the ROM open dialog " ) ;
2011-02-12 16:32:53 +01:00
AddBoolC ( " AVIHiRes " , GUI . AVIHiRes , false , " true to record AVI in Hi-Res scale " ) ;
2019-08-03 15:44:08 +02:00
AddBoolC ( " ConfirmSaveLoad " , GUI . ConfirmSaveLoad , false , " true to ask for confirmation when saving/loading " ) ;
2010-09-25 17:46:12 +02:00
// AddUIntC("Language", GUI.Language, 0, "0=English, 1=Nederlands"); // NYI
AddBoolC ( " FrameAdvanceSkipsNonInput " , GUI . FASkipsNonInput , false , " causes frame advance to fast-forward past frames where the game is definitely not checking input, such as during lag or loading time. EXPERIMENTAL " ) ;
AddBool ( " MovieDefaultClearSRAM " , GUI . MovieClearSRAM , false ) ;
AddBool ( " MovieDefaultStartFromReset " , GUI . MovieStartFromReset , false ) ;
AddBool ( " MovieDefaultReadOnly " , GUI . MovieReadOnly , true ) ;
AddUInt ( " CurrentSaveSlot " , GUI . CurrentSaveSlot , 0 ) ;
AddUIntC ( " MaxRecentGames " , GUI . MaxRecentGames , 14 , " max recent games to show in the recent games menu (must be <= 32) " ) ;
# undef CATEGORY
# define CATEGORY "Settings\\Win\\Files"
AddStringC ( " Dir:Roms " , GUI . RomDir , _MAX_PATH , " . \\ Roms " , " directory where the Open ROM dialog will start " ) ;
AddStringC ( " Dir:Screenshots " , GUI . ScreensDir , _MAX_PATH , " . \\ Screenshots " , " directory where screenshots will be saved " ) ;
AddStringC ( " Dir:Movies " , GUI . MovieDir , _MAX_PATH , " . \\ Movies " , " the default directory for recorded movie (.smv) files " ) ;
AddStringC ( " Dir:SPCs " , GUI . SPCDir , _MAX_PATH , " . \\ SPCs " , " directory where SPCs will be saved " ) ;
AddStringC ( " Dir:Savestates " , GUI . FreezeFileDir , _MAX_PATH , " . \\ Saves " , " directory where savestates will be created and loaded from " ) ;
AddStringC ( " Dir:SRAM " , GUI . SRAMFileDir , _MAX_PATH , " . \\ Saves " , " directory where battery saves will be created and loaded from " ) ;
2017-09-04 20:41:04 +02:00
AddStringC ( " Dir:Cheats " , GUI . CheatDir , _MAX_PATH , " . \\ Cheats " , " directory in which cheats (.cht files) will be looked for " ) ;
AddStringC ( " Dir:Patches " , GUI . PatchDir , _MAX_PATH , " . \\ Patches " , " directory in which ROM patches (.ips/.bps/.ups files) will be looked for " ) ;
2010-09-25 17:46:12 +02:00
AddStringC ( " Dir:Bios " , GUI . BiosDir , _MAX_PATH , " . \\ BIOS " , " directory where BIOS files (such as \" BS-X.bios \" ) will be located " ) ;
2016-12-28 16:36:21 +01:00
AddStringC ( " Dir:SatData " , GUI . SatDir , _MAX_PATH , " . \\ SatData " , " directory where Satellaview Signal Data files will be located " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " Dir:Lock " , GUI . LockDirectories , false , " true to prevent Snes9x from changing configured directories when you browse to a new location " ) ;
# define ADD(n) AddString("Rom:RecentGame" #n, GUI.RecentGames[n-1], MAX_PATH, "")
ADD ( 1 ) ; ADD ( 2 ) ; ADD ( 3 ) ; ADD ( 4 ) ; ADD ( 5 ) ; ADD ( 6 ) ; ADD ( 7 ) ; ADD ( 8 ) ;
ADD ( 9 ) ; ADD ( 10 ) ; ADD ( 11 ) ; ADD ( 12 ) ; ADD ( 13 ) ; ADD ( 14 ) ; ADD ( 15 ) ; ADD ( 16 ) ;
ADD ( 17 ) ; ADD ( 18 ) ; ADD ( 19 ) ; ADD ( 20 ) ; ADD ( 21 ) ; ADD ( 22 ) ; ADD ( 23 ) ; ADD ( 24 ) ;
ADD ( 25 ) ; ADD ( 26 ) ; ADD ( 27 ) ; ADD ( 28 ) ; ADD ( 29 ) ; ADD ( 30 ) ; ADD ( 31 ) ; ADD ( 32 ) ;
assert ( MAX_RECENT_GAMES_LIST_SIZE = = 32 ) ;
# undef ADD
AddString ( " Rom:MultiCartA " , multiRomA , _MAX_PATH , " " ) ;
AddString ( " Rom:MultiCartB " , multiRomB , _MAX_PATH , " " ) ;
# undef CATEGORY
# define CATEGORY "Sound"
2010-09-25 17:52:32 +02:00
AddIntC ( " Sync " , Settings . SoundSync , 1 , " 1 to sync emulation to sound output, 0 to disable. " ) ;
2019-02-15 19:59:18 +01:00
AddUIntC ( " Rate " , Settings . SoundPlaybackRate , 48000 , " sound playback quality, in Hz " ) ;
2019-04-12 19:10:51 +02:00
AddUIntC ( " InputRate " , Settings . SoundInputRate , 31950 , " for each 'Input rate' samples generated by the SNES, 'Playback rate' samples will produced. If you experience crackling you can try to lower this setting. " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " Mute " , GUI . Mute , false , " true to mute sound output (does not disable the sound CPU) " ) ;
2017-11-28 20:48:12 +01:00
AddBool ( " DynamicRateControl " , Settings . DynamicRateControl , false ) ;
2018-05-25 01:52:43 +02:00
AddBool ( " AutomaticInputRate " , GUI . AutomaticInputRate , true ) ;
2018-08-06 19:31:07 +02:00
AddIntC ( " InterpolationMethod " , Settings . InterpolationMethod , 2 , " 0 = None, 1 = Linear, 2 = Gaussian (accurate), 3 = Cubic, 4 = Sinc " ) ;
2010-09-25 17:46:12 +02:00
# undef CATEGORY
# define CATEGORY "Sound\\Win"
2019-02-12 16:52:05 +01:00
AddUIntC ( " SoundDriver " , GUI . SoundDriver , 4 , " 4=XAudio2 (recommended), 8=WaveOut " ) ;
2010-09-25 17:52:32 +02:00
AddUIntC ( " BufferSize " , GUI . SoundBufferSize , 64 , " sound buffer size in ms - determines the internal and output sound buffer sizes. actual mixing is done every SoundBufferSize/4 samples " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " MuteFrameAdvance " , GUI . FAMute , false , " true to prevent Snes9x from outputting sound when the Frame Advance command is in use " ) ;
2017-11-25 00:10:44 +01:00
AddUIntC ( " VolumeRegular " , GUI . VolumeRegular , 100 , " volume during regular play (percentage between 0 and 100) " ) ;
AddUIntC ( " VolumeTurbo " , GUI . VolumeTurbo , 100 , " volume during turbo mode (percentage between 0 and 100) " ) ;
2018-12-15 14:19:16 +01:00
AddStringC ( " OutputDevice " , GUI . AudioDevice , MAX_AUDIO_NAME_LENGTH , " Default " , " Name of the output audio device (substring matching, XAudio2 only atm), set to 'Default' for default audio device " ) ;
2010-09-25 17:46:12 +02:00
# undef CATEGORY
# define CATEGORY "Controls"
AddBoolC ( " AllowLeftRight " , Settings . UpAndDown , false , " true to allow left+right and up+down " ) ;
# undef CATEGORY
# define CATEGORY "ROM"
AddBoolC ( " Cheat " , Settings . ApplyCheats , true , " true to allow enabled cheats to be applied " ) ;
2010-09-25 17:52:32 +02:00
AddInvBoolC ( " Patch " , Settings . NoPatch , true , " true to allow IPS/UPS patches to be applied ( \" soft patching \" ) " ) ;
2017-09-28 19:45:32 +02:00
AddBoolC ( " IgnorePatchChecksum " , Settings . IgnorePatchChecksum , false , " true to allow BPS patches to be applied even if the checksum fails " ) ;
2010-09-25 17:46:12 +02:00
AddBoolC ( " BS " , Settings . BS , false , " Broadcast Satellaview emulation " ) ;
# undef CATEGORY
# ifdef NETPLAY_SUPPORT
# define CATEGORY "Netplay"
AddUInt ( " Port " , Settings . Port , NP_DEFAULT_PORT ) ;
AddString ( " Server " , Settings . ServerName , 128 , Settings . ServerName ) ;
AddBool2 ( " SyncByReset " , NPServer . SyncByReset , true ) ;
AddBool2 ( " SendROMImageOnConnect " , NPServer . SendROMImageOnConnect , false ) ;
AddUInt ( " MaxFrameSkip " , NetPlay . MaxFrameSkip , 10 ) ;
AddUInt ( " MaxBehindFrameCount " , NetPlay . MaxBehindFrameCount , 10 ) ;
AddBoolC ( " UseJoypad1 " , GUI . NetplayUseJoypad1 , true , " if false, player 2 has to use their joypad #2 controls, etc. " ) ;
# define ADD(n,d) AddString("RecentHost" #n, GUI.RecentHostNames[n-1], MAX_PATH, d)
ADD ( 1 , " localhost " ) ; ADD ( 2 , " " ) ; ADD ( 3 , " " ) ; ADD ( 4 , " " ) ; ADD ( 5 , " " ) ; ADD ( 6 , " " ) ; ADD ( 7 , " " ) ; ADD ( 8 , " " ) ;
ADD ( 9 , " " ) ; ADD ( 10 , " " ) ; ADD ( 11 , " " ) ; ADD ( 12 , " " ) ; ADD ( 13 , " " ) ; ADD ( 14 , " " ) ; ADD ( 15 , " " ) ; ADD ( 16 , " " ) ;
assert ( MAX_RECENT_HOSTS_LIST_SIZE = = 16 ) ;
# undef ADD
# undef CATEGORY
# endif
# define CATEGORY "Controls\\Win"
# define ADD(n,x) AddVKey("Joypad" #n ":" #x, Joypad[n-1].x, Joypad[n-1].x)
# define ADDN(n,x,n2) AddVKey("Joypad" #n ":" #n2, Joypad[n-1].x, Joypad[n-1].x)
# define ADDB(n,x) AddBool("Joypad" #n ":" #x, Joypad[n-1].x, Joypad[n-1].x)
# define ADD2(n) ADDB(n,Enabled); ADD(n,Up); ADD(n,Down); ADD(n,Left); ADD(n,Right); ADD(n,A); ADD(n,B); ADD(n,Y); ADD(n,X); ADD(n,L); ADD(n,R); ADD(n,Start); ADD(n,Select); ADDN(n,Left_Up,Left+Up); ADDN(n,Right_Up,Right+Up); ADDN(n,Right_Down,Right+Down); ADDN(n,Left_Down,Left+Down)
# define ADDT(n,x) AddVKey("Joypad" #n "Turbo:" #x, Joypad[n-1+8].x, Joypad[n-1+8].x)
# define ADDTN(n,x,n2) AddVKey("Joypad" #n "Turbo:" #n2, Joypad[n-1+8].x, Joypad[n-1+8].x)
# define ADDT2(n) ADDTN(n,Down,AutoFire); ADDTN(n,Left,AutoHold); ADDTN(n,Up,TempTurbo); ADDTN(n,Right,ClearAll)
# define ADDT3(n) ADDT(n,A); ADDT(n,B); ADDT(n,Y); ADDT(n,X); ADDT(n,L); ADDT(n,R); ADDT(n,Start); ADDT(n,Select)
# define ADD2T2(n) ADD2(n); ADDT2(n)
// NOTE: for now, the windows port doesn't actually allow 8 different controllers to be set configured, only 5
ADD2T2 ( 1 ) ; ADD2T2 ( 2 ) ; ADD2T2 ( 3 ) ; ADD2T2 ( 4 ) ; ADD2T2 ( 5 ) ; ADD2T2 ( 6 ) ; ADD2T2 ( 7 ) ; ADD2T2 ( 8 ) ;
ADDT3 ( 1 ) ; ADDT3 ( 2 ) ; ADDT3 ( 3 ) ; ADDT3 ( 4 ) ; ADDT3 ( 5 ) ; ADDT3 ( 6 ) ; ADDT3 ( 7 ) ; ADDT3 ( 8 ) ;
# undef ADD
# undef ADD2
# undef ADDN
# undef ADDB
# undef ADDT
# undef ADDT2
# undef ADDT3
# undef ADDTN
# undef ADD2T2
2011-05-08 01:41:33 +02:00
AddBool2C ( " Input:Background " , GUI . BackgroundInput , false , " on to detect game keypresses and hotkeys while window is inactive, if PauseWhenInactive = FALSE. " ) ;
2018-05-05 18:28:49 +02:00
AddBool2C ( " Input:BackgroundKeyHotkeys " , GUI . BackgroundKeyHotkeys , true , " on to also detect keyboard hotkeys when backgroundinput is active " ) ;
2010-09-25 17:46:12 +02:00
# undef CATEGORY
# define CATEGORY "Controls\\Win\\Hotkeys"
AddBool2C ( " Handler:Joystick " , GUI . JoystickHotkeys , true , " on to detect game controller buttons assigned to hotkeys. May impact performance. " ) ;
# define ADD(x) AddVKey("Key:" #x , CustomKeys.x.key, CustomKeys.x.key); AddVKMod("Mods:" #x, CustomKeys.x.modifiers, CustomKeys.x.modifiers)
# define ADDN(x,n2) AddVKey("Key:" #n2, CustomKeys.x.key, CustomKeys.x.key); AddVKMod("Mods:" #n2, CustomKeys.x.modifiers, CustomKeys.x.modifiers)
ADD ( SpeedUp ) ; ADD ( SpeedDown ) ; ADD ( Pause ) ; ADD ( FrameAdvance ) ;
ADD ( SkipUp ) ; ADD ( SkipDown ) ; ADD ( ScopeTurbo ) ; ADD ( ScopePause ) ;
2012-08-03 01:05:57 +02:00
ADD ( FrameCount ) ; ADD ( ReadOnly ) ; ADD ( FastForward ) ; ADD ( FastForwardToggle ) ; ADD ( ShowPressed ) ;
2010-09-25 17:46:12 +02:00
ADDN ( Save [ 0 ] , SaveSlot0 ) ; ADDN ( Save [ 1 ] , SaveSlot1 ) ; ADDN ( Save [ 2 ] , SaveSlot2 ) ; ADDN ( Save [ 3 ] , SaveSlot3 ) ; ADDN ( Save [ 4 ] , SaveSlot4 ) ; ADDN ( Save [ 5 ] , SaveSlot5 ) ; ADDN ( Save [ 6 ] , SaveSlot6 ) ; ADDN ( Save [ 7 ] , SaveSlot7 ) ; ADDN ( Save [ 8 ] , SaveSlot8 ) ; ADDN ( Save [ 9 ] , SaveSlot9 ) ;
ADDN ( Load [ 0 ] , LoadSlot0 ) ; ADDN ( Load [ 1 ] , LoadSlot1 ) ; ADDN ( Load [ 2 ] , LoadSlot2 ) ; ADDN ( Load [ 3 ] , LoadSlot3 ) ; ADDN ( Load [ 4 ] , LoadSlot4 ) ; ADDN ( Load [ 5 ] , LoadSlot5 ) ; ADDN ( Load [ 6 ] , LoadSlot6 ) ; ADDN ( Load [ 7 ] , LoadSlot7 ) ; ADDN ( Load [ 8 ] , LoadSlot8 ) ; ADDN ( Load [ 9 ] , LoadSlot9 ) ;
ADDN ( SelectSave [ 0 ] , SelectSlot0 ) ; ADDN ( SelectSave [ 1 ] , SelectSlot1 ) ; ADDN ( SelectSave [ 2 ] , SelectSlot2 ) ; ADDN ( SelectSave [ 3 ] , SelectSlot3 ) ; ADDN ( SelectSave [ 4 ] , SelectSlot4 ) ; ADDN ( SelectSave [ 5 ] , SelectSlot5 ) ; ADDN ( SelectSave [ 6 ] , SelectSlot6 ) ; ADDN ( SelectSave [ 7 ] , SelectSlot7 ) ; ADDN ( SelectSave [ 8 ] , SelectSlot8 ) ; ADDN ( SelectSave [ 9 ] , SelectSlot9 ) ;
2019-12-20 16:39:07 +01:00
ADD ( SaveScreenShot ) ; ADD ( SlotPlus ) ; ADD ( SlotMinus ) ; ADD ( SlotSave ) ; ADD ( SlotLoad ) ; ADD ( DialogSave ) ; ADD ( DialogLoad ) ;
2010-09-25 17:46:12 +02:00
ADD ( BGL1 ) ; ADD ( BGL2 ) ; ADD ( BGL3 ) ; ADD ( BGL4 ) ; ADD ( BGL5 ) ;
2011-01-16 14:06:43 +01:00
ADD ( ClippingWindows ) ; /*ADD(BGLHack);*/ ADD ( Transparency ) ; /*ADD(HDMA)*/ ; /*ADD(GLCube);*/
2010-09-25 17:46:12 +02:00
/*ADD(InterpMode7);*/ ADD ( JoypadSwap ) ; ADD ( SwitchControllers ) ; ADD ( ResetGame ) ; ADD ( ToggleCheats ) ;
ADD ( TurboA ) ; ADD ( TurboB ) ; ADD ( TurboY ) ; ADD ( TurboX ) ; ADD ( TurboL ) ; ADD ( TurboR ) ; ADD ( TurboStart ) ; ADD ( TurboSelect ) ; ADD ( TurboUp ) ; ADD ( TurboDown ) ; ADD ( TurboLeft ) ; ADD ( TurboRight ) ;
2012-03-28 00:18:03 +02:00
ADD ( QuitS9X ) ; ADD ( Rewind ) ;
2018-05-05 15:51:45 +02:00
ADD ( SaveFileSelect ) ; ADD ( LoadFileSelect ) ;
2018-05-05 16:11:00 +02:00
ADD ( Mute ) ;
2010-09-25 17:46:12 +02:00
# undef ADD
# undef ADDN
# undef CATEGORY
2018-05-29 20:36:36 +02:00
# define CATEGORY "Hack"
2019-04-08 23:54:24 +02:00
AddUIntC ( " CPUOverclockMode " , Settings . OverclockMode , 0 , " CPU Overclock: 0=none, 1=min, 2=medium, 3=max " ) ;
AddUIntC ( " MaxSpriteTilesPerLine " , Settings . MaxSpriteTilesPerLine , 34 , " Max sprite tiles rendered per line. Default = 34, Unlimited ~= 128 " ) ;
2018-05-29 20:36:36 +02:00
AddUIntC ( " SuperFXClockMultiplier " , Settings . SuperFXClockMultiplier , 100 , " SuperFX speed, in percent (default 100) " ) ;
2019-04-08 23:54:24 +02:00
AddBoolC ( " SeparateEchoBuffer " , Settings . SeparateEchoBuffer , false , " Separate echo buffer from APU ram. For old hacks only. " ) ;
2018-05-29 20:36:36 +02:00
# undef CATEGORY
2010-09-25 17:46:12 +02:00
}
// These let us give the config file read-only status to other applications while snes9x is running,
// to prevent the situation where the user saves a modified .cfg file while snes9x is running
// only to have the changes overwritten by snes9x upon closing snes9x.
static HANDLE locked_file = NULL ;
void WinLockConfigFile ( )
{
if ( readOnlyConfig ) return ; // if user has lock on file, don't let Snes9x lock it
static std : : string fname ;
fname = S9xGetDirectory ( DEFAULT_DIR ) ;
fname + = SLASH_STR " snes9x.conf " ;
STREAM fp ;
if ( ( fp = OPEN_STREAM ( fname . c_str ( ) , " r " ) ) ! = NULL ) {
CLOSE_STREAM ( fp ) ;
2010-09-25 19:35:19 +02:00
locked_file = CreateFileA ( fname . c_str ( ) , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , NULL ) ;
2010-09-25 17:46:12 +02:00
} else {
fname = S9xGetDirectory ( DEFAULT_DIR ) ;
fname + = SLASH_STR " snes9x.cfg " ;
if ( ( fp = OPEN_STREAM ( fname . c_str ( ) , " r " ) ) ! = NULL ) {
CLOSE_STREAM ( fp ) ;
2010-09-25 19:35:19 +02:00
locked_file = CreateFileA ( fname . c_str ( ) , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , NULL ) ;
2010-09-25 17:46:12 +02:00
}
}
}
void WinUnlockConfigFile ( )
{
if ( locked_file ) {
CloseHandle ( locked_file ) ;
locked_file = NULL ;
}
}
/*****************************************************************************/
/* WinSave/WinLoad - Save/Load the settings to/from the registry */
/*****************************************************************************/
static ConfigFile loaded_config_file ;
void WinLoadConfigFile ( ConfigFile & conf )
{
WinPreLoad ( conf ) ;
WinSetDefaultValues ( ) ;
for ( unsigned int i = 0 ; i < configItems . size ( ) ; i + + )
configItems [ i ] . Get ( conf ) ;
loaded_config_file = conf ;
WinPostLoad ( conf ) ;
}
void WinSaveConfigFile ( )
{
if ( readOnlyConfig ) return ; // if user has lock on file, don't let Snes9x overwrite it
ConfigFile & conf = loaded_config_file ;
conf . ClearUnused ( ) ;
WinPreSave ( conf ) ;
for ( unsigned int i = 0 ; i < configItems . size ( ) ; i + + )
configItems [ i ] . Set ( conf ) ;
bool wasLocked = locked_file ! = NULL ;
if ( wasLocked ) WinUnlockConfigFile ( ) ;
S9xSaveConfigFile ( conf ) ;
if ( wasLocked ) WinLockConfigFile ( ) ;
WinPostSave ( conf ) ;
}
void S9xParsePortConfig ( ConfigFile & conf , int pass )
{
WinLoadConfigFile ( conf ) ;
return ;
}
void WinCleanupConfigData ( )
{
configItems . clear ( ) ;
}