ALL: synced with scummvm

This commit is contained in:
Pawel Kolodziejski 2013-07-13 14:30:29 +02:00
parent f78a3c0171
commit c68193e3a4
8 changed files with 179 additions and 83 deletions

1
.gitignore vendored
View file

@ -57,6 +57,7 @@ project.xcworkspace
/dists/msvc*/*.SAV /dists/msvc*/*.SAV
/dists/msvc*/*.dat /dists/msvc*/*.dat
/dists/msvc*/*.dll /dists/msvc*/*.dll
/dists/msvc*/test_runner.cpp
/doc/*.aux /doc/*.aux
/doc/*.dvi /doc/*.dvi

View file

@ -102,18 +102,18 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const {
return computeStreamMD5AsString(resForkStream, MIN<uint32>(length, _resForkSize)); return computeStreamMD5AsString(resForkStream, MIN<uint32>(length, _resForkSize));
} }
bool MacResManager::open(String filename) { bool MacResManager::open(const String &fileName) {
close(); close();
#ifdef MACOSX #ifdef MACOSX
// Check the actual fork on a Mac computer // Check the actual fork on a Mac computer
String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc"; String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath); FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) { if (resFsNode.exists()) {
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
@ -123,38 +123,39 @@ bool MacResManager::open(String filename) {
File *file = new File(); File *file = new File();
// First, let's try to see if the Mac converted name exists // Prefer standalone files first, starting with raw forks
if (file->open(constructAppleDoubleName(filename)) && loadFromAppleDouble(*file)) { if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
file->close(); file->close();
// Check .bin too // Then try for AppleDouble using Apple's naming
if (file->open(filename + ".bin") && loadFromMacBinary(*file)) { if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
file->close(); file->close();
// Maybe we have a dumped fork? // Check .bin for MacBinary next
if (file->open(filename + ".rsrc") && loadFromRawFork(*file)) { if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
file->close(); file->close();
// Fine, what about just the data fork? // As a last resort, see if just the data fork exists
if (file->open(filename)) { if (file->open(fileName)) {
_baseFileName = filename; _baseFileName = fileName;
// FIXME: Is this really needed?
if (isMacBinary(*file)) { if (isMacBinary(*file)) {
file->seek(0, SEEK_SET); file->seek(0);
if (loadFromMacBinary(*file)) if (loadFromMacBinary(*file))
return true; return true;
} }
file->seek(0, SEEK_SET); file->seek(0);
_stream = file; _stream = file;
return true; return true;
} }
@ -165,18 +166,18 @@ bool MacResManager::open(String filename) {
return false; return false;
} }
bool MacResManager::open(FSNode path, String filename) { bool MacResManager::open(const FSNode &path, const String &fileName) {
close(); close();
#ifdef MACOSX #ifdef MACOSX
// Check the actual fork on a Mac computer // Check the actual fork on a Mac computer
String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc"; String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath); FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) { if (resFsNode.exists()) {
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
@ -184,52 +185,53 @@ bool MacResManager::open(FSNode path, String filename) {
} }
#endif #endif
// First, let's try to see if the Mac converted name exists // Prefer standalone files first, starting with raw forks
FSNode fsNode = path.getChild(constructAppleDoubleName(filename)); FSNode fsNode = path.getChild(fileName + ".rsrc");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromAppleDouble(*stream)) {
_baseFileName = filename;
return true;
}
delete stream;
}
// Check .bin too
fsNode = path.getChild(filename + ".bin");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromMacBinary(*stream)) {
_baseFileName = filename;
return true;
}
delete stream;
}
// Maybe we have a dumped fork?
fsNode = path.getChild(filename + ".rsrc");
if (fsNode.exists() && !fsNode.isDirectory()) { if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream(); SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromRawFork(*stream)) { if (loadFromRawFork(*stream)) {
_baseFileName = filename; _baseFileName = fileName;
return true; return true;
} }
delete stream; delete stream;
} }
// Fine, what about just the data fork? // Then try for AppleDouble using Apple's naming
fsNode = path.getChild(filename); fsNode = path.getChild(constructAppleDoubleName(fileName));
if (fsNode.exists() && !fsNode.isDirectory()) { if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream(); SeekableReadStream *stream = fsNode.createReadStream();
_baseFileName = filename; if (loadFromAppleDouble(*stream)) {
_baseFileName = fileName;
return true;
}
delete stream;
}
// Check .bin for MacBinary next
fsNode = path.getChild(fileName + ".bin");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromMacBinary(*stream)) {
_baseFileName = fileName;
return true;
}
delete stream;
}
// As a last resort, see if just the data fork exists
fsNode = path.getChild(fileName);
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
_baseFileName = fileName;
// FIXME: Is this really needed?
if (isMacBinary(*stream)) { if (isMacBinary(*stream)) {
stream->seek(0, SEEK_SET); stream->seek(0);
if (loadFromMacBinary(*stream)) if (loadFromMacBinary(*stream))
return true; return true;
} }
stream->seek(0, SEEK_SET); stream->seek(0);
_stream = stream; _stream = stream;
return true; return true;
} }
@ -238,22 +240,22 @@ bool MacResManager::open(FSNode path, String filename) {
return false; return false;
} }
bool MacResManager::exists(const String &filename) { bool MacResManager::exists(const String &fileName) {
// Try the file name by itself // Try the file name by itself
if (Common::File::exists(filename)) if (File::exists(fileName))
return true; return true;
// Try the .rsrc extension // Try the .rsrc extension
if (Common::File::exists(filename + ".rsrc")) if (File::exists(fileName + ".rsrc"))
return true; return true;
// Check if we have a MacBinary file // Check if we have a MacBinary file
Common::File tempFile; File tempFile;
if (tempFile.open(filename + ".bin") && isMacBinary(tempFile)) if (tempFile.open(fileName + ".bin") && isMacBinary(tempFile))
return true; return true;
// Check if we have an AppleDouble file // Check if we have an AppleDouble file
if (tempFile.open(constructAppleDoubleName(filename)) && tempFile.readUint32BE() == 0x00051607) if (tempFile.open(constructAppleDoubleName(fileName)) && tempFile.readUint32BE() == 0x00051607)
return true; return true;
return false; return false;
@ -480,10 +482,10 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) {
return _stream->readStream(len); return _stream->readStream(len);
} }
SeekableReadStream *MacResManager::getResource(const String &filename) { SeekableReadStream *MacResManager::getResource(const String &fileName) {
for (uint32 i = 0; i < _resMap.numTypes; i++) { for (uint32 i = 0; i < _resMap.numTypes; i++) {
for (uint32 j = 0; j < _resTypes[i].items; j++) { for (uint32 j = 0; j < _resTypes[i].items; j++) {
if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) { if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) {
_stream->seek(_dataOffset + _resLists[i][j].dataOffset); _stream->seek(_dataOffset + _resLists[i][j].dataOffset);
uint32 len = _stream->readUint32BE(); uint32 len = _stream->readUint32BE();
@ -499,13 +501,13 @@ SeekableReadStream *MacResManager::getResource(const String &filename) {
return 0; return 0;
} }
SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &filename) { SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &fileName) {
for (uint32 i = 0; i < _resMap.numTypes; i++) { for (uint32 i = 0; i < _resMap.numTypes; i++) {
if (_resTypes[i].id != typeID) if (_resTypes[i].id != typeID)
continue; continue;
for (uint32 j = 0; j < _resTypes[i].items; j++) { for (uint32 j = 0; j < _resTypes[i].items; j++) {
if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) { if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) {
_stream->seek(_dataOffset + _resLists[i][j].dataOffset); _stream->seek(_dataOffset + _resLists[i][j].dataOffset);
uint32 len = _stream->readUint32BE(); uint32 len = _stream->readUint32BE();
@ -574,7 +576,7 @@ void MacResManager::readMap() {
} }
} }
Common::String MacResManager::constructAppleDoubleName(Common::String name) { String MacResManager::constructAppleDoubleName(String name) {
// Insert "._" before the last portion of a path name // Insert "._" before the last portion of a path name
for (int i = name.size() - 1; i >= 0; i--) { for (int i = name.size() - 1; i >= 0; i--) {
if (i == 0) { if (i == 0) {

View file

@ -54,27 +54,32 @@ public:
/** /**
* Open a Mac data/resource fork pair. * Open a Mac data/resource fork pair.
*
* This uses SearchMan to find the data/resource forks. This should only be used
* from inside an engine.
*
* @param filename The base file name of the file * @param filename The base file name of the file
* @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats.
* @return True on success * @return True on success
*/ */
bool open(String filename); bool open(const String &fileName);
/** /**
* Open a Mac data/resource fork pair. * Open a Mac data/resource fork pair.
*
* @param path The path that holds the forks * @param path The path that holds the forks
* @param filename The base file name of the file * @param filename The base file name of the file
* @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats.
* @return True on success * @return True on success
*/ */
bool open(FSNode path, String filename); bool open(const FSNode &path, const String &fileName);
/** /**
* See if a Mac data/resource fork pair exists. * See if a Mac data/resource fork pair exists.
* @param filename The base file name of the file * @param filename The base file name of the file
* @return True if either a data fork or resource fork with this name exists * @return True if either a data fork or resource fork with this name exists
*/ */
static bool exists(const String &filename); static bool exists(const String &fileName);
/** /**
* Close the Mac data/resource fork pair. * Close the Mac data/resource fork pair.
@ -93,12 +98,6 @@ public:
*/ */
bool hasResFork() const; bool hasResFork() const;
/**
* Check if the given stream is in the MacBinary format.
* @param stream The stream we're checking
*/
static bool isMacBinary(SeekableReadStream &stream);
/** /**
* Read resource from the MacBinary file * Read resource from the MacBinary file
* @param typeID FourCC of the type * @param typeID FourCC of the type
@ -176,7 +175,13 @@ private:
bool loadFromMacBinary(SeekableReadStream &stream); bool loadFromMacBinary(SeekableReadStream &stream);
bool loadFromAppleDouble(SeekableReadStream &stream); bool loadFromAppleDouble(SeekableReadStream &stream);
static Common::String constructAppleDoubleName(Common::String name); static String constructAppleDoubleName(String name);
/**
* Check if the given stream is in the MacBinary format.
* @param stream The stream we're checking
*/
static bool isMacBinary(SeekableReadStream &stream);
enum { enum {
kResForkNone = 0, kResForkNone = 0,

15
configure vendored
View file

@ -2373,7 +2373,8 @@ if test -n "$_host"; then
DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER" DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER"
DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE" DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE"
DEFINES="$DEFINES -DDISABLE_COMMAND_LINE" DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
if test "$_release_build" = yes; then # Enable serial debugging output only when --enable-debug is passed
if test "$_release_build" = yes -o "$_debug_build" != yes; then
DEFINES="$DEFINES -DNOSERIAL" DEFINES="$DEFINES -DNOSERIAL"
fi fi
_optimization_level=-O3 _optimization_level=-O3
@ -2708,7 +2709,8 @@ case $_backend in
LDFLAGS="$LDFLAGS -nostartfiles" LDFLAGS="$LDFLAGS -nostartfiles"
LDFLAGS="$LDFLAGS "'$(ronindir)/lib/crt0.o' LDFLAGS="$LDFLAGS "'$(ronindir)/lib/crt0.o'
LDFLAGS="$LDFLAGS "'-L$(ronindir)/lib' LDFLAGS="$LDFLAGS "'-L$(ronindir)/lib'
if test "$_release_build" = yes; then # Enable serial debugging output only when --enable-debug is passed
if test "$_release_build" = yes -o "$_debug_build" != yes; then
LIBS="$LIBS -lronin-noserial -lm" LIBS="$LIBS -lronin-noserial -lm"
else else
LIBS="$LIBS -lronin -lm" LIBS="$LIBS -lronin -lm"
@ -3993,7 +3995,14 @@ fi
test "x$prefix" = xNONE && prefix=/usr/local test "x$prefix" = xNONE && prefix=/usr/local
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFINES="$DEFINES -DDATA_PATH=\\\"$datadir\\\"" case $_host_os in
mingw*)
# Windows stores all the external data files in executable file.
;;
*)
DEFINES="$DEFINES -DDATA_PATH=\\\"$datadir\\\""
;;
esac
case $_backend in case $_backend in
openpandora) openpandora)

