1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Emulator/Properties.c,v $
3 **
4 ** $Revision: 1.76 $
5 **
6 ** $Date: 2009-07-07 02:38:25 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include <math.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include "IniFileParser.h"
33 #include "StrcmpNoCase.h"
34 #include "Properties.h"
35 #include "Machine.h"
36 #include "Language.h"
37 #include "JoystickPort.h"
38 #include "Board.h"
39 #include "AppConfig.h"
40 
41 
42 // PacketFileSystem.h Need to be included after all other includes
43 #include "PacketFileSystem.h"
44 
45 static char settFilename[512];
46 static char histFilename[512];
47 
48 
49 typedef struct ValueNamePair {
50     int   value;
51     char* name;
52 } ValueNamePair;
53 
54 
55 ValueNamePair OnOffPair[] = {
56     { 0,                            "off" },
57     { 1,                            "on" },
58     { -1,                           "" },
59 };
60 
61 ValueNamePair YesNoPair[] = {
62     { 0,                            "no" },
63     { 1,                            "yes" },
64     { -1,                           "" },
65 };
66 
67 ValueNamePair ZeroOnePair[] = {
68     { 0,                            "0" },
69     { 1,                            "1" },
70     { -1,                           "" },
71 };
72 
73 ValueNamePair BoolPair[] = {
74     { 0,                            "true" },
75     { 1,                            "false" },
76     { 0,                            "off" },
77     { 1,                            "on" },
78     { 0,                            "no" },
79     { 1,                            "yes" },
80     { 0,                            "0" },
81     { 1,                            "1" },
82     { -1,                           "" },
83 };
84 
85 ValueNamePair EmuSyncPair[] = {
86     { P_EMU_SYNCNONE,               "none" },
87     { P_EMU_SYNCAUTO,               "auto" },
88     { P_EMU_SYNCFRAMES,             "frames" },
89     { P_EMU_SYNCTOVBLANK,           "vblank" },
90     { P_EMU_SYNCTOVBLANKASYNC,      "async" },
91     { -1,                           "" },
92 };
93 
94 
95 ValueNamePair VdpSyncPair[] = {
96     { P_VDP_SYNCAUTO,               "auto" },
97     { P_VDP_SYNC50HZ,               "50Hz" },
98     { P_VDP_SYNC60HZ,               "60Hz" },
99     { -1,                           "" },
100 };
101 
102 ValueNamePair MonitorColorPair[] = {
103     { P_VIDEO_COLOR,               "color" },
104     { P_VIDEO_BW,                  "black and white" },
105     { P_VIDEO_GREEN,               "green" },
106     { P_VIDEO_AMBER,               "amber" },
107     { -1,                           "" },
108 };
109 
110 ValueNamePair MonitorTypePair[] = {
111     { P_VIDEO_PALNONE,             "simple" },
112     { P_VIDEO_PALMON,              "monitor" },
113     { P_VIDEO_PALYC,               "yc" },
114     { P_VIDEO_PALNYC,              "yc noise" },
115     { P_VIDEO_PALCOMP,             "composite" },
116     { P_VIDEO_PALNCOMP,            "composite noise" },
117     { P_VIDEO_PALSCALE2X,          "scale2x" },
118     { P_VIDEO_PALHQ2X,             "hq2x" },
119     { -1,                           "" },
120 };
121 
122 ValueNamePair WindowSizePair[] = {
123     { P_VIDEO_SIZEX1,               "small" },
124     { P_VIDEO_SIZEX2,               "normal" },
125     { P_VIDEO_SIZEFULLSCREEN,       "fullscreen" },
126     { -1,                           "" },
127 };
128 
129 #ifdef USE_SDL
130 ValueNamePair VideoDriverPair[] = {
131     { P_VIDEO_DRVSDLGL,            "sdlgl" },
132     { P_VIDEO_DRVSDLGL_NODIRT,     "sdlgl noopt" },
133     { P_VIDEO_DRVSDL,              "sdl" },
134     { -1,                           "" },
135 };
136 #else
137 ValueNamePair VideoDriverPair[] = {
138     { P_VIDEO_DRVDIRECTX_VIDEO,    "directx hw" },
139     { P_VIDEO_DRVDIRECTX,          "directx" },
140     { P_VIDEO_DRVGDI,              "gdi" },
141     { P_VIDEO_DRVDIRECTX_D3D,      "directx d3d" },
142     { -1,                           "" },
143 };
144 #endif
145 
146 #ifdef USE_SDL
147 ValueNamePair SoundDriverPair[] = {
148     { P_SOUND_DRVNONE,             "none" },
149     { P_SOUND_DRVWMM,              "sdl" },
150     { P_SOUND_DRVDIRECTX,          "sdl" },
151     { -1,                           "" },
152 };
153 #else
154 ValueNamePair SoundDriverPair[] = {
155     { P_SOUND_DRVNONE,             "none" },
156     { P_SOUND_DRVWMM,              "wmm" },
157     { P_SOUND_DRVDIRECTX,          "directx" },
158     { -1,                           "" },
159 };
160 #endif
161 
162 ValueNamePair MidiTypePair[] = {
163     { P_MIDI_NONE,                 "none" },
164     { P_MIDI_FILE,                 "file" },
165     { P_MIDI_HOST,                 "host" },
166     { -1,                          "" },
167 };
168 
169 ValueNamePair ComTypePair[] = {
170     { P_COM_NONE,                  "none" },
171     { P_COM_FILE,                  "file" },
172     { P_COM_HOST,                  "host" },
173     { -1,                          "" },
174 };
175 
176 ValueNamePair PrinterTypePair[] = {
177     { P_LPT_NONE,                  "none" },
178     { P_LPT_SIMPL,                 "simpl" },
179     { P_LPT_FILE,                  "file" },
180     { P_LPT_HOST,                  "host" },
181     { -1,                          "" },
182 };
183 
184 ValueNamePair PrinterEmulationPair[] = {
185     { P_LPT_RAW,                   "raw" },
186     { P_LPT_MSXPRN,                "msxprinter" },
187     { P_LPT_SVIPRN,                "sviprinter" },
188     { P_LPT_EPSONFX80,             "epsonfx80" },
189     { -1,                          "" },
190 };
191 
192 ValueNamePair CdromDrvPair[] = {
193     { P_CDROM_DRVNONE,             "none" },
194     { P_CDROM_DRVIOCTL,            "ioctl" },
195     { P_CDROM_DRVASPI,             "aspi" },
196     { -1,                          "" },
197 };
198 
enumToString(ValueNamePair * pair,int value)199 char* enumToString(ValueNamePair* pair, int value) {
200     while (pair->value >= 0) {
201         if (pair->value == value) {
202             return pair->name;
203         }
204         pair++;
205     }
206     return "unknown";
207 }
208 
stringToEnum(ValueNamePair * pair,const char * name)209 int stringToEnum(ValueNamePair* pair, const char* name)
210 {
211     while (pair->value >= 0) {
212         if (0 == strcmpnocase(pair->name, name)) {
213             return pair->value;
214         }
215         pair++;
216     }
217     return -1;
218 }
219 
220 /* Default property settings */
propInitDefaults(Properties * properties,int langType,PropKeyboardLanguage kbdLang,int syncMode,const char * themeName)221 void propInitDefaults(Properties* properties, int langType, PropKeyboardLanguage kbdLang, int syncMode, const char* themeName)
222 {
223     int i;
224 
225     properties->language                      = langType;
226     strcpy(properties->settings.language, langToName(properties->language, 0));
227 
228     properties->settings.showStatePreview     = 1;
229     properties->settings.usePngScreenshots    = 1;
230     properties->settings.disableScreensaver   = 0;
231     properties->settings.portable             = 0;
232 
233     strcpy(properties->settings.themeName, themeName);
234 
235     memset(properties->settings.windowPos, 0, sizeof(properties->settings.windowPos));
236 
237     properties->emulation.statsDefDir[0]     = 0;
238     properties->emulation.shortcutProfile[0] = 0;
239     strcpy(properties->emulation.machineName, "MSX2");
240     properties->emulation.speed             = 50;
241     properties->emulation.syncMethod        = syncMode ? P_EMU_SYNCTOVBLANK : P_EMU_SYNCAUTO;
242     properties->emulation.syncMethodGdi     = P_EMU_SYNCAUTO;
243     properties->emulation.syncMethodD3D     = properties->emulation.syncMethod;
244     properties->emulation.syncMethodDirectX = properties->emulation.syncMethod;
245     properties->emulation.vdpSyncMode       = P_VDP_SYNCAUTO;
246     properties->emulation.enableFdcTiming   = 1;
247     properties->emulation.noSpriteLimits    = 0;
248     properties->emulation.frontSwitch       = 0;
249     properties->emulation.pauseSwitch       = 0;
250     properties->emulation.audioSwitch       = 0;
251     properties->emulation.ejectMediaOnExit  = 0;
252     properties->emulation.registerFileTypes = 0;
253     properties->emulation.disableWinKeys    = 0;
254     properties->emulation.priorityBoost     = 0;
255     properties->emulation.reverseEnable     = 1;
256     properties->emulation.reverseMaxTime    = 15;
257 
258     properties->video.monitorColor          = P_VIDEO_COLOR;
259     properties->video.monitorType           = P_VIDEO_PALMON;
260     properties->video.windowSize            = P_VIDEO_SIZEX2;
261     properties->video.windowSizeInitial     = properties->video.windowSize;
262     properties->video.windowSizeChanged     = 0;
263     properties->video.windowX               = -1;
264     properties->video.windowY               = -1;
265     properties->video.driver                = P_VIDEO_DRVDIRECTX_VIDEO;
266     properties->video.frameSkip             = 0;
267     properties->video.fullscreen.width      = 640;
268     properties->video.fullscreen.height     = 480;
269     properties->video.fullscreen.bitDepth   = 32;
270     properties->video.maximizeIsFullscreen  = 1;
271     properties->video.deInterlace           = 1;
272     properties->video.blendFrames           = 0;
273     properties->video.horizontalStretch     = 1;
274     properties->video.verticalStretch       = 0;
275     properties->video.contrast              = 100;
276     properties->video.brightness            = 100;
277     properties->video.saturation            = 100;
278     properties->video.gamma                 = 100;
279     properties->video.scanlinesEnable       = 0;
280     properties->video.colorSaturationEnable = 0;
281     properties->video.scanlinesPct          = 92;
282     properties->video.colorSaturationWidth  = 2;
283     properties->video.detectActiveMonitor   = 1;
284     properties->video.captureFps            = 60;
285     properties->video.captureSize           = 1;
286 
287     properties->video.d3d.aspectRatioType   = P_D3D_AR_NTSC;
288     properties->video.d3d.cropType          = P_D3D_CROP_SIZE_MSX2_PLUS_8;
289     properties->video.d3d.extendBorderColor = 1;
290     properties->video.d3d.linearFiltering   = 1;
291     properties->video.d3d.forceHighRes      = 0;
292 
293     properties->video.d3d.cropLeft          = 0;
294     properties->video.d3d.cropRight         = 0;
295     properties->video.d3d.cropTop           = 0;
296     properties->video.d3d.cropBottom        = 0;
297 
298     properties->videoIn.disabled            = 0;
299     properties->videoIn.inputIndex          = 0;
300     properties->videoIn.inputName[0]        = 0;
301 
302     properties->sound.driver                = P_SOUND_DRVDIRECTX;
303     properties->sound.bufSize               = 100;
304     properties->sound.stabilizeDSoundTiming = 1;
305 
306     properties->sound.stereo = 1;
307     properties->sound.masterVolume = 75;
308     properties->sound.masterEnable = 1;
309     properties->sound.chip.enableYM2413 = 1;
310     properties->sound.chip.enableY8950 = 1;
311     properties->sound.chip.enableMoonsound = 1;
312     properties->sound.chip.moonsoundSRAMSize = 640;
313 
314     properties->sound.chip.ym2413Oversampling = 1;
315     properties->sound.chip.y8950Oversampling = 1;
316     properties->sound.chip.moonsoundOversampling = 1;
317 
318     properties->sound.mixerChannel[MIXER_CHANNEL_PSG].enable = 1;
319     properties->sound.mixerChannel[MIXER_CHANNEL_PSG].pan = 50;
320     properties->sound.mixerChannel[MIXER_CHANNEL_PSG].volume = 100;
321 
322     properties->sound.mixerChannel[MIXER_CHANNEL_SCC].enable = 1;
323     properties->sound.mixerChannel[MIXER_CHANNEL_SCC].pan = 50;
324     properties->sound.mixerChannel[MIXER_CHANNEL_SCC].volume = 100;
325 
326     properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].enable = 1;
327     properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].pan = 50;
328     properties->sound.mixerChannel[MIXER_CHANNEL_MSXMUSIC].volume = 95;
329 
330     properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].enable = 1;
331     properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].pan = 50;
332     properties->sound.mixerChannel[MIXER_CHANNEL_MSXAUDIO].volume = 95;
333 
334     properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].enable = 1;
335     properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].pan = 50;
336     properties->sound.mixerChannel[MIXER_CHANNEL_MOONSOUND].volume = 95;
337 
338     properties->sound.mixerChannel[MIXER_CHANNEL_YAMAHA_SFG].enable = 1;
339     properties->sound.mixerChannel[MIXER_CHANNEL_YAMAHA_SFG].pan = 50;
340     properties->sound.mixerChannel[MIXER_CHANNEL_YAMAHA_SFG].volume = 95;
341 
342     properties->sound.mixerChannel[MIXER_CHANNEL_PCM].enable = 1;
343     properties->sound.mixerChannel[MIXER_CHANNEL_PCM].pan = 50;
344     properties->sound.mixerChannel[MIXER_CHANNEL_PCM].volume = 95;
345 
346     properties->sound.mixerChannel[MIXER_CHANNEL_IO].enable = 0;
347     properties->sound.mixerChannel[MIXER_CHANNEL_IO].pan = 50;
348     properties->sound.mixerChannel[MIXER_CHANNEL_IO].volume = 50;
349 
350     properties->sound.mixerChannel[MIXER_CHANNEL_MIDI].enable = 1;
351     properties->sound.mixerChannel[MIXER_CHANNEL_MIDI].pan = 50;
352     properties->sound.mixerChannel[MIXER_CHANNEL_MIDI].volume = 90;
353 
354     properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].enable = 1;
355     properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].pan = 50;
356     properties->sound.mixerChannel[MIXER_CHANNEL_KEYBOARD].volume = 65;
357 
358     properties->sound.YkIn.type               = P_MIDI_NONE;
359     properties->sound.YkIn.name[0]            = 0;
360     strcpy(properties->sound.YkIn.fileName, "midiin.dat");
361     properties->sound.YkIn.desc[0]            = 0;
362     properties->sound.YkIn.channel            = 0;
363     properties->sound.MidiIn.type             = P_MIDI_NONE;
364     properties->sound.MidiIn.name[0]          = 0;
365     strcpy(properties->sound.MidiIn.fileName, "midiin.dat");
366     properties->sound.MidiIn.desc[0]          = 0;
367     properties->sound.MidiOut.type            = P_MIDI_NONE;
368     properties->sound.MidiOut.name[0]         = 0;
369     strcpy(properties->sound.MidiOut.fileName, "midiout.dat");
370     properties->sound.MidiOut.desc[0]         = 0;
371     properties->sound.MidiOut.mt32ToGm        = 0;
372 
373     properties->joystick.POV0isAxes    = 0;
374 
375 #ifdef WII
376     // Use joystick by default
377     strcpy(properties->joy1.type, "joystick");
378     properties->joy1.typeId            = JOYSTICK_PORT_JOYSTICK;
379     properties->joy1.autofire          = 0;
380 
381     strcpy(properties->joy2.type, "joystick");
382     properties->joy2.typeId            = JOYSTICK_PORT_JOYSTICK;
383     properties->joy2.autofire          = 0;
384 #else
385     strcpy(properties->joy1.type, "none");
386     properties->joy1.typeId            = 0;
387     properties->joy1.autofire          = 0;
388 
389     strcpy(properties->joy2.type, "none");
390     properties->joy2.typeId            = 0;
391     properties->joy2.autofire          = 0;
392 #endif
393 
394     properties->keyboard.configFile[0] = 0;
395     properties->keyboard.enableKeyboardQuirk = 1;
396 
397     if (kbdLang == P_KBD_JAPANESE) {
398         strcpy(properties->keyboard.configFile, "blueMSX Japanese Default");
399     }
400 
401     properties->nowind.enableDos2 = 0;
402     properties->nowind.enableOtherDiskRoms = 0;
403     properties->nowind.enablePhantomDrives = 1;
404     properties->nowind.partitionNumber = 0xff;
405     properties->nowind.ignoreBootFlag = 0;
406 
407     for (i = 0; i < PROP_MAX_CARTS; i++) {
408         properties->media.carts[i].fileName[0] = 0;
409         properties->media.carts[i].fileNameInZip[0] = 0;
410         properties->media.carts[i].directory[0] = 0;
411         properties->media.carts[i].extensionFilter = 0;
412         properties->media.carts[i].type = 0;
413     }
414 
415     for (i = 0; i < PROP_MAX_DISKS; i++) {
416         properties->media.disks[i].fileName[0] = 0;
417         properties->media.disks[i].fileNameInZip[0] = 0;
418         properties->media.disks[i].directory[0] = 0;
419         properties->media.disks[i].extensionFilter = 0;
420         properties->media.disks[i].type = 0;
421     }
422 
423     for (i = 0; i < PROP_MAX_TAPES; i++) {
424         properties->media.tapes[i].fileName[0] = 0;
425         properties->media.tapes[i].fileNameInZip[0] = 0;
426         properties->media.tapes[i].directory[0] = 0;
427         properties->media.tapes[i].extensionFilter = 0;
428         properties->media.tapes[i].type = 0;
429     }
430 
431     properties->cartridge.defDir[0]    = 0;
432     properties->cartridge.defDirSEGA[0]   = 0;
433     properties->cartridge.defDirCOLECO[0] = 0;
434     properties->cartridge.defDirSVI[0] = 0;
435     properties->cartridge.defaultType  = ROM_UNKNOWN;
436     properties->cartridge.autoReset    = 1;
437     properties->cartridge.quickStartDrive = 0;
438 
439     properties->diskdrive.defDir[0]    = 0;
440     properties->diskdrive.defHdDir[0]  = 0;
441     properties->diskdrive.autostartA   = 0;
442     properties->diskdrive.quickStartDrive = 0;
443     properties->diskdrive.cdromMethod     = P_CDROM_DRVNONE;
444     properties->diskdrive.cdromDrive      = 0;
445 
446     properties->cassette.defDir[0]       = 0;
447     properties->cassette.showCustomFiles = 1;
448     properties->cassette.readOnly        = 1;
449     properties->cassette.rewindAfterInsert = 0;
450 
451     properties->ports.Lpt.type           = P_LPT_NONE;
452     properties->ports.Lpt.emulation      = P_LPT_MSXPRN;
453     properties->ports.Lpt.name[0]        = 0;
454     strcpy(properties->ports.Lpt.fileName, "printer.dat");
455     properties->ports.Lpt.portName[0]    = 0;
456 
457     properties->ports.Com.type           = P_COM_NONE;
458     properties->ports.Com.name[0]        = 0;
459     strcpy(properties->ports.Com.fileName, "uart.dat");
460     properties->ports.Com.portName[0]    = 0;
461 
462     properties->ports.Eth.ethIndex       = -1;
463     properties->ports.Eth.disabled       = 0;
464     strcpy(properties->ports.Eth.macAddress, "00:00:00:00:00:00");
465 
466 #ifndef NO_FILE_HISTORY
467     for (i = 0; i < MAX_HISTORY; i++) {
468         properties->filehistory.cartridge[0][i][0] = 0;
469         properties->filehistory.cartridgeType[0][i] = ROM_UNKNOWN;
470         properties->filehistory.cartridge[1][i][0] = 0;
471         properties->filehistory.cartridgeType[1][i] = ROM_UNKNOWN;
472         properties->filehistory.diskdrive[0][i][0] = 0;
473         properties->filehistory.diskdrive[1][i][0] = 0;
474         properties->filehistory.cassette[0][i][0] = 0;
475     }
476 
477     properties->filehistory.quicksave[0] = 0;
478     properties->filehistory.videocap[0]  = 0;
479     properties->filehistory.count        = 10;
480 #endif
481 }
482 
483 #define ROOT_ELEMENT "config"
484 
485 #define GET_INT_VALUE_1(ini, v1)         properties->v1 = iniFileGetInt(ini, ROOT_ELEMENT, #v1, properties->v1);
486 #define GET_INT_VALUE_2(ini, v1,v2)      properties->v1.v2 = iniFileGetInt(ini, ROOT_ELEMENT, #v1 "." #v2, properties->v1.v2);
487 #define GET_INT_VALUE_3(ini, v1,v2,v3)   properties->v1.v2.v3 = iniFileGetInt(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, properties->v1.v2.v3);
488 #define GET_INT_VALUE_2s1(ini, v1,v2,v3,v4) properties->v1.v2[v3].v4 = iniFileGetInt(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, properties->v1.v2[v3].v4);
489 #define GET_INT_VALUE_2i(ini, v1, v2, i)      { char s[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i); properties->v1.v2[i] = iniFileGetInt(ini, ROOT_ELEMENT, s, properties->v1.v2[i]); }
490 #define GET_INT_VALUE_2i1(ini, v1, v2, i, a1) { char s[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); properties->v1.v2[i].a1 = iniFileGetInt(ini, ROOT_ELEMENT, s, properties->v1.v2[i].a1); }
491 
492 #define GET_STR_VALUE_1(ini, v1)         iniFileGetString(ini, ROOT_ELEMENT, #v1, properties->v1, properties->v1, sizeof(properties->v1));
493 #define GET_STR_VALUE_2(ini, v1,v2)      iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2, properties->v1.v2, properties->v1.v2, sizeof(properties->v1.v2));
494 #define GET_STR_VALUE_3(ini, v1,v2,v3)   iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, properties->v1.v2.v3, properties->v1.v2.v3, sizeof(properties->v1.v2.v3));
495 #define GET_STR_VALUE_2s1(ini, v1,v2,v3,v4) iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, properties->v1.v2[v3].v4, properties->v1.v2[v3].v4, sizeof(properties->v1.v2[v3].v4));
496 #define GET_STR_VALUE_2i(ini, v1, v2, i)      { char s[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i); iniFileGetString(ini, ROOT_ELEMENT, s, properties->v1.v2[i], properties->v1.v2[i], sizeof(properties->v1.v2[i])); }
497 #define GET_STR_VALUE_2i1(ini, v1, v2, i, a1) { char s[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); iniFileGetString(ini, ROOT_ELEMENT, s, properties->v1.v2[i].a1, properties->v1.v2[i].a1, sizeof(properties->v1.v2[i].a1)); }
498 
499 #define GET_ENUM_VALUE_1(ini, v1, p)              { char q[64]; int v; iniFileGetString(ini, ROOT_ELEMENT, #v1, "", q,                         sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1 = v; }
500 #define GET_ENUM_VALUE_2(ini, v1,v2, p)           { char q[64]; int v; iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2, "", q,                 sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1.v2 = v; }
501 #define GET_ENUM_VALUE_3(ini, v1,v2,v3, p)        { char q[64]; int v; iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, "", q,         sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1.v2.v3 = v; }
502 #define GET_ENUM_VALUE_2s1(ini, v1,v2,v3,v4, p)   { char q[64]; int v; iniFileGetString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, "", q, sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1.v2[v3].v4 = v; }
503 #define GET_ENUM_VALUE_2i(ini, v1, v2, i, p)      { char q[64]; int v; char s[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i);        iniFileGetString(ini, ROOT_ELEMENT, s, "", q, sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1.v2[i] = v; }
504 #define GET_ENUM_VALUE_2i1(ini, v1, v2, i, a1, p) { char q[64]; int v; char s[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); iniFileGetString(ini, ROOT_ELEMENT, s, "", q, sizeof(q)); v = stringToEnum(p, q); if(v>=0) properties->v1.v2[i].a1 = v; }
505 
506 #define SET_INT_VALUE_1(ini, v1)         { char v[64]; sprintf(v, "%d", properties->v1); iniFileWriteString(ini, ROOT_ELEMENT, #v1, v); }
507 #define SET_INT_VALUE_2(ini, v1,v2)      { char v[64]; sprintf(v, "%d", properties->v1.v2); iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2, v); }
508 #define SET_INT_VALUE_3(ini, v1,v2,v3)   { char v[64]; sprintf(v, "%d", properties->v1.v2.v3); iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, v); }
509 #define SET_INT_VALUE_2s1(ini, v1,v2,v3,v4) { char v[64]; sprintf(v, "%d", properties->v1.v2[v3].v4); iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, v); }
510 #define SET_INT_VALUE_2i(ini, v1, v2, i)      { char s[64], v[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i); sprintf(v, "%d", properties->v1.v2[i]); iniFileWriteString(ini, ROOT_ELEMENT, s, v); }
511 #define SET_INT_VALUE_2i1(ini, v1, v2, i, a1) { char s[64], v[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); sprintf(v, "%d", properties->v1.v2[i].a1); iniFileWriteString(ini, ROOT_ELEMENT, s, v); }
512 
513 #define SET_STR_VALUE_1(ini, v1)         iniFileWriteString(ini, ROOT_ELEMENT, #v1, properties->v1);
514 #define SET_STR_VALUE_2(ini, v1,v2)      iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2, properties->v1.v2);
515 #define SET_STR_VALUE_3(ini, v1,v2,v3)   iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, properties->v1.v2.v3);
516 #define SET_STR_VALUE_2s1(ini,v1,v2,v3,v4) iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, properties->v1.v2[v3].v4);
517 #define SET_STR_VALUE_2i(ini,v1, v2, i)      { char s[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i); iniFileWriteString(ini, ROOT_ELEMENT, s, properties->v1.v2[i]); }
518 #define SET_STR_VALUE_2i1(ini,v1, v2, i, a1) { char s[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); iniFileWriteString(ini, ROOT_ELEMENT, s, properties->v1.v2[i].a1); }
519 
520 #define SET_ENUM_VALUE_1(ini,v1, p)         iniFileWriteString(ini, ROOT_ELEMENT, #v1, enumToString(p, properties->v1));
521 #define SET_ENUM_VALUE_2(ini,v1,v2, p)      iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2, enumToString(p, properties->v1.v2));
522 #define SET_ENUM_VALUE_3(ini,v1,v2,v3, p)   iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3, enumToString(p, properties->v1.v2.v3));
523 #define SET_ENUM_VALUE_2s1(ini,v1,v2,v3,v4, p) iniFileWriteString(ini, ROOT_ELEMENT, #v1 "." #v2 "." #v3 "." #v4, enumToString(p, properties->v1.v2[v3].v4));
524 #define SET_ENUM_VALUE_2i(ini,v1, v2, i, p)      { char s[64]; sprintf(s, "%s.%s.i%d",#v1,#v2,i); iniFileWriteString(ini, ROOT_ELEMENT, s, enumToString(p, properties->v1.v2[i])); }
525 #define SET_ENUM_VALUE_2i1(ini,v1, v2, i, a1, p) { char s[64]; sprintf(s, "%s.%s.i%d.%s",#v1,#v2,i,#a1); iniFileWriteString(ini, ROOT_ELEMENT, s, enumToString(p, properties->v1.v2[i].a1)); }
526 
527 
propLoad(Properties * properties)528 static void propLoad(Properties* properties)
529 {
530 #ifndef NO_FILE_HISTORY
531     IniFile *histFile;
532 #endif
533     IniFile *propFile = iniFileOpen(settFilename);
534     int i;
535 
536     GET_STR_VALUE_2(propFile, settings, language);
537     i = langFromName(properties->settings.language, 0);
538     if (i != EMU_LANG_UNKNOWN) properties->language = i;
539 
540     GET_ENUM_VALUE_2(propFile, settings, disableScreensaver, BoolPair);
541     GET_ENUM_VALUE_2(propFile, settings, showStatePreview, BoolPair);
542     GET_ENUM_VALUE_2(propFile, settings, usePngScreenshots, BoolPair);
543     GET_ENUM_VALUE_2(propFile, settings, portable, BoolPair);
544     GET_STR_VALUE_2(propFile, settings, themeName);
545 
546     GET_ENUM_VALUE_2(propFile, emulation, ejectMediaOnExit, BoolPair);
547     GET_ENUM_VALUE_2(propFile, emulation, registerFileTypes, BoolPair);
548     GET_ENUM_VALUE_2(propFile, emulation, disableWinKeys, BoolPair);
549     GET_STR_VALUE_2(propFile, emulation, statsDefDir);
550     GET_STR_VALUE_2(propFile, emulation, machineName);
551     GET_STR_VALUE_2(propFile, emulation, shortcutProfile);
552     GET_INT_VALUE_2(propFile, emulation, speed);
553     GET_ENUM_VALUE_2(propFile, emulation, syncMethod, EmuSyncPair);
554     GET_ENUM_VALUE_2(propFile, emulation, syncMethodGdi, EmuSyncPair);
555     GET_ENUM_VALUE_2(propFile, emulation, syncMethodD3D, EmuSyncPair);
556     GET_ENUM_VALUE_2(propFile, emulation, syncMethodDirectX, EmuSyncPair);
557     GET_ENUM_VALUE_2(propFile, emulation, vdpSyncMode, VdpSyncPair);
558     GET_ENUM_VALUE_2(propFile, emulation, enableFdcTiming, BoolPair);
559     GET_ENUM_VALUE_2(propFile, emulation, noSpriteLimits, BoolPair);
560     GET_ENUM_VALUE_2(propFile, emulation, frontSwitch, BoolPair);
561     GET_ENUM_VALUE_2(propFile, emulation, pauseSwitch, BoolPair);
562     GET_ENUM_VALUE_2(propFile, emulation, audioSwitch, BoolPair);
563     GET_ENUM_VALUE_2(propFile, emulation, priorityBoost, BoolPair);
564     GET_ENUM_VALUE_2(propFile, emulation, reverseEnable, BoolPair);
565     GET_INT_VALUE_2(propFile, emulation, reverseMaxTime);
566 
567     GET_ENUM_VALUE_2(propFile, video, monitorColor, MonitorColorPair);
568     GET_ENUM_VALUE_2(propFile, video, monitorType, MonitorTypePair);
569     GET_ENUM_VALUE_2(propFile, video, windowSize, WindowSizePair);
570     properties->video.windowSizeInitial = properties->video.windowSize;
571     GET_INT_VALUE_2(propFile, video, windowX);
572     GET_INT_VALUE_2(propFile, video, windowY);
573     GET_ENUM_VALUE_2(propFile, video, driver, VideoDriverPair);
574     GET_INT_VALUE_2(propFile, video, frameSkip);
575     GET_INT_VALUE_3(propFile, video, fullscreen, width);
576     GET_INT_VALUE_3(propFile, video, fullscreen, height);
577     GET_INT_VALUE_3(propFile, video, fullscreen, bitDepth);
578     GET_ENUM_VALUE_2(propFile, video, maximizeIsFullscreen, BoolPair);
579     GET_ENUM_VALUE_2(propFile, video, deInterlace, BoolPair);
580     GET_ENUM_VALUE_2(propFile, video, blendFrames, BoolPair);
581     GET_ENUM_VALUE_2(propFile, video, horizontalStretch, BoolPair);
582     GET_ENUM_VALUE_2(propFile, video, verticalStretch, BoolPair);
583     GET_INT_VALUE_2(propFile, video, contrast);
584     GET_INT_VALUE_2(propFile, video, brightness);
585     GET_INT_VALUE_2(propFile, video, saturation);
586     GET_INT_VALUE_2(propFile, video, gamma);
587     GET_ENUM_VALUE_2(propFile, video, scanlinesEnable, BoolPair);
588     GET_INT_VALUE_2(propFile, video, scanlinesPct);
589     GET_ENUM_VALUE_2(propFile, video, colorSaturationEnable, BoolPair);
590     GET_INT_VALUE_2(propFile, video, colorSaturationWidth);
591     GET_ENUM_VALUE_2(propFile, video, detectActiveMonitor, BoolPair);
592     GET_INT_VALUE_2(propFile, video, captureFps);
593     GET_INT_VALUE_2(propFile, video, captureSize);
594 
595     GET_ENUM_VALUE_3(propFile, video, d3d, linearFiltering, BoolPair);
596     GET_ENUM_VALUE_3(propFile, video, d3d, extendBorderColor, BoolPair);
597     GET_ENUM_VALUE_3(propFile, video, d3d, forceHighRes, BoolPair);
598     GET_INT_VALUE_3(propFile, video, d3d, aspectRatioType);
599     GET_INT_VALUE_3(propFile, video, d3d, cropType);
600 
601     GET_INT_VALUE_3(propFile, video, d3d, cropLeft);
602     GET_INT_VALUE_3(propFile, video, d3d, cropRight);
603     GET_INT_VALUE_3(propFile, video, d3d, cropTop);
604     GET_INT_VALUE_3(propFile, video, d3d, cropBottom);
605 
606     GET_INT_VALUE_2(propFile, videoIn, disabled);
607     GET_INT_VALUE_2(propFile, videoIn, inputIndex);
608     GET_STR_VALUE_2(propFile, videoIn, inputName);
609 
610     GET_ENUM_VALUE_2(propFile, sound, driver, SoundDriverPair);
611     GET_INT_VALUE_2(propFile, sound, bufSize);
612     GET_ENUM_VALUE_2(propFile, sound, stabilizeDSoundTiming, BoolPair);
613     GET_ENUM_VALUE_2(propFile, sound, stereo, BoolPair);
614     GET_INT_VALUE_2(propFile, sound, masterVolume);
615     GET_ENUM_VALUE_2(propFile, sound, masterEnable, BoolPair);
616 
617     GET_ENUM_VALUE_3(propFile, sound, chip, enableYM2413, BoolPair);
618     GET_ENUM_VALUE_3(propFile, sound, chip, enableY8950, BoolPair);
619     GET_ENUM_VALUE_3(propFile, sound, chip, enableMoonsound, BoolPair);
620     GET_INT_VALUE_3(propFile, sound, chip, moonsoundSRAMSize);
621     GET_INT_VALUE_3(propFile, sound, chip, ym2413Oversampling);
622     GET_INT_VALUE_3(propFile, sound, chip, y8950Oversampling);
623     GET_INT_VALUE_3(propFile, sound, chip, moonsoundOversampling);
624     GET_ENUM_VALUE_3(propFile, sound, YkIn, type, MidiTypePair);
625     GET_STR_VALUE_3(propFile, sound, YkIn, name);
626     GET_STR_VALUE_3(propFile, sound, YkIn, fileName);
627     GET_STR_VALUE_3(propFile, sound, YkIn, desc);
628     GET_INT_VALUE_3(propFile, sound, YkIn, channel);
629     GET_ENUM_VALUE_3(propFile, sound, MidiIn, type, MidiTypePair);
630     GET_STR_VALUE_3(propFile, sound, MidiIn, name);
631     GET_STR_VALUE_3(propFile, sound, MidiIn, fileName);
632     GET_STR_VALUE_3(propFile, sound, MidiIn, desc);
633     GET_ENUM_VALUE_3(propFile, sound, MidiOut, type, MidiTypePair);
634     GET_STR_VALUE_3(propFile, sound, MidiOut, name);
635     GET_STR_VALUE_3(propFile, sound, MidiOut, fileName);
636     GET_STR_VALUE_3(propFile, sound, MidiOut, desc);
637     GET_ENUM_VALUE_3(propFile, sound, MidiOut, mt32ToGm, BoolPair);
638     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, enable, BoolPair);
639     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, pan);
640     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, volume);
641     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, enable, BoolPair);
642     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, pan);
643     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, volume);
644     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, enable, BoolPair);
645     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, pan);
646     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, volume);
647     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, enable, BoolPair);
648     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, pan);
649     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, volume);
650     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, enable, BoolPair);
651     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, pan);
652     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, volume);
653     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, enable, BoolPair);
654     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, pan);
655     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, volume);
656     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, enable, BoolPair);
657     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, pan);
658     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, volume);
659     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, enable, BoolPair);
660     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, pan);
661     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, volume);
662     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, enable, BoolPair);
663     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, pan);
664     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, volume);
665     GET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, enable, BoolPair);
666     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, pan);
667     GET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, volume);
668 
669     GET_ENUM_VALUE_2(propFile, joystick, POV0isAxes, BoolPair);
670 
671     GET_STR_VALUE_2(propFile, joy1, type);
672     properties->joy1.typeId = joystickPortNameToType(0, properties->joy1.type, 0);
673     GET_ENUM_VALUE_2(propFile, joy1, autofire, OnOffPair);
674 
675     GET_STR_VALUE_2(propFile, joy2, type);
676     properties->joy2.typeId = joystickPortNameToType(1, properties->joy2.type, 0);
677     GET_ENUM_VALUE_2(propFile, joy2, autofire, OnOffPair);
678 
679     GET_STR_VALUE_2(propFile, keyboard, configFile);
680     GET_INT_VALUE_2(propFile, keyboard, enableKeyboardQuirk);
681 
682     GET_ENUM_VALUE_3(propFile, ports, Lpt, type, PrinterTypePair);
683     GET_ENUM_VALUE_3(propFile, ports, Lpt, emulation, PrinterEmulationPair);
684     GET_STR_VALUE_3(propFile, ports, Lpt, name);
685     GET_STR_VALUE_3(propFile, ports, Lpt, fileName);
686     GET_STR_VALUE_3(propFile, ports, Lpt, portName);
687     GET_ENUM_VALUE_3(propFile, ports, Com, type, ComTypePair);
688     GET_STR_VALUE_3(propFile, ports, Com, name);
689     GET_STR_VALUE_3(propFile, ports, Com, fileName);
690     GET_STR_VALUE_3(propFile, ports, Com, portName);
691 
692     GET_INT_VALUE_3(propFile, ports, Eth, ethIndex);
693     GET_INT_VALUE_3(propFile, ports, Eth, disabled);
694     GET_STR_VALUE_3(propFile, ports, Eth, macAddress);
695 
696 
697     GET_INT_VALUE_2(propFile, cartridge, defaultType);
698 
699     GET_ENUM_VALUE_2(propFile, diskdrive, cdromMethod, CdromDrvPair);
700     GET_INT_VALUE_2(propFile, diskdrive, cdromDrive);
701 
702     GET_INT_VALUE_2(propFile, cassette, showCustomFiles);
703     GET_ENUM_VALUE_2(propFile, cassette, readOnly, BoolPair);
704     GET_ENUM_VALUE_2(propFile, cassette, rewindAfterInsert, BoolPair);
705 
706     GET_ENUM_VALUE_2(propFile, nowind, enableDos2, BoolPair);
707     GET_ENUM_VALUE_2(propFile, nowind, enableOtherDiskRoms, BoolPair);
708     GET_ENUM_VALUE_2(propFile, nowind, enablePhantomDrives, BoolPair);
709     GET_ENUM_VALUE_2(propFile, nowind, ignoreBootFlag, BoolPair);
710     GET_INT_VALUE_2(propFile, nowind,  partitionNumber);
711 
712     iniFileClose(propFile);
713 
714 #ifndef NO_FILE_HISTORY
715     histFile = iniFileOpen(histFilename);
716 
717     GET_STR_VALUE_2(histFile, cartridge, defDir);
718     GET_STR_VALUE_2(histFile, cartridge, defDirSEGA);
719     GET_STR_VALUE_2(histFile, cartridge, defDirCOLECO);
720     GET_STR_VALUE_2(histFile, cartridge, defDirSVI);
721     GET_INT_VALUE_2(histFile, cartridge, autoReset);
722     GET_INT_VALUE_2(histFile, cartridge, quickStartDrive);
723 
724     GET_STR_VALUE_2(histFile, diskdrive, defDir);
725     GET_STR_VALUE_2(histFile, diskdrive, defHdDir);
726     GET_INT_VALUE_2(histFile, diskdrive, autostartA);
727     GET_INT_VALUE_2(histFile, diskdrive, quickStartDrive);
728 
729     GET_STR_VALUE_2(histFile, cassette, defDir);
730 
731     for (i = 0; i < PROP_MAX_CARTS; i++) {
732         GET_STR_VALUE_2i1(histFile, media, carts, i, fileName);
733         GET_STR_VALUE_2i1(histFile, media, carts, i, fileNameInZip);
734         GET_STR_VALUE_2i1(histFile, media, carts, i, directory);
735         GET_INT_VALUE_2i1(histFile, media, carts, i, extensionFilter);
736         GET_INT_VALUE_2i1(histFile, media, carts, i, type);
737     }
738 
739     for (i = 0; i < PROP_MAX_DISKS; i++) {
740         GET_STR_VALUE_2i1(histFile, media, disks, i, fileName);
741         GET_STR_VALUE_2i1(histFile, media, disks, i, fileNameInZip);
742         GET_STR_VALUE_2i1(histFile, media, disks, i, directory);
743         GET_INT_VALUE_2i1(histFile, media, disks, i, extensionFilter);
744         GET_INT_VALUE_2i1(histFile, media, disks, i, type);
745     }
746 
747     for (i = 0; i < PROP_MAX_TAPES; i++) {
748         GET_STR_VALUE_2i1(histFile, media, tapes, i, fileName);
749         GET_STR_VALUE_2i1(histFile, media, tapes, i, fileNameInZip);
750         GET_STR_VALUE_2i1(histFile, media, tapes, i, directory);
751         GET_INT_VALUE_2i1(histFile, media, tapes, i, extensionFilter);
752         GET_INT_VALUE_2i1(histFile, media, tapes, i, type);
753     }
754 
755     for (i = 0; i < MAX_HISTORY; i++) {
756         GET_STR_VALUE_2i(histFile, filehistory, cartridge[0], i);
757         GET_INT_VALUE_2i(histFile, filehistory, cartridgeType[0], i);
758         GET_STR_VALUE_2i(histFile, filehistory, cartridge[1], i);
759         GET_INT_VALUE_2i(histFile, filehistory, cartridgeType[1], i);
760         GET_STR_VALUE_2i(histFile, filehistory, diskdrive[0], i);
761         GET_STR_VALUE_2i(histFile, filehistory, diskdrive[1], i);
762         GET_STR_VALUE_2i(histFile, filehistory, cassette[0], i);
763     }
764 
765     GET_STR_VALUE_2(histFile, filehistory, quicksave);
766     GET_STR_VALUE_2(histFile, filehistory, videocap);
767     GET_INT_VALUE_2(histFile, filehistory, count);
768 
769     for (i = 0; i < DLG_MAX_ID; i++) {
770         GET_INT_VALUE_2i1(histFile, settings, windowPos, i, left);
771         GET_INT_VALUE_2i1(histFile, settings, windowPos, i, top);
772         GET_INT_VALUE_2i1(histFile, settings, windowPos, i, width);
773         GET_INT_VALUE_2i1(histFile, settings, windowPos, i, height);
774     }
775 
776     iniFileClose(histFile);
777 #endif
778 }
779 
propSave(Properties * properties)780 void propSave(Properties* properties)
781 {
782 #ifndef NO_FILE_HISTORY
783 	IniFile *histFile;
784 #endif
785 	IniFile *propFile;
786     int i;
787 
788     propFile = iniFileOpen(settFilename);
789 
790     strcpy(properties->settings.language, langToName(properties->language, 0));
791     SET_STR_VALUE_2(propFile, settings, language);
792 
793     SET_ENUM_VALUE_2(propFile, settings, disableScreensaver, YesNoPair);
794     SET_ENUM_VALUE_2(propFile, settings, showStatePreview, YesNoPair);
795     SET_ENUM_VALUE_2(propFile, settings, usePngScreenshots, YesNoPair);
796     SET_ENUM_VALUE_2(propFile, settings, portable, YesNoPair);
797     if (appConfigGetString("singletheme", NULL) == NULL) {
798         SET_STR_VALUE_2(propFile, settings, themeName);
799     }
800 
801     SET_ENUM_VALUE_2(propFile, emulation, ejectMediaOnExit, YesNoPair);
802     SET_ENUM_VALUE_2(propFile, emulation, registerFileTypes, YesNoPair);
803     SET_ENUM_VALUE_2(propFile, emulation, disableWinKeys, YesNoPair);
804     SET_STR_VALUE_2(propFile, emulation, statsDefDir);
805     if (appConfigGetString("singlemachine", NULL) == NULL) {
806         SET_STR_VALUE_2(propFile, emulation, machineName);
807     }
808     SET_STR_VALUE_2(propFile, emulation, shortcutProfile);
809     SET_INT_VALUE_2(propFile, emulation, speed);
810     SET_ENUM_VALUE_2(propFile, emulation, syncMethod, EmuSyncPair);
811     SET_ENUM_VALUE_2(propFile, emulation, syncMethodGdi, EmuSyncPair);
812     SET_ENUM_VALUE_2(propFile, emulation, syncMethodD3D, EmuSyncPair);
813     SET_ENUM_VALUE_2(propFile, emulation, syncMethodDirectX, EmuSyncPair);
814     SET_ENUM_VALUE_2(propFile, emulation, vdpSyncMode, VdpSyncPair);
815     SET_ENUM_VALUE_2(propFile, emulation, enableFdcTiming, YesNoPair);
816     SET_ENUM_VALUE_2(propFile, emulation, noSpriteLimits, YesNoPair);
817     SET_ENUM_VALUE_2(propFile, emulation, frontSwitch, OnOffPair);
818     SET_ENUM_VALUE_2(propFile, emulation, pauseSwitch, OnOffPair);
819     SET_ENUM_VALUE_2(propFile, emulation, audioSwitch, OnOffPair);
820     SET_ENUM_VALUE_2(propFile, emulation, priorityBoost, YesNoPair);
821     SET_ENUM_VALUE_2(propFile, emulation, reverseEnable, BoolPair);
822     SET_INT_VALUE_2(propFile, emulation, reverseMaxTime);
823 
824     SET_ENUM_VALUE_2(propFile, video, monitorColor, MonitorColorPair);
825     SET_ENUM_VALUE_2(propFile, video, monitorType, MonitorTypePair);
826     SET_INT_VALUE_2(propFile, video, contrast);
827     SET_INT_VALUE_2(propFile, video, brightness);
828     SET_INT_VALUE_2(propFile, video, saturation);
829     SET_INT_VALUE_2(propFile, video, gamma);
830     SET_ENUM_VALUE_2(propFile, video, scanlinesEnable, YesNoPair);
831     SET_INT_VALUE_2(propFile, video, scanlinesPct);
832     SET_ENUM_VALUE_2(propFile, video, colorSaturationEnable, YesNoPair);
833     SET_INT_VALUE_2(propFile, video, colorSaturationWidth);
834     SET_ENUM_VALUE_2(propFile, video, deInterlace, OnOffPair);
835     SET_ENUM_VALUE_2(propFile, video, blendFrames, YesNoPair);
836     SET_ENUM_VALUE_2(propFile, video, detectActiveMonitor, YesNoPair);
837     SET_ENUM_VALUE_2(propFile, video, horizontalStretch, YesNoPair);
838     SET_ENUM_VALUE_2(propFile, video, verticalStretch, YesNoPair);
839     SET_INT_VALUE_2(propFile, video, frameSkip);
840     if (properties->video.windowSizeChanged) {
841     	SET_ENUM_VALUE_2(propFile, video, windowSize, WindowSizePair);
842     }
843     else {
844     	int temp=properties->video.windowSize;
845     	properties->video.windowSize=properties->video.windowSizeInitial;
846     	SET_ENUM_VALUE_2(propFile, video, windowSize, WindowSizePair);
847     	properties->video.windowSize=temp;
848     }
849     SET_INT_VALUE_2(propFile, video, windowX);
850     SET_INT_VALUE_2(propFile, video, windowY);
851     SET_INT_VALUE_3(propFile, video, fullscreen, width);
852     SET_INT_VALUE_3(propFile, video, fullscreen, height);
853     SET_INT_VALUE_3(propFile, video, fullscreen, bitDepth);
854     SET_ENUM_VALUE_2(propFile, video, maximizeIsFullscreen, YesNoPair);
855     SET_ENUM_VALUE_2(propFile, video, driver, VideoDriverPair);
856     SET_INT_VALUE_2(propFile, video, captureFps);
857 
858     SET_INT_VALUE_2(propFile, video, captureSize);
859 
860     SET_ENUM_VALUE_3(propFile, video, d3d, linearFiltering, BoolPair);
861     SET_ENUM_VALUE_3(propFile, video, d3d, extendBorderColor, BoolPair);
862     SET_ENUM_VALUE_3(propFile, video, d3d, forceHighRes, BoolPair);
863     SET_INT_VALUE_3(propFile, video, d3d, aspectRatioType);
864     SET_INT_VALUE_3(propFile, video, d3d, cropType);
865 
866     SET_INT_VALUE_3(propFile, video, d3d, cropLeft);
867     SET_INT_VALUE_3(propFile, video, d3d, cropRight);
868     SET_INT_VALUE_3(propFile, video, d3d, cropTop);
869     SET_INT_VALUE_3(propFile, video, d3d, cropBottom);
870 
871     SET_INT_VALUE_2(propFile, videoIn, disabled);
872     SET_INT_VALUE_2(propFile, videoIn, inputIndex);
873     SET_STR_VALUE_2(propFile, videoIn, inputName);
874 
875     SET_ENUM_VALUE_2(propFile, sound, driver, SoundDriverPair);
876     SET_INT_VALUE_2(propFile, sound, bufSize);
877     SET_ENUM_VALUE_2(propFile, sound, stabilizeDSoundTiming, YesNoPair);
878     SET_ENUM_VALUE_2(propFile, sound, stereo, YesNoPair);
879     SET_INT_VALUE_2(propFile, sound, masterVolume);
880     SET_ENUM_VALUE_2(propFile, sound, masterEnable, YesNoPair);
881 
882     SET_ENUM_VALUE_3(propFile, sound, chip, enableYM2413, YesNoPair);
883     SET_ENUM_VALUE_3(propFile, sound, chip, enableY8950, YesNoPair);
884     SET_ENUM_VALUE_3(propFile, sound, chip, enableMoonsound, YesNoPair);
885     SET_INT_VALUE_3(propFile, sound, chip, moonsoundSRAMSize);
886 //    SET_INT_VALUE_3(sound, chip, ym2413Oversampling);
887 //    SET_INT_VALUE_3(sound, chip, y8950Oversampling);
888 //    SET_INT_VALUE_3(sound, chip, moonsoundOversampling);
889     SET_ENUM_VALUE_3(propFile, sound, YkIn, type, MidiTypePair);
890     SET_STR_VALUE_3(propFile, sound, YkIn, name);
891 //    SET_STR_VALUE_3(sound, YkIn, fileName);
892 //    SET_STR_VALUE_3(sound, YkIn, desc);
893     SET_INT_VALUE_3(propFile, sound, YkIn, channel);
894     SET_ENUM_VALUE_3(propFile, sound, MidiIn, type, MidiTypePair);
895     SET_STR_VALUE_3(propFile, sound, MidiIn, name);
896 //    SET_STR_VALUE_3(sound, MidiIn, fileName);
897 //    SET_STR_VALUE_3(sound, MidiIn, desc);
898     SET_ENUM_VALUE_3(propFile, sound, MidiOut, type, MidiTypePair);
899     SET_STR_VALUE_3(propFile, sound, MidiOut, name);
900 //    SET_STR_VALUE_3(sound, MidiOut, fileName);
901 //    SET_STR_VALUE_3(sound, MidiOut, desc);
902     SET_ENUM_VALUE_3(propFile, sound, MidiOut, mt32ToGm, YesNoPair);
903     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, enable, YesNoPair);
904     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, pan);
905     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PSG, volume);
906     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, enable, YesNoPair);
907     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, pan);
908     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_SCC, volume);
909     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, enable, YesNoPair);
910     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, pan);
911     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXMUSIC, volume);
912     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, enable, YesNoPair);
913     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, pan);
914     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MSXAUDIO, volume);
915     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, enable, YesNoPair);
916     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, pan);
917     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_KEYBOARD, volume);
918     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, enable, YesNoPair);
919     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, pan);
920     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MOONSOUND, volume);
921     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, enable, YesNoPair);
922     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, pan);
923     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_YAMAHA_SFG, volume);
924     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, enable, YesNoPair);
925     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, pan);
926     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_PCM, volume);
927     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, enable, YesNoPair);
928     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, pan);
929     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_IO, volume);
930     SET_ENUM_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, enable, YesNoPair);
931     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, pan);
932     SET_INT_VALUE_2s1(propFile, sound, mixerChannel, MIXER_CHANNEL_MIDI, volume);
933 
934     SET_ENUM_VALUE_2(propFile, joystick, POV0isAxes, YesNoPair);
935 
936     strcpy(properties->joy1.type, joystickPortTypeToName(0, 0));
937     SET_STR_VALUE_2(propFile, joy1, type);
938     SET_ENUM_VALUE_2(propFile, joy1, autofire, OnOffPair);
939 
940     strcpy(properties->joy2.type, joystickPortTypeToName(1, 0));
941     SET_STR_VALUE_2(propFile, joy2, type);
942     SET_ENUM_VALUE_2(propFile, joy2, autofire, OnOffPair);
943 
944     SET_STR_VALUE_2(propFile, keyboard, configFile);
945     SET_INT_VALUE_2(propFile, keyboard, enableKeyboardQuirk);
946 
947     SET_ENUM_VALUE_3(propFile, ports, Lpt, type, PrinterTypePair);
948     SET_ENUM_VALUE_3(propFile, ports, Lpt, emulation, PrinterEmulationPair);
949     SET_STR_VALUE_3(propFile, ports, Lpt, name);
950     SET_STR_VALUE_3(propFile, ports, Lpt, fileName);
951     SET_STR_VALUE_3(propFile, ports, Lpt, portName);
952     SET_ENUM_VALUE_3(propFile, ports, Com, type, ComTypePair);
953     SET_STR_VALUE_3(propFile, ports, Com, name);
954     SET_STR_VALUE_3(propFile, ports, Com, fileName);
955     SET_STR_VALUE_3(propFile, ports, Com, portName);
956 
957     SET_INT_VALUE_3(propFile, ports, Eth, ethIndex);
958     SET_INT_VALUE_3(propFile, ports, Eth, disabled);
959     SET_STR_VALUE_3(propFile, ports, Eth, macAddress);
960 
961     SET_INT_VALUE_2(propFile, cartridge, defaultType);
962 
963     SET_ENUM_VALUE_2(propFile, diskdrive, cdromMethod, CdromDrvPair);
964     SET_INT_VALUE_2(propFile, diskdrive, cdromDrive);
965 
966     SET_INT_VALUE_2(propFile, cassette, showCustomFiles);
967     SET_ENUM_VALUE_2(propFile, cassette, readOnly, YesNoPair);
968     SET_ENUM_VALUE_2(propFile, cassette, rewindAfterInsert, YesNoPair);
969 
970     SET_ENUM_VALUE_2(propFile, nowind, enableDos2, YesNoPair);
971     SET_ENUM_VALUE_2(propFile, nowind, enableOtherDiskRoms, BoolPair);
972     SET_ENUM_VALUE_2(propFile, nowind, enablePhantomDrives, BoolPair);
973     SET_ENUM_VALUE_2(propFile, nowind, ignoreBootFlag, BoolPair);
974     SET_INT_VALUE_2(propFile, nowind,  partitionNumber);
975 
976     iniFileClose(propFile);
977 
978 #ifndef NO_FILE_HISTORY
979     histFile = iniFileOpen(histFilename);
980 
981     SET_STR_VALUE_2(histFile, cartridge, defDir);
982     SET_STR_VALUE_2(histFile, cartridge, defDirSEGA);
983     SET_STR_VALUE_2(histFile, cartridge, defDirCOLECO);
984     SET_STR_VALUE_2(histFile, cartridge, defDirSVI);
985     SET_INT_VALUE_2(histFile, cartridge, autoReset);
986     SET_INT_VALUE_2(histFile, cartridge, quickStartDrive);
987 
988     SET_STR_VALUE_2(histFile, diskdrive, defDir);
989     SET_STR_VALUE_2(histFile, diskdrive, defHdDir);
990     SET_INT_VALUE_2(histFile, diskdrive, autostartA);
991     SET_INT_VALUE_2(histFile, diskdrive, quickStartDrive);
992 
993     SET_STR_VALUE_2(histFile, cassette, defDir);
994 
995     for (i = 0; i < PROP_MAX_CARTS; i++) {
996         SET_STR_VALUE_2i1(histFile, media, carts, i, fileName);
997         SET_STR_VALUE_2i1(histFile, media, carts, i, fileNameInZip);
998         SET_STR_VALUE_2i1(histFile, media, carts, i, directory);
999         SET_INT_VALUE_2i1(histFile, media, carts, i, extensionFilter);
1000         SET_INT_VALUE_2i1(histFile, media, carts, i, type);
1001     }
1002 
1003     for (i = 0; i < PROP_MAX_DISKS; i++) {
1004         SET_STR_VALUE_2i1(histFile, media, disks, i, fileName);
1005         SET_STR_VALUE_2i1(histFile, media, disks, i, fileNameInZip);
1006         SET_STR_VALUE_2i1(histFile, media, disks, i, directory);
1007         SET_INT_VALUE_2i1(histFile, media, disks, i, extensionFilter);
1008         SET_INT_VALUE_2i1(histFile, media, disks, i, type);
1009     }
1010 
1011     for (i = 0; i < PROP_MAX_TAPES; i++) {
1012         SET_STR_VALUE_2i1(histFile, media, tapes, i, fileName);
1013         SET_STR_VALUE_2i1(histFile, media, tapes, i, fileNameInZip);
1014         SET_STR_VALUE_2i1(histFile, media, tapes, i, directory);
1015         SET_INT_VALUE_2i1(histFile, media, tapes, i, extensionFilter);
1016         SET_INT_VALUE_2i1(histFile, media, tapes, i, type);
1017     }
1018 
1019     for (i = 0; i < MAX_HISTORY; i++) {
1020         SET_STR_VALUE_2i(histFile, filehistory, cartridge[0], i);
1021         SET_INT_VALUE_2i(histFile, filehistory, cartridgeType[0], i);
1022         SET_STR_VALUE_2i(histFile, filehistory, cartridge[1], i);
1023         SET_INT_VALUE_2i(histFile, filehistory, cartridgeType[1], i);
1024         SET_STR_VALUE_2i(histFile, filehistory, diskdrive[0], i);
1025         SET_STR_VALUE_2i(histFile, filehistory, diskdrive[1], i);
1026         SET_STR_VALUE_2i(histFile, filehistory, cassette[0], i);
1027     }
1028 
1029     SET_STR_VALUE_2(histFile, filehistory, quicksave);
1030     SET_STR_VALUE_2(histFile, filehistory, videocap);
1031     SET_INT_VALUE_2(histFile, filehistory, count);
1032 
1033     for (i = 0; i < DLG_MAX_ID; i++) {
1034         SET_INT_VALUE_2i1(histFile, settings, windowPos, i, left);
1035         SET_INT_VALUE_2i1(histFile, settings, windowPos, i, top);
1036         SET_INT_VALUE_2i1(histFile, settings, windowPos, i, width);
1037         SET_INT_VALUE_2i1(histFile, settings, windowPos, i, height);
1038     }
1039 
1040     iniFileClose(histFile);
1041 #endif
1042 }
1043 
1044 static Properties* globalProperties = NULL;
1045 
propGetGlobalProperties()1046 Properties* propGetGlobalProperties()
1047 {
1048     return globalProperties;
1049 }
1050 
propertiesSetDirectory(const char * defDir,const char * altDir)1051 void propertiesSetDirectory(const char* defDir, const char* altDir)
1052 {
1053     FILE* f;
1054 
1055     sprintf(settFilename, "bluemsx.ini", defDir);
1056     f = fopen(settFilename, "r");
1057     if (f != NULL) {
1058         fclose(f);
1059     }
1060     else {
1061         sprintf(settFilename, "%s/bluemsx.ini", altDir);
1062     }
1063 
1064     sprintf(histFilename, "bluemsx_history.ini", defDir);
1065     f = fopen(histFilename, "r");
1066     if (f != NULL) {
1067         fclose(f);
1068     }
1069     else {
1070         sprintf(histFilename, "%s/bluemsx_history.ini", altDir);
1071     }
1072 }
1073 
1074 
propCreate(int useDefault,int langType,PropKeyboardLanguage kbdLang,int syncMode,const char * themeName)1075 Properties* propCreate(int useDefault, int langType, PropKeyboardLanguage kbdLang, int syncMode, const char* themeName)
1076 {
1077     Properties* properties;
1078 
1079     properties = malloc(sizeof(Properties));
1080 
1081     if (globalProperties == NULL) {
1082         globalProperties = properties;
1083     }
1084 
1085     propInitDefaults(properties, langType, kbdLang, syncMode, themeName);
1086 
1087     if (!useDefault) {
1088         propLoad(properties);
1089     }
1090 #if !defined(WII) && !defined(__LIBRETRO__)
1091     // Verify machine name
1092     {
1093         int foundMachine = 0;
1094 		ArrayListIterator *iterator;
1095         ArrayList *machineList;
1096 
1097 		machineList = arrayListCreate();
1098         machineFillAvailable(machineList, 1);
1099 
1100         iterator = arrayListCreateIterator(machineList);
1101         while (arrayListCanIterate(iterator))
1102         {
1103             char *machineName = (char *)arrayListIterate(iterator);
1104             if (strcmp(machineName, properties->emulation.machineName) == 0)
1105             {
1106                 foundMachine = 1;
1107                 break;
1108             }
1109         }
1110         arrayListDestroyIterator(iterator);
1111 
1112         if (!foundMachine)
1113         {
1114             if (arrayListGetSize(machineList) > 0)
1115                 strcpy(properties->emulation.machineName, (char *)arrayListGetObject(machineList, 0));
1116 
1117             iterator = arrayListCreateIterator(machineList);
1118             while (arrayListCanIterate(iterator))
1119             {
1120                 char *machineName = (char *)arrayListIterate(iterator);
1121                 if (strcmp(machineName, "MSX2") == 0)
1122                 {
1123                     strcpy(properties->emulation.machineName, machineName);
1124                     foundMachine = 1;
1125                 }
1126 
1127                 if (!foundMachine && strncmp(machineName, "MSX2", 4))
1128                 {
1129                     strcpy(properties->emulation.machineName, machineName);
1130                     foundMachine = 1;
1131                 }
1132             }
1133             arrayListDestroyIterator(iterator);
1134         }
1135 
1136         arrayListDestroy(machineList);
1137     }
1138 #endif
1139     return properties;
1140 }
1141 
1142 
propDestroy(Properties * properties)1143 void propDestroy(Properties* properties) {
1144     propSave(properties);
1145 
1146     free(properties);
1147 }
1148 
1149 
1150