1 #include "ConfigManager.h"
2 extern "C" {
3 #include "../common/iniparser.h"
4 }
5 
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <cmath>
13 #include <unistd.h>
14 
15 #include "../AutoBuild.h"
16 #include "../version.h"
17 
18 #include "../common/Patch.h"
19 #include "../common/ConfigManager.h"
20 #include "../gba/GBA.h"
21 #include "../gba/agbprint.h"
22 #include "../gba/Flash.h"
23 #include "../gba/Cheats.h"
24 #include "../gba/remote.h"
25 #include "../gba/RTC.h"
26 #include "../gba/Sound.h"
27 #include "../gb/gb.h"
28 #include "../gb/gbGlobals.h"
29 #include "../gb/gbCheats.h"
30 #include "../gb/gbSound.h"
31 #include "../Util.h"
32 
33 #ifndef _WIN32
34 #define GETCWD getcwd
35 #else // _WIN32
36 #include <direct.h>
37 #define GETCWD _getcwd
38 #define snprintf sprintf
39 #endif // _WIN32
40 
41 #ifndef __GNUC__
42 #define HAVE_DECL_GETOPT 0
43 #define __STDC__ 1
44 #include "getopt.h"
45 #else // ! __GNUC__
46 #define HAVE_DECL_GETOPT 1
47 #include <getopt.h>
48 #endif // ! __GNUC__
49 #include <string>
50 
51 enum named_opts
52 {
53 	OPT_AGB_PRINT = 1000,
54 	OPT_AUTOFIRE,
55 	OPT_AUTO_FRAME_SKIP,
56 	OPT_AVI_RECORD_DIR,
57 	OPT_BATTERY_DIR,
58 	OPT_BIOS_FILE_NAME_GB,
59 	OPT_BIOS_FILE_NAME_GBA,
60 	OPT_BIOS_FILE_NAME_GBC,
61 	OPT_CAPTURE_FORMAT,
62 	OPT_CHEAT,
63 	OPT_CPU_SAVE_TYPE,
64 	OPT_DOTCODE_FILE_NAME_LOAD,
65 	OPT_DOTCODE_FILE_NAME_SAVE,
66 	OPT_EMULATOR_TYPE,
67 	OPT_FS_ADAPTER,
68 	OPT_FS_COLOR_DEPTH,
69 	OPT_FS_FREQUENCY,
70 	OPT_FS_HEIGHT,
71 	OPT_FS_WIDTH,
72 	OPT_GB_EMULATOR_TYPE,
73 	OPT_GB_FRAME_SKIP,
74 	OPT_GB_PALETTE_OPTION,
75 	OPT_GDB_PORT,
76 	OPT_GL_FILTER,
77 	OPT_IFB_TYPE,
78 	OPT_JOYPAD_DEFAULT,
79 	OPT_LANGUAGE_OPTION,
80 	OPT_LINK_AUTO,
81 	OPT_LINK_HACKS,
82 	OPT_LINK_HOST_ADDR,
83 	OPT_LINK_MODE,
84 	OPT_LINK_NUM_PLAYERS,
85 	OPT_LINK_TIMEOUT,
86 	OPT_MAX_SCALE,
87 	OPT_MOVIE_RECORD_DIR,
88 	OPT_OPT_FLASH_SIZE,
89 	OPT_REWIND_TIMER,
90 	OPT_ROM_DIR_GB,
91 	OPT_ROM_DIR_GBA,
92 	OPT_ROM_DIR_GBC,
93 	OPT_RTC_ENABLED,
94 	OPT_SAVE_DIR,
95 	OPT_SCREEN_SHOT_DIR,
96 	OPT_SHOW_SPEED,
97 	OPT_SHOW_SPEED_TRANSPARENT,
98 	OPT_SOUND_FILTERING,
99 	OPT_SOUND_RECORD_DIR,
100 	OPT_SYNCHRONIZE,
101 	OPT_THREAD_PRIORITY,
102 	OPT_VIDEO_OPTION,
103 	OPT_WINDOW_POSITION_X,
104 	OPT_WINDOW_POSITION_Y
105 
106 };
107 
108 #define SOUND_MAX_VOLUME 2.0
109 #define SOUND_ECHO       0.2
110 #define SOUND_STEREO     0.15
111 
112 #define REWIND_NUM 8
113 #define REWIND_SIZE 400000
114 
115 char path[2048];
116 
117 dictionary* preferences;
118 
119 bool cpuIsMultiBoot = false;
120 bool mirroringEnable = true;
121 bool parseDebug = true;
122 bool speedHack = false;
123 bool speedup = false;
124 char* aviRecordDir;
125 char* batteryDir;
126 char* biosFileNameGB;
127 char* biosFileNameGBA;
128 char* biosFileNameGBC;
129 char* loadDotCodeFile;
130 char* saveDotCodeFile;
131 char* linkHostAddr;
132 char* movieRecordDir;
133 char* rewindMemory = NULL;
134 char* romDirGB;
135 char* romDirGBA;
136 char* romDirGBC;
137 char* saveDir;
138 char* screenShotDir;
139 char* soundRecordDir;
140 int active = 1;
141 int agbPrint;
142 int autoFire;
143 int autoFireMaxCount = 1;
144 int autoFireToggle;
145 int autoFrameSkip = 0;
146 int autoLoadMostRecent;
147 int autoPatch;
148 int autoSaveLoadCheatList;
149 int aviRecording;
150 int captureFormat = 0;
151 int cheatsEnabled = true;
152 int cpuDisableSfx = false;
153 int cpuSaveType = 0;
154 int disableMMX;
155 int disableStatusMessages = 0;
156 int dsoundDisableHardwareAcceleration;
157 int filterHeight;
158 int filterMagnification;
159 int filterMT; // enable multi-threading for pixel filters
160 int filter = kStretch2x;
161 int filterWidth;
162 int frameSkip = 1;
163 int frameskipadjust;
164 int fsAdapter;
165 int fsColorDepth;
166 int fsForceChange;
167 int fsFrequency;
168 int fsHeight;
169 int fsWidth;
170 int fullScreen;
171 int fullScreenStretch;
172 int gdbBreakOnLoad;
173 int gdbPort;
174 int glFilter;
175 int ifbType = kIFBNone;
176 int joypadDefault;
177 int languageOption;
178 int layerEnable = 0xff00;
179 int layerSettings = 0xff00;
180 int linkAuto;
181 int linkHacks = 1;
182 int linkMode;
183 int linkNumPlayers;
184 int linkTimeout = 1;
185 int maxScale;
186 int mouseCounter = 0;
187 int movieFrame;
188 int moviePlayFrame;
189 int moviePlaying;
190 int movieRecording;
191 int openGL;
192 int optFlashSize;
193 int optPrintUsage;
194 int paused;
195 int pauseWhenInactive = 0;
196 int preparedCheats = 0;
197 int recentFreeze;
198 int renderedFrames;
199 int rewindCount;
200 int rewindCounter;
201 int rewindPos;
202 int rewindSaveNeeded = 0;
203 int rewindTimer = 0;
204 int rewindTopPos;
205 int rtcEnabled;
206 int saveType = 0;
207 int screenMessage;
208 int sensorX;
209 int sensorY;
210 int showRenderedFrames;
211 int showSpeed;
212 int showSpeedTransparent;
213 int sizeX;
214 int sizeY;
215 int skipBios = 0;
216 int skipSaveGameBattery = false;
217 int skipSaveGameCheats = false;
218 int soundRecording;
219 int speedupToggle;
220 int sunBars;
221 int surfaceSizeX;
222 int surfaceSizeY;
223 int threadPriority;
224 int tripleBuffering;
225 int useBios = 0;
226 int useBiosFileGB;
227 int useBiosFileGBA;
228 int useBiosFileGBC;
229 int videoOption;
230 int vsync;
231 int wasPaused = 0;
232 int windowPositionX;
233 int windowPositionY;
234 int winFlashSize;
235 int winGbBorderOn;
236 int winGbPrinterEnabled;
237 int winPauseNextFrame;
238 int* rewindSerials = NULL;
239 u32 autoFrameSkipLastTime;
240 u32 movieLastJoypad;
241 u32 movieNextJoypad;
242 int throttle;
243 
244 const char* preparedCheatCodes[MAX_CHEATS];
245 
246 FilterFunc filterFunction = 0;
247 IFBFilterFunc ifbFunction = 0;
248 
249 // allow up to 100 IPS/UPS/PPF patches given on commandline
250 int	patchNum = 0;
251 char *(patchNames[PATCH_MAX_NUM]) = { NULL }; // and so on
252 
253 void(*dbgMain)() = remoteStubMain;
254 void(*dbgSignal)(int, int) = remoteStubSignal;
255 void(*dbgOutput)(const char *, u32) = debuggerOutput;
256 
257 char* homeDir = NULL;
258 char* arg0 = NULL;
259 
260 
261 struct option argOptions[] = {
262 
263 	{ "agb-print", required_argument, 0, OPT_AGB_PRINT },
264 	{ "auto-frame-skip", required_argument, 0, OPT_AUTO_FRAME_SKIP },
265 	{ "auto-load-most-recent", no_argument, &autoLoadMostRecent, 1 },
266 	{ "auto-patch", no_argument, &autoPatch, 1 },
267 	{ "auto-save-cheat-list", no_argument, &autoSaveLoadCheatList, 1 },
268 	{ "auto-save-load-cheat-list", no_argument, &autoSaveLoadCheatList, 1 },
269 	{ "autofire", required_argument, 0, OPT_AUTOFIRE },
270 	{ "avi-record-dir", required_argument, 0, OPT_AVI_RECORD_DIR },
271 	{ "battery-dir", required_argument, 0, OPT_BATTERY_DIR },
272 	{ "bios", required_argument, 0, 'b' },
273 	{ "bios-file-name-gb", required_argument, 0, OPT_BIOS_FILE_NAME_GB },
274 	{ "bios-file-name-gba", required_argument, 0, OPT_BIOS_FILE_NAME_GBA },
275 	{ "bios-file-name-gbc", required_argument, 0, OPT_BIOS_FILE_NAME_GBC },
276 	{ "border-automatic", no_argument, &gbBorderAutomatic, 1 },
277 	{ "border-on", no_argument, &gbBorderOn, 1 },
278 	{ "capture-format", required_argument, 0, OPT_CAPTURE_FORMAT },
279 	{ "cheat", required_argument, 0, OPT_CHEAT },
280 	{ "cheats-enabled", no_argument, &cheatsEnabled, 1 },
281 	{ "color-option", no_argument, &gbColorOption, 1 },
282 	{ "config", required_argument, 0, 'c' },
283 	{ "cpu-disable-sfx", no_argument, &cpuDisableSfx, 1 },
284 	{ "cpu-save-type", required_argument, 0, OPT_CPU_SAVE_TYPE },
285 	{ "debug", no_argument, 0, 'd' },
286 	{ "disable-mmx", no_argument, &disableMMX, 1 },
287 	{ "disable-sfx", no_argument, &cpuDisableSfx, 1 },
288 	{ "disable-status-messages", no_argument, &disableStatusMessages, 1 },
289 	{ "dotcode-file-name-load", required_argument, 0, OPT_DOTCODE_FILE_NAME_LOAD },
290 	{ "dotcode-file-name-save", required_argument, 0, OPT_DOTCODE_FILE_NAME_SAVE },
291 	{ "emulator-type", required_argument, 0, OPT_EMULATOR_TYPE },
292 	{ "filter", required_argument, 0, 'f' },
293 	{ "filter-enable-multi-threading", no_argument, &filterMT, 1 },
294 	{ "filter-mt", no_argument, &filterMT, 1 },
295 	{ "flash-128k", no_argument, &optFlashSize, 1 },
296 	{ "flash-64k", no_argument, &optFlashSize, 0 },
297 	{ "flash-size", required_argument, 0, 'S' },
298 	{ "frameskip", required_argument, 0, 's' },
299 	{ "fs-adapter", required_argument, 0, OPT_FS_ADAPTER },
300 	{ "fs-color-depth", required_argument, 0, OPT_FS_COLOR_DEPTH },
301 	{ "fs-frequency", required_argument, 0, OPT_FS_FREQUENCY },
302 	{ "fs-height", required_argument, 0, OPT_FS_HEIGHT },
303 	{ "fs-width", required_argument, 0, OPT_FS_WIDTH },
304 	{ "full-screen", no_argument, &fullScreen, 1 },
305 	{ "full-screen-stretch", no_argument, &fullScreenStretch, 1 },
306 	{ "gb-border-automatic", no_argument, &gbBorderAutomatic, 1 },
307 	{ "gb-border-on", no_argument, &gbBorderOn, 1 },
308 	{ "gb-color-option", no_argument, &gbColorOption, 1 },
309 	{ "gb-emulator-type", required_argument, 0, OPT_GB_EMULATOR_TYPE },
310 	{ "gb-frame-skip", required_argument, 0, OPT_GB_FRAME_SKIP },
311 	{ "gb-palette-option", required_argument, 0, OPT_GB_PALETTE_OPTION },
312 	{ "gb-printer", no_argument, &winGbPrinterEnabled, 1 },
313 	{ "gdb", required_argument, 0, 'G' },
314 	{ "gdb-break-on-load", no_argument, &gdbBreakOnLoad, 1 },
315 	{ "gdb-port", required_argument, 0, OPT_GDB_PORT },
316 	{ "gl-filter", required_argument, 0, OPT_GL_FILTER },
317 	{ "help", no_argument, &optPrintUsage, 1 },
318 	{ "ifb-filter", required_argument, 0, 'I' },
319 	{ "ifb-type", required_argument, 0, OPT_IFB_TYPE },
320 	{ "joypad-default", required_argument, 0, OPT_JOYPAD_DEFAULT },
321 	{ "language-option", required_argument, 0, OPT_LANGUAGE_OPTION },
322 	{ "link-auto", required_argument, 0, OPT_LINK_AUTO },
323 	{ "link-hacks", required_argument, 0, OPT_LINK_HACKS },
324 	{ "link-host-addr", required_argument, 0, OPT_LINK_HOST_ADDR },
325 	{ "link-mode", required_argument, 0, OPT_LINK_MODE },
326 	{ "link-num-players", required_argument, 0, OPT_LINK_NUM_PLAYERS },
327 	{ "link-timeout", required_argument, 0, OPT_LINK_TIMEOUT },
328 	{ "max-scale", required_argument, 0, OPT_MAX_SCALE },
329 	{ "movie-record-dir", required_argument, 0, OPT_MOVIE_RECORD_DIR },
330 	{ "no-agb-print", no_argument, &agbPrint, 0 },
331 	{ "no-auto-frameskip", no_argument, &autoFrameSkip, 0 },
332 	{ "no-debug", no_argument, 0, 'N' },
333 	{ "no-opengl", no_argument, &openGL, 0 },
334 	{ "no-patch", no_argument, &autoPatch, 0 },
335 	{ "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 },
336 	{ "no-rtc", no_argument, &rtcEnabled, 0 },
337 	{ "no-show-speed", no_argument, &showSpeed, 0 },
338 	{ "opengl", required_argument, 0, 'O' },
339 	{ "opengl-bilinear", no_argument, &openGL, 2 },
340 	{ "opengl-nearest", no_argument, &openGL, 1 },
341 	{ "opt-flash-size", required_argument, 0, OPT_OPT_FLASH_SIZE },
342 	{ "patch", required_argument, 0, 'i' },
343 	{ "pause-when-inactive", no_argument, &pauseWhenInactive, 1 },
344 	{ "profile", optional_argument, 0, 'p' },
345 	{ "recent-freeze", no_argument, &recentFreeze, 1 },
346 	{ "rewind-timer", required_argument, 0, OPT_REWIND_TIMER },
347 	{ "rom-dir-gb", required_argument, 0, OPT_ROM_DIR_GB },
348 	{ "rom-dir-gba", required_argument, 0, OPT_ROM_DIR_GBA },
349 	{ "rom-dir-gbc", required_argument, 0, OPT_ROM_DIR_GBC },
350 	{ "rtc", no_argument, &rtcEnabled, 1 },
351 	{ "rtc-enabled", required_argument, 0, OPT_RTC_ENABLED },
352 	{ "save-auto", no_argument, &cpuSaveType, 0 },
353 	{ "save-dir", required_argument, 0, OPT_SAVE_DIR },
354 	{ "save-eeprom", no_argument, &cpuSaveType, 1 },
355 	{ "save-flash", no_argument, &cpuSaveType, 3 },
356 	{ "save-none", no_argument, &cpuSaveType, 5 },
357 	{ "save-sensor", no_argument, &cpuSaveType, 4 },
358 	{ "save-sram", no_argument, &cpuSaveType, 2 },
359 	{ "save-type", required_argument, 0, 't' },
360 	{ "screen-shot-dir", required_argument, 0, OPT_SCREEN_SHOT_DIR },
361 	{ "show-speed", required_argument, 0, OPT_SHOW_SPEED },
362 	{ "show-speed-detailed", no_argument, &showSpeed, 2 },
363 	{ "show-speed-normal", no_argument, &showSpeed, 1 },
364 	{ "show-speed-transparent", required_argument, 0, OPT_SHOW_SPEED_TRANSPARENT },
365 	{ "skip-bios", no_argument, &skipBios, 1 },
366 	{ "skip-save-game-battery", no_argument, &skipSaveGameBattery, 1 },
367 	{ "skip-save-game-cheats", no_argument, &skipSaveGameCheats, 1 },
368 	{ "sound-filtering", required_argument, 0, OPT_SOUND_FILTERING },
369 	{ "sound-record-dir", required_argument, 0, OPT_SOUND_RECORD_DIR },
370 	{ "stretch", no_argument, &fullScreenStretch, 1 },
371 	{ "synchronize", required_argument, 0, OPT_SYNCHRONIZE },
372 	{ "thread-priority", required_argument, 0, OPT_THREAD_PRIORITY },
373 	{ "throttle", required_argument, 0, 'T' },
374 	{ "triple-buffering", no_argument, &tripleBuffering, 1 },
375 	{ "use-bios", no_argument, &useBios, 1 },
376 	{ "use-bios-file-gb", no_argument, &useBiosFileGB, 1 },
377 	{ "use-bios-file-gba", no_argument, &useBiosFileGBA, 1 },
378 	{ "use-bios-file-gbc", no_argument, &useBiosFileGBC, 1 },
379 	{ "verbose", required_argument, 0, 'v' },
380 	{ "video-option", required_argument, 0, OPT_VIDEO_OPTION },
381 	{ "vsync", no_argument, &vsync, 1 },
382 	{ "win-gb-printer-enabled", no_argument, &winGbPrinterEnabled, 1 },
383 	{ "window-position-x", required_argument, 0, OPT_WINDOW_POSITION_X },
384 	{ "window-position-y", required_argument, 0, OPT_WINDOW_POSITION_Y },
385 
386 
387 	{ NULL, no_argument, NULL, 0 }
388 };
389 
390 
fromHex(char * s)391 u32 fromHex(char *s)
392 {
393 	if (!s)
394 		return 0;
395 	u32 value;
396 	sscanf(s, "%x", &value);
397 	return value;
398 }
399 
fromDec(char * s)400 u32 fromDec(char *s)
401 {
402 	if (!s)
403 		return 0;
404 	u32 value = 0;
405 	sscanf(s, "%u", &value);
406 	return value;
407 }
408 
SetHome(char * _arg0)409 void SetHome(char *_arg0)
410 {
411 	arg0 = _arg0;
412 }
413 
OpenPreferences(const char * name)414 void OpenPreferences(const char *name)
415 {
416 	if (!preferences && name)
417 		preferences = iniparser_load(name);
418 }
419 
ValidateConfig()420 void ValidateConfig()
421 {
422 	if (gbEmulatorType < 0 || gbEmulatorType > 5)
423 		gbEmulatorType = 1;
424 	if (frameSkip < 0 || frameSkip > 9)
425 		frameSkip = 2;
426 	if (gbFrameSkip < 0 || gbFrameSkip > 9)
427 		gbFrameSkip = 0;
428 	if (filter < kStretch1x || filter >= kInvalidFilter)
429 		filter = kStretch2x;
430 
431 	if (cpuSaveType < 0 || cpuSaveType > 5)
432 		cpuSaveType = 0;
433 	if (optFlashSize != 0 && optFlashSize != 1)
434 		optFlashSize = 0;
435 	if (ifbType < kIFBNone || ifbType >= kInvalidIFBFilter)
436 		ifbType = kIFBNone;
437 	if (showSpeed < 0 || showSpeed > 2)
438 		showSpeed = 1;
439 	if (rewindTimer < 0 || rewindTimer > 600)
440 		rewindTimer = 0;
441 	if (autoFireMaxCount < 1)
442 		autoFireMaxCount = 1;
443 
444 	if (rewindTimer) {
445 		rewindMemory = (char *)malloc(REWIND_NUM*REWIND_SIZE);
446 		rewindSerials = (int *)calloc(REWIND_NUM, sizeof(int)); // init to zeroes
447 	}
448 }
449 
LoadConfig()450 void LoadConfig()
451 {
452 	agbPrint = ReadPrefHex("agbPrint");
453 	autoFireMaxCount = fromDec(ReadPrefString("autoFireMaxCount"));
454 	autoFrameSkip = ReadPref("autoFrameSkip", 0);
455 	autoLoadMostRecent = ReadPref("autoLoadMostRecent", 0);
456 	autoPatch = ReadPref("autoPatch", 1);
457 	autoSaveLoadCheatList = ReadPref("autoSaveCheatList", 1);
458 	aviRecordDir = ReadPrefString("aviRecordDir");
459 	batteryDir = ReadPrefString("batteryDir");
460 	biosFileNameGB = ReadPrefString("biosFileGB");
461 	biosFileNameGBA = ReadPrefString("biosFileGBA");
462 	biosFileNameGBC = ReadPrefString("biosFileGBC");
463 	captureFormat = ReadPref("captureFormat", 0);
464 	cheatsEnabled = ReadPref("cheatsEnabled", 0);
465 	cpuDisableSfx = ReadPref("disableSfx", 0);
466 	cpuSaveType = ReadPrefHex("saveType");
467 	disableMMX = ReadPref("disableMMX", 0);
468 	disableStatusMessages = ReadPrefHex("disableStatus");
469 	filterMT = ReadPref("filterEnableMultiThreading", 0);
470 	filter = ReadPref("filter", 0);
471 	frameSkip = ReadPref("frameSkip", 0);
472 	fsAdapter = ReadPref("fsAdapter", 0);
473 	fsColorDepth = ReadPref("fsColorDepth", 32);
474 	fsFrequency = ReadPref("fsFrequency", 60);
475 	fsHeight = ReadPref("fsHeight", 600);
476 	fsWidth = ReadPref("fsWidth", 800);
477 	fullScreen = ReadPrefHex("fullScreen");
478 	fullScreenStretch = ReadPref("stretch", 0);
479 	gbBorderAutomatic = ReadPref("borderAutomatic", 0);
480 	gbBorderOn = ReadPrefHex("borderOn");
481 	gbColorOption = ReadPref("colorOption", 0);
482 	gbEmulatorType = ReadPref("emulatorType", 1);
483 	gbFrameSkip = ReadPref("gbFrameSkip", 0);
484 	gbPaletteOption = ReadPref("gbPaletteOption", 0);
485 	gbSoundSetDeclicking(ReadPref("gbSoundDeclicking", 1));
486 	gb_effects_config.echo = (float)ReadPref("gbSoundEffectsEcho", 20) / 100.0f;
487 	gb_effects_config.enabled = ReadPref("gbSoundEffectsEnabled", 0);
488 	gb_effects_config.stereo = (float)ReadPref("gbSoundEffectsStereo", 15) / 100.0f;
489 	gb_effects_config.surround = ReadPref("gbSoundEffectsSurround", 0);
490 	gdbBreakOnLoad = ReadPref("gdbBreakOnLoad", 0);
491 	gdbPort = ReadPref("gdbPort", 55555);
492 	glFilter = ReadPref("glFilter", 1);
493 	ifbType = ReadPref("ifbType", 0);
494 	joypadDefault = ReadPref("joypadDefault", 0);
495 	languageOption = ReadPref("language", 1);
496 	linkAuto = ReadPref("LinkAuto", 1);
497 	linkHacks = ReadPref("LinkHacks", 0);
498 	linkHostAddr = ReadPrefString("LinkHostAddr", "localhost");
499 	linkMode = ReadPref("LinkMode", 0); // LINK_DISCONNECTED = 0
500 	linkNumPlayers = ReadPref("LinkNumPlayers", 2);
501 	linkTimeout = ReadPref("LinkTimeout", 1);
502 	loadDotCodeFile = ReadPrefString("loadDotCodeFile");
503 	maxScale = ReadPref("maxScale", 0);
504 	movieRecordDir = ReadPrefString("movieRecordDir");
505 	openGL = ReadPrefHex("openGL");
506 	optFlashSize = ReadPrefHex("flashSize");
507 	pauseWhenInactive = ReadPref("pauseWhenInactive", 1);
508 	recentFreeze = ReadPref("recentFreeze", 0);
509 	rewindTimer = ReadPref("rewindTimer", 0);
510 	romDirGB = ReadPrefString("romDirGB");
511 	romDirGBA = ReadPrefString("romDirGBA");
512 	romDirGBC = ReadPrefString("romDirGBC");
513 	rtcEnabled = ReadPref("rtcEnabled", 0);
514 	saveDir = ReadPrefString("saveDir");
515 	saveDotCodeFile = ReadPrefString("saveDotCodeFile");
516 	screenShotDir = ReadPrefString("screenShotDir");
517 	showSpeed = ReadPref("showSpeed", 0);
518 	showSpeedTransparent = ReadPref("showSpeedTransparent", 1);
519 	skipBios = ReadPref("skipBios", 0);
520 	skipSaveGameBattery = ReadPref("skipSaveGameBattery", 0);
521 	skipSaveGameCheats = ReadPref("skipSaveGameCheats", 0);
522 	soundFiltering = (float)ReadPref("gbaSoundFiltering", 50) / 100.0f;
523 	soundInterpolation = ReadPref("gbaSoundInterpolation", 1);
524 	soundRecordDir = ReadPrefString("soundRecordDir");
525 	threadPriority = ReadPref("priority", 2);
526 	throttle = ReadPref("throttle", 100);
527 	tripleBuffering = ReadPref("tripleBuffering", 0);
528 	useBios = ReadPrefHex("useBiosGBA");
529 	useBiosFileGB = ReadPref("useBiosGB", 0);
530 	useBiosFileGBA = ReadPref("useBiosGBA", 0);
531 	useBiosFileGBC = ReadPref("useBiosGBC", 0);
532 	videoOption = ReadPref("video", 2); // VIDEO_3X = 2
533 	vsync = ReadPref("vsync", false);
534 	windowPositionX = ReadPref("windowX", 0);
535 	windowPositionY = ReadPref("windowY", 0);
536 	winFlashSize = ReadPref("flashSize", 0x10000);
537 	winGbBorderOn = ReadPref("borderOn", 0);
538 	winGbPrinterEnabled = ReadPref("gbPrinter", 0);
539 
540 	int soundQuality = (ReadPrefHex("soundQuality"));
541 	switch (soundQuality) {
542 	case 1:
543 	case 2:
544 	case 4:
545 		break;
546 	default:
547 		log("Unknown sound quality %d. Defaulting to 22Khz\n", soundQuality);
548 		soundQuality = 2;
549 		break;
550 	}
551 	soundSetSampleRate(44100 / soundQuality);
552 	int volume = ReadPref("soundVolume", 100);
553 	float volume_percent = volume / 100.0f;
554 	if (volume_percent < 0.0 || volume_percent > SOUND_MAX_VOLUME)
555 		volume_percent = 1.0;
556 	soundSetVolume(volume_percent);
557 
558 	soundSetEnable((ReadPrefHex("soundEnable")) & 0x30f);
559 	if ((ReadPrefHex("soundStereo"))) {
560 		gb_effects_config.enabled = true;
561 	}
562 	if ((ReadPrefHex("soundEcho"))) {
563 		gb_effects_config.enabled = true;
564 	}
565 	if ((ReadPrefHex("soundSurround"))) {
566 		gb_effects_config.surround = true;
567 		gb_effects_config.enabled = true;
568 	}
569 
570 	if (optFlashSize == 0)
571 		flashSetSize(0x10000);
572 	else
573 		flashSetSize(0x20000);
574 
575 	rtcEnable(rtcEnabled ? true : false);
576 	agbPrintEnable(agbPrint ? true : false);
577 
578 	for (int i = 0; i < 24;) {
579 		systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
580 		systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
581 		systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
582 		systemGbPalette[i++] = 0;
583 	}
584 
585 	systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
586 
587 	optPrintUsage = 0;
588 
589 	// TODO
590 	//int s = ReadPref("mapViewStretch", 0);
591 	//m_size = ReadPref("memViewerDataSize", 0);
592 	//m_stretch = ReadPref("GBOamViewStretch", 0);
593 	//m_stretch = ReadPref("tileViewStretch", 0);
594 	//numberType = ReadPref("cheatsNumberType", 2);
595 	//numberType = ReadPref("gbCheatsNumberType", 2);
596 	//restoreValues = ReadPref("cheatsRestore", 0) ?
597 	//scale = ReadPref("printerScale", 0);
598 	//searchType = ReadPref("cheatsSearchType", SEARCH_EQ);
599 	//searchType = ReadPref("gbCheatsSearchType",
600 	//selectedFilter = ReadPref(("selectedFilter"), 0);
601 	//sizeType = ReadPref("cheatsSizeType", 0);
602 	//sizeType = ReadPref("gbCheatsSizeType", 0);
603 	//updateValues = ReadPref("cheatsUpdate", 0);
604 	//updateValues = ReadPref("gbCheatsUpdate", 0);
605 	//valueType = ReadPref("cheatsValueType", 0);
606 	//valueType = ReadPref("gbCheatsValueType", 0);
607 
608 	ValidateConfig();
609 }
610 
CloseConfig()611 void CloseConfig()
612 {
613 	if (preferences)
614 		iniparser_freedict(preferences);
615 }
616 
FindConfigFile(char * name)617 char* FindConfigFile(char *name)
618 {
619 	char buffer[4096];
620 
621 #ifdef _WIN32
622 #define PATH_SEP ";"
623 #define FILE_SEP '\\'
624 #define EXE_NAME "vbam.exe"
625 #else // ! _WIN32
626 #define PATH_SEP ":"
627 #define FILE_SEP '/'
628 #define EXE_NAME "vbam"
629 #endif // ! _WIN32
630 
631 	if (GETCWD(buffer, 2048)) {
632 	}
633 
634 	if (FileExists(name))
635 	{
636 		return name;
637 	}
638 
639 	if (homeDir) {
640 		sprintf(path, "%s%c%s%c%s", homeDir, FILE_SEP, DOT_DIR, FILE_SEP, name);
641 		if (FileExists(path))
642 		{
643 			return path;
644 		}
645 	}
646 
647 #ifdef _WIN32
648 	char *home = getenv("USERPROFILE");
649 	if (home != NULL) {
650 		sprintf(path, "%s%c%s", home, FILE_SEP, name);
651 		if (FileExists(path))
652 		{
653 			return path;
654 		}
655 	}
656 
657 	if (!strchr(arg0, '/') &&
658 		!strchr(arg0, '\\')) {
659 		char *path = getenv("PATH");
660 
661 		if (path != NULL) {
662 			strncpy(buffer, path, 4096);
663 			buffer[4095] = 0;
664 			char *tok = strtok(buffer, PATH_SEP);
665 
666 			while (tok) {
667 				sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME);
668 				if (FileExists(path)) {
669 					char path2[2048];
670 					sprintf(path2, "%s%c%s", tok, FILE_SEP, name);
671 					if (FileExists(path2)) {
672 						return path2;
673 					}
674 				}
675 				tok = strtok(NULL, PATH_SEP);
676 			}
677 		}
678 	}
679 	else {
680 		// executable is relative to some directory
681 		strcpy(buffer, arg0);
682 		char *p = strrchr(buffer, FILE_SEP);
683 		if (p) {
684 			*p = 0;
685 			sprintf(path, "%s%c%s", buffer, FILE_SEP, name);
686 			if (FileExists(path))
687 			{
688 				return path;
689 			}
690 		}
691 	}
692 #else // ! _WIN32
693 	sprintf(path, "%s%c%s", PKGDATADIR, FILE_SEP, name);
694 	if (FileExists(path))
695 	{
696 		return path;
697 	}
698 
699 	sprintf(path, "%s%c%s", SYSCONFDIR, FILE_SEP, name);
700 	if (FileExists(path))
701 	{
702 		return path;
703 	}
704 #endif // ! _WIN32
705 	return 0;
706 }
707 
LoadConfigFile()708 void LoadConfigFile()
709 {
710 #ifndef _WIN32
711 	// Get home dir
712 	char buf[1024];
713 	struct stat s;
714 	homeDir = getenv("HOME");
715 	snprintf(buf, 1024, "%s/%s", homeDir, DOT_DIR);
716 	// Make dot dir if not existent
717 	if (stat(buf, &s) == -1 || !S_ISDIR(s.st_mode))
718 		mkdir(buf, 0755);
719 #else
720 	homeDir = 0;
721 #endif
722 
723 	if (preferences == NULL)
724 	{
725 		char* configFile = FindConfigFile("vbam.ini");
726 		OpenPreferences(configFile);
727 	}
728 
729 	if (preferences == NULL)
730 	{
731 		char* configFile = FindConfigFile("vbam.cfg");
732 		OpenPreferences(configFile);
733 	}
734 }
735 
SaveConfigFile()736 void SaveConfigFile()
737 {
738 #ifndef _WIN32
739 	// Get home dir
740 	char buf[1024];
741 	struct stat s;
742 	homeDir = getenv("HOME");
743 	snprintf(buf, 1024, "%s/%s", homeDir, DOT_DIR);
744 	// Make dot dir if not existent
745 	if (stat(buf, &s) == -1 || !S_ISDIR(s.st_mode))
746 		mkdir(buf, 0755);
747 #else
748 	homeDir = 0;
749 #endif
750 
751 	char* configFile = FindConfigFile("vbam.ini");
752 
753 	if (configFile == NULL)
754 	{
755 		configFile = FindConfigFile("vbam.cfg");
756 	}
757 
758 	if (configFile != NULL)
759 	{
760 		FILE *f = fopen(configFile, "w");
761 		// Needs mixed case version of the option name to add new options into the ini
762 		//for (int i = 0; i < (sizeof(argOptions) / sizeof(option)); i++)
763 		//{
764 		//	std::string pref = "preferences:";
765 		//	pref.append(argOptions[i].name);
766 		//	if (!iniparser_find_entry(preferences, pref.c_str()))
767 		//	{
768 		//		iniparser_set(preferences, pref.c_str(), NULL);
769 		//	}
770 		//}
771 		iniparser_dump_ini(preferences, f);
772 		fclose(f);
773 	}
774 }
775 
ReadPrefHex(char * pref_key)776 u32 ReadPrefHex(char* pref_key)
777 {
778 	LoadConfigFile();
779 	std::string pref = "preferences:";
780 	pref.append(pref_key);
781 	return fromHex(iniparser_getstring(preferences, pref.c_str(), 0));
782 }
783 
ReadPref(char * pref_key,int default_value)784 u32 ReadPref(char* pref_key, int default_value)
785 {
786 	LoadConfigFile();
787 	std::string pref = "preferences:";
788 	pref.append(pref_key);
789 	return iniparser_getint(preferences, pref.c_str(), default_value);
790 }
791 
ReadPref(char * pref_key)792 u32 ReadPref(char* pref_key)
793 {
794 	return ReadPref(pref_key, 0);
795 }
796 
ReadPrefString(char * pref_key,char * default_value)797 char* ReadPrefString(char* pref_key, char* default_value)
798 {
799 	LoadConfigFile();
800 	std::string pref = "preferences:";
801 	pref.append(pref_key);
802 	return iniparser_getstring(preferences, pref.c_str(), default_value);
803 }
804 
ReadPrefString(char * pref_key)805 char* ReadPrefString(char* pref_key)
806 {
807 	return ReadPrefString(pref_key, "");
808 }
809 
ReadOpts(int argc,char ** argv)810 int ReadOpts(int argc, char ** argv)
811 {
812 	int op = -1;
813 	while ((op = getopt_long(argc,
814 		argv,
815 		"FNO:T:Y:G:I:D:b:c:df:hi:p::s:t:v:",
816 		argOptions,
817 		NULL)) != -1) {
818 		switch (op) {
819 		case 0:
820 			// long option already processed by getopt_long
821 			break;
822 		case OPT_CHEAT:
823 			// --cheat
824 			if (preparedCheats >= MAX_CHEATS) {
825 				log("Warning: cannot add more than %d cheats.\n", MAX_CHEATS);
826 				break;
827 			}
828 		  {
829 			  //char* cpy;
830 			  //cpy = (char *)malloc(1 + strlen(optarg));
831 			  //strcpy(cpy, optarg);
832 			  //preparedCheatCodes[preparedCheats++] = cpy;
833 			std::string cpy = optarg;
834 			preparedCheatCodes[preparedCheats++] = cpy.c_str();
835 		  }
836 		  break;
837 		case OPT_AUTOFIRE:
838 			// --autofire
839 			autoFireMaxCount = fromDec(optarg);
840 			if (autoFireMaxCount < 1)
841 				autoFireMaxCount = 1;
842 			break;
843 		case 'b':
844 			useBios = true;
845 			if (optarg == NULL) {
846 				log("Missing BIOS file name\n");
847 				break;
848 			}
849 			strcpy(biosFileNameGBA, optarg);
850 			break;
851 		case 'c':
852 		{
853 			if (optarg == NULL) {
854 				log("Missing config file name\n");
855 				break;
856 			}
857 			FILE *f = fopen(optarg, "r");
858 			if (f == NULL) {
859 				log("File not found %s\n", optarg);
860 				break;
861 			}
862 			preferences = NULL;
863 			OpenPreferences(optarg);
864 			fclose(f);
865 		}
866 		break;
867 		case 'd':
868 			debugger = true;
869 			break;
870 		case 'h':
871 			optPrintUsage = 1;
872 			break;
873 		case 'i':
874 			if (optarg == NULL) {
875 				log("Missing patch name\n");
876 				break;
877 			}
878 			if (patchNum >= PATCH_MAX_NUM) {
879 				log("Too many patches given at %s (max is %d). Ignoring.\n", optarg, PATCH_MAX_NUM);
880 			}
881 			else {
882 				patchNames[patchNum] = (char *)malloc(1 + strlen(optarg));
883 				strcpy(patchNames[patchNum], optarg);
884 				patchNum++;
885 			}
886 			break;
887 		case 'G':
888 			dbgMain = remoteStubMain;
889 			dbgSignal = remoteStubSignal;
890 			dbgOutput = remoteOutput;
891 			debugger = true;
892 			if (optarg) {
893 				char *s = optarg;
894 				if (strncmp(s, "tcp:", 4) == 0) {
895 					s += 4;
896 					int port = atoi(s);
897 					remoteSetProtocol(0);
898 					remoteSetPort(port);
899 				}
900 				else if (strcmp(s, "tcp") == 0) {
901 					remoteSetProtocol(0);
902 				}
903 				else if (strcmp(s, "pipe") == 0) {
904 					remoteSetProtocol(1);
905 				}
906 				else {
907 					log("Unknown protocol %s\n", s);
908 					break;
909 				}
910 			}
911 			else {
912 				remoteSetProtocol(0);
913 			}
914 			break;
915 		case 'N':
916 			parseDebug = false;
917 			break;
918 		case 'F':
919 			fullScreen = 1;
920 			mouseCounter = 120;
921 			break;
922 		case 'f':
923 			if (optarg) {
924 				filter = (Filter)atoi(optarg);
925 			}
926 			else {
927 				filter = kStretch2x;
928 			}
929 			break;
930 		case 'I':
931 			if (optarg) {
932 				ifbType = (IFBFilter)atoi(optarg);
933 			}
934 			else {
935 				ifbType = kIFBNone;
936 			}
937 			break;
938 		case 'p':
939 #ifdef PROFILING
940 			if (optarg) {
941 				cpuEnableProfiling(atoi(optarg));
942 			}
943 			else
944 				cpuEnableProfiling(100);
945 #endif
946 			break;
947 		case 'S':
948 			optFlashSize = atoi(optarg);
949 			if (optFlashSize < 0 || optFlashSize > 1)
950 				optFlashSize = 0;
951 			break;
952 		case 's':
953 			if (optarg) {
954 				int a = atoi(optarg);
955 				if (a >= 0 && a <= 9) {
956 					gbFrameSkip = a;
957 					frameSkip = a;
958 				}
959 			}
960 			else {
961 				frameSkip = 2;
962 				gbFrameSkip = 0;
963 			}
964 			break;
965 		case 't':
966 			if (optarg) {
967 				int a = atoi(optarg);
968 				if (a < 0 || a > 5)
969 					a = 0;
970 				cpuSaveType = a;
971 			}
972 			break;
973 		case 'v':
974 			if (optarg) {
975 				systemVerbose = atoi(optarg);
976 			}
977 			else
978 				systemVerbose = 0;
979 			break;
980 		case '?':
981 			optPrintUsage = 1;
982 			break;
983 		case 'O':
984 			if (optarg) {
985 				openGL = atoi(optarg);
986 				if (openGL < 0 || openGL > 2)
987 					openGL = 1;
988 			}
989 			else
990 				openGL = 0;
991 			break;
992 
993 		case OPT_CAPTURE_FORMAT:
994 			// --capture-format
995 			if (optarg) {
996 				captureFormat = atoi(optarg);
997 			}
998 			break;
999 
1000 		case OPT_SHOW_SPEED_TRANSPARENT:
1001 			// --show-speed-transparent
1002 			if (optarg) {
1003 				showSpeedTransparent = atoi(optarg);
1004 			}
1005 			break;
1006 
1007 		case OPT_AUTO_FRAME_SKIP:
1008 			// --auto-frame-skip
1009 			if (optarg) {
1010 				autoFrameSkip = atoi(optarg);
1011 			}
1012 			break;
1013 
1014 		case OPT_AGB_PRINT:
1015 			// --agb-print
1016 			if (optarg) {
1017 				agbPrint = atoi(optarg);
1018 			}
1019 			break;
1020 
1021 		case OPT_RTC_ENABLED:
1022 			// --rtc-enabled
1023 			if (optarg) {
1024 				rtcEnabled = atoi(optarg);
1025 			}
1026 			break;
1027 
1028 		case OPT_VIDEO_OPTION:
1029 			// --video-option
1030 			if (optarg) {
1031 				videoOption = atoi(optarg);
1032 			}
1033 			break;
1034 
1035 		case OPT_LANGUAGE_OPTION:
1036 			// --language-option
1037 			if (optarg) {
1038 				languageOption = atoi(optarg);
1039 			}
1040 			break;
1041 
1042 		case OPT_GB_FRAME_SKIP:
1043 			// --gb-frame-skip
1044 			if (optarg) {
1045 				gbFrameSkip = atoi(optarg);
1046 			}
1047 			break;
1048 
1049 		case OPT_FS_ADAPTER:
1050 			// --fs-adapter
1051 			if (optarg) {
1052 				fsAdapter = atoi(optarg);
1053 			}
1054 			break;
1055 
1056 		case OPT_FS_WIDTH:
1057 			// --fs-width
1058 			if (optarg) {
1059 				fsWidth = atoi(optarg);
1060 			}
1061 			break;
1062 
1063 		case OPT_FS_HEIGHT:
1064 			// --fs-height
1065 			if (optarg) {
1066 				fsHeight = atoi(optarg);
1067 			}
1068 			break;
1069 
1070 		case OPT_FS_COLOR_DEPTH:
1071 			// --fs-color-depth
1072 			if (optarg) {
1073 				fsColorDepth = atoi(optarg);
1074 			}
1075 			break;
1076 
1077 		case OPT_FS_FREQUENCY:
1078 			// --fs-frequency
1079 			if (optarg) {
1080 				fsFrequency = atoi(optarg);
1081 			}
1082 			break;
1083 
1084 		case OPT_WINDOW_POSITION_X:
1085 			// --window-position-x
1086 			if (optarg) {
1087 				windowPositionX = atoi(optarg);
1088 			}
1089 			break;
1090 
1091 		case OPT_WINDOW_POSITION_Y:
1092 			// --window-position-y
1093 			if (optarg) {
1094 				windowPositionY = atoi(optarg);
1095 			}
1096 			break;
1097 
1098 		case OPT_SOUND_FILTERING:
1099 			// --sound-filtering
1100 			if (optarg) {
1101 				soundFiltering = atoi(optarg);
1102 			}
1103 			break;
1104 
1105 		case OPT_GL_FILTER:
1106 			// --gl-filter
1107 			if (optarg) {
1108 				glFilter = atoi(optarg);
1109 			}
1110 			break;
1111 
1112 		case OPT_SHOW_SPEED:
1113 			// --show-speed
1114 			if (optarg) {
1115 				showSpeed = atoi(optarg);
1116 			}
1117 			break;
1118 
1119 		case OPT_IFB_TYPE:
1120 			// --ifb-type
1121 			if (optarg) {
1122 				ifbType = atoi(optarg);
1123 			}
1124 			break;
1125 
1126 		case OPT_GB_EMULATOR_TYPE:
1127 			// --gb-emulator-type
1128 			if (optarg) {
1129 				gbEmulatorType = atoi(optarg);
1130 			}
1131 			break;
1132 
1133 		case OPT_THREAD_PRIORITY:
1134 			// --thread-priority
1135 			if (optarg) {
1136 				threadPriority = atoi(optarg);
1137 			}
1138 			break;
1139 
1140 		case OPT_GB_PALETTE_OPTION:
1141 			// --gb-palette-option
1142 			if (optarg) {
1143 				gbPaletteOption = atoi(optarg);
1144 			}
1145 			break;
1146 
1147 		case OPT_REWIND_TIMER:
1148 			// --rewind-timer
1149 			if (optarg) {
1150 				rewindTimer = atoi(optarg);
1151 			}
1152 			break;
1153 
1154 		case OPT_JOYPAD_DEFAULT:
1155 			// --joypad-default
1156 			if (optarg) {
1157 				joypadDefault = atoi(optarg);
1158 			}
1159 			break;
1160 
1161 		case OPT_MAX_SCALE:
1162 			// --max-scale
1163 			if (optarg) {
1164 				maxScale = atoi(optarg);
1165 			}
1166 			break;
1167 
1168 		case OPT_LINK_TIMEOUT:
1169 			// --link-timeout
1170 			if (optarg) {
1171 				linkTimeout = atoi(optarg);
1172 			}
1173 			break;
1174 
1175 		case OPT_LINK_MODE:
1176 			// --link-mode
1177 			if (optarg) {
1178 				linkMode = atoi(optarg);
1179 			}
1180 			break;
1181 
1182 		case OPT_LINK_AUTO:
1183 			// --link-auto
1184 			if (optarg) {
1185 				linkAuto = atoi(optarg);
1186 			}
1187 			break;
1188 
1189 		case OPT_LINK_HACKS:
1190 			// --link-hacks
1191 			if (optarg) {
1192 				linkHacks = atoi(optarg);
1193 			}
1194 			break;
1195 
1196 		case OPT_LINK_NUM_PLAYERS:
1197 			// --link-num-players
1198 			if (optarg) {
1199 				linkNumPlayers = atoi(optarg);
1200 			}
1201 			break;
1202 
1203 		case OPT_GDB_PORT:
1204 			// --gdb-port
1205 			if (optarg) {
1206 				gdbPort = atoi(optarg);
1207 			}
1208 			break;
1209 
1210 		case OPT_BIOS_FILE_NAME_GB:
1211 			// --bios-file-name-gb
1212 			biosFileNameGB = optarg;
1213 			break;
1214 
1215 		case OPT_BIOS_FILE_NAME_GBA:
1216 			// --bios-file-name-gba
1217 			biosFileNameGBA = optarg;
1218 			break;
1219 
1220 		case OPT_BIOS_FILE_NAME_GBC:
1221 			// --bios-file-name-gbc
1222 			biosFileNameGBC = optarg;
1223 			break;
1224 
1225 		case OPT_AVI_RECORD_DIR:
1226 			// --avi-record-dir
1227 			aviRecordDir = optarg;
1228 			break;
1229 
1230 		case OPT_MOVIE_RECORD_DIR:
1231 			// --movie-record-dir
1232 			movieRecordDir = optarg;
1233 			break;
1234 
1235 		case OPT_SOUND_RECORD_DIR:
1236 			// --sound-record-dir
1237 			soundRecordDir = optarg;
1238 			break;
1239 
1240 		case OPT_SCREEN_SHOT_DIR:
1241 			// --screen-shot-dir
1242 			screenShotDir = optarg;
1243 			break;
1244 
1245 		case OPT_SAVE_DIR:
1246 			// --save-dir
1247 			saveDir = optarg;
1248 			break;
1249 
1250 		case OPT_BATTERY_DIR:
1251 			// --battery-dir
1252 			batteryDir = optarg;
1253 			break;
1254 
1255 		case OPT_ROM_DIR_GBC:
1256 			// --rom-dir-gbc
1257 			romDirGBC = optarg;
1258 			break;
1259 
1260 		case OPT_ROM_DIR_GB:
1261 			// --rom-dir-gb
1262 			romDirGB = optarg;
1263 			break;
1264 
1265 		case OPT_ROM_DIR_GBA:
1266 			// --rom-dir-gba
1267 			romDirGBA = optarg;
1268 			break;
1269 
1270 		case OPT_LINK_HOST_ADDR:
1271 			// --link-host-addr
1272 			linkHostAddr = optarg;
1273 			break;
1274 
1275 		case OPT_CPU_SAVE_TYPE:
1276 			// --cpu-save-type
1277 			if (optarg) {
1278 				cpuSaveType = atoi(optarg);
1279 			}
1280 			break;
1281 
1282 		case OPT_OPT_FLASH_SIZE:
1283 			// --opt-flash-size
1284 			if (optarg) {
1285 				optFlashSize = atoi(optarg);
1286 			}
1287 			break;
1288 
1289 		case OPT_DOTCODE_FILE_NAME_LOAD:
1290 			// --dotcode-file-name-load
1291 			loadDotCodeFile = optarg;
1292 			break;
1293 
1294 		case OPT_DOTCODE_FILE_NAME_SAVE:
1295 			// --dotcode-file-name-save
1296 			saveDotCodeFile = optarg;
1297 			break;
1298 		}
1299 	}
1300 	return op;
1301 }
1302 
1303