mirror of https://github.com/stella-emu/stella.git
Almost all file I/O now goes through FilesystemNode::read/write, instead of raw C++ fstreams.
This allows data to be stored in a ZIP archive and for Stella to use it as if it were a normal file. Still TODO is add ZIP write support.
This commit is contained in:
parent
02176d1c7e
commit
155839fb0b
11
Changes.txt
11
Changes.txt
|
@ -22,9 +22,14 @@
|
|||
|
||||
* Allow taking snapshots from within Time Machine dialog
|
||||
|
||||
* Added ability to load per-ROM properties file from a ZIP file containing
|
||||
the ROM. This allows to distribute ROM and properties in one file,
|
||||
which Stella can use directly.
|
||||
* Added ability to access most files that Stella uses from within a ZIP
|
||||
file. This includes the following:
|
||||
- Per-ROM properties file (so one can distribute a ROM and its
|
||||
associated properties).
|
||||
- Debugger symbol (.sym) and list (.lst) files, etc.
|
||||
- Several others, as we extend the support.
|
||||
Basically, you are now able to put many files that Stella uses inside
|
||||
one ZIP file, and distribute just that file.
|
||||
|
||||
* Replaced "Re-disassemble" with "Disassemble @ current line" in debugger
|
||||
|
||||
|
|
|
@ -213,10 +213,9 @@ void CheatManager::enable(const string& code, bool enable)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CheatManager::loadCheatDatabase()
|
||||
{
|
||||
const string& cheatfile = myOSystem.cheatFile();
|
||||
ifstream in(cheatfile);
|
||||
if(!in)
|
||||
return;
|
||||
stringstream in;
|
||||
try { myOSystem.cheatFile().read(in); }
|
||||
catch(...) { return; }
|
||||
|
||||
string line, md5, cheat;
|
||||
string::size_type one, two, three, four;
|
||||
|
@ -253,13 +252,12 @@ void CheatManager::saveCheatDatabase()
|
|||
if(!myListIsDirty)
|
||||
return;
|
||||
|
||||
const string& cheatfile = myOSystem.cheatFile();
|
||||
ofstream out(cheatfile);
|
||||
if(!out)
|
||||
return;
|
||||
|
||||
stringstream out;
|
||||
for(const auto& iter: myCheatMap)
|
||||
out << "\"" << iter.first << "\" " << "\"" << iter.second << "\"" << endl;
|
||||
|
||||
try { myOSystem.cheatFile().write(out); }
|
||||
catch(...) { return; }
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -52,7 +52,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
|
|||
throw runtime_error(s);
|
||||
};
|
||||
|
||||
ifstream in(filename, std::ios_base::binary);
|
||||
std::ifstream in(filename, std::ios_base::binary);
|
||||
if(!in.is_open())
|
||||
loadImageERROR("No snapshot found");
|
||||
|
||||
|
@ -125,7 +125,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::saveImage(const string& filename, const VariantList& comments)
|
||||
{
|
||||
ofstream out(filename, std::ios_base::binary);
|
||||
std::ofstream out(filename, std::ios_base::binary);
|
||||
if(!out.is_open())
|
||||
throw runtime_error("ERROR: Couldn't create snapshot file");
|
||||
|
||||
|
@ -156,7 +156,7 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments)
|
|||
void PNGLibrary::saveImage(const string& filename, const FBSurface& surface,
|
||||
const Common::Rect& rect, const VariantList& comments)
|
||||
{
|
||||
ofstream out(filename, std::ios_base::binary);
|
||||
std::ofstream out(filename, std::ios_base::binary);
|
||||
if(!out.is_open())
|
||||
throw runtime_error("ERROR: Couldn't create snapshot file");
|
||||
|
||||
|
@ -182,7 +182,7 @@ void PNGLibrary::saveImage(const string& filename, const FBSurface& surface,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::saveImageToDisk(ofstream& out, const vector<png_bytep>& rows,
|
||||
void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector<png_bytep>& rows,
|
||||
png_uint_32 width, png_uint_32 height, const VariantList& comments)
|
||||
{
|
||||
png_structp png_ptr = nullptr;
|
||||
|
@ -297,7 +297,7 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
// Figure out the correct snapshot name
|
||||
string filename;
|
||||
bool showmessage = number == 0;
|
||||
string sspath = myOSystem.snapshotSaveDir() +
|
||||
string sspath = myOSystem.snapshotSaveDir().getPath() +
|
||||
(myOSystem.settings().getString("snapname") != "int" ?
|
||||
myOSystem.romFile().getNameWithExt("")
|
||||
: myOSystem.console().properties().get(PropType::Cart_Name));
|
||||
|
@ -456,21 +456,21 @@ void PNGLibrary::writeComments(png_structp png_ptr, png_infop info_ptr,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::png_read_data(png_structp ctx, png_bytep area, png_size_t size)
|
||||
{
|
||||
(static_cast<ifstream*>(png_get_io_ptr(ctx)))->read(
|
||||
(static_cast<std::ifstream*>(png_get_io_ptr(ctx)))->read(
|
||||
reinterpret_cast<char *>(area), size);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::png_write_data(png_structp ctx, png_bytep area, png_size_t size)
|
||||
{
|
||||
(static_cast<ofstream*>(png_get_io_ptr(ctx)))->write(
|
||||
(static_cast<std::ofstream*>(png_get_io_ptr(ctx)))->write(
|
||||
reinterpret_cast<const char *>(area), size);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::png_io_flush(png_structp ctx)
|
||||
{
|
||||
(static_cast<ofstream*>(png_get_io_ptr(ctx)))->flush();
|
||||
(static_cast<std::ofstream*>(png_get_io_ptr(ctx)))->flush();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -165,7 +165,7 @@ class PNGLibrary
|
|||
@param height The height of the PNG image
|
||||
@param comments The text comments to add to the PNG image
|
||||
*/
|
||||
void saveImageToDisk(ofstream& out, const vector<png_bytep>& rows,
|
||||
void saveImageToDisk(std::ofstream& out, const vector<png_bytep>& rows,
|
||||
png_uint_32 width, png_uint_32 height,
|
||||
const VariantList& comments);
|
||||
|
||||
|
|
|
@ -85,11 +85,13 @@ void PaletteHandler::showAdjustableMessage()
|
|||
{
|
||||
const ConsoleTiming timing = myOSystem.console().timing();
|
||||
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
||||
const float value = myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
|
||||
const float value =
|
||||
myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
|
||||
buf << std::fixed << std::setprecision(1) << value << DEGREE;
|
||||
myOSystem.frameBuffer().showMessage("Palette phase shift", buf.str(), value,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT);
|
||||
myOSystem.frameBuffer().showMessage(
|
||||
"Palette phase shift", buf.str(), value,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -328,29 +330,25 @@ void PaletteHandler::loadUserPalette()
|
|||
if (!myOSystem.checkUserPalette(true))
|
||||
return;
|
||||
|
||||
const string& palette = myOSystem.paletteFile();
|
||||
ifstream in(palette, std::ios::binary);
|
||||
ByteBuffer in;
|
||||
try { myOSystem.paletteFile().read(in); }
|
||||
catch(...) { return; }
|
||||
|
||||
// Now that we have valid data, create the user-defined palettes
|
||||
std::array<uInt8, 3> pixbuf; // Temporary buffer for one 24-bit pixel
|
||||
|
||||
for(int i = 0; i < 128; i++) // NTSC palette
|
||||
uInt8* pixbuf = in.get();
|
||||
for(int i = 0; i < 128; i++, pixbuf += 3) // NTSC palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
ourUserNTSCPalette[(i<<1)] = pixel;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) // PAL palette
|
||||
for(int i = 0; i < 128; i++, pixbuf += 3) // PAL palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
ourUserPALPalette[(i<<1)] = pixel;
|
||||
}
|
||||
|
||||
std::array<uInt32, 16> secam; // All 8 24-bit pixels, plus 8 colorloss pixels
|
||||
for(int i = 0; i < 8; i++) // SECAM palette
|
||||
for(int i = 0; i < 8; i++, pixbuf += 3) // SECAM palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
secam[(i<<1)] = pixel;
|
||||
secam[(i<<1)+1] = 0;
|
||||
|
|
|
@ -64,8 +64,6 @@ using std::istream;
|
|||
using std::ostream;
|
||||
using std::fstream;
|
||||
using std::iostream;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::ostringstream;
|
||||
using std::istringstream;
|
||||
using std::stringstream;
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace {
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const string& filename)
|
||||
: myFilename(filename)
|
||||
KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const FilesystemNode& file)
|
||||
: myFile(file)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,10 +41,14 @@ std::map<string, Variant> KeyValueRepositoryConfigfile::load()
|
|||
string line, key, value;
|
||||
string::size_type equalPos, garbage;
|
||||
|
||||
ifstream in(myFilename);
|
||||
if(!in || !in.is_open()) {
|
||||
Logger::error("ERROR: Couldn't load from settings file " + myFilename);
|
||||
|
||||
stringstream in;
|
||||
try
|
||||
{
|
||||
myFile.read(in);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Logger::error("ERROR: Couldn't load from settings file " + myFile.getShortPath());
|
||||
return values;
|
||||
}
|
||||
|
||||
|
@ -79,13 +83,7 @@ std::map<string, Variant> KeyValueRepositoryConfigfile::load()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
ofstream out(myFilename);
|
||||
if(!out || !out.is_open()) {
|
||||
Logger::error("ERROR: Couldn't save to settings file " + myFilename);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
stringstream out;
|
||||
out << "; Stella configuration file" << endl
|
||||
<< ";" << endl
|
||||
<< "; Lines starting with ';' are comments and are ignored." << endl
|
||||
|
@ -104,4 +102,13 @@ void KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
|
|||
// Write out each of the key and value pairs
|
||||
for(const auto& pair: values)
|
||||
out << pair.first << " = " << pair.second << endl;
|
||||
|
||||
try
|
||||
{
|
||||
myFile.write(out);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Logger::error("ERROR: Couldn't save to settings file " + myFile.getShortPath());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
#ifndef KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
||||
#define KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
||||
|
||||
#include "FSNode.hxx"
|
||||
#include "KeyValueRepository.hxx"
|
||||
|
||||
class KeyValueRepositoryConfigfile : public KeyValueRepository
|
||||
{
|
||||
public:
|
||||
|
||||
explicit KeyValueRepositoryConfigfile(const string& filename);
|
||||
explicit KeyValueRepositoryConfigfile(const FilesystemNode& file);
|
||||
|
||||
std::map<string, Variant> load() override;
|
||||
|
||||
|
@ -34,7 +35,7 @@ class KeyValueRepositoryConfigfile : public KeyValueRepository
|
|||
|
||||
private:
|
||||
|
||||
const string& myFilename;
|
||||
FilesystemNode myFile;
|
||||
};
|
||||
|
||||
#endif // KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
||||
|
|
|
@ -747,7 +747,7 @@ string CartDebug::loadListFile()
|
|||
try
|
||||
{
|
||||
if(lst.read(in) == 0)
|
||||
return DebuggerParser::red("list file '" + lst.getShortPath() + "' not readable");
|
||||
return DebuggerParser::red("list file '" + lst.getShortPath() + "' not found");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -811,7 +811,7 @@ string CartDebug::loadSymbolFile()
|
|||
try
|
||||
{
|
||||
if(sym.read(in) == 0)
|
||||
return DebuggerParser::red("symbol file '" + sym.getShortPath() + "' not readable");
|
||||
return DebuggerParser::red("symbol file '" + sym.getShortPath() + "' not found");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -862,15 +862,14 @@ string CartDebug::loadConfigFile()
|
|||
// on the actual ROM filename
|
||||
|
||||
FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg"));
|
||||
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
|
||||
FilesystemNode cfg = myOSystem.cfgDir(); cfg /= romNode.getName();
|
||||
if(!cfg.isReadable())
|
||||
return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not found");
|
||||
|
||||
stringstream in;
|
||||
try
|
||||
{
|
||||
if(cfg.read(in) == 0)
|
||||
return "Unable to load directives from " + cfg.getPath();
|
||||
cfg.read(in);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -1002,12 +1001,11 @@ string CartDebug::saveConfigFile()
|
|||
try
|
||||
{
|
||||
FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg"));
|
||||
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
|
||||
FilesystemNode cfg = myOSystem.cfgDir(); cfg /= romNode.getName();
|
||||
if(!cfg.getParent().isWritable())
|
||||
return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not writable");
|
||||
|
||||
size_t size = cfg.write(out);
|
||||
if(size == 0)
|
||||
if(cfg.write(out) == 0)
|
||||
return "Unable to save directives to " + cfg.getShortPath();
|
||||
|
||||
if(myConsole.cartridge().romBankCount() > 1)
|
||||
|
@ -1016,7 +1014,7 @@ string CartDebug::saveConfigFile()
|
|||
}
|
||||
catch(const runtime_error& e)
|
||||
{
|
||||
retVal << e.what();
|
||||
retVal << "Unable to save directives: " << e.what();
|
||||
}
|
||||
return retVal.str();
|
||||
}
|
||||
|
@ -1331,24 +1329,21 @@ string CartDebug::saveDisassembly()
|
|||
// And finally, output the disassembly
|
||||
out << buf.str();
|
||||
|
||||
const string& propsname =
|
||||
myConsole.properties().get(PropType::Cart_Name) + ".asm";
|
||||
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + propsname);
|
||||
stringstream retVal;
|
||||
try
|
||||
{
|
||||
const string& propsname =
|
||||
myConsole.properties().get(PropType::Cart_Name) + ".asm";
|
||||
FilesystemNode node(myOSystem.defaultSaveDir() + propsname);
|
||||
|
||||
size_t size = node.write(out);
|
||||
if(size == 0)
|
||||
return "Unable to save disassembly to " + node.getShortPath();
|
||||
node.write(out);
|
||||
|
||||
if(myConsole.cartridge().romBankCount() > 1)
|
||||
retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported\n");
|
||||
retVal << "saved " << node.getShortPath() << " OK";
|
||||
}
|
||||
catch(const runtime_error& e)
|
||||
catch(...)
|
||||
{
|
||||
retVal << e.what();
|
||||
retVal << "Unable to save disassembly to " << node.getShortPath();
|
||||
}
|
||||
return retVal.str();
|
||||
}
|
||||
|
@ -1358,7 +1353,7 @@ string CartDebug::saveRom()
|
|||
{
|
||||
const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".a26";
|
||||
|
||||
FilesystemNode node(myOSystem.defaultSaveDir() + rom);
|
||||
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom);
|
||||
if(myConsole.cartridge().saveROM(node))
|
||||
return "saved ROM as " + node.getShortPath();
|
||||
else
|
||||
|
@ -1376,15 +1371,13 @@ string CartDebug::saveAccessFile()
|
|||
try
|
||||
{
|
||||
const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".csv";
|
||||
FilesystemNode node(myOSystem.defaultSaveDir() + rom);
|
||||
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom);
|
||||
|
||||
size_t size = node.write(out);
|
||||
if(size > 0)
|
||||
return "saved access counters as " + node.getShortPath();
|
||||
node.write(out);
|
||||
return "saved access counters as " + node.getShortPath();
|
||||
}
|
||||
catch(const runtime_error& e)
|
||||
catch(...)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
return DebuggerParser::red("failed to save access counters file");
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ string Debugger::autoExec(StringList* history)
|
|||
ostringstream buf;
|
||||
|
||||
// autoexec.script is always run
|
||||
FilesystemNode autoexec(myOSystem.baseDir() + "autoexec.script");
|
||||
FilesystemNode autoexec(myOSystem.baseDir().getPath() + "autoexec.script");
|
||||
buf << "autoExec():" << endl
|
||||
<< myParser->exec(autoexec, history) << endl;
|
||||
|
||||
|
@ -304,7 +304,7 @@ int Debugger::step(bool save)
|
|||
myOSystem.console().tia().updateScanlineByStep().flushLineCache();
|
||||
lockSystem();
|
||||
|
||||
if(save)
|
||||
if(save)
|
||||
addState("step");
|
||||
return int(mySystem.cycles() - startCycle);
|
||||
}
|
||||
|
|
|
@ -132,9 +132,9 @@ string DebuggerParser::exec(const FilesystemNode& file, StringList* history)
|
|||
{
|
||||
if(file.exists())
|
||||
{
|
||||
ifstream in(file.getPath());
|
||||
if(!in.is_open())
|
||||
return red("script file \'" + file.getShortPath() + "\' not found");
|
||||
stringstream in;
|
||||
try { file.read(in); }
|
||||
catch(...) { return red("script file \'" + file.getShortPath() + "\' not found"); }
|
||||
|
||||
ostringstream buf;
|
||||
int count = 0;
|
||||
|
@ -633,11 +633,7 @@ string DebuggerParser::saveScriptFile(string file)
|
|||
if(file.find_last_of('.') == string::npos)
|
||||
file += ".script";
|
||||
|
||||
FilesystemNode node(debugger.myOSystem.defaultSaveDir() + file);
|
||||
ofstream out(node.getPath());
|
||||
if(!out.is_open())
|
||||
return "Unable to save script to " + node.getShortPath();
|
||||
|
||||
stringstream out;
|
||||
Debugger::FunctionDefMap funcs = debugger.getFunctionDefMap();
|
||||
for(const auto& f: funcs)
|
||||
if (!debugger.isBuiltinFunction(f.first))
|
||||
|
@ -678,6 +674,16 @@ string DebuggerParser::saveScriptFile(string file)
|
|||
out << endl;
|
||||
}
|
||||
|
||||
FilesystemNode node(debugger.myOSystem.defaultSaveDir().getPath() + file);
|
||||
try
|
||||
{
|
||||
node.write(out);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return "Unable to save script to " + node.getShortPath();
|
||||
}
|
||||
|
||||
return "saved " + node.getShortPath() + " OK";
|
||||
}
|
||||
|
||||
|
@ -1140,7 +1146,7 @@ void DebuggerParser::executeDump()
|
|||
file << ".dump";
|
||||
FilesystemNode node(file.str());
|
||||
// cout << "dump " << args[0] << "-" << args[1] << " to " << file.str() << endl;
|
||||
ofstream ofs(node.getPath(), ofstream::out | ofstream::app);
|
||||
std::ofstream ofs(node.getPath(), std::ofstream::out | std::ofstream::app);
|
||||
if(!ofs.is_open())
|
||||
{
|
||||
outputCommandError("Unable to append dump to file " + node.getShortPath(), myCommand);
|
||||
|
@ -1221,9 +1227,8 @@ void DebuggerParser::executeExec()
|
|||
if(file.find_last_of('.') == string::npos)
|
||||
file += ".script";
|
||||
FilesystemNode node(file);
|
||||
if (!node.exists()) {
|
||||
node = FilesystemNode(debugger.myOSystem.defaultSaveDir() + file);
|
||||
}
|
||||
if (!node.exists())
|
||||
node = FilesystemNode(debugger.myOSystem.defaultSaveDir().getPath() + file);
|
||||
|
||||
if (argCount == 2) {
|
||||
execPrefix = argStrings[1];
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AtariVox::AtariVox(Jack jack, const Event& event, const System& system,
|
||||
const string& portname, const string& eepromfile,
|
||||
const string& portname, const FilesystemNode& eepromfile,
|
||||
const onMessageCallback& callback)
|
||||
: SaveKey(jack, event, system, eepromfile, callback, Controller::Type::AtariVox)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class OSystem;
|
||||
class SerialPort;
|
||||
class FilesystemNode;
|
||||
|
||||
#include "Control.hxx"
|
||||
#include "SaveKey.hxx"
|
||||
|
@ -47,7 +48,7 @@ class AtariVox : public SaveKey
|
|||
@param callback Called to pass messages back to the parent controller
|
||||
*/
|
||||
AtariVox(Jack jack, const Event& event, const System& system,
|
||||
const string& portname, const string& eepromfile,
|
||||
const string& portname, const FilesystemNode& eepromfile,
|
||||
const onMessageCallback& callback);
|
||||
virtual ~AtariVox();
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
|||
myConsoleInfo.BankSwitch = myCart->about();
|
||||
|
||||
// Some carts have an associated nvram file
|
||||
myCart->setNVRamFile(myOSystem.nvramDir(), myConsoleInfo.CartName);
|
||||
myCart->setNVRamFile(myOSystem.nvramDir().getPath(), myConsoleInfo.CartName);
|
||||
|
||||
// Let the other devices know about the new console
|
||||
mySystem->consoleChanged(myConsoleTiming);
|
||||
|
@ -824,7 +824,8 @@ unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
|
|||
|
||||
case Controller::Type::AtariVox:
|
||||
{
|
||||
const string& nvramfile = myOSystem.nvramDir() + "atarivox_eeprom.dat";
|
||||
FilesystemNode nvramfile = myOSystem.nvramDir();
|
||||
nvramfile /= "atarivox_eeprom.dat";
|
||||
Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) {
|
||||
bool devSettings = os.settings().getBool("dev.settings");
|
||||
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
|
||||
|
@ -836,7 +837,8 @@ unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
|
|||
}
|
||||
case Controller::Type::SaveKey:
|
||||
{
|
||||
const string& nvramfile = myOSystem.nvramDir() + "savekey_eeprom.dat";
|
||||
FilesystemNode nvramfile = myOSystem.nvramDir();
|
||||
nvramfile /= "savekey_eeprom.dat";
|
||||
Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) {
|
||||
bool devSettings = os.settings().getBool("dev.settings");
|
||||
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
|
||||
|
|
|
@ -334,8 +334,9 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
|
|||
#endif
|
||||
#if 0
|
||||
case SystemEvent::WINDOW_MINIMIZED:
|
||||
if(myState == EventHandlerState::EMULATION) enterMenuMode(EventHandlerState::OPTIONSMENU);
|
||||
break;
|
||||
if(myState == EventHandlerState::EMULATION)
|
||||
enterMenuMode(EventHandlerState::OPTIONSMENU);
|
||||
break;
|
||||
#endif
|
||||
default: // handle other events as testing requires
|
||||
// cerr << "handleSystemEvent: " << e << endl;
|
||||
|
@ -343,7 +344,6 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandler::AdjustGroup EventHandler::getAdjustGroup()
|
||||
{
|
||||
|
|
|
@ -25,15 +25,49 @@ FilesystemNode::FilesystemNode(const AbstractFSNodePtr& realNode)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FilesystemNode::FilesystemNode(const string& p)
|
||||
FilesystemNode::FilesystemNode(const string& path)
|
||||
{
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FilesystemNode::setPath(const string& path)
|
||||
{
|
||||
// Only create a new object when necessary
|
||||
if (path == getPath())
|
||||
return;
|
||||
|
||||
// Is this potentially a ZIP archive?
|
||||
#if defined(ZIP_SUPPORT)
|
||||
if (BSPF::containsIgnoreCase(p, ".zip"))
|
||||
_realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::Type::ZIP);
|
||||
if (BSPF::containsIgnoreCase(path, ".zip"))
|
||||
_realNode = FilesystemNodeFactory::create(path, FilesystemNodeFactory::Type::ZIP);
|
||||
else
|
||||
#endif
|
||||
_realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::Type::SYSTEM);
|
||||
_realNode = FilesystemNodeFactory::create(path, FilesystemNodeFactory::Type::SYSTEM);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FilesystemNode& FilesystemNode::operator/=(const string& path)
|
||||
{
|
||||
// This part could probably be put in a virtual function, but it seems like
|
||||
// a waste since almost every system uses the same separator, except Windows
|
||||
#ifdef BSPF_WINDOWS
|
||||
#define PATH_SEPARATOR '\\'
|
||||
#else
|
||||
#define PATH_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
if (path != EmptyString)
|
||||
{
|
||||
string newPath = getPath();
|
||||
if (newPath != EmptyString && newPath[newPath.length()-1] != PATH_SEPARATOR)
|
||||
newPath += PATH_SEPARATOR;
|
||||
newPath += path;
|
||||
setPath(newPath);
|
||||
}
|
||||
|
||||
return *this;
|
||||
#undef PATH_SEPARATOR
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -234,7 +268,7 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const
|
|||
return sizeRead;
|
||||
|
||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||
ifstream in(getPath(), std::ios::binary);
|
||||
std::ifstream in(getPath(), std::ios::binary);
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
|
@ -268,7 +302,7 @@ size_t FilesystemNode::read(stringstream& buffer) const
|
|||
|
||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||
// and convert to a stringstream
|
||||
ifstream in(getPath(), std::ios::binary);
|
||||
std::ifstream in(getPath(), std::ios::binary);
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
|
@ -296,7 +330,7 @@ size_t FilesystemNode::write(const ByteBuffer& buffer, size_t size) const
|
|||
return sizeWritten;
|
||||
|
||||
// Otherwise, the default behaviour is to write to a normal C++ ofstream
|
||||
ofstream out(getPath(), std::ios::binary);
|
||||
std::ofstream out(getPath(), std::ios::binary);
|
||||
if (out)
|
||||
{
|
||||
out.write(reinterpret_cast<const char*>(buffer.get()), size);
|
||||
|
@ -321,7 +355,7 @@ size_t FilesystemNode::write(const stringstream& buffer) const
|
|||
return sizeWritten;
|
||||
|
||||
// Otherwise, the default behaviour is to write to a normal C++ ofstream
|
||||
ofstream out(getPath(), std::ios::binary);
|
||||
std::ofstream out(getPath(), std::ios::binary);
|
||||
if (out)
|
||||
{
|
||||
out << buffer.rdbuf();
|
||||
|
|
|
@ -84,13 +84,19 @@ class FilesystemNode
|
|||
|
||||
/**
|
||||
* Compare the name of this node to the name of another, testing for
|
||||
* equality,
|
||||
* equality.
|
||||
*/
|
||||
inline bool operator==(const FilesystemNode& node) const
|
||||
{
|
||||
return BSPF::compareIgnoreCase(getName(), node.getName()) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given path to the node, adding a directory separator
|
||||
* when necessary. Modelled on the C++17 fs::path API.
|
||||
*/
|
||||
FilesystemNode& operator/=(const string& path);
|
||||
|
||||
/**
|
||||
* By default, the output operator simply outputs the fully-qualified
|
||||
* pathname of the node.
|
||||
|
@ -269,6 +275,7 @@ class FilesystemNode
|
|||
private:
|
||||
AbstractFSNodePtr _realNode;
|
||||
explicit FilesystemNode(const AbstractFSNodePtr& realNode);
|
||||
void setPath(const string& path);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -43,27 +43,23 @@
|
|||
*/
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
MT24LC256::MT24LC256(const string& filename, const System& system,
|
||||
MT24LC256::MT24LC256(const FilesystemNode& eepromfile, const System& system,
|
||||
const Controller::onMessageCallback& callback)
|
||||
: mySystem(system),
|
||||
myCallback(callback),
|
||||
myDataFile(filename)
|
||||
myDataFile(eepromfile)
|
||||
{
|
||||
// Load the data from an external file (if it exists)
|
||||
ifstream in(myDataFile, std::ios_base::binary);
|
||||
if(in.is_open())
|
||||
try
|
||||
{
|
||||
// Get length of file; it must be 32768
|
||||
in.seekg(0, std::ios::end);
|
||||
if(uInt32(in.tellg()) == FLASH_SIZE)
|
||||
{
|
||||
in.seekg(0, std::ios::beg);
|
||||
in.read(reinterpret_cast<char*>(myData.data()), myData.size());
|
||||
if(myDataFile.read(myData) == FLASH_SIZE)
|
||||
myDataFileExists = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch(...)
|
||||
{
|
||||
myDataFileExists = false;
|
||||
}
|
||||
|
||||
// Then initialize the I2C state
|
||||
jpee_init();
|
||||
|
@ -77,9 +73,8 @@ MT24LC256::~MT24LC256()
|
|||
// Save EEPROM data to external file only when necessary
|
||||
if(!myDataFileExists || myDataChanged)
|
||||
{
|
||||
ofstream out(myDataFile, std::ios_base::binary);
|
||||
if(out.is_open())
|
||||
out.write(reinterpret_cast<char*>(myData.data()), myData.size());
|
||||
try { myDataFile.write(myData, FLASH_SIZE); }
|
||||
catch(...) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +134,7 @@ void MT24LC256::eraseAll()
|
|||
// Work around a bug in XCode 11.2 with -O0 and -O1
|
||||
const uInt8 initialValue = INITIAL_VALUE;
|
||||
|
||||
myData.fill(initialValue);
|
||||
std::fill_n(myData.get(), FLASH_SIZE, initialValue);
|
||||
myDataChanged = true;
|
||||
}
|
||||
|
||||
|
@ -153,7 +148,7 @@ void MT24LC256::eraseCurrent()
|
|||
{
|
||||
if(myPageHit[page])
|
||||
{
|
||||
std::fill_n(myData.begin() + page * PAGE_SIZE, PAGE_SIZE, initialValue);
|
||||
std::fill_n(myData.get() + page * PAGE_SIZE, PAGE_SIZE, initialValue);
|
||||
myDataChanged = true;
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +177,7 @@ void MT24LC256::jpee_init()
|
|||
jpee_smallmode = 0;
|
||||
jpee_logmode = -1;
|
||||
if(!myDataFileExists)
|
||||
myData.fill(initialValue);
|
||||
std::fill_n(myData.get(), FLASH_SIZE, initialValue);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
class System;
|
||||
|
||||
#include "Control.hxx"
|
||||
#include "FSNode.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
|
@ -36,11 +37,11 @@ class MT24LC256
|
|||
/**
|
||||
Create a new 24LC256 with its data stored in the given file
|
||||
|
||||
@param filename Data file containing the EEPROM data
|
||||
@param system The system using the controller of this device
|
||||
@param callback Called to pass messages back to the parent controller
|
||||
@param eepromfile Data file containing the EEPROM data
|
||||
@param system The system using the controller of this device
|
||||
@param callback Called to pass messages back to the parent controller
|
||||
*/
|
||||
MT24LC256(const string& filename, const System& system,
|
||||
MT24LC256(const FilesystemNode& eepromfile, const System& system,
|
||||
const Controller::onMessageCallback& callback);
|
||||
~MT24LC256();
|
||||
|
||||
|
@ -92,7 +93,7 @@ class MT24LC256
|
|||
Controller::onMessageCallback myCallback;
|
||||
|
||||
// The EEPROM data
|
||||
std::array<uInt8, FLASH_SIZE> myData;
|
||||
ByteBuffer myData;
|
||||
|
||||
// Track which pages are used
|
||||
std::array<bool, PAGE_NUM> myPageHit;
|
||||
|
@ -110,7 +111,7 @@ class MT24LC256
|
|||
uInt64 myCyclesWhenSDASet{0}, myCyclesWhenSCLSet{0};
|
||||
|
||||
// The file containing the EEPROM data
|
||||
string myDataFile;
|
||||
FilesystemNode myDataFile;
|
||||
|
||||
// Indicates if a valid EEPROM data file exists/was successfully loaded
|
||||
bool myDataFileExists{false};
|
||||
|
|
|
@ -121,22 +121,22 @@ bool OSystem::create()
|
|||
<< " Features: " << myFeatures << endl
|
||||
<< " " << myBuildInfo << endl << endl
|
||||
<< "Base directory: '"
|
||||
<< FilesystemNode(myBaseDir).getShortPath() << "'" << endl
|
||||
<< myBaseDir.getShortPath() << "'" << endl
|
||||
<< "State directory: '"
|
||||
<< FilesystemNode(myStateDir).getShortPath() << "'" << endl
|
||||
<< myStateDir.getShortPath() << "'" << endl
|
||||
<< "NVRam directory: '"
|
||||
<< FilesystemNode(myNVRamDir).getShortPath() << "'" << endl;
|
||||
<< myNVRamDir.getShortPath() << "'" << endl;
|
||||
|
||||
if(!myConfigFile.empty())
|
||||
if(myConfigFile.getPath() != EmptyString)
|
||||
buf << "Configuration file: '"
|
||||
<< FilesystemNode(myConfigFile).getShortPath() << "'" << endl;
|
||||
<< myConfigFile.getShortPath() << "'" << endl;
|
||||
|
||||
buf << "Game properties: '"
|
||||
<< myPropertiesFile.getShortPath() << "'" << endl
|
||||
<< "Cheat file: '"
|
||||
<< FilesystemNode(myCheatFile).getShortPath() << "'" << endl
|
||||
<< myCheatFile.getShortPath() << "'" << endl
|
||||
<< "Palette file: '"
|
||||
<< FilesystemNode(myPaletteFile).getShortPath() << "'" << endl;
|
||||
<< myPaletteFile.getShortPath() << "'" << endl;
|
||||
Logger::info(buf.str());
|
||||
|
||||
// NOTE: The framebuffer MUST be created before any other object!!!
|
||||
|
@ -193,30 +193,27 @@ void OSystem::loadConfig(const Settings::Options& options)
|
|||
{
|
||||
// Get base directory and config file from derived class
|
||||
// It will decide whether it can override its default location
|
||||
getBaseDirAndConfig(myBaseDir, myConfigFile,
|
||||
myDefaultSaveDir, myDefaultLoadDir,
|
||||
ourOverrideBaseDirWithApp, ourOverrideBaseDir);
|
||||
string baseDir, cfgFile, defSaveDir, defLoadDir;
|
||||
getBaseDirAndConfig(baseDir, cfgFile, defSaveDir, defLoadDir,
|
||||
ourOverrideBaseDirWithApp, ourOverrideBaseDir);
|
||||
|
||||
// Get fully-qualified pathnames, and make directories when needed
|
||||
FilesystemNode node(myBaseDir);
|
||||
if(!node.isDirectory())
|
||||
node.makeDir();
|
||||
myBaseDir = node.getPath();
|
||||
if(!myConfigFile.empty())
|
||||
myConfigFile = FilesystemNode(myConfigFile).getPath();
|
||||
myBaseDir = FilesystemNode(baseDir);
|
||||
if(!myBaseDir.isDirectory())
|
||||
myBaseDir.makeDir();
|
||||
if(!cfgFile.empty())
|
||||
myConfigFile = FilesystemNode(cfgFile);
|
||||
|
||||
FilesystemNode save(myDefaultSaveDir);
|
||||
if(!save.isDirectory())
|
||||
save.makeDir();
|
||||
myDefaultSaveDir = save.getShortPath();
|
||||
myDefaultSaveDir = FilesystemNode(defSaveDir);
|
||||
if(!myDefaultSaveDir.isDirectory())
|
||||
myDefaultSaveDir.makeDir();
|
||||
|
||||
FilesystemNode load(myDefaultLoadDir);
|
||||
if(!load.isDirectory())
|
||||
load.makeDir();
|
||||
myDefaultLoadDir = load.getShortPath();
|
||||
myDefaultLoadDir = FilesystemNode(defLoadDir);
|
||||
if(!myDefaultLoadDir.isDirectory())
|
||||
myDefaultLoadDir.makeDir();
|
||||
|
||||
#ifdef SQLITE_SUPPORT
|
||||
mySettingsDb = make_shared<SettingsDb>(myBaseDir, "settings");
|
||||
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "settings");
|
||||
if(!mySettingsDb->initialize())
|
||||
mySettingsDb.reset();
|
||||
#endif
|
||||
|
@ -259,38 +256,48 @@ void OSystem::saveConfig()
|
|||
void OSystem::setConfigPaths()
|
||||
{
|
||||
// Make sure all required directories actually exist
|
||||
auto buildDirIfRequired = [](string& path, const string& pathToBuild)
|
||||
auto buildDirIfRequired = [](FilesystemNode& path,
|
||||
const FilesystemNode& initialPath,
|
||||
const string& pathToAppend = EmptyString)
|
||||
{
|
||||
FilesystemNode node(pathToBuild);
|
||||
if(!node.isDirectory())
|
||||
node.makeDir();
|
||||
|
||||
path = node.getPath();
|
||||
path = initialPath;
|
||||
if(pathToAppend != EmptyString)
|
||||
path /= pathToAppend;
|
||||
if(!path.isDirectory())
|
||||
path.makeDir();
|
||||
};
|
||||
|
||||
buildDirIfRequired(myStateDir, myBaseDir + "state");
|
||||
buildDirIfRequired(myNVRamDir, myBaseDir + "nvram");
|
||||
buildDirIfRequired(myStateDir, myBaseDir, "state");
|
||||
buildDirIfRequired(myNVRamDir, myBaseDir, "nvram");
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
buildDirIfRequired(myCfgDir, myBaseDir + "cfg");
|
||||
buildDirIfRequired(myCfgDir, myBaseDir, "cfg");
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
mySnapshotSaveDir = mySettings->getString("snapsavedir");
|
||||
if(mySnapshotSaveDir == "") mySnapshotSaveDir = defaultSaveDir();
|
||||
buildDirIfRequired(mySnapshotSaveDir, mySnapshotSaveDir);
|
||||
const string& ssSaveDir = mySettings->getString("snapsavedir");
|
||||
if(ssSaveDir == EmptyString)
|
||||
mySnapshotSaveDir = defaultSaveDir();
|
||||
else
|
||||
mySnapshotSaveDir = FilesystemNode(ssSaveDir);
|
||||
if(!mySnapshotSaveDir.isDirectory())
|
||||
mySnapshotSaveDir.makeDir();
|
||||
|
||||
mySnapshotLoadDir = mySettings->getString("snaploaddir");
|
||||
if(mySnapshotLoadDir == "") mySnapshotLoadDir = defaultLoadDir();
|
||||
buildDirIfRequired(mySnapshotLoadDir, mySnapshotLoadDir);
|
||||
const string& ssLoadDir = mySettings->getString("snaploaddir");
|
||||
if(ssLoadDir == EmptyString)
|
||||
mySnapshotLoadDir = defaultLoadDir();
|
||||
else
|
||||
mySnapshotLoadDir = FilesystemNode(ssLoadDir);
|
||||
if(!mySnapshotLoadDir.isDirectory())
|
||||
mySnapshotLoadDir.makeDir();
|
||||
#endif
|
||||
|
||||
myCheatFile = FilesystemNode(myBaseDir + "stella.cht").getPath();
|
||||
myPaletteFile = FilesystemNode(myBaseDir + "stella.pal").getPath();
|
||||
myPropertiesFile = FilesystemNode(myBaseDir + "stella.pro");
|
||||
myCheatFile = myBaseDir; myCheatFile /= "stella.cht";
|
||||
myPaletteFile = myBaseDir; myPaletteFile /= "stella.pal";
|
||||
myPropertiesFile = myBaseDir; myPropertiesFile /= "stella.pro";
|
||||
|
||||
#if 0
|
||||
// Debug code
|
||||
auto dbgPath = [](const string& desc, const string& location)
|
||||
auto dbgPath = [](const string& desc, const FilesystemNode& location)
|
||||
{
|
||||
cerr << desc << ": " << location << endl;
|
||||
};
|
||||
|
@ -310,21 +317,24 @@ void OSystem::setConfigPaths()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool OSystem::checkUserPalette(bool outputError) const
|
||||
{
|
||||
const string& palette = paletteFile();
|
||||
ifstream in(palette, std::ios::binary);
|
||||
if (!in)
|
||||
return false;
|
||||
|
||||
// Make sure the contains enough data for the NTSC, PAL and SECAM palettes
|
||||
// This means 128 colours each for NTSC and PAL, at 3 bytes per pixel
|
||||
// and 8 colours for SECAM at 3 bytes per pixel
|
||||
in.seekg(0, std::ios::end);
|
||||
std::streampos length = in.tellg();
|
||||
in.seekg(0, std::ios::beg);
|
||||
if (length < 128 * 3 * 2 + 8 * 3)
|
||||
try
|
||||
{
|
||||
ByteBuffer palette;
|
||||
size_t size = paletteFile().read(palette);
|
||||
|
||||
// Make sure the contains enough data for the NTSC, PAL and SECAM palettes
|
||||
// This means 128 colours each for NTSC and PAL, at 3 bytes per pixel
|
||||
// and 8 colours for SECAM at 3 bytes per pixel
|
||||
if(size != 128 * 3 * 2 + 8 * 3)
|
||||
{
|
||||
if(outputError)
|
||||
cerr << "ERROR: invalid palette file " << paletteFile() << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
if (outputError)
|
||||
cerr << "ERROR: invalid palette file " << palette << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -457,8 +467,11 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
|
|||
myConsole->cartridge().detectedType() + ", loading ROM" + id);
|
||||
}
|
||||
buf << "Game console created:" << endl
|
||||
<< " ROM file: " << myRomFile.getShortPath() << endl << endl
|
||||
<< getROMInfo(*myConsole);
|
||||
<< " ROM file: " << myRomFile.getShortPath() << endl;
|
||||
FilesystemNode propsFile(myRomFile.getPathWithExt(".pro"));
|
||||
if(propsFile.exists())
|
||||
buf << " PRO file: " << propsFile.getShortPath() << endl;
|
||||
buf << endl << getROMInfo(*myConsole);
|
||||
Logger::info(buf.str());
|
||||
|
||||
myFrameBuffer->setCursorState();
|
||||
|
@ -821,7 +834,7 @@ shared_ptr<KeyValueRepository> OSystem::createSettingsRepository()
|
|||
? shared_ptr<KeyValueRepository>(mySettingsDb, &mySettingsDb->settingsRepository())
|
||||
: make_shared<KeyValueRepositoryNoop>();
|
||||
#else
|
||||
if (myConfigFile.empty())
|
||||
if (myConfigFile.getPath() == EmptyString)
|
||||
return make_shared<KeyValueRepositoryNoop>();
|
||||
|
||||
return make_shared<KeyValueRepositoryConfigfile>(myConfigFile);
|
||||
|
|
|
@ -246,53 +246,48 @@ class OSystem
|
|||
void setConfigPaths();
|
||||
|
||||
/**
|
||||
Return the default full/complete directory name for storing data.
|
||||
Return the default full/complete path name for storing data.
|
||||
*/
|
||||
const string& baseDir() const { return myBaseDir; }
|
||||
const FilesystemNode& baseDir() const { return myBaseDir; }
|
||||
|
||||
/**
|
||||
Return the full/complete directory name for storing state files.
|
||||
Return the full/complete path name for storing state files.
|
||||
*/
|
||||
const string& stateDir() const { return myStateDir; }
|
||||
const FilesystemNode& stateDir() const { return myStateDir; }
|
||||
|
||||
/**
|
||||
Return the full/complete directory name for storing nvram
|
||||
Return the full/complete path name for storing nvram
|
||||
(flash/EEPROM) files.
|
||||
*/
|
||||
const string& nvramDir() const { return myNVRamDir; }
|
||||
const FilesystemNode& nvramDir() const { return myNVRamDir; }
|
||||
|
||||
#ifdef CHEATCODE_SUPPORT
|
||||
/**
|
||||
This method should be called to get the full path of the cheat file.
|
||||
|
||||
@return String representing the full path of the cheat filename.
|
||||
Return the full/complete path name of the cheat file.
|
||||
*/
|
||||
const string& cheatFile() const { return myCheatFile; }
|
||||
const FilesystemNode& cheatFile() const { return myCheatFile; }
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Return the full/complete directory name for storing Distella cfg files.
|
||||
Return the full/complete path name for storing Distella cfg files.
|
||||
*/
|
||||
const string& cfgDir() const { return myCfgDir; }
|
||||
const FilesystemNode& cfgDir() const { return myCfgDir; }
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
/**
|
||||
Return the full/complete directory name for saving and loading
|
||||
Return the full/complete path name for saving and loading
|
||||
PNG snapshots.
|
||||
*/
|
||||
const string& snapshotSaveDir() const { return mySnapshotSaveDir; }
|
||||
const string& snapshotLoadDir() const { return mySnapshotLoadDir; }
|
||||
const FilesystemNode& snapshotSaveDir() const { return mySnapshotSaveDir; }
|
||||
const FilesystemNode& snapshotLoadDir() const { return mySnapshotLoadDir; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
This method should be called to get the full path of the
|
||||
(optional) palette file.
|
||||
|
||||
@return String representing the full path of the properties filename.
|
||||
Return the full/complete path name of the (optional) palette file.
|
||||
*/
|
||||
const string& paletteFile() const { return myPaletteFile; }
|
||||
const FilesystemNode& paletteFile() const { return myPaletteFile; }
|
||||
|
||||
/**
|
||||
Checks if a valid a user-defined palette file exists.
|
||||
|
@ -300,10 +295,7 @@ class OSystem
|
|||
bool checkUserPalette(bool outputError = false) const;
|
||||
|
||||
/**
|
||||
This method should be called to get the full path of the currently
|
||||
loaded ROM.
|
||||
|
||||
@return FSNode object representing the ROM file.
|
||||
Return the full/complete path name of the currently loaded ROM.
|
||||
*/
|
||||
const FilesystemNode& romFile() const { return myRomFile; }
|
||||
|
||||
|
@ -311,8 +303,8 @@ class OSystem
|
|||
The default locations for saving and loading various files that
|
||||
don't already have a specific location.
|
||||
*/
|
||||
const string& defaultSaveDir() const { return myDefaultSaveDir; }
|
||||
const string& defaultLoadDir() const { return myDefaultLoadDir; }
|
||||
const FilesystemNode& defaultSaveDir() const { return myDefaultSaveDir; }
|
||||
const FilesystemNode& defaultLoadDir() const { return myDefaultLoadDir; }
|
||||
|
||||
/**
|
||||
Open the given ROM and return an array containing its contents.
|
||||
|
@ -533,22 +525,10 @@ class OSystem
|
|||
bool myQuitLoop{false};
|
||||
|
||||
private:
|
||||
string myBaseDir;
|
||||
string myStateDir;
|
||||
string mySnapshotSaveDir;
|
||||
string mySnapshotLoadDir;
|
||||
string myNVRamDir;
|
||||
string myCfgDir;
|
||||
string myDefaultSaveDir;
|
||||
string myDefaultLoadDir;
|
||||
|
||||
string myCheatFile;
|
||||
string myConfigFile;
|
||||
string myPaletteFile;
|
||||
FilesystemNode myPropertiesFile;
|
||||
|
||||
FilesystemNode myRomFile;
|
||||
string myRomMD5;
|
||||
FilesystemNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir,
|
||||
myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir;
|
||||
FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile;
|
||||
FilesystemNode myRomFile; string myRomMD5;
|
||||
|
||||
string myFeatures;
|
||||
string myBuildInfo;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
|
||||
const string& eepromfile, const onMessageCallback& callback,
|
||||
const FilesystemNode& eepromfile, const onMessageCallback& callback,
|
||||
Type type)
|
||||
: Controller(jack, event, system, type),
|
||||
myEEPROM(make_unique<MT24LC256>(eepromfile, system, callback))
|
||||
|
@ -33,7 +33,7 @@ SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
|
||||
const string& eepromfile, const onMessageCallback& callback)
|
||||
const FilesystemNode& eepromfile, const onMessageCallback& callback)
|
||||
: SaveKey(jack, event, system, eepromfile, callback, Controller::Type::SaveKey)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class MT24LC256;
|
||||
class OSystem;
|
||||
class FilesystemNode;
|
||||
|
||||
#include "Control.hxx"
|
||||
|
||||
|
@ -45,7 +46,7 @@ class SaveKey : public Controller
|
|||
@param callback Called to pass messages back to the parent controller
|
||||
*/
|
||||
SaveKey(Jack jack, const Event& event, const System& system,
|
||||
const string& eepromfile, const onMessageCallback& callback);
|
||||
const FilesystemNode& eepromfile, const onMessageCallback& callback);
|
||||
virtual ~SaveKey();
|
||||
|
||||
protected:
|
||||
|
@ -54,7 +55,8 @@ class SaveKey : public Controller
|
|||
that inherit from SaveKey (currently, AtariVox)
|
||||
*/
|
||||
SaveKey(Jack jack, const Event& event, const System& system,
|
||||
const string& eepromfile, const onMessageCallback& callback, Type type);
|
||||
const FilesystemNode& eepromfile,
|
||||
const onMessageCallback& callback, Type type);
|
||||
|
||||
public:
|
||||
using Controller::read;
|
||||
|
|
|
@ -809,17 +809,22 @@ void GameInfoDialog::eraseEEPROM()
|
|||
void GameInfoDialog::saveCurrentPropertiesToDisk()
|
||||
{
|
||||
saveProperties();
|
||||
stringstream out;
|
||||
out << myGameProperties;
|
||||
|
||||
FilesystemNode propfile(instance().defaultSaveDir() + myGameFile.getNameWithExt(".pro"));
|
||||
ofstream out(propfile.getPath());
|
||||
if(out)
|
||||
try
|
||||
{
|
||||
out << myGameProperties;
|
||||
FilesystemNode propfile = instance().defaultSaveDir();
|
||||
propfile /= myGameFile.getNameWithExt(".pro");
|
||||
|
||||
propfile.write(out);
|
||||
instance().frameBuffer().showMessage("Properties saved to " +
|
||||
propfile.getShortPath());
|
||||
}
|
||||
else
|
||||
catch(...)
|
||||
{
|
||||
instance().frameBuffer().showMessage("Error saving properties");
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -116,15 +116,18 @@ void LoggerDialog::saveConfig()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void LoggerDialog::saveLogFile()
|
||||
{
|
||||
ostringstream path;
|
||||
path << instance().defaultSaveDir() << "stella.log";
|
||||
FilesystemNode node(path.str());
|
||||
FilesystemNode node = instance().defaultSaveDir();
|
||||
node /= "stella.log";
|
||||
|
||||
ofstream out(node.getPath());
|
||||
if(out.is_open())
|
||||
try
|
||||
{
|
||||
stringstream out;
|
||||
out << Logger::instance().logMessages();
|
||||
instance().frameBuffer().showMessage("Saving log file to " + path.str());
|
||||
instance().frameBuffer().showMessage("Saving log file to " + node.getShortPath());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
instance().frameBuffer().showMessage("Error savin log file to " + node.getShortPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
|
|||
|
||||
#ifdef PNG_SUPPORT
|
||||
// Get a valid filename representing a snapshot file for this rom
|
||||
const string& filename = instance().snapshotLoadDir() +
|
||||
const string& filename = instance().snapshotLoadDir().getPath() +
|
||||
myProperties.get(PropType::Cart_Name) + ".png";
|
||||
|
||||
// Read the PNG file
|
||||
|
|
|
@ -131,7 +131,7 @@ void SnapshotDialog::saveConfig()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SnapshotDialog::setDefaults()
|
||||
{
|
||||
mySnapSavePath->setText(instance().defaultSaveDir());
|
||||
mySnapSavePath->setText(instance().defaultSaveDir().getShortPath());
|
||||
mySnapInterval->setValue(2);
|
||||
mySnapName->setState(false);
|
||||
mySnapSingle->setState(false);
|
||||
|
|
|
@ -507,7 +507,7 @@ void UIDialog::setDefaults()
|
|||
myLauncherHeightSlider->setValue(h);
|
||||
myLauncherFontPopup->setSelected("medium", "");
|
||||
myRomViewerSize->setValue(35);
|
||||
mySnapLoadPath->setText(instance().defaultLoadDir());
|
||||
mySnapLoadPath->setText(instance().defaultLoadDir().getShortPath());
|
||||
myLauncherExitWidget->setState(false);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue