Rewrote the remaining parts of the ResourceManager class to work with file streams, thus removing the SCI_detection hack in the fallback detector
svn-id: r49438
This commit is contained in:
parent
b9065aa2d2
commit
e9f35fbf4c
3 changed files with 88 additions and 66 deletions
|
@ -373,19 +373,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
filename.toLowercase();
|
filename.toLowercase();
|
||||||
|
|
||||||
if (filename.contains("resource.map") || filename.contains("resmap.00") || filename.contains("Data1")) {
|
if (filename.contains("resource.map") || filename.contains("resmap.00") || filename.contains("Data1")) {
|
||||||
// HACK: resource.map is located in the same directory as the other resource files,
|
|
||||||
// therefore add the directory here, so that the game files can be opened later on
|
|
||||||
// We now add the parent directory temporary to our SearchMan so the engine code
|
|
||||||
// used in the detection can access all files via Common::File without any problems.
|
|
||||||
// In all branches returning from this function, we need to have a call to
|
|
||||||
// SearchMan.remove to remove it from the default directory pool again.
|
|
||||||
//
|
|
||||||
// A proper solution to remove this hack would be to have the code, which is needed
|
|
||||||
// for detection, to operate on Stream objects, so they can be easily called from
|
|
||||||
// the detection code. This might be easily to achieve through refactoring the
|
|
||||||
// code needed for detection.
|
|
||||||
assert(!SearchMan.hasArchive("SCI_detection"));
|
|
||||||
SearchMan.addDirectory("SCI_detection", file->getParent());
|
|
||||||
foundResMap = true;
|
foundResMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +416,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
|
|
||||||
// If these files aren't found, it can't be SCI
|
// If these files aren't found, it can't be SCI
|
||||||
if (!foundResMap && !foundRes000) {
|
if (!foundResMap && !foundRes000) {
|
||||||
SearchMan.remove("SCI_detection");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,11 +423,10 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
ViewType gameViews = resMan->getViewType();
|
ViewType gameViews = resMan->getViewType();
|
||||||
|
|
||||||
// Have we identified the game views? If not, stop here
|
// Have we identified the game views? If not, stop here
|
||||||
|
// Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
|
||||||
|
// but doesnt share sci format at all, if we dont return 0 here we will detect this game as SCI
|
||||||
if (gameViews == kViewUnknown) {
|
if (gameViews == kViewUnknown) {
|
||||||
SearchMan.remove("SCI_detection");
|
|
||||||
delete resMan;
|
delete resMan;
|
||||||
// Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
|
|
||||||
// but doesnt share sci format at all, if we dont return 0 here we will detect this game as SCI
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +434,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
// Is SCI32 compiled in? If not, and this is a SCI32 game,
|
// Is SCI32 compiled in? If not, and this is a SCI32 game,
|
||||||
// stop here
|
// stop here
|
||||||
if (getSciVersion() >= SCI_VERSION_2) {
|
if (getSciVersion() >= SCI_VERSION_2) {
|
||||||
SearchMan.remove("SCI_detection");
|
|
||||||
delete resMan;
|
delete resMan;
|
||||||
return (const ADGameDescription *)&s_fallbackDesc;
|
return (const ADGameDescription *)&s_fallbackDesc;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +452,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
|
|
||||||
// If we don't have a game id, the game is not SCI
|
// If we don't have a game id, the game is not SCI
|
||||||
if (sierraGameId.empty()) {
|
if (sierraGameId.empty()) {
|
||||||
SearchMan.remove("SCI_detection");
|
|
||||||
delete resMan;
|
delete resMan;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -522,8 +505,6 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
if (s_fallbackDesc.flags & ADGF_DEMO)
|
if (s_fallbackDesc.flags & ADGF_DEMO)
|
||||||
s_fallbackDesc.extra = "demo";
|
s_fallbackDesc.extra = "demo";
|
||||||
|
|
||||||
SearchMan.remove("SCI_detection");
|
|
||||||
|
|
||||||
return (const ADGameDescription *)&s_fallbackDesc;
|
return (const ADGameDescription *)&s_fallbackDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,6 +371,8 @@ void ResourceManager::loadResource(Resource *res) {
|
||||||
case kSourceWave:
|
case kSourceWave:
|
||||||
fileStream->seek(res->_fileOffset, SEEK_SET);
|
fileStream->seek(res->_fileOffset, SEEK_SET);
|
||||||
loadFromWaveFile(res, fileStream);
|
loadFromWaveFile(res, fileStream);
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case kSourceAudioVolume:
|
case kSourceAudioVolume:
|
||||||
|
@ -408,6 +410,8 @@ void ResourceManager::loadResource(Resource *res) {
|
||||||
case kResourceTypeAudio36:
|
case kResourceTypeAudio36:
|
||||||
// Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
|
// Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
|
||||||
loadFromAudioVolumeSCI1(res, fileStream);
|
loadFromAudioVolumeSCI1(res, fileStream);
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -420,11 +424,18 @@ void ResourceManager::loadResource(Resource *res) {
|
||||||
loadFromAudioVolumeSCI1(res, fileStream);
|
loadFromAudioVolumeSCI1(res, fileStream);
|
||||||
else
|
else
|
||||||
loadFromAudioVolumeSCI11(res, fileStream);
|
loadFromAudioVolumeSCI11(res, fileStream);
|
||||||
|
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fileStream->seek(res->_fileOffset, SEEK_SET);
|
fileStream->seek(res->_fileOffset, SEEK_SET);
|
||||||
int error = decompress(res, fileStream);
|
int error = decompress(res, fileStream);
|
||||||
|
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
warning("Error %d occured while reading %s from resource file: %s",
|
warning("Error %d occured while reading %s from resource file: %s",
|
||||||
error, res->_id.toString().c_str(), sci_error_types[error]);
|
error, res->_id.toString().c_str(), sci_error_types[error]);
|
||||||
|
@ -437,19 +448,6 @@ Resource *ResourceManager::testResource(ResourceId id) {
|
||||||
return _resMap.getVal(id, NULL);
|
return _resMap.getVal(id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sci0_get_compression_method(Common::ReadStream &stream) {
|
|
||||||
uint16 compressionMethod;
|
|
||||||
|
|
||||||
stream.readUint16LE();
|
|
||||||
stream.readUint16LE();
|
|
||||||
stream.readUint16LE();
|
|
||||||
compressionMethod = stream.readUint16LE();
|
|
||||||
if (stream.err())
|
|
||||||
return SCI_ERROR_IO_ERROR;
|
|
||||||
|
|
||||||
return compressionMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ResourceManager::addAppropriateSources() {
|
int ResourceManager::addAppropriateSources() {
|
||||||
Common::ArchiveMemberList files;
|
Common::ArchiveMemberList files;
|
||||||
|
|
||||||
|
@ -1205,25 +1203,34 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
|
int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
|
||||||
Common::File file;
|
Common::SeekableReadStream *fileStream = 0;
|
||||||
Resource *res;
|
Resource *res;
|
||||||
ResourceType type;
|
ResourceType type;
|
||||||
uint16 number, id;
|
uint16 number, id;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
|
|
||||||
if (!file.open(map->location_name))
|
if (map->resourceFile) {
|
||||||
return SCI_ERROR_RESMAP_NOT_FOUND;
|
fileStream = map->resourceFile->createReadStream();
|
||||||
|
if (!fileStream)
|
||||||
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
Common::File *file = new Common::File();
|
||||||
|
if (!file->open(map->location_name))
|
||||||
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
|
fileStream = file;
|
||||||
|
}
|
||||||
|
|
||||||
file.seek(0, SEEK_SET);
|
fileStream->seek(0, SEEK_SET);
|
||||||
|
|
||||||
byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
|
byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
|
||||||
byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
|
byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
id = file.readUint16LE();
|
id = fileStream->readUint16LE();
|
||||||
offset = file.readUint32LE();
|
offset = fileStream->readUint32LE();
|
||||||
|
|
||||||
if (file.eos() || file.err()) {
|
if (fileStream->eos() || fileStream->err()) {
|
||||||
|
delete fileStream;
|
||||||
warning("Error while reading %s", map->location_name.c_str());
|
warning("Error while reading %s", map->location_name.c_str());
|
||||||
return SCI_ERROR_RESMAP_NOT_FOUND;
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -1252,15 +1259,26 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
|
||||||
res->_id = resId;
|
res->_id = resId;
|
||||||
_resMap.setVal(resId, res);
|
_resMap.setVal(resId, res);
|
||||||
}
|
}
|
||||||
} while (!file.eos());
|
} while (!fileStream->eos());
|
||||||
|
|
||||||
|
delete fileStream;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
||||||
Common::File file;
|
Common::SeekableReadStream *fileStream = 0;
|
||||||
Resource *res;
|
Resource *res;
|
||||||
if (!file.open(map->location_name))
|
|
||||||
return SCI_ERROR_RESMAP_NOT_FOUND;
|
if (map->resourceFile) {
|
||||||
|
fileStream = map->resourceFile->createReadStream();
|
||||||
|
if (!fileStream)
|
||||||
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
Common::File *file = new Common::File();
|
||||||
|
if (!file->open(map->location_name))
|
||||||
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
|
fileStream = file;
|
||||||
|
}
|
||||||
|
|
||||||
resource_index_t resMap[32];
|
resource_index_t resMap[32];
|
||||||
memset(resMap, 0, sizeof(resource_index_t) * 32);
|
memset(resMap, 0, sizeof(resource_index_t) * 32);
|
||||||
|
@ -1271,8 +1289,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
||||||
// Read resource type and offsets to resource offsets block from .MAP file
|
// Read resource type and offsets to resource offsets block from .MAP file
|
||||||
// The last entry has type=0xFF (0x1F) and offset equals to map file length
|
// The last entry has type=0xFF (0x1F) and offset equals to map file length
|
||||||
do {
|
do {
|
||||||
type = file.readByte() & 0x1F;
|
type = fileStream->readByte() & 0x1F;
|
||||||
resMap[type].wOffset = file.readUint16LE();
|
resMap[type].wOffset = fileStream->readUint16LE();
|
||||||
resMap[prevtype].wSize = (resMap[type].wOffset
|
resMap[prevtype].wSize = (resMap[type].wOffset
|
||||||
- resMap[prevtype].wOffset) / nEntrySize;
|
- resMap[prevtype].wOffset) / nEntrySize;
|
||||||
prevtype = type;
|
prevtype = type;
|
||||||
|
@ -1283,18 +1301,18 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
||||||
for (type = 0; type < 32; type++) {
|
for (type = 0; type < 32; type++) {
|
||||||
if (resMap[type].wOffset == 0) // this resource does not exist in map
|
if (resMap[type].wOffset == 0) // this resource does not exist in map
|
||||||
continue;
|
continue;
|
||||||
file.seek(resMap[type].wOffset);
|
fileStream->seek(resMap[type].wOffset);
|
||||||
for (int i = 0; i < resMap[type].wSize; i++) {
|
for (int i = 0; i < resMap[type].wSize; i++) {
|
||||||
uint16 number = file.readUint16LE();
|
uint16 number = fileStream->readUint16LE();
|
||||||
int volume_nr = 0;
|
int volume_nr = 0;
|
||||||
if (_mapVersion == kResVersionSci11) {
|
if (_mapVersion == kResVersionSci11) {
|
||||||
// offset stored in 3 bytes
|
// offset stored in 3 bytes
|
||||||
off = file.readUint16LE();
|
off = fileStream->readUint16LE();
|
||||||
off |= file.readByte() << 16;
|
off |= fileStream->readByte() << 16;
|
||||||
off <<= 1;
|
off <<= 1;
|
||||||
} else {
|
} else {
|
||||||
// offset/volume stored in 4 bytes
|
// offset/volume stored in 4 bytes
|
||||||
off = file.readUint32LE();
|
off = fileStream->readUint32LE();
|
||||||
if (_mapVersion < kResVersionSci11) {
|
if (_mapVersion < kResVersionSci11) {
|
||||||
volume_nr = off >> 28; // most significant 4 bits
|
volume_nr = off >> 28; // most significant 4 bits
|
||||||
off &= 0x0FFFFFFF; // least significant 28 bits
|
off &= 0x0FFFFFFF; // least significant 28 bits
|
||||||
|
@ -1302,7 +1320,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
||||||
// in SCI32 it's a plain offset
|
// in SCI32 it's a plain offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (file.eos() || file.err()) {
|
if (fileStream->eos() || fileStream->err()) {
|
||||||
|
delete fileStream;
|
||||||
warning("Error while reading %s", map->location_name.c_str());
|
warning("Error while reading %s", map->location_name.c_str());
|
||||||
return SCI_ERROR_RESMAP_NOT_FOUND;
|
return SCI_ERROR_RESMAP_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -1322,6 +1341,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete fileStream;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1574,7 +1595,7 @@ ResourceCompression ResourceManager::getViewCompression() {
|
||||||
|
|
||||||
// Test 10 views to see if any are compressed
|
// Test 10 views to see if any are compressed
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
Common::File *file;
|
Common::SeekableReadStream *fileStream = 0;
|
||||||
Resource *res = testResource(ResourceId(kResourceTypeView, i));
|
Resource *res = testResource(ResourceId(kResourceTypeView, i));
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
|
@ -1583,16 +1604,26 @@ ResourceCompression ResourceManager::getViewCompression() {
|
||||||
if (res->_source->source_type != kSourceVolume)
|
if (res->_source->source_type != kSourceVolume)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
file = getVolumeFile(res->_source->location_name.c_str());
|
if (res->_source->resourceFile)
|
||||||
if (!file)
|
fileStream = res->_source->resourceFile->createReadStream();
|
||||||
|
else
|
||||||
|
fileStream = getVolumeFile(res->_source->location_name.c_str());
|
||||||
|
|
||||||
|
if (!fileStream)
|
||||||
continue;
|
continue;
|
||||||
file->seek(res->_fileOffset, SEEK_SET);
|
fileStream->seek(res->_fileOffset, SEEK_SET);
|
||||||
|
|
||||||
uint32 szPacked;
|
uint32 szPacked;
|
||||||
ResourceCompression compression;
|
ResourceCompression compression;
|
||||||
|
|
||||||
if (readResourceInfo(res, file, szPacked, compression))
|
if (readResourceInfo(res, fileStream, szPacked, compression)) {
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res->_source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
|
|
||||||
if (compression != kCompNone)
|
if (compression != kCompNone)
|
||||||
return compression;
|
return compression;
|
||||||
|
|
|
@ -33,13 +33,20 @@
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
|
void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
|
||||||
Common::File *file = getVolumeFile(source->location_name.c_str());
|
Common::SeekableReadStream *fileStream;
|
||||||
if (!file) {
|
|
||||||
|
if (source->resourceFile)
|
||||||
|
fileStream = source->resourceFile->createReadStream();
|
||||||
|
else
|
||||||
|
fileStream = getVolumeFile(source->location_name.c_str());
|
||||||
|
|
||||||
|
if (!fileStream) {
|
||||||
warning("Failed to open %s", source->location_name.c_str());
|
warning("Failed to open %s", source->location_name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->seek(0, SEEK_SET);
|
|
||||||
uint32 compressionType = file->readUint32BE();
|
fileStream->seek(0, SEEK_SET);
|
||||||
|
uint32 compressionType = fileStream->readUint32BE();
|
||||||
switch (compressionType) {
|
switch (compressionType) {
|
||||||
case MKID_BE('MP3 '):
|
case MKID_BE('MP3 '):
|
||||||
case MKID_BE('OGG '):
|
case MKID_BE('OGG '):
|
||||||
|
@ -47,19 +54,22 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
|
||||||
// Detected a compressed audio volume
|
// Detected a compressed audio volume
|
||||||
source->audioCompressionType = compressionType;
|
source->audioCompressionType = compressionType;
|
||||||
// Now read the whole offset mapping table for later usage
|
// Now read the whole offset mapping table for later usage
|
||||||
int32 recordCount = file->readUint32LE();
|
int32 recordCount = fileStream->readUint32LE();
|
||||||
if (!recordCount)
|
if (!recordCount)
|
||||||
error("compressed audio volume doesn't contain any entries!");
|
error("compressed audio volume doesn't contain any entries!");
|
||||||
int32 *offsetMapping = new int32[(recordCount + 1) * 2];
|
int32 *offsetMapping = new int32[(recordCount + 1) * 2];
|
||||||
source->audioCompressionOffsetMapping = offsetMapping;
|
source->audioCompressionOffsetMapping = offsetMapping;
|
||||||
for (int recordNo = 0; recordNo < recordCount; recordNo++) {
|
for (int recordNo = 0; recordNo < recordCount; recordNo++) {
|
||||||
*offsetMapping++ = file->readUint32LE();
|
*offsetMapping++ = fileStream->readUint32LE();
|
||||||
*offsetMapping++ = file->readUint32LE();
|
*offsetMapping++ = fileStream->readUint32LE();
|
||||||
}
|
}
|
||||||
// Put ending zero
|
// Put ending zero
|
||||||
*offsetMapping++ = 0;
|
*offsetMapping++ = 0;
|
||||||
*offsetMapping++ = file->size();
|
*offsetMapping++ = fileStream->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (source->resourceFile)
|
||||||
|
delete fileStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) {
|
bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue