visualboyadvance-m/src/common/ConfigManager.cpp

1350 lines
34 KiB
C++

// necessary to get portable strerror_r
#undef _GNU_SOURCE
#include <string.h>
#define _GNU_SOURCE 1
#include "ConfigManager.h"
extern "C" {
#include "../common/iniparser.h"
}
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <cmath>
#include "../common/Patch.h"
#include "../common/ConfigManager.h"
#include "../gba/GBA.h"
#include "../gba/agbprint.h"
#include "../gba/Flash.h"
#include "../gba/Cheats.h"
#include "../gba/remote.h"
#include "../gba/RTC.h"
#include "../gba/Sound.h"
#include "../gb/gb.h"
#include "../gb/gbGlobals.h"
#include "../gb/gbCheats.h"
#include "../gb/gbSound.h"
#include "../Util.h"
#ifndef _WIN32
#define GETCWD getcwd
#else // _WIN32
#include <direct.h>
#define GETCWD _getcwd
#define snprintf sprintf
#endif // _WIN32
#ifndef __GNUC__
#define HAVE_DECL_GETOPT 0
#define __STDC__ 1
#include "getopt.h"
#else // ! __GNUC__
#define HAVE_DECL_GETOPT 1
#include <getopt.h>
#endif // ! __GNUC__
#include <string>
#include <sstream>
enum named_opts
{
OPT_AGB_PRINT = 1000,
OPT_AUTOFIRE,
OPT_AUTO_FRAME_SKIP,
OPT_AVI_RECORD_DIR,
OPT_BATTERY_DIR,
OPT_BIOS_FILE_NAME_GB,
OPT_BIOS_FILE_NAME_GBA,
OPT_BIOS_FILE_NAME_GBC,
OPT_CAPTURE_FORMAT,
OPT_CHEAT,
OPT_CPU_SAVE_TYPE,
OPT_DOTCODE_FILE_NAME_LOAD,
OPT_DOTCODE_FILE_NAME_SAVE,
OPT_EMULATOR_TYPE,
OPT_FS_ADAPTER,
OPT_FS_COLOR_DEPTH,
OPT_FS_FREQUENCY,
OPT_FS_HEIGHT,
OPT_FS_WIDTH,
OPT_GB_EMULATOR_TYPE,
OPT_GB_FRAME_SKIP,
OPT_GB_PALETTE_OPTION,
OPT_GDB_PORT,
OPT_GL_FILTER,
OPT_IFB_TYPE,
OPT_JOYPAD_DEFAULT,
OPT_LANGUAGE_OPTION,
OPT_LINK_AUTO,
OPT_LINK_HACKS,
OPT_LINK_HOST_ADDR,
OPT_LINK_MODE,
OPT_LINK_NUM_PLAYERS,
OPT_LINK_TIMEOUT,
OPT_MAX_SCALE,
OPT_MOVIE_RECORD_DIR,
OPT_OPT_FLASH_SIZE,
OPT_REWIND_TIMER,
OPT_ROM_DIR_GB,
OPT_ROM_DIR_GBA,
OPT_ROM_DIR_GBC,
OPT_RTC_ENABLED,
OPT_SAVE_DIR,
OPT_SCREEN_SHOT_DIR,
OPT_SHOW_SPEED,
OPT_SHOW_SPEED_TRANSPARENT,
OPT_SOUND_FILTERING,
OPT_SOUND_RECORD_DIR,
OPT_SYNCHRONIZE,
OPT_THREAD_PRIORITY,
OPT_VIDEO_OPTION,
OPT_WINDOW_POSITION_X,
OPT_WINDOW_POSITION_Y
};
#define SOUND_MAX_VOLUME 2.0
#define SOUND_ECHO 0.2
#define SOUND_STEREO 0.15
#define REWIND_NUM 8
#define REWIND_SIZE 400000
char path[2048];
dictionary* preferences;
bool cpuIsMultiBoot = false;
bool mirroringEnable = true;
bool parseDebug = true;
bool speedHack = false;
bool speedup = false;
const char* aviRecordDir;
const char* batteryDir;
const char* biosFileNameGB;
const char* biosFileNameGBA;
const char* biosFileNameGBC;
const char* loadDotCodeFile;
const char* saveDotCodeFile;
const char* linkHostAddr;
const char* movieRecordDir;
char* rewindMemory = NULL;
const char* romDirGB;
const char* romDirGBA;
const char* romDirGBC;
const char* saveDir;
const char* screenShotDir;
const char* soundRecordDir;
int active = 1;
int agbPrint;
int autoFire;
int autoFireMaxCount = 1;
int autoFireToggle;
int autoFrameSkip = 0;
int autoLoadMostRecent;
int autoPatch;
int autoSaveLoadCheatList;
int aviRecording;
int captureFormat = 0;
int cheatsEnabled = true;
int cpuDisableSfx = false;
int cpuSaveType = 0;
int disableMMX;
int disableStatusMessages = 0;
int dsoundDisableHardwareAcceleration;
int filterHeight;
int filterMagnification;
int filterMT; // enable multi-threading for pixel filters
int filter = kStretch2x;
int filterWidth;
int frameSkip = 1;
int frameskipadjust;
int fsAdapter;
int fsColorDepth;
int fsForceChange;
int fsFrequency;
int fsHeight;
int fsWidth;
int fullScreen;
int fullScreenStretch;
int gdbBreakOnLoad;
int gdbPort;
int glFilter;
int ifbType = kIFBNone;
int joypadDefault;
int languageOption;
int layerEnable = 0xff00;
int layerSettings = 0xff00;
int linkAuto;
int linkHacks = 1;
int linkMode;
int linkNumPlayers;
int linkTimeout = 1;
int maxScale;
int mouseCounter = 0;
int movieFrame;
int moviePlayFrame;
int moviePlaying;
int movieRecording;
int openGL;
int optFlashSize;
int optPrintUsage;
int paused;
int pauseWhenInactive = 0;
int preparedCheats = 0;
int recentFreeze;
int renderedFrames;
int rewindCount;
int rewindCounter;
int rewindPos;
int rewindSaveNeeded = 0;
int rewindTimer = 0;
int rewindTopPos;
int rtcEnabled;
int saveType = 0;
int screenMessage;
int sensorX;
int sensorY;
int showRenderedFrames;
int showSpeed;
int showSpeedTransparent;
int sizeX;
int sizeY;
int skipBios = 0;
int skipSaveGameBattery = false;
int skipSaveGameCheats = false;
int soundRecording;
int speedupToggle;
int sunBars;
int surfaceSizeX;
int surfaceSizeY;
int threadPriority;
int tripleBuffering;
int useBios = 0;
int useBiosFileGB;
int useBiosFileGBA;
int useBiosFileGBC;
int videoOption;
int vsync;
int wasPaused = 0;
int windowPositionX;
int windowPositionY;
int winFlashSize;
int winGbBorderOn;
int winGbPrinterEnabled;
int winPauseNextFrame;
int* rewindSerials = NULL;
uint32_t autoFrameSkipLastTime;
uint32_t movieLastJoypad;
uint32_t movieNextJoypad;
int throttle;
const char* preparedCheatCodes[MAX_CHEATS];
FilterFunc filterFunction = 0;
IFBFilterFunc ifbFunction = 0;
// allow up to 100 IPS/UPS/PPF patches given on commandline
int patchNum = 0;
char *(patchNames[PATCH_MAX_NUM]) = { NULL }; // and so on
void(*dbgMain)() = remoteStubMain;
void(*dbgSignal)(int, int) = remoteStubSignal;
void(*dbgOutput)(const char *, uint32_t) = debuggerOutput;
char* homeDir = NULL;
char* arg0 = NULL;
struct option argOptions[] = {
{ "agb-print", required_argument, 0, OPT_AGB_PRINT },
{ "auto-frame-skip", required_argument, 0, OPT_AUTO_FRAME_SKIP },
{ "auto-load-most-recent", no_argument, &autoLoadMostRecent, 1 },
{ "auto-patch", no_argument, &autoPatch, 1 },
{ "auto-save-cheat-list", no_argument, &autoSaveLoadCheatList, 1 },
{ "auto-save-load-cheat-list", no_argument, &autoSaveLoadCheatList, 1 },
{ "autofire", required_argument, 0, OPT_AUTOFIRE },
{ "avi-record-dir", required_argument, 0, OPT_AVI_RECORD_DIR },
{ "battery-dir", required_argument, 0, OPT_BATTERY_DIR },
{ "bios", required_argument, 0, 'b' },
{ "bios-file-name-gb", required_argument, 0, OPT_BIOS_FILE_NAME_GB },
{ "bios-file-name-gba", required_argument, 0, OPT_BIOS_FILE_NAME_GBA },
{ "bios-file-name-gbc", required_argument, 0, OPT_BIOS_FILE_NAME_GBC },
{ "border-automatic", no_argument, &gbBorderAutomatic, 1 },
{ "border-on", no_argument, &gbBorderOn, 1 },
{ "capture-format", required_argument, 0, OPT_CAPTURE_FORMAT },
{ "cheat", required_argument, 0, OPT_CHEAT },
{ "cheats-enabled", no_argument, &cheatsEnabled, 1 },
{ "color-option", no_argument, &gbColorOption, 1 },
{ "config", required_argument, 0, 'c' },
{ "cpu-disable-sfx", no_argument, &cpuDisableSfx, 1 },
{ "cpu-save-type", required_argument, 0, OPT_CPU_SAVE_TYPE },
{ "debug", no_argument, 0, 'd' },
{ "disable-mmx", no_argument, &disableMMX, 1 },
{ "disable-sfx", no_argument, &cpuDisableSfx, 1 },
{ "disable-status-messages", no_argument, &disableStatusMessages, 1 },
{ "dotcode-file-name-load", required_argument, 0, OPT_DOTCODE_FILE_NAME_LOAD },
{ "dotcode-file-name-save", required_argument, 0, OPT_DOTCODE_FILE_NAME_SAVE },
{ "emulator-type", required_argument, 0, OPT_EMULATOR_TYPE },
{ "filter", required_argument, 0, 'f' },
{ "filter-enable-multi-threading", no_argument, &filterMT, 1 },
{ "filter-mt", no_argument, &filterMT, 1 },
{ "flash-128k", no_argument, &optFlashSize, 1 },
{ "flash-64k", no_argument, &optFlashSize, 0 },
{ "flash-size", required_argument, 0, 'S' },
{ "frameskip", required_argument, 0, 's' },
{ "fs-adapter", required_argument, 0, OPT_FS_ADAPTER },
{ "fs-color-depth", required_argument, 0, OPT_FS_COLOR_DEPTH },
{ "fs-frequency", required_argument, 0, OPT_FS_FREQUENCY },
{ "fs-height", required_argument, 0, OPT_FS_HEIGHT },
{ "fs-width", required_argument, 0, OPT_FS_WIDTH },
{ "full-screen", no_argument, &fullScreen, 1 },
{ "full-screen-stretch", no_argument, &fullScreenStretch, 1 },
{ "gb-border-automatic", no_argument, &gbBorderAutomatic, 1 },
{ "gb-border-on", no_argument, &gbBorderOn, 1 },
{ "gb-color-option", no_argument, &gbColorOption, 1 },
{ "gb-emulator-type", required_argument, 0, OPT_GB_EMULATOR_TYPE },
{ "gb-frame-skip", required_argument, 0, OPT_GB_FRAME_SKIP },
{ "gb-palette-option", required_argument, 0, OPT_GB_PALETTE_OPTION },
{ "gb-printer", no_argument, &winGbPrinterEnabled, 1 },
{ "gdb", required_argument, 0, 'G' },
{ "gdb-break-on-load", no_argument, &gdbBreakOnLoad, 1 },
{ "gdb-port", required_argument, 0, OPT_GDB_PORT },
{ "gl-filter", required_argument, 0, OPT_GL_FILTER },
{ "help", no_argument, &optPrintUsage, 1 },
{ "ifb-filter", required_argument, 0, 'I' },
{ "ifb-type", required_argument, 0, OPT_IFB_TYPE },
{ "joypad-default", required_argument, 0, OPT_JOYPAD_DEFAULT },
{ "language-option", required_argument, 0, OPT_LANGUAGE_OPTION },
{ "link-auto", required_argument, 0, OPT_LINK_AUTO },
{ "link-hacks", required_argument, 0, OPT_LINK_HACKS },
{ "link-host-addr", required_argument, 0, OPT_LINK_HOST_ADDR },
{ "link-mode", required_argument, 0, OPT_LINK_MODE },
{ "link-num-players", required_argument, 0, OPT_LINK_NUM_PLAYERS },
{ "link-timeout", required_argument, 0, OPT_LINK_TIMEOUT },
{ "max-scale", required_argument, 0, OPT_MAX_SCALE },
{ "movie-record-dir", required_argument, 0, OPT_MOVIE_RECORD_DIR },
{ "no-agb-print", no_argument, &agbPrint, 0 },
{ "no-auto-frameskip", no_argument, &autoFrameSkip, 0 },
{ "no-debug", no_argument, 0, 'N' },
{ "no-opengl", no_argument, &openGL, 0 },
{ "no-patch", no_argument, &autoPatch, 0 },
{ "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 },
{ "no-rtc", no_argument, &rtcEnabled, 0 },
{ "no-show-speed", no_argument, &showSpeed, 0 },
{ "opengl", required_argument, 0, 'O' },
{ "opengl-bilinear", no_argument, &openGL, 2 },
{ "opengl-nearest", no_argument, &openGL, 1 },
{ "opt-flash-size", required_argument, 0, OPT_OPT_FLASH_SIZE },
{ "patch", required_argument, 0, 'i' },
{ "pause-when-inactive", no_argument, &pauseWhenInactive, 1 },
{ "profile", optional_argument, 0, 'p' },
{ "recent-freeze", no_argument, &recentFreeze, 1 },
{ "rewind-timer", required_argument, 0, OPT_REWIND_TIMER },
{ "rom-dir-gb", required_argument, 0, OPT_ROM_DIR_GB },
{ "rom-dir-gba", required_argument, 0, OPT_ROM_DIR_GBA },
{ "rom-dir-gbc", required_argument, 0, OPT_ROM_DIR_GBC },
{ "rtc", no_argument, &rtcEnabled, 1 },
{ "rtc-enabled", required_argument, 0, OPT_RTC_ENABLED },
{ "save-auto", no_argument, &cpuSaveType, 0 },
{ "save-dir", required_argument, 0, OPT_SAVE_DIR },
{ "save-eeprom", no_argument, &cpuSaveType, 1 },
{ "save-flash", no_argument, &cpuSaveType, 3 },
{ "save-none", no_argument, &cpuSaveType, 5 },
{ "save-sensor", no_argument, &cpuSaveType, 4 },
{ "save-sram", no_argument, &cpuSaveType, 2 },
{ "save-type", required_argument, 0, 't' },
{ "screen-shot-dir", required_argument, 0, OPT_SCREEN_SHOT_DIR },
{ "show-speed", required_argument, 0, OPT_SHOW_SPEED },
{ "show-speed-detailed", no_argument, &showSpeed, 2 },
{ "show-speed-normal", no_argument, &showSpeed, 1 },
{ "show-speed-transparent", required_argument, 0, OPT_SHOW_SPEED_TRANSPARENT },
{ "skip-bios", no_argument, &skipBios, 1 },
{ "skip-save-game-battery", no_argument, &skipSaveGameBattery, 1 },
{ "skip-save-game-cheats", no_argument, &skipSaveGameCheats, 1 },
{ "sound-filtering", required_argument, 0, OPT_SOUND_FILTERING },
{ "sound-record-dir", required_argument, 0, OPT_SOUND_RECORD_DIR },
{ "stretch", no_argument, &fullScreenStretch, 1 },
{ "synchronize", required_argument, 0, OPT_SYNCHRONIZE },
{ "thread-priority", required_argument, 0, OPT_THREAD_PRIORITY },
{ "throttle", required_argument, 0, 'T' },
{ "triple-buffering", no_argument, &tripleBuffering, 1 },
{ "use-bios", no_argument, &useBios, 1 },
{ "use-bios-file-gb", no_argument, &useBiosFileGB, 1 },
{ "use-bios-file-gba", no_argument, &useBiosFileGBA, 1 },
{ "use-bios-file-gbc", no_argument, &useBiosFileGBC, 1 },
{ "verbose", required_argument, 0, 'v' },
{ "video-option", required_argument, 0, OPT_VIDEO_OPTION },
{ "vsync", no_argument, &vsync, 1 },
{ "win-gb-printer-enabled", no_argument, &winGbPrinterEnabled, 1 },
{ "window-position-x", required_argument, 0, OPT_WINDOW_POSITION_X },
{ "window-position-y", required_argument, 0, OPT_WINDOW_POSITION_Y },
{ NULL, no_argument, NULL, 0 }
};
uint32_t fromHex(const char *s)
{
if (!s)
return 0;
uint32_t value;
sscanf(s, "%x", &value);
return value;
}
uint32_t fromDec(const char *s)
{
if (!s)
return 0;
uint32_t value = 0;
sscanf(s, "%u", &value);
return value;
}
void SetHome(char *_arg0)
{
arg0 = _arg0;
}
void OpenPreferences(const char *name)
{
if (!preferences && name)
preferences = iniparser_load(name);
}
void ValidateConfig()
{
if (gbEmulatorType < 0 || gbEmulatorType > 5)
gbEmulatorType = 1;
if (frameSkip < 0 || frameSkip > 9)
frameSkip = 2;
if (gbFrameSkip < 0 || gbFrameSkip > 9)
gbFrameSkip = 0;
if (filter < kStretch1x || filter >= kInvalidFilter)
filter = kStretch2x;
if (cpuSaveType < 0 || cpuSaveType > 5)
cpuSaveType = 0;
if (optFlashSize != 0 && optFlashSize != 1)
optFlashSize = 0;
if (ifbType < kIFBNone || ifbType >= kInvalidIFBFilter)
ifbType = kIFBNone;
if (showSpeed < 0 || showSpeed > 2)
showSpeed = 1;
if (rewindTimer < 0 || rewindTimer > 600)
rewindTimer = 0;
if (autoFireMaxCount < 1)
autoFireMaxCount = 1;
if (rewindTimer) {
rewindMemory = (char *)malloc(REWIND_NUM*REWIND_SIZE);
rewindSerials = (int *)calloc(REWIND_NUM, sizeof(int)); // init to zeroes
}
}
void LoadConfig()
{
agbPrint = ReadPrefHex("agbPrint");
autoFireMaxCount = fromDec(ReadPrefString("autoFireMaxCount"));
autoFrameSkip = ReadPref("autoFrameSkip", 0);
autoLoadMostRecent = ReadPref("autoLoadMostRecent", 0);
autoPatch = ReadPref("autoPatch", 1);
autoSaveLoadCheatList = ReadPref("autoSaveCheatList", 1);
aviRecordDir = ReadPrefString("aviRecordDir");
batteryDir = ReadPrefString("batteryDir");
biosFileNameGB = ReadPrefString("biosFileGB");
biosFileNameGBA = ReadPrefString("biosFileGBA");
biosFileNameGBC = ReadPrefString("biosFileGBC");
captureFormat = ReadPref("captureFormat", 0);
cheatsEnabled = ReadPref("cheatsEnabled", 0);
cpuDisableSfx = ReadPref("disableSfx", 0);
cpuSaveType = ReadPrefHex("saveType");
disableMMX = ReadPref("disableMMX", 0);
disableStatusMessages = ReadPrefHex("disableStatus");
filterMT = ReadPref("filterEnableMultiThreading", 0);
filter = ReadPref("filter", 0);
frameSkip = ReadPref("frameSkip", 0);
fsAdapter = ReadPref("fsAdapter", 0);
fsColorDepth = ReadPref("fsColorDepth", 32);
fsFrequency = ReadPref("fsFrequency", 60);
fsHeight = ReadPref("fsHeight", 600);
fsWidth = ReadPref("fsWidth", 800);
fullScreen = ReadPrefHex("fullScreen");
fullScreenStretch = ReadPref("stretch", 0);
gbBorderAutomatic = ReadPref("borderAutomatic", 0);
gbBorderOn = ReadPrefHex("borderOn");
gbColorOption = ReadPref("colorOption", 0);
gbEmulatorType = ReadPref("emulatorType", 1);
gbFrameSkip = ReadPref("gbFrameSkip", 0);
gbPaletteOption = ReadPref("gbPaletteOption", 0);
gbSoundSetDeclicking(ReadPref("gbSoundDeclicking", 1));
gb_effects_config.echo = (float)ReadPref("gbSoundEffectsEcho", 20) / 100.0f;
gb_effects_config.enabled = ReadPref("gbSoundEffectsEnabled", 0);
gb_effects_config.stereo = (float)ReadPref("gbSoundEffectsStereo", 15) / 100.0f;
gb_effects_config.surround = ReadPref("gbSoundEffectsSurround", 0);
gdbBreakOnLoad = ReadPref("gdbBreakOnLoad", 0);
gdbPort = ReadPref("gdbPort", 55555);
glFilter = ReadPref("glFilter", 1);
ifbType = ReadPref("ifbType", 0);
joypadDefault = ReadPref("joypadDefault", 0);
languageOption = ReadPref("language", 1);
linkAuto = ReadPref("LinkAuto", 1);
linkHacks = ReadPref("LinkHacks", 0);
linkHostAddr = ReadPrefString("LinkHostAddr", "localhost");
linkMode = ReadPref("LinkMode", 0); // LINK_DISCONNECTED = 0
linkNumPlayers = ReadPref("LinkNumPlayers", 2);
linkTimeout = ReadPref("LinkTimeout", 1);
loadDotCodeFile = ReadPrefString("loadDotCodeFile");
maxScale = ReadPref("maxScale", 0);
movieRecordDir = ReadPrefString("movieRecordDir");
openGL = ReadPrefHex("openGL");
optFlashSize = ReadPrefHex("flashSize");
pauseWhenInactive = ReadPref("pauseWhenInactive", 1);
recentFreeze = ReadPref("recentFreeze", 0);
rewindTimer = ReadPref("rewindTimer", 0);
romDirGB = ReadPrefString("romDirGB");
romDirGBA = ReadPrefString("romDirGBA");
romDirGBC = ReadPrefString("romDirGBC");
rtcEnabled = ReadPref("rtcEnabled", 0);
saveDir = ReadPrefString("saveDir");
saveDotCodeFile = ReadPrefString("saveDotCodeFile");
screenShotDir = ReadPrefString("screenShotDir");
showSpeed = ReadPref("showSpeed", 0);
showSpeedTransparent = ReadPref("showSpeedTransparent", 1);
skipBios = ReadPref("skipBios", 0);
skipSaveGameBattery = ReadPref("skipSaveGameBattery", 0);
skipSaveGameCheats = ReadPref("skipSaveGameCheats", 0);
soundFiltering = (float)ReadPref("gbaSoundFiltering", 50) / 100.0f;
soundInterpolation = ReadPref("gbaSoundInterpolation", 1);
soundRecordDir = ReadPrefString("soundRecordDir");
threadPriority = ReadPref("priority", 2);
throttle = ReadPref("throttle", 100);
tripleBuffering = ReadPref("tripleBuffering", 0);
useBios = ReadPrefHex("useBiosGBA");
useBiosFileGB = ReadPref("useBiosGB", 0);
useBiosFileGBA = ReadPref("useBiosGBA", 0);
useBiosFileGBC = ReadPref("useBiosGBC", 0);
videoOption = ReadPref("video", 2); // VIDEO_3X = 2
vsync = ReadPref("vsync", false);
windowPositionX = ReadPref("windowX", 0);
windowPositionY = ReadPref("windowY", 0);
winFlashSize = ReadPref("flashSize", 0x10000);
winGbBorderOn = ReadPref("borderOn", 0);
winGbPrinterEnabled = ReadPref("gbPrinter", 0);
int soundQuality = (ReadPrefHex("soundQuality", 1));
switch (soundQuality) {
case 1:
case 2:
case 4:
break;
default:
log("Unknown sound quality %d. Defaulting to 44Khz\n", soundQuality);
soundQuality = 1;
break;
}
soundSetSampleRate(44100 / soundQuality);
int volume = ReadPref("soundVolume", 100);
float volume_percent = volume / 100.0f;
if (volume_percent < 0.0 || volume_percent > SOUND_MAX_VOLUME)
volume_percent = 1.0;
soundSetVolume(volume_percent);
soundSetEnable((ReadPrefHex("soundEnable", 0x30f)) & 0x30f);
if ((ReadPrefHex("soundStereo"))) {
gb_effects_config.enabled = true;
}
if ((ReadPrefHex("soundEcho"))) {
gb_effects_config.enabled = true;
}
if ((ReadPrefHex("soundSurround"))) {
gb_effects_config.surround = true;
gb_effects_config.enabled = true;
}
if (optFlashSize == 0)
flashSetSize(0x10000);
else
flashSetSize(0x20000);
rtcEnable(rtcEnabled ? true : false);
agbPrintEnable(agbPrint ? true : false);
for (int i = 0; i < 24;) {
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
systemGbPalette[i++] = 0;
}
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
optPrintUsage = 0;
// TODO
//int s = ReadPref("mapViewStretch", 0);
//m_size = ReadPref("memViewerDataSize", 0);
//m_stretch = ReadPref("GBOamViewStretch", 0);
//m_stretch = ReadPref("tileViewStretch", 0);
//numberType = ReadPref("cheatsNumberType", 2);
//numberType = ReadPref("gbCheatsNumberType", 2);
//restoreValues = ReadPref("cheatsRestore", 0) ?
//scale = ReadPref("printerScale", 0);
//searchType = ReadPref("cheatsSearchType", SEARCH_EQ);
//searchType = ReadPref("gbCheatsSearchType",
//selectedFilter = ReadPref(("selectedFilter"), 0);
//sizeType = ReadPref("cheatsSizeType", 0);
//sizeType = ReadPref("gbCheatsSizeType", 0);
//updateValues = ReadPref("cheatsUpdate", 0);
//updateValues = ReadPref("gbCheatsUpdate", 0);
//valueType = ReadPref("cheatsValueType", 0);
//valueType = ReadPref("gbCheatsValueType", 0);
ValidateConfig();
}
void CloseConfig()
{
if (preferences)
iniparser_freedict(preferences);
}
const char* FindConfigFile(const char *name)
{
char buffer[4096];
#ifdef _WIN32
#define PATH_SEP ";"
#define FILE_SEP '\\'
#define EXE_NAME "vbam.exe"
#else // ! _WIN32
#define PATH_SEP ":"
#define FILE_SEP '/'
#define EXE_NAME "vbam"
#endif // ! _WIN32
if (GETCWD(buffer, 2048)) {
}
if (FileExists(name))
{
return name;
}
if (homeDir) {
sprintf(path, "%s%c%s%c%s", homeDir, FILE_SEP, DOT_DIR, FILE_SEP, name);
if (FileExists(path))
{
return path;
}
}
#ifdef _WIN32
char *home = getenv("USERPROFILE");
if (home != NULL) {
sprintf(path, "%s%c%s", home, FILE_SEP, name);
if (FileExists(path))
{
return path;
}
}
if (!strchr(arg0, '/') &&
!strchr(arg0, '\\')) {
char *path = getenv("PATH");
if (path != NULL) {
strncpy(buffer, path, 4096);
buffer[4095] = 0;
char *tok = strtok(buffer, PATH_SEP);
while (tok) {
sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME);
if (FileExists(path)) {
char path2[2048];
sprintf(path2, "%s%c%s", tok, FILE_SEP, name);
if (FileExists(path2)) {
return path2;
}
}
tok = strtok(NULL, PATH_SEP);
}
}
}
else {
// executable is relative to some directory
strcpy(buffer, arg0);
char *p = strrchr(buffer, FILE_SEP);
if (p) {
*p = 0;
sprintf(path, "%s%c%s", buffer, FILE_SEP, name);
if (FileExists(path))
{
return path;
}
}
}
#else // ! _WIN32
sprintf(path, "%s%c%s", PKGDATADIR, FILE_SEP, name);
if (FileExists(path))
{
return path;
}
sprintf(path, "%s%c%s", SYSCONF_INSTALL_DIR, FILE_SEP, name);
if (FileExists(path))
{
return path;
}
#endif // ! _WIN32
return 0;
}
void LoadConfigFile()
{
#if !defined(_WIN32) && !defined(__APPLE__)
// Get home dir
char buf[1024];
struct stat s;
homeDir = getenv("HOME");
snprintf(buf, 1024, "%s/%s", homeDir, DOT_DIR);
// Make dot dir if not existent
if (stat(buf, &s) == -1 || !S_ISDIR(s.st_mode))
mkdir(buf, 0755);
#else
homeDir = 0;
#endif
if (preferences == NULL)
{
const char* configFile = FindConfigFile("vbam.ini");
OpenPreferences(configFile);
}
if (preferences == NULL)
{
const char* configFile = FindConfigFile("vbam.cfg");
OpenPreferences(configFile);
}
}
void SaveConfigFile()
{
#if !defined(_WIN32) && !defined(__APPLE__)
// Get home dir
char buf[1024];
struct stat s;
homeDir = getenv("HOME");
snprintf(buf, 1024, "%s/%s", homeDir, DOT_DIR);
// Make dot dir if not existent
if (stat(buf, &s) == -1 || !S_ISDIR(s.st_mode))
mkdir(buf, 0755);
#else
homeDir = 0;
#endif
const char* configFile = FindConfigFile("vbam.ini");
if (configFile == NULL)
{
configFile = FindConfigFile("vbam.cfg");
}
if (configFile != NULL)
{
FILE *f = fopen(configFile, "w");
if (f == NULL) {
char err_msg[4096] = "unknown error";
#ifdef _WIN32
strerror_s(err_msg, errno, 4096);
#else
strerror_r(errno, err_msg, 4096);
#endif
fprintf(stderr, "Configuration file '%s' could not be written to: %s\n", configFile, err_msg);
return;
}
// Needs mixed case version of the option name to add new options into the ini
//for (int i = 0; i < (sizeof(argOptions) / sizeof(option)); i++)
//{
// std::string pref = "preferences:";
// pref.append(argOptions[i].name);
// if (!iniparser_find_entry(preferences, pref.c_str()))
// {
// iniparser_set(preferences, pref.c_str(), NULL);
// }
//}
iniparser_dump_ini(preferences, f);
fclose(f);
}
}
uint32_t ReadPrefHex(const char* pref_key, int default_value)
{
std::stringstream ss;
std::string default_string;
ss.setf(std::ios::hex|std::ios::showbase, std::ios::basefield);
ss << default_value;
ss >> default_string;
LoadConfigFile();
std::string pref = "preferences:";
pref.append(pref_key);
return fromHex(iniparser_getstring(preferences, pref.c_str(), default_string.c_str()));
}
uint32_t ReadPrefHex(const char* pref_key)
{
LoadConfigFile();
std::string pref = "preferences:";
pref.append(pref_key);
return fromHex(iniparser_getstring(preferences, pref.c_str(), 0));
}
uint32_t ReadPref(const char* pref_key, int default_value)
{
LoadConfigFile();
std::string pref = "preferences:";
pref.append(pref_key);
return iniparser_getint(preferences, pref.c_str(), default_value);
}
uint32_t ReadPref(const char* pref_key)
{
return ReadPref(pref_key, 0);
}
const char* ReadPrefString(const char* pref_key, const char* default_value)
{
LoadConfigFile();
std::string pref = "preferences:";
pref.append(pref_key);
return iniparser_getstring(preferences, pref.c_str(), default_value);
}
const char* ReadPrefString(const char* pref_key)
{
return ReadPrefString(pref_key, "");
}
/*-------------------------------------------------------------------------*/
/**
@brief Duplicate a string
@param s String to duplicate
@return Pointer to a newly allocated string, to be freed with free()
This is a replacement for strdup(). This implementation is provided
for systems that do not have it.
*/
/*--------------------------------------------------------------------------*/
static char *xstrdup(const char *s)
{
char *t;
if (!s)
return NULL;
t = (char *)malloc(strlen(s) + 1);
if (t) {
strcpy(t, s);
}
return t;
}
int ReadOpts(int argc, char ** argv)
{
int op = -1;
while ((op = getopt_long(argc,
argv,
"FNO:T:Y:G:I:D:b:c:df:hi:p::s:t:v:",
argOptions,
NULL)) != -1) {
switch (op) {
case 0:
// long option already processed by getopt_long
break;
case OPT_CHEAT:
// --cheat
if (preparedCheats >= MAX_CHEATS) {
log("Warning: cannot add more than %d cheats.\n", MAX_CHEATS);
break;
}
{
//char* cpy;
//cpy = (char *)malloc(1 + strlen(optarg));
//strcpy(cpy, optarg);
//preparedCheatCodes[preparedCheats++] = cpy;
std::string cpy = optarg;
preparedCheatCodes[preparedCheats++] = cpy.c_str();
}
break;
case OPT_AUTOFIRE:
// --autofire
autoFireMaxCount = fromDec(optarg);
if (autoFireMaxCount < 1)
autoFireMaxCount = 1;
break;
case 'b':
useBios = true;
if (optarg == NULL) {
log("Missing BIOS file name\n");
break;
}
biosFileNameGBA = xstrdup(optarg);
break;
case 'c':
{
if (optarg == NULL) {
log("Missing config file name\n");
break;
}
FILE *f = fopen(optarg, "r");
if (f == NULL) {
log("File not found %s\n", optarg);
break;
}
preferences = NULL;
OpenPreferences(optarg);
fclose(f);
}
break;
case 'd':
debugger = true;
break;
case 'h':
optPrintUsage = 1;
break;
case 'i':
if (optarg == NULL) {
log("Missing patch name\n");
break;
}
if (patchNum >= PATCH_MAX_NUM) {
log("Too many patches given at %s (max is %d). Ignoring.\n", optarg, PATCH_MAX_NUM);
}
else {
patchNames[patchNum] = (char *)malloc(1 + strlen(optarg));
strcpy(patchNames[patchNum], optarg);
patchNum++;
}
break;
case 'G':
dbgMain = remoteStubMain;
dbgSignal = remoteStubSignal;
dbgOutput = remoteOutput;
debugger = true;
if (optarg) {
char *s = optarg;
if (strncmp(s, "tcp:", 4) == 0) {
s += 4;
int port = atoi(s);
remoteSetProtocol(0);
remoteSetPort(port);
}
else if (strcmp(s, "tcp") == 0) {
remoteSetProtocol(0);
}
else if (strcmp(s, "pipe") == 0) {
remoteSetProtocol(1);
}
else {
log("Unknown protocol %s\n", s);
break;
}
}
else {
remoteSetProtocol(0);
}
break;
case 'N':
parseDebug = false;
break;
case 'F':
fullScreen = 1;
mouseCounter = 120;
break;
case 'f':
if (optarg) {
filter = (Filter)atoi(optarg);
}
else {
filter = kStretch2x;
}
break;
case 'I':
if (optarg) {
ifbType = (IFBFilter)atoi(optarg);
}
else {
ifbType = kIFBNone;
}
break;
case 'p':
#ifdef PROFILING
if (optarg) {
cpuEnableProfiling(atoi(optarg));
}
else
cpuEnableProfiling(100);
#endif
break;
case 'S':
optFlashSize = atoi(optarg);
if (optFlashSize < 0 || optFlashSize > 1)
optFlashSize = 0;
break;
case 's':
if (optarg) {
int a = atoi(optarg);
if (a >= 0 && a <= 9) {
gbFrameSkip = a;
frameSkip = a;
}
}
else {
frameSkip = 2;
gbFrameSkip = 0;
}
break;
case 't':
if (optarg) {
int a = atoi(optarg);
if (a < 0 || a > 5)
a = 0;
cpuSaveType = a;
}
break;
case 'v':
if (optarg) {
systemVerbose = atoi(optarg);
}
else
systemVerbose = 0;
break;
case '?':
optPrintUsage = 1;
break;
case 'O':
if (optarg) {
openGL = atoi(optarg);
if (openGL < 0 || openGL > 2)
openGL = 1;
}
else
openGL = 0;
break;
case OPT_CAPTURE_FORMAT:
// --capture-format
if (optarg) {
captureFormat = atoi(optarg);
}
break;
case OPT_SHOW_SPEED_TRANSPARENT:
// --show-speed-transparent
if (optarg) {
showSpeedTransparent = atoi(optarg);
}
break;
case OPT_AUTO_FRAME_SKIP:
// --auto-frame-skip
if (optarg) {
autoFrameSkip = atoi(optarg);
}
break;
case OPT_AGB_PRINT:
// --agb-print
if (optarg) {
agbPrint = atoi(optarg);
}
break;
case OPT_RTC_ENABLED:
// --rtc-enabled
if (optarg) {
rtcEnabled = atoi(optarg);
}
break;
case OPT_VIDEO_OPTION:
// --video-option
if (optarg) {
videoOption = atoi(optarg);
}
break;
case OPT_LANGUAGE_OPTION:
// --language-option
if (optarg) {
languageOption = atoi(optarg);
}
break;
case OPT_GB_FRAME_SKIP:
// --gb-frame-skip
if (optarg) {
gbFrameSkip = atoi(optarg);
}
break;
case OPT_FS_ADAPTER:
// --fs-adapter
if (optarg) {
fsAdapter = atoi(optarg);
}
break;
case OPT_FS_WIDTH:
// --fs-width
if (optarg) {
fsWidth = atoi(optarg);
}
break;
case OPT_FS_HEIGHT:
// --fs-height
if (optarg) {
fsHeight = atoi(optarg);
}
break;
case OPT_FS_COLOR_DEPTH:
// --fs-color-depth
if (optarg) {
fsColorDepth = atoi(optarg);
}
break;
case OPT_FS_FREQUENCY:
// --fs-frequency
if (optarg) {
fsFrequency = atoi(optarg);
}
break;
case OPT_WINDOW_POSITION_X:
// --window-position-x
if (optarg) {
windowPositionX = atoi(optarg);
}
break;
case OPT_WINDOW_POSITION_Y:
// --window-position-y
if (optarg) {
windowPositionY = atoi(optarg);
}
break;
case OPT_SOUND_FILTERING:
// --sound-filtering
if (optarg) {
soundFiltering = atoi(optarg);
}
break;
case OPT_GL_FILTER:
// --gl-filter
if (optarg) {
glFilter = atoi(optarg);
}
break;
case OPT_SHOW_SPEED:
// --show-speed
if (optarg) {
showSpeed = atoi(optarg);
}
break;
case OPT_IFB_TYPE:
// --ifb-type
if (optarg) {
ifbType = atoi(optarg);
}
break;
case OPT_GB_EMULATOR_TYPE:
// --gb-emulator-type
if (optarg) {
gbEmulatorType = atoi(optarg);
}
break;
case OPT_THREAD_PRIORITY:
// --thread-priority
if (optarg) {
threadPriority = atoi(optarg);
}
break;
case OPT_GB_PALETTE_OPTION:
// --gb-palette-option
if (optarg) {
gbPaletteOption = atoi(optarg);
}
break;
case OPT_REWIND_TIMER:
// --rewind-timer
if (optarg) {
rewindTimer = atoi(optarg);
}
break;
case OPT_JOYPAD_DEFAULT:
// --joypad-default
if (optarg) {
joypadDefault = atoi(optarg);
}
break;
case OPT_MAX_SCALE:
// --max-scale
if (optarg) {
maxScale = atoi(optarg);
}
break;
case OPT_LINK_TIMEOUT:
// --link-timeout
if (optarg) {
linkTimeout = atoi(optarg);
}
break;
case OPT_LINK_MODE:
// --link-mode
if (optarg) {
linkMode = atoi(optarg);
}
break;
case OPT_LINK_AUTO:
// --link-auto
if (optarg) {
linkAuto = atoi(optarg);
}
break;
case OPT_LINK_HACKS:
// --link-hacks
if (optarg) {
linkHacks = atoi(optarg);
}
break;
case OPT_LINK_NUM_PLAYERS:
// --link-num-players
if (optarg) {
linkNumPlayers = atoi(optarg);
}
break;
case OPT_GDB_PORT:
// --gdb-port
if (optarg) {
gdbPort = atoi(optarg);
}
break;
case OPT_BIOS_FILE_NAME_GB:
// --bios-file-name-gb
biosFileNameGB = optarg;
break;
case OPT_BIOS_FILE_NAME_GBA:
// --bios-file-name-gba
biosFileNameGBA = optarg;
break;
case OPT_BIOS_FILE_NAME_GBC:
// --bios-file-name-gbc
biosFileNameGBC = optarg;
break;
case OPT_AVI_RECORD_DIR:
// --avi-record-dir
aviRecordDir = optarg;
break;
case OPT_MOVIE_RECORD_DIR:
// --movie-record-dir
movieRecordDir = optarg;
break;
case OPT_SOUND_RECORD_DIR:
// --sound-record-dir
soundRecordDir = optarg;
break;
case OPT_SCREEN_SHOT_DIR:
// --screen-shot-dir
screenShotDir = optarg;
break;
case OPT_SAVE_DIR:
// --save-dir
saveDir = optarg;
break;
case OPT_BATTERY_DIR:
// --battery-dir
batteryDir = optarg;
break;
case OPT_ROM_DIR_GBC:
// --rom-dir-gbc
romDirGBC = optarg;
break;
case OPT_ROM_DIR_GB:
// --rom-dir-gb
romDirGB = optarg;
break;
case OPT_ROM_DIR_GBA:
// --rom-dir-gba
romDirGBA = optarg;
break;
case OPT_LINK_HOST_ADDR:
// --link-host-addr
linkHostAddr = optarg;
break;
case OPT_CPU_SAVE_TYPE:
// --cpu-save-type
if (optarg) {
cpuSaveType = atoi(optarg);
}
break;
case OPT_OPT_FLASH_SIZE:
// --opt-flash-size
if (optarg) {
optFlashSize = atoi(optarg);
}
break;
case OPT_DOTCODE_FILE_NAME_LOAD:
// --dotcode-file-name-load
loadDotCodeFile = optarg;
break;
case OPT_DOTCODE_FILE_NAME_SAVE:
// --dotcode-file-name-save
saveDotCodeFile = optarg;
break;
}
}
return op;
}