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