View file

@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools if "%~1"=="/TOOLS" goto tools
if "%~1"=="/tests" goto tests
if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help if "%~1"=="/help" goto command_help
@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 10 create_project ..\.. --tools --msvc --msvc-version 10
goto done goto done
:tests
echo.
echo Creating tests project files
echo.
create_project ..\.. --tests --msvc --msvc-version 10
goto done
:clean_check :clean_check
echo. echo.
set cleananswer=N set cleananswer=N
@ -86,8 +95,9 @@ echo Removing all project files
del /Q *.vcxproj* > NUL 2>&1 del /Q *.vcxproj* > NUL 2>&1
del /Q *.props > NUL 2>&1 del /Q *.props > NUL 2>&1
del /Q *.sln* > NUL 2>&1 del /Q *.sln* > NUL 2>&1
del /Q residual* > NUL 2>&1 del /Q residualvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1 del /Q devtools* > NUL 2>&1
del /Q test_runner.cpp > NUL 2>&1
goto done goto done
:done :done

View file

@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools if "%~1"=="/TOOLS" goto tools
if "%~1"=="/tests" goto tests
if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help if "%~1"=="/help" goto command_help
@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 8 create_project ..\.. --tools --msvc --msvc-version 8
goto done goto done
:tests
echo.
echo Creating tests project files
echo.
create_project ..\.. --tests --msvc --msvc-version 8
goto done
:clean_check :clean_check
echo. echo.
set cleananswer=N set cleananswer=N
@ -86,8 +95,9 @@ echo Removing all project files
del /Q *.vcproj* > NUL 2>&1 del /Q *.vcproj* > NUL 2>&1
del /Q *.vsprops > NUL 2>&1 del /Q *.vsprops > NUL 2>&1
del /Q *.sln* > NUL 2>&1 del /Q *.sln* > NUL 2>&1
del /Q residual* > NUL 2>&1 del /Q residualvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1 del /Q devtools* > NUL 2>&1
del /Q test_runner.cpp
goto done goto done
:done :done

