286 { |
285 { |
287 _sl.need_length = NL_WANTLENGTH; |
286 _sl.need_length = NL_WANTLENGTH; |
288 _sl.array_index = index; |
287 _sl.array_index = index; |
289 } |
288 } |
290 |
289 |
|
290 static uint32 _next_offs; |
|
291 |
291 /** |
292 /** |
292 * Iterate through the elements of an array and read the whole thing |
293 * Iterate through the elements of an array and read the whole thing |
293 * @return The index of the object, or -1 if we have reached the end of current block |
294 * @return The index of the object, or -1 if we have reached the end of current block |
294 */ |
295 */ |
295 int SlIterateArray() |
296 int SlIterateArray() |
296 { |
297 { |
297 int index; |
298 int index; |
298 static uint32 next_offs; |
|
299 |
299 |
300 /* After reading in the whole array inside the loop |
300 /* After reading in the whole array inside the loop |
301 * we must have read in all the data, so we must be at end of current block. */ |
301 * we must have read in all the data, so we must be at end of current block. */ |
302 assert(next_offs == 0 || SlGetOffs() == next_offs); |
302 if (_next_offs != 0 && SlGetOffs() != _next_offs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size"); |
303 |
303 |
304 while (true) { |
304 while (true) { |
305 uint length = SlReadArrayLength(); |
305 uint length = SlReadArrayLength(); |
306 if (length == 0) { |
306 if (length == 0) { |
307 next_offs = 0; |
307 _next_offs = 0; |
308 return -1; |
308 return -1; |
309 } |
309 } |
310 |
310 |
311 _sl.obj_len = --length; |
311 _sl.obj_len = --length; |
312 next_offs = SlGetOffs() + length; |
312 _next_offs = SlGetOffs() + length; |
313 |
313 |
314 switch (_sl.block_mode) { |
314 switch (_sl.block_mode) { |
315 case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break; |
315 case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break; |
316 case CH_ARRAY: index = _sl.array_index++; break; |
316 case CH_ARRAY: index = _sl.array_index++; break; |
317 default: |
317 default: |
494 * @param length maximum length of the string (buffer). If -1 we don't care |
494 * @param length maximum length of the string (buffer). If -1 we don't care |
495 * about a maximum length, but take string length as it is. |
495 * about a maximum length, but take string length as it is. |
496 * @return return the net length of the string */ |
496 * @return return the net length of the string */ |
497 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length) |
497 static inline size_t SlCalcNetStringLen(const char *ptr, size_t length) |
498 { |
498 { |
|
499 if (ptr == NULL) return 0; |
499 return minu(strlen(ptr), length - 1); |
500 return minu(strlen(ptr), length - 1); |
500 } |
501 } |
501 |
502 |
502 /** Calculate the gross length of the string that it |
503 /** Calculate the gross length of the string that it |
503 * will occupy in the savegame. This includes the real length, returned |
504 * will occupy in the savegame. This includes the real length, returned |
571 } |
572 } |
572 break; |
573 break; |
573 case SLE_VAR_STR: |
574 case SLE_VAR_STR: |
574 case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate |
575 case SLE_VAR_STRQ: // Malloc'd string, free previous incarnation, and allocate |
575 free(*(char**)ptr); |
576 free(*(char**)ptr); |
576 *(char**)ptr = (char*)malloc(len + 1); // terminating '\0' |
577 if (len == 0) { |
577 ptr = *(char**)ptr; |
578 *(char**)ptr = NULL; |
578 SlCopyBytes(ptr, len); |
579 } else { |
|
580 *(char**)ptr = (char*)malloc(len + 1); // terminating '\0' |
|
581 ptr = *(char**)ptr; |
|
582 SlCopyBytes(ptr, len); |
|
583 } |
579 break; |
584 break; |
580 } |
585 } |
581 |
586 |
582 ((char*)ptr)[len] = '\0'; // properly terminate the string |
587 ((char*)ptr)[len] = '\0'; // properly terminate the string |
583 } |
588 } |
1597 if (!_do_autosave) ShowErrorMessage(INVALID_STRING_ID, STR_SAVE_STILL_IN_PROGRESS, 0, 0); |
1602 if (!_do_autosave) ShowErrorMessage(INVALID_STRING_ID, STR_SAVE_STILL_IN_PROGRESS, 0, 0); |
1598 return SL_OK; |
1603 return SL_OK; |
1599 } |
1604 } |
1600 WaitTillSaved(); |
1605 WaitTillSaved(); |
1601 |
1606 |
|
1607 _next_offs = 0; |
|
1608 |
1602 /* Load a TTDLX or TTDPatch game */ |
1609 /* Load a TTDLX or TTDPatch game */ |
1603 if (mode == SL_OLD_LOAD) { |
1610 if (mode == SL_OLD_LOAD) { |
1604 InitializeGame(IG_DATE_RESET, 256, 256); // set a mapsize of 256x256 for TTDPatch games or it might get confused |
1611 InitializeGame(IG_DATE_RESET, 256, 256); // set a mapsize of 256x256 for TTDPatch games or it might get confused |
1605 if (!LoadOldSaveGame(filename)) return SL_REINIT; |
1612 if (!LoadOldSaveGame(filename)) return SL_REINIT; |
1606 _sl_version = 0; |
1613 _sl_version = 0; |