1 /*
2 IMPORT_DEFINITIONS.C
3
4 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 and the "Aleph One" developers.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 This license is contained in the file "COPYING",
18 which is included with this source code; it is available online at
19 http://www.gnu.org/licenses/gpl.html
20
21 Sunday, October 2, 1994 1:25:23 PM (Jason')
22
23 Aug 12, 2000 (Loren Petrich):
24 Using object-oriented file handler
25
26 Aug 31, 2000 (Loren Petrich):
27 Added unpacking code for the physics models
28 */
29
30 #include "cseries.h"
31 #include <string.h>
32
33 #include "tags.h"
34 #include "map.h"
35 #include "interface.h"
36 #include "game_wad.h"
37 #include "wad.h"
38 #include "game_errors.h"
39 #include "shell.h"
40 #include "preferences.h"
41 #include "FileHandler.h"
42 #include "shell.h"
43 #include "preferences.h"
44
45 // LP: get all the unpacker definitions
46 #include "monsters.h"
47 #include "effects.h"
48 #include "projectiles.h"
49 #include "player.h"
50 #include "weapons.h"
51 #include "physics_models.h"
52
53 #include "AStream.h"
54
55 /* ---------- globals */
56
57 #define IMPORT_STRUCTURE
58 #include "extensions.h"
59
60 /* ---------- local globals */
61 static FileSpecifier PhysicsFileSpec;
62
63 /* ---------- local prototype */
64 static struct wad_data *get_physics_wad_data(bool *bungie_physics);
65 static void import_physics_wad_data(struct wad_data *wad);
66 static void import_m1_physics_data();
67 static void import_m1_physics_data_from_network(uint8 *data, uint32 length);
68
69 /* ---------- code */
set_physics_file(FileSpecifier & File)70 void set_physics_file(FileSpecifier& File)
71 {
72 PhysicsFileSpec = File;
73 }
74
set_to_default_physics_file(void)75 void set_to_default_physics_file(
76 void)
77 {
78 get_default_physics_spec(PhysicsFileSpec);
79 // dprintf("Set to: %d %d %.*s", physics_file.vRefNum, physics_file.parID, physics_file.name[0], physics_file.name+1);
80 }
81
init_physics_wad_data()82 void init_physics_wad_data()
83 {
84 init_monster_definitions();
85 init_effect_definitions();
86 init_projectile_definitions();
87 init_physics_constants();
88 init_weapon_definitions();
89 }
90
physics_file_is_m1(void)91 bool physics_file_is_m1(void)
92 {
93 bool m1_physics = false;
94
95 // check for M1 physics
96 OpenedFile PhysicsFile;
97 short SavedType, SavedError = get_game_error(&SavedType);
98 if (PhysicsFileSpec.Open(PhysicsFile))
99 {
100 uint32 tag = SDL_ReadBE32(PhysicsFile.GetRWops());
101 switch (tag)
102 {
103 case M1_MONSTER_PHYSICS_TAG:
104 case M1_EFFECTS_PHYSICS_TAG:
105 case M1_PROJECTILE_PHYSICS_TAG:
106 case M1_PHYSICS_PHYSICS_TAG:
107 case M1_WEAPONS_PHYSICS_TAG:
108 m1_physics = true;
109 break;
110 default:
111 break;
112 }
113
114 PhysicsFile.Close();
115 }
116 set_game_error(SavedType, SavedError);
117 return m1_physics;
118 }
119
import_definition_structures(void)120 void import_definition_structures(
121 void)
122 {
123 init_physics_wad_data();
124
125 if (physics_file_is_m1())
126 {
127 import_m1_physics_data();
128 }
129 else
130 {
131 struct wad_data *wad;
132 bool bungie_physics;
133
134 wad= get_physics_wad_data(&bungie_physics);
135 if(wad)
136 {
137 /* Actually load it in.. */
138 import_physics_wad_data(wad);
139
140 free_wad(wad);
141 }
142 }
143 }
144
145 #define M1_PHYSICS_MAGIC_COOKIE (0xDEAFDEAF)
146
get_network_physics_buffer(int32 * physics_length)147 void *get_network_physics_buffer(
148 int32 *physics_length)
149 {
150 if (physics_file_is_m1())
151 {
152 bool success = false;
153 uint8 *data = NULL;
154 OpenedFile PhysicsFile;
155 if (PhysicsFileSpec.Open(PhysicsFile) &&
156 PhysicsFile.GetLength(*physics_length))
157 {
158 data = (uint8 *)malloc(*physics_length + 4);
159 SDL_RWops *ops = SDL_RWFromMem(data, *physics_length + 4);
160 success = SDL_WriteBE32(ops, uint32(M1_PHYSICS_MAGIC_COOKIE));
161 if (success)
162 success = SDL_WriteBE32(ops, uint32(*physics_length));
163 SDL_RWclose(ops);
164 if (success)
165 success = PhysicsFile.Read(*physics_length, &data[8]);
166 if (!success)
167 free(data);
168 }
169 if (!success)
170 {
171 *physics_length = 0;
172 return NULL;
173 }
174 return data;
175 }
176
177 short SavedType, SavedError = get_game_error(&SavedType);
178 void *data= get_flat_data(PhysicsFileSpec, false, 0);
179 set_game_error(SavedType, SavedError);
180
181 if(data)
182 {
183 *physics_length= get_flat_data_length(data);
184 } else {
185 *physics_length= 0;
186 }
187
188 return data;
189 }
190
process_network_physics_model(void * data)191 void process_network_physics_model(
192 void *data)
193 {
194 init_physics_wad_data();
195
196 if(data)
197 {
198 // check for M1 physics
199 SDL_RWops *ops = SDL_RWFromConstMem(data, 8);
200 uint32 cookie = SDL_ReadBE32(ops);
201 if(cookie == M1_PHYSICS_MAGIC_COOKIE)
202 {
203 uint32 length= SDL_ReadBE32(ops);
204 SDL_RWclose(ops);
205 uint8 *s= (uint8 *)data;
206 import_m1_physics_data_from_network(&s[8], length);
207 return;
208 }
209 else
210 {
211 SDL_RWclose(ops);
212 }
213
214 struct wad_header header;
215 struct wad_data *wad;
216
217 wad= inflate_flat_data(data, &header);
218 if(wad)
219 {
220 import_physics_wad_data(wad);
221 free_wad(wad); /* Note that the flat data points into the wad. */
222 }
223 }
224 }
225
226 /* --------- local code */
get_physics_wad_data(bool * bungie_physics)227 static struct wad_data *get_physics_wad_data(
228 bool *bungie_physics)
229 {
230 struct wad_data *wad= NULL;
231
232 // dprintf("Open is: %d %d %.*s", physics_file.vRefNum, physics_file.parID, physics_file.name[0], physics_file.name+1);
233
234 OpenedFile PhysicsFile;
235 if(open_wad_file_for_reading(PhysicsFileSpec,PhysicsFile))
236 {
237 struct wad_header header;
238
239 if(read_wad_header(PhysicsFile, &header))
240 {
241 if(header.data_version==BUNGIE_PHYSICS_DATA_VERSION || header.data_version==PHYSICS_DATA_VERSION)
242 {
243 wad= read_indexed_wad_from_file(PhysicsFile, &header, 0, true);
244 if(header.data_version==BUNGIE_PHYSICS_DATA_VERSION)
245 {
246 *bungie_physics= true;
247 } else {
248 *bungie_physics= false;
249 }
250 }
251 }
252
253 close_wad_file(PhysicsFile);
254 }
255
256 /* Reset any errors that might have occurred.. */
257 set_game_error(systemError, errNone);
258
259 return wad;
260 }
261
import_physics_wad_data(struct wad_data * wad)262 static void import_physics_wad_data(
263 struct wad_data *wad)
264 {
265 // LP: this code is copied out of game_wad.c
266 size_t data_length;
267 byte *data;
268 size_t count;
269
270 data= (unsigned char *)extract_type_from_wad(wad, MONSTER_PHYSICS_TAG, &data_length);
271 count = data_length/SIZEOF_monster_definition;
272 assert(count*SIZEOF_monster_definition == data_length);
273 assert(count <= NUMBER_OF_MONSTER_TYPES);
274 if (data_length > 0)
275 {
276 unpack_monster_definition(data,count);
277 }
278
279 data= (unsigned char *)extract_type_from_wad(wad, EFFECTS_PHYSICS_TAG, &data_length);
280 count = data_length/SIZEOF_effect_definition;
281 assert(count*SIZEOF_effect_definition == data_length);
282 assert(count <= NUMBER_OF_EFFECT_TYPES);
283 if (data_length > 0)
284 {
285 unpack_effect_definition(data,count);
286 }
287
288 data= (unsigned char *)extract_type_from_wad(wad, PROJECTILE_PHYSICS_TAG, &data_length);
289 count = data_length/SIZEOF_projectile_definition;
290 assert(count*SIZEOF_projectile_definition == data_length);
291 assert(count <= NUMBER_OF_PROJECTILE_TYPES);
292 if (data_length > 0)
293 {
294 unpack_projectile_definition(data,count);
295 }
296
297 data= (unsigned char *)extract_type_from_wad(wad, PHYSICS_PHYSICS_TAG, &data_length);
298 count = data_length/SIZEOF_physics_constants;
299 assert(count*SIZEOF_physics_constants == data_length);
300 assert(count <= get_number_of_physics_models());
301 if (data_length > 0)
302 {
303 unpack_physics_constants(data,count);
304 }
305
306 data= (unsigned char*) extract_type_from_wad(wad, WEAPONS_PHYSICS_TAG, &data_length);
307 count = data_length/SIZEOF_weapon_definition;
308 assert(count*SIZEOF_weapon_definition == data_length);
309 assert(count <= get_number_of_weapon_types());
310 if (data_length > 0)
311 {
312 unpack_weapon_definition(data,count);
313 }
314 }
315
import_m1_physics_data()316 static void import_m1_physics_data()
317 {
318 OpenedFile PhysicsFile;
319 if (!PhysicsFileSpec.Open(PhysicsFile))
320 {
321 return;
322 }
323
324 int32 position = 0;
325 int32 length;
326 PhysicsFile.GetLength(length);
327
328 while (position < length)
329 {
330 std::vector<uint8> header(12);
331 PhysicsFile.Read(header.size(), &header[0]);
332 AIStreamBE header_stream(&header[0], header.size());
333
334 uint32 tag;
335 uint16 count;
336 uint16 size;
337
338 header_stream >> tag;
339 header_stream.ignore(4); // unused
340 header_stream >> count;
341 header_stream >> size;
342
343 std::vector<uint8> data(count * size);
344 PhysicsFile.Read(data.size(), &data[0]);
345 switch (tag)
346 {
347 case M1_MONSTER_PHYSICS_TAG:
348 unpack_m1_monster_definition(&data[0], count);
349 break;
350 case M1_EFFECTS_PHYSICS_TAG:
351 unpack_m1_effect_definition(&data[0], count);
352 break;
353 case M1_PROJECTILE_PHYSICS_TAG:
354 unpack_m1_projectile_definition(&data[0], count);
355 break;
356 case M1_PHYSICS_PHYSICS_TAG:
357 unpack_m1_physics_constants(&data[0], count);
358 break;
359 case M1_WEAPONS_PHYSICS_TAG:
360 unpack_m1_weapon_definition(&data[0], count);
361 break;
362 }
363
364 PhysicsFile.GetPosition(position);
365 }
366 }
367
import_m1_physics_data_from_network(uint8 * data,uint32 length)368 static void import_m1_physics_data_from_network(uint8 *data, uint32 length)
369 {
370 int32 position = 0;
371 while (position < length)
372 {
373 AIStreamBE header_stream(&data[position], 12);
374 position += 12;
375
376 uint32 tag;
377 uint16 count;
378 uint16 size;
379
380 header_stream >> tag;
381 header_stream.ignore(4); // unused
382 header_stream >> count;
383 header_stream >> size;
384
385 switch (tag)
386 {
387 case M1_MONSTER_PHYSICS_TAG:
388 unpack_m1_monster_definition(&data[position], count);
389 break;
390 case M1_EFFECTS_PHYSICS_TAG:
391 unpack_m1_effect_definition(&data[position], count);
392 break;
393 case M1_PROJECTILE_PHYSICS_TAG:
394 unpack_m1_projectile_definition(&data[position], count);
395 break;
396 case M1_PHYSICS_PHYSICS_TAG:
397 unpack_m1_physics_constants(&data[position], count);
398 break;
399 case M1_WEAPONS_PHYSICS_TAG:
400 unpack_m1_weapon_definition(&data[position], count);
401 break;
402 }
403 position += count * size;
404 }
405 }
406
407