Ticket #8624: dialog_save.patch
File dialog_save.patch, 11.3 KB (added by , 17 years ago) |
---|
-
../../engines/scumm/input.cpp
499 499 500 500 // Alt-F5 brings up the original save/load dialog. 501 501 502 if (lastKeyHit == 440 && _game.version > 2 && _game.version < 8) { 503 lastKeyHit = saveloadkey; 504 saveloadkey = -1; 502 if (lastKeyHit == 440) { 503 if(_game.version <= 3) 504 prepareSavegame(); 505 if(_game.version > 2 && _game.version < 8) { 506 lastKeyHit = saveloadkey; 507 saveloadkey = -1; 508 } 505 509 } 506 510 507 511 if (lastKeyHit == saveloadkey) { -
../../engines/scumm/intern.h
82 82 int getWordVararg(int *ptr); 83 83 void saveVars(); 84 84 void loadVars(); 85 void saveIQPoints(); 86 void loadIQPoints(); 85 87 86 88 virtual int getVar(); 87 89 virtual int getVarOrDirectByte(byte mask); -
../../engines/scumm/saveload.cpp
84 84 _saveLoadFlag = 2; // 2 for load 85 85 } 86 86 87 static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) { 88 hdr.type = MKID_BE('SCVM'); 89 hdr.size = 0; 90 hdr.ver = CURRENT_VER; 91 92 out->writeUint32BE(hdr.type); 93 out->writeUint32LE(hdr.size); 94 out->writeUint32LE(hdr.ver); 95 out->write(hdr.name, sizeof(hdr.name)); 96 return true; 97 } 98 87 99 bool ScummEngine::saveState(int slot, bool compat) { 88 100 char filename[256]; 89 101 Common::OutSaveFile *out; … … 95 107 return false; 96 108 97 109 memcpy(hdr.name, _saveLoadName, sizeof(hdr.name)); 98 99 hdr.type = MKID_BE('SCVM'); 100 hdr.size = 0; 101 hdr.ver = CURRENT_VER; 102 103 out->writeUint32BE(hdr.type); 104 out->writeUint32LE(hdr.size); 105 out->writeUint32LE(hdr.ver); 106 out->write(hdr.name, sizeof(hdr.name)); 110 saveSaveGameHeader(out, hdr); 107 111 saveThumbnail(out); 108 112 saveInfos(out); 109 113 … … 429 433 return true; 430 434 } 431 435 436 void ScummEngine::prepareSavegame() { 437 saveState(0, true); 438 } 439 440 bool ScummEngine::savePreparedSavegame(int slot, char *desc) { 441 return copyRenameSavegame(0, true, slot, false, desc); 442 } 443 444 bool ScummEngine::copyRenameSavegame(int oldSlot, bool oldTemporary, int newSlot, bool newTemporary, char *desc) { 445 bool result; 446 uint32 nread; 447 byte buffer[1024]; 448 char oldFilename[256]; 449 char newFilename[256]; 450 Common::InSaveFile *in; 451 Common::OutSaveFile *out; 452 SaveGameHeader hdr; 453 454 makeSavegameName(oldFilename, oldSlot, oldTemporary); 455 if (!(in = _saveFileMan->openForLoading(oldFilename))) 456 return false; 457 458 if (!loadSaveGameHeader(in, hdr)) { 459 warning("Invalid savegame '%s'", oldFilename); 460 delete in; 461 return false; 462 } 463 464 if (hdr.ver != CURRENT_VER) { 465 warning("Incompatible savegame '%s'", oldFilename); 466 delete in; 467 return false; 468 } 469 470 makeSavegameName(newFilename, newSlot, newTemporary); 471 if (!(out = _saveFileMan->openForSaving(newFilename))) { 472 delete in; 473 return false; 474 } 475 476 memset(hdr.name, 0, sizeof(hdr.name)); 477 strncpy(hdr.name, desc, sizeof(hdr.name)-1); 478 saveSaveGameHeader(out, hdr); 479 480 // copy bytes 481 result = true; 482 while (nread = in->read(buffer, sizeof(buffer))) { 483 uint32 nwritten = out->write(buffer, nread); 484 if (nwritten < nread) { 485 result = false; 486 break; 487 } 488 } 489 490 out->finalize(); 491 if (out->ioFailed()) { 492 result = false; 493 } 494 delete in; 495 delete out; 496 497 return result; 498 } 499 432 500 Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) { 433 501 char filename[256]; 434 502 Common::InSaveFile *in; -
../../engines/scumm/script_v5.cpp
870 870 871 871 void ScummEngine_v5::saveVars() { 872 872 int a, b; 873 static char filename[256]; 873 874 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 3877 // The former is not so important as we have our own save system, but the878 // latter one of course is a desirable feature.879 // So implementing this would be nice indeed. Not sure what the filename880 // should be -- either base it on the target name, or base it on the gameid.881 // Both approaches have their merits, though.882 883 875 while ((_opcode = fetchScriptByte()) != 0) { 884 876 switch (_opcode & 0x1F) { 885 877 case 0x01: // write a range of variables … … 892 884 case 0x02: // write a range of string variables 893 885 a = getVarOrDirectByte(PARAM_1); 894 886 b = getVarOrDirectByte(PARAM_2); 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 } 896 899 break; 897 900 case 0x03: // open file 898 901 a = resStrLen(_scriptPointer); 899 debug(0, "stub saveVars to %s", _scriptPointer); 902 strncpy(filename, (char*)_scriptPointer, a); 903 filename[a] = '\0'; 900 904 _scriptPointer += a + 1; 901 905 break; 902 906 case 0x04: 903 907 return; 904 908 case 0x1F: // close file 905 debug(0, "stub saveVars close file");909 filename[0] = '\0'; 906 910 return; 907 911 } 908 912 } … … 910 914 911 915 void ScummEngine_v5::loadVars() { 912 916 int a, b; 917 static char filename[256]; 913 918 914 // FIXME: See ScummEngine_v5::saveVars915 916 // Common::hexdump(_scriptPointer, 64);917 919 while ((_opcode = fetchScriptByte()) != 0) { 918 920 switch (_opcode & 0x1F) { 919 921 case 0x01: // read a range of variables … … 926 928 case 0x02: // read a range of string variables 927 929 a = getVarOrDirectByte(PARAM_1); 928 930 b = getVarOrDirectByte(PARAM_2); 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 } 930 976 break; 931 977 case 0x03: // open file 932 978 a = resStrLen(_scriptPointer); 933 debug(0, "stub loadVars from %s", _scriptPointer); 979 strncpy(filename, (char*)_scriptPointer, a); 980 filename[a] = '\0'; 934 981 _scriptPointer += a + 1; 935 982 break; 936 983 case 0x04: 937 984 return; 938 985 case 0x1F: // close file 939 debug(0, "stub loadVars close file");986 filename[0] = '\0'; 940 987 return; 941 988 } 942 989 } 943 990 } 944 991 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 945 1027 void ScummEngine_v5::o5_expression() { 946 1028 int dst, i; 947 1029 … … 1124 1206 void ScummEngine_v5::o5_saveLoadGame() { 1125 1207 getResultPos(); 1126 1208 byte a = getVarOrDirectByte(PARAM_1); 1127 byte slot = (a & 0x1F) + 1;1209 byte slot = a & 0x1F; 1128 1210 byte result = 0; 1129 1211 1212 if (_game.version <= 2) { 1213 // Slot numbers in older games start with 0, in newer games with 1 1214 slot++; 1215 } 1216 1130 1217 if ((_game.id == GID_MANIAC) && (_game.version <= 1)) { 1131 1218 // Convert older load/save screen 1132 1219 // 1 Load … … 1145 1232 result = 100; 1146 1233 break; 1147 1234 case 0x20: // drive 1148 if (_game.id == GID_INDY3) { 1149 // 0 = hard drive 1150 // 1 = disk drive 1151 result = 0; 1235 if (_game.version <= 3) { 1236 // 0 = ??? 1237 // [1,2] = disk drive [A:,B:] 1238 // 3 = hard drive 1239 result = 3; 1152 1240 } else { 1153 1241 // set current drive 1154 1242 result = 1; 1155 1243 } 1156 1244 break; 1157 1245 case 0x40: // load 1158 if (loadState(slot, _saveTemporaryState))1246 if (loadState(slot, false)) 1159 1247 result = 3; // sucess 1160 1248 else 1161 1249 result = 5; // failed to load 1162 1250 break; 1163 1251 case 0x80: // save 1164 //if (saveState(slot, _saveTemporaryState)) 1165 // result = 0; // sucess 1166 //else 1252 if (_game.version <= 3) { 1253 char name[32]; 1254 if (_game.version <= 2) { 1255 // use generic name 1256 sprintf(name, "Game %c", 'A'+slot-1); 1257 } else { 1258 // use name entered by the user 1259 char* ptr; 1260 int firstSlot = (_game.id == GID_LOOM) ? RESID_SAVENAME1_LOOM : RESID_SAVENAME1; 1261 ptr = (char*)getStringAddress(slot + firstSlot - 1); 1262 strncpy(name, ptr, sizeof(name)); 1263 } 1264 1265 if(savePreparedSavegame(slot, name)) 1266 result = 0; 1267 else 1268 result = 2; 1269 } else { 1167 1270 result = 2; // failed to save 1271 } 1168 1272 break; 1169 1273 case 0xC0: // test if save exists 1170 1274 Common::InSaveFile *file; -
../../engines/scumm/scumm.h
328 328 rtNumTypes = 22 329 329 }; 330 330 331 enum ResIds { 332 RESID_IQ_EPISODE = 7, 333 RESID_IQ_SERIES = 9, 334 RESID_SAVENAME1 = 10, 335 RESID_SAVENAME1_LOOM = 9, 336 }; 331 337 332 338 339 333 340 /** 334 341 * The 'resource manager' class. Currently doesn't really deserve to be called 335 342 * a 'class', at least until somebody gets around to OOfying this more. … … 620 627 void requestSave(int slot, const char *name, bool temporary = false); 621 628 void requestLoad(int slot); 622 629 630 void prepareSavegame(); 631 bool savePreparedSavegame(int slot, char *desc); 632 bool copyRenameSavegame(int oldSlot, bool oldTemporary, int newSlot, bool newTemporary, char *desc); 633 623 634 // thumbnail + info stuff 624 635 public: 625 636 Graphics::Surface *loadThumbnailFromSlot(int slot);