source: golgotha/src/golg/g1_file.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 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: 4.9 KB
RevLine 
[80]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 "error/alert.hh"
10#include "string/str_checksum.hh"
11#include "threads/threads.hh"
12#include "file/file.hh"
13#include "memory/array.hh"
14#include "file/file_man.hh"
15#include "main/main.hh"
16#include "checksum/checksum.hh"
17
18i4_critical_section_class cd_file_lock;
19static char *cd_image="golgotha.cd";
20
21
22struct g1_dir_entry
23{
24  w32 offset;
25  w32 checksum;
26  w32 length;
27};
28
29
30int g1_dir_entry_compare(const g1_dir_entry *a, const g1_dir_entry *b)
31{
32  if (a->checksum<b->checksum)
33    return -1;
34  else if (a->checksum>b->checksum)
35    return 1;
36  else return 0;
37}
38
39
40// this is the only file that is actually used by the game, the rest is just seeking
41i4_file_class *g1_single_file=0;
42
43
44void g1_cd_file_callback(w32 count, void *context);
45
46class g1_cd_file : public i4_file_class
47{
48public:
49  w32 offset;
50  w32 end_offset;
51  w32 start_offset;
52  i4_file_class::async_callback callback;
53  void *context;
54  i4_file_class *use_file;
55
56
57  virtual w32 read (void *buffer, w32 size)
58  {
59    cd_file_lock.lock();
60
61    if (use_file->tell()!=offset)
62      use_file->seek(offset);
63    if (offset+size>end_offset)
64      size=end_offset-offset;
65
66    w32 ret=use_file->read(buffer,size);
67    offset+=ret;
68
69    cd_file_lock.unlock();
70    return ret;
71  }
72
73  virtual w32 write(const void *buffer, w32 size)
74  {
75    return 0;
76  }
77
78  virtual w32 seek (w32 _offset)
79  {
80    offset=start_offset+_offset;
81    if (offset>end_offset)
82      offset=end_offset;
83
84    return offset;
85  }
86
87  virtual w32 size ()
88  {
89    return end_offset-start_offset;
90  }
91
92  virtual w32 tell ()
93  {
94    return offset-start_offset;
95  }
96
97  ~g1_cd_file()
98  {
99    if (use_file!=g1_single_file)
100      delete use_file;
101  }
102
103  g1_cd_file(w32 start, w32 length, i4_file_class *fp)
104  {
105    use_file=fp;
106    start_offset=start;
107    offset=start_offset;
108    end_offset=start_offset+length;
109  }
110
111};
112
113void g1_cd_file_callback(w32 count, void *context)
114
115{
116  cd_file_lock.unlock();
117  ((g1_cd_file *)context)->callback(count, ((g1_cd_file *)context)->context);
118}
119
120
121
122class g1_file_manager_class : public i4_file_manager_class
123{
124  i4_array<g1_dir_entry> entries;
125  char current_cd_file[100];
126
127public:
128  int g1_file_manager_class::find_checksum(w32 id)
129  {
130    g1_dir_entry find;
131    find.checksum=id;
132    return entries.binary_search(&find, g1_dir_entry_compare);   
133  }
134
135  virtual i4_file_class *open(const i4_const_str &name, w32 flags)
136  {
137    if (flags & (I4_WRITE|I4_APPEND|I4_SUPPORT_ASYNC))
138      return 0;
139
140    char tmp[256];
141    int k=0;
142
143    // convert slashes to a commonf format
144    for (i4_const_str::iterator i=name.begin(); i!=name.end(); )
145    {
146      int c=i.get().value();
147      if (c=='\\')
148        tmp[k++]='/';
149      else
150        tmp[k++]=c;
151      ++i;
152    }
153
154
155    int handle=find_checksum(i4_check_sum32(tmp,k));
156    if (handle>=0)
157    {
158      if (flags & I4_SUPPORT_ASYNC)
159      {
160        i4_file_class *fp=i4_open(current_cd_file, flags);
161        return new g1_cd_file(entries[handle].offset, entries[handle].length, fp);
162      }
163
164      return new g1_cd_file(entries[handle].offset, entries[handle].length, g1_single_file);
165    }
166    else return 0;
167  }
168
169  void set_cd_file()
170  {
171    if (cd_image)
172    {
173      g1_single_file=i4_open(cd_image);
174      if (!g1_single_file)
175        i4_warning("could not open cd image file");
176      else
177      { 
178        strcpy(current_cd_file, cd_image);
179
180        int tfiles = g1_single_file->read_32();
181
182        for (int i=0; i<tfiles; i++)
183        {
184          g1_dir_entry *e=entries.add();
185          e->offset=g1_single_file->read_32();
186          e->checksum=g1_single_file->read_32();
187          e->length=g1_single_file->read_32();
188        }
189
190
191        int netfirst=0;
192        for (int j=1; j<i4_global_argc; j++)
193          if (i4_global_argv[j]=="-netfirst")
194            netfirst=1;
195
196        if (netfirst)
197          i4_add_file_manager(this, i4_F);
198        else
199          i4_add_file_manager(this, i4_T);
200      }
201    }
202  }
203
204
205  void init()
206  { 
207    set_cd_file();
208  }
209
210  void uninit()
211  {
212    entries.uninit();
213    if (g1_single_file)
214    {
215      i4_remove_file_manger(this);
216      delete g1_single_file;
217    }
218  }
219
220  g1_file_manager_class()
221    : entries(0,512)
222  {
223  }
224
225} g1_file_manager_class_instance;
226
227
228
229void g1_set_cd_image(char *filename)
230{
231  cd_image=filename;
232  g1_file_manager_class_instance.set_cd_file();
233}
Note: See TracBrowser for help on using the repository browser.