SCI: Added enum for map and volume versions. Removed res_version setting from

detection.cpp (should be detectable). Cleanup.

svn-id: r43390
This commit is contained in:
Walter van Niftrik 2009-08-15 00:28:59 +00:00
parent 2e72ed0f69
commit f99932b72a
13 changed files with 171 additions and 393 deletions

View file

@ -428,7 +428,7 @@ void ResourceManager::scanNewSources() {
readResourcePatches(source);
break;
case kSourceExtMap:
if (_mapVersion < SCI_VERSION_1)
if (_mapVersion < kResVersionSci1Late)
readResourceMapSCI0(source);
else
readResourceMapSCI1(source);
@ -453,74 +453,72 @@ void ResourceManager::freeResourceSources() {
_sources.clear();
}
ResourceManager::ResourceManager(int version, int maxMemory) {
ResourceManager::ResourceManager(int maxMemory) {
_maxMemory = maxMemory;
_memoryLocked = 0;
_memoryLRU = 0;
_LRU.clear();
_resMap.clear();
_sciVersion = version;
_audioMapSCI1 = NULL;
addAppropriateSources();
if (version != SCI_VERSION_AUTODETECT) {
_mapVersion = version;
_volVersion = version;
} else {
_mapVersion = detectMapVersion();
_volVersion = detectVolVersion();
if (_volVersion == 0 && _mapVersion > 0) {
warning("Volume version not detected, but map version has been detected. Setting volume version to map version");
_volVersion = _mapVersion;
}
// FIXME: put this in an Init() function, so that we can error out if detection fails completely
if (_mapVersion == 0 && _volVersion > 0) {
warning("Map version not detected, but volume version has been detected. Setting map version to volume version");
_mapVersion = _volVersion;
}
_mapVersion = detectMapVersion();
_volVersion = detectVolVersion();
if ((_volVersion == kResVersionUnknown) && (_mapVersion != kResVersionUnknown)) {
warning("Volume version not detected, but map version has been detected. Setting volume version to map version");
_volVersion = _mapVersion;
}
debug("Using resource map version %d %s", _mapVersion, versionNames[_mapVersion]);
debug("Using volume version %d %s", _volVersion, versionNames[_volVersion]);
if ((_mapVersion == kResVersionUnknown) && (_volVersion != kResVersionUnknown)) {
warning("Map version not detected, but volume version has been detected. Setting map version to volume version");
_mapVersion = _volVersion;
}
debug("Resmgr: Detected resource map version %d: %s", _mapVersion, versionDescription(_mapVersion));
debug("Resmgr: Detected volume version %d: %s", _volVersion, versionDescription(_volVersion));
scanNewSources();
addInternalSources();
scanNewSources();
if (version == SCI_VERSION_AUTODETECT)
switch (_mapVersion) {
case SCI_VERSION_0:
if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB))) {
version = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0;
} else if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB))) {
version = guessSciVersion();
if (version != SCI_VERSION_01) {
version = testResource(ResourceId(kResourceTypeVocab, 912)) ? SCI_VERSION_0 : SCI_VERSION_01;
}
} else {
version = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0;
switch (_mapVersion) {
case kResVersionSci0Sci1Early:
if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB))) {
_sciVersion = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0;
} else if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB))) {
_sciVersion = guessSciVersion();
if (_sciVersion != SCI_VERSION_01) {
_sciVersion = testResource(ResourceId(kResourceTypeVocab, 912)) ? SCI_VERSION_0 : SCI_VERSION_01;
}
break;
case SCI_VERSION_01_VGA_ODD:
version = _mapVersion;
break;
case SCI_VERSION_1:
_sciVersion = version = SCI_VERSION_1;
break;
case SCI_VERSION_1_1:
// No need to handle SCI 1.1 here - it was done in resource_map.cpp
version = SCI_VERSION_1_1;
break;
default:
version = SCI_VERSION_AUTODETECT;
} else {
_sciVersion = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0;
}
break;
case kResVersionSci1Middle:
_sciVersion = SCI_VERSION_01;
break;
case kResVersionSci1Late:
_sciVersion = SCI_VERSION_1;
break;
case kResVersionSci11:
_sciVersion = SCI_VERSION_1_1;
break;
case kResVersionSci32:
_sciVersion = SCI_VERSION_32;
break;
default:
_sciVersion = SCI_VERSION_AUTODETECT;
}
_isVGA = false;
// Determine if the game is using EGA graphics or not
if (version == SCI_VERSION_0) {
if (_sciVersion == SCI_VERSION_0) {
_isVGA = false; // There is no SCI0 VGA game
} else if (version >= SCI_VERSION_1_1) {
} else if (_sciVersion >= SCI_VERSION_1_1) {
_isVGA = true; // There is no SCI11 EGA game
} else {
// SCI01 or SCI1: EGA games have the second byte of their views set
@ -538,12 +536,11 @@ ResourceManager::ResourceManager(int version, int maxMemory) {
}
// Workaround for QFG1 VGA (has SCI 1.1 view data with SCI 1 compression)
if (version == SCI_VERSION_1 && !strcmp(((SciEngine*)g_engine)->getGameID(), "qfg1")) {
if (_sciVersion == SCI_VERSION_1 && !strcmp(((SciEngine*)g_engine)->getGameID(), "qfg1")) {
debug("Resmgr: Detected QFG1 VGA");
_isVGA = true;
}
_sciVersion = version;
// temporary version printout - should be reworked later
switch (_sciVersion) {
case SCI_VERSION_0:
@ -552,9 +549,6 @@ ResourceManager::ResourceManager(int version, int maxMemory) {
case SCI_VERSION_01:
debug("Resmgr: Detected SCI01");
break;
case SCI_VERSION_01_VGA_ODD:
debug("Resmgr: Detected SCI01VGA - Jones/CD or similar");
break;
case SCI_VERSION_1:
debug("Resmgr: Detected SCI1");
break;
@ -713,7 +707,26 @@ void ResourceManager::unlockResource(Resource *res) {
freeOldResources();
}
int ResourceManager::detectMapVersion() {
const char *ResourceManager::versionDescription(ResVersion version) const {
switch (version) {
case kResVersionUnknown:
return "Unknown";
case kResVersionSci0Sci1Early:
return "SCI0 / Early SCI1";
case kResVersionSci1Middle:
return "Middle SCI1";
case kResVersionSci1Late:
return "Late SCI1";
case kResVersionSci11:
return "SCI1.1";
case kResVersionSci32:
return "SCI32";
}
return "Version not valid";
}
ResourceManager::ResVersion ResourceManager::detectMapVersion() {
Common::File file;
byte buff[6];
ResourceSource *rsrc= 0;
@ -728,7 +741,7 @@ int ResourceManager::detectMapVersion() {
}
if (file.isOpen() == false) {
error("Failed to open resource map file");
return SCI_VERSION_AUTODETECT;
return kResVersionUnknown;
}
// detection
// SCI0 and SCI01 maps have last 6 bytes set to FF
@ -739,9 +752,9 @@ int ResourceManager::detectMapVersion() {
file.seek(0, SEEK_SET);
while (file.read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) {
if (getVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL)
return SCI_VERSION_01_VGA_ODD;
return kResVersionSci1Middle;
}
return SCI_VERSION_0;
return kResVersionSci0Sci1Early;
}
// SCI1 and SCI1.1 maps consist of a fixed 3-byte header, a directory list (3-bytes each) that has one entry
@ -750,7 +763,7 @@ int ResourceManager::detectMapVersion() {
uint16 directoryOffset = 0;
uint16 lastDirectoryOffset = 0;
uint16 directorySize = 0;
int mapDetected = 0;
ResVersion mapDetected = kResVersionUnknown;
file.seek(0, SEEK_SET);
while (!file.eos()) {
directoryType = file.readByte();
@ -763,9 +776,9 @@ int ResourceManager::detectMapVersion() {
if (lastDirectoryOffset) {
directorySize = directoryOffset - lastDirectoryOffset;
if ((directorySize % 5) && (directorySize % 6 == 0))
mapDetected = SCI_VERSION_1;
mapDetected = kResVersionSci1Late;
if ((directorySize % 5 == 0) && (directorySize % 6))
mapDetected = SCI_VERSION_1_1;
mapDetected = kResVersionSci11;
}
if (directoryType==0xFF) {
// FFh entry needs to point to EOF
@ -773,7 +786,7 @@ int ResourceManager::detectMapVersion() {
break;
if (mapDetected)
return mapDetected;
return SCI_VERSION_1;
return kResVersionSci1Late;
}
lastDirectoryOffset = directoryOffset;
}
@ -789,13 +802,13 @@ int ResourceManager::detectMapVersion() {
// last directory entry instead of the last checked directory entry.
file.seek(lastDirectoryOffset - 7, SEEK_SET);
if (file.readByte() == 0xFF && file.readUint16LE() == file.size())
return SCI_VERSION_32; // TODO : check if there is a difference between these maps
return kResVersionSci32; // TODO : check if there is a difference between these maps
#endif
return SCI_VERSION_AUTODETECT;
return kResVersionUnknown;
}
int ResourceManager::detectVolVersion() {
ResourceManager::ResVersion ResourceManager::detectVolVersion() {
Common::File file;
ResourceSource *rsrc;
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
@ -808,7 +821,7 @@ int ResourceManager::detectVolVersion() {
}
if (file.isOpen() == false) {
error("Failed to open volume file");
return SCI_VERSION_AUTODETECT;
return kResVersionUnknown;
}
// SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
// SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
@ -818,34 +831,34 @@ int ResourceManager::detectVolVersion() {
// Checking 1MB of data should be enough to determine the version
uint16 resId, wCompression;
uint32 dwPacked, dwUnpacked;
int curVersion = SCI_VERSION_0;
ResVersion curVersion = kResVersionSci0Sci1Early;
bool failed = false;
// Check for SCI0, SCI1, SCI1.1 and SCI32 v2 (Gabriel Knight 1 CD) formats
while (!file.eos() && file.pos() < 0x100000) {
if (curVersion > SCI_VERSION_0)
if (curVersion > kResVersionSci0Sci1Early)
file.readByte();
resId = file.readUint16LE();
dwPacked = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE();
dwUnpacked = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE();
wCompression = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE();
dwPacked = (curVersion < kResVersionSci32) ? file.readUint16LE() : file.readUint32LE();
dwUnpacked = (curVersion < kResVersionSci32) ? file.readUint16LE() : file.readUint32LE();
wCompression = (curVersion < kResVersionSci32) ? file.readUint16LE() : file.readUint32LE();
if (file.eos())
return curVersion;
int chk = (curVersion == SCI_VERSION_0) ? 4 : 20;
int offs = curVersion < SCI_VERSION_1_1 ? 4 : 0;
if ((curVersion < SCI_VERSION_32 && wCompression > chk)
|| (curVersion == SCI_VERSION_32 && wCompression != 0 && wCompression != 32)
int chk = (curVersion == kResVersionSci0Sci1Early) ? 4 : 20;
int offs = curVersion < kResVersionSci11 ? 4 : 0;
if ((curVersion < kResVersionSci32 && wCompression > chk)
|| (curVersion == kResVersionSci32 && wCompression != 0 && wCompression != 32)
|| (wCompression == 0 && dwPacked != dwUnpacked + offs)
|| (dwUnpacked < dwPacked - offs)) {
// Retry with a newer SCI version
if (curVersion == SCI_VERSION_0) {
curVersion = SCI_VERSION_1;
} else if (curVersion == SCI_VERSION_1) {
curVersion = SCI_VERSION_1_1;
} else if (curVersion == SCI_VERSION_1_1) {
curVersion = SCI_VERSION_32;
if (curVersion == kResVersionSci0Sci1Early) {
curVersion = kResVersionSci1Late;
} else if (curVersion == kResVersionSci1Late) {
curVersion = kResVersionSci11;
} else if (curVersion == kResVersionSci11) {
curVersion = kResVersionSci32;
} else {
// All version checks failed, exit loop
failed = true;
@ -856,11 +869,11 @@ int ResourceManager::detectVolVersion() {
continue;
}
if (curVersion < SCI_VERSION_1_1)
if (curVersion < kResVersionSci11)
file.seek(dwPacked - 4, SEEK_CUR);
else if (curVersion == SCI_VERSION_1_1)
else if (curVersion == kResVersionSci11)
file.seek((9 + dwPacked) % 2 ? dwPacked + 1 : dwPacked, SEEK_CUR);
else if (curVersion == SCI_VERSION_32)
else if (curVersion == kResVersionSci32)
file.seek(dwPacked, SEEK_CUR);//(9 + wPacked) % 2 ? wPacked + 1 : wPacked, SEEK_CUR);
}
@ -868,7 +881,7 @@ int ResourceManager::detectVolVersion() {
return curVersion;
// Failed to detect volume version
return SCI_VERSION_AUTODETECT;
return kResVersionUnknown;
}
// version-agnostic patch application
@ -997,10 +1010,8 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
file.seek(0, SEEK_SET);
byte bMask = 0xFC;
// FIXME: The code above seems to give correct results for Jones
//byte bMask = _mapVersion == SCI_VERSION_01_VGA_ODD ? 0xF0 : 0xFC;
byte bShift = _mapVersion == SCI_VERSION_01_VGA_ODD ? 28 : 26;
byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC;
byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26;
do {
id = file.readUint16LE();
@ -1040,7 +1051,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
resource_index_t resMap[32];
memset(resMap, 0, sizeof(resource_index_t) * 32);
byte type = 0, prevtype = 0;
byte nEntrySize = _mapVersion == SCI_VERSION_1_1 ? SCI11_RESMAP_ENTRIES_SIZE : SCI1_RESMAP_ENTRIES_SIZE;
byte nEntrySize = _mapVersion == kResVersionSci11 ? SCI11_RESMAP_ENTRIES_SIZE : SCI1_RESMAP_ENTRIES_SIZE;
ResourceId resId;
// Read resource type and offsets to resource offsets block from .MAP file
@ -1062,7 +1073,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
for (int i = 0; i < resMap[type].wSize; i++) {
uint16 number = file.readUint16LE();
int volume_nr = 0;
if (_mapVersion == SCI_VERSION_1_1) {
if (_mapVersion == kResVersionSci11) {
// offset stored in 3 bytes
off = file.readUint16LE();
off |= file.readByte() << 16;
@ -1070,7 +1081,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
} else {
// offset/volume stored in 4 bytes
off = file.readUint32LE();
if (_mapVersion < SCI_VERSION_1_1) {
if (_mapVersion < kResVersionSci11) {
volume_nr = off >> 28; // most significant 4 bits
off &= 0x0FFFFFFF; // least significant 28 bits
} else {
@ -1351,7 +1362,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
ResourceType type;
switch (_volVersion) {
case SCI_VERSION_0:
case kResVersionSci0Sci1Early:
case kResVersionSci1Middle:
w = file->readUint16LE();
type = (ResourceType)(w >> 11);
number = w & 0x7FF;
@ -1359,14 +1371,14 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
szUnpacked = file->readUint16LE();
wCompression = file->readUint16LE();
break;
case SCI_VERSION_1:
case kResVersionSci1Late:
type = (ResourceType)(file->readByte() & 0x7F);
number = file->readUint16LE();
szPacked = file->readUint16LE() - 4;
szUnpacked = file->readUint16LE();
wCompression = file->readUint16LE();
break;
case SCI_VERSION_1_1:
case kResVersionSci11:
type = (ResourceType)(file->readByte() & 0x7F);
number = file->readUint16LE();
szPacked = file->readUint16LE();
@ -1374,7 +1386,7 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
wCompression = file->readUint16LE();
break;
#ifdef ENABLE_SCI32
case SCI_VERSION_32:
case kResVersionSci32:
type = (ResourceType)(file->readByte() &0x7F);
number = file->readUint16LE();
szPacked = file->readUint32LE();