Skip to content

Commit

Permalink
SCI: Cleanup of the save/load dialog patching code and the lofs type …
Browse files Browse the repository at this point in the history
…detection code
  • Loading branch information
bluegr committed Feb 27, 2011
1 parent d90c7a8 commit 4d33923
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 68 deletions.
20 changes: 8 additions & 12 deletions engines/sci/engine/features.cpp
Expand Up @@ -285,20 +285,16 @@ SciVersion GameFeatures::detectLofsType() {
}

// Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss
reg_t gameSuperClass = g_sci->getGameSuperClassAddress();
const Object *gameObject = _segMan->getObject(g_sci->getGameObject());
const Object *gameSuperObject = _segMan->getObject(gameObject->getSuperClassSelector());
bool found = false;
if (!gameSuperClass.isNull()) {
Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
const Object *gameSuperObject = _segMan->getObject(gameSuperClass);
if (gameSuperObject) {
Common::String gameSuperClassName = _segMan->getObjectName(gameObject->getSuperClassSelector());

if (gameSuperObject) {
for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
found = autoDetectLofsType(gameSuperClassName, m);
if (found)
break;
}
} else {
warning("detectLofsType(): Could not get superclass object");
for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
found = autoDetectLofsType(gameSuperClassName, m);
if (found)
break;
}
} else {
warning("detectLofsType(): Could not find superclass of game object");
Expand Down
81 changes: 27 additions & 54 deletions engines/sci/sci.cpp
Expand Up @@ -213,7 +213,6 @@ Common::Error SciEngine::run() {
// Add the after market GM patches for the specified game, if they exist
_resMan->addNewGMPatch(_gameId);
_gameObjectAddress = _resMan->findGameObject();
_gameSuperClassAddress = NULL_REG;

SegManager *segMan = new SegManager(_resMan);

Expand Down Expand Up @@ -250,7 +249,6 @@ Common::Error SciEngine::run() {
warning("Could not get game object, aborting...");
return Common::kUnknownError;
}
_gameSuperClassAddress = gameObject->getSuperClassSelector();

script_adjust_opcode_formats();

Expand Down Expand Up @@ -441,19 +439,24 @@ static byte patchGameRestoreSaveSci2[] = {
0x48, // ret
};

static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
Script *script = segMan->getScript(methodAddress.segment);
byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.offset));
if (getSciVersion() <= SCI_VERSION_1_1)
memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
else if (getSciVersion() == SCI_VERSION_2)
memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
// TODO: SCI21/SCI3
patchPtr[8] = id;
}

void SciEngine::patchGameSaveRestore() {
SegManager *segMan = _gamestate->_segMan;
const Object *gameObject = segMan->getObject(_gameObjectAddress);
const uint16 gameMethodCount = gameObject->getMethodCount();
const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress);
const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector());
if (!gameSuperObject)
gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510
const uint16 gameSuperMethodCount = gameSuperObject->getMethodCount();
reg_t methodAddress;
const uint16 kernelCount = _kernel->getKernelNamesSize();
const byte *scriptRestorePtr = NULL;
byte kernelIdRestore = 0;
const byte *scriptSavePtr = NULL;
byte kernelIdSave = 0;

// This feature is currently not supported in SCI21 or SCI3
Expand All @@ -473,69 +476,39 @@ void SciEngine::patchGameSaveRestore() {
if (ConfMan.getBool("sci_originalsaveload"))
return;

for (uint16 kernelNr = 0; kernelNr < kernelCount; kernelNr++) {
uint16 kernelNamesSize = _kernel->getKernelNamesSize();
for (uint16 kernelNr = 0; kernelNr < kernelNamesSize; kernelNr++) {
Common::String kernelName = _kernel->getKernelName(kernelNr);
if (kernelName == "RestoreGame")
kernelIdRestore = kernelNr;
if (kernelName == "SaveGame")
kernelIdSave = kernelNr;
}

// Search for gameobject-superclass ::restore
for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; methodNr++) {
// Search for gameobject superclass ::restore
uint16 gameSuperObjectMethodCount = gameSuperObject->getMethodCount();
for (uint16 methodNr = 0; methodNr < gameSuperObjectMethodCount; methodNr++) {
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "restore") {
methodAddress = gameSuperObject->getFunction(methodNr);
Script *script = segMan->getScript(methodAddress.segment);
scriptRestorePtr = script->getBuf(methodAddress.offset);
}
if (methodName == "save") {
methodAddress = gameSuperObject->getFunction(methodNr);
Script *script = segMan->getScript(methodAddress.segment);
scriptSavePtr = script->getBuf(methodAddress.offset);
if (methodName == "restore")
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore);
else if (methodName == "save") {
if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave);
}
}

// Search for gameobject ::save, if there is one patch that one instead
for (uint16 methodNr = 0; methodNr < gameMethodCount; methodNr++) {
// Search for gameobject ::save, if there is one patch that one too
uint16 gameObjectMethodCount = gameObject->getMethodCount();
for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) {
uint16 selectorId = gameObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "save") {
methodAddress = gameObject->getFunction(methodNr);
Script *script = segMan->getScript(methodAddress.segment);
scriptSavePtr = script->getBuf(methodAddress.offset);
if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog
patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave);
break;
}
}

switch (_gameId) {
case GID_FAIRYTALES: // fairy tales automatically saves w/o dialog
scriptSavePtr = NULL;
default:
break;
}

if (scriptRestorePtr) {
// Now patch in our code
byte *patchPtr = const_cast<byte *>(scriptRestorePtr);
if (getSciVersion() <= SCI_VERSION_1_1)
memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
else if (getSciVersion() == SCI_VERSION_2)
memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
// TODO: SCI21/SCI3
patchPtr[8] = kernelIdRestore;
}
if (scriptSavePtr) {
// Now patch in our code
byte *patchPtr = const_cast<byte *>(scriptSavePtr);
if (getSciVersion() <= SCI_VERSION_1_1)
memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
else if (getSciVersion() == SCI_VERSION_2)
memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
// TODO: SCI21/SCI3
patchPtr[8] = kernelIdSave;
}
}

bool SciEngine::initGame() {
Expand Down
2 changes: 0 additions & 2 deletions engines/sci/sci.h
Expand Up @@ -246,7 +246,6 @@ class SciEngine : public Engine {
inline Vocabulary *getVocabulary() const { return _vocabulary; }
inline EventManager *getEventManager() const { return _eventMan; }
inline reg_t getGameObject() const { return _gameObjectAddress; }
inline reg_t getGameSuperClassAddress() const { return _gameSuperClassAddress; }

Common::RandomSource &getRNG() { return _rng; }

Expand Down Expand Up @@ -375,7 +374,6 @@ class SciEngine : public Engine {
int16 _vocabularyLanguage;
EventManager *_eventMan;
reg_t _gameObjectAddress; /**< Pointer to the game object */
reg_t _gameSuperClassAddress; // Address of the super class of the game object
Console *_console;
Common::RandomSource _rng;
Common::MacResManager _macExecutable;
Expand Down

0 comments on commit 4d33923

Please sign in to comment.