947 lines
30 KiB
C++
947 lines
30 KiB
C++
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2020 mjbudd77
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include <QDir>
|
|
|
|
#include "Qt/main.h"
|
|
#include "Qt/throttle.h"
|
|
#include "Qt/config.h"
|
|
|
|
#include "fceu.h"
|
|
#include "ppu.h"
|
|
#include "../common/cheat.h"
|
|
|
|
#include "Qt/input.h"
|
|
#include "Qt/dface.h"
|
|
|
|
#include "Qt/sdl.h"
|
|
#include "Qt/sdl-video.h"
|
|
#include "Qt/unix-netplay.h"
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
//#include <unistd.h>
|
|
|
|
#include <csignal>
|
|
#include <cstring>
|
|
#include <cerrno>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
#ifdef WIN32
|
|
#include <direct.h>
|
|
#else
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
extern bool force_grayscale;
|
|
extern bool palupdate;
|
|
extern int palnotch;
|
|
extern int palsaturation;
|
|
extern int palsharpness;
|
|
extern int palcontrast;
|
|
extern int palbrightness;
|
|
|
|
int getHotKeyConfig( int i, const char **nameOut, const char **keySeqOut, const char **titleOut )
|
|
{
|
|
const char *name = "";
|
|
const char *keySeq = "";
|
|
const char *title = NULL;
|
|
|
|
switch ( i )
|
|
{
|
|
case HK_OPEN_ROM:
|
|
name = "OpenROM"; keySeq = "Ctrl+O"; title = "Open ROM";
|
|
break;
|
|
case HK_CLOSE_ROM:
|
|
name = "CloseROM"; keySeq = "Ctrl+C"; title = "Close ROM";
|
|
break;
|
|
case HK_CHEAT_MENU:
|
|
name = "CheatMenu"; keySeq = ""; title = "Open Cheat Window";
|
|
break;
|
|
case HK_BIND_STATE:
|
|
name = "BindState"; keySeq = ""; title = "Bind Save State to Movie";
|
|
break;
|
|
case HK_LOAD_LUA:
|
|
name = "LoadLua"; keySeq = "Ctrl+L";
|
|
break;
|
|
case HK_TOGGLE_BG:
|
|
name = "ToggleBG"; keySeq = ""; title = "Toggle Background Display";
|
|
break;
|
|
case HK_TOGGLE_FG:
|
|
name = "ToggleFG"; keySeq = ""; title = "Toggle Object Display";
|
|
break;
|
|
// Save States
|
|
case HK_SAVE_STATE:
|
|
name = "SaveState"; keySeq = "I"; title = "Save State";
|
|
break;
|
|
case HK_SAVE_STATE_0:
|
|
name = "SaveState0"; keySeq = "Shift+F10"; title = "Save State to Slot 0";
|
|
break;
|
|
case HK_SAVE_STATE_1:
|
|
name = "SaveState1"; keySeq = "Shift+F1"; title = "Save State to Slot 1";
|
|
break;
|
|
case HK_SAVE_STATE_2:
|
|
name = "SaveState2"; keySeq = "Shift+F2"; title = "Save State to Slot 2";
|
|
break;
|
|
case HK_SAVE_STATE_3:
|
|
name = "SaveState3"; keySeq = "Shift+F3"; title = "Save State to Slot 3";
|
|
break;
|
|
case HK_SAVE_STATE_4:
|
|
name = "SaveState4"; keySeq = "Shift+F4"; title = "Save State to Slot 4";
|
|
break;
|
|
case HK_SAVE_STATE_5:
|
|
name = "SaveState5"; keySeq = "Shift+F5"; title = "Save State to Slot 5";
|
|
break;
|
|
case HK_SAVE_STATE_6:
|
|
name = "SaveState6"; keySeq = "Shift+F6"; title = "Save State to Slot 6";
|
|
break;
|
|
case HK_SAVE_STATE_7:
|
|
name = "SaveState7"; keySeq = "Shift+F7"; title = "Save State to Slot 7";
|
|
break;
|
|
case HK_SAVE_STATE_8:
|
|
name = "SaveState8"; keySeq = "Shift+F8"; title = "Save State to Slot 8";
|
|
break;
|
|
case HK_SAVE_STATE_9:
|
|
name = "SaveState9"; keySeq = "Shift+F9"; title = "Save State to Slot 9";
|
|
break;
|
|
// Load States
|
|
case HK_LOAD_STATE:
|
|
name = "LoadState"; keySeq = "P"; title = "Load State";
|
|
break;
|
|
case HK_LOAD_STATE_0:
|
|
name = "LoadState0"; keySeq = "F10"; title = "Load State From Slot 0";
|
|
break;
|
|
case HK_LOAD_STATE_1:
|
|
name = "LoadState1"; keySeq = "F1"; title = "Load State From Slot 1";
|
|
break;
|
|
case HK_LOAD_STATE_2:
|
|
name = "LoadState2"; keySeq = "F2"; title = "Load State From Slot 2";
|
|
break;
|
|
case HK_LOAD_STATE_3:
|
|
name = "LoadState3"; keySeq = "F3"; title = "Load State From Slot 3";
|
|
break;
|
|
case HK_LOAD_STATE_4:
|
|
name = "LoadState4"; keySeq = "F4"; title = "Load State From Slot 4";
|
|
break;
|
|
case HK_LOAD_STATE_5:
|
|
name = "LoadState5"; keySeq = "F5"; title = "Load State From Slot 5";
|
|
break;
|
|
case HK_LOAD_STATE_6:
|
|
name = "LoadState6"; keySeq = "F6"; title = "Load State From Slot 6";
|
|
break;
|
|
case HK_LOAD_STATE_7:
|
|
name = "LoadState7"; keySeq = "F7"; title = "Load State From Slot 7";
|
|
break;
|
|
case HK_LOAD_STATE_8:
|
|
name = "LoadState8"; keySeq = "F8"; title = "Load State From Slot 8";
|
|
break;
|
|
case HK_LOAD_STATE_9:
|
|
name = "LoadState9"; keySeq = "F9"; title = "Load State From Slot 9";
|
|
break;
|
|
case HK_FDS_SELECT:
|
|
name = "FDSSelect"; keySeq = ""; title = "Switch FDS Disk Side";
|
|
break;
|
|
case HK_FDS_EJECT:
|
|
name = "FDSEject"; keySeq = ""; title = "Eject FDS Disk";
|
|
break;
|
|
case HK_VS_INSERT_COIN:
|
|
name = "VSInsertCoin"; keySeq = ""; title = "VS Insert Coin";
|
|
break;
|
|
case HK_VS_TOGGLE_DIPSWITCH:
|
|
name = "VSToggleDip"; keySeq = ""; title = "VS Toggle Dipswitch";
|
|
break;
|
|
case HK_TOGGLE_FRAME_DISPLAY:
|
|
name = "MovieToggleFrameDisplay"; keySeq = "."; title = "Toggle Frame Display";
|
|
break;
|
|
case HK_TOGGLE_SUBTITLE:
|
|
name = "SubtitleDisplay"; keySeq = ""; title = "Toggle Movie Subtitles";
|
|
break;
|
|
case HK_POWER:
|
|
name = "Power"; keySeq = ""; title = "Power";
|
|
break;
|
|
case HK_RESET:
|
|
name = "Reset"; keySeq = "Ctrl+R"; title = "Reset";
|
|
break;
|
|
case HK_PAUSE:
|
|
name = "Pause"; keySeq = "Pause"; title = "Pause";
|
|
break;
|
|
case HK_QUIT:
|
|
name = "Quit"; keySeq = "Ctrl+Q"; title = "Exit Application";
|
|
break;
|
|
case HK_SCREENSHOT:
|
|
name = "Screenshot"; keySeq = "F12";
|
|
break;
|
|
case HK_DECREASE_SPEED:
|
|
name = "DecreaseSpeed"; keySeq = "-";
|
|
break;
|
|
case HK_INCREASE_SPEED:
|
|
name = "IncreaseSpeed"; keySeq = "=";
|
|
break;
|
|
case HK_FRAME_ADVANCE:
|
|
name = "FrameAdvance"; keySeq = "\\";
|
|
break;
|
|
case HK_TURBO:
|
|
name = "Turbo"; keySeq = "Tab";
|
|
break;
|
|
case HK_TOGGLE_INPUT_DISPLAY:
|
|
name = "ToggleInputDisplay"; keySeq = ",";
|
|
break;
|
|
case HK_MOVIE_TOGGLE_RW:
|
|
name = "ToggleMovieRW"; keySeq = "Q";
|
|
break;
|
|
case HK_PLAY_MOVIE_FROM:
|
|
name = "PlayMovieFrom"; keySeq = "";
|
|
break;
|
|
case HK_MOVIE_PLAY_RESTART:
|
|
name = "PlayMovieFromBeginning"; keySeq = "";
|
|
break;
|
|
case HK_RECORD_MOVIE_TO:
|
|
name = "RecordMovieTo"; keySeq = "";
|
|
break;
|
|
case HK_STOP_MOVIE:
|
|
name = "StopMovie"; keySeq = "";
|
|
break;
|
|
case HK_RECORD_AVI:
|
|
name = "RecordAvi"; keySeq = "";
|
|
break;
|
|
case HK_RECORD_AVI_TO:
|
|
name = "RecordAviTo"; keySeq = "";
|
|
break;
|
|
case HK_STOP_AVI:
|
|
name = "StopAvi"; keySeq = "";
|
|
break;
|
|
case HK_RECORD_WAV:
|
|
name = "RecordWav"; keySeq = "";
|
|
break;
|
|
case HK_RECORD_WAV_TO:
|
|
name = "RecordWavTo"; keySeq = "";
|
|
break;
|
|
case HK_STOP_WAV:
|
|
name = "StopWav"; keySeq = "";
|
|
break;
|
|
case HK_MUTE_CAPTURE:
|
|
name = "MuteCapture"; keySeq = "'";
|
|
break;
|
|
case HK_FA_LAG_SKIP:
|
|
name = "FrameAdvanceLagSkip"; keySeq = "Delete";
|
|
break;
|
|
case HK_LAG_COUNTER_DISPLAY:
|
|
name = "LagCounterDisplay"; keySeq = "/";
|
|
break;
|
|
case HK_SELECT_STATE_0:
|
|
name = "SelectState0"; keySeq = "0"; title = "Select State Slot 0";
|
|
break;
|
|
case HK_SELECT_STATE_1:
|
|
name = "SelectState1"; keySeq = "1"; title = "Select State Slot 1";
|
|
break;
|
|
case HK_SELECT_STATE_2:
|
|
name = "SelectState2"; keySeq = "2"; title = "Select State Slot 2";
|
|
break;
|
|
case HK_SELECT_STATE_3:
|
|
name = "SelectState3"; keySeq = "3"; title = "Select State Slot 3";
|
|
break;
|
|
case HK_SELECT_STATE_4:
|
|
name = "SelectState4"; keySeq = "4"; title = "Select State Slot 4";
|
|
break;
|
|
case HK_SELECT_STATE_5:
|
|
name = "SelectState5"; keySeq = "5"; title = "Select State Slot 5";
|
|
break;
|
|
case HK_SELECT_STATE_6:
|
|
name = "SelectState6"; keySeq = "6"; title = "Select State Slot 6";
|
|
break;
|
|
case HK_SELECT_STATE_7:
|
|
name = "SelectState7"; keySeq = "7"; title = "Select State Slot 7";
|
|
break;
|
|
case HK_SELECT_STATE_8:
|
|
name = "SelectState8"; keySeq = "8"; title = "Select State Slot 8";
|
|
break;
|
|
case HK_SELECT_STATE_9:
|
|
name = "SelectState9"; keySeq = "9"; title = "Select State Slot 9";
|
|
break;
|
|
case HK_SELECT_STATE_NEXT:
|
|
name = "SelectStateNext"; keySeq = ""; title = "Select Next State Slot";
|
|
break;
|
|
case HK_SELECT_STATE_PREV:
|
|
name = "SelectStatePrev"; keySeq = ""; title = "Select Previous State Slot";
|
|
break;
|
|
case HK_VOLUME_DOWN:
|
|
name = "VolumeDown"; keySeq = "";
|
|
break;
|
|
case HK_VOLUME_UP:
|
|
name = "VolumeUp"; keySeq = "";
|
|
break;
|
|
case HK_FKB_ENABLE:
|
|
name = "FKB_Enable"; keySeq = "ScrollLock"; title = "Toggle Family Keyboard Enable";
|
|
break;
|
|
case HK_FULLSCREEN:
|
|
name = "FullScreen"; keySeq = "Alt+Return"; title = "Toggle Fullscreen View";
|
|
break;
|
|
case HK_MAIN_MENU_HIDE:
|
|
name = "MainMenuHide"; keySeq = "Alt+/"; title = "Toggle Main Menu Visibility";
|
|
break;
|
|
default:
|
|
case HK_MAX:
|
|
name = ""; keySeq = "";
|
|
break;
|
|
|
|
}
|
|
|
|
if ( nameOut )
|
|
{
|
|
*nameOut = name;
|
|
}
|
|
if ( keySeqOut )
|
|
{
|
|
*keySeqOut = keySeq;
|
|
}
|
|
if ( titleOut )
|
|
{
|
|
if ( title == NULL )
|
|
{
|
|
title = name;
|
|
}
|
|
*titleOut = title;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Read a custom pallete from a file and load it into the core.
|
|
*/
|
|
int
|
|
LoadCPalette(const std::string &file)
|
|
{
|
|
uint8 tmpp[192];
|
|
FILE *fp;
|
|
|
|
if(!(fp = FCEUD_UTF8fopen(file.c_str(), "rb"))) {
|
|
char errorMsg[256];
|
|
strcpy(errorMsg, "Error loading custom palette from file: ");
|
|
strcat(errorMsg, file.c_str());
|
|
FCEUD_PrintError(errorMsg);
|
|
return 0;
|
|
}
|
|
size_t result = fread(tmpp, 1, 192, fp);
|
|
if(result != 192) {
|
|
char errorMsg[256];
|
|
strcpy(errorMsg, "Error loading custom palette from file: ");
|
|
strcat(errorMsg, file.c_str());
|
|
FCEUD_PrintError(errorMsg);
|
|
return 0;
|
|
}
|
|
FCEUI_SetUserPalette(tmpp, result/3);
|
|
fclose(fp);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Creates the subdirectories used for saving snapshots, movies, game
|
|
* saves, etc. Hopefully obsolete with new configuration system.
|
|
*/
|
|
static void
|
|
CreateDirs(const std::string &dir)
|
|
{
|
|
const char *subs[]={"fcs","snaps","gameinfo","sav","cheats","avi","wav","movies","input", NULL };
|
|
std::string subdir;
|
|
int x=0;
|
|
|
|
#if defined(WIN32) || defined(NEED_MINGW_HACKS)
|
|
mkdir(dir.c_str());
|
|
chmod(dir.c_str(), 755);
|
|
while ( subs[x] != NULL )
|
|
{
|
|
subdir = dir + PSS + subs[x];
|
|
mkdir(subdir.c_str());
|
|
x++;
|
|
}
|
|
#else
|
|
mkdir(dir.c_str(), S_IRWXU);
|
|
while ( subs[x] != NULL )
|
|
{
|
|
subdir = dir + PSS + subs[x];
|
|
mkdir(subdir.c_str(), S_IRWXU);
|
|
x++;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Attempts to locate FCEU's application directory. This will
|
|
* hopefully become obsolete once the new configuration system is in
|
|
* place.
|
|
*/
|
|
static void
|
|
GetBaseDirectory(std::string &dir)
|
|
{
|
|
char *home = getenv("FCEUX_HOME");
|
|
|
|
#ifdef WIN32
|
|
// Windows users want base directory to be where executable resides.
|
|
// Only way to override this behavior is to set an FCEUX_HOME
|
|
// environment variable prior to starting the application.
|
|
//if ( home == NULL )
|
|
//{
|
|
// home = getenv("USERPROFILE");
|
|
//}
|
|
//if ( home == NULL )
|
|
//{
|
|
// home = getenv("HOMEPATH");
|
|
//}
|
|
#else
|
|
if ( home == NULL )
|
|
{
|
|
home = getenv("HOME");
|
|
}
|
|
#endif
|
|
|
|
if (home)
|
|
{
|
|
dir = std::string(home) + "/.fceux";
|
|
} else {
|
|
#ifdef WIN32
|
|
home = new char[MAX_PATH + 1];
|
|
GetModuleFileNameA(NULL, home, MAX_PATH + 1);
|
|
|
|
char *lastBS = strrchr(home,'\\');
|
|
if(lastBS) {
|
|
*lastBS = 0;
|
|
}
|
|
|
|
dir = std::string(home);
|
|
delete[] home;
|
|
#else
|
|
dir = "";
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// returns a config structure with default options
|
|
// also creates config base directory (ie: /home/user/.fceux as well as subdirs
|
|
Config *
|
|
InitConfig()
|
|
{
|
|
std::string dir, prefix, savPath, movPath;
|
|
Config *config;
|
|
|
|
GetBaseDirectory(dir);
|
|
|
|
FCEUI_SetBaseDirectory(dir.c_str());
|
|
CreateDirs(dir);
|
|
|
|
config = new Config(dir);
|
|
|
|
// sound options
|
|
config->addOption('s', "sound", "SDL.Sound", 1);
|
|
config->addOption("volume", "SDL.Sound.Volume", 150);
|
|
config->addOption("trianglevol", "SDL.Sound.TriangleVolume", 255);
|
|
config->addOption("square1vol", "SDL.Sound.Square1Volume", 255);
|
|
config->addOption("square2vol", "SDL.Sound.Square2Volume", 255);
|
|
config->addOption("noisevol", "SDL.Sound.NoiseVolume", 255);
|
|
config->addOption("pcmvol", "SDL.Sound.PCMVolume", 255);
|
|
config->addOption("soundrate", "SDL.Sound.Rate", 44100);
|
|
config->addOption("soundq", "SDL.Sound.Quality", 1);
|
|
config->addOption("soundrecord", "SDL.Sound.RecordFile", "");
|
|
config->addOption("soundbufsize", "SDL.Sound.BufSize", 128);
|
|
config->addOption("lowpass", "SDL.Sound.LowPass", 0);
|
|
|
|
config->addOption('g', "gamegenie", "SDL.GameGenie", 0);
|
|
config->addOption("pal", "SDL.PAL", 0);
|
|
config->addOption("autoPal", "SDL.AutoDetectPAL", 1);
|
|
config->addOption("frameskip", "SDL.Frameskip", 0);
|
|
config->addOption("clipsides", "SDL.ClipSides", 0);
|
|
config->addOption("nospritelim", "SDL.DisableSpriteLimit", 1);
|
|
config->addOption("swapduty", "SDL.SwapDuty", 0);
|
|
config->addOption("ramInit", "SDL.RamInitMethod", 0);
|
|
|
|
// color control
|
|
config->addOption('p', "palette", "SDL.Palette", "");
|
|
config->addOption("tint", "SDL.Tint", 56);
|
|
config->addOption("hue", "SDL.Hue", 72);
|
|
config->addOption("ntsccolor", "SDL.NTSCpalette", 0);
|
|
config->addOption("SDL.ForceGrayScale", 0);
|
|
config->addOption("SDL.DeempBitSwap", 0);
|
|
config->addOption("SDL.PalNotch", 100);
|
|
config->addOption("SDL.PalSaturation", 100);
|
|
config->addOption("SDL.PalSharpness", 0);
|
|
config->addOption("SDL.PalContrast", 100);
|
|
config->addOption("SDL.PalBrightness", 50);
|
|
|
|
// scanline settings
|
|
config->addOption("SDL.ScanLineStartNTSC", 0+8);
|
|
config->addOption("SDL.ScanLineEndNTSC", 239-8);
|
|
config->addOption("SDL.ScanLineStartPAL", 0);
|
|
config->addOption("SDL.ScanLineEndPAL", 239);
|
|
|
|
// video controls
|
|
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
|
|
config->addOption("videoDriver", "SDL.VideoDriver", 0);
|
|
|
|
// set x/y res to 0 for automatic fullscreen resolution detection (no change)
|
|
config->addOption('x', "xres", "SDL.XResolution", 0);
|
|
config->addOption('y', "yres", "SDL.YResolution", 0);
|
|
config->addOption("SDL.LastXRes", 0);
|
|
config->addOption("SDL.LastYRes", 0);
|
|
config->addOption("SDL.WinSizeX", 0);
|
|
config->addOption("SDL.WinSizeY", 0);
|
|
config->addOption("doublebuf", "SDL.DoubleBuffering", 1);
|
|
config->addOption("autoscale", "SDL.AutoScale", 1);
|
|
config->addOption("forceAspect", "SDL.ForceAspect", 1);
|
|
config->addOption("aspectSelect", "SDL.AspectSelect", 0);
|
|
config->addOption("aspectX", "SDL.AspectX", 1.000);
|
|
config->addOption("aspectY", "SDL.AspectY", 1.000);
|
|
config->addOption("xscale", "SDL.XScale", 2.000);
|
|
config->addOption("yscale", "SDL.YScale", 2.000);
|
|
config->addOption("xstretch", "SDL.XStretch", 0);
|
|
config->addOption("ystretch", "SDL.YStretch", 0);
|
|
config->addOption("noframe", "SDL.NoFrame", 0);
|
|
config->addOption("special", "SDL.SpecialFilter", 0);
|
|
config->addOption("showfps", "SDL.ShowFPS", 0);
|
|
config->addOption("togglemenu", "SDL.ToggleMenu", 0);
|
|
config->addOption("cursorType", "SDL.CursorType", 0);
|
|
config->addOption("cursorVis" , "SDL.CursorVis", 1);
|
|
config->addOption("SDL.DrawInputAids", 1);
|
|
|
|
// OpenGL options
|
|
config->addOption("opengl", "SDL.OpenGL", 1);
|
|
config->addOption("openglip", "SDL.OpenGLip", 0);
|
|
config->addOption("SDL.SpecialFilter", 0);
|
|
config->addOption("SDL.SpecialFX", 0);
|
|
config->addOption("SDL.Vsync", 1);
|
|
|
|
// network play options - netplay is broken
|
|
config->addOption("server", "SDL.NetworkIsServer", 0);
|
|
config->addOption('n', "net", "SDL.NetworkIP", "");
|
|
config->addOption('u', "user", "SDL.NetworkUsername", "");
|
|
config->addOption('w', "pass", "SDL.NetworkPassword", "");
|
|
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
|
config->addOption("port", "SDL.NetworkPort", 4046);
|
|
config->addOption("players", "SDL.NetworkPlayers", 1);
|
|
|
|
// input configuration options
|
|
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
|
config->addOption("input2", "SDL.Input.1", "GamePad.1");
|
|
config->addOption("input3", "SDL.Input.2", "Gamepad.2");
|
|
config->addOption("input4", "SDL.Input.3", "Gamepad.3");
|
|
|
|
config->addOption("autoInputPreset", "SDL.AutoInputPreset", 0);
|
|
config->addOption("SDL.AutofireOnFrames" , 1);
|
|
config->addOption("SDL.AutofireOffFrames", 1);
|
|
config->addOption("SDL.AutofireCustomOnFrames" , 1);
|
|
config->addOption("SDL.AutofireCustomOffFrames", 1);
|
|
|
|
// display input
|
|
config->addOption("inputdisplay", "SDL.InputDisplay", 0);
|
|
|
|
// enable / disable opposite directionals (left + right or up + down simultaneously)
|
|
config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1);
|
|
|
|
// pause movie playback at frame x
|
|
config->addOption("pauseframe", "SDL.PauseFrame", 0);
|
|
config->addOption("recordhud", "SDL.RecordHUD", 1);
|
|
config->addOption("moviemsg", "SDL.MovieMsg", 1);
|
|
config->addOption("SDL.AviVideoFormat", 0);
|
|
|
|
// Hex Editor Options
|
|
config->addOption("hexEditBgColor", "SDL.HexEditBgColor", "#000000");
|
|
config->addOption("hexEditFgColor", "SDL.HexEditFgColor", "#FFFFFF");
|
|
config->addOption("SDL.HexEditCursorColorRC", "#000080");
|
|
config->addOption("SDL.HexEditAltColColor" , "#545454");
|
|
config->addOption("SDL.HexEditFont" , "");
|
|
config->addOption("SDL.HexEditActivityHlgt", true);
|
|
config->addOption("SDL.HexEditReverseVideo", true);
|
|
config->addOption("SDL.HexEditRowColumnHlgt", false);
|
|
config->addOption("SDL.HexEditAltnColumnColor", false);
|
|
config->addOption("SDL.HexEditRefreshRate", 10);
|
|
|
|
// Debugger Options
|
|
config->addOption("autoLoadDebugFiles" , "SDL.AutoLoadDebugFiles", 1);
|
|
config->addOption("autoOpenDebugger" , "SDL.AutoOpenDebugger" , 0);
|
|
config->addOption("debuggerPCPlacementMode", "SDL.DebuggerPCPlacement" , 0);
|
|
config->addOption("debuggerPCDLineOffset" , "SDL.DebuggerPCLineOffset" , 0);
|
|
config->addOption("SDL.DebuggerAsmFont" , "");
|
|
config->addOption("SDL.DebuggerStackFont" , "");
|
|
config->addOption("SDL.DebuggerCpuStatusFont" , "");
|
|
config->addOption("SDL.AsmSyntaxColorOpcode", "");
|
|
config->addOption("SDL.AsmSyntaxColorAddress", "");
|
|
config->addOption("SDL.AsmSyntaxColorImmediate", "");
|
|
config->addOption("SDL.AsmSyntaxColorLabel", "");
|
|
config->addOption("SDL.AsmSyntaxColorComment", "");
|
|
config->addOption("SDL.AsmSyntaxColorPC", "");
|
|
config->addOption("SDL.AsmShowByteCodes", 0);
|
|
config->addOption("SDL.AsmShowRomOffsets", 0);
|
|
config->addOption("SDL.DebuggerShowSymNames", 1);
|
|
config->addOption("SDL.DebuggerShowRegNames", 1);
|
|
config->addOption("SDL.DebuggerBreakOnBadOpcodes", 0);
|
|
config->addOption("SDL.DebuggerBreakOnUnloggedCode", 0);
|
|
config->addOption("SDL.DebuggerBreakOnUnloggedData", 0);
|
|
|
|
// Code Data Logger Options
|
|
config->addOption("autoSaveCDL" , "SDL.AutoSaveCDL", 1);
|
|
config->addOption("autoLoadCDL" , "SDL.AutoLoadCDL", 1);
|
|
config->addOption("autoResumeCDL", "SDL.AutoResumeCDL", 0);
|
|
|
|
// Trace Logger Options
|
|
config->addOption("SDL.TraceLogRegisterState", 1);
|
|
config->addOption("SDL.TraceLogProcessorState", 1);
|
|
config->addOption("SDL.TraceLogNewInstructions", 0);
|
|
config->addOption("SDL.TraceLogNewData", 0);
|
|
config->addOption("SDL.TraceLogFrameCount", 0);
|
|
config->addOption("SDL.TraceLogCycleCount", 0);
|
|
config->addOption("SDL.TraceLogInstructionCount", 0);
|
|
config->addOption("SDL.TraceLogMessages", 1);
|
|
config->addOption("SDL.TraceLogBreakpointHits", 1);
|
|
config->addOption("SDL.TraceLogBankNumber", 0);
|
|
config->addOption("SDL.TraceLogSymbolic", 0);
|
|
config->addOption("SDL.TraceLogStackTabbing", 1);
|
|
config->addOption("SDL.TraceLogLeftDisassembly", 1);
|
|
|
|
// overwrite the config file?
|
|
config->addOption("no-config", "SDL.NoConfig", 0);
|
|
|
|
config->addOption("autoresume", "SDL.AutoResume", 0);
|
|
|
|
// video playback
|
|
config->addOption("playmov", "SDL.Movie", "");
|
|
config->addOption("subtitles", "SDL.SubtitleDisplay", 1);
|
|
config->addOption("movielength", "SDL.MovieLength", 0);
|
|
|
|
config->addOption("fourscore", "SDL.FourScore", 0);
|
|
|
|
config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1);
|
|
|
|
#ifdef _S9XLUA_H
|
|
// load lua script
|
|
config->addOption("loadlua", "SDL.LuaScript", "");
|
|
#endif
|
|
|
|
#ifdef CREATE_AVI
|
|
config->addOption("videolog", "SDL.VideoLog", "");
|
|
config->addOption("mute", "SDL.MuteCapture", 0);
|
|
#endif
|
|
|
|
// auto load/save on gameload/close
|
|
config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE);
|
|
config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE);
|
|
|
|
//TODO implement this
|
|
config->addOption("periodicsaves", "SDL.PeriodicSaves", 0);
|
|
|
|
savPath = dir + "/sav";
|
|
movPath = dir + "/movies";
|
|
|
|
// prefixed with _ because they are internal (not cli options)
|
|
config->addOption("_lastopenfile", "SDL.LastOpenFile", dir);
|
|
config->addOption("_laststatefrom", "SDL.LastLoadStateFrom", savPath );
|
|
config->addOption("_lastopennsf", "SDL.LastOpenNSF", dir);
|
|
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", savPath );
|
|
config->addOption("_lastopenmovie", "SDL.LastOpenMovie", movPath);
|
|
config->addOption("_lastloadlua", "SDL.LastLoadLua", "");
|
|
|
|
for (unsigned int i=0; i<10; i++)
|
|
{
|
|
char buf[128];
|
|
sprintf(buf, "SDL.RecentRom%02u", i);
|
|
|
|
config->addOption( buf, "");
|
|
}
|
|
|
|
config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false);
|
|
config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false);
|
|
config->addOption("SDL.PauseOnMainMenuAccess", false);
|
|
config->addOption("SDL.ContextMenuEnable", true);
|
|
config->addOption("SDL.GuiStyle", "");
|
|
config->addOption("SDL.QtStyleSheet", "");
|
|
config->addOption("SDL.QPaletteFile", "");
|
|
config->addOption("SDL.UseCustomQss", 0);
|
|
config->addOption("SDL.UseCustomQPal", 0);
|
|
|
|
config->addOption("_setSchedParam" , "SDL.SetSchedParam" , 0);
|
|
config->addOption("_emuSchedPolicy" , "SDL.EmuSchedPolicy", 0);
|
|
config->addOption("_emuSchedNice" , "SDL.EmuSchedNice" , 0);
|
|
config->addOption("_emuSchedPrioRt" , "SDL.EmuSchedPrioRt", 40);
|
|
config->addOption("_guiSchedPolicy" , "SDL.GuiSchedPolicy", 0);
|
|
config->addOption("_guiSchedNice" , "SDL.GuiSchedNice" , 0);
|
|
config->addOption("_guiSchedPrioRt" , "SDL.GuiSchedPrioRt", 40);
|
|
config->addOption("_emuTimingMech" , "SDL.EmuTimingMech" , 0);
|
|
|
|
// fcm -> fm2 conversion
|
|
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
|
|
|
// fm2 -> srt conversion
|
|
config->addOption("ripsubs", "SDL.RipSubs", "");
|
|
|
|
// enable new PPU core
|
|
config->addOption("newppu", "SDL.NewPPU", 0);
|
|
|
|
// PPU Viewer Preferences
|
|
config->addOption("SDL.NT_TileFocusPolicy", 0);
|
|
config->addOption("SDL.PPU_TileFocusPolicy", 0);
|
|
config->addOption("SDL.OAM_TileFocusPolicy", 0);
|
|
config->addOption("SDL.PPU_MaskUnused", 0);
|
|
config->addOption("SDL.PPU_InvertMask", 0);
|
|
config->addOption("SDL.PPU_View1_8x16", 0);
|
|
config->addOption("SDL.PPU_View2_8x16", 0);
|
|
config->addOption("SDL.PPU_ViewScanLine", 0);
|
|
config->addOption("SDL.PPU_ViewRefreshFrames", 1);
|
|
config->addOption("SDL.NT_TileSelColor", "#FFFFFF");
|
|
config->addOption("SDL.NT_TileGridColor", "#FF0000");
|
|
config->addOption("SDL.NT_AttrGridColor", "#0000FF");
|
|
config->addOption("SDL.NT_ViewScanLine", 0);
|
|
config->addOption("SDL.NT_DrawScrollLines", 1);
|
|
config->addOption("SDL.NT_DrawTileGridLines", 1);
|
|
config->addOption("SDL.NT_DrawAttrGridLines", 0);
|
|
config->addOption("SDL.NT_DrawAttrbView", 0);
|
|
config->addOption("SDL.NT_IgnoreHidePal", 0);
|
|
config->addOption("SDL.NT_RefreshFrames", 1);
|
|
config->addOption("SDL.PPU_TileSelColor0", "#FFFFFF");
|
|
config->addOption("SDL.PPU_TileGridColor0", "#7F7F7F");
|
|
config->addOption("SDL.PPU_TileSelColor1", "#FFFFFF");
|
|
config->addOption("SDL.PPU_TileGridColor1", "#7F7F7F");
|
|
config->addOption("SDL.PPU_TileShowGrid0", 1);
|
|
config->addOption("SDL.PPU_TileShowGrid1", 1);
|
|
config->addOption("SDL.OAM_TileShowGrid", 0);
|
|
config->addOption("SDL.OAM_TileSelColor", "#FFFFFF");
|
|
config->addOption("SDL.OAM_TileGridColor", "#7F7F7F");
|
|
config->addOption("SDL.OAM_LocatorColor", "#7F7F7F");
|
|
config->addOption("SDL.OAM_ShowPosHex", 0);
|
|
|
|
// quit when a+b+select+start is pressed
|
|
config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0);
|
|
|
|
// GamePad 0 - 3
|
|
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++)
|
|
{
|
|
char buf[64];
|
|
snprintf(buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i);
|
|
prefix = buf;
|
|
|
|
config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]);
|
|
config->addOption(prefix + "DeviceGUID", "");
|
|
config->addOption(prefix + "Profile" , "");
|
|
}
|
|
|
|
// PowerPad 0 - 1
|
|
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
|
|
char buf[64];
|
|
snprintf(buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i);
|
|
prefix = buf;
|
|
|
|
config->addOption(prefix + "DeviceType", DefaultPowerPadDevice[i]);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix +PowerPadNames[j], DefaultPowerPad[i][j]);
|
|
}
|
|
}
|
|
|
|
// QuizKing
|
|
prefix = "SDL.Input.QuizKing.";
|
|
config->addOption(prefix + "DeviceType", DefaultQuizKingDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + QuizKingNames[j], DefaultQuizKing[j]);
|
|
}
|
|
|
|
// HyperShot
|
|
prefix = "SDL.Input.HyperShot.";
|
|
config->addOption(prefix + "DeviceType", DefaultHyperShotDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + HyperShotNames[j], DefaultHyperShot[j]);
|
|
}
|
|
|
|
// Mahjong
|
|
prefix = "SDL.Input.Mahjong.";
|
|
config->addOption(prefix + "DeviceType", DefaultMahjongDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + MahjongNames[j], DefaultMahjong[j]);
|
|
}
|
|
|
|
// TopRider
|
|
prefix = "SDL.Input.TopRider.";
|
|
config->addOption(prefix + "DeviceType", DefaultTopRiderDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + TopRiderNames[j], DefaultTopRider[j]);
|
|
}
|
|
|
|
// FTrainer
|
|
prefix = "SDL.Input.FTrainer.";
|
|
config->addOption(prefix + "DeviceType", DefaultFTrainerDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + FTrainerNames[j], DefaultFTrainer[j]);
|
|
}
|
|
|
|
// FamilyKeyBoard
|
|
prefix = "SDL.Input.FamilyKeyBoard.";
|
|
config->addOption(prefix + "DeviceType", DefaultFamilyKeyBoardDevice);
|
|
config->addOption(prefix + "DeviceNum", 0);
|
|
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
|
|
config->addOption(prefix + FamilyKeyBoardNames[j],
|
|
DefaultFamilyKeyBoard[j]);
|
|
}
|
|
|
|
// for FAMICOM microphone in pad 2 pad 1 didn't have it
|
|
// Takeshi no Chousenjou uses it for example.
|
|
prefix = "SDL.Input.FamicomPad2.";
|
|
config->addOption("rp2mic", prefix + "EnableMic", 0);
|
|
|
|
// TODO: use a better data structure to store the hotkeys or something
|
|
// improve this code overall in the future to make it
|
|
// easier to maintain
|
|
//const int Hotkeys[HK_MAX] = {
|
|
// SDLK_F1, // cheat menu
|
|
// SDLK_F2, // bind state
|
|
// SDLK_F3, // load lua
|
|
// SDLK_F4, // toggleBG
|
|
// SDLK_F5, // save state
|
|
// SDLK_F6, // fds select
|
|
// SDLK_F7, // load state
|
|
// SDLK_F8, // fds eject
|
|
// SDLK_F6, // VS insert coin
|
|
// SDLK_F8, // VS toggle dipswitch
|
|
// SDLK_PERIOD, // toggle frame display
|
|
// SDLK_F10, // toggle subtitle
|
|
// SDLK_F11, // reset
|
|
// SDLK_F12, // screenshot
|
|
// SDLK_PAUSE, // pause
|
|
// SDLK_MINUS, // speed++
|
|
// SDLK_EQUALS, // speed--
|
|
// SDLK_BACKSLASH, //frame advnace
|
|
// SDLK_TAB, // turbo
|
|
// SDLK_COMMA, // toggle input display
|
|
// SDLK_q, // toggle movie RW
|
|
// SDLK_QUOTE, // toggle mute capture
|
|
// 0, // quit // edit 10/11/11 - don't map to escape, it causes ugly things to happen to sdl. can be manually appended to config
|
|
// SDLK_DELETE, // frame advance lag skip
|
|
// SDLK_SLASH, // lag counter display
|
|
// SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
|
|
// SDLK_6, SDLK_7, SDLK_8, SDLK_9,
|
|
// SDLK_PAGEUP, // select state next
|
|
// SDLK_PAGEDOWN, // select state prev
|
|
// 0, // Volume Down Internal
|
|
// 0, // Volume Up Internal
|
|
// SDLK_SCROLLLOCK }; // FKB Enable Toggle
|
|
|
|
|
|
//Hotkeys[ HK_OPEN_ROM ].init( "OpenROM", QKeySequence(QKeySequence::Open) );
|
|
|
|
prefix = "SDL.Hotkeys.";
|
|
|
|
for(int i=0; i < HK_MAX; i++)
|
|
{
|
|
const char *hotKeyName, *hotKeySeq;
|
|
std::string nameText, keyText;
|
|
|
|
getHotKeyConfig( i, &hotKeyName, &hotKeySeq );
|
|
|
|
//printf("Hot Key: '%s' = '%s' \n", hotKeyName, hotKeySeq );
|
|
|
|
//keyText.assign(" mod=");
|
|
|
|
//sprintf( buf, " key=%s", SDL_GetKeyName( Hotkeys[i] ) );
|
|
|
|
if ( hotKeyName[0] != 0 )
|
|
{
|
|
nameText.assign( hotKeyName );
|
|
keyText.assign( hotKeySeq );
|
|
|
|
config->addOption(prefix + nameText, keyText);
|
|
|
|
Hotkeys[i].setConfigName( hotKeyName );
|
|
}
|
|
}
|
|
// All mouse devices
|
|
config->addOption("SDL.OekaKids.0.DeviceType", "Mouse");
|
|
config->addOption("SDL.OekaKids.0.DeviceNum", 0);
|
|
|
|
config->addOption("SDL.Arkanoid.0.DeviceType", "Mouse");
|
|
config->addOption("SDL.Arkanoid.0.DeviceNum", 0);
|
|
|
|
config->addOption("SDL.Shadow.0.DeviceType", "Mouse");
|
|
config->addOption("SDL.Shadow.0.DeviceNum", 0);
|
|
|
|
config->addOption("SDL.Zapper.0.DeviceType", "Mouse");
|
|
config->addOption("SDL.Zapper.0.DeviceNum", 0);
|
|
|
|
return config;
|
|
}
|
|
|
|
void
|
|
UpdateEMUCore(Config *config)
|
|
{
|
|
int ntsccol, ntsctint, ntschue, flag, region;
|
|
int startNTSC, endNTSC, startPAL, endPAL;
|
|
std::string cpalette;
|
|
|
|
config->getOption("SDL.NTSCpalette", &ntsccol);
|
|
config->getOption("SDL.Tint", &ntsctint);
|
|
config->getOption("SDL.Hue", &ntschue);
|
|
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
|
|
|
|
config->getOption("SDL.ForceGrayScale", &force_grayscale);
|
|
config->getOption("SDL.DeempBitSwap" , &paldeemphswap);
|
|
config->getOption("SDL.PalNotch" , &palnotch);
|
|
config->getOption("SDL.PalSaturation" , &palsaturation);
|
|
config->getOption("SDL.PalSharpness" , &palsharpness);
|
|
config->getOption("SDL.PalContrast" , &palcontrast);
|
|
config->getOption("SDL.PalBrightness" , &palbrightness);
|
|
palupdate = 1;
|
|
|
|
config->getOption("SDL.Palette", &cpalette);
|
|
if(cpalette.size()) {
|
|
LoadCPalette(cpalette);
|
|
}
|
|
|
|
config->getOption("SDL.NewPPU", &newppu);
|
|
|
|
config->getOption("SDL.PAL", ®ion);
|
|
FCEUI_SetRegion(region);
|
|
|
|
config->getOption("SDL.GameGenie", &flag);
|
|
FCEUI_SetGameGenie(flag ? 1 : 0);
|
|
|
|
config->getOption("SDL.Sound.LowPass", &flag);
|
|
FCEUI_SetLowPass(flag ? 1 : 0);
|
|
|
|
config->getOption("SDL.DisableSpriteLimit", &flag);
|
|
FCEUI_DisableSpriteLimitation(flag ? 1 : 0);
|
|
|
|
config->getOption("SDL.ScanLineStartNTSC", &startNTSC);
|
|
config->getOption("SDL.ScanLineEndNTSC", &endNTSC);
|
|
config->getOption("SDL.ScanLineStartPAL", &startPAL);
|
|
config->getOption("SDL.ScanLineEndPAL", &endPAL);
|
|
|
|
#if DOING_SCANLINE_CHECKS
|
|
for(int i = 0; i < 2; x++) {
|
|
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
|
|
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
|
|
}
|
|
#endif
|
|
|
|
FCEUI_SetRenderedLines(startNTSC, endNTSC, startPAL, endPAL);
|
|
}
|
|
|