aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2009-08-18 10:01:18 +0000
committerFilippos Karapetis2009-08-18 10:01:18 +0000
commitca9bbce9b3e8771f346eca037bd0c39a7e0360de (patch)
treeb48e0126781ab5e042bd144d2be1d109b14ec39b
parent65ac355efa2cb792278e34de5c397ab11c8a46e3 (diff)
downloadscummvm-rg350-ca9bbce9b3e8771f346eca037bd0c39a7e0360de.tar.gz
scummvm-rg350-ca9bbce9b3e8771f346eca037bd0c39a7e0360de.tar.bz2
scummvm-rg350-ca9bbce9b3e8771f346eca037bd0c39a7e0360de.zip
- Added game ID detection to the fallback detector. We still need to map some of Sierra's internal IDs to our own ones
- The class table is now created in the segment manager constructor svn-id: r43504
-rw-r--r--engines/sci/detection.cpp23
-rw-r--r--engines/sci/engine/game.cpp151
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/engine/seg_manager.cpp150
-rw-r--r--engines/sci/engine/seg_manager.h5
-rw-r--r--engines/sci/engine/vm.cpp10
-rw-r--r--engines/sci/engine/vm.h2
7 files changed, 177 insertions, 166 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index d46dd2cbd8..c025523ca0 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -27,6 +27,7 @@
#include "base/plugins.h"
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/exereader.h"
#include "sci/engine/seg_manager.h"
@@ -3047,8 +3048,12 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
Common::String filename = file->getName();
filename.toLowercase();
- if (filename.contains("resource.map") || filename.contains("resmap.000"))
+ if (filename.contains("resource.map") || filename.contains("resmap.000")) {
+ // 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
+ Common::File::addDefaultDirectory(file->getParent().getPath());
foundResMap = true;
+ }
if (filename.contains("resource.000") || filename.contains("resource.001")
|| filename.contains("ressci.000") || filename.contains("ressci.001"))
@@ -3081,24 +3086,30 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
return 0;
// Set some defaults
- s_fallbackDesc.desc.gameid = "sci";
s_fallbackDesc.desc.extra = "";
s_fallbackDesc.desc.language = Common::UNK_LANG;
s_fallbackDesc.desc.platform = exePlatform;
s_fallbackDesc.desc.flags = ADGF_NO_FLAGS;
-#if 0
// Determine the game id
- // TODO
ResourceManager *resMgr = new ResourceManager();
SciVersion version = resMgr->sciVersion();
- SegManager *segManager = new SegManager(resMgr, version);
+ Kernel *kernel = new Kernel(resMgr);
+ SegManager *segManager = new SegManager(resMgr, version, kernel->hasOldScriptHeader());
+ if (!script_instantiate(resMgr, segManager, version, kernel->hasOldScriptHeader(), 0)) {
+ warning("fallbackDetect(): Could not instantiate script 0");
+ return 0;
+ }
reg_t game_obj = script_lookup_export(segManager, 0, 0);
Common::String gameName = obj_get_name(segManager,version, game_obj);
debug(2, " \"%s\" at %04x:%04x", gameName.c_str(), PRINT_REG(game_obj));
+ gameName.toLowercase();
+ // TODO: Sierra's game IDs are not always the same as our own ones, we need to map them
+ // accordingly here
+ s_fallbackDesc.desc.gameid = strdup(gameName.c_str());
+ delete kernel;
delete segManager;
delete resMgr;
-#endif
printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
printf("translation), please, report the data above, including the following\n");
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index 6872039c89..c34ac1cf00 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -188,157 +188,10 @@ int game_init_sound(EngineState *s, int sound_flags) {
return 0;
}
-int create_class_table_sci11(EngineState *s) {
- int scriptnr;
- unsigned int seeker_offset;
- char *seeker_ptr;
- int classnr;
-
- Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
-
- if (!vocab996)
- s->seg_manager->_classtable.resize(20);
- else
- s->seg_manager->_classtable.resize(vocab996->size >> 2);
-
- for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
- Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
-
- if (heap) {
- int global_vars = READ_LE_UINT16(heap->data + 2);
-
- seeker_ptr = (char*)heap->data + 4 + global_vars * 2;
- seeker_offset = 4 + global_vars * 2;
-
- while (READ_LE_UINT16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
- if (READ_LE_UINT16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
- classnr = READ_LE_UINT16((byte*)seeker_ptr + 10);
- if (classnr >= (int)s->seg_manager->_classtable.size()) {
- if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
- warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
- classnr, scriptnr, scriptnr, seeker_offset);
- return 1;
- }
-
- s->seg_manager->_classtable.resize(classnr + 1); // Adjust maximum number of entries
- }
-
- s->seg_manager->_classtable[classnr].reg.offset = seeker_offset;
- s->seg_manager->_classtable[classnr].reg.segment = 0;
- s->seg_manager->_classtable[classnr].script = scriptnr;
- }
-
- seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
- seeker_offset += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
- }
- }
- }
-
- s->resmgr->unlockResource(vocab996);
- vocab996 = NULL;
- return 0;
-}
-
-static int create_class_table_sci0(EngineState *s) {
- int scriptnr;
- unsigned int seeker;
- int classnr;
- int magic_offset; // For strange scripts in older SCI versions
-
- Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
- SciVersion version = s->_version; // for the offset defines
-
- if (!vocab996)
- s->seg_manager->_classtable.resize(20);
- else
- s->seg_manager->_classtable.resize(vocab996->size >> 2);
-
- for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
- int objtype = 0;
- Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0);
-
- if (script) {
- if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader())
- magic_offset = seeker = 2;
- else
- magic_offset = seeker = 0;
-
- do {
- while (seeker < script->size) {
- unsigned int lastseeker = seeker;
- objtype = (int16)READ_LE_UINT16(script->data + seeker);
- if (objtype == SCI_OBJ_CLASS || objtype == SCI_OBJ_TERMINATOR)
- break;
- seeker += (int16)READ_LE_UINT16(script->data + seeker + 2);
- if (seeker <= lastseeker) {
- s->seg_manager->_classtable.clear();
- error("Script version is invalid");
- }
- }
-
- if (objtype == SCI_OBJ_CLASS) {
- int sugg_script;
-
- seeker -= SCRIPT_OBJECT_MAGIC_OFFSET; // Adjust position; script home is base +8 bytes
-
- classnr = (int16)READ_LE_UINT16(script->data + seeker + 4 + SCRIPT_SPECIES_OFFSET);
- if (classnr >= (int)s->seg_manager->_classtable.size()) {
-
- if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
- warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
- classnr, scriptnr, scriptnr, seeker);
- return 1;
- }
-
- s->seg_manager->_classtable.resize(classnr + 1); // Adjust maximum number of entries
- }
-
- // Map the class ID to the script the corresponding class is contained in
- // The script number is found in vocab.996, if it exists
- if (!vocab996 || (uint32)classnr >= vocab996->size >> 2)
- sugg_script = -1;
- else
- sugg_script = (int16)READ_LE_UINT16(vocab996->data + 2 + (classnr << 2));
-
- // First, test whether the script hasn't been claimed, or if it's been claimed by the wrong script
-
- if (sugg_script == -1 || scriptnr == sugg_script /*|| !s->_classtable[classnr].reg.segment*/) {
- // Now set the home script of the class
- s->seg_manager->_classtable[classnr].reg.offset = seeker + 4 - magic_offset;
- s->seg_manager->_classtable[classnr].reg.segment = 0;
- s->seg_manager->_classtable[classnr].script = scriptnr;
- }
-
- seeker += SCRIPT_OBJECT_MAGIC_OFFSET; // Re-adjust position
- seeker += (int16)READ_LE_UINT16(script->data + seeker + 2); // Move to next
- }
-
- } while (objtype != SCI_OBJ_TERMINATOR && seeker <= script->size);
-
- }
- }
- s->resmgr->unlockResource(vocab996);
- vocab996 = NULL;
- return 0;
-}
-
// Architectural stuff: Init/Unintialize engine
int script_init_engine(EngineState *s) {
- int result;
-
s->kernel_opt_flags = 0;
- s->seg_manager = new SegManager(s->resmgr, s->_version);
-
- if (s->_version >= SCI_VERSION_1_1)
- result = create_class_table_sci11(s);
- else
- result = create_class_table_sci0(s);
-
- if (result) {
- debug(2, "Failed to initialize class table");
- return 1;
- }
-
+ s->seg_manager = new SegManager(s->resmgr, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader());
s->gc_countdown = GC_INTERVAL - 1;
SegmentId script_000_segment = s->seg_manager->getSegment(0, SCRIPT_GET_LOCK);
@@ -441,7 +294,7 @@ int game_init(EngineState *s) {
s->stack_base = stack->entries;
s->stack_top = s->stack_base + VM_STACK_SIZE;
- if (!script_instantiate(s->resmgr, s->seg_manager, s->_version, 0)) {
+ if (!script_instantiate(s->resmgr, s->seg_manager, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader(), 0)) {
warning("game_init(): Could not instantiate script 0");
return 1;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index b53e9d522c..0ddb5187ac 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -219,7 +219,7 @@ static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) {
if (s.isLoading()) {
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
delete obj;
- obj = new SegManager(resMgr, version);
+ obj = new SegManager(resMgr, version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader());
}
obj->saveLoadWithSerializer(s);
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index f47a874528..a6f54c5bf7 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -52,7 +52,7 @@ namespace Sci {
#define INVALID_SCRIPT_ID -1
-SegManager::SegManager(ResourceManager *resMgr, SciVersion version) {
+SegManager::SegManager(ResourceManager *resMgr, SciVersion version, bool oldScriptHeader) {
id_seg_map = new IntMapper();
reserved_id = INVALID_SCRIPT_ID;
id_seg_map->checkKey(reserved_id, true); // reserve entry 0 for INVALID_SCRIPT_ID
@@ -68,6 +68,17 @@ SegManager::SegManager(ResourceManager *resMgr, SciVersion version) {
exports_wide = 0;
_version = version;
_resMgr = resMgr;
+ _oldScriptHeader = oldScriptHeader;
+
+ int result = 0;
+
+ if (version >= SCI_VERSION_1_1)
+ result = createSci11ClassTable();
+ else
+ result = createSci0ClassTable();
+
+ if (result)
+ error("SegManager: Failed to initialize class table");
}
// Destroy the object, free the memorys if allocated before
@@ -139,7 +150,7 @@ void SegManager::setScriptSize(Script &scr, int script_nr) {
if (!script || (_version >= SCI_VERSION_1_1 && !heap)) {
error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
}
- if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
+ if (_oldScriptHeader) {
scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
//locals_size = READ_LE_UINT16(script->data) * 2;
} else if (_version < SCI_VERSION_1_1) {
@@ -434,7 +445,7 @@ SegmentId SegManager::getSegment(int script_nr, SCRIPT_GET load) {
SegmentId segment;
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
- script_instantiate(_resMgr, this, _version, script_nr);
+ script_instantiate(_resMgr, this, _version, _oldScriptHeader, script_nr);
segment = segGet(script_nr);
@@ -906,5 +917,138 @@ int SegManager::freeDynmem(reg_t addr) {
return 0; // OK
}
+int SegManager::createSci11ClassTable() {
+ int scriptnr;
+ unsigned int seeker_offset;
+ char *seeker_ptr;
+ int classnr;
+
+ Resource *vocab996 = _resMgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
+
+ if (!vocab996)
+ _classtable.resize(20);
+ else
+ _classtable.resize(vocab996->size >> 2);
+
+ for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
+ Resource *heap = _resMgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
+
+ if (heap) {
+ int global_vars = READ_LE_UINT16(heap->data + 2);
+
+ seeker_ptr = (char*)heap->data + 4 + global_vars * 2;
+ seeker_offset = 4 + global_vars * 2;
+
+ while (READ_LE_UINT16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
+ if (READ_LE_UINT16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
+ classnr = READ_LE_UINT16((byte*)seeker_ptr + 10);
+ if (classnr >= (int)_classtable.size()) {
+ if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
+ warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
+ classnr, scriptnr, scriptnr, seeker_offset);
+ return 1;
+ }
+
+ _classtable.resize(classnr + 1); // Adjust maximum number of entries
+ }
+
+ _classtable[classnr].reg.offset = seeker_offset;
+ _classtable[classnr].reg.segment = 0;
+ _classtable[classnr].script = scriptnr;
+ }
+
+ seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
+ seeker_offset += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
+ }
+ }
+ }
+
+ _resMgr->unlockResource(vocab996);
+ vocab996 = NULL;
+ return 0;
+}
+
+int SegManager::createSci0ClassTable() {
+ int scriptnr;
+ unsigned int seeker;
+ int classnr;
+ int magic_offset; // For strange scripts in older SCI versions
+
+ Resource *vocab996 = _resMgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
+ SciVersion version = _version; // for the offset defines
+
+ if (!vocab996)
+ _classtable.resize(20);
+ else
+ _classtable.resize(vocab996->size >> 2);
+
+ for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
+ int objtype = 0;
+ Resource *script = _resMgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0);
+
+ if (script) {
+ if (_oldScriptHeader)
+ magic_offset = seeker = 2;
+ else
+ magic_offset = seeker = 0;
+
+ do {
+ while (seeker < script->size) {
+ unsigned int lastseeker = seeker;
+ objtype = (int16)READ_LE_UINT16(script->data + seeker);
+ if (objtype == SCI_OBJ_CLASS || objtype == SCI_OBJ_TERMINATOR)
+ break;
+ seeker += (int16)READ_LE_UINT16(script->data + seeker + 2);
+ if (seeker <= lastseeker) {
+ _classtable.clear();
+ error("Script version is invalid");
+ }
+ }
+
+ if (objtype == SCI_OBJ_CLASS) {
+ int sugg_script;
+
+ seeker -= SCRIPT_OBJECT_MAGIC_OFFSET; // Adjust position; script home is base +8 bytes
+
+ classnr = (int16)READ_LE_UINT16(script->data + seeker + 4 + SCRIPT_SPECIES_OFFSET);
+ if (classnr >= (int)_classtable.size()) {
+
+ if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
+ warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
+ classnr, scriptnr, scriptnr, seeker);
+ return 1;
+ }
+
+ _classtable.resize(classnr + 1); // Adjust maximum number of entries
+ }
+
+ // Map the class ID to the script the corresponding class is contained in
+ // The script number is found in vocab.996, if it exists
+ if (!vocab996 || (uint32)classnr >= vocab996->size >> 2)
+ sugg_script = -1;
+ else
+ sugg_script = (int16)READ_LE_UINT16(vocab996->data + 2 + (classnr << 2));
+
+ // First, test whether the script hasn't been claimed, or if it's been claimed by the wrong script
+
+ if (sugg_script == -1 || scriptnr == sugg_script /*|| !s->_classtable[classnr].reg.segment*/) {
+ // Now set the home script of the class
+ _classtable[classnr].reg.offset = seeker + 4 - magic_offset;
+ _classtable[classnr].reg.segment = 0;
+ _classtable[classnr].script = scriptnr;
+ }
+
+ seeker += SCRIPT_OBJECT_MAGIC_OFFSET; // Re-adjust position
+ seeker += (int16)READ_LE_UINT16(script->data + seeker + 2); // Move to next
+ }
+
+ } while (objtype != SCI_OBJ_TERMINATOR && seeker <= script->size);
+
+ }
+ }
+ _resMgr->unlockResource(vocab996);
+ vocab996 = NULL;
+ return 0;
+}
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index f73c788b37..fcf2659df3 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -58,7 +58,7 @@ public:
/**
* Initialize the segment manager
*/
- SegManager(ResourceManager *resMgr, SciVersion version);
+ SegManager(ResourceManager *resMgr, SciVersion version, bool oldScriptHeader);
/**
* Deallocate all memory associated with the segment manager
@@ -342,6 +342,7 @@ public:
private:
IntMapper *id_seg_map; ///< id - script id; seg - index of heap
+ bool _oldScriptHeader;
public: // TODO: make private
Common::Array<MemObject *> _heap;
int reserved_id;
@@ -360,6 +361,8 @@ private:
LocalVariables *allocLocalsSegment(Script *scr, int count);
MemObject *memObjAllocate(SegmentId segid, int hash_id, MemObjectType type);
int deallocate(SegmentId seg, bool recursive);
+ int createSci0ClassTable();
+ int createSci11ClassTable();
Hunk *alloc_Hunk(reg_t *);
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index fbd3bc3baf..64ee7243fb 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -208,7 +208,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
Script *scr = s->seg_manager->getScriptIfLoaded(seg);
if (!scr) // Script not present yet?
- seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, script);
+ seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader(), script);
else
scr->unmarkDeleted();
@@ -1573,7 +1573,7 @@ int script_instantiate_common(ResourceManager *resMgr, SegManager *segManager, S
return seg_id;
}
-int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
+int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr) {
int objtype;
unsigned int objlength;
reg_t reg;
@@ -1593,7 +1593,7 @@ int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, Sci
Script *scr = segManager->getScript(seg_id);
- if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
+ if (oldScriptHeader) {
//
int locals_nr = READ_LE_UINT16(script->data);
@@ -1761,11 +1761,11 @@ int script_instantiate_sci11(ResourceManager *resMgr, SegManager *segManager, Sc
return seg_id;
}
-int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
+int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr) {
if (version >= SCI_VERSION_1_1)
return script_instantiate_sci11(resMgr, segManager, version, script_nr);
else
- return script_instantiate_sci0(resMgr, segManager, version, script_nr);
+ return script_instantiate_sci0(resMgr, segManager, version, oldScriptHeader, script_nr);
}
void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int script_nr, SegmentId seg) {
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index c8f94d5446..867f732e2a 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -489,7 +489,7 @@ reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_ind
* @param[in] script_nr The script number to load
* @return The script's segment ID or 0 if out of heap
*/
-int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr);
+int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr);
/**
* Decreases the numer of lockers of a script and unloads it if that number