mirror of https://github.com/stella-emu/stella.git
Merge branch 'master' of https://github.com/stella-emu/stella
This commit is contained in:
commit
3d0c5fa5d3
|
@ -18,6 +18,13 @@
|
||||||
|
|
||||||
* Extended global hotkeys for debug options.
|
* Extended global hotkeys for debug options.
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
-Have fun!
|
||||||
|
|
||||||
|
|
||||||
6.2 to 6.2.1: (June 20, 2020)
|
6.2 to 6.2.1: (June 20, 2020)
|
||||||
|
|
||||||
* Fixed Pitfall II ROM not working correctly.
|
* Fixed Pitfall II ROM not working correctly.
|
||||||
|
@ -61,8 +68,6 @@
|
||||||
* The codebase now compiles under gcc6 again. Future versions will
|
* The codebase now compiles under gcc6 again. Future versions will
|
||||||
require gcc7, though.
|
require gcc7, though.
|
||||||
|
|
||||||
-Have fun!
|
|
||||||
|
|
||||||
|
|
||||||
6.1.2 to 6.2: (June 7, 2020)
|
6.1.2 to 6.2: (June 7, 2020)
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,19 @@ size_t FilesystemNodeZIP::read(ByteBuffer& image) const
|
||||||
return found ? uInt32(myZipHandler->decompress(image)) : 0; // TODO: 64bit
|
return found ? uInt32(myZipHandler->decompress(image)) : 0; // TODO: 64bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
size_t FilesystemNodeZIP::read(stringstream& image) const
|
||||||
|
{
|
||||||
|
// For now, we just read into a buffer and store in the stream
|
||||||
|
// TODO: maybe there's a more efficient way to do this?
|
||||||
|
ByteBuffer buffer;
|
||||||
|
size_t size = read(buffer);
|
||||||
|
if(size > 0)
|
||||||
|
image.write(reinterpret_cast<char*>(buffer.get()), size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
AbstractFSNodePtr FilesystemNodeZIP::getParent() const
|
AbstractFSNodePtr FilesystemNodeZIP::getParent() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,7 @@ class FilesystemNodeZIP : public AbstractFSNode
|
||||||
AbstractFSNodePtr getParent() const override;
|
AbstractFSNodePtr getParent() const override;
|
||||||
|
|
||||||
size_t read(ByteBuffer& image) const override;
|
size_t read(ByteBuffer& image) const override;
|
||||||
|
size_t read(stringstream& image) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilesystemNodeZIP(const string& zipfile, const string& virtualpath,
|
FilesystemNodeZIP(const string& zipfile, const string& virtualpath,
|
||||||
|
|
|
@ -225,7 +225,7 @@ bool FilesystemNode::rename(const string& newfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
size_t FilesystemNode::read(ByteBuffer& image) const
|
size_t FilesystemNode::read(ByteBuffer& buffer) const
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
|
@ -234,11 +234,11 @@ size_t FilesystemNode::read(ByteBuffer& image) const
|
||||||
throw runtime_error("File not found/readable");
|
throw runtime_error("File not found/readable");
|
||||||
|
|
||||||
// First let the private subclass attempt to open the file
|
// First let the private subclass attempt to open the file
|
||||||
if (_realNode && (size = _realNode->read(image)) > 0)
|
if (_realNode && (size = _realNode->read(buffer)) > 0)
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||||
image = make_unique<uInt8[]>(Cartridge::maxSize());
|
buffer = make_unique<uInt8[]>(Cartridge::maxSize());
|
||||||
ifstream in(getPath(), std::ios::binary);
|
ifstream in(getPath(), std::ios::binary);
|
||||||
if (in)
|
if (in)
|
||||||
{
|
{
|
||||||
|
@ -250,7 +250,41 @@ size_t FilesystemNode::read(ByteBuffer& image) const
|
||||||
throw runtime_error("Zero-byte file");
|
throw runtime_error("Zero-byte file");
|
||||||
|
|
||||||
size = std::min<size_t>(length, Cartridge::maxSize());
|
size = std::min<size_t>(length, Cartridge::maxSize());
|
||||||
in.read(reinterpret_cast<char*>(image.get()), size);
|
in.read(reinterpret_cast<char*>(buffer.get()), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw runtime_error("File open/read error");
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
size_t FilesystemNode::read(stringstream& buffer) const
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
// File must actually exist
|
||||||
|
if (!(exists() && isReadable()))
|
||||||
|
throw runtime_error("File not found/readable");
|
||||||
|
|
||||||
|
// First let the private subclass attempt to open the file
|
||||||
|
if (_realNode && (size = _realNode->read(buffer)) > 0)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||||
|
// and convert to a stringstream
|
||||||
|
ifstream in(getPath(), std::ios::binary);
|
||||||
|
if (in)
|
||||||
|
{
|
||||||
|
in.seekg(0, std::ios::end);
|
||||||
|
std::streampos length = in.tellg();
|
||||||
|
in.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
throw runtime_error("Zero-byte file");
|
||||||
|
|
||||||
|
size = std::min<size_t>(length, Cartridge::maxSize());
|
||||||
|
buffer << in.rdbuf();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw runtime_error("File open/read error");
|
throw runtime_error("File open/read error");
|
||||||
|
|
|
@ -241,6 +241,17 @@ class FilesystemNode
|
||||||
*/
|
*/
|
||||||
size_t read(ByteBuffer& buffer) const;
|
size_t read(ByteBuffer& buffer) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data (text format) into the given stream.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer stream to contain the data.
|
||||||
|
*
|
||||||
|
* @return The number of bytes read (0 in the case of failure)
|
||||||
|
* This method can throw exceptions, and should be used inside
|
||||||
|
* a try-catch block.
|
||||||
|
*/
|
||||||
|
size_t read(stringstream& buffer) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following methods are almost exactly the same as the various
|
* The following methods are almost exactly the same as the various
|
||||||
* getXXXX() methods above. Internally, they call the respective methods
|
* getXXXX() methods above. Internally, they call the respective methods
|
||||||
|
@ -400,6 +411,17 @@ class AbstractFSNode
|
||||||
* a try-catch block.
|
* a try-catch block.
|
||||||
*/
|
*/
|
||||||
virtual size_t read(ByteBuffer& buffer) const { return 0; }
|
virtual size_t read(ByteBuffer& buffer) const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data (text format) into the given steam.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer stream to containing the data
|
||||||
|
*
|
||||||
|
* @return The number of bytes read (0 in the case of failure)
|
||||||
|
* This method can throw exceptions, and should be used inside
|
||||||
|
* a try-catch block.
|
||||||
|
*/
|
||||||
|
virtual size_t read(stringstream& buffer) const { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -132,7 +132,7 @@ bool OSystem::create()
|
||||||
<< FilesystemNode(myConfigFile).getShortPath() << "'" << endl;
|
<< FilesystemNode(myConfigFile).getShortPath() << "'" << endl;
|
||||||
|
|
||||||
buf << "Game properties: '"
|
buf << "Game properties: '"
|
||||||
<< FilesystemNode(myPropertiesFile).getShortPath() << "'" << endl
|
<< myPropertiesFile.getShortPath() << "'" << endl
|
||||||
<< "Cheat file: '"
|
<< "Cheat file: '"
|
||||||
<< FilesystemNode(myCheatFile).getShortPath() << "'" << endl
|
<< FilesystemNode(myCheatFile).getShortPath() << "'" << endl
|
||||||
<< "Palette file: '"
|
<< "Palette file: '"
|
||||||
|
@ -251,7 +251,7 @@ void OSystem::saveConfig()
|
||||||
Logger::debug("Saving config options ...");
|
Logger::debug("Saving config options ...");
|
||||||
mySettings->save();
|
mySettings->save();
|
||||||
|
|
||||||
if(myPropSet && myPropSet->save(myPropertiesFile))
|
if(myPropSet && myPropSet->save(myPropertiesFile.getPath()))
|
||||||
Logger::debug("Saving properties set ...");
|
Logger::debug("Saving properties set ...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ void OSystem::setConfigPaths()
|
||||||
|
|
||||||
myCheatFile = FilesystemNode(myBaseDir + "stella.cht").getPath();
|
myCheatFile = FilesystemNode(myBaseDir + "stella.cht").getPath();
|
||||||
myPaletteFile = FilesystemNode(myBaseDir + "stella.pal").getPath();
|
myPaletteFile = FilesystemNode(myBaseDir + "stella.pal").getPath();
|
||||||
myPropertiesFile = FilesystemNode(myBaseDir + "stella.pro").getPath();
|
myPropertiesFile = FilesystemNode(myBaseDir + "stella.pro");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Debug code
|
// Debug code
|
||||||
|
|
|
@ -545,7 +545,7 @@ class OSystem
|
||||||
string myCheatFile;
|
string myCheatFile;
|
||||||
string myConfigFile;
|
string myConfigFile;
|
||||||
string myPaletteFile;
|
string myPaletteFile;
|
||||||
string myPropertiesFile;
|
FilesystemNode myPropertiesFile;
|
||||||
|
|
||||||
FilesystemNode myRomFile;
|
FilesystemNode myRomFile;
|
||||||
string myRomMD5;
|
string myRomMD5;
|
||||||
|
|
|
@ -24,13 +24,21 @@
|
||||||
#include "PropsSet.hxx"
|
#include "PropsSet.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PropertiesSet::load(const string& filename, bool save)
|
void PropertiesSet::load(const FilesystemNode& file, bool save)
|
||||||
{
|
{
|
||||||
ifstream in(filename);
|
try
|
||||||
|
{
|
||||||
Properties prop;
|
stringstream in;
|
||||||
while(in >> prop)
|
if(file.exists() && file.read(in) > 0)
|
||||||
insert(prop, save);
|
{
|
||||||
|
Properties prop;
|
||||||
|
while(in >> prop)
|
||||||
|
insert(prop, save);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -166,8 +174,9 @@ void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5)
|
||||||
// First, does this ROM have a per-ROM properties entry?
|
// First, does this ROM have a per-ROM properties entry?
|
||||||
// If so, load it into the database
|
// If so, load it into the database
|
||||||
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
|
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
|
||||||
if(propsNode.exists() && propsNode.isFile())
|
|
||||||
load(propsNode.getPath(), false);
|
if(propsNode.exists())
|
||||||
|
load(propsNode, false);
|
||||||
|
|
||||||
// Next, make sure we have a valid md5 and name
|
// Next, make sure we have a valid md5 and name
|
||||||
Properties props;
|
Properties props;
|
||||||
|
|
|
@ -48,11 +48,11 @@ class PropertiesSet
|
||||||
Load properties from the specified file, and create an internal
|
Load properties from the specified file, and create an internal
|
||||||
searchable list.
|
searchable list.
|
||||||
|
|
||||||
@param filename Full pathname of input file to use
|
@param file The node representing the input file to use
|
||||||
@param save Indicates whether the properties should be saved
|
@param save Indicates whether the properties should be saved
|
||||||
when the program exits
|
when the program exits
|
||||||
*/
|
*/
|
||||||
void load(const string& filename, bool save = true);
|
void load(const FilesystemNode& file, bool save = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save properties to the specified file.
|
Save properties to the specified file.
|
||||||
|
|
Loading…
Reference in New Issue