From 76d8fd9e6b585428a11c4ba5591a44365979772d Mon Sep 17 00:00:00 2001 From: OmniBlade Date: Wed, 28 Apr 2021 22:12:12 +0100 Subject: [PATCH] [TD] Updates Save/Load code to use Pipe/Straw system. Adds LCW compression and SHA1 checksum. Uses CDFileClass to ensure files are saved/loaded to/from user data folder. Adds prefix for side to save/load menu items similar to RA. --- tiberiandawn/base.cpp | 28 +- tiberiandawn/base.h | 7 +- tiberiandawn/cell.h | 7 +- tiberiandawn/dllinterface.cpp | 106 +++---- tiberiandawn/function.h | 6 +- tiberiandawn/heap.cpp | 2 +- tiberiandawn/heap.h | 49 +-- tiberiandawn/iomap.cpp | 87 +++--- tiberiandawn/ioobj.cpp | 36 +-- tiberiandawn/layer.h | 6 +- tiberiandawn/loaddlg.cpp | 76 +++-- tiberiandawn/mouse.h | 7 +- tiberiandawn/saveload.cpp | 532 +++++++++++++++++++-------------- tiberiandawn/sidebarglyphx.cpp | 14 +- tiberiandawn/sidebarglyphx.h | 11 +- tiberiandawn/teamtype.h | 7 +- 16 files changed, 547 insertions(+), 434 deletions(-) diff --git a/tiberiandawn/base.cpp b/tiberiandawn/base.cpp index 569a215a..f025d729 100644 --- a/tiberiandawn/base.cpp +++ b/tiberiandawn/base.cpp @@ -240,7 +240,7 @@ void BaseClass::Write_INI(CCINIClass& ini) * HISTORY: * * 03/24/1995 BRR : Created. * *=============================================================================================*/ -bool BaseClass::Load(FileClass& file) +bool BaseClass::Load(Straw& file) { int num_struct; int i; @@ -249,7 +249,7 @@ bool BaseClass::Load(FileClass& file) /* ** Read in & check the size of this class */ - if (file.Read(&i, sizeof(i)) != sizeof(i)) { + if (file.Get(&i, sizeof(i)) != sizeof(i)) { return (false); } @@ -260,11 +260,11 @@ bool BaseClass::Load(FileClass& file) /* ** Read in the House & the number of structures in the base */ - if (file.Read(&House, sizeof(House)) != sizeof(House)) { + if (file.Get(&House, sizeof(House)) != sizeof(House)) { return (false); } - if (file.Read(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) { + if (file.Get(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) { return (false); } @@ -272,7 +272,7 @@ bool BaseClass::Load(FileClass& file) ** Read each node entry & add it to the list */ for (i = 0; i < num_struct; i++) { - if (file.Read(&node, sizeof(node)) != sizeof(node)) { + if (file.Get(&node, sizeof(node)) != sizeof(node)) { return (false); } Nodes.Add(node); @@ -296,7 +296,7 @@ bool BaseClass::Load(FileClass& file) * HISTORY: * * 03/24/1995 BRR : Created. * *=============================================================================================*/ -bool BaseClass::Save(FileClass& file) +bool BaseClass::Save(Pipe& file) const { int num_struct; int i; @@ -306,30 +306,22 @@ bool BaseClass::Save(FileClass& file) ** Write the size of this class */ i = sizeof(*this); - if (file.Write(&i, sizeof(i)) != sizeof(i)) { - return (false); - } + file.Put(&i, sizeof(i)); /* ** Write the House & the number of structures in the base */ - if (file.Write(&House, sizeof(House)) != sizeof(House)) { - return (false); - } + file.Put(&House, sizeof(House)); num_struct = Nodes.Count(); - if (file.Write(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) { - return (false); - } + file.Put(&num_struct, sizeof(num_struct)); /* ** Write each node entry */ for (i = 0; i < num_struct; i++) { node = Nodes[i]; - if (file.Write(&node, sizeof(node)) != sizeof(node)) { - return (false); - } + file.Put(&node, sizeof(node)); } return (true); diff --git a/tiberiandawn/base.h b/tiberiandawn/base.h index 36184aad..84c89573 100644 --- a/tiberiandawn/base.h +++ b/tiberiandawn/base.h @@ -33,6 +33,9 @@ #ifndef BASE_H #define BASE_H +class Straw; +class Pipe; + /**************************************************************************** ** This class defines one "node" in the pre-built base list. Each node ** contains a type of building to build, and the COORD to build it at. @@ -82,8 +85,8 @@ class BaseClass { return "Base"; } - bool Load(FileClass& file); - bool Save(FileClass& file); + bool Load(Straw& file); + bool Save(Pipe& file) const; virtual void Code_Pointers(void){}; virtual void Decode_Pointers(void){}; diff --git a/tiberiandawn/cell.h b/tiberiandawn/cell.h index 1d172272..57e238e6 100644 --- a/tiberiandawn/cell.h +++ b/tiberiandawn/cell.h @@ -39,6 +39,9 @@ #include "unit.h" #include "template.h" +class Pipe; +class Straw; + /**************************************************************************** ** Each cell on the map is controlled by the following structure. */ @@ -246,8 +249,8 @@ class CellClass ** File I/O. */ bool Should_Save(void) const; - bool Save(FileClass& file); - bool Load(FileClass& file); + bool Save(Pipe& file) const; + bool Load(Straw& file); void Code_Pointers(void); void Decode_Pointers(void); diff --git a/tiberiandawn/dllinterface.cpp b/tiberiandawn/dllinterface.cpp index 7ccce4b2..7202c5b0 100644 --- a/tiberiandawn/dllinterface.cpp +++ b/tiberiandawn/dllinterface.cpp @@ -33,6 +33,8 @@ #include "defines.h" // VOC_COUNT, VOX_COUNT #include "sidebarglyphx.h" #include "common/irandom.h" +#include "common/pipe.h" +#include "common/straw.h" /* ** Externs @@ -365,8 +367,8 @@ class DLLExportClass static void Set_Special_Key_Flags(unsigned char special_key_flags); static void Clear_Special_Key_Flags(); - static bool Load(FileClass& file); - static bool Save(FileClass& file); + static bool Load(Straw& file); + static bool Save(Pipe& file); static void Code_Pointers(void); static void Decode_Pointers(void); @@ -7399,12 +7401,12 @@ bool DLL_Export_Get_Input_Key_State(KeyNumType key) return DLLExportClass::Get_Input_Key_State(key); } -bool DLLSave(FileClass& file) +bool DLLSave(Pipe& file) { return DLLExportClass::Save(file); } -bool DLLLoad(FileClass& file) +bool DLLLoad(Straw& file) { return DLLExportClass::Load(file); } @@ -7420,90 +7422,90 @@ bool DLLLoad(FileClass& file) * * History: 9/10/2019 10:24AM - ST **************************************************************************************************/ -bool DLLExportClass::Save(FileClass& file) +bool DLLExportClass::Save(Pipe& file) { /* ** Version first */ unsigned int version = CNC_DLL_API_VERSION; - if (file.Write(&version, sizeof(version)) != sizeof(version)) { + if (file.Put(&version, sizeof(version)) != sizeof(version)) { return false; } - if (file.Write(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { + if (file.Put(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { return false; } - if (file.Write(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs)) != sizeof(GlyphxPlayerIDs)) { + if (file.Put(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs)) != sizeof(GlyphxPlayerIDs)) { return false; } - if (file.Write(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons)) + if (file.Put(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons)) != sizeof(GlyphXClientSidebarWidthInLeptons)) { return false; } - if (file.Write(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { + if (file.Put(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { return false; } - if (file.Write(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { + if (file.Put(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { return false; } - if (file.Write(PlacementType, sizeof(PlacementType)) != sizeof(PlacementType)) { + if (file.Put(PlacementType, sizeof(PlacementType)) != sizeof(PlacementType)) { return false; } - if (file.Write(&MPlayerCount, sizeof(MPlayerCount)) != sizeof(MPlayerCount)) { + if (file.Put(&MPlayerCount, sizeof(MPlayerCount)) != sizeof(MPlayerCount)) { return false; } - if (file.Write(&MPlayerBases, sizeof(MPlayerBases)) != sizeof(MPlayerBases)) { + if (file.Put(&MPlayerBases, sizeof(MPlayerBases)) != sizeof(MPlayerBases)) { return false; } - if (file.Write(&MPlayerCredits, sizeof(MPlayerCredits)) != sizeof(MPlayerCredits)) { + if (file.Put(&MPlayerCredits, sizeof(MPlayerCredits)) != sizeof(MPlayerCredits)) { return false; } - if (file.Write(&MPlayerTiberium, sizeof(MPlayerTiberium)) != sizeof(MPlayerTiberium)) { + if (file.Put(&MPlayerTiberium, sizeof(MPlayerTiberium)) != sizeof(MPlayerTiberium)) { return false; } - if (file.Write(&MPlayerGoodies, sizeof(MPlayerGoodies)) != sizeof(MPlayerGoodies)) { + if (file.Put(&MPlayerGoodies, sizeof(MPlayerGoodies)) != sizeof(MPlayerGoodies)) { return false; } - if (file.Write(&MPlayerGhosts, sizeof(MPlayerGhosts)) != sizeof(MPlayerGhosts)) { + if (file.Put(&MPlayerGhosts, sizeof(MPlayerGhosts)) != sizeof(MPlayerGhosts)) { return false; } - if (file.Write(&MPlayerSolo, sizeof(MPlayerSolo)) != sizeof(MPlayerSolo)) { + if (file.Put(&MPlayerSolo, sizeof(MPlayerSolo)) != sizeof(MPlayerSolo)) { return false; } - if (file.Write(&MPlayerUnitCount, sizeof(MPlayerUnitCount)) != sizeof(MPlayerUnitCount)) { + if (file.Put(&MPlayerUnitCount, sizeof(MPlayerUnitCount)) != sizeof(MPlayerUnitCount)) { return false; } - if (file.Write(&MPlayerLocalID, sizeof(MPlayerLocalID)) != sizeof(MPlayerLocalID)) { + if (file.Put(&MPlayerLocalID, sizeof(MPlayerLocalID)) != sizeof(MPlayerLocalID)) { return false; } - if (file.Write(MPlayerHouses, sizeof(MPlayerHouses)) != sizeof(MPlayerHouses)) { + if (file.Put(MPlayerHouses, sizeof(MPlayerHouses)) != sizeof(MPlayerHouses)) { return false; } - if (file.Write(MPlayerNames, sizeof(MPlayerNames)) != sizeof(MPlayerNames)) { + if (file.Put(MPlayerNames, sizeof(MPlayerNames)) != sizeof(MPlayerNames)) { return false; } - if (file.Write(MPlayerID, sizeof(MPlayerID)) != sizeof(MPlayerID)) { + if (file.Put(MPlayerID, sizeof(MPlayerID)) != sizeof(MPlayerID)) { return false; } - if (file.Write(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { + if (file.Put(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { return false; } @@ -7511,7 +7513,7 @@ bool DLLExportClass::Save(FileClass& file) Sidebar_Glyphx_Save(file, &MultiplayerSidebars[i]); } - if (file.Write(&Special, sizeof(Special)) != sizeof(Special)) { + if (file.Put(&Special, sizeof(Special)) != sizeof(Special)) { return false; } @@ -7519,7 +7521,7 @@ bool DLLExportClass::Save(FileClass& file) ** Special case for Rule.AllowSuperWeapons - store negated value so it defaults to enabled */ bool not_allow_super_weapons = !Rule.AllowSuperWeapons; - if (file.Write(¬_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) { + if (file.Put(¬_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) { return false; } @@ -7529,7 +7531,7 @@ bool DLLExportClass::Save(FileClass& file) unsigned char padding[4095]; memset(padding, 0, sizeof(padding)); - if (file.Write(padding, sizeof(padding)) != sizeof(padding)) { + if (file.Put(padding, sizeof(padding)) != sizeof(padding)) { return false; } @@ -7547,88 +7549,88 @@ bool DLLExportClass::Save(FileClass& file) * * History: 9/10/2019 10:24AM - ST **************************************************************************************************/ -bool DLLExportClass::Load(FileClass& file) +bool DLLExportClass::Load(Straw& file) { unsigned int version = 0; - if (file.Read(&version, sizeof(version)) != sizeof(version)) { + if (file.Get(&version, sizeof(version)) != sizeof(version)) { return false; } - if (file.Read(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { + if (file.Get(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { return false; } - if (file.Read(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs)) != sizeof(GlyphxPlayerIDs)) { + if (file.Get(GlyphxPlayerIDs, sizeof(GlyphxPlayerIDs)) != sizeof(GlyphxPlayerIDs)) { return false; } - if (file.Read(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons)) + if (file.Get(&GlyphXClientSidebarWidthInLeptons, sizeof(GlyphXClientSidebarWidthInLeptons)) != sizeof(GlyphXClientSidebarWidthInLeptons)) { return false; } - if (file.Read(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { + if (file.Get(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { return false; } - if (file.Read(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { + if (file.Get(MultiplayerStartPositions, sizeof(MultiplayerStartPositions)) != sizeof(MultiplayerStartPositions)) { return false; } - if (file.Read(PlacementType, sizeof(PlacementType)) != sizeof(PlacementType)) { + if (file.Get(PlacementType, sizeof(PlacementType)) != sizeof(PlacementType)) { return false; } - if (file.Read(&MPlayerCount, sizeof(MPlayerCount)) != sizeof(MPlayerCount)) { + if (file.Get(&MPlayerCount, sizeof(MPlayerCount)) != sizeof(MPlayerCount)) { return false; } - if (file.Read(&MPlayerBases, sizeof(MPlayerBases)) != sizeof(MPlayerBases)) { + if (file.Get(&MPlayerBases, sizeof(MPlayerBases)) != sizeof(MPlayerBases)) { return false; } - if (file.Read(&MPlayerCredits, sizeof(MPlayerCredits)) != sizeof(MPlayerCredits)) { + if (file.Get(&MPlayerCredits, sizeof(MPlayerCredits)) != sizeof(MPlayerCredits)) { return false; } - if (file.Read(&MPlayerTiberium, sizeof(MPlayerTiberium)) != sizeof(MPlayerTiberium)) { + if (file.Get(&MPlayerTiberium, sizeof(MPlayerTiberium)) != sizeof(MPlayerTiberium)) { return false; } - if (file.Read(&MPlayerGoodies, sizeof(MPlayerGoodies)) != sizeof(MPlayerGoodies)) { + if (file.Get(&MPlayerGoodies, sizeof(MPlayerGoodies)) != sizeof(MPlayerGoodies)) { return false; } - if (file.Read(&MPlayerGhosts, sizeof(MPlayerGhosts)) != sizeof(MPlayerGhosts)) { + if (file.Get(&MPlayerGhosts, sizeof(MPlayerGhosts)) != sizeof(MPlayerGhosts)) { return false; } - if (file.Read(&MPlayerSolo, sizeof(MPlayerSolo)) != sizeof(MPlayerSolo)) { + if (file.Get(&MPlayerSolo, sizeof(MPlayerSolo)) != sizeof(MPlayerSolo)) { return false; } - if (file.Read(&MPlayerUnitCount, sizeof(MPlayerUnitCount)) != sizeof(MPlayerUnitCount)) { + if (file.Get(&MPlayerUnitCount, sizeof(MPlayerUnitCount)) != sizeof(MPlayerUnitCount)) { return false; } - if (file.Read(&MPlayerLocalID, sizeof(MPlayerLocalID)) != sizeof(MPlayerLocalID)) { + if (file.Get(&MPlayerLocalID, sizeof(MPlayerLocalID)) != sizeof(MPlayerLocalID)) { return false; } - if (file.Read(MPlayerHouses, sizeof(MPlayerHouses)) != sizeof(MPlayerHouses)) { + if (file.Get(MPlayerHouses, sizeof(MPlayerHouses)) != sizeof(MPlayerHouses)) { return false; } - if (file.Read(MPlayerNames, sizeof(MPlayerNames)) != sizeof(MPlayerNames)) { + if (file.Get(MPlayerNames, sizeof(MPlayerNames)) != sizeof(MPlayerNames)) { return false; } - if (file.Read(MPlayerID, sizeof(MPlayerID)) != sizeof(MPlayerID)) { + if (file.Get(MPlayerID, sizeof(MPlayerID)) != sizeof(MPlayerID)) { return false; } - if (file.Read(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { + if (file.Get(MPlayerIsHuman, sizeof(MPlayerIsHuman)) != sizeof(MPlayerIsHuman)) { return false; } @@ -7636,7 +7638,7 @@ bool DLLExportClass::Load(FileClass& file) Sidebar_Glyphx_Load(file, &MultiplayerSidebars[i]); } - if (file.Read(&Special, sizeof(Special)) != sizeof(Special)) { + if (file.Get(&Special, sizeof(Special)) != sizeof(Special)) { return false; } @@ -7644,14 +7646,14 @@ bool DLLExportClass::Load(FileClass& file) ** Special case for Rule.AllowSuperWeapons - store negated value so it defaults to enabled */ bool not_allow_super_weapons = false; - if (file.Read(¬_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) { + if (file.Get(¬_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) { return false; } Rule.AllowSuperWeapons = !not_allow_super_weapons; unsigned char padding[4095]; - if (file.Read(padding, sizeof(padding)) != sizeof(padding)) { + if (file.Get(padding, sizeof(padding)) != sizeof(padding)) { return false; } diff --git a/tiberiandawn/function.h b/tiberiandawn/function.h index 48bfbad7..861c43d3 100644 --- a/tiberiandawn/function.h +++ b/tiberiandawn/function.h @@ -243,6 +243,8 @@ inline CELL Coord_YCell(COORDINATE coord) #include "ipxaddr.h" #include "common/miscasm.h" #include "common/face.h" +#include "common/pipe.h" +#include "common/straw.h" /**************************************************************************** ** This is a "node", used for the lists of available games & players. The ** 'Game' structure is used for games; the 'Player' structure for players. @@ -621,8 +623,8 @@ int Create_Air_Reinforcement(HouseClass* house, /* ** SAVELOAD.CPP */ -bool Load_Misc_Values(FileClass& file); -bool Save_Misc_Values(FileClass& file); +bool Load_Misc_Values(Straw& file); +bool Save_Misc_Values(Pipe& file); bool Get_Savefile_Info(int id, char* buf, unsigned* scenp, HousesType* housep); bool Load_Game(int id); bool Load_Game(const char* file_name); diff --git a/tiberiandawn/heap.cpp b/tiberiandawn/heap.cpp index d888b0f1..52d24b4c 100644 --- a/tiberiandawn/heap.cpp +++ b/tiberiandawn/heap.cpp @@ -245,7 +245,7 @@ int FixedHeapClass::Free(void* pointer) * HISTORY: * * 02/21/1995 JLB : Created. * *=============================================================================================*/ -int FixedHeapClass::ID(void const* pointer) +int FixedHeapClass::ID(void const* pointer) const { if (pointer && Size) { return ((int)(((char*)pointer - (char*)Buffer) / Size)); diff --git a/tiberiandawn/heap.h b/tiberiandawn/heap.h index 130eac84..a8f3b5da 100644 --- a/tiberiandawn/heap.h +++ b/tiberiandawn/heap.h @@ -36,6 +36,8 @@ #define HEAP_H #include "vector.h" +#include "common/straw.h" +#include "common/pipe.h" /************************************************************************** ** This is a block memory managment handler. It is used when memory is to @@ -50,16 +52,16 @@ class FixedHeapClass FixedHeapClass(int size); virtual ~FixedHeapClass(void); - int ID(void const* pointer); - int Count(void) + int ID(void const* pointer) const; + int Count(void) const { return ActiveCount; }; - int Length(void) + int Length(void) const { return TotalCount; }; - int Avail(void) + int Avail(void) const { return TotalCount - ActiveCount; }; @@ -128,7 +130,7 @@ template class TFixedHeapClass : public FixedHeapClass : FixedHeapClass(sizeof(T)){}; virtual ~TFixedHeapClass(void){}; - int ID(T const* pointer) + int ID(T const* pointer) const { return FixedHeapClass::ID(pointer); }; @@ -173,6 +175,10 @@ class FixedIHeapClass : public FixedHeapClass return ActivePointers[index]; }; + virtual void const* Active_Ptr(int index) const + { + return ActivePointers[index]; + }; /* ** This is an array of pointers to allocated objects. Using this array ** to control iteration through the objects ensures a minimum of processing. @@ -194,7 +200,7 @@ template class TFixedIHeapClass : public FixedIHeapClass : FixedIHeapClass(sizeof(T)){}; virtual ~TFixedIHeapClass(void){}; - int ID(T const* pointer) + int ID(T const* pointer) const { return FixedIHeapClass::ID(pointer); }; @@ -210,12 +216,12 @@ template class TFixedIHeapClass : public FixedIHeapClass { return FixedIHeapClass::Free(pointer); }; - virtual int Save(FileClass&); - virtual int Load(FileClass&); + virtual int Save(Pipe&) const; + virtual int Load(Straw&); virtual void Code_Pointers(void); virtual void Decode_Pointers(void); - virtual T* Ptr(int index) + virtual T* Ptr(int index) const { return (T*)FixedIHeapClass::ActivePointers[index]; }; @@ -237,35 +243,30 @@ template class TFixedIHeapClass : public FixedIHeapClass * HISTORY: * * 03/15/1995 BRR : Created. * *=============================================================================================*/ -template int TFixedIHeapClass::Save(FileClass& file) +template int TFixedIHeapClass::Save(Pipe& file) const { - int i; // loop counter int idx; // object index /* ** Save the number of instances of this class */ - if (file.Write(&ActiveCount, sizeof(ActiveCount)) != sizeof(ActiveCount)) { - return (false); - } + file.Put(&ActiveCount, sizeof(ActiveCount)); /* ** Save each instance of this class */ - for (i = 0; i < ActiveCount; i++) { + for (int i = 0; i < ActiveCount; i++) { /* ** Save the array index of the object, so it can be loaded back into the ** same array location (so TARGET translations will work) */ - idx = ID(Ptr(i)); - if (file.Write(&idx, sizeof(idx)) != sizeof(idx)) { - return (false); - } + int idx = ID(Ptr(i)); + file.Put(&idx, sizeof(idx)); /* ** Save the object itself */ - file.Write(Ptr(i), sizeof(T)); + file.Put(Ptr(i), sizeof(T)); } return (true); @@ -292,7 +293,7 @@ inline void Load_Object(...) * HISTORY: * * 03/15/1995 BRR : Created. * *=============================================================================================*/ -template int TFixedIHeapClass::Load(FileClass& file) +template int TFixedIHeapClass::Load(Straw& file) { int i; // loop counter int idx; // object index @@ -302,7 +303,7 @@ template int TFixedIHeapClass::Load(FileClass& file) /* ** Read the number of instances of this class */ - if (file.Read(&a_count, sizeof(a_count)) != sizeof(a_count)) { + if (file.Get(&a_count, sizeof(a_count)) != sizeof(a_count)) { return (false); } @@ -320,7 +321,7 @@ template int TFixedIHeapClass::Load(FileClass& file) /* ** Read the object's array index */ - if (file.Read(&idx, sizeof(idx)) != sizeof(idx)) { + if (file.Get(&idx, sizeof(idx)) != sizeof(idx)) { return (false); } @@ -335,7 +336,7 @@ template int TFixedIHeapClass::Load(FileClass& file) /* ** Load the object */ - file.Read(ptr, sizeof(T)); + file.Get(ptr, sizeof(T)); new (ptr) T(NoInitClass()); Load_Object(ptr); } diff --git a/tiberiandawn/iomap.cpp b/tiberiandawn/iomap.cpp index 4d14bd77..9d1b11cd 100644 --- a/tiberiandawn/iomap.cpp +++ b/tiberiandawn/iomap.cpp @@ -64,6 +64,8 @@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" +#include "common/straw.h" +#include "common/pipe.h" #pragma warning(disable : 4302) // Truncation from pointer to TARGET @@ -101,14 +103,14 @@ bool CellClass::Should_Save(void) const * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool CellClass::Load(FileClass& file) +bool CellClass::Load(Straw& file) { TriggerClass* trig; /* -------------------------- Load the object data -------------------------- */ - if (file.Read(this, sizeof(*this)) != sizeof(*this)) { + if (file.Get(this, sizeof(*this)) != sizeof(*this)) { return false; } @@ -116,7 +118,7 @@ bool CellClass::Load(FileClass& file) ------------------------ Load the trigger pointer ------------------------ */ if (IsTrigger) { - if (file.Read(&trig, sizeof(trig)) != sizeof(trig)) + if (file.Get(&trig, sizeof(trig)) != sizeof(trig)) return (false); CellTriggers[Cell_Number()] = trig; } @@ -136,16 +138,14 @@ bool CellClass::Load(FileClass& file) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool CellClass::Save(FileClass& file) +bool CellClass::Save(Pipe& file) const { - if (file.Write(this, sizeof(*this)) != sizeof(*this)) { - return false; - } + file.Put(this, sizeof(*this)); if (IsTrigger) { TriggerClass* trig; trig = CellTriggers[Cell_Number()]; - if (file.Write(&trig, sizeof(trig)) != sizeof(trig)) + if (file.Put(&trig, sizeof(trig)) != sizeof(trig)) return (false); } @@ -307,7 +307,7 @@ void CellClass::Decode_Pointers(void) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool MouseClass::Load(FileClass& file) +bool MouseClass::Load(Straw& file) { unsigned count; CELL cell = 0; @@ -323,7 +323,7 @@ bool MouseClass::Load(FileClass& file) disk will be over-written when initialization occurs. This code must go in the most-derived Map class. ------------------------------------------------------------------------*/ - if (file.Read(&Theater, sizeof(Theater)) != sizeof(Theater)) + if (file.Get(&Theater, sizeof(Theater)) != sizeof(Theater)) return (false); /* @@ -356,10 +356,10 @@ bool MouseClass::Load(FileClass& file) Free_Cells(); /* - ** Read the entire map object in. Only read in sizeof(MouseClass), so if we're + ** Get the entire map object in. Only read in sizeof(MouseClass), so if we're ** in editor mode, none of the map editor object is read in. */ - if (file.Read(this, sizeof(*this)) != sizeof(*this)) { + if (file.Get(this, sizeof(*this)) != sizeof(*this)) { return (false); } new (this) MouseClass(NoInitClass()); @@ -375,17 +375,17 @@ bool MouseClass::Load(FileClass& file) Init_Cells(); /* - --------------------------- Read # cells saved --------------------------- + --------------------------- Get # cells saved --------------------------- */ - if (file.Read(&count, sizeof(count)) != sizeof(count)) { + if (file.Get(&count, sizeof(count)) != sizeof(count)) { return (false); } /* - ------------------------------- Read cells ------------------------------- + ------------------------------- Get cells ------------------------------- */ for (index = 0; index < (int)count; index++) { - if (file.Read(&cell, sizeof(cell)) != sizeof(cell)) + if (file.Get(&cell, sizeof(cell)) != sizeof(cell)) return (false); if (!(*this)[cell].Load(file)) @@ -407,58 +407,49 @@ bool MouseClass::Load(FileClass& file) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool MouseClass::Save(FileClass& file) +bool MouseClass::Save(Pipe& file) { - unsigned count; - int pos; - /* -------------------------- Save Theater >first< -------------------------- */ - if (file.Write(&Theater, sizeof(Theater)) != sizeof(Theater)) - return (false); + TheaterType theater = Theater; + file.Put(&theater, sizeof(theater)); - if (file.Write(this, sizeof(*this)) != sizeof(*this)) - return (false); + file.Put(this, sizeof(*this)); /* - ---------------------- Record current file position ---------------------- + ** Count how many cells will be saved. */ - pos = file.Seek(0, SEEK_CUR); + unsigned count = 0; + CellClass const* cellptr = &(*this)[(CELL)0]; + for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) { + if (cellptr->Should_Save()) { + count++; + } + cellptr++; + } /* - ---------------------- write out placeholder bytes ----------------------- + ** write out count of the cells. */ - if (file.Write(&count, sizeof(count)) != sizeof(count)) - return (false); + file.Put(&count, sizeof(count)); /* - ------------------------ Save cells that need it ------------------------- + ** Save cells that need it */ - count = 0; + cellptr = &(*this)[(CELL)0]; for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) { - - if ((*this)[cell].Should_Save()) { - if (file.Write(&cell, sizeof(cell)) != sizeof(cell)) - return (false); - - count++; - - if (!(*this)[cell].Save(file)) - return (false); + if (cellptr->Should_Save()) { + file.Put(&cell, sizeof(cell)); + cellptr->Save(file); + count--; } + cellptr++; } - /* - -------------------------- Save # cells written -------------------------- - */ - file.Seek(pos, SEEK_SET); - - if (file.Write(&count, sizeof(count)) != sizeof(count)) + if (count != 0) return (false); - file.Seek(0, SEEK_END); - return (true); } diff --git a/tiberiandawn/ioobj.cpp b/tiberiandawn/ioobj.cpp index ebfdda87..81a9812b 100644 --- a/tiberiandawn/ioobj.cpp +++ b/tiberiandawn/ioobj.cpp @@ -144,9 +144,9 @@ * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool TeamTypeClass::Load(FileClass& file) +bool TeamTypeClass::Load(Straw& file) { - if (file.Read(this, sizeof(*this)) != sizeof(*this)) { + if (file.Get(this, sizeof(*this)) != sizeof(*this)) { return false; } ::new (this) TeamTypeClass(NoInitClass()); @@ -165,9 +165,9 @@ bool TeamTypeClass::Load(FileClass& file) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool TeamTypeClass::Save(FileClass& file) +bool TeamTypeClass::Save(Pipe& file) { - return (file.Write(this, sizeof(*this) == sizeof(*this))); + return (file.Put(this, sizeof(*this) == sizeof(*this))); } /*********************************************************************************************** @@ -1162,7 +1162,7 @@ void FactoryClass::Decode_Pointers(void) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool LayerClass::Load(FileClass& file) +bool LayerClass::Load(Straw& file) { int count; int i; @@ -1171,7 +1171,7 @@ bool LayerClass::Load(FileClass& file) /* ---------------------- Read # elements in the layer ---------------------- */ - if (file.Read(&count, sizeof(count)) != sizeof(count)) { + if (file.Get(&count, sizeof(count)) != sizeof(count)) { return (false); } @@ -1184,7 +1184,7 @@ bool LayerClass::Load(FileClass& file) ----------------------- Read in all array elements ----------------------- */ for (i = 0; i < count; i++) { - if (file.Read(&ptr, sizeof(ObjectClass*)) != sizeof(ObjectClass*)) { + if (file.Get(&ptr, sizeof(ObjectClass*)) != sizeof(ObjectClass*)) { return (false); } Add(ptr); @@ -1205,26 +1205,20 @@ bool LayerClass::Load(FileClass& file) * HISTORY: * * 09/19/1994 JLB : Created. * *=============================================================================================*/ -bool LayerClass::Save(FileClass& file) +bool LayerClass::Save(Pipe& file) const { - int count; - int i; - ObjectClass* ptr; - /* - ------------------------- Save # array elements -------------------------- + ** Save # array elements */ - count = Count(); - if (file.Write(&count, sizeof(count)) != sizeof(count)) - return (false); + int count = Count(); + file.Put(&count, sizeof(count)); /* - --------------------------- Save all elements ---------------------------- + ** Save all elements */ - for (i = 0; i < count; i++) { - ptr = (*this)[i]; - if (file.Write(&ptr, sizeof(ObjectClass*)) != sizeof(ObjectClass*)) - return (false); + for (int index = 0; index < count; index++) { + ObjectClass* ptr = (*this)[index]; + file.Put(&ptr, sizeof(ObjectClass*)); } return (true); diff --git a/tiberiandawn/layer.h b/tiberiandawn/layer.h index bf192d6c..c86cd442 100644 --- a/tiberiandawn/layer.h +++ b/tiberiandawn/layer.h @@ -38,6 +38,8 @@ #include "vector.h" class ObjectClass; +class Straw; +class Pipe; class LayerClass : public DynamicVectorClass { @@ -56,8 +58,8 @@ class LayerClass : public DynamicVectorClass /* ** File I/O. */ - bool Load(FileClass& file); - bool Save(FileClass& file); + bool Load(Straw& file); + bool Save(Pipe& file) const; virtual void Code_Pointers(void); virtual void Decode_Pointers(void); }; diff --git a/tiberiandawn/loaddlg.cpp b/tiberiandawn/loaddlg.cpp index fb7e3eaa..ee31d400 100644 --- a/tiberiandawn/loaddlg.cpp +++ b/tiberiandawn/loaddlg.cpp @@ -43,6 +43,7 @@ #include "loaddlg.h" #include "common/file.h" #include "common/framelimit.h" +#include "common/paths.h" /*********************************************************************************************** * LoadOptionsClass::LoadOptionsClass -- class constructor * @@ -481,6 +482,17 @@ int LoadOptionsClass::Process(void) */ if (game_idx != 0) { strcpy(game_descr, listbtn.Get_Item(game_idx)); + + /* + ** Strip any leading parenthesis off of the description. + */ + if (game_descr[0] == '(') { + char* ptr = strchr(game_descr, ')'); + if (ptr != NULL) { + strcpy(game_descr, ptr + 1); + strtrim(game_descr); + } + } } else { game_descr[0] = 0; } @@ -568,10 +580,13 @@ void LoadOptionsClass::Fill_List(ListClass* list) { FileEntryClass* fdata; // for adding entries to 'Files' char descr[DESCRIP_MAX]; + char scan_path[_MAX_PATH]; + char sep[2] = {0}; unsigned scenario; // scenario # HousesType house; // house Find_File_Data* ff = nullptr; int id; + bool found; /* ** Make sure the list is empty @@ -591,38 +606,51 @@ void LoadOptionsClass::Fill_List(ListClass* list) /* ** Find all savegame files */ - bool rc = Find_First("savegame.*", 0, &ff); + sep[0] = PathsClass::SEP; + snprintf(scan_path, sizeof(scan_path), "%s%s%s", Paths.User_Path(), sep, "SAVEGAME.*"); - while (rc) { - /* - ** Extract the game ID from the filename - */ - id = Num_From_Ext(ff->GetName()); - - /* - ** get the game's info; if success, add it to the list - */ - bool ok = Get_Savefile_Info(id, descr, &scenario, &house); + found = Find_First(scan_path, 0, &ff); + while (found) { + if (stricmp(ff->GetName(), NET_SAVE_FILE_NAME) != 0) { + /* + ** Extract the game ID from the filename + */ + id = Num_From_Ext(ff->GetName()); - fdata = new FileEntryClass; + /* + ** get the game's info; if success, add it to the list + */ + bool ok = Get_Savefile_Info(id, descr, &scenario, &house); - fdata->Descr[0] = '\0'; - if (!ok) - strcpy(fdata->Descr, Text_String(TXT_OLD_GAME)); - strncat(fdata->Descr, descr, (sizeof(fdata->Descr) - strlen(fdata->Descr)) - 1); - fdata->Valid = ok; - fdata->Scenario = scenario; - fdata->House = house; - fdata->Num = id; - fdata->DateTime = ff->GetTime(); - Files.Add(fdata); + fdata = new FileEntryClass; + fdata->Descr[0] = '\0'; + if (!ok) { + strcpy(fdata->Descr, Text_String(TXT_OLD_GAME)); + } else { + if (house == HOUSE_BAD) { + sprintf(fdata->Descr, "(%s) ", Text_String(TXT_N_O_D)); + } else { + sprintf(fdata->Descr, "(%s) ", Text_String(TXT_G_D_I)); + } + } + strncat(fdata->Descr, descr, (sizeof(fdata->Descr) - strlen(fdata->Descr)) - 1); + fdata->Valid = ok; + fdata->Scenario = scenario; + fdata->House = house; + fdata->Num = id; + fdata->DateTime = ff->GetTime(); + Files.Add(fdata); + } /* ** Find the next file */ - rc = Find_Next(ff); + found = Find_Next(ff); + } + + if (ff) { + Find_Close(ff); } - Find_Close(ff); /* ** If saving a game, determine a unique file ID for the empty slot diff --git a/tiberiandawn/mouse.h b/tiberiandawn/mouse.h index b492c10a..ca3ac738 100644 --- a/tiberiandawn/mouse.h +++ b/tiberiandawn/mouse.h @@ -38,6 +38,9 @@ #include "stage.h" #include "scroll.h" +class Pipe; +class Straw; + class MouseClass : public ScrollClass { public: @@ -66,8 +69,8 @@ class MouseClass : public ScrollClass /* ** File I/O. */ - virtual bool Load(FileClass& file); - virtual bool Save(FileClass& file); + virtual bool Load(Straw& file); + virtual bool Save(Pipe& file); virtual void Code_Pointers(void); virtual void Decode_Pointers(void); diff --git a/tiberiandawn/saveload.cpp b/tiberiandawn/saveload.cpp index 58d98b1c..0136100f 100644 --- a/tiberiandawn/saveload.cpp +++ b/tiberiandawn/saveload.cpp @@ -45,9 +45,17 @@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" +#include "common/xpipe.h" +#include "shapipe.h" +#include "shastraw.h" +#include "lcwpipe.h" +#include "lcwstraw.h" +#include -extern bool DLLSave(FileClass& file); -extern bool DLLLoad(FileClass& file); +extern bool DLLSave(Pipe& file); +extern bool DLLLoad(Straw& file); + +#define SAVE_BLOCK_SIZE 4096 /* ********************************** Defines ********************************** @@ -62,6 +70,120 @@ extern bool DLLLoad(FileClass& file); + sizeof(TerrainClass) + sizeof(TerrainTypeClass) + sizeof(UnitClass) + sizeof(UnitTypeClass) \ + sizeof(MouseClass) + sizeof(CellClass) + sizeof(FactoryClass) + sizeof(BaseClass) + sizeof(LayerClass) \ + sizeof(Scen.BriefingText) + sizeof(Scen.Waypoint))) +/*********************************************************************************************** + * Put_All -- Store all save game data to the pipe. * + * * + * This is the bulk processor of the game related save game data. All the game object * + * and state data is stored to the pipe specified. * + * * + * INPUT: pipe -- Reference to the pipe that will receive the save game data. * + * * + * OUTPUT: none * + * * + * WARNINGS: none * + * * + * HISTORY: * + * 07/08/1996 JLB : Created. * + *=============================================================================================*/ +static void Put_All(Pipe& pipe, int save_net) +{ + if (!save_net) + Call_Back(); + /* + ** Save the map. The map must be saved first, since it saves the Theater. + */ + Map.Save(pipe); + + if (!save_net) + Call_Back(); + /* + ** Save all game objects. This code saves every object that's stored in a + ** TFixedIHeap class. + */ + Houses.Save(pipe); + if (!save_net) + Call_Back(); + TeamTypes.Save(pipe); + if (!save_net) + Call_Back(); + Teams.Save(pipe); + if (!save_net) + Call_Back(); + Triggers.Save(pipe); + if (!save_net) + Call_Back(); + Aircraft.Save(pipe); + if (!save_net) + Call_Back(); + Anims.Save(pipe); + + if (!save_net) + Call_Back(); + + Buildings.Save(pipe); + if (!save_net) + Call_Back(); + Bullets.Save(pipe); + if (!save_net) + Call_Back(); + Infantry.Save(pipe); + if (!save_net) + Call_Back(); + Overlays.Save(pipe); + if (!save_net) + Call_Back(); + Smudges.Save(pipe); + if (!save_net) + Call_Back(); + Templates.Save(pipe); + if (!save_net) + Call_Back(); + Terrains.Save(pipe); + if (!save_net) + Call_Back(); + Units.Save(pipe); + if (!save_net) + Call_Back(); + Factories.Save(pipe); + if (!save_net) + Call_Back(); + + /* + ** Save the Logic & Map layers + */ + Logic.Save(pipe); + + if (!save_net) + Call_Back(); + + for (int i = 0; i < LAYER_COUNT; i++) { + Map.Layer[i].Save(pipe); + } + + /* + ** Save the Score + */ + pipe.Put(&Score, sizeof(Score)); + if (!save_net) + Call_Back(); + + /* + ** Save the AI Base + */ + Base.Save(pipe); + if (!save_net) + Call_Back(); + + /* + ** Save miscellaneous variables. + */ + Save_Misc_Values(pipe); + + if (!save_net) + Call_Back(); + + pipe.Flush(); +} /*************************************************************************** * Save_Game -- saves a game to disk * @@ -118,15 +240,14 @@ bool Save_Game(int id, char* descr) */ bool Save_Game(const char* file_name, const char* descr) { - RawFileClass file; - int i; - unsigned int version; - unsigned scenario; - HousesType house; - char descr_buf[DESCRIP_MAX]; + int save_net = 0; // 1 = save network/modem game - scenario = Scen.Scenario; // get current scenario # - house = PlayerPtr->Class->House; // get current house + if (GameToPlay == GAME_GLYPHX_MULTIPLAYER) { + save_net = 1; + } + + unsigned scenario = Scen.Scenario; // get current scenario # + HousesType house = PlayerPtr->Class->House; // get current house /* ** Code everybody's pointers @@ -136,20 +257,15 @@ bool Save_Game(const char* file_name, const char* descr) /* ** Open the file */ - if (!file.Open(file_name, WRITE)) { - Decode_All_Pointers(); - return (false); - } + CDFileClass file(file_name); + FilePipe fpipe(&file); + #ifdef REMASTER_BUILD /* ** Save the DLLs variables first, so we can do a version check in the DLL when we begin the load */ if (RunningAsDLL) { - if (!DLLSave(file)) { - file.Close(); - Decode_All_Pointers(); - return false; - } + DLLSave(fpipe); } #endif /* @@ -161,107 +277,55 @@ bool Save_Game(const char* file_name, const char* descr) ** which may or may not be a HousesType number; so, saving 'house' ** here ensures we can always pull out the house for this file.) */ - sprintf(descr_buf, "%s\r\n", descr); // put CR-LF after text - descr_buf[strlen(descr_buf) + 1] = 26; // put CTRL-Z after NULL + char descr_buf[DESCRIP_MAX]; + memset(descr_buf, '\0', sizeof(descr_buf)); + sprintf(descr_buf, "%s\r\n", descr); // put CR-LF after text + // descr_buf[strlen(descr_buf) + 1] = 26; // put CTRL-Z after NULL - if (file.Write(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) { - file.Close(); - return (false); - } + fpipe.Put(descr_buf, DESCRIP_MAX); - if (file.Write(&scenario, sizeof(scenario)) != sizeof(scenario)) { - file.Close(); - return (false); - } + fpipe.Put(&scenario, sizeof(scenario)); - if (file.Write(&house, sizeof(house)) != sizeof(house)) { - file.Close(); - return (false); - } + fpipe.Put(&house, sizeof(house)); /* ** Save the save-game version, for loading verification */ - version = SAVEGAME_VERSION; + uint32_t version = SAVEGAME_VERSION; - if (file.Write(&version, sizeof(version)) != sizeof(version)) { - file.Close(); - return (false); - } + fpipe.Put(&version, sizeof(version)); - Call_Back(); - /* - ** Save the map. The map must be saved first, since it saves the Theater. - */ - Map.Save(file); + int pos = file.Seek(0, SEEK_CUR); - Call_Back(); /* - ** Save all game objects. This code saves every object that's stored in a - ** TFixedIHeap class. + ** Store a dummy message digest. */ - if (!Houses.Save(file) || !TeamTypes.Save(file) || !Teams.Save(file) || !Triggers.Save(file) || !Aircraft.Save(file) - || !Anims.Save(file) || !Buildings.Save(file) || !Bullets.Save(file) || !Infantry.Save(file) - || !Overlays.Save(file) || !Smudges.Save(file) || !Templates.Save(file) || !Terrains.Save(file) - || !Units.Save(file) || !Factories.Save(file)) { - file.Close(); - - Decode_All_Pointers(); - - return (false); - } + char digest[20]; + fpipe.Put(digest, sizeof(digest)); - Call_Back(); /* - ** Save the Logic & Map layers - */ - if (!Logic.Save(file)) { - file.Close(); - Decode_All_Pointers(); - return (false); - } - - for (i = 0; i < LAYER_COUNT; i++) { - if (!Map.Layer[i].Save(file)) { - file.Close(); - Decode_All_Pointers(); - return (false); - } - } - - /* - ** Save the Score + ** Dump the save game data to the file. The data is compressed + ** and then encrypted. The message digest is calculated in the + ** process by using the data just as it is written to disk. */ - if (!Score.Save(file)) { - file.Close(); - Decode_All_Pointers(); - return (false); - } + SHAPipe sha; + LCWPipe compress(LCWPipe::COMPRESS, SAVE_BLOCK_SIZE); + Pipe& pipe = compress; // TODO Make compression optional. + sha.Put_To(fpipe); + compress.Put_To(sha); + Put_All(pipe, save_net); /* - ** Save the AI Base + ** Output the real final message digest. This is the one that is of + ** the data image as it exists on the disk. */ - if (!Base.Save(file)) { - file.Close(); - Decode_All_Pointers(); - return (false); - } - - /* - ** Save miscellaneous variables. - */ - if (!Save_Misc_Values(file)) { - file.Close(); - Decode_All_Pointers(); - return (false); - } + pipe.Flush(); + file.Seek(pos, SEEK_SET); + sha.Result(digest); + fpipe.Put(digest, sizeof(digest)); - Call_Back(); + pipe.End(); - /* - ** Close the file; we're done - */ - file.Close(); Decode_All_Pointers(); return (true); @@ -323,7 +387,7 @@ bool Load_Game(int id) */ bool Load_Game(const char* file_name) { - RawFileClass file; + static char _staging_buffer[32000]; int i; unsigned int version; unsigned scenario; @@ -333,39 +397,96 @@ bool Load_Game(const char* file_name) /* ** Open the file */ - if (!file.Open(file_name, READ)) { + CDFileClass file(file_name); + + if (!file.Is_Available()) { return (false); } + + FileStraw fstraw(file); + + Call_Back(); #ifdef REMASTER_BUILD /* ** Load the DLLs variables first, in case we need to do something different based on version */ if (RunningAsDLL) { - if (!DLLLoad(file)) { - file.Close(); - return false; - } + DLLLoad(fstraw); } #endif /* ** Read & discard the save-game's header info */ - if (file.Read(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) { - file.Close(); + if (fstraw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) { return (false); } - if (file.Read(&scenario, sizeof(scenario)) != sizeof(scenario)) { + if (fstraw.Get(&scenario, sizeof(scenario)) != sizeof(scenario)) { + return (false); + } + + if (fstraw.Get(&house, sizeof(house)) != sizeof(house)) { + return (false); + } + + /* + ** Read in & verify the save-game ID code + */ + if (file.Read(&version, sizeof(version)) != sizeof(version)) { file.Close(); return (false); } - if (file.Read(&house, sizeof(house)) != sizeof(house)) { + if (version != SAVEGAME_VERSION) { file.Close(); return (false); } + /* + ** Get the message digest that is embedded in the file. + */ + char digest[20]; + fstraw.Get(digest, sizeof(digest)); + + /* + ** Remember the file position since we must seek back here to + ** perform the real saved game read. + */ + long pos = file.Seek(0, SEEK_CUR); + + /* + ** Pass the rest of the file through the hash straw so that + ** the digest can be compaired to the one in the file. + */ + SHAStraw sha; + sha.Get_From(fstraw); + for (;;) { + if (sha.Get(_staging_buffer, sizeof(_staging_buffer)) != sizeof(_staging_buffer)) + break; + } + char actual[20]; + sha.Result(actual); + sha.Get_From(NULL); + Call_Back(); + + /* + ** Compare the two digests. If they differ then return a failure condition + ** before any damage could be done. + */ + if (memcmp(actual, digest, sizeof(digest)) != 0) { + return (false); + } + + /* + ** Set up the pipe so that the scenario data can be read. + */ + file.Seek(pos, SEEK_SET); + LCWStraw compress(LCWStraw::DECOMPRESS, SAVE_BLOCK_SIZE); + + compress.Get_From(fstraw); + + Straw& straw = compress; /* ** Clear the scenario so we start fresh; this calls the Init_Clear() routine ** for the Map, and all object arrays. It has the following important @@ -379,19 +500,6 @@ bool Load_Game(const char* file_name) */ Clear_Scenario(); - /* - ** Read in & verify the save-game ID code - */ - if (file.Read(&version, sizeof(version)) != sizeof(version)) { - file.Close(); - return (false); - } - - if (version != SAVEGAME_VERSION) { - file.Close(); - return (false); - } - Call_Back(); /* ** Set the required CD to be in the drive according to the scenario @@ -431,59 +539,60 @@ bool Load_Game(const char* file_name) ** what the Theater is; this must be done before any objects are created, so ** they'll be properly created. */ - Map.Load(file); + Map.Load(straw); Call_Back(); + /* ** Load the object data. */ - if (!Houses.Load(file) || !TeamTypes.Load(file) || !Teams.Load(file) || !Triggers.Load(file) || !Aircraft.Load(file) - || !Anims.Load(file) || !Buildings.Load(file) || !Bullets.Load(file) || !Infantry.Load(file) - || !Overlays.Load(file) || !Smudges.Load(file) || !Templates.Load(file) || !Terrains.Load(file) - || !Units.Load(file) || !Factories.Load(file)) { - file.Close(); - return (false); - } + Houses.Load(straw); + TeamTypes.Load(straw); + Teams.Load(straw); + Triggers.Load(straw); + Aircraft.Load(straw); + Anims.Load(straw); + Buildings.Load(straw); + Bullets.Load(straw); + + Call_Back(); + + Infantry.Load(straw); + Overlays.Load(straw); + Smudges.Load(straw); + Templates.Load(straw); + Terrains.Load(straw); + Units.Load(straw); + Factories.Load(straw); Call_Back(); + /* ** Load the Logic & Map Layers */ - if (!Logic.Load(file)) { - file.Close(); - return (false); - } + Logic.Load(straw); + for (i = 0; i < LAYER_COUNT; i++) { - if (!Map.Layer[i].Load(file)) { - file.Close(); - return (false); - } + Map.Layer[i].Load(straw); } Call_Back(); + /* ** Load the Score */ - if (!Score.Load(file)) { - file.Close(); - return (false); - } + straw.Get(&Score, sizeof(Score)); + new (&Score) ScoreClass(NoInitClass()); /* ** Load the AI Base */ - if (!Base.Load(file)) { - file.Close(); - return (false); - } + Base.Load(straw); /* ** Load miscellaneous variables, including the map size & the Theater */ - if (!Load_Misc_Values(file)) { - file.Close(); - return (false); - } + Load_Misc_Values(straw); file.Close(); Decode_All_Pointers(); @@ -545,7 +654,7 @@ bool Load_Game(const char* file_name) * HISTORY: * * 12/29/1994 BR : Created. * *=========================================================================*/ -bool Save_Misc_Values(FileClass& file) +bool Save_Misc_Values(Pipe& file) { int i, j; int count; // # ptrs in 'CurrentObject' @@ -554,47 +663,34 @@ bool Save_Misc_Values(FileClass& file) /* ** Player's House. */ - if (file.Write(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) { - return (false); - } + file.Put(&PlayerPtr, sizeof(PlayerPtr)); /* ** Save this scenario number. */ - if (file.Write(&Scen.Scenario, sizeof(Scen.Scenario)) != sizeof(Scen.Scenario)) { - return (false); - } + file.Put(&Scen.Scenario, sizeof(Scen.Scenario)); /* ** Save difficulty. */ - if (file.Write(&Scen.Difficulty, sizeof(Scen.Difficulty)) != sizeof(Scen.Difficulty)) { - return (false); - } + file.Put(&Scen.Difficulty, sizeof(Scen.Difficulty)); /* ** Save AI difficulty. */ - if (file.Write(&Scen.CDifficulty, sizeof(Scen.CDifficulty)) != sizeof(Scen.CDifficulty)) { - return (false); - } + file.Put(&Scen.CDifficulty, sizeof(Scen.CDifficulty)); + /* ** Save frame #. */ - if (file.Write(&Frame, sizeof(Frame)) != sizeof(Frame)) { - return (false); - } + file.Put(&Frame, sizeof(Frame)); /* ** Save VQ Movie names. */ - if (file.Write(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) { - return (false); - } + file.Put(WinMovie, sizeof(WinMovie)); - if (file.Write(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) { - return (false); - } + file.Put(LoseMovie, sizeof(LoseMovie)); /* ** Save currently-selected objects list. @@ -603,41 +699,35 @@ bool Save_Misc_Values(FileClass& file) for (i = 0; i < SelectedObjectsType::COUNT; i++) { DynamicVectorClass& selection = CurrentObject.Raw(i); count = selection.Count(); - if (file.Write(&count, sizeof(count)) != sizeof(count)) { - return (false); - } + file.Put(&count, sizeof(count)); /* ** Save the pointers. */ for (j = 0; j < count; j++) { ptr = selection[j]; - if (file.Write(&ptr, sizeof(ptr)) != sizeof(ptr)) { - return (false); - } + file.Put(&ptr, sizeof(ptr)); } } /* ** Save the list of waypoints. */ - if (file.Write(Scen.Waypoint, sizeof(Scen.Waypoint)) != sizeof(Scen.Waypoint)) { - return (false); - } + file.Put(Scen.Waypoint, sizeof(Scen.Waypoint)); - file.Write(&ScenDir, sizeof(ScenDir)); - file.Write(&ScenVar, sizeof(ScenVar)); - file.Write(&Scen.CarryOverMoney, sizeof(Scen.CarryOverMoney)); - file.Write(&Scen.CarryOverPercent, sizeof(Scen.CarryOverPercent)); - file.Write(&BuildLevel, sizeof(BuildLevel)); - file.Write(BriefMovie, sizeof(BriefMovie)); - file.Write(Scen.Views, sizeof(Scen.Views)); - file.Write(&EndCountDown, sizeof(EndCountDown)); - file.Write(Scen.BriefingText, sizeof(Scen.BriefingText)); + file.Put(&ScenDir, sizeof(ScenDir)); + file.Put(&ScenVar, sizeof(ScenVar)); + file.Put(&Scen.CarryOverMoney, sizeof(Scen.CarryOverMoney)); + file.Put(&Scen.CarryOverPercent, sizeof(Scen.CarryOverPercent)); + file.Put(&BuildLevel, sizeof(BuildLevel)); + file.Put(BriefMovie, sizeof(BriefMovie)); + file.Put(Scen.Views, sizeof(Scen.Views)); + file.Put(&EndCountDown, sizeof(EndCountDown)); + file.Put(Scen.BriefingText, sizeof(Scen.BriefingText)); // This is new... - file.Write(ActionMovie, sizeof(ActionMovie)); - file.Write(&TempleIoned, sizeof(TempleIoned)); + file.Put(ActionMovie, sizeof(ActionMovie)); + file.Put(&TempleIoned, sizeof(TempleIoned)); return (true); } @@ -654,7 +744,7 @@ bool Save_Misc_Values(FileClass& file) * HISTORY: * * 06/24/1995 BRR : Created. * *=============================================================================================*/ -bool Load_Misc_Values(FileClass& file) +bool Load_Misc_Values(Straw& file) { int i, j; int count; // # ptrs in 'CurrentObject' @@ -663,46 +753,46 @@ bool Load_Misc_Values(FileClass& file) /* ** Player's House. */ - if (file.Read(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) { + if (file.Get(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) { return (false); } /* ** Read this scenario number. */ - if (file.Read(&Scen.Scenario, sizeof(Scen.Scenario)) != sizeof(Scen.Scenario)) { + if (file.Get(&Scen.Scenario, sizeof(Scen.Scenario)) != sizeof(Scen.Scenario)) { return (false); } /* ** Read difficulty. */ - if (file.Read(&Scen.Difficulty, sizeof(Scen.Difficulty)) != sizeof(Scen.Difficulty)) { + if (file.Get(&Scen.Difficulty, sizeof(Scen.Difficulty)) != sizeof(Scen.Difficulty)) { return (false); } /* ** Read AI difficulty. */ - if (file.Read(&Scen.CDifficulty, sizeof(Scen.CDifficulty)) != sizeof(Scen.CDifficulty)) { + if (file.Get(&Scen.CDifficulty, sizeof(Scen.CDifficulty)) != sizeof(Scen.CDifficulty)) { return (false); } /* ** Load frame #. */ - if (file.Read(&Frame, sizeof(Frame)) != sizeof(Frame)) { + if (file.Get(&Frame, sizeof(Frame)) != sizeof(Frame)) { return (false); } /* ** Load VQ Movie names. */ - if (file.Read(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) { + if (file.Get(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) { return (false); } - if (file.Read(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) { + if (file.Get(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) { return (false); } @@ -712,7 +802,7 @@ bool Load_Misc_Values(FileClass& file) ** Load the # of ptrs in the list. */ DynamicVectorClass& selection = CurrentObject.Raw(i); - if (file.Read(&count, sizeof(count)) != sizeof(count)) { + if (file.Get(&count, sizeof(count)) != sizeof(count)) { return (false); } @@ -720,7 +810,7 @@ bool Load_Misc_Values(FileClass& file) ** Load the pointers. */ for (j = 0; j < count; j++) { - if (file.Read(&ptr, sizeof(ptr)) != sizeof(ptr)) { + if (file.Get(&ptr, sizeof(ptr)) != sizeof(ptr)) { return (false); } selection.Add(ptr); // add to the list @@ -730,27 +820,21 @@ bool Load_Misc_Values(FileClass& file) /* ** Save the list of waypoints. */ - if (file.Read(Scen.Waypoint, sizeof(Scen.Waypoint)) != sizeof(Scen.Waypoint)) { + if (file.Get(Scen.Waypoint, sizeof(Scen.Waypoint)) != sizeof(Scen.Waypoint)) { return (false); } - file.Read(&ScenDir, sizeof(ScenDir)); - file.Read(&ScenVar, sizeof(ScenVar)); - file.Read(&Scen.CarryOverMoney, sizeof(Scen.CarryOverMoney)); - file.Read(&Scen.CarryOverPercent, sizeof(Scen.CarryOverPercent)); - file.Read(&BuildLevel, sizeof(BuildLevel)); - file.Read(BriefMovie, sizeof(BriefMovie)); - file.Read(Scen.Views, sizeof(Scen.Views)); - file.Read(&EndCountDown, sizeof(EndCountDown)); - file.Read(Scen.BriefingText, sizeof(Scen.BriefingText)); - - if (file.Seek(0, SEEK_CUR) < file.Size()) { - file.Read(ActionMovie, sizeof(ActionMovie)); - } - - if (file.Seek(0, SEEK_CUR) < file.Size()) { - file.Read(&TempleIoned, sizeof(TempleIoned)); - } + file.Get(&ScenDir, sizeof(ScenDir)); + file.Get(&ScenVar, sizeof(ScenVar)); + file.Get(&Scen.CarryOverMoney, sizeof(Scen.CarryOverMoney)); + file.Get(&Scen.CarryOverPercent, sizeof(Scen.CarryOverPercent)); + file.Get(&BuildLevel, sizeof(BuildLevel)); + file.Get(BriefMovie, sizeof(BriefMovie)); + file.Get(Scen.Views, sizeof(Scen.Views)); + file.Get(&EndCountDown, sizeof(EndCountDown)); + file.Get(Scen.BriefingText, sizeof(Scen.BriefingText)); + file.Get(ActionMovie, sizeof(ActionMovie)); + file.Get(&TempleIoned, sizeof(TempleIoned)); return (true); } @@ -986,7 +1070,7 @@ void Decode_All_Pointers(void) *=========================================================================*/ bool Get_Savefile_Info(int id, char* buf, unsigned* scenp, HousesType* housep) { - RawFileClass file; + CDFileClass file; char name[_MAX_FNAME + _MAX_EXT]; unsigned int version; char descr_buf[DESCRIP_MAX]; @@ -1012,12 +1096,12 @@ bool Get_Savefile_Info(int id, char* buf, unsigned* scenp, HousesType* housep) descr_buf[strlen(descr_buf) - 2] = '\0'; // trim off CR/LF strcpy(buf, descr_buf); - if (file.Read(scenp, sizeof(unsigned)) != sizeof(unsigned)) { + if (file.Read(scenp, sizeof(*scenp)) != sizeof(*scenp)) { file.Close(); return (false); } - if (file.Read(housep, sizeof(HousesType)) != sizeof(HousesType)) { + if (file.Read(housep, sizeof(*housep)) != sizeof(*housep)) { file.Close(); return (false); } diff --git a/tiberiandawn/sidebarglyphx.cpp b/tiberiandawn/sidebarglyphx.cpp index a02c5b05..f433c743 100644 --- a/tiberiandawn/sidebarglyphx.cpp +++ b/tiberiandawn/sidebarglyphx.cpp @@ -33,6 +33,8 @@ #include "function.h" #include "sidebarglyphx.h" +#include "common/pipe.h" +#include "common/straw.h" /* ** ST - 3/14/2019 10:49AM @@ -667,11 +669,11 @@ void SidebarGlyphxClass::Decode_Pointers(void) * HISTORY: * * 9/26/2019 10:57AM ST : Created. * *=============================================================================================*/ -bool SidebarGlyphxClass::Load(FileClass& file) +bool SidebarGlyphxClass::Load(Straw& file) { ::new (this) SidebarGlyphxClass(); - if (file.Read(this, sizeof(*this)) != sizeof(*this)) { + if (file.Get(this, sizeof(*this)) != sizeof(*this)) { return false; } @@ -693,9 +695,9 @@ bool SidebarGlyphxClass::Load(FileClass& file) * HISTORY: * * 9/26/2019 10:57AM ST : Created. * *=============================================================================================*/ -bool SidebarGlyphxClass::Save(FileClass& file) +bool SidebarGlyphxClass::Save(Pipe& file) { - return (file.Write(this, sizeof(*this)) == sizeof(*this)); + return (file.Put(this, sizeof(*this)) == sizeof(*this)); } extern SidebarGlyphxClass* Get_Current_Context_Sidebar(HouseClass* player_ptr); @@ -762,7 +764,7 @@ bool Sidebar_Glyphx_Factory_Link(int factory, RTTIType type, int id, HouseClass* return false; } -bool Sidebar_Glyphx_Save(FileClass& file, SidebarGlyphxClass* sidebar) +bool Sidebar_Glyphx_Save(Pipe& file, SidebarGlyphxClass* sidebar) { if (sidebar) { return sidebar->Save(file); @@ -770,7 +772,7 @@ bool Sidebar_Glyphx_Save(FileClass& file, SidebarGlyphxClass* sidebar) return false; } -bool Sidebar_Glyphx_Load(FileClass& file, SidebarGlyphxClass* sidebar) +bool Sidebar_Glyphx_Load(Straw& file, SidebarGlyphxClass* sidebar) { if (sidebar) { return sidebar->Load(file); diff --git a/tiberiandawn/sidebarglyphx.h b/tiberiandawn/sidebarglyphx.h index 14caaeaf..277fc761 100644 --- a/tiberiandawn/sidebarglyphx.h +++ b/tiberiandawn/sidebarglyphx.h @@ -41,6 +41,9 @@ #include "power.h" #include "factory.h" +class Straw; +class Pipe; + /* ** ST - 3/14/2019 10:49AM ** @@ -85,8 +88,8 @@ class SidebarGlyphxClass */ void Code_Pointers(void); void Decode_Pointers(void); - bool Load(FileClass& file); - bool Save(FileClass& file); + bool Load(Straw& file); + bool Save(Pipe& file); /* ** Each side strip is managed by this class. It handles all strip specific @@ -194,8 +197,8 @@ bool Sidebar_Glyphx_Add(RTTIType type, int ID, HouseClass* player_ptr = NULL, bo void Sidebar_Glyphx_Recalc(HouseClass* player_ptr = NULL); bool Sidebar_Glyphx_Factory_Link(int factory, RTTIType type, int id, HouseClass* player_ptr = NULL); void Sidebar_Glyphx_AI(HouseClass* player_ptr, KeyNumType& input); -bool Sidebar_Glyphx_Save(FileClass& file, SidebarGlyphxClass* sidebar); -bool Sidebar_Glyphx_Load(FileClass& file, SidebarGlyphxClass* sidebar); +bool Sidebar_Glyphx_Save(Pipe& file, SidebarGlyphxClass* sidebar); +bool Sidebar_Glyphx_Load(Straw& file, SidebarGlyphxClass* sidebar); void Sidebar_Glyphx_Code_Pointers(SidebarGlyphxClass* sidebar); void Sidebar_Glyphx_Decode_Pointers(SidebarGlyphxClass* sidebar); diff --git a/tiberiandawn/teamtype.h b/tiberiandawn/teamtype.h index a30ddd75..1bba4d4c 100644 --- a/tiberiandawn/teamtype.h +++ b/tiberiandawn/teamtype.h @@ -33,6 +33,9 @@ #ifndef TEAMTYPE_H #define TEAMTYPE_H +class Pipe; +class Straw; + /* ********************************** Defines ********************************** */ @@ -112,8 +115,8 @@ class TeamTypeClass : public AbstractTypeClass { return "TeamTypes"; }; - bool Load(FileClass& file); - bool Save(FileClass& file); + bool Load(Straw& file); + bool Save(Pipe& file); void Code_Pointers(void); void Decode_Pointers(void);