source: golgotha/src/i4/loaders/dir_load.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 6.3 KB
Line 
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
9#include "loaders/dir_load.hh"
10#include "checksum/checksum.hh"
11#include "memory/malloc.hh"
12#include "file/buf_file.hh"
13#include "file/sub_section.hh"
14#include <stdlib.h>
15
16#include <string.h>
17
18
19i4_bool i4_insert_sections(i4_file_class *in, i4_file_class *out,
20                           int total_sections_to_insert,
21                           i4_file_class **section_data,
22                           char **section_names)
23{
24  w32 sig=in->read_32();
25  if (sig!=i4_check_sum32("GOLG_SECTION_ID=32",17))
26    i4_error("doesn't work on this");
27 
28  w32 t_sections=in->read_32();
29  int copy_size=in->size()-8+t_sections*8;
30
31  out->write_32(sig);
32  out->write_32(t_sections + total_sections_to_insert);
33
34  int i;
35  for (i=0; i<t_sections; i++)
36  {
37    out->write_32(in->read_32());    // copy id unchanged
38    int offset=in->read_32();
39    out->write_32(offset + total_sections_to_insert * 8);
40  }
41
42  int offset2 = copy_size + out->tell() + total_sections_to_insert*8;
43
44  for (i=0; i<total_sections_to_insert; i++)
45  {
46    out->write_32(i4_check_sum32(section_names[i], strlen(section_names[i])));
47    out->write_32(offset2);
48    offset2+=section_data[i]->size();
49  }
50
51  w8 buf[4096];
52  while (copy_size)
53  {
54    int rs=sizeof(buf) > copy_size ? copy_size : sizeof(buf);
55    in->read(buf, rs);
56    out->write(buf, rs);
57    copy_size-=rs;
58  }
59 
60
61  for (i=0; i<total_sections_to_insert; i++)
62  {
63    int fsize=section_data[i]->size();
64    while (fsize)
65    {
66      int rs=sizeof(buf) > fsize ? fsize : sizeof(buf);
67      section_data[i]->read(buf, rs);
68      out->write(buf, rs);
69      fsize-=rs;
70    }
71  } 
72
73  return i4_T;
74}
75
76
77i4_loader_class *i4_open_save_file(i4_file_class *in, i4_bool close_on_delete_or_fail)
78{
79  i4_loader_class *l=new i4_loader_class(in, close_on_delete_or_fail);
80
81  if (l->error())
82  {
83    delete l;
84    return 0;
85  }
86
87  return l;
88}
89
90
91int i4_loader_section_compare(const i4_loader_section_type *a, const i4_loader_section_type *b)
92{
93  return a->section_id>b->section_id ? 1 : (a->section_id<b->section_id ? -1 : 0);
94}
95
96i4_loader_class::i4_loader_class(i4_file_class *_in, i4_bool close_on_delete)
97  : close_on_delete(close_on_delete),
98    sections(512,512)
99{
100  seek_to_before_using=-1;
101
102
103  in=new i4_buffered_file_class(_in, 0x1000, _in->tell());
104
105  _error=0;
106
107  w32 sig=in->read_32();
108  int use_16;
109
110  if (sig==i4_check_sum32("GOLG",4))
111    use_16=1;
112  else if (sig==i4_check_sum32("GOLG_SECTION_ID=32",17))
113    use_16=0;
114  else             // this is not a directoried file
115  {
116    _error=1;
117    return ;
118  }
119
120  w32 t_sections=in->read_32(), i;
121
122  last=0x7fffffff;
123
124  for (i=0; i<t_sections; i++)
125  {
126    i4_loader_section_type *t=sections.add();
127    if (use_16)
128      t->section_id=in->read_16();
129    else
130      t->section_id=in->read_32();
131
132    t->section_offset=in->read_32();
133  }
134
135
136  if (t_sections)
137  {
138    int offset=sections[0].section_offset;
139    for (i=0; i<t_sections-1; i++)
140      sections[i].section_size=sections[i+1].section_offset-sections[i].section_offset;
141
142    sections[t_sections-1].section_size=in->size()-sections[t_sections-1].section_offset;
143  }
144
145
146  sections.sort(i4_loader_section_compare);
147}
148
149int i4_loader_class::find_section(w32 section_id)
150{
151  sw32 lo=0,hi=sections.size()-1,mid;
152
153  mid=(lo+hi+1)/2;
154  if (last<hi && sections[last+1].section_id==section_id)
155    mid=last+1;
156  else
157  {
158    while (sections[mid].section_id!=section_id)
159    {
160      if (sections[mid].section_id>section_id)
161        hi=mid-1;
162      else
163        lo=mid+1;
164
165   
166      w32 last_mid=mid;
167      mid=(hi+lo)/2;
168
169      if (last_mid==mid)
170        return -1;
171
172    }
173  }
174
175  last=mid;
176
177  return mid;
178}
179
180
181i4_bool i4_loader_class::goto_section(w32 section_id)
182{
183  int mid=find_section(section_id);
184  if (mid==-1)
185    return i4_F;
186
187  if (in->tell()!=sections[mid].section_offset)
188  {
189    i4_warning("goto section : non-linear %d", section_id);
190    in->seek(sections[mid].section_offset);
191  }
192  return i4_T;
193}
194
195i4_bool i4_loader_class::get_section_info(char *section_name, w32 &offset, w32 &size)
196{
197  w32 id=i4_check_sum32(section_name, strlen(section_name));
198  int mid=find_section(id);
199  if (mid!=-1)
200  {
201    offset=sections[mid].section_offset;
202    size=sections[mid].section_size;
203    return i4_T;
204  }
205  else return i4_F;
206
207}
208
209i4_bool i4_loader_class::goto_section(char *section_name)
210{
211  return goto_section(i4_check_sum32(section_name, strlen(section_name)));
212}
213
214static w32 i4_check_end=0;
215void i4_loader_class::get_version(w16 &version, w16 &data_size)
216
217  version   = in->read_16();
218  data_size = in->read_16(); 
219
220
221  //data_size is the size of the data + 4 bytes for the version and data size variables
222  //since data_size is used to seek past the data, and we already read 4 bytes for
223  //the version and data_size, return the data_size - 4
224  data_size -= 4;
225
226  i4_check_end=in->tell() + data_size;
227}
228
229
230i4_bool i4_loader_class::check_version(w16 version)
231{
232  w16 ver,add;
233  ver=in->read_16();
234  add=in->read_16();
235 
236  i4_check_end=in->tell()+add-4;
237
238  if (ver!=version)
239  {
240    in->seek(i4_check_end);
241    return i4_F;
242  }
243  return i4_T;
244}
245
246
247void i4_loader_class::end_version(I4_LF_ARGS)
248{
249  if (in->tell()!=i4_check_end)
250    i4_warning("end_check_version did not read proper amount %s:%d", I4_FILE, I4_LINE);
251}
252
253w32 i4_loader_class::size ()
254{ return in->size(); }
255
256w32 i4_loader_class::tell ()
257{ return in->tell(); }
258
259
260w32 i4_loader_class::seek(w32 offset)
261{
262  return in->seek(offset);
263}
264
265 
266w32 i4_loader_class::read (void *buffer, w32 size)
267{
268  return in->read(buffer, size);
269}
270
271
272w32 i4_loader_class::write(const void *buffer, w32 size)
273{
274  i4_error("Bad bad");
275  return 0;
276}
277
278i4_loader_class::~i4_loader_class()
279
280  if (close_on_delete && in)
281    delete in;
282}
Note: See TracBrowser for help on using the repository browser.