fceugx/source/ngc/preferences.cpp

473 lines
14 KiB
C++
Raw Normal View History

2008-09-02 03:57:21 +02:00
/****************************************************************************
2009-07-22 04:05:49 +02:00
* FCE Ultra
2008-09-02 03:57:21 +02:00
* Nintendo Wii/Gamecube Port
*
2009-03-28 18:23:08 +01:00
* Tantric 2008-2009
2008-09-02 03:57:21 +02:00
*
2009-03-28 18:23:08 +01:00
* preferences.cpp
2008-09-02 03:57:21 +02:00
*
* Preferences save/load preferences utilities
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include <mxml.h>
2009-03-28 18:23:08 +01:00
#include "fceuconfig.h"
#include "button_mapping.h"
#include "filebrowser.h"
#include "menu.h"
2008-09-02 03:57:21 +02:00
#include "fileop.h"
#include "fceugx.h"
2008-09-02 03:57:21 +02:00
#include "pad.h"
/****************************************************************************
* Prepare Preferences Data
*
* This sets up the save buffer for saving.
2009-10-02 00:21:25 +02:00
***************************************************************************/
static mxml_node_t *xml = NULL;
static mxml_node_t *data = NULL;
static mxml_node_t *section = NULL;
static mxml_node_t *item = NULL;
static mxml_node_t *elem = NULL;
2008-09-02 03:57:21 +02:00
static char temp[200];
2008-09-02 03:57:21 +02:00
static const char * toStr(int i)
2008-09-02 03:57:21 +02:00
{
sprintf(temp, "%d", i);
return temp;
}
static const char * FtoStr(float i)
2008-10-24 07:38:46 +02:00
{
sprintf(temp, "%.2f", i);
return temp;
}
static void createXMLSection(const char * name, const char * description)
2008-09-02 03:57:21 +02:00
{
section = mxmlNewElement(data, "section");
mxmlElementSetAttr(section, "name", name);
mxmlElementSetAttr(section, "description", description);
}
static void createXMLSetting(const char * name, const char * description, const char * value)
2008-09-02 03:57:21 +02:00
{
item = mxmlNewElement(section, "setting");
mxmlElementSetAttr(item, "name", name);
mxmlElementSetAttr(item, "value", value);
mxmlElementSetAttr(item, "description", description);
}
static void createXMLController(unsigned int controller[], const char * name, const char * description)
2008-09-02 03:57:21 +02:00
{
item = mxmlNewElement(section, "controller");
mxmlElementSetAttr(item, "name", name);
mxmlElementSetAttr(item, "description", description);
// create buttons
2009-10-02 00:21:25 +02:00
for(int i=0; i < MAXJP; i++)
2008-09-02 03:57:21 +02:00
{
elem = mxmlNewElement(item, "button");
mxmlElementSetAttr(elem, "number", toStr(i));
mxmlElementSetAttr(elem, "assignment", toStr(controller[i]));
}
}
static const char * XMLSaveCallback(mxml_node_t *node, int where)
2008-09-02 03:57:21 +02:00
{
const char *name;
name = node->value.element.name;
if(where == MXML_WS_BEFORE_CLOSE)
{
if(!strcmp(name, "file") || !strcmp(name, "section"))
return ("\n");
else if(!strcmp(name, "controller"))
return ("\n\t");
}
if (where == MXML_WS_BEFORE_OPEN)
{
if(!strcmp(name, "file"))
return ("\n");
else if(!strcmp(name, "section"))
return ("\n\n");
else if(!strcmp(name, "setting") || !strcmp(name, "controller"))
return ("\n\t");
else if(!strcmp(name, "button"))
return ("\n\t\t");
}
return (NULL);
}
static int
2009-10-02 00:21:25 +02:00
preparePrefsData ()
2008-09-02 03:57:21 +02:00
{
xml = mxmlNewXML("1.0");
mxmlSetWrapMargin(0); // disable line wrapping
data = mxmlNewElement(xml, "file");
2009-10-02 00:21:25 +02:00
mxmlElementSetAttr(data, "app", APPNAME);
mxmlElementSetAttr(data, "version", APPVERSION);
2008-09-02 03:57:21 +02:00
createXMLSection("File", "File Settings");
createXMLSetting("AutoLoad", "Auto Load", toStr(GCSettings.AutoLoad));
createXMLSetting("AutoSave", "Auto Save", toStr(GCSettings.AutoSave));
createXMLSetting("LoadMethod", "Load Method", toStr(GCSettings.LoadMethod));
createXMLSetting("SaveMethod", "Save Method", toStr(GCSettings.SaveMethod));
createXMLSetting("LoadFolder", "Load Folder", GCSettings.LoadFolder);
createXMLSetting("SaveFolder", "Save Folder", GCSettings.SaveFolder);
2009-07-22 03:58:45 +02:00
createXMLSetting("CheatFolder", "Cheats Folder", GCSettings.CheatFolder);
2009-10-07 08:59:10 +02:00
createXMLSetting("gamegenie", "Game Genie", toStr(GCSettings.gamegenie));
2008-09-02 03:57:21 +02:00
createXMLSection("Network", "Network Settings");
createXMLSetting("smbip", "Share Computer IP", GCSettings.smbip);
createXMLSetting("smbshare", "Share Name", GCSettings.smbshare);
createXMLSetting("smbuser", "Share Username", GCSettings.smbuser);
createXMLSetting("smbpwd", "Share Password", GCSettings.smbpwd);
2009-03-28 18:23:08 +01:00
createXMLSection("Video", "Video Settings");
2008-09-02 03:57:21 +02:00
2009-04-27 09:49:30 +02:00
createXMLSetting("videomode", "Video Mode", toStr(GCSettings.videomode));
2008-09-02 03:57:21 +02:00
createXMLSetting("currpal", "Palette", toStr(GCSettings.currpal));
createXMLSetting("timing", "Timing", toStr(GCSettings.timing));
createXMLSetting("spritelimit", "Sprite Limit", toStr(GCSettings.spritelimit));
2009-11-16 09:14:38 +01:00
createXMLSetting("zoomHor", "Horizontal Zoom Level", FtoStr(GCSettings.zoomHor));
createXMLSetting("zoomVert", "Vertical Zoom Level", FtoStr(GCSettings.zoomVert));
createXMLSetting("render", "Video Filtering", toStr(GCSettings.render));
createXMLSetting("widescreen", "Aspect Ratio Correction", toStr(GCSettings.widescreen));
2009-07-21 08:26:38 +02:00
createXMLSetting("FilterMethod", "Filter Method", toStr(GCSettings.FilterMethod));
2008-11-20 17:58:44 +01:00
createXMLSetting("hideoverscan", "Video Cropping", toStr(GCSettings.hideoverscan));
2009-01-26 08:10:20 +01:00
createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift));
createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift));
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
createXMLSection("Menu", "Menu Settings");
createXMLSetting("WiimoteOrientation", "Wiimote Orientation", toStr(GCSettings.WiimoteOrientation));
createXMLSetting("ExitAction", "Exit Action", toStr(GCSettings.ExitAction));
createXMLSetting("MusicVolume", "Music Volume", toStr(GCSettings.MusicVolume));
createXMLSetting("SFXVolume", "Sound Effects Volume", toStr(GCSettings.SFXVolume));
2009-05-30 08:28:00 +02:00
createXMLSetting("Rumble", "Rumble", toStr(GCSettings.Rumble));
2009-03-28 18:23:08 +01:00
2008-09-02 03:57:21 +02:00
createXMLSection("Controller", "Controller Settings");
2009-03-28 18:23:08 +01:00
createXMLSetting("Controller", "Controller", toStr(GCSettings.Controller));
2008-10-02 01:10:30 +02:00
createXMLSetting("crosshair", "Zapper Crosshair", toStr(GCSettings.crosshair));
2009-03-28 18:23:08 +01:00
createXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad", "NES Pad - GameCube Controller");
createXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote", "NES Pad - Wiimote");
createXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic", "NES Pad - Classic Controller");
createXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk", "NES Pad - Nunchuk + Wiimote");
createXMLController(btnmap[CTRL_ZAPPER][CTRLR_GCPAD], "btnmap_zapper_gcpad", "Zapper - GameCube Controller");
createXMLController(btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE], "btnmap_zapper_wiimote", "Zapper - Wiimote");
2008-09-02 03:57:21 +02:00
int datasize = mxmlSaveString(xml, (char *)savebuffer, SAVEBUFFERSIZE, XMLSaveCallback);
mxmlDelete(xml);
return datasize;
}
/****************************************************************************
2009-10-02 00:21:25 +02:00
* loadXMLSetting
*
* Load XML elements into variables for an individual variable
***************************************************************************/
2009-01-25 08:01:50 +01:00
static void loadXMLSetting(char * var, const char * name, int maxsize)
2008-09-02 03:57:21 +02:00
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
{
const char * tmp = mxmlElementGetAttr(item, "value");
if(tmp)
snprintf(var, maxsize, "%s", tmp);
}
2008-09-02 03:57:21 +02:00
}
2009-01-25 08:01:50 +01:00
static void loadXMLSetting(int * var, const char * name)
2008-09-02 03:57:21 +02:00
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
{
const char * tmp = mxmlElementGetAttr(item, "value");
if(tmp)
*var = atoi(tmp);
}
2008-09-02 03:57:21 +02:00
}
2009-01-25 08:01:50 +01:00
static void loadXMLSetting(float * var, const char * name)
2008-10-24 07:38:46 +02:00
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
{
const char * tmp = mxmlElementGetAttr(item, "value");
if(tmp)
*var = atof(tmp);
}
2008-10-24 07:38:46 +02:00
}
2008-09-02 03:57:21 +02:00
2009-10-02 00:21:25 +02:00
/****************************************************************************
* loadXMLController
*
* Load XML elements into variables for a controller mapping
***************************************************************************/
static void loadXMLController(unsigned int controller[], const char * name)
2008-09-02 03:57:21 +02:00
{
item = mxmlFindElement(xml, xml, "controller", "name", name, MXML_DESCEND);
if(item)
{
// populate buttons
2009-10-02 00:21:25 +02:00
for(int i=0; i < MAXJP; i++)
2008-09-02 03:57:21 +02:00
{
elem = mxmlFindElement(item, xml, "button", "number", toStr(i), MXML_DESCEND);
if(elem)
{
const char * tmp = mxmlElementGetAttr(elem, "assignment");
if(tmp)
controller[i] = atoi(tmp);
}
2008-09-02 03:57:21 +02:00
}
}
}
2009-10-02 00:21:25 +02:00
/****************************************************************************
* decodePrefsData
*
* Decodes preferences - parses XML and loads preferences into the variables
***************************************************************************/
static bool
2009-10-02 00:21:25 +02:00
decodePrefsData ()
2008-09-02 03:57:21 +02:00
{
bool result = false;
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
xml = mxmlLoadString(NULL, (char *)savebuffer, MXML_TEXT_CALLBACK);
2008-09-02 03:57:21 +02:00
if(xml)
{
// check settings version
item = mxmlFindElement(xml, xml, "file", "version", NULL, MXML_DESCEND);
if(item) // a version entry exists
{
2009-10-02 00:21:25 +02:00
const char * version = mxmlElementGetAttr(item, "version");
2009-10-02 00:21:25 +02:00
if(version && strlen(version) == 5)
{
// this code assumes version in format X.X.X
// XX.X.X, X.XX.X, or X.X.XX will NOT work
int verMajor = version[0] - '0';
int verMinor = version[2] - '0';
int verPoint = version[4] - '0';
int curMajor = APPVERSION[0] - '0';
int curMinor = APPVERSION[2] - '0';
int curPoint = APPVERSION[4] - '0';
// first we'll check that the versioning is valid
if(!(verMajor >= 0 && verMajor <= 9 &&
verMinor >= 0 && verMinor <= 9 &&
verPoint >= 0 && verPoint <= 9))
result = false;
2009-04-09 09:49:28 +02:00
else if(verMajor < 3) // less than version 3.0.0
result = false; // reset settings
2009-10-07 08:59:10 +02:00
else if((verMajor*100 + verMinor*10 + verPoint) >
(curMajor*100 + curMinor*10 + curPoint)) // some future version
result = false; // reset settings
else
result = true;
}
}
2008-09-02 03:57:21 +02:00
if(result)
{
// File Settings
2009-01-25 08:01:50 +01:00
loadXMLSetting(&GCSettings.AutoLoad, "AutoLoad");
loadXMLSetting(&GCSettings.AutoSave, "AutoSave");
loadXMLSetting(&GCSettings.LoadMethod, "LoadMethod");
loadXMLSetting(&GCSettings.SaveMethod, "SaveMethod");
loadXMLSetting(GCSettings.LoadFolder, "LoadFolder", sizeof(GCSettings.LoadFolder));
loadXMLSetting(GCSettings.SaveFolder, "SaveFolder", sizeof(GCSettings.SaveFolder));
2009-07-22 03:58:45 +02:00
loadXMLSetting(GCSettings.CheatFolder, "CheatFolder", sizeof(GCSettings.CheatFolder));
2009-10-07 08:59:10 +02:00
loadXMLSetting(&GCSettings.gamegenie, "gamegenie");
// Network Settings
2009-01-25 08:01:50 +01:00
loadXMLSetting(GCSettings.smbip, "smbip", sizeof(GCSettings.smbip));
loadXMLSetting(GCSettings.smbshare, "smbshare", sizeof(GCSettings.smbshare));
loadXMLSetting(GCSettings.smbuser, "smbuser", sizeof(GCSettings.smbuser));
loadXMLSetting(GCSettings.smbpwd, "smbpwd", sizeof(GCSettings.smbpwd));
2009-03-28 18:23:08 +01:00
// Video Settings
2009-04-27 09:49:30 +02:00
loadXMLSetting(&GCSettings.videomode, "videomode");
2009-01-25 08:01:50 +01:00
loadXMLSetting(&GCSettings.currpal, "currpal");
loadXMLSetting(&GCSettings.timing, "timing");
loadXMLSetting(&GCSettings.spritelimit, "spritelimit");
2009-11-16 09:14:38 +01:00
loadXMLSetting(&GCSettings.zoomHor, "zoomHor");
loadXMLSetting(&GCSettings.zoomVert, "zoomVert");
2009-01-25 08:01:50 +01:00
loadXMLSetting(&GCSettings.render, "render");
loadXMLSetting(&GCSettings.widescreen, "widescreen");
2009-07-21 08:26:38 +02:00
loadXMLSetting(&GCSettings.FilterMethod, "FilterMethod");
2009-01-25 08:01:50 +01:00
loadXMLSetting(&GCSettings.hideoverscan, "hideoverscan");
2009-01-26 08:10:20 +01:00
loadXMLSetting(&GCSettings.xshift, "xshift");
loadXMLSetting(&GCSettings.yshift, "yshift");
2009-03-28 18:23:08 +01:00
// Menu Settings
loadXMLSetting(&GCSettings.WiimoteOrientation, "WiimoteOrientation");
loadXMLSetting(&GCSettings.ExitAction, "ExitAction");
loadXMLSetting(&GCSettings.MusicVolume, "MusicVolume");
loadXMLSetting(&GCSettings.SFXVolume, "SFXVolume");
2009-05-30 08:28:00 +02:00
loadXMLSetting(&GCSettings.Rumble, "Rumble");
2009-03-28 18:23:08 +01:00
// Controller Settings
2009-10-02 00:21:25 +02:00
2009-03-28 18:23:08 +01:00
loadXMLSetting(&GCSettings.Controller, "Controller");
2009-01-25 08:01:50 +01:00
loadXMLSetting(&GCSettings.crosshair, "crosshair");
2009-03-28 18:23:08 +01:00
loadXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad");
loadXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote");
loadXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic");
loadXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk");
loadXMLController(btnmap[CTRL_ZAPPER][CTRLR_GCPAD], "btnmap_zapper_gcpad");
loadXMLController(btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE], "btnmap_zapper_wiimote");
}
mxmlDelete(xml);
}
return result;
2008-09-02 03:57:21 +02:00
}
/****************************************************************************
* Save Preferences
***************************************************************************/
2009-10-02 00:21:25 +02:00
static char prefpath[MAXPATHLEN] = { 0 };
2008-09-02 03:57:21 +02:00
bool
SavePrefs (bool silent)
2008-09-02 03:57:21 +02:00
{
2009-10-02 00:21:25 +02:00
char filepath[MAXPATHLEN];
2008-11-12 09:40:09 +01:00
int datasize;
int offset = 0;
2009-10-02 00:21:25 +02:00
int device = 0;
2009-10-06 08:38:32 +02:00
2009-10-02 00:21:25 +02:00
if(prefpath[0] != 0)
{
strcpy(filepath, prefpath);
FindDevice(filepath, &device);
}
else if(appPath[0] != 0)
{
2009-10-05 03:33:15 +02:00
sprintf(filepath, "%s/%s", appPath, PREF_FILE_NAME);
2009-10-02 00:21:25 +02:00
FindDevice(filepath, &device);
}
else
{
2009-10-06 08:38:32 +02:00
device = autoSaveMethod(silent);
2009-10-02 00:21:25 +02:00
if(device == 0)
return false;
2009-11-29 08:55:21 +01:00
sprintf(filepath, "%s%s/%s", pathPrefix[device], APPFOLDER, PREF_FILE_NAME);
2009-10-02 00:21:25 +02:00
}
2009-10-06 08:38:32 +02:00
2009-10-02 00:21:25 +02:00
if(device == 0)
2008-11-12 09:40:09 +01:00
return false;
2008-09-02 03:57:21 +02:00
if (!silent)
ShowAction ("Saving preferences...");
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
FixInvalidSettings();
AllocSaveBuffer ();
2009-10-02 00:21:25 +02:00
datasize = preparePrefsData ();
offset = SaveFile(filepath, datasize, silent);
2008-09-02 03:57:21 +02:00
FreeSaveBuffer ();
2009-03-28 18:23:08 +01:00
CancelAction();
2008-09-02 03:57:21 +02:00
if (offset > 0)
{
if (!silent)
2009-10-02 00:21:25 +02:00
InfoPrompt("Preferences saved");
2008-09-02 03:57:21 +02:00
return true;
}
return false;
}
/****************************************************************************
2009-10-02 00:21:25 +02:00
* Load Preferences from specified filepath
***************************************************************************/
2008-09-02 03:57:21 +02:00
bool
2009-10-02 00:21:25 +02:00
LoadPrefsFromMethod (char * filepath)
2008-09-02 03:57:21 +02:00
{
bool retval = false;
int offset = 0;
AllocSaveBuffer ();
2009-10-02 00:21:25 +02:00
offset = LoadFile(filepath, SILENT);
2008-09-02 03:57:21 +02:00
if (offset > 0)
2009-10-02 00:21:25 +02:00
retval = decodePrefsData ();
FreeSaveBuffer ();
2009-10-02 00:21:25 +02:00
if(retval)
{
strcpy(prefpath, filepath);
}
2008-09-02 03:57:21 +02:00
return retval;
}
/****************************************************************************
* Load Preferences
* Checks sources consecutively until we find a preference file
***************************************************************************/
2009-03-28 18:23:08 +01:00
static bool prefLoaded = false;
bool LoadPrefs()
{
2009-03-28 18:23:08 +01:00
if(prefLoaded) // already attempted loading
return true;
bool prefFound = false;
2009-10-02 00:21:25 +02:00
char filepath[4][MAXPATHLEN];
int numDevices;
2009-10-06 08:38:32 +02:00
2009-10-02 00:21:25 +02:00
#ifdef HW_RVL
numDevices = 3;
sprintf(filepath[0], "%s/%s", appPath, PREF_FILE_NAME);
sprintf(filepath[1], "sd:/%s/%s", APPFOLDER, PREF_FILE_NAME);
sprintf(filepath[2], "usb:/%s/%s", APPFOLDER, PREF_FILE_NAME);
#else
2009-11-29 08:55:21 +01:00
numDevices = 2;
2009-10-02 00:21:25 +02:00
sprintf(filepath[0], "carda:/%s/%s", APPFOLDER, PREF_FILE_NAME);
sprintf(filepath[1], "cardb:/%s/%s", APPFOLDER, PREF_FILE_NAME);
#endif
for(int i=0; i<numDevices; i++)
{
2009-10-02 00:21:25 +02:00
prefFound = LoadPrefsFromMethod(filepath[i]);
if(prefFound)
break;
}
2009-03-28 18:23:08 +01:00
prefLoaded = true; // attempted to load preferences
if(prefFound)
FixInvalidSettings();
return prefFound;
}