Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
w3d_dep.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : G *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/w3d_dep.cpp $*
26 * *
27 * $Author:: Byon_g $*
28 * *
29 * $Modtime:: 7/23/01 6:17p $*
30 * *
31 * $Revision:: 4 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * Get_W3D_Dependencies -- Scans a W3D file to determine which other files it depends on. *
36 * Scan_Chunk -- Chooses the correct chunk loader for this chunk. *
37 * Scan_Mesh -- Scans a mesh for references to other files. *
38 * Scan_Mesh_Header -- Scans a mesh's header for file references. *
39 * Scan_Mesh_Textures -- Scans a mesh's textures. *
40 * Scan_HTree -- Scans an HTree for references to other files. *
41 * Scan_Anim -- Scans an animation for references to other files. *
42 * Scan_Compressed_Anim -- Scans an animation for references to other files. *
43 * Scan_HModel -- Scans an HModel for references to other files. *
44 * Scan_Emitter -- Scans an emitter for references to other files. *
45 * Scan_Aggregate -- Scans an aggregate for references to other files. *
46 * Scan_HLOD -- Scans an HLOD for references to other files. *
47 * Get_W3D_Name -- Gets a W3D object name from a W3D filename. *
48 * Make_W3D_Filename -- Converts a W3D object name into a W3D filename. *
49 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
50
51//-----------------------------------------------------------------------------
52// srj sez: hack festival :-(
54{
55public:
56 // this one is needed for proper simple_alloc wrapping
57 static void* allocate(size_t __n) { return ::operator new(__n); }
58 static void deallocate(void* __p, size_t) { ::operator delete(__p); }
59};
60
61
62#include "w3d_dep.h"
63#include "w3d_file.h"
64#include <assert.h>
65#include <chunkio.h>
66#include "ffactory.h"
67
68
69/*
70** Forward declarations.
71*/
72
73static void Scan_Chunk (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
74
75static void Scan_Mesh (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
76static void Scan_Mesh_Header (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
77static void Scan_Mesh_Textures (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
78
79static void Scan_Anim (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
80static void Scan_Compressed_Anim (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
81static void Scan_HModel (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
82static void Scan_Emitter (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
83static void Scan_Aggregate (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
84static void Scan_HLOD (ChunkLoadClass &cload, StringList &files, const char *w3d_name);
85
86static void Get_W3D_Name (const char *filename, char *w3d_name);
87static const char * Make_W3D_Filename (const char *w3d_name);
88
89
90/***********************************************************************************************
91 * Get_W3D_Dependencies -- Scans a W3D file to determine which other files it depends on. *
92 * *
93 * INPUT: *
94 * *
95 * OUTPUT: *
96 * *
97 * WARNINGS: *
98 * *
99 * HISTORY: *
100 * 4/3/00 AJA : Created. *
101 *=============================================================================================*/
102bool Get_W3D_Dependencies (const char *w3d_filename, StringList &files)
103{
104 assert(w3d_filename);
105
106 // Open the W3D file.
107 FileClass *file=_TheFileFactory->Get_File(w3d_filename);
108 if ( file ) {
109 file->Open();
110 if ( ! file->Is_Open()) {
111 _TheFileFactory->Return_File(file);
112 file=NULL;
113 return false;
114 }
115 } else {
116 return false;
117 }
118
119 // Get the W3D name from the filename.
120 char w3d_name[W3D_NAME_LEN];
121 Get_W3D_Name(w3d_filename, w3d_name);
122
123 // Create a chunk loader for this file, and scan the file.
124 ChunkLoadClass cload(file);
125 while (cload.Open_Chunk())
126 {
127 Scan_Chunk(cload, files, w3d_name);
128 cload.Close_Chunk();
129 }
130
131 // Close the file.
132 file->Close();
133 _TheFileFactory->Return_File(file);
134 file=NULL;
135
136 // Sort the set of filenames, and remove any duplicates.
137 files.sort();
138 files.unique();
139
140 return true;
141}
142
143
144/***********************************************************************************************
145 * Scan_Chunk -- Chooses the correct chunk loader for this chunk. *
146 * *
147 * INPUT: *
148 * *
149 * OUTPUT: *
150 * *
151 * WARNINGS: *
152 * *
153 * HISTORY: *
154 * 4/3/00 AJA : Created. *
155 *=============================================================================================*/
156static void Scan_Chunk (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
157{
158 assert(w3d_name);
159
160 switch (cload.Cur_Chunk_ID())
161 {
162 case W3D_CHUNK_MESH:
163 Scan_Mesh(cload, files, w3d_name);
164 break;
165
167 Scan_Anim(cload, files, w3d_name);
168 break;
169
171 Scan_Compressed_Anim(cload, files, w3d_name);
172 break;
173
174 case W3D_CHUNK_HMODEL:
175 Scan_HModel(cload, files, w3d_name);
176 break;
177
179 Scan_Emitter(cload, files, w3d_name);
180 break;
181
183 Scan_Aggregate(cload, files, w3d_name);
184 break;
185
186 case W3D_CHUNK_HLOD:
187 Scan_HLOD(cload, files, w3d_name);
188 break;
189 }
190}
191
192
193/***********************************************************************************************
194 * Scan_Mesh -- Scans a mesh for references to other files. *
195 * *
196 * INPUT: *
197 * *
198 * OUTPUT: *
199 * *
200 * WARNINGS: *
201 * *
202 * HISTORY: *
203 *=============================================================================================*/
204static void Scan_Mesh (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
205{
206 // Scan the mesh's sub-chunks.
207 while (cload.Open_Chunk())
208 {
209 switch (cload.Cur_Chunk_ID())
210 {
212 // Ahh, the mesh header.
213 Scan_Mesh_Header(cload, files, w3d_name);
214 break;
215
217 // We sure want textures...
218 Scan_Mesh_Textures(cload, files, w3d_name);
219 break;
220 }
221 cload.Close_Chunk();
222 }
223}
224
225/***********************************************************************************************
226 * Scan_Mesh_Header -- Scans a mesh's header for file references. *
227 * *
228 * INPUT: *
229 * *
230 * OUTPUT: *
231 * *
232 * WARNINGS: *
233 * *
234 * HISTORY: *
235 * 4/3/00 AJA : Created. *
236 *=============================================================================================*/
237static void Scan_Mesh_Header (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
238{
239 // In the mesh header, we want the 'ContainerName' string.
241 cload.Read(&hdr, sizeof(hdr));
242 if (strcmp(hdr.ContainerName, w3d_name) != 0)
243 {
244 // The container is not this file... Create a W3D filename
245 // for the container object and add it to the list of
246 // files we refer to.
247 const char *filename = Make_W3D_Filename(hdr.ContainerName);
248 if (*filename) // don't push empty filenames
249 files.push_back(filename);
250 }
251}
252
253/***********************************************************************************************
254 * Scan_Mesh_Textures -- Scans a mesh's textures. *
255 * *
256 * INPUT: *
257 * *
258 * OUTPUT: *
259 * *
260 * WARNINGS: *
261 * *
262 * HISTORY: *
263 * 4/3/00 AJA : Created. *
264 *=============================================================================================*/
265static void Scan_Mesh_Textures (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
266{
267 // Let's see which textures are used by this mesh...
268 while (cload.Open_Chunk())
269 {
270 // We're interested in the TEXTURE sub-chunk.
271 if (cload.Cur_Chunk_ID() == W3D_CHUNK_TEXTURE)
272 {
273 while (cload.Open_Chunk())
274 {
275 // We're interested in the TEXTURE_NAME sub-chunk.
277 {
278 // This chunk's data is a NULL-terminated string
279 // which is the texture filename. Read it and
280 // add it to the list of files referred to.
281 char texture[_MAX_PATH];
282 cload.Read(texture, cload.Cur_Chunk_Length());
283 if (*texture) // don't push empty filenames
284 files.push_back(texture);
285 }
286 cload.Close_Chunk();
287 }
288 }
289 cload.Close_Chunk();
290 }
291}
292
293
294/***********************************************************************************************
295 * Scan_Anim -- Scans an animation for references to other files. *
296 * *
297 * INPUT: *
298 * *
299 * OUTPUT: *
300 * *
301 * WARNINGS: *
302 * *
303 * HISTORY: *
304 *=============================================================================================*/
305static void Scan_Anim (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
306{
307 while (cload.Open_Chunk())
308 {
309 // We only want the animation header, because it can refer to an HTree.
311 {
312 // Read in the header.
314 cload.Read(&hdr, sizeof(hdr));
315 if (strcmp(hdr.HierarchyName, w3d_name) != 0)
316 {
317 const char *hierarchy = Make_W3D_Filename(hdr.HierarchyName);
318 if (*hierarchy) // don't push an empty filename
319 files.push_back(hierarchy);
320 }
321 }
322 cload.Close_Chunk();
323 }
324}
325
326
327/***********************************************************************************************
328 * Scan_Compressed_Anim -- Scans a compressed animation mesh for references to other files. *
329 * *
330 * INPUT: *
331 * *
332 * OUTPUT: *
333 * *
334 * WARNINGS: *
335 * *
336 * HISTORY: *
337 *=============================================================================================*/
338static void Scan_Compressed_Anim (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
339{
340 while (cload.Open_Chunk())
341 {
342 // We only want the animation header, because it can refer to an HTree.
344 {
345 // Read in the header.
347 cload.Read(&hdr, sizeof(hdr));
348 if (strcmp(hdr.HierarchyName, w3d_name) != 0)
349 {
350 const char *hierarchy = Make_W3D_Filename(hdr.HierarchyName);
351 if (*hierarchy) // don't push an empty filename
352 files.push_back(hierarchy);
353 }
354 }
355 cload.Close_Chunk();
356 }
357}
358
359
360/***********************************************************************************************
361 * Scan_HModel -- Scans an HModel for references to other files. *
362 * *
363 * INPUT: *
364 * *
365 * OUTPUT: *
366 * *
367 * WARNINGS: *
368 * *
369 * HISTORY: *
370 *=============================================================================================*/
371static void Scan_HModel (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
372{
373 while (cload.Open_Chunk())
374 {
375 // We only want the header because it can refer to an HTree.
377 {
378 // Read in the header.
380 cload.Read(&hdr, sizeof(hdr));
381 if (strcmp(hdr.HierarchyName, w3d_name) != 0)
382 {
383 const char *hierarchy = Make_W3D_Filename(hdr.HierarchyName);
384 if (*hierarchy) // don't push an empty filename
385 files.push_back(hierarchy);
386 }
387 }
388 cload.Close_Chunk();
389 }
390}
391
392
393/***********************************************************************************************
394 * Scan_Emitter -- Scans an emitter for references to other files. *
395 * *
396 * INPUT: *
397 * *
398 * OUTPUT: *
399 * *
400 * WARNINGS: *
401 * *
402 * HISTORY: *
403 *=============================================================================================*/
404static void Scan_Emitter (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
405{
406 while (cload.Open_Chunk())
407 {
408 // We only want the emitter info chunk, it has a texture name in it.
410 {
411 // Read in the header.
413 cload.Read(&hdr, sizeof(hdr));
414 if (hdr.TextureFilename[0]) // don't push an empty texture name
415 files.push_back(hdr.TextureFilename);
416 }
417 cload.Close_Chunk();
418 }
419}
420
421
422/***********************************************************************************************
423 * Scan_Aggregate -- Scans an aggregate for references to other files. *
424 * *
425 * INPUT: *
426 * *
427 * OUTPUT: *
428 * *
429 * WARNINGS: *
430 * *
431 * HISTORY: *
432 *=============================================================================================*/
433static void Scan_Aggregate (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
434{
435 while (cload.Open_Chunk())
436 {
437 // We want the aggregate info chunk.
439 {
441 cload.Read(&chunk, sizeof(chunk));
442 if (strcmp(chunk.BaseModelName, w3d_name) != 0)
443 {
444 // Check the name of the base model against the name of this file.
445 const char *base_model = Make_W3D_Filename(chunk.BaseModelName);
446 if (*base_model)
447 files.push_back(base_model);
448 }
449
450 // Iterate through the sub-objects.
451 unsigned int i;
452 for (i = 0; i < chunk.SubobjectCount; ++i)
453 {
455 cload.Read(&subchunk, sizeof(subchunk));
456 if (strcmp(subchunk.SubobjectName, w3d_name) != 0)
457 {
458 // Check the name of the subobject against the name of this file.
459 const char *subobject = Make_W3D_Filename(subchunk.SubobjectName);
460 if (*subobject)
461 files.push_back(subobject);
462 }
463 }
464 }
465 cload.Close_Chunk();
466 }
467}
468
469
470/***********************************************************************************************
471 * Scan_HLOD -- Scans an HLOD for references to other files. *
472 * *
473 * INPUT: *
474 * *
475 * OUTPUT: *
476 * *
477 * WARNINGS: *
478 * *
479 * HISTORY: *
480 *=============================================================================================*/
481static void Scan_HLOD (ChunkLoadClass &cload, StringList &files, const char *w3d_name)
482{
483 while (cload.Open_Chunk())
484 {
485 // We only want the header.
486 if (cload.Cur_Chunk_ID() == W3D_CHUNK_HLOD_HEADER)
487 {
489 cload.Read(&hdr, sizeof(hdr));
490 if (strcmp(hdr.HierarchyName, w3d_name) != 0)
491 {
492 const char *hierarchy = Make_W3D_Filename(hdr.HierarchyName);
493 if (*hierarchy)
494 files.push_back(hierarchy);
495 }
496 }
497 cload.Close_Chunk();
498 }
499}
500
501
502/***********************************************************************************************
503 * Get_W3D_Name -- Gets a W3D object name from a W3D filename. *
504 * *
505 * INPUT: *
506 * *
507 * OUTPUT: *
508 * *
509 * WARNINGS: *
510 * *
511 * HISTORY: *
512 * 4/3/00 AJA : Created. *
513 *=============================================================================================*/
514static void Get_W3D_Name (const char *filename, char *w3d_name)
515{
516 assert(filename);
517 assert(w3d_name);
518
519 // Figure out the first character of the name of the file
520 // (bypass the path if it was given).
521 const char *start = strrchr(filename, '\\');
522 if (start)
523 ++start; // point to first character after the last backslash
524 else
525 start = filename; // point to the start of the filename
526
527 // We don't want to copy the .w3d extension. Find where
528 // it occurs.
529 const char *end = strrchr(start, '.');
530 if (!end)
531 end = start + strlen(start); // point to the null character
532
533 // Copy all characters from start to end (excluding 'end')
534 // into the w3d_name buffer. Then capitalize the string.
535 memset(w3d_name, 0, W3D_NAME_LEN); // blank out the buffer
536 int num_chars = end - start;
537 strncpy(w3d_name, start, num_chars < W3D_NAME_LEN ? num_chars : W3D_NAME_LEN-1);
538 strupr(w3d_name);
539}
540
541
542/***********************************************************************************************
543 * Make_W3D_Filename -- Converts a W3D object name into a W3D filename. *
544 * *
545 * INPUT: *
546 * *
547 * OUTPUT: *
548 * *
549 * WARNINGS: *
550 * *
551 * HISTORY: *
552 * 4/3/00 AJA : Created. *
553 *=============================================================================================*/
554static const char * Make_W3D_Filename (const char *w3d_name)
555{
556 assert(w3d_name);
557 assert(strlen(w3d_name) < W3D_NAME_LEN);
558
559 // Copy the w3d name into a static buffer, turn it into lowercase
560 // letters, and append a ".w3d" file extension. That's the filename.
561 static char buffer[64];
562 if (*w3d_name == 0)
563 {
564 // Empty W3D name case.
565 buffer[0] = 0;
566 return buffer;
567 }
568 strcpy(buffer, w3d_name);
569 char *dot = strchr(buffer, '.');
570 if (dot)
571 *dot = 0;
572 strlwr(buffer);
573 strcat(buffer, ".w3d");
574 return buffer;
575}
#define NULL
Definition BaseType.h:92
#define W3D_NAME_LEN
Definition w3d_file.h:319
@ W3D_CHUNK_TEXTURE_NAME
Definition w3d_file.h:368
@ W3D_CHUNK_AGGREGATE_INFO
Definition w3d_file.h:461
@ W3D_CHUNK_HMODEL_HEADER
Definition w3d_file.h:419
@ W3D_CHUNK_HMODEL
Definition w3d_file.h:418
@ W3D_CHUNK_EMITTER
Definition w3d_file.h:444
@ W3D_CHUNK_HLOD
Definition w3d_file.h:465
@ W3D_CHUNK_MESH
Definition w3d_file.h:341
@ W3D_CHUNK_COMPRESSED_ANIMATION
Definition w3d_file.h:406
@ W3D_CHUNK_AGGREGATE
Definition w3d_file.h:459
@ W3D_CHUNK_ANIMATION_HEADER
Definition w3d_file.h:402
@ W3D_CHUNK_TEXTURE
Definition w3d_file.h:367
@ W3D_CHUNK_TEXTURES
Definition w3d_file.h:366
@ W3D_CHUNK_MESH_HEADER3
Definition w3d_file.h:346
@ W3D_CHUNK_ANIMATION
Definition w3d_file.h:401
@ W3D_CHUNK_EMITTER_INFO
Definition w3d_file.h:447
@ W3D_CHUNK_HLOD_HEADER
Definition w3d_file.h:466
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Cur_Chunk_Length()
Definition chunkio.cpp:503
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
virtual bool Is_Open(void) const =0
virtual void Close(void)=0
virtual int Open(char const *filename, int rights=READ)=0
static void deallocate(void *__p, size_t)
Definition w3d_dep.cpp:58
static void * allocate(size_t __n)
Definition w3d_dep.cpp:57
FileFactoryClass * _TheFileFactory
Definition ffactory.cpp:51
char BaseModelName[W3D_NAME_LEN *2]
Definition w3d_file.h:1974
char SubobjectName[W3D_NAME_LEN *2]
Definition w3d_file.h:1980
char HierarchyName[W3D_NAME_LEN]
Definition w3d_file.h:1394
char HierarchyName[W3D_NAME_LEN]
Definition w3d_file.h:1404
char TextureFilename[260]
Definition w3d_file.h:1781
char HierarchyName[W3D_NAME_LEN]
Definition w3d_file.h:2052
char HierarchyName[W3D_NAME_LEN]
Definition w3d_file.h:1584
char ContainerName[W3D_NAME_LEN]
Definition w3d_file.h:1207
bool Get_W3D_Dependencies(const char *w3d_filename, StringList &files)
Definition w3d_dep.cpp:102
std::list< std::string > StringList
Definition w3d_dep.h:51