mirror of https://github.com/stella-emu/stella.git
Move detection of MVC file out of FSNode class. There are several reasons for this:
- It more properly belongs in the class actually opening the ROM, since FSNode can represent more than just ROM files. - Some ports don't have proper FSNode support, so MVC would break there. - In general, it makes FSNode::read more general, able to read partial files.
This commit is contained in:
parent
e5287ae125
commit
bc877443c1
|
@ -180,7 +180,7 @@ bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FilesystemNodeZIP::read(ByteBuffer& image) const
|
||||
size_t FilesystemNodeZIP::read(ByteBuffer& image, size_t) const
|
||||
{
|
||||
switch(_error)
|
||||
{
|
||||
|
@ -205,7 +205,7 @@ 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);
|
||||
size_t size = read(buffer, 0);
|
||||
if(size > 0)
|
||||
image.write(reinterpret_cast<char*>(buffer.get()), size);
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ class FilesystemNodeZIP : public AbstractFSNode
|
|||
bool getChildren(AbstractFSList& list, ListMode mode) const override;
|
||||
AbstractFSNodePtr getParent() const override;
|
||||
|
||||
size_t read(ByteBuffer& image) const override;
|
||||
size_t read(stringstream& image) const override;
|
||||
size_t read(ByteBuffer& buffer, size_t size) const override;
|
||||
size_t read(stringstream& buffer) const override;
|
||||
size_t write(const ByteBuffer& buffer, size_t size) const override;
|
||||
size_t write(const stringstream& buffer) const override;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class Bankswitch
|
|||
_DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0,
|
||||
_F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA,
|
||||
_FA2, _FC, _FE, _MDM, _MVC, _SB, _TVBOY,
|
||||
_UA, _UASW, _WD, _WDSW, _X07,
|
||||
_UA, _UASW, _WD, _WDSW, _X07,
|
||||
#ifdef CUSTOM_ARM
|
||||
_CUSTOM,
|
||||
#endif
|
||||
|
|
|
@ -697,31 +697,31 @@ bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size)
|
|||
{
|
||||
// MVC version 0
|
||||
uInt8 sig[] = { 'M', 'V', 'C', 0 };
|
||||
int sigSize = sizeof(sig);
|
||||
int sigSize = sizeof(sig);
|
||||
return searchForBytes(image, std::min<size_t>(size, sigSize+1), sig, sigSize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t CartDetector::isProbablyMVC(std::istream &in, size_t maxSize)
|
||||
size_t CartDetector::isProbablyMVC(const FilesystemNode& rom)
|
||||
{
|
||||
const size_t frameSize = 2 * CartridgeMVC::MVC_FIELD_PAD_SIZE;
|
||||
bool found = false;
|
||||
constexpr size_t frameSize = 2 * CartridgeMVC::MVC_FIELD_PAD_SIZE;
|
||||
|
||||
// Returns size of field if stream is probably an MVC movie cartridge
|
||||
if(Bankswitch::typeFromExtension(rom) == Bankswitch::Type::_MVC)
|
||||
return frameSize;
|
||||
|
||||
if (maxSize >= frameSize)
|
||||
Serializer s(rom.getPath(), Serializer::Mode::ReadOnly);
|
||||
if(s)
|
||||
{
|
||||
auto pos = in.tellg();
|
||||
if(s.size() < frameSize)
|
||||
return 0;
|
||||
|
||||
ByteBuffer image = make_unique<uInt8[]>(frameSize);
|
||||
in.read(reinterpret_cast<char*>(image.get()), frameSize);
|
||||
uInt8 image[frameSize];
|
||||
s.getByteArray(image, frameSize);
|
||||
|
||||
in.seekg(pos);
|
||||
|
||||
found = isProbablyMVC(image, frameSize);
|
||||
uInt8 sig[] = { 'M', 'V', 'C', 0 }; // MVC version 0
|
||||
return searchForBytes(image, frameSize, sig, 4) ? frameSize : 0;
|
||||
}
|
||||
|
||||
return found ? frameSize : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define CARTRIDGE_DETECTOR_HXX
|
||||
|
||||
#include "Bankswitch.hxx"
|
||||
#include "FSNode.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
|
@ -40,12 +41,11 @@ class CartDetector
|
|||
*/
|
||||
static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
MVC cartridges are of arbitary large length
|
||||
MVC cartridges are of arbitary large length
|
||||
Returns size of frame if stream is probably an MVC movie cartridge
|
||||
*/
|
||||
static size_t isProbablyMVC(std::istream &in, size_t size);
|
||||
static size_t isProbablyMVC(const FilesystemNode& rom);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -1340,3 +1340,15 @@ bool CartridgeMVC::poke(uInt16 address, uInt8 value)
|
|||
{
|
||||
return myMovie->process(address);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeMVC::save(Serializer& out) const
|
||||
{
|
||||
return false; // TODO: implement this
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeMVC::load(Serializer& in)
|
||||
{
|
||||
return false; // TODO: implement this
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class CartridgeMVC : public Cartridge
|
|||
@param bsSize The size specified by the bankswitching scheme
|
||||
*/
|
||||
CartridgeMVC(const string& path, size_t size, const string& md5,
|
||||
const Settings& settings, size_t bsSize = 1_KB);
|
||||
const Settings& settings, size_t bsSize = 8_KB);
|
||||
~CartridgeMVC() override;
|
||||
|
||||
/**
|
||||
|
@ -113,7 +113,7 @@ class CartridgeMVC : public Cartridge
|
|||
@param out The Serializer object to use
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool save(Serializer& out) const override { return false; }
|
||||
bool save(Serializer& out) const override;
|
||||
|
||||
/**
|
||||
Load the current state of this cart from the given Serializer.
|
||||
|
@ -121,7 +121,7 @@ class CartridgeMVC : public Cartridge
|
|||
@param in The Serializer object to use
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool load(Serializer& in) override { return false; }
|
||||
bool load(Serializer& in) override;
|
||||
|
||||
private:
|
||||
// Currently not used:
|
||||
|
|
|
@ -333,7 +333,7 @@ bool FilesystemNode::rename(const string& newfile)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FilesystemNode::read(ByteBuffer& buffer) const
|
||||
size_t FilesystemNode::read(ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
size_t sizeRead = 0;
|
||||
|
||||
|
@ -342,7 +342,7 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const
|
|||
throw runtime_error("File not found/readable");
|
||||
|
||||
// First let the private subclass attempt to open the file
|
||||
if (_realNode && (sizeRead = _realNode->read(buffer)) > 0)
|
||||
if (_realNode && (sizeRead = _realNode->read(buffer, size)) > 0)
|
||||
return sizeRead;
|
||||
|
||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||
|
@ -355,12 +355,8 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const
|
|||
|
||||
if (sizeRead == 0)
|
||||
throw runtime_error("Zero-byte file");
|
||||
|
||||
// In the case of MVC (MovieCart) files, contents are streaming data
|
||||
// of arbitrary length, so just read first frame.
|
||||
size_t subSize = CartDetector::isProbablyMVC(in, sizeRead);
|
||||
if (subSize > 0)
|
||||
sizeRead = subSize;
|
||||
else if (size != 0)
|
||||
sizeRead = size;
|
||||
|
||||
buffer = make_unique<uInt8[]>(sizeRead);
|
||||
in.read(reinterpret_cast<char*>(buffer.get()), sizeRead);
|
||||
|
|
|
@ -244,12 +244,13 @@ class FilesystemNode
|
|||
* Read data (binary format) into the given buffer.
|
||||
*
|
||||
* @param buffer The buffer to contain the data (allocated in this method).
|
||||
* @param size The amount of data to read (0 means read all 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(ByteBuffer& buffer) const;
|
||||
size_t read(ByteBuffer& buffer, size_t size = 0) const;
|
||||
|
||||
/**
|
||||
* Read data (text format) into the given stream.
|
||||
|
@ -438,12 +439,13 @@ class AbstractFSNode
|
|||
* Read data (binary format) into the given buffer.
|
||||
*
|
||||
* @param buffer The buffer to contain the data (allocated in this method).
|
||||
* @param size The amount of data to read (0 means read all 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(ByteBuffer& buffer) const { return 0; }
|
||||
virtual size_t read(ByteBuffer& buffer, size_t size) const { return 0; }
|
||||
|
||||
/**
|
||||
* Read data (text format) into the given stream.
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "MD5.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartCreator.hxx"
|
||||
#include "CartDetector.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "TIASurface.hxx"
|
||||
#include "TIAConstants.hxx"
|
||||
|
@ -688,8 +689,16 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size
|
|||
// but also adds a properties entry if the one for the ROM doesn't
|
||||
// contain a valid name
|
||||
|
||||
// First check if this is a 'streaming' ROM (one where we only read
|
||||
// a portion of the file)
|
||||
size_t sizeToRead = CartDetector::isProbablyMVC(rom);
|
||||
|
||||
// Next check if rom is a valid size
|
||||
// TODO: We should check if ROM is < Cart::maxSize(), but only
|
||||
// if it's not a ZIP file (that size should be higher; still TBD)
|
||||
|
||||
ByteBuffer image;
|
||||
if((size = rom.read(image)) == 0)
|
||||
if((size = rom.read(image, sizeToRead)) == 0)
|
||||
return nullptr;
|
||||
|
||||
// If we get to this point, we know we have a valid file to open
|
||||
|
|
|
@ -94,11 +94,15 @@ void Serializer::rewind()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t Serializer::size() const
|
||||
size_t Serializer::size()
|
||||
{
|
||||
myStream->seekp(0, std::ios::end);
|
||||
std::streampos oldPos = myStream->tellp();
|
||||
|
||||
return myStream->tellp();
|
||||
myStream->seekp(0, std::ios::end);
|
||||
size_t s = myStream->tellp();
|
||||
setPosition(oldPos);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -70,9 +70,9 @@ class Serializer
|
|||
void rewind();
|
||||
|
||||
/**
|
||||
Returns the current write pointer location.
|
||||
Returns the current total size of the stream.
|
||||
*/
|
||||
size_t size() const;
|
||||
size_t size();
|
||||
|
||||
/**
|
||||
Reads a byte value (unsigned 8-bit) from the current input stream.
|
||||
|
|
Loading…
Reference in New Issue