summaryrefslogtreecommitdiff
path: root/src/saveload/saveload.cpp
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-06-12 14:49:51 +0200
committerPatric Stout <github@truebrain.nl>2021-06-15 16:45:04 +0200
commit97b94bdc9ab4ceeb589c5022d5c238442faf0454 (patch)
tree7d22a32f5bf2ac2a56467b7ce5f190fff9c8d09a /src/saveload/saveload.cpp
parentf67af5cbe5cb754c3b64553b9cc03b5c18ca7e79 (diff)
downloadopenttd-97b94bdc9ab4ceeb589c5022d5c238442faf0454.tar.xz
Change: prefix SL_ARR with the length of the array
This means that during loading we can validate that what is saved is also that what is expected. Additionally, this makes all list types similar to how they are stored on disk: First a gamma to indicate length, followed by the data. The size still depends on the type.
Diffstat (limited to 'src/saveload/saveload.cpp')
-rw-r--r--src/saveload/saveload.cpp110
1 files changed, 79 insertions, 31 deletions
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index d4ca1b308..04002fd3f 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -1043,51 +1043,34 @@ static void SlStdString(void *ptr, VarType conv)
}
/**
- * Return the size in bytes of a certain type of atomic array
- * @param length The length of the array counted in elements
- * @param conv VarType type of the variable that is used in calculating the size
+ * Internal function to save/Load a list of SL_VARs.
+ * SlCopy() and SlArray() are very similar, with the exception of the header.
+ * This function represents the common part.
+ * @param object The object being manipulated.
+ * @param length The length of the object in elements
+ * @param conv VarType type of the items.
*/
-static inline size_t SlCalcArrayLen(size_t length, VarType conv)
+static void SlCopyInternal(void *object, size_t length, VarType conv)
{
- return SlCalcConvFileLen(conv) * length;
-}
-
-/**
- * Save/Load an array.
- * @param array The array being manipulated
- * @param length The length of the array in elements
- * @param conv VarType type of the atomic array (int, byte, uint64, etc.)
- */
-void SlArray(void *array, size_t length, VarType conv)
-{
- if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
-
- /* Automatically calculate the length? */
- if (_sl.need_length != NL_NONE) {
- SlSetLength(SlCalcArrayLen(length, conv));
- /* Determine length only? */
- if (_sl.need_length == NL_CALCLENGTH) return;
- }
-
if (GetVarMemType(conv) == SLE_VAR_NULL) {
assert(_sl.action != SLA_SAVE); // Use SL_NULL if you want to write null-bytes
- SlSkipBytes(SlCalcArrayLen(length, conv));
+ SlSkipBytes(length * SlCalcConvFileLen(conv));
return;
}
/* NOTICE - handle some buggy stuff, in really old versions everything was saved
- * as a byte-type. So detect this, and adjust array size accordingly */
+ * as a byte-type. So detect this, and adjust object size accordingly */
if (_sl.action != SLA_SAVE && _sl_version == 0) {
- /* all arrays except difficulty settings */
+ /* all objects except difficulty settings */
if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
conv == SLE_INT32 || conv == SLE_UINT32) {
- SlCopyBytes(array, length * SlCalcConvFileLen(conv));
+ SlCopyBytes(object, length * SlCalcConvFileLen(conv));
return;
}
/* used for conversion of Money 32bit->64bit */
if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
for (uint i = 0; i < length; i++) {
- ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
+ ((int64*)object)[i] = (int32)BSWAP32(SlReadUint32());
}
return;
}
@@ -1096,9 +1079,9 @@ void SlArray(void *array, size_t length, VarType conv)
/* If the size of elements is 1 byte both in file and memory, no special
* conversion is needed, use specialized copy-copy function to speed up things */
if (conv == SLE_INT8 || conv == SLE_UINT8) {
- SlCopyBytes(array, length);
+ SlCopyBytes(object, length);
} else {
- byte *a = (byte*)array;
+ byte *a = (byte*)object;
byte mem_size = SlCalcConvMemLen(conv);
for (; length != 0; length --) {
@@ -1108,6 +1091,71 @@ void SlArray(void *array, size_t length, VarType conv)
}
}
+/**
+ * Copy a list of SL_VARs to/from a savegame.
+ * These entries are copied as-is, and you as caller have to make sure things
+ * like length-fields are calculated correctly.
+ * @param object The object being manipulated.
+ * @param length The length of the object in elements
+ * @param conv VarType type of the items.
+ */
+void SlCopy(void *object, size_t length, VarType conv)
+{
+ if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return;
+
+ /* Automatically calculate the length? */
+ if (_sl.need_length != NL_NONE) {
+ SlSetLength(length * SlCalcConvFileLen(conv));
+ /* Determine length only? */
+ if (_sl.need_length == NL_CALCLENGTH) return;
+ }
+
+ SlCopyInternal(object, length, conv);
+}
+
+/**
+ * Return the size in bytes of a certain type of atomic array
+ * @param length The length of the array counted in elements
+ * @param conv VarType type of the variable that is used in calculating the size
+ */
+static inline size_t SlCalcArrayLen(size_t length, VarType conv)
+{
+ return SlCalcConvFileLen(conv) * length + SlGetArrayLength(length);
+}
+
+/**
+ * Save/Load the length of the array followed by the array of SL_VAR elements.
+ * @param array The array being manipulated
+ * @param length The length of the array in elements
+ * @param conv VarType type of the atomic array (int, byte, uint64, etc.)
+ */
+static void SlArray(void *array, size_t length, VarType conv)
+{
+ switch (_sl.action) {
+ case SLA_SAVE:
+ SlWriteArrayLength(length);
+ SlCopyInternal(array, length, conv);
+ return;
+
+ case SLA_LOAD_CHECK:
+ case SLA_LOAD: {
+ if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
+ size_t sv_length = SlReadArrayLength();
+ if (sv_length != length) SlErrorCorrupt("Fixed-length array is of wrong length");
+ }
+
+ SlCopyInternal(array, length, conv);
+ return;
+ }
+
+ case SLA_PTRS:
+ case SLA_NULL:
+ return;
+
+ default:
+ NOT_REACHED();
+ }
+}
/**
* Pointers cannot be saved to a savegame, so this functions gets