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:
Stephen Anthony 2021-05-03 20:35:11 -02:30
parent e5287ae125
commit bc877443c1
12 changed files with 64 additions and 41 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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:
/**

View File

@ -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
}

View File

@ -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:

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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.