(MovieCart) Limit reading of image data to single frame

when its likely an MVC file. This avoids reading of GB of data.
This commit is contained in:
Rob Bairos 2021-04-05 09:27:51 -04:00
parent a92a33b4da
commit 44e15ff86f
3 changed files with 40 additions and 2 deletions

View File

@ -19,6 +19,7 @@
#include "Logger.hxx" #include "Logger.hxx"
#include "CartDetector.hxx" #include "CartDetector.hxx"
#include "MovieCart/StreamReader.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size) Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size)
@ -694,11 +695,34 @@ bool CartDetector::isProbablyMDM(const ByteBuffer& image, size_t size)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size) bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size)
{ {
// MVC version 0, frame 0 // MVC version 0
uInt8 sig[] = { 'M', 'V', 'C', 0 }; uInt8 sig[] = { 'M', 'V', 'C', 0 };
return searchForBytes(image, std::min<size_t>(size, 5), sig, 4); 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)
{
const size_t frameSize = 2 * MVC_FIELD_PAD_SIZE;
bool found = false;
// Returns size of field if stream is probably an MVC movie cartridge
if (maxSize >= frameSize)
{
auto pos = in.tellg();
ByteBuffer image = make_unique<uInt8[]>(frameSize);
in.read(reinterpret_cast<char*>(image.get()), frameSize);
in.seekg(pos);
found = isProbablyMVC(image, frameSize);
}
return found ? frameSize : 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size) bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size)

View File

@ -40,6 +40,13 @@ class CartDetector
*/ */
static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size); static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size);
/**
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);
private: private:
/** /**
Search the image for the specified byte signature Search the image for the specified byte signature

View File

@ -17,6 +17,7 @@
#include "FSNodeFactory.hxx" #include "FSNodeFactory.hxx"
#include "FSNode.hxx" #include "FSNode.hxx"
#include "CartDetector.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode(const AbstractFSNodePtr& realNode) FilesystemNode::FilesystemNode(const AbstractFSNodePtr& realNode)
@ -355,6 +356,12 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const
if (sizeRead == 0) if (sizeRead == 0)
throw runtime_error("Zero-byte file"); 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;
buffer = make_unique<uInt8[]>(sizeRead); buffer = make_unique<uInt8[]>(sizeRead);
in.read(reinterpret_cast<char*>(buffer.get()), sizeRead); in.read(reinterpret_cast<char*>(buffer.get()), sizeRead);
} }