View file

@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools if "%~1"=="/TOOLS" goto tools
if "%~1"=="/tests" goto tests
if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help if "%~1"=="/help" goto command_help
@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 9 create_project ..\.. --tools --msvc --msvc-version 9
goto done goto done
:tests
echo.
echo Creating tests project files
echo.
create_project ..\.. --tests --msvc --msvc-version 9
goto done
:clean_check :clean_check
echo. echo.
set cleananswer=N set cleananswer=N
@ -88,6 +97,7 @@ del /Q *.vsprops > NUL 2>&1
del /Q *.sln* > NUL 2>&1 del /Q *.sln* > NUL 2>&1
del /Q residualvm* > NUL 2>&1 del /Q residualvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1 del /Q devtools* > NUL 2>&1
del /Q test_runner.cpp
goto done goto done
:done :done

View file

@ -43,7 +43,16 @@ struct ThumbnailHeader {
#define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4)) #define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4))
bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) { enum HeaderState {
/// There is no header present
kHeaderNone,
/// The header present only has reliable values for version and size
kHeaderUnsupported,
/// The header is present and the version is supported
kHeaderPresent
};
HeaderState loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
header.type = in.readUint32BE(); header.type = in.readUint32BE();
// We also accept the bad 'BMHT' header here, for the sake of compatibility // We also accept the bad 'BMHT' header here, for the sake of compatibility
// with some older savegames which were written incorrectly due to a bug in // with some older savegames which were written incorrectly due to a bug in
@ -51,16 +60,28 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) { if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) {
if (outputWarnings) if (outputWarnings)
warning("couldn't find thumbnail header type"); warning("couldn't find thumbnail header type");
return false; return kHeaderNone;
} }
header.size = in.readUint32BE(); header.size = in.readUint32BE();
header.version = in.readByte(); header.version = in.readByte();
// Do a check whether any read errors had occured. If so we cannot use the
// values obtained for size and version because they might be bad.
if (in.err() || in.eos()) {
// TODO: We fake that there is no header. This is actually not quite
// correct since we found the start of the header and then things
// started to break. Right no we leave detection of this to the client.
// Since this case is caused by broken files, the client code should
// catch it anyway... If there is a nicer solution here, we should
// implement it.
return kHeaderNone;
}
if (header.version > THMB_VERSION) { if (header.version > THMB_VERSION) {
if (outputWarnings) if (outputWarnings)
warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION); warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION);
return false; return kHeaderUnsupported;
} }
header.width = in.readUint16BE(); header.width = in.readUint16BE();
@ -82,7 +103,15 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
header.format = createPixelFormat<565>(); header.format = createPixelFormat<565>();
} }
return true; if (in.err() || in.eos()) {
// When we reached this point we know that at least the size and
// version field was loaded successfully, thus we tell this header
// is not supported and silently hope that the client code is
// prepared to handle read errors.
return kHeaderUnsupported;
} else {
return kHeaderPresent;
}
} }
} // end of anonymous namespace } // end of anonymous namespace
@ -90,7 +119,12 @@ bool checkThumbnailHeader(Common::SeekableReadStream &in) {
uint32 position = in.pos(); uint32 position = in.pos();
ThumbnailHeader header; ThumbnailHeader header;
bool hasHeader = loadHeader(in, header, false); // TODO: It is not clear whether this is the best semantics. Now
// checkThumbnailHeader will return true even when the thumbnail header
// found is actually not usable. However, most engines seem to use this
// to detect the presence of any header and if there is none it wont even
// try to skip it. Thus, this looks like the best solution for now...
bool hasHeader = (loadHeader(in, header, false) != kHeaderNone);
in.seek(position, SEEK_SET); in.seek(position, SEEK_SET);
@ -101,7 +135,9 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
uint32 position = in.pos(); uint32 position = in.pos();
ThumbnailHeader header; ThumbnailHeader header;
if (!loadHeader(in, header, false)) { // We can skip unsupported and supported headers. So we only seek back
// to the old position in case there is no header at all.
if (loadHeader(in, header, false) == kHeaderNone) {
in.seek(position, SEEK_SET); in.seek(position, SEEK_SET);
return false; return false;
} }
@ -111,10 +147,23 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
} }
Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) { Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
const uint32 position = in.pos();
ThumbnailHeader header; ThumbnailHeader header;
HeaderState headerState = loadHeader(in, header, true);
if (!loadHeader(in, header, true)) // Try to handle unsupported/broken headers gracefully. If there is no
// header at all, we seek back and return at this point. If there is an
// unsupported/broken header, we skip the actual data and return. The
// downside is that we might reset the end of stream flag with this and
// the client code would not be able to notice a read past the end of the
// stream at this point then.
if (headerState == kHeaderNone) {
in.seek(position, SEEK_SET);
return 0; return 0;
} else if (headerState == kHeaderUnsupported) {
in.seek(header.size - (in.pos() - position), SEEK_CUR);
return 0;
}
if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) { if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) {
warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel); warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel);