aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/saveload.cpp50
-rw-r--r--scumm/saveload.h20
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;
};