saveload.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWSaveLoad *
  23. * *
  24. * $Archive:: /Commando/Code/wwsaveload/saveload.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 12/09/01 6:42p $*
  29. * *
  30. * $Revision:: 19 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "saveload.h"
  36. #include "saveloadsubsystem.h"
  37. #include "persist.h"
  38. #include "persistfactory.h"
  39. #include "chunkio.h"
  40. #include "wwdebug.h"
  41. #include "saveloadstatus.h"
  42. #include "wwhack.h"
  43. #include "wwprofile.h"
  44. #pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
  45. #include <windows.h>
  46. #include "systimer.h"
  47. SaveLoadSubSystemClass * SaveLoadSystemClass::SubSystemListHead = NULL;
  48. PersistFactoryClass * SaveLoadSystemClass::FactoryListHead = NULL;
  49. SList<PostLoadableClass> SaveLoadSystemClass::PostLoadList;
  50. PointerRemapClass SaveLoadSystemClass::PointerRemapper;
  51. bool SaveLoadSystemClass::Save (ChunkSaveClass &csave,SaveLoadSubSystemClass & subsystem)
  52. {
  53. bool ok = true;
  54. if (subsystem.Contains_Data()) {
  55. csave.Begin_Chunk (subsystem.Chunk_ID ());
  56. ok &= subsystem.Save (csave);
  57. csave.End_Chunk ();
  58. }
  59. return ok;
  60. }
  61. bool SaveLoadSystemClass::Load (ChunkLoadClass &cload,bool auto_post_load)
  62. {
  63. WWLOG_PREPARE_TIME_AND_MEMORY("SaveLoadSystemClass::Load");
  64. PointerRemapper.Reset();
  65. WWLOG_INTERMEDIATE("PointerRemapper.Reset()");
  66. bool ok = true;
  67. // Load each chunk we encounter and link the manager into the PostLoad list
  68. while (cload.Open_Chunk ()) {
  69. SaveLoadStatus::Inc_Status_Count(); // Count the sub systems loaded
  70. SaveLoadSubSystemClass *sys = Find_Sub_System(cload.Cur_Chunk_ID ());
  71. WWLOG_INTERMEDIATE("Find_Sub_System");
  72. if (sys != NULL) {
  73. //WWRELEASE_SAY((" Name: %s\n",sys->Name()));
  74. INIT_SUB_STATUS(sys->Name());
  75. ok &= sys->Load(cload);
  76. WWLOG_INTERMEDIATE(sys->Name());
  77. }
  78. cload.Close_Chunk();
  79. }
  80. // Process all of the pointer remap requests
  81. PointerRemapper.Process();
  82. WWLOG_INTERMEDIATE("PointerRemapper.Process()");
  83. PointerRemapper.Reset();
  84. WWLOG_INTERMEDIATE("PointerRemapper.Reset()");
  85. // Call PostLoad on each PersistClass that wanted post-load
  86. if (auto_post_load) {
  87. Post_Load_Processing(NULL);
  88. }
  89. WWLOG_INTERMEDIATE("PostLoadProcessing");
  90. return ok;
  91. }
  92. // Nework update macro for post loader.
  93. #define UPDATE_NETWORK \
  94. if (network_callback) { \
  95. unsigned long time2 = TIMEGETTIME(); \
  96. if (time2 - time > 20) { \
  97. network_callback(); \
  98. time = time2; \
  99. } \
  100. } \
  101. bool SaveLoadSystemClass::Post_Load_Processing (void(*network_callback)(void))
  102. {
  103. unsigned long time = TIMEGETTIME();
  104. // Call PostLoad on each PersistClass that wanted post-load
  105. PostLoadableClass * obj = PostLoadList.Remove_Head();
  106. while (obj) {
  107. UPDATE_NETWORK;
  108. obj->On_Post_Load();
  109. obj->Set_Post_Load_Registered(false);
  110. obj = PostLoadList.Remove_Head();
  111. }
  112. return true;
  113. }
  114. void SaveLoadSystemClass::Register_Sub_System (SaveLoadSubSystemClass * sys)
  115. {
  116. WWASSERT(sys != NULL);
  117. Link_Sub_System(sys);
  118. }
  119. void SaveLoadSystemClass::Unregister_Sub_System (SaveLoadSubSystemClass * sys)
  120. {
  121. WWASSERT(sys != NULL);
  122. Unlink_Sub_System(sys);
  123. }
  124. SaveLoadSubSystemClass * SaveLoadSystemClass::Find_Sub_System (uint32 chunk_id)
  125. {
  126. // TODO: need a d-s that gives fast searching based on chunk_id!!
  127. SaveLoadSubSystemClass * sys;
  128. for ( sys = SubSystemListHead; sys != NULL; sys = sys->NextSubSystem ) {
  129. if ( sys->Chunk_ID() == chunk_id ) {
  130. break;
  131. }
  132. }
  133. return sys;
  134. }
  135. void SaveLoadSystemClass::Register_Persist_Factory(PersistFactoryClass * factory)
  136. {
  137. WWASSERT(factory != NULL);
  138. Link_Factory(factory);
  139. }
  140. void SaveLoadSystemClass::Unregister_Persist_Factory(PersistFactoryClass * factory)
  141. {
  142. WWASSERT(factory != NULL);
  143. Unlink_Factory(factory);
  144. }
  145. PersistFactoryClass * SaveLoadSystemClass::Find_Persist_Factory(uint32 chunk_id)
  146. {
  147. // TODO: need a d-s that gives fast searching based on chunk_id!!
  148. PersistFactoryClass * fact;
  149. for ( fact = FactoryListHead; fact != NULL; fact = fact->NextFactory ) {
  150. if ( fact->Chunk_ID() == chunk_id ) {
  151. break;
  152. }
  153. }
  154. return fact;
  155. }
  156. bool SaveLoadSystemClass::Is_Post_Load_Callback_Registered(PostLoadableClass * obj)
  157. {
  158. // obsolete!
  159. bool retval = false;
  160. SLNode<PostLoadableClass> *list_node = NULL;
  161. for ( list_node = PostLoadList.Head();
  162. retval == false && list_node != NULL;
  163. list_node = list_node->Next())
  164. {
  165. retval = (list_node->Data() == obj);
  166. }
  167. return retval;
  168. }
  169. void SaveLoadSystemClass::Register_Post_Load_Callback(PostLoadableClass * obj)
  170. {
  171. WWASSERT(obj != NULL);
  172. if (!obj->Is_Post_Load_Registered()) {
  173. obj->Set_Post_Load_Registered(true);
  174. PostLoadList.Add_Head(obj);
  175. }
  176. }
  177. void SaveLoadSystemClass::Register_Pointer (void *old_pointer, void *new_pointer)
  178. {
  179. PointerRemapper.Register_Pointer(old_pointer,new_pointer);
  180. }
  181. #ifdef WWDEBUG
  182. void SaveLoadSystemClass::Request_Pointer_Remap (void **pointer_to_convert,const char * file,int line)
  183. {
  184. PointerRemapper.Request_Pointer_Remap(pointer_to_convert,file,line);
  185. }
  186. void SaveLoadSystemClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert,const char * file,int line)
  187. {
  188. PointerRemapper.Request_Ref_Counted_Pointer_Remap(pointer_to_convert,file,line);
  189. }
  190. #else
  191. void SaveLoadSystemClass::Request_Pointer_Remap (void **pointer_to_convert)
  192. {
  193. PointerRemapper.Request_Pointer_Remap(pointer_to_convert);
  194. }
  195. void SaveLoadSystemClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert)
  196. {
  197. PointerRemapper.Request_Ref_Counted_Pointer_Remap(pointer_to_convert);
  198. }
  199. #endif
  200. void SaveLoadSystemClass::Link_Sub_System(SaveLoadSubSystemClass * sys)
  201. {
  202. WWASSERT(sys != NULL);
  203. if (sys != NULL) {
  204. WWASSERT(sys->NextSubSystem == NULL); // sys should never be registered twice!
  205. sys->NextSubSystem = SubSystemListHead;
  206. SubSystemListHead = sys;
  207. }
  208. }
  209. void SaveLoadSystemClass::Unlink_Sub_System(SaveLoadSubSystemClass * sys)
  210. {
  211. WWASSERT(sys != NULL);
  212. SaveLoadSubSystemClass * cursys = SubSystemListHead;
  213. SaveLoadSubSystemClass * prev = NULL;
  214. while (cursys != sys) {
  215. prev = cursys;
  216. cursys = cursys->NextSubSystem;
  217. }
  218. if (prev == NULL) {
  219. SubSystemListHead = sys->NextSubSystem;
  220. } else {
  221. prev->NextSubSystem = sys->NextSubSystem;
  222. }
  223. sys->NextSubSystem = NULL;
  224. }
  225. void SaveLoadSystemClass::Link_Factory(PersistFactoryClass * fact)
  226. {
  227. WWASSERT(fact != NULL);
  228. if (fact != NULL) {
  229. WWASSERT(fact->NextFactory == NULL); // factories should never be registered twice!
  230. fact->NextFactory = FactoryListHead;
  231. FactoryListHead = fact;
  232. }
  233. }
  234. void SaveLoadSystemClass::Unlink_Factory(PersistFactoryClass * fact)
  235. {
  236. WWASSERT(fact != NULL);
  237. PersistFactoryClass * curfact = FactoryListHead;
  238. PersistFactoryClass * prev = NULL;
  239. while (curfact != fact) {
  240. prev = curfact;
  241. curfact = curfact->NextFactory;
  242. }
  243. if (prev == NULL) {
  244. FactoryListHead = fact->NextFactory;
  245. } else {
  246. prev->NextFactory = fact->NextFactory;
  247. }
  248. fact->NextFactory = NULL;
  249. }
  250. void Force_Link_WWSaveLoad (void)
  251. {
  252. FORCE_LINK( Twiddler );
  253. return ;
  254. }