Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
iff.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#include "stdAfx.h"
21#include "sys/stat.h"
22#include "iff.h"
23#include <fcntl.h>
24#include <io.h>
25#include <stdlib.h>
26#include <stdio.h>
27
28#define IFF_RAWREAD(iff,data,size,label) {if ( IFF_rawread ( (iff), (data), (size)) != (size)) goto label;}
29
30
31int IFF_rawread ( IFF_FILE *iff, void *buffer, int bytes )
32{
33 if ( ! (iff->flags & mIFF_FILE_LOADED ) )
34 {
35 return _read ( iff->fp, buffer, bytes );
36 }
37
38 if ( iff->file_size < (iff->file_pos + bytes) )
39 {
40 bytes = iff->file_size - iff->file_pos;
41 }
42 memcpy ( buffer, &iff->mem_file[iff->file_pos], bytes );
43 iff->file_pos += bytes;
44 return bytes;
45}
46
47/******************************************************************/
48/* */
49/* */
50/******************************************************************/
51
52int IFF_seek ( IFF_FILE *iff, int pos, int mode )
53{
54
55 if ( ! (iff->flags & mIFF_FILE_LOADED ))
56 {
57 return lseek ( iff->fp, pos, mode );
58 }
59
60 switch ( mode )
61 {
62 case SEEK_CUR:
63 iff->file_pos += pos;
64 break;
65 case SEEK_END:
66 iff->file_pos = iff->file_size - pos;
67 break;
68 case SEEK_SET:
69 iff->file_pos = pos;
70 break;
71 }
72
73 if ( iff->file_pos < 0 )
74 {
75 iff->file_pos = 0;
76 }
77 else
78 {
79 if ( iff->file_pos > iff->file_size )
80 {
81 iff->file_pos = iff->file_size;
82 }
83 }
84
85 return iff->file_pos;
86}
87
88/******************************************************************/
89/* */
90/* */
91/******************************************************************/
92
93IFF_FILE *IFF_Open ( const char *name )
94{
95 IFF_FILE *iff = NULL;
96
97
98 if ( ! (iff = (IFF_FILE *) malloc ( sizeof (IFF_FILE))))
99 {
100 goto error;
101 }
102
103 iff->fp = -1;
104 memset ( iff, 0, sizeof ( IFF_FILE ));
105
106 if ((iff->fp = open ( name, _O_BINARY | _O_RDONLY )) == -1 )
107 {
108 goto error;
109 }
110
111
112 return iff;
113
114error:
115
116 if (iff)
117 {
118 IFF_Close ( iff );
119 }
120
121 return NULL;
122}
123
124/******************************************************************/
125/* */
126/* */
127/******************************************************************/
128
129IFF_FILE *IFF_Load ( const char *name )
130{
131 IFF_FILE *iff = NULL;
132
133 if ( ! (iff = (IFF_FILE *) malloc ( sizeof (IFF_FILE))))
134 {
135 goto error;
136 }
137
138 memset ( iff, 0, sizeof ( IFF_FILE ));
139 iff->fp = -1;
140
141 if ((iff->fp = open ( name, _O_BINARY | _O_RDONLY )) == -1 )
142 {
143 goto error;
144 }
145
146 iff->file_size = lseek ( iff->fp, 0, SEEK_END );
147 lseek ( iff->fp, 0, SEEK_SET );
148
149 if ( !(iff->mem_file = ( char *) malloc ( iff->file_size) ) )
150 {
151 goto error;
152 }
153
154 DO_READ ( iff->fp, iff->mem_file, iff->file_size, error );
155
156 iff->flags |= mIFF_FILE_LOADED;
157
158 return iff;
159
160error:
161
162 if (iff)
163 {
164 IFF_Close ( iff );
165 }
166
167 return NULL;
168}
169
170/******************************************************************/
171/* */
172/* */
173/******************************************************************/
174
175void IFF_Reset ( IFF_FILE *iff )
176{
177 IFF_seek ( iff, 0, SEEK_SET );
178 iff->pad_form = 0;
179 iff->pad_chunk = 0;
180 iff->FormSize = 0;
181 iff->ChunkSize = 0;
182 iff->next_byte = 0;
183 iff->chunk_size_pos = 0;
184 iff->form_size_pos = 0;
185
186}
187
188/******************************************************************/
189/* */
190/* */
191/******************************************************************/
192
194{
195
196 iff->FormSize += iff->pad_form;
197 iff->pad_form = 0;
198 if (iff->FormSize)
199 {
200 IFF_seek ( iff, iff->FormSize, SEEK_CUR );
201 iff->next_byte += iff->FormSize;
202 iff->FormSize = 0;
203 iff->ChunkSize = 0;
204 }
205
206}
207
208/******************************************************************/
209/* */
210/* */
211/******************************************************************/
212
214{
215
216 iff->ChunkSize += iff->pad_chunk;
217 iff->pad_chunk = 0;
218 if (iff->ChunkSize)
219 {
220 IFF_seek ( iff, iff->ChunkSize, SEEK_CUR );
221 iff->next_byte += iff->ChunkSize;
222 iff->FormSize -= iff->ChunkSize;
223 iff->ChunkSize = 0;
224 }
225}
226
227
228
229/******************************************************************/
230/* */
231/* */
232/******************************************************************/
233
235{
236 IFF_CHUNK chunk;
237 int form;
238
239 IFF_goto_form_end ( iff );
240
241 IFF_RAWREAD (iff, &chunk, sizeof( IFF_CHUNK ), error );
242
243 chunk.Size = BgEn32 (chunk.Size);
244 chunk.ID = BgEn32 (chunk.ID);
245
246 iff->pad_form = (int) (chunk.Size & 0x0001);
247
248 if (chunk.ID != vIFF_ID_FORM )
249 {
250 goto error;
251 }
252
253 IFF_RAWREAD (iff, &form, sizeof( int ), error);
254
255 iff->FormID = (int) BgEn32 (form);
256
258 iff->next_byte += sizeof( int ) + sizeof ( IFF_CHUNK );
259 iff->FormSize = (int) chunk.Size - sizeof ( int );
260 iff->ChunkSize = 0;
261 iff->pad_chunk = 0;
262
263 return TRUE;
264
265error:
266
267 return FALSE;
268}
269
270/******************************************************************/
271/* */
272/* */
273/******************************************************************/
274
276{
277 IFF_CHUNK chunk;
278
279 IFF_goto_chunk_end ( iff );
280
281 if (iff->FormSize==0)
282 {
283 goto error;
284 }
285
286 IFF_RAWREAD ( iff, &chunk, sizeof( IFF_CHUNK ), error );
287
288 chunk.Size = BgEn32 (chunk.Size);
289 chunk.ID = BgEn32 (chunk.ID);
290
291 iff->pad_chunk = (int) (chunk.Size & 0x0001);
292
294 iff->ChunkID = (int) chunk.ID;
295 iff->ChunkSize = (int) chunk.Size;
296 iff->next_byte += sizeof ( IFF_CHUNK );
297 iff->FormSize -= sizeof ( IFF_CHUNK );
298
299 return TRUE;
300
301error:
302
303 return FALSE;
304}
305
306/******************************************************************/
307/* */
308/* */
309/******************************************************************/
310
311void IFF_Close ( IFF_FILE *iff )
312{
313 if (iff->fp != -1)
314 {
315 _close (iff->fp);
316 }
317
318 if ( iff->mem_file )
319 {
320 free ( iff->mem_file );
321 }
322
323 free ( iff );
324}
325
326/******************************************************************/
327/* */
328/* */
329/******************************************************************/
330
331int IFF_Read ( IFF_FILE *iff, void *buff, int size )
332{
333 int read =0;
334
335 if ( size>iff->ChunkSize )
336 {
337 size = iff->ChunkSize;
338 }
339
340 read = IFF_rawread ( iff, buff, size);
341
342 if (read==-1)
343 {
344 read = 0;
345 }
346
347 iff->ChunkSize -= read;
348 iff->FormSize -= read;
349 iff->next_byte += read;
350
351
352 return read;
353}
354
355/******************************************************************/
356/* */
357/* */
358/******************************************************************/
359
360IFF_FILE *IFF_New ( const char *name )
361{
362 IFF_FILE *iff = NULL;
363
364
365 if ( ! (iff = (IFF_FILE *) malloc ( sizeof (IFF_FILE))))
366 {
367 goto error;
368 }
369
370 memset ( iff, 0, sizeof ( IFF_FILE ));
371 iff->fp = -1;
372
373 if ((iff->fp = _open ( name, _O_BINARY | _O_RDWR | _O_CREAT | _O_TRUNC, _S_IREAD | _S_IWRITE )) == -1 )
374 {
375 goto error;
376 }
377
378 return iff;
379
380error:
381
382 if (iff)
383 {
384 IFF_Close ( iff );
385 }
386
387 return NULL;
388}
389
390/******************************************************************/
391/* */
392/* */
393/******************************************************************/
394
395int IFF_NewForm ( IFF_FILE *iff, int id )
396{
397 IFF_CHUNK chunk;
398
399 chunk.ID = BgEn32 (vIFF_ID_FORM);
400 chunk.Size = BgEn32 (90000);
401
402 iff->FormSize = 0;
403 iff->ChunkSize = 0;
404 iff->FormID = id;
405
406 DO_WRITE ( iff->fp, &chunk, sizeof (IFF_CHUNK), error);
407
408 chunk.ID = BgEn32 ( (int) iff->FormID);
409 DO_WRITE ( iff->fp, &chunk.ID, sizeof (int), error );
410
412 iff->form_size_pos = iff->next_byte + sizeof (int);
413 iff->next_byte += sizeof ( IFF_CHUNK ) + sizeof (int);
414
415 return TRUE;
416
417error:
418
419 return FALSE;
420}
421
422/******************************************************************/
423/* */
424/* */
425/******************************************************************/
426
427int IFF_NewChunk ( IFF_FILE *iff, int id )
428{
429 IFF_CHUNK chunk;
430
431 chunk.Size = BgEn32 (90000);
432 chunk.ID = BgEn32 ( (int) id);
433
434
435 DO_WRITE ( iff->fp, &chunk, sizeof ( IFF_CHUNK ), error );
436
438 iff->chunk_size_pos = iff->next_byte + sizeof (int);
439 iff->next_byte += sizeof ( IFF_CHUNK ) ;
440 iff->FormSize += sizeof ( IFF_CHUNK ) ;
441 iff->ChunkSize = 0;
442 iff->ChunkID = id;
443
444 return TRUE;
445
446error:
447
448 return FALSE;
449
450}
451
452/******************************************************************/
453/* */
454/* */
455/******************************************************************/
456
457int IFF_Write ( IFF_FILE *iff, void *buff, int size )
458{
459 int val =0;
460
461 val = _write ( iff->fp, buff, size);
462
463 if (val==-1)
464 {
465 val = 0;
466 }
467
468 iff->ChunkSize += val;
469 iff->FormSize += val;
470 iff->next_byte += val;
471
472
473 return val;
474}
475
476/******************************************************************/
477/* */
478/* */
479/******************************************************************/
480
482{
483 int fp;
484 int off;
485 int size;
486 int pad = 0;
487
488 if (iff && ((fp = iff->fp) != -1))
489 {
490
491 if (iff->FormSize&0x0001)
492 {
493 DO_WRITE (fp, &pad, 1, error );
494 iff->next_byte++;
495 }
496
497 off = iff->next_byte - iff->form_size_pos;
498
499 size = BgEn32 ( (int) (iff->FormSize+sizeof ( int )));
500
501 if (lseek (fp, -off, SEEK_CUR)==iff->form_size_pos)
502 {
503 DO_WRITE ( fp, &size, sizeof (int), error );
504 lseek ( fp, 0, SEEK_END);
505 return TRUE;
506 }
507 }
508
509error:
510
511 return FALSE;
512}
513
514
515/******************************************************************/
516/* */
517/* */
518/******************************************************************/
519
521{
522 int fp;
523 int off;
524 int size;
525 int pad = 0;
526
527 if (iff && ((fp = iff->fp) != -1 ))
528 {
529
530 if (iff->ChunkSize&0x0001)
531 {
532 DO_WRITE (fp, &pad, 1, error );
533 iff->next_byte++;
534 iff->FormSize++;
535 }
536
537 off = iff->next_byte - iff->chunk_size_pos;
538
539 size = BgEn32 ((int) iff->ChunkSize);
540
541 if (lseek (fp, -off, SEEK_CUR)==iff->chunk_size_pos)
542 {
543 DO_WRITE ( fp, &size, sizeof (int), error );
544 lseek ( fp, 0, SEEK_END);
545 return TRUE;
546 }
547 }
548
549error:
550
551 return TRUE;
552}
553
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
#define SEEK_SET
Definition WWFILE.H:55
#define SEEK_CUR
Definition WWFILE.H:56
#define SEEK_END
Definition WWFILE.H:57
#define BgEn32(L)
Definition iff.h:118
#define mIFF_FILE_CHUNKOPEN
Definition iff.h:39
#define mIFF_FILE_LOADED
Definition iff.h:40
#define vIFF_ID_FORM
Definition iff.h:27
#define mIFF_FILE_FORMOPEN
Definition iff.h:38
#define DO_READ(P, B, S, E)
Definition iff.h:95
#define DO_WRITE(P, B, S, E)
Definition iff.h:96
int IFF_CloseChunk(IFF_FILE *iff)
Definition iff.cpp:520
int IFF_NewForm(IFF_FILE *iff, int id)
Definition iff.cpp:395
int IFF_CloseForm(IFF_FILE *iff)
Definition iff.cpp:481
int IFF_Write(IFF_FILE *iff, void *buff, int size)
Definition iff.cpp:457
int IFF_NextForm(IFF_FILE *iff)
Definition iff.cpp:234
int IFF_NewChunk(IFF_FILE *iff, int id)
Definition iff.cpp:427
void IFF_goto_chunk_end(IFF_FILE *iff)
Definition iff.cpp:213
#define IFF_RAWREAD(iff, data, size, label)
Definition iff.cpp:28
int IFF_rawread(IFF_FILE *iff, void *buffer, int bytes)
Definition iff.cpp:31
IFF_FILE * IFF_New(const char *name)
Definition iff.cpp:360
void IFF_goto_form_end(IFF_FILE *iff)
Definition iff.cpp:193
int IFF_Read(IFF_FILE *iff, void *buff, int size)
Definition iff.cpp:331
IFF_FILE * IFF_Load(const char *name)
Definition iff.cpp:129
int IFF_seek(IFF_FILE *iff, int pos, int mode)
Definition iff.cpp:52
IFF_FILE * IFF_Open(const char *name)
Definition iff.cpp:93
int IFF_NextChunk(IFF_FILE *iff)
Definition iff.cpp:275
void IFF_Reset(IFF_FILE *iff)
Definition iff.cpp:175
void IFF_Close(IFF_FILE *iff)
Definition iff.cpp:311
int Size
Definition iff.h:46
int ID
Definition iff.h:45
Definition iff.h:50
int ChunkID
Definition iff.h:54
int FormID
Definition iff.h:53
int next_byte
Definition iff.h:62
int file_size
Definition iff.h:67
int form_size_pos
Definition iff.h:64
int chunk_size_pos
Definition iff.h:63
int flags
Definition iff.h:61
char * mem_file
Definition iff.h:69
int file_pos
Definition iff.h:68
int FormSize
Definition iff.h:55
int fp
Definition iff.h:60
int pad_chunk
Definition iff.h:66
int ChunkSize
Definition iff.h:56
int pad_form
Definition iff.h:65