25 #include "player.h" |
25 #include "player.h" |
26 #include "saveload.h" |
26 #include "saveload.h" |
27 #include "network/network.h" |
27 #include "network/network.h" |
28 #include "variables.h" |
28 #include "variables.h" |
29 #include <setjmp.h> |
29 #include <setjmp.h> |
30 |
30 #include <list> |
31 extern const uint16 SAVEGAME_VERSION = 54; |
31 |
|
32 extern const uint16 SAVEGAME_VERSION = 57; |
32 uint16 _sl_version; ///< the major savegame version identifier |
33 uint16 _sl_version; ///< the major savegame version identifier |
33 byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! |
34 byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! |
34 |
35 |
35 typedef void WriterProc(uint len); |
36 typedef void WriterProc(uint len); |
36 typedef uint ReaderProc(); |
37 typedef uint ReaderProc(); |
249 { |
250 { |
250 if (i >= (1 << 7)) { |
251 if (i >= (1 << 7)) { |
251 if (i >= (1 << 14)) { |
252 if (i >= (1 << 14)) { |
252 if (i >= (1 << 21)) { |
253 if (i >= (1 << 21)) { |
253 assert(i < (1 << 28)); |
254 assert(i < (1 << 28)); |
254 SlWriteByte((byte)0xE0 | (i>>24)); |
255 SlWriteByte((byte)0xE0 | (i >> 24)); |
255 SlWriteByte((byte)(i>>16)); |
256 SlWriteByte((byte)(i >> 16)); |
256 } else { |
257 } else { |
257 SlWriteByte((byte)0xC0 | (i>>16)); |
258 SlWriteByte((byte)0xC0 | (i >> 16)); |
258 } |
259 } |
259 SlWriteByte((byte)(i>>8)); |
260 SlWriteByte((byte)(i >> 8)); |
260 } else { |
261 } else { |
261 SlWriteByte((byte)(0x80 | (i>>8))); |
262 SlWriteByte((byte)(0x80 | (i >> 8))); |
262 } |
263 } |
263 } |
264 } |
264 SlWriteByte(i); |
265 SlWriteByte(i); |
265 } |
266 } |
266 |
267 |
625 a += mem_size; // get size |
626 a += mem_size; // get size |
626 } |
627 } |
627 } |
628 } |
628 } |
629 } |
629 |
630 |
|
631 |
|
632 static uint ReferenceToInt(const void* obj, SLRefType rt); |
|
633 static void* IntToReference(uint index, SLRefType rt); |
|
634 |
|
635 |
|
636 /** |
|
637 * Return the size in bytes of a list |
|
638 * @param list The std::list to find the size of |
|
639 */ |
|
640 static inline size_t SlCalcListLen(const void *list) |
|
641 { |
|
642 std::list<void *> *l = (std::list<void *> *) list; |
|
643 |
|
644 /* Each entry is saved as 2 bytes, plus 2 bytes are used for the length |
|
645 * of the list */ |
|
646 return l->size() * 2 + 2; |
|
647 } |
|
648 |
|
649 |
|
650 /** |
|
651 * Save/Load a list. |
|
652 * @param list The list being manipulated |
|
653 * @param conv SLRefType type of the list (Vehicle *, Station *, etc) |
|
654 */ |
|
655 void SlList(void *list, SLRefType conv) |
|
656 { |
|
657 /* Automatically calculate the length? */ |
|
658 if (_sl.need_length != NL_NONE) { |
|
659 SlSetLength(SlCalcListLen(list)); |
|
660 /* Determine length only? */ |
|
661 if (_sl.need_length == NL_CALCLENGTH) return; |
|
662 } |
|
663 |
|
664 std::list<void *> *l = (std::list<void *> *) list; |
|
665 |
|
666 if (_sl.save) { |
|
667 SlWriteUint16(l->size()); |
|
668 |
|
669 std::list<void *>::iterator iter; |
|
670 for (iter = l->begin(); iter != l->end(); ++iter) { |
|
671 void *ptr = *iter; |
|
672 SlWriteUint16(ReferenceToInt(ptr, conv)); |
|
673 } |
|
674 } else { |
|
675 uint length = SlReadUint16(); |
|
676 |
|
677 /* Load each reference and push to the end of the list */ |
|
678 for (uint i = 0; i < length; i++) { |
|
679 void *ptr = IntToReference(SlReadUint16(), conv); |
|
680 l->push_back(ptr); |
|
681 } |
|
682 } |
|
683 } |
|
684 |
|
685 |
630 /** Are we going to save this object or not? */ |
686 /** Are we going to save this object or not? */ |
631 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) |
687 static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) |
632 { |
688 { |
633 if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false; |
689 if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false; |
634 if (sld->conv & SLF_SAVE_NO) return false; |
690 if (sld->conv & SLF_SAVE_NO) return false; |
673 switch (sld->cmd) { |
729 switch (sld->cmd) { |
674 case SL_VAR: |
730 case SL_VAR: |
675 case SL_REF: |
731 case SL_REF: |
676 case SL_ARR: |
732 case SL_ARR: |
677 case SL_STR: |
733 case SL_STR: |
|
734 case SL_LST: |
678 /* CONDITIONAL saveload types depend on the savegame version */ |
735 /* CONDITIONAL saveload types depend on the savegame version */ |
679 if (!SlIsObjectValidInSavegame(sld)) break; |
736 if (!SlIsObjectValidInSavegame(sld)) break; |
680 |
737 |
681 switch (sld->cmd) { |
738 switch (sld->cmd) { |
682 case SL_VAR: return SlCalcConvFileLen(sld->conv); |
739 case SL_VAR: return SlCalcConvFileLen(sld->conv); |
683 case SL_REF: return SlCalcRefLen(); |
740 case SL_REF: return SlCalcRefLen(); |
684 case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv); |
741 case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv); |
685 case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv); |
742 case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv); |
|
743 case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld)); |
686 default: NOT_REACHED(); |
744 default: NOT_REACHED(); |
687 } |
745 } |
688 break; |
746 break; |
689 case SL_WRITEBYTE: return 1; // a byte is logically of size 1 |
747 case SL_WRITEBYTE: return 1; // a byte is logically of size 1 |
690 case SL_INCLUDE: return SlCalcObjLength(object, _sl.includes[sld->version_from]); |
748 case SL_INCLUDE: return SlCalcObjLength(object, _sl.includes[sld->version_from]); |
692 } |
750 } |
693 return 0; |
751 return 0; |
694 } |
752 } |
695 |
753 |
696 |
754 |
697 static uint ReferenceToInt(const void* obj, SLRefType rt); |
|
698 static void* IntToReference(uint index, SLRefType rt); |
|
699 |
|
700 |
|
701 bool SlObjectMember(void *ptr, const SaveLoad *sld) |
755 bool SlObjectMember(void *ptr, const SaveLoad *sld) |
702 { |
756 { |
703 VarType conv = GB(sld->conv, 0, 8); |
757 VarType conv = GB(sld->conv, 0, 8); |
704 switch (sld->cmd) { |
758 switch (sld->cmd) { |
705 case SL_VAR: |
759 case SL_VAR: |
706 case SL_REF: |
760 case SL_REF: |
707 case SL_ARR: |
761 case SL_ARR: |
708 case SL_STR: |
762 case SL_STR: |
|
763 case SL_LST: |
709 /* CONDITIONAL saveload types depend on the savegame version */ |
764 /* CONDITIONAL saveload types depend on the savegame version */ |
710 if (!SlIsObjectValidInSavegame(sld)) return false; |
765 if (!SlIsObjectValidInSavegame(sld)) return false; |
711 if (SlSkipVariableOnLoad(sld)) return false; |
766 if (SlSkipVariableOnLoad(sld)) return false; |
712 |
767 |
713 switch (sld->cmd) { |
768 switch (sld->cmd) { |
720 *(void**)ptr = IntToReference(SlReadUint16(), (SLRefType)conv); |
775 *(void**)ptr = IntToReference(SlReadUint16(), (SLRefType)conv); |
721 } |
776 } |
722 break; |
777 break; |
723 case SL_ARR: SlArray(ptr, sld->length, conv); break; |
778 case SL_ARR: SlArray(ptr, sld->length, conv); break; |
724 case SL_STR: SlString(ptr, sld->length, conv); break; |
779 case SL_STR: SlString(ptr, sld->length, conv); break; |
|
780 case SL_LST: SlList(ptr, (SLRefType)conv); break; |
725 default: NOT_REACHED(); |
781 default: NOT_REACHED(); |
726 } |
782 } |
727 break; |
783 break; |
728 |
784 |
729 /* SL_WRITEBYTE translates a value of a variable to another one upon |
785 /* SL_WRITEBYTE translates a value of a variable to another one upon |
923 */ |
979 */ |
924 static const ChunkHandler *SlFindChunkHandler(uint32 id) |
980 static const ChunkHandler *SlFindChunkHandler(uint32 id) |
925 { |
981 { |
926 const ChunkHandler *ch; |
982 const ChunkHandler *ch; |
927 const ChunkHandler *const *chsc; |
983 const ChunkHandler *const *chsc; |
928 for (chsc = _sl.chs; (ch=*chsc++) != NULL;) { |
984 for (chsc = _sl.chs; (ch = *chsc++) != NULL;) { |
929 for (;;) { |
985 for (;;) { |
930 if (ch->id == id) return ch; |
986 if (ch->id == id) return ch; |
931 if (ch->flags & CH_LAST) break; |
987 if (ch->flags & CH_LAST) break; |
932 ch++; |
988 ch++; |
933 } |
989 } |