saveload.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. ** Command & Conquer Generals(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:: 5/09/01 11:48a $*
  29. * *
  30. * $Revision:: 15 $*
  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. SaveLoadSubSystemClass * SaveLoadSystemClass::SubSystemListHead = NULL;
  44. PersistFactoryClass * SaveLoadSystemClass::FactoryListHead = NULL;
  45. SList<PostLoadableClass> SaveLoadSystemClass::PostLoadList;
  46. PointerRemapClass SaveLoadSystemClass::PointerRemapper;
  47. bool SaveLoadSystemClass::Save (ChunkSaveClass &csave,SaveLoadSubSystemClass & subsystem)
  48. {
  49. bool ok = true;
  50. if (subsystem.Contains_Data()) {
  51. csave.Begin_Chunk (subsystem.Chunk_ID ());
  52. ok &= subsystem.Save (csave);
  53. csave.End_Chunk ();
  54. }
  55. return ok;
  56. }
  57. bool SaveLoadSystemClass::Load (ChunkLoadClass &cload,bool auto_post_load)
  58. {
  59. // WWASSERT(PostLoadList.Head() == NULL);
  60. PointerRemapper.Reset();
  61. bool ok = true;
  62. // Load each chunk we encounter and link the manager into the PostLoad list
  63. while (cload.Open_Chunk ()) {
  64. SaveLoadSubSystemClass *sys = Find_Sub_System(cload.Cur_Chunk_ID ());
  65. if (sys != NULL) {
  66. INIT_SUB_STATUS(sys->Name());
  67. ok &= sys->Load(cload);
  68. }
  69. cload.Close_Chunk();
  70. }
  71. // Process all of the pointer remap requests
  72. PointerRemapper.Process();
  73. PointerRemapper.Reset();
  74. // Call PostLoad on each PersistClass that wanted post-load
  75. if (auto_post_load) {
  76. Post_Load_Processing();
  77. }
  78. return ok;
  79. }
  80. bool SaveLoadSystemClass::Post_Load_Processing (void)
  81. {
  82. // Call PostLoad on each PersistClass that wanted post-load
  83. PostLoadableClass * obj = PostLoadList.Remove_Head();
  84. while (obj) {
  85. obj->On_Post_Load();
  86. obj->Set_Post_Load_Registered(false);
  87. obj = PostLoadList.Remove_Head();
  88. }
  89. return true;
  90. }
  91. void SaveLoadSystemClass::Register_Sub_System (SaveLoadSubSystemClass * sys)
  92. {
  93. WWASSERT(sys != NULL);
  94. Link_Sub_System(sys);
  95. }
  96. void SaveLoadSystemClass::Unregister_Sub_System (SaveLoadSubSystemClass * sys)
  97. {
  98. WWASSERT(sys != NULL);
  99. Unlink_Sub_System(sys);
  100. }
  101. SaveLoadSubSystemClass * SaveLoadSystemClass::Find_Sub_System (uint32 chunk_id)
  102. {
  103. // TODO: need a d-s that gives fast searching based on chunk_id!!
  104. SaveLoadSubSystemClass * sys;
  105. for ( sys = SubSystemListHead; sys != NULL; sys = sys->NextSubSystem ) {
  106. if ( sys->Chunk_ID() == chunk_id ) {
  107. break;
  108. }
  109. }
  110. return sys;
  111. }
  112. void SaveLoadSystemClass::Register_Persist_Factory(PersistFactoryClass * factory)
  113. {
  114. WWASSERT(factory != NULL);
  115. Link_Factory(factory);
  116. }
  117. void SaveLoadSystemClass::Unregister_Persist_Factory(PersistFactoryClass * factory)
  118. {
  119. WWASSERT(factory != NULL);
  120. Unlink_Factory(factory);
  121. }
  122. PersistFactoryClass * SaveLoadSystemClass::Find_Persist_Factory(uint32 chunk_id)
  123. {
  124. // TODO: need a d-s that gives fast searching based on chunk_id!!
  125. PersistFactoryClass * fact;
  126. for ( fact = FactoryListHead; fact != NULL; fact = fact->NextFactory ) {
  127. if ( fact->Chunk_ID() == chunk_id ) {
  128. break;
  129. }
  130. }
  131. return fact;
  132. }
  133. bool SaveLoadSystemClass::Is_Post_Load_Callback_Registered(PostLoadableClass * obj)
  134. {
  135. // obsolete!
  136. bool retval = false;
  137. SLNode<PostLoadableClass> *list_node = NULL;
  138. for ( list_node = PostLoadList.Head();
  139. retval == false && list_node != NULL;
  140. list_node = list_node->Next())
  141. {
  142. retval = (list_node->Data() == obj);
  143. }
  144. return retval;
  145. }
  146. void SaveLoadSystemClass::Register_Post_Load_Callback(PostLoadableClass * obj)
  147. {
  148. WWASSERT(obj != NULL);
  149. if (!obj->Is_Post_Load_Registered()) {
  150. obj->Set_Post_Load_Registered(true);
  151. PostLoadList.Add_Head(obj);
  152. }
  153. }
  154. void SaveLoadSystemClass::Register_Pointer (void *old_pointer, void *new_pointer)
  155. {
  156. PointerRemapper.Register_Pointer(old_pointer,new_pointer);
  157. }
  158. #ifdef WWDEBUG
  159. void SaveLoadSystemClass::Request_Pointer_Remap (void **pointer_to_convert,const char * file,int line)
  160. {
  161. PointerRemapper.Request_Pointer_Remap(pointer_to_convert,file,line);
  162. }
  163. void SaveLoadSystemClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert,const char * file,int line)
  164. {
  165. PointerRemapper.Request_Ref_Counted_Pointer_Remap(pointer_to_convert,file,line);
  166. }
  167. #else
  168. void SaveLoadSystemClass::Request_Pointer_Remap (void **pointer_to_convert)
  169. {
  170. PointerRemapper.Request_Pointer_Remap(pointer_to_convert);
  171. }
  172. void SaveLoadSystemClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert)
  173. {
  174. PointerRemapper.Request_Ref_Counted_Pointer_Remap(pointer_to_convert);
  175. }
  176. #endif
  177. void SaveLoadSystemClass::Link_Sub_System(SaveLoadSubSystemClass * sys)
  178. {
  179. WWASSERT(sys != NULL);
  180. if (sys != NULL) {
  181. WWASSERT(sys->NextSubSystem == NULL); // sys should never be registered twice!
  182. sys->NextSubSystem = SubSystemListHead;
  183. SubSystemListHead = sys;
  184. }
  185. }
  186. void SaveLoadSystemClass::Unlink_Sub_System(SaveLoadSubSystemClass * sys)
  187. {
  188. WWASSERT(sys != NULL);
  189. SaveLoadSubSystemClass * cursys = SubSystemListHead;
  190. SaveLoadSubSystemClass * prev = NULL;
  191. while (cursys != sys) {
  192. prev = cursys;
  193. cursys = cursys->NextSubSystem;
  194. }
  195. if (prev == NULL) {
  196. SubSystemListHead = sys->NextSubSystem;
  197. } else {
  198. prev->NextSubSystem = sys->NextSubSystem;
  199. }
  200. sys->NextSubSystem = NULL;
  201. }
  202. void SaveLoadSystemClass::Link_Factory(PersistFactoryClass * fact)
  203. {
  204. WWASSERT(fact != NULL);
  205. if (fact != NULL) {
  206. WWASSERT(fact->NextFactory == NULL); // factories should never be registered twice!
  207. fact->NextFactory = FactoryListHead;
  208. FactoryListHead = fact;
  209. }
  210. }
  211. void SaveLoadSystemClass::Unlink_Factory(PersistFactoryClass * fact)
  212. {
  213. WWASSERT(fact != NULL);
  214. PersistFactoryClass * curfact = FactoryListHead;
  215. PersistFactoryClass * prev = NULL;
  216. while (curfact != fact) {
  217. prev = curfact;
  218. curfact = curfact->NextFactory;
  219. }
  220. if (prev == NULL) {
  221. FactoryListHead = fact->NextFactory;
  222. } else {
  223. prev->NextFactory = fact->NextFactory;
  224. }
  225. fact->NextFactory = NULL;
  226. }
  227. void Force_Link_WWSaveLoad (void)
  228. {
  229. FORCE_LINK( Twiddler );
  230. return ;
  231. }