[Scummvm-cvs-logs] SF.net SVN: scummvm:[43824] scummvm/trunk/engines/sci
waltervn at users.sourceforge.net
waltervn at users.sourceforge.net
Sun Aug 30 16:53:58 CEST 2009
Revision: 43824
http://scummvm.svn.sourceforge.net/scummvm/?rev=43824&view=rev
Author: waltervn
Date: 2009-08-30 14:53:58 +0000 (Sun, 30 Aug 2009)
Log Message:
-----------
SCI: Add lofs detection.
Modified Paths:
--------------
scummvm/trunk/engines/sci/engine/game.cpp
scummvm/trunk/engines/sci/engine/kernel.cpp
scummvm/trunk/engines/sci/engine/kernel.h
scummvm/trunk/engines/sci/engine/script.cpp
scummvm/trunk/engines/sci/engine/script.h
scummvm/trunk/engines/sci/engine/state.cpp
scummvm/trunk/engines/sci/engine/state.h
scummvm/trunk/engines/sci/engine/static_selectors.cpp
scummvm/trunk/engines/sci/engine/vm.cpp
scummvm/trunk/engines/sci/engine/vm.h
scummvm/trunk/engines/sci/sci.cpp
Modified: scummvm/trunk/engines/sci/engine/game.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/game.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/game.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -226,7 +226,7 @@
s->bp_list = NULL; // No breakpoints defined
s->have_bp = 0;
- if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
+ if (s->detectLofsType() == SCI_VERSION_1_MIDDLE)
s->segmentManager->setExportWidth(1);
else
s->segmentManager->setExportWidth(0);
Modified: scummvm/trunk/engines/sci/engine/kernel.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/kernel.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -401,16 +401,6 @@
features |= kFeatureOldGfxFunctions;
}
- // 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 (_selectorMap.egoMoveSpeed != -1)
- features |= kFeatureLofsAbsolute;
- }
-
printf("Kernel auto-detected features:\n");
printf("Graphics functions: ");
@@ -418,14 +408,6 @@
printf("old\n");
else
printf("new\n");
-
- if (version < SCI_VERSION_1_1) {
- printf("lofs parameters: ");
- if (features & kFeatureLofsAbsolute)
- printf("absolute\n");
- else
- printf("relative\n");
- }
}
void Kernel::loadSelectorNames() {
Modified: scummvm/trunk/engines/sci/engine/kernel.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.h 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/kernel.h 2009-08-30 14:53:58 UTC (rev 43824)
@@ -54,8 +54,7 @@
enum AutoDetectedFeatures {
kFeatureOldScriptHeader = 1 << 0,
- kFeatureOldGfxFunctions = 1 << 1,
- kFeatureLofsAbsolute = 1 << 2
+ kFeatureOldGfxFunctions = 1 << 1
};
class Kernel {
@@ -95,13 +94,6 @@
*/
bool usesOldGfxFunctions() const { return (features & kFeatureOldGfxFunctions); }
- /**
- * Applies to all SCI1 versions after 1.000.200
- * In late SCI1 versions, the argument of lofs[as] instructions
- * is absolute rather than relative.
- */
- bool hasLofsAbsolute() const { return (features & kFeatureLofsAbsolute); }
-
// Script dissection/dumping functions
void dissectScript(int scriptNumber, Vocabulary *vocab);
void dumpScriptObject(char *data, int seeker, int objsize);
Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/script.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -88,14 +88,16 @@
};
#undef END
-void script_adjust_opcode_formats(SciVersion version) {
+void script_adjust_opcode_formats(EngineState *s) {
// TODO: Check that this is correct
- if ((version >= SCI_VERSION_1_1) || ((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) {
+ if (s->detectLofsType() != SCI_VERSION_0_EARLY) {
g_opcode_formats[op_lofsa][0] = Script_Offset;
g_opcode_formats[op_lofss][0] = Script_Offset;
}
-
+
#ifdef ENABLE_SCI32
+ SciVersion version = s->resourceManager->sciVersion();
+
// In SCI32, some arguments are now words instead of bytes
if (version >= SCI_VERSION_2) {
g_opcode_formats[op_calle][2] = Script_Word;
@@ -240,7 +242,6 @@
FIND_SELECTOR(subtitleLang);
FIND_SELECTOR(parseLang);
FIND_SELECTOR(motionCue);
- FIND_SELECTOR(egoMoveSpeed);
FIND_SELECTOR(setCursor);
}
Modified: scummvm/trunk/engines/sci/engine/script.h
===================================================================
--- scummvm/trunk/engines/sci/engine/script.h 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/script.h 2009-08-30 14:53:58 UTC (rev 43824)
@@ -202,7 +202,7 @@
extern opcode_format g_opcode_formats[128][4];
-void script_adjust_opcode_formats(SciVersion version);
+void script_adjust_opcode_formats(EngineState *s);
void script_free_breakpoints(EngineState *s);
Modified: scummvm/trunk/engines/sci/engine/state.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/state.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/state.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -25,6 +25,7 @@
#include "sci/engine/state.h"
#include "sci/engine/vm.h"
+#include "sci/engine/script.h"
#include "sci/console.h" // For parse_reg_t
namespace Sci {
@@ -121,6 +122,7 @@
_setCursorType = SCI_VERSION_AUTODETECT;
_doSoundType = SCI_VERSION_AUTODETECT;
+ _lofsType = SCI_VERSION_AUTODETECT;
}
EngineState::~EngineState() {
@@ -334,10 +336,133 @@
_setCursorType = SCI_VERSION_0_EARLY;
}
- debugC(0, kDebugLevelGraphics, "Detected SetCursor type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_setCursorType).c_str());
+ debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_setCursorType).c_str());
}
return _setCursorType;
}
+SciVersion EngineState::detectLofsType() {
+ if (_lofsType == SCI_VERSION_AUTODETECT) {
+ SciVersion version = segmentManager->sciVersion(); // FIXME: for VM_OBJECT_READ_FUNCTION
+
+ // This detection only works (and is only needed) pre-SCI1.1
+ if (version >= SCI_VERSION_1_1) {
+ _lofsType = SCI_VERSION_1_1;
+ return _lofsType;
+ }
+
+ reg_t gameClass;
+ Object *obj = NULL;
+
+ if (!parse_reg_t(this, "?Game", &gameClass))
+ obj = obj_get(segmentManager, gameClass);
+
+ bool couldBeAbs = true;
+ bool couldBeRel = true;
+
+ // Check methods of the Game class for lofs operations
+ if (obj) {
+ for (int m = 0; m < obj->methods_nr; m++) {
+ reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, m);
+
+ Script *script = segmentManager->getScript(fptr.segment);
+
+ if ((script == NULL) || (script->buf == NULL))
+ continue;
+
+ uint offset = fptr.offset;
+ bool done = false;
+
+ while (!done) {
+ // Read opcode
+ if (offset >= script->buf_size)
+ break;
+
+ byte opcode = script->buf[offset++];
+ byte opnumber = opcode >> 1;
+
+ if ((opnumber == 0x39) || (opnumber == 0x3a)) {
+ uint16 lofs;
+
+ // Load lofs operand
+ if (opcode & 1) {
+ if (offset >= script->buf_size)
+ break;
+ lofs = script->buf[offset++];
+ } else {
+ if (offset + 1 >= script->buf_size)
+ break;
+ lofs = READ_LE_UINT16(script->buf + offset);
+ offset += 2;
+ }
+
+ // Check for going out of bounds when interpreting as abs/rel
+ if (lofs >= script->buf_size)
+ couldBeAbs = false;
+
+ if ((signed)offset + (int16)lofs < 0)
+ couldBeRel = false;
+
+ if ((signed)offset + (int16)lofs >= (signed)script->buf_size)
+ couldBeRel = false;
+
+ continue;
+ }
+
+ // Skip operands for non-lofs opcodes
+ for (int i = 0; g_opcode_formats[opnumber][i]; i++) {
+ switch (g_opcode_formats[opnumber][i]) {
+ case Script_Byte:
+ case Script_SByte:
+ offset++;
+ break;
+ case Script_Word:
+ case Script_SWord:
+ offset += 2;
+ break;
+ case Script_Variable:
+ case Script_Property:
+ case Script_Local:
+ case Script_Temp:
+ case Script_Global:
+ case Script_Param:
+ case Script_SVariable:
+ case Script_SRelative:
+ case Script_Offset:
+ offset++;
+ if (!(opcode & 1))
+ offset++;
+ break;
+ case Script_End:
+ done = true;
+ break;
+ case Script_Invalid:
+ default:
+ warning("opcode %02x: Invalid", opcode);
+ }
+ }
+ }
+ }
+ }
+
+ if (couldBeRel == couldBeAbs) {
+ warning("Lofs detection failed, taking an educated guess");
+
+ if (version >= SCI_VERSION_1_MIDDLE)
+ _lofsType = SCI_VERSION_1_MIDDLE;
+
+ _lofsType = SCI_VERSION_0_EARLY;
+ } else if (couldBeAbs) {
+ _lofsType = SCI_VERSION_1_MIDDLE;
+ } else {
+ _lofsType = SCI_VERSION_0_EARLY;
+ }
+
+ debugC(1, kDebugLevelVM, "Detected Lofs type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_lofsType).c_str());
+ }
+
+ return _lofsType;
+}
+
} // End of namespace Sci
Modified: scummvm/trunk/engines/sci/engine/state.h
===================================================================
--- scummvm/trunk/engines/sci/engine/state.h 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/state.h 2009-08-30 14:53:58 UTC (rev 43824)
@@ -274,16 +274,22 @@
/**
* Autodetects the DoSound type
- * @return DoSound type
+ * @return DoSound type, SCI_VERSION_0_EARLY / SCI_VERSION_1_EARLY / SCI_VERSION_1_LATE
*/
SciVersion detectDoSoundType();
/**
* Autodetects the SetCursor type
- * @return SetCursor type
+ * @return SetCursor type, SCI_VERSION_0_EARLY / SCI_VERSION_1_1
*/
SciVersion detectSetCursorType();
+ /**
+ * Autodetects the Lofs type
+ * @return Lofs type, SCI_VERSION_0_EARLY / SCI_VERSION_1_MIDDLE / SCI_VERSION_1_1
+ */
+ SciVersion detectLofsType();
+
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -314,7 +320,7 @@
Common::String getLanguageString(const char *str, kLanguage lang) const;
private:
- SciVersion _doSoundType, _setCursorType;
+ SciVersion _doSoundType, _setCursorType, _lofsType;
kLanguage charToLanguage(const char c) const;
int methodChecksum(reg_t objAddress, Selector sel, int offset, uint size) const;
};
Modified: scummvm/trunk/engines/sci/engine/static_selectors.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/static_selectors.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/static_selectors.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -120,7 +120,7 @@
{ "cue", 136 }, { "owner", 150 }, { "setVol", 156 },
{ "completed", 210 }, { "motionCue", 213 }, { "cycler", 215 },
{ "setTarget", 221 }, { "distance", 224 }, { "canBeHere", 232 },
- { "syncTime", 247 }, { "syncCue", 248 }, { "egoMoveSpeed", 370 }
+ { "syncTime", 247 }, { "syncCue", 248 }
};
// Taken from Space Quest 1 VGA (Demo)
@@ -133,7 +133,7 @@
{ "moveDone", 100 }, { "init", 103 }, { "dispose", 104 },
{ "caller", 133 }, { "cue", 135 }, { "owner", 149 },
{ "flags", 150 }, { "completed", 207 }, { "motionCue", 210 },
- { "cycler", 212 }, { "distance", 221 }, { "egoMoveSpeed", 357 }
+ { "cycler", 212 }, { "distance", 221 }
};
// A macro for loading one of the above tables in the function below
Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/vm.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -1160,13 +1160,15 @@
case 0x39: // lofsa
s->r_acc.segment = scriptState.xs->addr.pc.segment;
- if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {
+ switch (s->detectLofsType()) {
+ case SCI_VERSION_1_1:
s->r_acc.offset = opparams[0] + local_script->script_size;
- } else {
- if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
- s->r_acc.offset = opparams[0];
- else
- s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0];
+ break;
+ case SCI_VERSION_1_MIDDLE:
+ s->r_acc.offset = opparams[0];
+ break;
+ default:
+ s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0];
}
#ifndef DISABLE_VALIDATIONS
@@ -1180,13 +1182,15 @@
case 0x3a: // lofss
r_temp.segment = scriptState.xs->addr.pc.segment;
- if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {
+ switch (s->detectLofsType()) {
+ case SCI_VERSION_1_1:
r_temp.offset = opparams[0] + local_script->script_size;
- } else {
- if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
- r_temp.offset = opparams[0];
- else
- r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0];
+ break;
+ case SCI_VERSION_1_MIDDLE:
+ r_temp.offset = opparams[0];
+ break;
+ default:
+ r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0];
}
#ifndef DISABLE_VALIDATIONS
Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/vm.h 2009-08-30 14:53:58 UTC (rev 43824)
@@ -190,7 +190,6 @@
Selector flags;
Selector motionCue; /**< Used to determine if a game is using old gfx functions or not */
- Selector egoMoveSpeed; /**< Used to determine if a game is using absolute lofs parameters */
Selector points; /**< Used by AvoidPath() */
Modified: scummvm/trunk/engines/sci/sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sci.cpp 2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/sci.cpp 2009-08-30 14:53:58 UTC (rev 43824)
@@ -136,7 +136,6 @@
_kernel = new Kernel(_resourceManager);
_vocabulary = new Vocabulary(_resourceManager);
- script_adjust_opcode_formats(_resourceManager->sciVersion());
_gamestate = new EngineState(_resourceManager, flags);
@@ -149,6 +148,8 @@
return Common::kUnknownError;
}
+ script_adjust_opcode_formats(_gamestate);
+
// Set the savegame dir (actually, we set it to a fake value,
// since we cannot let the game control where saves are stored)
script_set_gamestate_save_dir(_gamestate, "/");
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list