aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorSven Hesse2012-06-28 22:54:05 +0200
committerSven Hesse2012-07-30 01:44:42 +0200
commit4fc3a88c5f0b053323aeaeac658dafb8e4606662 (patch)
tree0889eb2314c738f713ea2075d06a162bfed70797 /engines
parent83896dea3edc3bcfb1e414b61644c7ca266e1cce (diff)
downloadscummvm-rg350-4fc3a88c5f0b053323aeaeac658dafb8e4606662.tar.gz
scummvm-rg350-4fc3a88c5f0b053323aeaeac658dafb8e4606662.tar.bz2
scummvm-rg350-4fc3a88c5f0b053323aeaeac658dafb8e4606662.zip
GOB: Add support for different methods of handling Endianness
The Once Upon A Time games handle endianness different in ANI, DEC and RXY files than Geisha does. We need to support both approaches.
Diffstat (limited to 'engines')
-rw-r--r--engines/gob/anifile.cpp34
-rw-r--r--engines/gob/cmpfile.cpp9
-rw-r--r--engines/gob/decfile.cpp42
-rw-r--r--engines/gob/gob.cpp8
-rw-r--r--engines/gob/gob.h10
-rw-r--r--engines/gob/rxyfile.cpp19
-rw-r--r--engines/gob/rxyfile.h4
7 files changed, 88 insertions, 38 deletions
diff --git a/engines/gob/anifile.cpp b/engines/gob/anifile.cpp
index 2671fe0405..e6bf30f4d7 100644
--- a/engines/gob/anifile.cpp
+++ b/engines/gob/anifile.cpp
@@ -37,30 +37,38 @@ ANIFile::ANIFile(GobEngine *vm, const Common::String &fileName,
uint16 width, uint8 bpp) : _vm(vm),
_width(width), _bpp(bpp), _hasPadding(false) {
- Common::SeekableReadStream *ani = _vm->_dataIO->getFile(fileName);
- if (ani) {
- Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), false, DisposeAfterUse::YES);
+ bool bigEndian = false;
+ Common::String endianFileName = fileName;
- load(sub, fileName);
- return;
- }
+ if ((_vm->getEndiannessMethod() == kEndiannessMethodAltFile) &&
+ !_vm->_dataIO->hasFile(fileName)) {
+ // If the game has alternate big-endian files, look if one exist
+
+ Common::String alternateFileName = fileName;
+ alternateFileName.setChar('_', 0);
- // File doesn't exist, try to open the big-endian'd alternate file
- Common::String alternateFileName = fileName;
- alternateFileName.setChar('_', 0);
+ if (_vm->_dataIO->hasFile(alternateFileName)) {
+ bigEndian = true;
+ endianFileName = alternateFileName;
+ }
+ } else if ((_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE)))
+ // Game always little endian or it follows the system and it is big endian
+ bigEndian = true;
- ani = _vm->_dataIO->getFile(alternateFileName);
+ Common::SeekableReadStream *ani = _vm->_dataIO->getFile(endianFileName);
if (ani) {
- Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), true, DisposeAfterUse::YES);
+ Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), bigEndian, DisposeAfterUse::YES);
// The big endian version pads a few fields to even size
- _hasPadding = true;
+ _hasPadding = bigEndian;
load(sub, fileName);
return;
}
- warning("ANIFile::ANIFile(): No such file \"%s\"", fileName.c_str());
+ warning("ANIFile::ANIFile(): No such file \"%s\" (\"%s\")", endianFileName.c_str(), fileName.c_str());
}
ANIFile::~ANIFile() {
diff --git a/engines/gob/cmpfile.cpp b/engines/gob/cmpfile.cpp
index 7b21c4c835..1cd1375879 100644
--- a/engines/gob/cmpfile.cpp
+++ b/engines/gob/cmpfile.cpp
@@ -21,6 +21,7 @@
*/
#include "common/stream.h"
+#include "common/substream.h"
#include "common/str.h"
#include "gob/gob.h"
@@ -143,7 +144,13 @@ void CMPFile::loadCMP(Common::SeekableReadStream &cmp) {
}
void CMPFile::loadRXY(Common::SeekableReadStream &rxy) {
- _coordinates = new RXYFile(rxy);
+ bool bigEndian = (_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE));
+
+ Common::SeekableSubReadStreamEndian sub(&rxy, 0, rxy.size(), bigEndian, DisposeAfterUse::NO);
+
+ _coordinates = new RXYFile(sub);
for (uint i = 0; i < _coordinates->size(); i++) {
const RXYFile::Coordinates &c = (*_coordinates)[i];
diff --git a/engines/gob/decfile.cpp b/engines/gob/decfile.cpp
index fb67c52627..85b4c09ca3 100644
--- a/engines/gob/decfile.cpp
+++ b/engines/gob/decfile.cpp
@@ -38,30 +38,38 @@ DECFile::DECFile(GobEngine *vm, const Common::String &fileName,
uint16 width, uint16 height, uint8 bpp) : _vm(vm),
_width(width), _height(height), _bpp(bpp), _hasPadding(false), _backdrop(0) {
- Common::SeekableReadStream *dec = _vm->_dataIO->getFile(fileName);
- if (dec) {
- Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), false, DisposeAfterUse::YES);
-
- load(sub, fileName);
- return;
- }
-
- // File doesn't exist, try to open the big-endian'd alternate file
- Common::String alternateFileName = fileName;
- alternateFileName.setChar('_', 0);
-
- dec = _vm->_dataIO->getFile(alternateFileName);
- if (dec) {
- Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), true, DisposeAfterUse::YES);
+ bool bigEndian = false;
+ Common::String endianFileName = fileName;
+
+ if ((_vm->getEndiannessMethod() == kEndiannessMethodAltFile) &&
+ !_vm->_dataIO->hasFile(fileName)) {
+ // If the game has alternate big-endian files, look if one exist
+
+ Common::String alternateFileName = fileName;
+ alternateFileName.setChar('_', 0);
+
+ if (_vm->_dataIO->hasFile(alternateFileName)) {
+ bigEndian = true;
+ endianFileName = alternateFileName;
+ }
+ } else if ((_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE)))
+ // Game always little endian or it follows the system and it is big endian
+ bigEndian = true;
+
+ Common::SeekableReadStream *ani = _vm->_dataIO->getFile(endianFileName);
+ if (ani) {
+ Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), bigEndian, DisposeAfterUse::YES);
// The big endian version pads a few fields to even size
- _hasPadding = true;
+ _hasPadding = bigEndian;
load(sub, fileName);
return;
}
- warning("DECFile::DECFile(): No such file \"%s\"", fileName.c_str());
+ warning("DECFile::DECFile(): No such file \"%s\" (\"%s\")", endianFileName.c_str(), fileName.c_str());
}
DECFile::~DECFile() {
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 02aea63377..fcf98f0355 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -184,6 +184,10 @@ void GobEngine::validateVideoMode(int16 videoMode) {
error("Video mode 0x%X is not supported", videoMode);
}
+EndiannessMethod GobEngine::getEndiannessMethod() const {
+ return _endiannessMethod;
+}
+
Endianness GobEngine::getEndianness() const {
if ((getPlatform() == Common::kPlatformAmiga) ||
(getPlatform() == Common::kPlatformMacintosh) ||
@@ -403,6 +407,8 @@ Common::Error GobEngine::initGameParts() {
// just detect some devices some of which will be always there if the music is not disabled
_noMusic = MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB)) == MT_NULL ? true : false;
+ _endiannessMethod = kEndiannessMethodSystem;
+
_global = new Global(this);
_util = new Util(this);
_dataIO = new DataIO();
@@ -433,6 +439,8 @@ Common::Error GobEngine::initGameParts() {
_goblin = new Goblin_v1(this);
_scenery = new Scenery_v1(this);
_saveLoad = new SaveLoad_Geisha(this, _targetName.c_str());
+
+ _endiannessMethod = kEndiannessMethodAltFile;
break;
case kGameTypeFascination:
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 9b919098d6..df73404596 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -149,6 +149,13 @@ enum Features {
kFeaturesTrueColor = 1 << 7
};
+enum EndiannessMethod {
+ kEndiannessMethodLE, ///< Always little endian.
+ kEndiannessMethodBE, ///< Always big endian.
+ kEndiannessMethodSystem, ///< Follows system endianness.
+ kEndiannessMethodAltFile ///< Different endianness in alternate file.
+};
+
enum {
kDebugFuncOp = 1 << 0,
kDebugDrawOp = 1 << 1,
@@ -172,6 +179,8 @@ private:
int32 _features;
Common::Platform _platform;
+ EndiannessMethod _endiannessMethod;
+
uint32 _pauseStart;
// Engine APIs
@@ -232,6 +241,7 @@ public:
void pauseGame();
+ EndiannessMethod getEndiannessMethod() const;
Endianness getEndianness() const;
Common::Platform getPlatform() const;
GameType getGameType() const;
diff --git a/engines/gob/rxyfile.cpp b/engines/gob/rxyfile.cpp
index 9702dc8c7f..2ff8c121cd 100644
--- a/engines/gob/rxyfile.cpp
+++ b/engines/gob/rxyfile.cpp
@@ -21,12 +21,19 @@
*/
#include "common/stream.h"
+#include "common/substream.h"
#include "gob/rxyfile.h"
namespace Gob {
RXYFile::RXYFile(Common::SeekableReadStream &rxy) : _width(0), _height(0) {
+ Common::SeekableSubReadStreamEndian sub(&rxy, 0, rxy.size(), false, DisposeAfterUse::NO);
+
+ load(sub);
+}
+
+RXYFile::RXYFile(Common::SeekableSubReadStreamEndian &rxy) : _width(0), _height(0) {
load(rxy);
}
@@ -64,22 +71,22 @@ const RXYFile::Coordinates &RXYFile::operator[](uint i) const {
return _coords[i];
}
-void RXYFile::load(Common::SeekableReadStream &rxy) {
+void RXYFile::load(Common::SeekableSubReadStreamEndian &rxy) {
if (rxy.size() < 2)
return;
rxy.seek(0);
- _realCount = rxy.readUint16LE();
+ _realCount = rxy.readUint16();
uint16 count = (rxy.size() - 2) / 8;
_coords.resize(count);
for (CoordArray::iterator c = _coords.begin(); c != _coords.end(); ++c) {
- c->left = rxy.readUint16LE();
- c->right = rxy.readUint16LE();
- c->top = rxy.readUint16LE();
- c->bottom = rxy.readUint16LE();
+ c->left = rxy.readUint16();
+ c->right = rxy.readUint16();
+ c->top = rxy.readUint16();
+ c->bottom = rxy.readUint16();
if (c->left != 0xFFFF) {
_width = MAX<uint16>(_width , c->right + 1);
diff --git a/engines/gob/rxyfile.h b/engines/gob/rxyfile.h
index bc9600b5b0..4fd46c5e40 100644
--- a/engines/gob/rxyfile.h
+++ b/engines/gob/rxyfile.h
@@ -28,6 +28,7 @@
namespace Common {
class SeekableReadStream;
+ class SeekableSubReadStreamEndian;
}
namespace Gob {
@@ -46,6 +47,7 @@ public:
};
RXYFile(Common::SeekableReadStream &rxy);
+ RXYFile(Common::SeekableSubReadStreamEndian &rxy);
RXYFile(uint16 width, uint16 height);
~RXYFile();
@@ -71,7 +73,7 @@ private:
uint16 _height;
- void load(Common::SeekableReadStream &rxy);
+ void load(Common::SeekableSubReadStreamEndian &rxy);
};
} // End of namespace Gob