SCI: Cleanup of the save/load dialog patching code and the lofs type detection code
This commit is contained in:
parent
d90c7a8314
commit
4d33923436
3 changed files with 35 additions and 68 deletions
|
@ -285,20 +285,16 @@ SciVersion GameFeatures::detectLofsType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss
|
// 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;
|
bool found = false;
|
||||||
if (!gameSuperClass.isNull()) {
|
if (gameSuperObject) {
|
||||||
Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
|
Common::String gameSuperClassName = _segMan->getObjectName(gameObject->getSuperClassSelector());
|
||||||
const Object *gameSuperObject = _segMan->getObject(gameSuperClass);
|
|
||||||
|
|
||||||
if (gameSuperObject) {
|
for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
|
||||||
for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
|
found = autoDetectLofsType(gameSuperClassName, m);
|
||||||
found = autoDetectLofsType(gameSuperClassName, m);
|
if (found)
|
||||||
if (found)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warning("detectLofsType(): Could not get superclass object");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warning("detectLofsType(): Could not find superclass of game object");
|
warning("detectLofsType(): Could not find superclass of game object");
|
||||||
|
|
|
@ -213,7 +213,6 @@ Common::Error SciEngine::run() {
|
||||||
// Add the after market GM patches for the specified game, if they exist
|
// Add the after market GM patches for the specified game, if they exist
|
||||||
_resMan->addNewGMPatch(_gameId);
|
_resMan->addNewGMPatch(_gameId);
|
||||||
_gameObjectAddress = _resMan->findGameObject();
|
_gameObjectAddress = _resMan->findGameObject();
|
||||||
_gameSuperClassAddress = NULL_REG;
|
|
||||||
|
|
||||||
SegManager *segMan = new SegManager(_resMan);
|
SegManager *segMan = new SegManager(_resMan);
|
||||||
|
|
||||||
|
@ -250,7 +249,6 @@ Common::Error SciEngine::run() {
|
||||||
warning("Could not get game object, aborting...");
|
warning("Could not get game object, aborting...");
|
||||||
return Common::kUnknownError;
|
return Common::kUnknownError;
|
||||||
}
|
}
|
||||||
_gameSuperClassAddress = gameObject->getSuperClassSelector();
|
|
||||||
|
|
||||||
script_adjust_opcode_formats();
|
script_adjust_opcode_formats();
|
||||||
|
|
||||||
|
@ -441,19 +439,24 @@ static byte patchGameRestoreSaveSci2[] = {
|
||||||
0x48, // ret
|
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() {
|
void SciEngine::patchGameSaveRestore() {
|
||||||
SegManager *segMan = _gamestate->_segMan;
|
SegManager *segMan = _gamestate->_segMan;
|
||||||
const Object *gameObject = segMan->getObject(_gameObjectAddress);
|
const Object *gameObject = segMan->getObject(_gameObjectAddress);
|
||||||
const uint16 gameMethodCount = gameObject->getMethodCount();
|
const Object *gameSuperObject = segMan->getObject(gameObject->getSuperClassSelector());
|
||||||
const Object *gameSuperObject = segMan->getObject(_gameSuperClassAddress);
|
|
||||||
if (!gameSuperObject)
|
if (!gameSuperObject)
|
||||||
gameSuperObject = gameObject; // happens in KQ5CD, when loading saved games before r54510
|
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;
|
byte kernelIdRestore = 0;
|
||||||
const byte *scriptSavePtr = NULL;
|
|
||||||
byte kernelIdSave = 0;
|
byte kernelIdSave = 0;
|
||||||
|
|
||||||
// This feature is currently not supported in SCI21 or SCI3
|
// This feature is currently not supported in SCI21 or SCI3
|
||||||
|
@ -473,7 +476,8 @@ void SciEngine::patchGameSaveRestore() {
|
||||||
if (ConfMan.getBool("sci_originalsaveload"))
|
if (ConfMan.getBool("sci_originalsaveload"))
|
||||||
return;
|
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);
|
Common::String kernelName = _kernel->getKernelName(kernelNr);
|
||||||
if (kernelName == "RestoreGame")
|
if (kernelName == "RestoreGame")
|
||||||
kernelIdRestore = kernelNr;
|
kernelIdRestore = kernelNr;
|
||||||
|
@ -481,61 +485,30 @@ void SciEngine::patchGameSaveRestore() {
|
||||||
kernelIdSave = kernelNr;
|
kernelIdSave = kernelNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for gameobject-superclass ::restore
|
// Search for gameobject superclass ::restore
|
||||||
for (uint16 methodNr = 0; methodNr < gameSuperMethodCount; methodNr++) {
|
uint16 gameSuperObjectMethodCount = gameSuperObject->getMethodCount();
|
||||||
|
for (uint16 methodNr = 0; methodNr < gameSuperObjectMethodCount; methodNr++) {
|
||||||
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
|
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
|
||||||
Common::String methodName = _kernel->getSelectorName(selectorId);
|
Common::String methodName = _kernel->getSelectorName(selectorId);
|
||||||
if (methodName == "restore") {
|
if (methodName == "restore")
|
||||||
methodAddress = gameSuperObject->getFunction(methodNr);
|
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore);
|
||||||
Script *script = segMan->getScript(methodAddress.segment);
|
else if (methodName == "save") {
|
||||||
scriptRestorePtr = script->getBuf(methodAddress.offset);
|
if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog
|
||||||
}
|
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave);
|
||||||
if (methodName == "save") {
|
|
||||||
methodAddress = gameSuperObject->getFunction(methodNr);
|
|
||||||
Script *script = segMan->getScript(methodAddress.segment);
|
|
||||||
scriptSavePtr = script->getBuf(methodAddress.offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for gameobject ::save, if there is one patch that one instead
|
// Search for gameobject ::save, if there is one patch that one too
|
||||||
for (uint16 methodNr = 0; methodNr < gameMethodCount; methodNr++) {
|
uint16 gameObjectMethodCount = gameObject->getMethodCount();
|
||||||
|
for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) {
|
||||||
uint16 selectorId = gameObject->getFuncSelector(methodNr);
|
uint16 selectorId = gameObject->getFuncSelector(methodNr);
|
||||||
Common::String methodName = _kernel->getSelectorName(selectorId);
|
Common::String methodName = _kernel->getSelectorName(selectorId);
|
||||||
if (methodName == "save") {
|
if (methodName == "save") {
|
||||||
methodAddress = gameObject->getFunction(methodNr);
|
if (_gameId != GID_FAIRYTALES) // Fairy Tales saves automatically without a dialog
|
||||||
Script *script = segMan->getScript(methodAddress.segment);
|
patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave);
|
||||||
scriptSavePtr = script->getBuf(methodAddress.offset);
|
|
||||||
break;
|
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() {
|
bool SciEngine::initGame() {
|
||||||
|
|
|
@ -246,7 +246,6 @@ public:
|
||||||
inline Vocabulary *getVocabulary() const { return _vocabulary; }
|
inline Vocabulary *getVocabulary() const { return _vocabulary; }
|
||||||
inline EventManager *getEventManager() const { return _eventMan; }
|
inline EventManager *getEventManager() const { return _eventMan; }
|
||||||
inline reg_t getGameObject() const { return _gameObjectAddress; }
|
inline reg_t getGameObject() const { return _gameObjectAddress; }
|
||||||
inline reg_t getGameSuperClassAddress() const { return _gameSuperClassAddress; }
|
|
||||||
|
|
||||||
Common::RandomSource &getRNG() { return _rng; }
|
Common::RandomSource &getRNG() { return _rng; }
|
||||||
|
|
||||||
|
@ -375,7 +374,6 @@ private:
|
||||||
int16 _vocabularyLanguage;
|
int16 _vocabularyLanguage;
|
||||||
EventManager *_eventMan;
|
EventManager *_eventMan;
|
||||||
reg_t _gameObjectAddress; /**< Pointer to the game object */
|
reg_t _gameObjectAddress; /**< Pointer to the game object */
|
||||||
reg_t _gameSuperClassAddress; // Address of the super class of the game object
|
|
||||||
Console *_console;
|
Console *_console;
|
||||||
Common::RandomSource _rng;
|
Common::RandomSource _rng;
|
||||||
Common::MacResManager _macExecutable;
|
Common::MacResManager _macExecutable;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue