saver.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "saver.hh"
  9. #include "checksum/checksum.hh"
  10. #include "memory/malloc.hh"
  11. #include "g1_object.hh"
  12. // Saver methods
  13. g1_saver_class::g1_saver_class(i4_file_class *out, i4_bool close_on_delete)
  14. : i4_saver_class(out, close_on_delete), remap(0)
  15. {
  16. t_refs=0;
  17. state=DIRECTORY_CREATE;
  18. current_offset=out->tell();
  19. }
  20. g1_saver_class::~g1_saver_class()
  21. {
  22. g1_global_id.free_remapping(remap);
  23. }
  24. void g1_saver_class::set_helpers(g1_object_class **reference_list, w32 total_references)
  25. {
  26. ref_list=reference_list;
  27. t_refs=total_references;
  28. remap = g1_global_id.alloc_remapping();
  29. for (w32 i=0; i<t_refs; i++)
  30. (*remap)[ref_list[i]->global_id] = i;
  31. }
  32. i4_bool g1_saver_class::write_global_id(w32 id)
  33. {
  34. if (state==DIRECTORY_CREATE)
  35. {
  36. current_offset+=2;
  37. return i4_T;
  38. }
  39. else
  40. {
  41. w16 found=0xffff;
  42. if (g1_global_id.check_id(id))
  43. found = (*remap)[id];
  44. out->write_16(found);
  45. if (found==0xffff)
  46. return i4_F;
  47. }
  48. return i4_T;
  49. }
  50. i4_bool g1_saver_class::write_reference(const g1_reference_class &ref)
  51. {
  52. if (state==DIRECTORY_CREATE)
  53. {
  54. current_offset+=4;
  55. return i4_T;
  56. }
  57. else
  58. {
  59. w16 found=0;
  60. if (ref.ref)
  61. {
  62. for (w32 i=0; !found && i<t_refs; i++)
  63. if (ref.ref==ref_list[i])
  64. found=i+1;
  65. out->write_16(found);
  66. }
  67. else
  68. out->write_16(0);
  69. // blank for notifee
  70. out->write_16(0);
  71. }
  72. return i4_T;
  73. }
  74. // Loader methods
  75. g1_loader_class::g1_loader_class(i4_file_class *in, i4_bool close_on_delete)
  76. : i4_loader_class(in, close_on_delete), id_remap(0)
  77. {
  78. ref_list=0;
  79. first_ref=0;
  80. li_remap=0;
  81. }
  82. g1_loader_class::~g1_loader_class()
  83. {
  84. if (id_remap)
  85. {
  86. g1_global_id.claim_freespace();
  87. i4_free(id_remap);
  88. }
  89. }
  90. void g1_loader_class::set_remap(w32 total_references)
  91. {
  92. t_refs=total_references;
  93. id_remap = (w32 *)i4_malloc(total_references*sizeof(*id_remap), "loader_remapping");
  94. for (int i=0; i<total_references; i++)
  95. id_remap[i] = g1_global_id.alloc(0);
  96. }
  97. void g1_loader_class::end_remap()
  98. {
  99. for (int i=0; i<t_refs; i++)
  100. if (g1_global_id.preassigned(id_remap[i]))
  101. g1_global_id.free(id_remap[i]);
  102. }
  103. void g1_loader_class::set_helpers(g1_object_class **reference_list, w32 total_references)
  104. {
  105. ref_list=reference_list;
  106. t_refs=total_references;
  107. }
  108. w32 g1_loader_class::read_global_id()
  109. {
  110. w32 i=in->read_16();
  111. if (i==0xffff || !id_remap)
  112. return g1_global_id.invalid_id();
  113. else
  114. return id_remap[i];
  115. }
  116. void g1_loader_class::read_reference(g1_reference_class &ref)
  117. {
  118. w16 index=in->read_16();
  119. ref.ref=0; // clear out hi bits
  120. ref.ref=(g1_object_class *)index;
  121. // read blank for notifee
  122. in->read_16();
  123. if (ref.ref) // if non-0 reference we need to modify it later, so add to list
  124. {
  125. ref.next=first_ref;
  126. first_ref=&ref;
  127. }
  128. else
  129. ref.next=0;
  130. }
  131. void g1_loader_class::convert_references()
  132. {
  133. g1_reference_class *f,*next;
  134. for (f=first_ref; f;)
  135. {
  136. next=f->next;
  137. g1_object_class *r;
  138. w16 ref=*((w16 *)&f->ref);
  139. if (ref==0)
  140. r=0;
  141. else
  142. {
  143. ref--;
  144. if (ref<t_refs)
  145. r=ref_list[ref];
  146. else
  147. {
  148. i4_warning("bad reference in file");
  149. r=0;
  150. }
  151. }
  152. f->ref=0;
  153. f->reference_object(r);
  154. f=next;
  155. }
  156. first_ref=0;
  157. }
  158. g1_loader_class *g1_open_save_file(i4_file_class *in, i4_bool close_on_delete_or_fail)
  159. {
  160. g1_loader_class *l=new g1_loader_class(in, close_on_delete_or_fail);
  161. if (l->error())
  162. {
  163. delete l;
  164. return 0;
  165. }
  166. return l;
  167. }