aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sci.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sci.cpp')
-rw-r--r--engines/sci/sci.cpp123
1 files changed, 77 insertions, 46 deletions
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index bdfb6ccc9c..f161569598 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -496,61 +496,86 @@ static byte patchGameRestoreSave[] = {
};
// SCI2 version: Same as above, but the second parameter to callk is a word
-static byte patchGameRestoreSaveSci2[] = {
- 0x39, 0x03, // pushi 03
- 0x76, // push0
- 0x38, 0xff, 0xff, // pushi -1
- 0x76, // push0
- 0x43, 0xff, 0x06, 0x00, // callk kRestoreGame/kSaveGame (will get changed afterwards)
- 0x48, // ret
+// and third parameter is a string reference
+static byte patchGameRestoreSci2[] = {
+ 0x39, 0x03, // pushi 03
+ 0x76, // push0 (game name)
+ 0x38, 0xff, 0xff, // pushi -1 (save number)
+ 0x89, 0x1b, // lsg global[27] (game version)
+ 0x43, 0xff, 0x06, 0x00, // callk kRestoreGame (0xFF will be overwritten by patcher)
+ 0x48, // ret
};
-// SCI21 version: Same as above, but the second parameter to callk is a word
-static byte patchGameRestoreSaveSci21[] = {
- 0x39, 0x04, // pushi 04
- 0x76, // push0 // 0: save, 1: restore (will get changed afterwards)
- 0x76, // push0
- 0x38, 0xff, 0xff, // pushi -1
- 0x76, // push0
- 0x43, 0xff, 0x08, 0x00, // callk kSave (will get changed afterwards)
- 0x48, // ret
+static byte patchGameSaveSci2[] = {
+ 0x39, 0x04, // pushi 04
+ 0x76, // push0 (game name)
+ 0x38, 0xff, 0xff, // pushi -1 (save number)
+ 0x76, // push0 (save description)
+ 0x89, 0x1b, // lsg global[27] (game version)
+ 0x43, 0xff, 0x08, 0x00, // callk kSaveGame (0xFF will be overwritten by patcher)
+ 0x48, // ret
+};
+
+// SCI2.1mid version: Same as above, but with an extra subop parameter
+static byte patchGameRestoreSci21[] = {
+ 0x39, 0x04, // pushi 04
+ 0x78, // push1 (subop)
+ 0x76, // push0 (game name)
+ 0x38, 0xff, 0xff, // pushi -1 (save number)
+ 0x89, 0x1b, // lsg global[27] (game version)
+ 0x43, 0xff, 0x08, 0x00, // callk kSave (0xFF will be overwritten by patcher)
+ 0x48, // ret
+};
+
+static byte patchGameSaveSci21[] = {
+ 0x39, 0x05, // pushi 05
+ 0x76, // push0 (subop)
+ 0x76, // push0 (game name)
+ 0x38, 0xff, 0xff, // pushi -1 (save number)
+ 0x76, // push0 (save description)
+ 0x89, 0x1b, // lsg global[27] (game version)
+ 0x43, 0xff, 0x0a, 0x00, // callk kSave (0xFF will be overwritten by patcher)
+ 0x48, // ret
};
static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
Script *script = segMan->getScript(methodAddress.getSegment());
byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
- if (getSciVersion() <= SCI_VERSION_1_1) {
- memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
- } else { // SCI2+
- memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
-
- if (g_sci->isBE()) {
- // LE -> BE
- patchPtr[9] = 0x00;
- patchPtr[10] = 0x06;
- }
- }
-
+ memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
patchPtr[8] = id;
}
-static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
+#ifdef ENABLE_SCI32
+static void patchGameSaveRestoreCodeSci2(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
Script *script = segMan->getScript(methodAddress.getSegment());
byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
- memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21));
+ int kcallOffset;
- if (doRestore)
- patchPtr[2] = 0x78; // push1
+ if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ if (doRestore) {
+ memcpy(patchPtr, patchGameRestoreSci2, sizeof(patchGameRestoreSci2));
+ kcallOffset = 9;
+ } else {
+ memcpy(patchPtr, patchGameSaveSci2, sizeof(patchGameSaveSci2));
+ kcallOffset = 10;
+ }
+ } else {
+ if (doRestore) {
+ memcpy(patchPtr, patchGameRestoreSci21, sizeof(patchGameRestoreSci21));
+ kcallOffset = 10;
+ } else {
+ memcpy(patchPtr, patchGameSaveSci21, sizeof(patchGameSaveSci21));
+ kcallOffset = 11;
+ }
+ }
+ patchPtr[kcallOffset] = id;
if (g_sci->isBE()) {
- // LE -> BE
- patchPtr[10] = 0x00;
- patchPtr[11] = 0x08;
+ SWAP(patchPtr[kcallOffset + 1], patchPtr[kcallOffset + 2]);
}
-
- patchPtr[9] = id;
}
+#endif
void SciEngine::patchGameSaveRestore() {
SegManager *segMan = _gamestate->_segMan;
@@ -595,17 +620,21 @@ void SciEngine::patchGameSaveRestore() {
uint16 selectorId = gameSuperObject->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "restore") {
- if (kernelIdSave != kernelIdRestore)
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true);
+ } else
+#endif
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore);
- else
- patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdRestore, true);
}
else if (methodName == "save") {
if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
- if (kernelIdSave != kernelIdRestore)
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false);
+ } else
+#endif
patchGameSaveRestoreCode(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave);
- else
- patchGameSaveRestoreCodeSci21(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false);
}
}
}
@@ -629,10 +658,12 @@ void SciEngine::patchGameSaveRestore() {
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "save") {
if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
- if (kernelIdSave != kernelIdRestore)
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ patchGameSaveRestoreCodeSci2(segMan, gameSuperObject->getFunction(methodNr), kernelIdSave, false);
+ } else
+#endif
patchGameSaveRestoreCode(segMan, patchObjectSave->getFunction(methodNr), kernelIdSave);
- else
- patchGameSaveRestoreCodeSci21(segMan, patchObjectSave->getFunction(methodNr), kernelIdSave, false);
}
break;
}