diff options
Diffstat (limited to 'scumm')
-rw-r--r-- | scumm/saveload.cpp | 50 | ||||
-rw-r--r-- | scumm/saveload.h | 20 |
2 files changed, 50 insertions, 20 deletions
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index ac4f6cc12a..63a483b22a 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -114,7 +114,7 @@ bool Scumm::loadState(int slot, bool compat, SaveFileManager *mgr) { delete out; return false; } - + // Due to a bug in scummvm up to and including 0.3.0, save games could be saved // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here if (hdr.ver == VER_V7) @@ -394,11 +394,23 @@ void Scumm::saveOrLoad(Serializer *s, uint32 savegameVersion) { MKLINE(Scumm, _currentScript, sleByte, VER_V8), MKARRAY(Scumm, _localScriptList[0], sleUint32, NUM_LOCALSCRIPT, VER_V8), - // vm.localvar grew from 25 to 40 entries and then from - // 16 to 32 bit variables... and THEN from 16 to 20 variables - MKARRAY_OLD(Scumm, vm.localvar[0][0], sleUint16, 25 * 17, VER_V8, VER_V8), - MKARRAY_OLD(Scumm, vm.localvar[0][0], sleUint16, NUM_SCRIPT_SLOT * 17, VER_V9, VER_V14), - MKARRAY(Scumm, vm.localvar[0][0], sleUint16, NUM_SCRIPT_SLOT * 25, VER_V15), + + // vm.localvar grew from 25 to 40 script entries and then from + // 16 to 32 bit variables (but that wasn't reflect hered)... and + // THEN from 16 to 25 variables. However, this was incorrectly implemented + // here. But now we support two dimensional arrays properly here. + MKARRAY2_OLD(Scumm, vm.localvar[0][0], sleUint16, 17, 25, (byte*)vm.localvar[1] - (byte*)vm.localvar[0], VER_V8, VER_V8), + MKARRAY2_OLD(Scumm, vm.localvar[0][0], sleUint16, 17, NUM_SCRIPT_SLOT, (byte*)vm.localvar[1] - (byte*)vm.localvar[0], VER_V9, VER_V14), + + // We used to save 25 * 40 = 1000 blocks; but actually, each 'row consisted of 26 entry, + // i.e. 26 * 40 = 1040. Thus the last 40 blocks of localvar where not saved at all. To be + // able to load this screwed format, we use a trick: We load 26 * 38 = 988 blocks. + // Then, we mark the followin 12 blocks (24 bytes) as obsolete. + MKARRAY2_OLD(Scumm, vm.localvar[0][0], sleUint16, 26, 38, (byte*)vm.localvar[1] - (byte*)vm.localvar[0], VER_V15, VER_V17), + MK_OBSOLETE_ARRAY(Scumm, vm.localvar[39][0], sleUint16, 12, VER_V15, VER_V17), + + MKARRAY2(Scumm, vm.localvar[0][0], sleUint32, 26, NUM_SCRIPT_SLOT, (byte*)vm.localvar[1] - (byte*)vm.localvar[0], VER_V18), + MKARRAY(Scumm, _resourceMapper[0], sleByte, 128, VER_V8), MKARRAY(Scumm, _charsetColorMap[0], sleByte, 16, VER_V8), @@ -941,13 +953,20 @@ void Serializer::saveEntries(void *d, const SaveLoadEntry *sle) { saveWord(ptr ? ((*_save_ref) (_ref_me, type, ptr) + 1) : 0); } else { // save entry - int replen = 1; + int columns = 1; + int rows = 1; + int rowlen = 0; if (type & 128) { sle++; - replen = sle->offs; + columns = sle->offs; + rows = sle->type; + rowlen = sle->size; type &= ~128; } - saveArrayOf(at, replen, size, type); + while (rows--) { + saveArrayOf(at, columns, size, type); + at += rowlen; + } } sle++; } @@ -975,14 +994,21 @@ void Serializer::loadEntries(void *d, const SaveLoadEntry *sle) { *((void **)at) = num ? (*_load_ref) (_ref_me, type, num - 1) : NULL; } else { // load entry - int replen = 1; + int columns = 1; + int rows = 1; + int rowlen = 0; if (type & 128) { sle++; - replen = sle->offs; + columns = sle->offs; + rows = sle->type; + rowlen = sle->size; type &= ~128; } - loadArrayOf(at, replen, size, type); + while (rows--) { + loadArrayOf(at, columns, size, type); + at += rowlen; + } } sle++; } diff --git a/scumm/saveload.h b/scumm/saveload.h index 857c313558..66114eac90 100644 --- a/scumm/saveload.h +++ b/scumm/saveload.h @@ -36,10 +36,11 @@ enum { VER_V14, VER_V15, VER_V16, - VER_V17 + VER_V17, + VER_V18 }; -#define CURRENT_VER VER_V17 +#define CURRENT_VER VER_V18 // To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types, @@ -55,16 +56,19 @@ enum { // Any item that is still in use automatically gets a maxVersion equal to CURRENT_VER #define MKLINE(type,item,saveas,minVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,CURRENT_VER} -#define MKARRAY(type,item,saveas,num,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {num,0,0,0,0} +#define MKARRAY(type,item,saveas,dim,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {dim,1,0,0,0} +#define MKARRAY2(type,item,saveas,dim,dim2,rowlen,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {dim,dim2,rowlen,0,0} // Use this if you have an entry that used to be smaller: #define MKLINE_OLD(type,item,saveas,minVer,maxVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,maxVer} -#define MKARRAY_OLD(type,item,saveas,num,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {num,0,0,0,0} +#define MKARRAY_OLD(type,item,saveas,dim,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {dim,1,0,0,0} +#define MKARRAY2_OLD(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {dim,dim2,rowlen,0,0} // An obsolete item/array, to be ignored upon load. We retain the type/item params to make it easier to debug. // Obsolete items have size == 0. #define MK_OBSOLETE(type,item,saveas,minVer,maxVer) {0,saveas,0,minVer,maxVer} -#define MK_OBSOLETE_ARRAY(type,item,saveas,num,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {num,0,0,0,0} +#define MK_OBSOLETE_ARRAY(type,item,saveas,dim,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {dim,1,0,0,0} +#define MK_OBSOLETE_ARRAY2(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {dim,dim2,rowlen,0,0} // End marker #define MKEND() {0xFFFF,0xFF,0xFF,0,0} @@ -87,9 +91,9 @@ enum { }; struct SaveLoadEntry { - uint32 offs; - uint8 type; - uint8 size; + uint32 offs; // or: array dimension + uint16 type; // or: array dimension 2 + uint16 size; // or: array row length uint8 minVersion; uint8 maxVersion; }; |