874 | | // FIXME: This opcode is currently a stub. It is needed for at least two things: |
875 | | // * storing save game names in Indy 3 (and maybe others) |
876 | | // * storing the global IQ (Indy Quotient) in Indy 3 |
877 | | // The former is not so important as we have our own save system, but the |
878 | | // latter one of course is a desirable feature. |
879 | | // So implementing this would be nice indeed. Not sure what the filename |
880 | | // should be -- either base it on the target name, or base it on the gameid. |
881 | | // Both approaches have their merits, though. |
882 | | |
895 | | debug(0, "stub saveVars: strings %d -> %d", a, b); |
| 887 | |
| 888 | if (_game.version == 3 && (_game.id == GID_INDY3 || _game.id == GID_ZAK || _game.id == GID_LOOM)) { |
| 889 | if (a == RESID_IQ_EPISODE && b == RESID_IQ_EPISODE) { |
| 890 | if (_game.id == GID_INDY3) { |
| 891 | saveIQPoints(); |
| 892 | } |
| 893 | break; |
| 894 | } |
| 895 | // FIXME: changing savegame-names not supported |
| 896 | } else { |
| 897 | debug(0, "stub saveVars: strings %d -> %d", a, b); |
| 898 | } |
929 | | debug(0, "stub loadVars: strings %d -> %d", a, b); |
| 931 | |
| 932 | if (_game.version == 3 && (_game.id == GID_INDY3 || _game.id == GID_ZAK || _game.id == GID_LOOM)) { |
| 933 | int slot; |
| 934 | int slotSize; |
| 935 | byte* slotContent; |
| 936 | int savegameId; |
| 937 | char name[32]; |
| 938 | bool avail_saves[100]; |
| 939 | |
| 940 | if (a == RESID_IQ_SERIES && b == RESID_IQ_SERIES) { |
| 941 | // Zak256 loads the IQ script-slot but does not use it -> ignore it |
| 942 | if(_game.id == GID_INDY3) { |
| 943 | loadIQPoints(); |
| 944 | } |
| 945 | break; |
| 946 | } |
| 947 | |
| 948 | listSavegames(avail_saves, ARRAYSIZE(avail_saves)); |
| 949 | for (slot = a; slot <= b; ++slot) { |
| 950 | slotSize = getResourceSize(rtString, slot); |
| 951 | slotContent = getResourceAddress(rtString, slot); |
| 952 | |
| 953 | // load savegame names |
| 954 | savegameId = slot - a + 1; |
| 955 | if (avail_saves[savegameId] && getSavegameName(savegameId, name)) { |
| 956 | int pos; |
| 957 | char *ptr = name; |
| 958 | // slotContent ends with {'\0','@'} -> max. length = slotSize-2 |
| 959 | for (pos = 0; pos < slotSize - 2; ++pos) { |
| 960 | if (!ptr[pos]) |
| 961 | break; |
| 962 | // replace special characters |
| 963 | if(ptr[pos] >= 32 && ptr[pos] <= 122 && ptr[pos] != 64) |
| 964 | slotContent[pos] = ptr[pos]; |
| 965 | else |
| 966 | slotContent[pos] = '_'; |
| 967 | } |
| 968 | slotContent[pos] = '\0'; |
| 969 | } else { |
| 970 | slotContent[0] = '\0'; |
| 971 | } |
| 972 | } |
| 973 | } else { |
| 974 | debug(0, "stub loadVars: strings %d -> %d", a, b); |
| 975 | } |
| 992 | void ScummEngine_v5::saveIQPoints() { |
| 993 | // save series IQ-points |
| 994 | Common::OutSaveFile *file; |
| 995 | char filename[256]; |
| 996 | |
| 997 | sprintf(filename, "%s.iq", _targetName.c_str()); |
| 998 | file = _saveFileMan->openForSaving(filename); |
| 999 | if (file != NULL) { |
| 1000 | int size = getResourceSize(rtString, RESID_IQ_EPISODE); |
| 1001 | byte *ptr = getResourceAddress(rtString, RESID_IQ_EPISODE); |
| 1002 | file->write(ptr, size); |
| 1003 | delete file; |
| 1004 | } |
| 1005 | } |
| 1006 | |
| 1007 | void ScummEngine_v5::loadIQPoints() { |
| 1008 | // load series IQ-points |
| 1009 | Common::InSaveFile *file; |
| 1010 | char filename[256]; |
| 1011 | |
| 1012 | sprintf(filename, "%s.iq", _targetName.c_str()); |
| 1013 | file = _saveFileMan->openForLoading(filename); |
| 1014 | if (file != NULL) { |
| 1015 | int size = getResourceSize(rtString, RESID_IQ_SERIES); |
| 1016 | byte *ptr = getResourceAddress(rtString, RESID_IQ_SERIES); |
| 1017 | byte *tmp = (byte*)malloc(size); |
| 1018 | int nread = file->read(tmp, size); |
| 1019 | if (nread == size) { |
| 1020 | memcpy(ptr, tmp, size); |
| 1021 | } |
| 1022 | free(tmp); |
| 1023 | delete file; |
| 1024 | } |
| 1025 | } |
| 1026 | |
1164 | | //if (saveState(slot, _saveTemporaryState)) |
1165 | | // result = 0; // sucess |
1166 | | //else |
| 1252 | // Save dialogs of old SCUMM games except Loom are cutscene, hence |
| 1253 | // we can easily break the cutscene and save the state after the cutscene |
| 1254 | // has terminated. Loom doesn't use cutscene so we would run inside an endless |
| 1255 | // loop. |
| 1256 | if (_game.version <= 3 && _game.id != GID_LOOM) { |
| 1257 | char name[32]; |
| 1258 | if (_game.version <= 2) { |
| 1259 | // use generic name |
| 1260 | sprintf(name, "Game %c", 'A'+slot-1); |
| 1261 | } else { |
| 1262 | // use name entered by the user |
| 1263 | char* ptr; |
| 1264 | int firstSlot = (_game.id == GID_LOOM) ? RESID_SAVENAME1_LOOM : RESID_SAVENAME1; |
| 1265 | ptr = (char*)getStringAddress(slot + firstSlot - 1); |
| 1266 | strncpy(name, ptr, sizeof(name)); |
| 1267 | } |
| 1268 | // HACK: works without a temporary savegame but does not behave |
| 1269 | // like the original SAVE-dialog (does not work with LOOM) |
| 1270 | if (_game.id == GID_INDY3) |
| 1271 | saveIQPoints(); |
| 1272 | abortCutscene(); |
| 1273 | getScriptEntryPoint(); |
| 1274 | requestSave(slot, name, false); |
| 1275 | // we do not have to return a result actually because we have already |
| 1276 | // jumped to the end of the cutscene. |
| 1277 | } else { |
| 1278 | //if (saveState(slot, _saveTemporaryState)) |
| 1279 | // result = 0; // sucess |
| 1280 | //else |