diff options
| author | Travis Howell | 2009-08-19 01:22:43 +0000 |
|---|---|---|
| committer | Travis Howell | 2009-08-19 01:22:43 +0000 |
| commit | 89d7fea4e619cd44d5ce16eee1e46ad417e26c9c (patch) | |
| tree | a5df60123d0d6a44d824d21e95df2ef421a4700b /engines/sci/engine | |
| parent | dfaa5acbee5766e59b35697ea1b03122aa4ea2aa (diff) | |
| parent | 2bd1f51d92492fa88ba61dc65f783fc9bbfd852c (diff) | |
| download | scummvm-rg350-89d7fea4e619cd44d5ce16eee1e46ad417e26c9c.tar.gz scummvm-rg350-89d7fea4e619cd44d5ce16eee1e46ad417e26c9c.tar.bz2 scummvm-rg350-89d7fea4e619cd44d5ce16eee1e46ad417e26c9c.zip | |
Merged revisions 43458-43468,43470-43471,43473-43475,43477,43479-43483,43485,43497-43498,43500,43503-43504,43507,43509-43510,43512-43515,43517,43519,43521,43523 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
........
r43458 | thebluegr | 2009-08-17 15:55:21 +1000 (Mon, 17 Aug 2009) | 8 lines
- Simplified some functions to accept only the parts of the EngineState they need as parameters, instead of the whole EngineState
- Moved the class table in the Segment manager - it's the only class using it directly
- Removed the sci11 flag from save games (we already know this, we don't need to store it)
- Moved script_get_segment() and get_class_address() inside the segment manager class
- Removed the script_locate_by_segment wrapper
- Simplified script_lookup_export() a lot by removing some paranoia checks
- Added some WIP code for automatically determining the game id in the fallback detector (still not working)
- General cleanup
........
r43459 | lordhoto | 2009-08-17 17:36:08 +1000 (Mon, 17 Aug 2009) | 1 line
Fix compilation of the SCI engine. It seems that all of the SCI header files I touched (and probably others I luckily didn't touch) seem to assume that files including them will supply needed types. That looks like a major issue in SCI. Someone with knowledge of the SCI code should look into this and cleanup the includes of *all* SCI headers.
........
r43460 | thebluegr | 2009-08-17 19:19:53 +1000 (Mon, 17 Aug 2009) | 1 line
Cleanup
........
r43461 | strangerke | 2009-08-17 19:50:35 +1000 (Mon, 17 Aug 2009) | 1 line
Added OPCODEDRAW 0x85, with a specific workaround for Bambou hardcoded paths in scripts
........
r43462 | strangerke | 2009-08-17 19:54:49 +1000 (Mon, 17 Aug 2009) | 1 line
Suppress useless parentheses
........
r43463 | lordhoto | 2009-08-17 19:57:09 +1000 (Mon, 17 Aug 2009) | 1 line
Formatting.
........
r43464 | strangerke | 2009-08-17 20:05:02 +1000 (Mon, 17 Aug 2009) | 1 line
Add back parenthesis (I wasn't aware of this convention, sorry) in saveload, and mimic this code in oPlaytoons_openItk
........
r43465 | lordhoto | 2009-08-17 20:48:03 +1000 (Mon, 17 Aug 2009) | 2 lines
- Add note about that modifing the parent stream will mess up SeekableSubReadStream and SeekableSubReadStreamEndian.
- Link to SubReadStream documentation from SeekableSubReadStream and SeekableSubReadStreamEndian.
........
r43466 | thebluegr | 2009-08-17 21:06:27 +1000 (Mon, 17 Aug 2009) | 1 line
Made sound effect playing code consistent for compressed and uncompressed sounds. MemoryReadStream is used again instead of SeekableSubReadStream, as there will be issues when multiple sound effects or voices are played simultaneously
........
r43467 | thebluegr | 2009-08-17 21:11:38 +1000 (Mon, 17 Aug 2009) | 1 line
Ignore speech and sound effect samples with unknown compression, instead of trying to play them as raw sound. Some cleanup
........
r43468 | dreammaster | 2009-08-17 21:36:09 +1000 (Mon, 17 Aug 2009) | 1 line
Fix for some more !!HIGH STRINGS!! when talking to the palace guards
........
r43470 | thebluegr | 2009-08-17 21:49:07 +1000 (Mon, 17 Aug 2009) | 1 line
Simplified the sound playing code by removing the boolean variables for signed, stereo, endian and sample bit information - now sound flags are used instead. Some cleanup.
........
r43471 | dreammaster | 2009-08-17 21:51:42 +1000 (Mon, 17 Aug 2009) | 1 line
Switched event loop while/do to do/while, to ensure event handling occurs even when the game is under heavy load
........
r43473 | lordhoto | 2009-08-17 22:22:15 +1000 (Mon, 17 Aug 2009) | 1 line
Cleanup: don't copy the Kyrandia 1 Amiga credits data in a temporary buffer, and thus keeping it twice in memory.
........
r43474 | lordhoto | 2009-08-17 22:22:30 +1000 (Mon, 17 Aug 2009) | 1 line
Clear input queue before displaying the credits in Kyrandia 1.
........
r43475 | lordhoto | 2009-08-17 22:47:57 +1000 (Mon, 17 Aug 2009) | 1 line
Fix possible out of bounds access in Screen::drawShape.
........
r43477 | joostp | 2009-08-17 22:57:37 +1000 (Mon, 17 Aug 2009) | 2 lines
Commit (slightly) modified version of patch #2831248: Allow suspend/resume for PSP
........
r43479 | thebluegr | 2009-08-17 23:16:40 +1000 (Mon, 17 Aug 2009) | 1 line
Added looping support to LinearDiskStream, needed by SAGA and perhaps other engines. Note that the loop end parameter is still not implemented
........
r43480 | thebluegr | 2009-08-17 23:25:44 +1000 (Mon, 17 Aug 2009) | 2 lines
- Removed the custom DigitalMusicInputStream used in SAGA for the digital music in ITE CD and replaced it with the common LinearDiskStream class
- Removed leftover code which plays standalone tracks (it's not used anywhere)
........
r43481 | lordhoto | 2009-08-17 23:49:56 +1000 (Mon, 17 Aug 2009) | 1 line
Slight cleanup to makeLinearDiskStream interface.
........
r43482 | waltervn | 2009-08-18 01:49:22 +1000 (Tue, 18 Aug 2009) | 1 line
SCI: Add autodetection for DoSound. Cleanup.
........
r43483 | waltervn | 2009-08-18 02:07:47 +1000 (Tue, 18 Aug 2009) | 1 line
SCI: Build fix.
........
r43485 | thebluegr | 2009-08-18 04:25:51 +1000 (Tue, 18 Aug 2009) | 1 line
Put back the code for playing external digital music, used by the MIDI enhancement project, which was removed in rev. #43480
........
r43497 | waltervn | 2009-08-18 09:11:25 +1000 (Tue, 18 Aug 2009) | 1 line
SCI: Fix kernel table for multilingual SCI01 games. Cleanup.
........
r43498 | joostp | 2009-08-18 09:54:40 +1000 (Tue, 18 Aug 2009) | 2 lines
PSP: increase optimization level and change clock rate to 333mhz
........
r43500 | thebluegr | 2009-08-18 16:43:06 +1000 (Tue, 18 Aug 2009) | 1 line
Applied agent-q's patch to the SAGA pathfinding code for all platforms - x and y should not ever be greater than 640 and 480 respectively, so it looks safe enough to be applied
........
r43503 | thebluegr | 2009-08-18 19:12:41 +1000 (Tue, 18 Aug 2009) | 1 line
Removed the maxMemory parameter of the resource manager and replaced it with a define
........
r43504 | thebluegr | 2009-08-18 20:01:18 +1000 (Tue, 18 Aug 2009) | 2 lines
- 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
........
r43507 | dreammaster | 2009-08-18 22:25:04 +1000 (Tue, 18 Aug 2009) | 1 line
Bugfix for Castle Skorl problem reported on the list
........
r43509 | thebluegr | 2009-08-18 22:49:34 +1000 (Tue, 18 Aug 2009) | 1 line
Mapped some Sierra internal IDs to our own ones, and added a note about a hack currently used in the fallback detector
........
r43510 | thebluegr | 2009-08-19 00:10:31 +1000 (Wed, 19 Aug 2009) | 1 line
Started rewriting the SCI engine to use FSNode instead of file names. This is the proper solution for removing the hack in the fallback detector, but it still needs work. Also, reduced the things needed to be initialized a bit, so that the detection is a bit faster
........
r43512 | lordhoto | 2009-08-19 01:31:26 +1000 (Wed, 19 Aug 2009) | 1 line
Made AGOS, DRASCULA, GOB, GROOVIE, MADE, SCUMM and TINSEL properly stop CD audio playback on engine quit. (This only problem affected playback from CD, not from ripped audio files)
........
r43513 | lordhoto | 2009-08-19 01:32:26 +1000 (Wed, 19 Aug 2009) | 2 lines
- Destory AudioCDManager singleton after user quits a game, this saves a few bytes memory
- Added FIXME to audiocd.h, concering why destroying the AudioCDManager can not quit CD playback right now
........
r43514 | joostp | 2009-08-19 01:39:47 +1000 (Wed, 19 Aug 2009) | 2 lines
PSP: disable dosbox OPL
........
r43515 | lordhoto | 2009-08-19 01:41:00 +1000 (Wed, 19 Aug 2009) | 1 line
Typos.
........
r43517 | joostp | 2009-08-19 03:12:01 +1000 (Wed, 19 Aug 2009) | 2 lines
PSP: Make R-trigger act as a context sensitive modifier key, remap ENTER to triangle
........
r43519 | joostp | 2009-08-19 04:06:50 +1000 (Wed, 19 Aug 2009) | 2 lines
Implement setCursorPalette(), correct hasFeature() <-> getFeatureState() mixup.
........
r43521 | john_doe | 2009-08-19 05:42:13 +1000 (Wed, 19 Aug 2009) | 2 lines
- PMV player: Use frame count from PVM file and fix incorrect "invalid chunk type" warning
- Fix sprite drawing glitch with vertically flipped sprites (bug #2825925)
........
r43523 | buddha_ | 2009-08-19 07:37:31 +1000 (Wed, 19 Aug 2009) | 1 line
Possible fix for #2828330 (AGI: KQ1: Fast text box). If doesn't break anything else then should go to the branch-1-0-0 too, but haven't had the time to do much testing yet - thus committing to the trunk first.
........
svn-id: r43524
Diffstat (limited to 'engines/sci/engine')
| -rw-r--r-- | engines/sci/engine/game.cpp | 173 | ||||
| -rw-r--r-- | engines/sci/engine/kernel.cpp | 151 | ||||
| -rw-r--r-- | engines/sci/engine/kernel.h | 23 | ||||
| -rw-r--r-- | engines/sci/engine/kmovement.cpp | 2 | ||||
| -rw-r--r-- | engines/sci/engine/kscripts.cpp | 16 | ||||
| -rw-r--r-- | engines/sci/engine/ksound.cpp | 23 | ||||
| -rw-r--r-- | engines/sci/engine/memobj.cpp | 1 | ||||
| -rw-r--r-- | engines/sci/engine/memobj.h | 1 | ||||
| -rw-r--r-- | engines/sci/engine/savegame.cpp | 33 | ||||
| -rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 7 | ||||
| -rw-r--r-- | engines/sci/engine/seg_manager.cpp | 244 | ||||
| -rw-r--r-- | engines/sci/engine/seg_manager.h | 44 | ||||
| -rw-r--r-- | engines/sci/engine/state.cpp | 75 | ||||
| -rw-r--r-- | engines/sci/engine/state.h | 17 | ||||
| -rw-r--r-- | engines/sci/engine/vm.cpp | 224 | ||||
| -rw-r--r-- | engines/sci/engine/vm.h | 59 |
16 files changed, 565 insertions, 528 deletions
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 1fa0e03d4c..c34ac1cf00 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -188,159 +188,13 @@ 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->_classtable.resize(20); - else - s->_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->_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->_classtable.resize(classnr + 1); // Adjust maximum number of entries - } - - s->_classtable[classnr].reg.offset = seeker_offset; - s->_classtable[classnr].reg.segment = 0; - s->_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); - - if (!vocab996) - s->_classtable.resize(20); - else - s->_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->_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->_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->_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->_classtable[classnr].reg.offset = seeker + 4 - magic_offset; - s->_classtable[classnr].reg.segment = 0; - s->_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; - - 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->_version >= SCI_VERSION_1_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 = script_get_segment(s, 0, SCRIPT_GET_LOCK); + SegmentId script_000_segment = s->seg_manager->getSegment(0, SCRIPT_GET_LOCK); if (script_000_segment <= 0) { debug(2, "Failed to instantiate script.000"); @@ -398,7 +252,8 @@ void internal_stringfrag_strncpy(EngineState *s, reg_t *dest, reg_t *src, int le void script_free_vm_memory(EngineState *s) { debug(2, "Freeing VM memory"); - s->_classtable.clear(); + if (s->seg_manager) + s->seg_manager->_classtable.clear(); // Close all opened file handles s->_fileHandles.clear(); @@ -433,14 +288,13 @@ void script_free_breakpoints(EngineState *s) { int game_init(EngineState *s) { // FIXME Use new VM instantiation code all over the place" - reg_t game_obj; // Address of the game object DataStack *stack; stack = s->seg_manager->allocateStack(VM_STACK_SIZE, &s->stack_segment); s->stack_base = stack->entries; s->stack_top = s->stack_base + VM_STACK_SIZE; - if (!script_instantiate(s, 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; } @@ -473,20 +327,11 @@ int game_init(EngineState *s) { srand(g_system->getMillis()); // Initialize random number generator // script_dissect(0, s->_selectorNames); - game_obj = script_lookup_export(s, 0, 0); // The first entry in the export table of script 0 points to the game object + s->game_obj = script_lookup_export(s->seg_manager, 0, 0); + s->_gameName = obj_get_name(s->seg_manager, s->_version, s->game_obj); - const char *tmp = obj_get_name(s, game_obj); - - if (!tmp) { - warning("Error: script.000, export 0 (%04x:%04x) does not yield an object with a name -> sanity check failed", PRINT_REG(game_obj)); - return 1; - } - s->_gameName = tmp; - - debug(2, " \"%s\" at %04x:%04x", s->_gameName.c_str(), PRINT_REG(game_obj)); - - s->game_obj = game_obj; + debug(2, " \"%s\" at %04x:%04x", s->_gameName.c_str(), PRINT_REG(s->game_obj)); // Mark parse tree as unused s->parser_nodes[0].type = kParseTreeLeafNode; @@ -512,7 +357,9 @@ int game_exit(EngineState *s) { game_init_sound(s, SFX_STATE_FLAG_NOSOUND); } + s->seg_manager->_classtable.clear(); delete s->seg_manager; + s->seg_manager = 0; s->_synonyms.clear(); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 193ff4cc51..223e7fc1e9 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -33,11 +33,7 @@ namespace Sci { -/** The string used to identify the "unknown" SCI0 function for each game */ -#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]" - // Default kernel name table -#define SCI0_KNAMES_WELL_DEFINED 0x6e #define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { @@ -367,11 +363,15 @@ static const char *argtype_description[] = { "Arithmetic" }; -Kernel::Kernel(ResourceManager *resmgr) : _resmgr(resmgr) { +Kernel::Kernel(ResourceManager *resmgr, bool minimalLoad) : _resmgr(resmgr) { memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t - detectSciFeatures(); // must be called before loadSelectorNames() loadSelectorNames(); + detectSciFeatures(); + + if (minimalLoad) // If we're only asked to detect game features, stop here + return; + mapSelectors(); // Map a few special selectors for later use loadOpcodes(); loadKernelNames(); @@ -382,61 +382,30 @@ Kernel::~Kernel() { } void Kernel::detectSciFeatures() { - // FIXME Much of this is unreliable - - Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); + SciVersion version = _resmgr->sciVersion(); - Common::StringList staticSelectorTable; - - if (!r) { // No such resource? - staticSelectorTable = checkStaticSelectorNames(); - if (staticSelectorTable.empty()) - error("Kernel: Could not retrieve selector names"); - } - - int count = staticSelectorTable.empty() ? READ_LE_UINT16(r->data) + 1 : staticSelectorTable.size(); // Counter is slightly off features = 0; // Initialize features based on SCI version - switch (_resmgr->sciVersion()) { - case SCI_VERSION_0_EARLY: - features |= kFeatureOldScriptHeader; - /* Fallthrough */ - case SCI_VERSION_0_LATE: - features |= kFeatureOldGfxFunctions; - break; - default: - break; - } - - for (int i = 0; i < count; i++) { - Common::String tmp; - - if (staticSelectorTable.empty()) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset); - - tmp = Common::String((const char *)r->data + offset + 2, len); - } else { - tmp = staticSelectorTable[i]; - } - if (tmp == "motionCue") - features &= ~kFeatureOldGfxFunctions; + // Script header and graphics functions + if (version == SCI_VERSION_0_EARLY) { + features |= kFeatureOldScriptHeader | kFeatureOldGfxFunctions; + } else if (version == SCI_VERSION_0_LATE) { + if (findSelector("motionCue") == -1) + features |= kFeatureOldGfxFunctions; + } - if (tmp == "egoMoveSpeed" && _resmgr->sciVersion() < SCI_VERSION_1_1) + // Lofs absolute/relative + if (version >= SCI_VERSION_1_MIDDLE && version < SCI_VERSION_1_1) { + // Assume all games use absolute lofs + features |= kFeatureLofsAbsolute; + } else if (version == SCI_VERSION_1_EARLY) { + // Use heuristic + if (findSelector("egoMoveSpeed") != -1) features |= kFeatureLofsAbsolute; - - if (tmp == "setVol") - features |= kFeatureSci1Sound; - - if (tmp == "nodePtr") - features |= kFeatureSci01Sound; } - if (features & kFeatureSci1Sound) - features &= ~kFeatureSci01Sound; - printf("Kernel auto-detected features:\n"); printf("Graphics functions: "); @@ -445,19 +414,13 @@ void Kernel::detectSciFeatures() { else printf("new\n"); - printf("lofs parameters: "); - if (features & kFeatureLofsAbsolute) - printf("absolute\n"); - else - printf("relative\n"); - - printf("Sound functions: "); - if (features & kFeatureSci1Sound) - printf("SCI1\n"); - else if (features & kFeatureSci01Sound) - printf("SCI01\n"); - else - printf("SCI0\n"); + if (version < SCI_VERSION_1_1) { + printf("lofs parameters: "); + if (features & kFeatureLofsAbsolute) + printf("absolute\n"); + else + printf("relative\n"); + } } void Kernel::loadSelectorNames() { @@ -473,7 +436,7 @@ void Kernel::loadSelectorNames() { for (uint32 i = 0; i < staticSelectorTable.size(); i++) { _selectorNames.push_back(staticSelectorTable[i]); - if (features & kFeatureOldScriptHeader) + if (_resmgr->sciVersion() == SCI_VERSION_0_EARLY) _selectorNames.push_back(staticSelectorTable[i]); } @@ -492,7 +455,7 @@ void Kernel::loadSelectorNames() { // Early SCI versions used the LSB in the selector ID as a read/write // toggle. To compensate for that, we add every selector name twice. - if (features & kFeatureOldScriptHeader) + if (_resmgr->sciVersion() == SCI_VERSION_0_EARLY) _selectorNames.push_back(tmp); } } @@ -706,6 +669,8 @@ int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) { mobj = s->seg_manager->_heap[reg.segment]; + SciVersion version = s->_version; // for the offset defines + switch (mobj->getType()) { case MEM_OBJ_SCRIPT: if (reg.offset <= (*(Script *)mobj).buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET @@ -817,32 +782,40 @@ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries } void Kernel::setDefaultKernelNames() { - bool isSci0 = (_resmgr->sciVersion() <= SCI_VERSION_0_LATE); - int offset = 0; - - _kernelNames.resize(SCI_KNAMES_DEFAULT_ENTRIES_NR + (isSci0 ? 4 : 0)); - for (int i = 0; i < SCI_KNAMES_DEFAULT_ENTRIES_NR; i++) { - // In SCI0, Platform was DoAvoider - if (!strcmp(sci_default_knames[i], "Platform") && isSci0) { - _kernelNames[i + offset] = "DoAvoider"; - continue; - } + _kernelNames = Common::StringList(sci_default_knames, SCI_KNAMES_DEFAULT_ENTRIES_NR); + + switch (_resmgr->sciVersion()) { + case SCI_VERSION_0_EARLY: + case SCI_VERSION_0_LATE: + // Insert SCI0 file functions after SetCursor (0x28) + _kernelNames.insert_at(0x29, "FOpen"); + _kernelNames.insert_at(0x2A, "FPuts"); + _kernelNames.insert_at(0x2B, "FGets"); + _kernelNames.insert_at(0x2C, "FClose"); - _kernelNames[i + offset] = sci_default_knames[i]; + // Function 0x55 is DoAvoider + _kernelNames[0x55] = "DoAvoider"; - // SCI0 has 4 extra functions between SetCursor (0x28) and Savegame - if (!strcmp(sci_default_knames[i], "SetCursor") && isSci0) { - _kernelNames[i + 1] = "FOpen"; - _kernelNames[i + 2] = "FPuts"; - _kernelNames[i + 3] = "FGets"; - _kernelNames[i + 4] = "FClose"; - offset = 4; - } - } + // Cut off unused functions + _kernelNames.resize(0x72); + break; + + case SCI_VERSION_01: + // Multilingual SCI01 games have StrSplit as function 0x78 + _kernelNames[0x78] = "StrSplit"; - if (_resmgr->sciVersion() == SCI_VERSION_1_1) { - // HACK: KQ6CD calls unimplemented function 0x26 + // Cut off unused functions + _kernelNames.resize(0x79); + break; + + case SCI_VERSION_1_1: + // KQ6CD calls unimplemented function 0x26 _kernelNames[0x26] = "Dummy"; + break; + + default: + // Use default table for the other versions + break; } } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 2c90728fb0..997cdaea77 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -32,6 +32,8 @@ #include "sci/uinput.h" #include "sci/vocabulary.h" +#include "sci/engine/vm_types.h" // for reg_t +#include "sci/engine/vm.h" namespace Sci { @@ -58,14 +60,17 @@ struct KernelFuncWithSignature { enum AutoDetectedFeatures { kFeatureOldScriptHeader = 1 << 0, kFeatureOldGfxFunctions = 1 << 1, - kFeatureLofsAbsolute = 1 << 2, - kFeatureSci01Sound = 1 << 3, - kFeatureSci1Sound = 1 << 4 + kFeatureLofsAbsolute = 1 << 2 }; class Kernel { public: - Kernel(ResourceManager *resmgr); + /** + * Initializes the SCI kernel + * @param minimalLoad If true, only the selector names are loaded, to detect game features. + * It's set to true by the advanced game detector to speed it up + */ + Kernel(ResourceManager *resmgr, bool minimalLoad = false); ~Kernel(); uint getOpcodesSize() const { return _opcodes.size(); } @@ -117,16 +122,6 @@ public: */ bool hasLofsAbsolute() const { return (features & kFeatureLofsAbsolute); } - /** - * Determines if the game is using SCI01 sound functions - */ - bool usesSci01SoundFunctions() const { return (features & kFeatureSci01Sound); } - - /** - * Determines if the game is using SCI1 sound functions - */ - bool usesSci1SoundFunctions() const { return (features & kFeatureSci1Sound); } - // Script dissection/dumping functions void dissectScript(int scriptNumber, Vocabulary *vocab); void dumpScriptObject(char *data, int seeker, int objsize); diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 7433324a70..58dc3b73f1 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -257,7 +257,7 @@ static void bresenham_autodetect(EngineState *s) { reg_t motion_class; if (!parse_reg_t(s, "?Motion", &motion_class)) { - Object *obj = obj_get(s, motion_class); + Object *obj = obj_get(s->seg_manager, s->_version, motion_class); reg_t fptr; byte *buf; diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index df25e11729..4d90dd68ac 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -108,7 +108,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc } bool is_object(EngineState *s, reg_t object) { - return obj_get(s, object) != NULL; + return obj_get(s->seg_manager, s->_version, object) != NULL; } // Loads arbitrary resources of type 'restype' with resource numbers 'resnrs' @@ -184,7 +184,7 @@ reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t parent_addr = argv[0]; - Object *parent_obj = obj_get(s, parent_addr); + Object *parent_obj = obj_get(s->seg_manager, s->_version, parent_addr); reg_t clone_addr; Clone *clone_obj; // same as Object* @@ -205,6 +205,8 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { *clone_obj = *parent_obj; clone_obj->flags = 0; + SciVersion version = s->_version; // for the selector defines + // Mark as clone clone_obj->_variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE; clone_obj->_variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos; @@ -220,7 +222,7 @@ extern void _k_view_list_mark_free(EngineState *s, reg_t off); reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t victim_addr = argv[0]; - Clone *victim_obj = obj_get(s, victim_addr); + Clone *victim_obj = obj_get(s->seg_manager, s->_version, victim_addr); uint16 underBits; if (!victim_obj) { @@ -229,6 +231,8 @@ reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } + SciVersion version = s->_version; // for the selector defines + if (victim_obj->_variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) { //warning("Attempt to dispose something other than a clone at %04x", offset); // SCI silently ignores this behaviour; some games actually depend on it @@ -260,7 +264,7 @@ reg_t kScriptID(EngineState *s, int funct_nr, int argc, reg_t *argv) { int script = argv[0].toUint16(); int index = (argc > 1) ? argv[1].toUint16() : 0; - SegmentId scriptid = script_get_segment(s, script, SCRIPT_GET_LOAD); + SegmentId scriptid = s->seg_manager->getSegment(script, SCRIPT_GET_LOAD); Script *scr; if (argv[0].segment) @@ -299,13 +303,13 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) { scr->setLockers(1); } - script_uninstantiate(s, script); + script_uninstantiate(s->seg_manager, s->_version, script); s->_executionStackPosChanged = true; return s->r_acc; } int is_heap_object(EngineState *s, reg_t pos) { - Object *obj = obj_get(s, pos); + Object *obj = obj_get(s->seg_manager, s->_version, pos); return (obj != NULL && (!(obj->flags & OBJECT_FLAG_FREED)) && (!s->seg_manager->scriptIsMarkedAsDeleted(pos.segment))); } diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 38baeafad8..44b2404e41 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -204,7 +204,7 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their } -reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { +reg_t kDoSoundSci0(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = (argc > 1) ? argv[1] : NULL_REG; uint16 command = argv[0].toUint16(); SongHandle handle = FROBNICATE_HANDLE(obj); @@ -383,7 +383,7 @@ reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { } -reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { +reg_t kDoSoundSci1Early(EngineState *s, int funct_nr, int argc, reg_t *argv) { uint16 command = argv[0].toUint16(); reg_t obj = (argc > 1) ? argv[1] : NULL_REG; SongHandle handle = FROBNICATE_HANDLE(obj); @@ -673,7 +673,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { +reg_t kDoSoundSci1Late(EngineState *s, int funct_nr, int argc, reg_t *argv) { uint16 command = argv[0].toUint16(); reg_t obj = (argc > 1) ? argv[1] : NULL_REG; SongHandle handle = FROBNICATE_HANDLE(obj); @@ -988,12 +988,17 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { * Used for synthesized music playback */ reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) { - if (((SciEngine*)g_engine)->getKernel()->usesSci1SoundFunctions()) - return kDoSound_SCI1(s, funct_nr, argc, argv); - else if (((SciEngine*)g_engine)->getKernel()->usesSci01SoundFunctions()) - return kDoSound_SCI01(s, funct_nr, argc, argv); - else - return kDoSound_SCI0(s, funct_nr, argc, argv); + switch(s->detectDoSoundType()) { + case EngineState::kDoSoundTypeSci0: + return kDoSoundSci0(s, funct_nr, argc, argv); + case EngineState::kDoSoundTypeSci1Early: + return kDoSoundSci1Early(s, funct_nr, argc, argv); + case EngineState::kDoSoundTypeSci1Late: + return kDoSoundSci1Late(s, funct_nr, argc, argv); + default: + warning("Unknown DoSound type"); + return NULL_REG; + } } /** diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp index ab8e14efc7..34432521a0 100644 --- a/engines/sci/engine/memobj.cpp +++ b/engines/sci/engine/memobj.cpp @@ -246,6 +246,7 @@ void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback not void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { Script *script = this; + SciVersion version = s->_version; // for the offset defines if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) { int idx = RAW_GET_CLASS_INDEX(script, addr); diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h index 50c43a0e88..efe7f26f1c 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -27,6 +27,7 @@ #define SCI_ENGINE_MEMOBJ_H #include "common/serializer.h" +#include "sci/engine/vm.h" #include "sci/engine/vm_types.h" // for reg_t //#include "common/util.h" diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 75cd4aee54..0ddb5187ac 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -205,19 +205,21 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { } static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) { - bool sci11 = false; + SciVersion version = SCI_VERSION_AUTODETECT; + ResourceManager *resMgr = 0; if (s.isSaving()) { assert(obj); - sci11 = obj->isSci1_1; + version = obj->_version; + resMgr = obj->_resMgr; } - s.syncAsByte(sci11); + s.skip(1); // obsolete: used to be a flag indicating if we got sci11 or not 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(sci11); + obj = new SegManager(resMgr, version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()); } obj->saveLoadWithSerializer(s); @@ -266,7 +268,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { sync_SegManagerPtr(s, seg_manager); - syncArray<Class>(s, _classtable); + syncArray<Class>(s, seg_manager->_classtable); sync_sfx_state_t(s, _sound); } @@ -549,7 +551,7 @@ static void load_script(EngineState *s, SegmentId seg) { heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scr->nr), 0); memcpy(scr->buf, script->data, script->size); - if (s->seg_manager->isSci1_1) + if (s->seg_manager->_version == SCI_VERSION_1_1) memcpy(scr->buf + scr->script_size, heap->data, heap->size); } @@ -557,6 +559,8 @@ static void load_script(EngineState *s, SegmentId seg) { static void reconstruct_scripts(EngineState *s, SegManager *self) { uint i, j; MemObject *mobj; + SciVersion version = s->_version; // for the selector defines + for (i = 0; i < self->_heap.size(); i++) { if (self->_heap[i]) { mobj = self->_heap[i]; @@ -567,7 +571,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { // FIXME: Unify this code with script_instantiate_* load_script(s, i); scr->locals_block = (scr->locals_segment == 0) ? NULL : (LocalVariables *)(s->seg_manager->_heap[scr->locals_segment]); - if (s->seg_manager->isSci1_1) { + if (s->seg_manager->_version == SCI_VERSION_1_1) { scr->export_table = 0; scr->synonyms = 0; if (READ_LE_UINT16(scr->buf + 6) > 0) { @@ -603,7 +607,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { for (j = 0; j < scr->_objects.size(); j++) { byte *data = scr->buf + scr->_objects[j].pos.offset; - if (self->isSci1_1) { + if (self->_version == SCI_VERSION_1_1) { uint16 *funct_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 6 )); uint16 *prop_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 4 )); @@ -613,7 +617,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET ); Object *base_obj; - base_obj = obj_get(s, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = obj_get(s->seg_manager, s->_version, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]); if (!base_obj) { warning("Object without a base class: Script %d, index %d (reg address %04x:%04x", @@ -638,6 +642,8 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { // FIXME: The following should likely become a SegManager method static void reconstruct_clones(EngineState *s, SegManager *self) { + SciVersion version = s->_version; // for the selector defines + for (uint i = 0; i < self->_heap.size(); i++) { if (self->_heap[i]) { MemObject *mobj = self->_heap[i]; @@ -667,7 +673,7 @@ static void reconstruct_clones(EngineState *s, SegManager *self) { continue; } CloneTable::Entry &seeker = ct->_table[j]; - base_obj = obj_get(s, seeker._variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = obj_get(s->seg_manager, s->_version, seeker._variables[SCRIPT_SPECIES_SELECTOR]); if (!base_obj) { printf("Clone entry without a base class: %d\n", j); seeker.base = seeker.base_obj = NULL; @@ -695,8 +701,7 @@ static void reconstruct_sounds(EngineState *s) { Song *seeker; SongIteratorType it_type; - if (((SciEngine *)g_engine)->getKernel()->usesSci01SoundFunctions() - || ((SciEngine *)g_engine)->getKernel()->usesSci1SoundFunctions()) + if (s->_version > SCI_VERSION_01) it_type = SCI_SONG_ITERATOR_TYPE_SCI1; else it_type = SCI_SONG_ITERATOR_TYPE_SCI0; @@ -791,7 +796,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { reconstruct_scripts(retval, retval->seg_manager); reconstruct_clones(retval, retval->seg_manager); retval->game_obj = s->game_obj; - retval->script_000 = retval->seg_manager->getScript(script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD)); + retval->script_000 = retval->seg_manager->getScript(retval->seg_manager->getSegment(0, SCRIPT_GET_DONT_LOAD)); retval->gc_countdown = GC_INTERVAL - 1; retval->sys_strings_segment = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_SYS_STRINGS); retval->sys_strings = (SystemStrings *)GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS); @@ -831,7 +836,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->successor = NULL; retval->pic_priority_table = (int *)gfxop_get_pic_metainfo(retval->gfx_state); - retval->_gameName = obj_get_name(retval, retval->game_obj); + retval->_gameName = obj_get_name(retval->seg_manager, retval->_version, retval->game_obj); retval->_sound._it = NULL; retval->_sound._flags = s->_sound._flags; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 0341ecb73d..fd7219bc85 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -37,9 +37,10 @@ extern const char *selector_name(EngineState *s, int selector); ScriptState scriptState; int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { - Object *obj = obj_get(s, objp); + Object *obj = obj_get(s->seg_manager, s->_version, objp); byte *selectoroffset; int selectors; + SciVersion version = s->_version; // for the selector defines if (!obj) { warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp)); @@ -52,7 +53,7 @@ int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; else { if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) { - obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + obj = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); selectoroffset = (byte *)obj->base_vars; } else selectoroffset = (byte *)obj->base_vars; @@ -268,7 +269,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod selector = sb[- stackframe].offset; - name = obj_get_name(s, called_obj_addr); + name = obj_get_name(s->seg_manager, s->_version, called_obj_addr); if (!name) name = "<invalid>"; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 905cba9d94..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(bool sci1_1) { +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 @@ -66,7 +66,19 @@ SegManager::SegManager(bool sci1_1) { Hunks_seg_id = 0; exports_wide = 0; - isSci1_1 = sci1_1; + _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 @@ -109,7 +121,7 @@ MemObject *SegManager::allocNonscriptSegment(MemObjectType type, SegmentId *segi // Returns : 0 - allocation failure // 1 - allocated successfully // seg_id - allocated segment id -Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg_id) { +Script *SegManager::allocateScript(int script_nr, SegmentId *seg_id) { bool was_added; MemObject *mem; @@ -128,20 +140,20 @@ Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg return (Script *)mem; } -void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { - Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); +void SegManager::setScriptSize(Script &scr, int script_nr) { + Resource *script = _resMgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); + Resource *heap = _resMgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); scr.script_size = script->size; scr.heap_size = 0; // Set later - if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) { + 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 (s->_version < SCI_VERSION_1_1) { + } else if (_version < SCI_VERSION_1_1) { scr.buf_size = script->size; } else { scr.buf_size = script->size + heap->size; @@ -163,10 +175,10 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { } } -int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { +int SegManager::initialiseScript(Script &scr, int script_nr) { // allocate the script.buf - setScriptSize(scr, s, script_nr); + setScriptSize(scr, script_nr); scr.buf = (byte *)malloc(scr.buf_size); #ifdef DEBUG_SEG_MANAGER @@ -191,7 +203,7 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { scr.obj_indices = new IntMapper(); - if (s->_version >= SCI_VERSION_1_1) + if (_version >= SCI_VERSION_1_1) scr.heap_start = scr.buf + scr.script_size; else scr.heap_start = scr.buf; @@ -319,7 +331,7 @@ int SegManager::relocateBlock(Common::Array<reg_t> &block, int block_location, S return 0; } block[idx].segment = segment; // Perform relocation - if (isSci1_1) + if (_version == SCI_VERSION_1_1) block[idx].offset += getScript(segment)->script_size; return 1; @@ -429,13 +441,51 @@ void SegManager::heapRelocate(reg_t block) { } } -#define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, NULL_REG)) +SegmentId SegManager::getSegment(int script_nr, SCRIPT_GET load) { + SegmentId segment; + + if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) + script_instantiate(_resMgr, this, _version, _oldScriptHeader, script_nr); + + segment = segGet(script_nr); + + if (segment > 0) { + if ((load & SCRIPT_GET_LOCK) == SCRIPT_GET_LOCK) + getScript(segment)->incrementLockers(); + + return segment; + } else + return 0; +} -reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller); +#define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(id, SCRIPT_GET_LOCK, NULL_REG)) -Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { +reg_t SegManager::get_class_address(int classnr, SCRIPT_GET lock, reg_t caller) { + if (classnr < 0 || (int)_classtable.size() <= classnr || _classtable[classnr].script < 0) { + error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classtable.size()); + return NULL_REG; + } else { + Class *the_class = &_classtable[classnr]; + if (!the_class->reg.segment) { + getSegment(the_class->script, lock); + + if (!the_class->reg.segment) { + error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;" + " Entering debugger.", classnr, the_class->script, the_class->script); + return NULL_REG; + } + } else + if (caller.segment != the_class->reg.segment) + getScript(the_class->reg.segment)->incrementLockers(); + + return the_class->reg; + } +} + +Object *SegManager::scriptObjInit0(reg_t obj_pos) { Object *obj; int id; + SciVersion version = _version; // for the offset defines unsigned int base = obj_pos.offset - SCRIPT_OBJECT_MAGIC_OFFSET; reg_t temp; @@ -489,7 +539,7 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { return obj; } -Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) { +Object *SegManager::scriptObjInit11(reg_t obj_pos) { Object *obj; int id; int base = obj_pos.offset; @@ -543,11 +593,11 @@ Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) { return obj; } -Object *SegManager::scriptObjInit(EngineState *s, reg_t obj_pos) { - if (!isSci1_1) - return scriptObjInit0(s, obj_pos); +Object *SegManager::scriptObjInit(reg_t obj_pos) { + if (_version != SCI_VERSION_1_1) + return scriptObjInit0(obj_pos); else - return scriptObjInit11(s, obj_pos); + return scriptObjInit11(obj_pos); } LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { @@ -588,7 +638,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) { VERIFY(location.offset + 1 < (uint16)scr->buf_size, "Locals beyond end of script\n"); - if (isSci1_1) + if (_version == SCI_VERSION_1_1) count = READ_LE_UINT16(scr->buf + location.offset - 2); else count = (READ_LE_UINT16(scr->buf + location.offset - 2) - 4) >> 1; @@ -627,24 +677,25 @@ void SegManager::scriptRelocateExportsSci11(SegmentId seg) { } } -void SegManager::scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg) { +void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { Script *scr = getScript(seg); byte *seeker = scr->heap_start + 4 + READ_LE_UINT16(scr->heap_start + 2) * 2; + SciVersion version = _version; // for the selector defines while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { if (READ_LE_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) { int classpos = seeker - scr->buf; int species = READ_LE_UINT16(seeker + 10); - if (species < 0 || species >= (int)s->_classtable.size()) { + if (species < 0 || species >= (int)_classtable.size()) { error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n", - species, species, s->_classtable.size(), scr->nr); + species, species, _classtable.size(), scr->nr); return; } - s->_classtable[species].script = scr->nr; - s->_classtable[species].reg.segment = seg; - s->_classtable[species].reg.offset = classpos; + _classtable[species].script = scr->nr; + _classtable[species].reg.segment = seg; + _classtable[species].reg.offset = classpos; } seeker += READ_LE_UINT16(seeker + 2) * 2; } @@ -656,12 +707,12 @@ void SegManager::scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg) { reg.segment = seg; reg.offset = seeker - scr->buf; - obj = scriptObjInit(s, reg); + obj = scriptObjInit(reg); #if 0 if (obj->_variables[5].offset != 0xffff) { obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset); - base_obj = obj_get(s, obj->_variables[5]); + base_obj = obj_get(s->seg_manager, s->_version, obj->_variables[5]); obj->variable_names_nr = base_obj->variables_nr; obj->base_obj = base_obj->base_obj; } @@ -866,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 9d406f559f..fcf2659df3 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -43,12 +43,22 @@ namespace Sci { (((mgr)._heap[index] && ((mgr)._heap[index]->getType() == MEM_OBJ_SCRIPT || (mgr)._heap[index]->getType() == MEM_OBJ_CLONES))? (mgr)._heap[index] \ : NULL): NULL) +/** + * Parameters for getSegment() + */ +typedef enum { + SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */ + SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */ + SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */ +} SCRIPT_GET; + + class SegManager : public Common::Serializable { public: /** * Initialize the segment manager */ - SegManager(bool sci1_1); + SegManager(ResourceManager *resMgr, SciVersion version, bool oldScriptHeader); /** * Deallocate all memory associated with the segment manager @@ -61,14 +71,12 @@ public: /** * Allocate a script into the segment manager - * @param s The state containing resource manager - * handlers to load the script data * @param script_nr The number of the script to load * @param seg_id The segment ID of the newly allocated segment, * on success * @return 0 on failure, 1 on success */ - Script *allocateScript(EngineState *s, int script_nr, SegmentId *seg_id); + Script *allocateScript(int script_nr, SegmentId *seg_id); // The script must then be initialised; see section (1b.), below. @@ -154,7 +162,7 @@ public: * @returns A newly created Object describing the object, * stored within the relevant script */ - Object *scriptObjInit(EngineState *s, reg_t obj_pos); + Object *scriptObjInit(reg_t obj_pos); /** * Informs the segment manager that a code block must be relocated @@ -317,21 +325,31 @@ public: */ byte *dereference(reg_t reg, int *size); - + /** + * Determines the segment occupied by a certain script + * @param[in] script_id The script in question + * @param[in] load One of SCRIPT_GET_* + * @return The script's segment, or 0 on failure + */ + SegmentId getSegment(int script_nr, SCRIPT_GET load); + reg_t get_class_address(int classnr, SCRIPT_GET lock, reg_t caller); void heapRelocate(reg_t block); void scriptRelocateExportsSci11(SegmentId seg); - void scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg); - int initialiseScript(Script &scr, EngineState *s, int script_nr); + void scriptInitialiseObjectsSci11(SegmentId seg); + int initialiseScript(Script &scr, int script_nr); 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; int exports_wide; - bool isSci1_1; + SciVersion _version; + ResourceManager *_resMgr; + Common::Array<Class> _classtable; /**< Table of all classes */ SegmentId Clones_seg_id; ///< ID of the (a) clones segment SegmentId Lists_seg_id; ///< ID of the (a) list segment @@ -343,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 *); @@ -351,9 +371,9 @@ private: int relocateObject(Object *obj, SegmentId segment, int location); int findFreeId(int *id); - static void setScriptSize(Script &scr, EngineState *s, int script_nr); - Object *scriptObjInit0(EngineState *s, reg_t obj_pos); - Object *scriptObjInit11(EngineState *s, reg_t obj_pos); + void setScriptSize(Script &scr, int script_nr); + Object *scriptObjInit0(reg_t obj_pos); + Object *scriptObjInit11(reg_t obj_pos); /** * Check segment validity diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index fd45ef5834..baa51bcb58 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -24,6 +24,8 @@ */ #include "sci/engine/state.h" +#include "sci/engine/vm.h" +#include "sci/console.h" // For parse_reg_t namespace Sci { @@ -116,6 +118,8 @@ EngineState::EngineState(ResourceManager *res, SciVersion version, uint32 flags) successor = 0; speedThrottler = new SpeedThrottler(version); + + _doSoundType = kDoSoundTypeUnknown; } EngineState::~EngineState() { @@ -242,4 +246,75 @@ Common::String EngineState::strSplit(const char *str, const char *sep) { return retval; } +EngineState::DoSoundType EngineState::detectDoSoundType() { + if (_doSoundType == kDoSoundTypeUnknown) { + reg_t soundClass; + const uint checkBytes = 6; // Number of bytes to check + + if (!parse_reg_t(this, "?Sound", &soundClass)) { + reg_t fptr; + + Object *obj = obj_get(seg_manager, _version, soundClass); + SelectorType sel = lookup_selector(this, soundClass, ((SciEngine*)g_engine)->getKernel()->_selectorMap.play, NULL, &fptr); + + if (obj && (sel == kSelectorMethod)) { + Script *script = seg_manager->getScript(fptr.segment); + + if (fptr.offset > checkBytes) { + // Go to the last portion of Sound::init, should be right before the play function + fptr.offset -= checkBytes; + byte *buf = script->buf + fptr.offset; + + // Check the call to DoSound's INIT_HANDLE function. + // It's either subfunction 0, 5 or 6, depending on the version of DoSound. + uint sum = 0; + for (uint i = 0; i < checkBytes; i++) + sum += buf[i]; + + switch(sum) { + case 0x1B2: // SCI0 + case 0x1AE: // SCI01 + _doSoundType = kDoSoundTypeSci0; + break; + case 0x13D: + _doSoundType = kDoSoundTypeSci1Early; + break; + case 0x13E: + _doSoundType = kDoSoundTypeSci1Late; + } + } + } + } + + if (_doSoundType == kDoSoundTypeUnknown) { + warning("DoSound detection failed, taking an educated guess"); + + if (_version >= SCI_VERSION_1_MIDDLE) + _doSoundType = kDoSoundTypeSci1Late; + else if (_version > SCI_VERSION_01) + _doSoundType = kDoSoundTypeSci1Early; + else + _doSoundType = kDoSoundTypeSci0; + } + + debugCN(1, kDebugLevelSound, "Detected DoSound type: "); + + switch(_doSoundType) { + case kDoSoundTypeSci0: + debugC(1, kDebugLevelSound, "SCI0"); + break; + case kDoSoundTypeSci1Early: + debugC(1, kDebugLevelSound, "SCI1 Early"); + break; + case kDoSoundTypeSci1Late: + debugC(1, kDebugLevelSound, "SCI1 Late"); + break; + default: + break; + } + } + + return _doSoundType; +} + } // End of namespace Sci diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 39dcbb0c0b..a3983f6ae4 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -163,6 +163,14 @@ struct EngineState : public Common::Serializable { public: EngineState(ResourceManager *res, SciVersion version, uint32 flags); virtual ~EngineState(); + + enum DoSoundType { + kDoSoundTypeUnknown, + kDoSoundTypeSci0, + kDoSoundTypeSci1Early, + kDoSoundTypeSci1Late + }; + virtual void saveLoadWithSerializer(Common::Serializer &ser); kLanguage getLanguage(); @@ -272,6 +280,12 @@ public: */ Common::String strSplit(const char *str, const char *sep = "\r----------\r"); + /** + * Autodetects the DoSound type + * @return DoSound type + */ + DoSoundType detectDoSoundType(); + /* Debugger data: */ Breakpoint *bp_list; /**< List of breakpoints */ int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */ @@ -291,8 +305,6 @@ public: reg_t game_obj; /**< Pointer to the game object */ - Common::Array<Class> _classtable; /**< Table of all classes */ - SegManager *seg_manager; int gc_countdown; /**< Number of kernel calls until next gc */ @@ -303,6 +315,7 @@ public: EngineState *successor; /**< Successor of this state: Used for restoring */ private: + DoSoundType _doSoundType; kLanguage charToLanguage(const char c) const; Common::String getLanguageString(const char *str, kLanguage lang) const; }; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index ae07c314d4..64ee7243fb 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -187,34 +187,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define OBJ_PROPERTY(o, p) (validate_property(o, p)) -reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller) { - - if (NULL == s) { - warning("vm.c: get_class_address(): NULL passed for \"s\""); - return NULL_REG; - } - - if (classnr < 0 || (int)s->_classtable.size() <= classnr || s->_classtable[classnr].script < 0) { - error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, s->_classtable.size()); - return NULL_REG; - } else { - Class *the_class = &s->_classtable[classnr]; - if (!the_class->reg.segment) { - script_get_segment(s, the_class->script, lock); - - if (!the_class->reg.segment) { - error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;" - " Entering debugger.", classnr, the_class->script, the_class->script); - return NULL_REG; - } - } else - if (caller.segment != the_class->reg.segment) - s->seg_manager->getScript(the_class->reg.segment)->incrementLockers(); - - return the_class->reg; - } -} - // Operating on the stack // 16 bit: #define PUSH(v) PUSH32(make_reg(0, v)) @@ -236,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, script); + seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader(), script); else scr->unmarkDeleted(); @@ -313,7 +285,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt Breakpoint *bp; char method_name [256]; - sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str()); + sprintf(method_name, "%s::%s", obj_get_name(s->seg_manager, s->_version, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str()); bp = s->bp_list; while (bp) { @@ -501,10 +473,6 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file) { error("Fatal VM error in %s, L%d; aborting...", file, line); } -static Script *script_locate_by_segment(EngineState *s, SegmentId seg) { - return s->seg_manager->getScriptIfLoaded(seg); -} - static reg_t pointer_add(EngineState *s, reg_t base, int offset) { MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, base.segment); @@ -559,8 +527,8 @@ void run_vm(EngineState *s, int restoring) { // Current execution data: scriptState.xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; - Object *obj = obj_get(s, scriptState.xs->objp); - Script *local_script = script_locate_by_segment(s, scriptState.xs->local_segment); + Object *obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp); + Script *local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment); int old_execution_stack_base = s->execution_stack_base; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) @@ -606,7 +574,7 @@ void run_vm(EngineState *s, int restoring) { scriptState.xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; - scr = script_locate_by_segment(s, scriptState.xs->addr.pc.segment); + scr = s->seg_manager->getScriptIfLoaded(scriptState.xs->addr.pc.segment); if (!scr) { // No script? Implicit return via fake instruction buffer warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment); @@ -619,12 +587,12 @@ void run_vm(EngineState *s, int restoring) { scr = NULL; obj = NULL; } else { - obj = obj_get(s, scriptState.xs->objp); + obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp); code_buf = scr->buf; #ifndef DISABLE_VALIDATIONS code_buf_size = scr->buf_size; #endif - local_script = script_locate_by_segment(s, scriptState.xs->local_segment); + local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment); if (!local_script) { warning("Could not find local script from segment %x", scriptState.xs->local_segment); local_script = NULL; @@ -1077,7 +1045,7 @@ void run_vm(EngineState *s, int restoring) { break; case 0x28: // class - s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, + s->r_acc = s->seg_manager->get_class_address((unsigned)opparams[0], SCRIPT_GET_LOCK, scriptState.xs->addr.pc); break; @@ -1097,7 +1065,7 @@ void run_vm(EngineState *s, int restoring) { break; case 0x2b: // super - r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc); + r_temp = s->seg_manager->get_class_address(opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc); if (!r_temp.segment) error("[VM]: Invalid superclass in object"); @@ -1432,6 +1400,7 @@ void run_vm(EngineState *s, int restoring) { static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) { // Determines if obj explicitly defines slc as a varselector // Returns -1 if not found + SciVersion version = s->_version; // for the selector defines if (s->_version < SCI_VERSION_1_1) { int varnum = obj->variable_names_nr; @@ -1452,7 +1421,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) { int varnum = obj->_variables[1].offset; if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) - buf = ((byte *) obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars); + buf = ((byte *) obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars); for (i = 0; i < varnum; i++) if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it? @@ -1478,6 +1447,7 @@ static int _class_locate_funcselector(EngineState *s, Object *obj, Selector slc) static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) { int index; + SciVersion version = s->_version; // for the selector defines // "recursive" lookup @@ -1492,7 +1462,7 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object return kSelectorMethod; } else { seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment; - obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + obj = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); } } @@ -1500,9 +1470,10 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object } SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) { - Object *obj = obj_get(s, obj_location); + Object *obj = obj_get(s->seg_manager, s->_version, obj_location); Object *species; int index; + SciVersion version = s->_version; // for the selector defines // Early SCI versions used the LSB in the selector ID as a read/write // toggle, meaning that we must remove it for selector lookup. @@ -1517,7 +1488,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select if (IS_CLASS(obj)) species = obj; else - species = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]); + species = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SPECIES_SELECTOR]); if (!obj) { @@ -1540,65 +1511,27 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr); } -SegmentId script_get_segment(EngineState *s, int script_nr, SCRIPT_GET load) { - SegmentId segment; - - if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) - script_instantiate(s, script_nr); - - segment = s->seg_manager->segGet(script_nr); - - if (segment > 0) { - if ((load & SCRIPT_GET_LOCK) == SCRIPT_GET_LOCK) - s->seg_manager->getScript(segment)->incrementLockers(); - - return segment; - } else - return 0; +reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_index) { + SegmentId seg = segManager->getSegment(script_nr, SCRIPT_GET_DONT_LOAD); + Script *script = segManager->getScriptIfLoaded(seg); + return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index))); } -reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) { - SegmentId seg = script_get_segment(s, script_nr, SCRIPT_GET_DONT_LOAD); - Script *script = NULL; +#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segManager->get_class_address(id, SCRIPT_GET_LOCK, reg)) -#ifndef DISABLE_VALIDATIONS - if (!seg) - error("script_lookup_export(): script.%03d (0x%x) is invalid or not loaded", - script_nr, script_nr); -#endif - - script = script_locate_by_segment(s, seg); - -#ifndef DISABLE_VALIDATIONS - if (script && export_index < script->exports_nr && export_index >= 0) -#endif - return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index))); -#ifndef DISABLE_VALIDATIONS - else { - if (!script) - error("script_lookup_export(): script.%03d missing", script_nr); - else - error("script_lookup_export(): script.%03d: Sought invalid export %d/%d", - script_nr, export_index, script->exports_nr); - } -#endif -} - -#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, reg)) - -int script_instantiate_common(EngineState *s, int script_nr, Resource **script, Resource **heap, int *was_new) { +int script_instantiate_common(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr, Resource **script, Resource **heap, int *was_new) { int seg_id; reg_t reg; *was_new = 1; - *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - if (s->_version >= SCI_VERSION_1_1) - *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); + *script = resMgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); + if (version >= SCI_VERSION_1_1) + *heap = resMgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); - if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) { + if (!*script || (version >= SCI_VERSION_1_1 && !heap)) { warning("Script 0x%x requested but not found", script_nr); - if (s->_version >= SCI_VERSION_1_1) { + if (version >= SCI_VERSION_1_1) { if (*heap) warning("Inconsistency: heap resource WAS found"); else if (*script) @@ -1607,13 +1540,8 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, return 0; } - if (NULL == s) { - warning("script_instantiate_common(): script_instantiate(): NULL passed for \"s\""); - return 0; - } - - seg_id = s->seg_manager->segGet(script_nr); - Script *scr = script_locate_by_segment(s, seg_id); + seg_id = segManager->segGet(script_nr); + Script *scr = segManager->getScriptIfLoaded(seg_id); if (scr) { if (!scr->isMarkedAsDeleted()) { scr->incrementLockers(); @@ -1622,14 +1550,14 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, scr->freeScript(); } } else { - scr = s->seg_manager->allocateScript(s, script_nr, &seg_id); + scr = segManager->allocateScript(script_nr, &seg_id); if (!scr) { // ALL YOUR SCRIPT BASE ARE BELONG TO US error("Not enough heap space for script size 0x%x of script 0x%x (Should this happen?)", (*script)->size, script_nr); return 0; } } - s->seg_manager->initialiseScript(*scr, s, script_nr); + segManager->initialiseScript(*scr, script_nr); reg.segment = seg_id; reg.offset = 0; @@ -1645,7 +1573,7 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, return seg_id; } -int script_instantiate_sci0(EngineState *s, 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; @@ -1655,7 +1583,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { Resource *script; int was_new; - seg_id = script_instantiate_common(s, script_nr, &script, NULL, &was_new); + seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, NULL, &was_new); if (was_new) return seg_id; @@ -1663,9 +1591,9 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { reg.segment = seg_id; reg.offset = 0; - Script *scr = s->seg_manager->getScript(seg_id); + Script *scr = segManager->getScript(seg_id); - if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { + if (oldScriptHeader) { // int locals_nr = READ_LE_UINT16(script->data); @@ -1678,7 +1606,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { magic_pos_adder = 2; // Step over the funny prefix if (locals_nr) - s->seg_manager->scriptInitialiseLocalsZero(reg.segment, locals_nr); + segManager->scriptInitialiseLocalsZero(reg.segment, locals_nr); } else { scr->mcpyInOut(0, script->data, script->size); @@ -1717,24 +1645,24 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { break; case SCI_OBJ_LOCALVARS: - s->seg_manager->scriptInitialiseLocals(data_base); + segManager->scriptInitialiseLocals(data_base); break; case SCI_OBJ_CLASS: { int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET; int species; species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET); - if (species < 0 || species >= (int)s->_classtable.size()) { + if (species < 0 || species >= (int)segManager->_classtable.size()) { error("Invalid species %d(0x%x) not in interval " "[0,%d) while instantiating script %d\n", - species, species, s->_classtable.size(), + species, species, segManager->_classtable.size(), script_nr); return 1; } - s->_classtable[species].script = script_nr; - s->_classtable[species].reg = addr; - s->_classtable[species].reg.offset = classpos; + segManager->_classtable[species].script = script_nr; + segManager->_classtable[species].reg = addr; + segManager->_classtable[species].reg.offset = classpos; // Set technical class position-- into the block allocated for it } break; @@ -1760,17 +1688,17 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { switch (objtype) { case SCI_OBJ_CODE: - s->seg_manager->scriptAddCodeBlock(addr); + segManager->scriptAddCodeBlock(addr); break; case SCI_OBJ_OBJECT: case SCI_OBJ_CLASS: { // object or class? - Object *obj = s->seg_manager->scriptObjInit(s, addr); + Object *obj = segManager->scriptObjInit(addr); Object *base_obj; // Instantiate the superclass, if neccessary obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset); - base_obj = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = obj_get(segManager, version, obj->_variables[SCRIPT_SPECIES_SELECTOR]); obj->variable_names_nr = base_obj->_variables.size(); obj->base_obj = base_obj->base_obj; // Copy base from species class, as we need its selector IDs @@ -1791,24 +1719,24 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { } while ((objtype != 0) && (((unsigned)reg.offset) < script->size - 2)); if (relocation >= 0) - s->seg_manager->scriptRelocate(make_reg(reg.segment, relocation)); + segManager->scriptRelocate(make_reg(reg.segment, relocation)); return reg.segment; // instantiation successful } -int script_instantiate_sci11(EngineState *s, int script_nr) { +int script_instantiate_sci11(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) { Resource *script, *heap; int seg_id; int heap_start; reg_t reg; int was_new; - seg_id = script_instantiate_common(s, script_nr, &script, &heap, &was_new); + seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, &heap, &was_new); if (was_new) return seg_id; - Script *scr = s->seg_manager->getScript(seg_id); + Script *scr = segManager->getScript(seg_id); heap_start = script->size; if (script->size & 2) @@ -1822,28 +1750,28 @@ int script_instantiate_sci11(EngineState *s, int script_nr) { reg.segment = seg_id; reg.offset = heap_start + 4; - s->seg_manager->scriptInitialiseLocals(reg); + segManager->scriptInitialiseLocals(reg); - s->seg_manager->scriptRelocateExportsSci11(seg_id); - s->seg_manager->scriptInitialiseObjectsSci11(s, seg_id); + segManager->scriptRelocateExportsSci11(seg_id); + segManager->scriptInitialiseObjectsSci11(seg_id); reg.offset = READ_LE_UINT16(heap->data); - s->seg_manager->heapRelocate(reg); + segManager->heapRelocate(reg); return seg_id; } -int script_instantiate(EngineState *s, int script_nr) { - if (s->_version >= SCI_VERSION_1_1) - return script_instantiate_sci11(s, 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(s, script_nr); + return script_instantiate_sci0(resMgr, segManager, version, oldScriptHeader, script_nr); } -void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { +void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int script_nr, SegmentId seg) { reg_t reg = make_reg(seg, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0); int objtype, objlength; - Script *scr = s->seg_manager->getScript(seg); + Script *scr = segManager->getScript(seg); // Make a pass over the object in order uninstantiate all superclasses objlength = 0; @@ -1866,13 +1794,13 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass... if (superclass >= 0) { - int superclass_script = s->_classtable[superclass].script; + int superclass_script = segManager->_classtable[superclass].script; if (superclass_script == script_nr) { if (scr->getLockers()) scr->decrementLockers(); // Decrease lockers if this is us ourselves } else - script_uninstantiate(s, superclass_script); + script_uninstantiate(segManager, version, superclass_script); // Recurse to assure that the superclass lockers number gets decreased } @@ -1884,11 +1812,9 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { } while (objtype != 0); } -void script_uninstantiate(EngineState *s, int script_nr) { - reg_t reg = make_reg(0, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0); - - reg.segment = s->seg_manager->segGet(script_nr); - Script *scr = script_locate_by_segment(s, reg.segment); +void script_uninstantiate(SegManager *segManager, SciVersion version, int script_nr) { + SegmentId segment = segManager->segGet(script_nr); + Script *scr = segManager->getScriptIfLoaded(segment); if (!scr) { // Is it already loaded? //warning("unloading script 0x%x requested although not loaded", script_nr); @@ -1902,12 +1828,12 @@ void script_uninstantiate(EngineState *s, int script_nr) { return; // Free all classtable references to this script - for (uint i = 0; i < s->_classtable.size(); i++) - if (s->_classtable[i].reg.segment == reg.segment) - s->_classtable[i].reg = NULL_REG; + for (uint i = 0; i < segManager->_classtable.size(); i++) + if (segManager->_classtable[i].reg.segment == segment) + segManager->_classtable[i].reg = NULL_REG; - if (s->_version < SCI_VERSION_1_1) - script_uninstantiate_sci0(s, script_nr, reg.segment); + if (version < SCI_VERSION_1_1) + script_uninstantiate_sci0(segManager, version, script_nr, segment); else warning("FIXME: Add proper script uninstantiation for SCI 1.1"); @@ -1999,8 +1925,8 @@ int game_run(EngineState **_s) { return 0; } -Object *obj_get(EngineState *s, reg_t offset) { - MemObject *mobj = GET_OBJECT_SEGMENT(*s->seg_manager, offset.segment); +Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset) { + MemObject *mobj = GET_OBJECT_SEGMENT(*segManager, offset.segment); Object *obj = NULL; int idx; @@ -2023,8 +1949,8 @@ Object *obj_get(EngineState *s, reg_t offset) { return obj; } -const char *obj_get_name(EngineState *s, reg_t pos) { - Object *obj = obj_get(s, pos); +const char *obj_get_name(SegManager *segManager, SciVersion version, reg_t pos) { + Object *obj = obj_get(segManager, version, pos); if (!obj) return "<no such object>"; @@ -2032,7 +1958,7 @@ const char *obj_get_name(EngineState *s, reg_t pos) { if (nameReg.isNull()) return "<no name>"; - const char *name = (const char*)s->seg_manager->dereference(obj->_variables[SCRIPT_NAME_SELECTOR], NULL); + const char *name = (const char*)segManager->dereference(obj->_variables[SCRIPT_NAME_SELECTOR], NULL); if (!name) return "<invalid name>"; @@ -2056,7 +1982,7 @@ void shrink_execution_stack(EngineState *s, uint size) { } reg_t* ObjVarRef::getPointer(EngineState *s) const { - Object *o = obj_get(s, obj); + Object *o = obj_get(s->seg_manager, s->_version, obj); if (!o) return 0; return &(o->_variables[varindex]); } diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index ba225a9c00..867f732e2a 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -29,6 +29,7 @@ /* VM and kernel declarations */ #include "sci/engine/vm_types.h" // for reg_t +#include "sci/resource.h" // for SciVersion #include "common/util.h" @@ -39,6 +40,7 @@ struct EngineState; typedef int sci_version_t; struct IntMapper; struct Object; +class ResourceManager; /** Number of bytes to be allocated for the stack */ #define VM_STACK_SIZE 0x1000 @@ -67,12 +69,12 @@ struct Object; #define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8 /** Offset of the name pointer */ -#define SCRIPT_NAME_OFFSET (s->_version < SCI_VERSION_1_1 ? 14 -8 : 16) -#define SCRIPT_NAME_SELECTOR (s->_version < SCI_VERSION_1_1 ? 3 : 8) +#define SCRIPT_NAME_OFFSET (version < SCI_VERSION_1_1 ? 14 -8 : 16) +#define SCRIPT_NAME_SELECTOR (version < SCI_VERSION_1_1 ? 3 : 8) /** Object-relative offset of the -info- selector */ -#define SCRIPT_INFO_OFFSET (s->_version < SCI_VERSION_1_1 ? 12 -8 : 14) -#define SCRIPT_INFO_SELECTOR (s->_version < SCI_VERSION_1_1 ? 2 : 7) +#define SCRIPT_INFO_OFFSET (version < SCI_VERSION_1_1 ? 12 -8 : 14) +#define SCRIPT_INFO_SELECTOR (version < SCI_VERSION_1_1 ? 2 : 7) /** Flag fo the -info- selector */ #define SCRIPT_INFO_CLONE 0x0001 @@ -84,18 +86,18 @@ struct Object; /** Magical object identifier */ #define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234 /** Offset of this identifier */ -#define SCRIPT_OBJECT_MAGIC_OFFSET (s->_version < SCI_VERSION_1_1 ? -8 : 0) +#define SCRIPT_OBJECT_MAGIC_OFFSET (version < SCI_VERSION_1_1 ? -8 : 0) /** Script-relative offset of the species ID */ #define SCRIPT_SPECIES_OFFSET 8 -8 -#define SCRIPT_SUPERCLASS_OFFSET (s->_version < SCI_VERSION_1_1 ? 10 -8 : 12) +#define SCRIPT_SUPERCLASS_OFFSET (version < SCI_VERSION_1_1 ? 10 -8 : 12) /*---------------------------------*/ /* Script selector index variables */ /*---------------------------------*/ -#define SCRIPT_SPECIES_SELECTOR (s->_version < SCI_VERSION_1_1 ? 0 : 5) -#define SCRIPT_SUPERCLASS_SELECTOR (s->_version < SCI_VERSION_1_1 ? 1 : 6) +#define SCRIPT_SPECIES_SELECTOR (version < SCI_VERSION_1_1 ? 0 : 5) +#define SCRIPT_SUPERCLASS_SELECTOR (version < SCI_VERSION_1_1 ? 1 : 6) #define SCRIPT_CLASSSCRIPT_SELECTOR 4 /** Magic adjustment value for lofsa and lofss */ @@ -467,31 +469,13 @@ SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid, ObjVarRef *varp, reg_t *fptr); /** - * Parameters for script_get_segment() - */ -typedef enum { - SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */ - SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */ - SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */ -} SCRIPT_GET; - -/** - * Determines the segment occupied by a certain script - * @param[in] s The state to operate on - * @param[in] script_id The script in question - * @param[in] load One of SCRIPT_GET_* - * @return The script's segment, or 0 on failure - */ -SegmentId script_get_segment(EngineState *s, int script_id, SCRIPT_GET load); - -/** * Looks up an entry of the exports table of a script - * @param[in] s The state to operate on + * @param[in] segManager The segment manager * @param[in] script_nr The script to look up in * @param[out] export_index The index of the export entry to look up * @return The handle */ -reg_t script_lookup_export(EngineState *s, int script_nr, int export_index); +reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_index); /** * Makes sure that a script and its superclasses get loaded to the heap. @@ -499,21 +483,24 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index); * increased. All scripts containing superclasses of this script are loaded * recursively as well, unless 'recursive' is set to zero. The * complementary function is "script_uninstantiate()" below. - * @param[in] s The state to operate on - * @param[in] script_nr The script number to load - * @return The script's segment ID or 0 if out of heap + * @param[in] resMgr The resource manager + * @param[in] segManager The segment manager + * @param[in] version The SCI version to use + * @param[in] script_nr The script number to load + * @return The script's segment ID or 0 if out of heap */ -int script_instantiate(EngineState *s, 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 * reaches zero. * This function will recursively unload scripts containing its * superclasses, if those aren't locked by other scripts as well. - * @param[in] s The state to operate on + * @param[in] segManager The segment manager + * @param[in] version The SCI version to use * @param[in] script_nr The script number that is requestet to be unloaded */ -void script_uninstantiate(EngineState *s, int script_nr); +void script_uninstantiate(SegManager *segManager, SciVersion version, int script_nr); /** * Initializes an SCI game @@ -613,7 +600,7 @@ int kfree(EngineState *s, reg_t handle); * in a static buffer and need not be freed (neither may * it be modified). */ -const char *obj_get_name(EngineState *s, reg_t pos); +const char *obj_get_name(SegManager *segManager, SciVersion version, reg_t pos); /** * Retrieves an object from the specified location @@ -621,7 +608,7 @@ const char *obj_get_name(EngineState *s, reg_t pos); * @param[in] offset The object's offset * @return The object in question, or NULL if there is none */ -Object *obj_get(EngineState *s, reg_t offset); +Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset); /** * Shrink execution stack to size. |
