Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
loadsave.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// loadsave.cpp
21//
22
23#include "stdAfx.h"
24#include "iff.h"
25#include "TransDB.h"
26#include "Babylondlg.h"
27
28#define FORM_BABYLONDB MakeID ('N','X','D','B')
29#define FORM_LABEL MakeID ('N','L','B','L')
30#define FORM_TEXT MakeID ('N','T','X','T')
31#define FORM_TRANS MakeID ('N','T','R','N')
32#define CHUNK_COMMENT MakeID ('C','M','N','T')
33#define CHUNK_CONTEXT MakeID ('C','T','X','T')
34#define CHUNK_SPEAKER MakeID ('S','P','K','R')
35#define CHUNK_LISTENER MakeID ('L','T','N','R')
36#define CHUNK_TEXT MakeID ('T','E','X','T')
37#define CHUNK_WAVE MakeID ('W','A','V','E')
38#define CHUNK_WAVE_INFO MakeID ('W','V','I','N')
39#define CHUNK_INFO MakeID ('I','N','F','O')
40#define CHUNK_NAME MakeID ('N','A','M','E')
41
42#define MAX_BUFFER (100*1024)
43
44static OLECHAR buffer[MAX_BUFFER];
45typedef struct
46{
49
50} DBINFO;
51
52typedef struct
53{
55
56} LBINFO;
57
58typedef struct
59{
60 int id;
62
63} TXINFO;
64
65typedef struct
66{
69
70} TRINFO;
71
72typedef struct
73{
74 int valid;
77
78} WVINFO;
79
80
81static int writeString ( IFF_FILE *iff, OLECHAR *string, int chunk_id )
82{
83 int len = (wcslen ( string ) );
84 int bytes = (len+1)*sizeof(OLECHAR);
85
86 if ( len )
87 {
88 IFF_NEWCHUNK ( iff, chunk_id, error );
89 IFF_WRITE ( iff, string, bytes, error);
90 IFF_CloseChunk ( iff );
91
92 }
93
94 return TRUE;
95
96error:
97
98 return FALSE;
99}
100
101static int readString ( IFF_FILE *iff, OLECHAR *string )
102{
103
104 *string = 0;
105
106 IFF_READ ( iff, string, iff->ChunkSize, error);
107
108 return TRUE;
109
110error:
111
112 return FALSE;
113}
114
115static int writeTransForm ( IFF_FILE *iff, Translation *trans )
116{
117 TRINFO trinfo;
118 WVINFO wvinfo;
119
120 if ( !IFF_NewForm ( iff, FORM_TRANS ))
121 {
122 goto error;
123 }
124
125 trinfo.lang = trans->GetLangID ();
126 trinfo.revision = trans->Revision ();
127
128 if ( !IFF_NewChunk ( iff, CHUNK_INFO ))
129 {
130 goto error;
131 }
132
133 IFF_Write ( iff, &trinfo, sizeof ( trinfo ));
134
135 IFF_CloseChunk ( iff );
136
137 writeString ( iff, trans->Get (), CHUNK_TEXT );
138 writeString ( iff, trans->Comment (), CHUNK_COMMENT );
139
140 if ( (wvinfo.valid = trans->WaveInfo.Valid()) )
141 {
142 wvinfo.lo = trans->WaveInfo.Lo ();
143 wvinfo.hi = trans->WaveInfo.Hi ();
144
145 if ( !IFF_NewChunk ( iff, CHUNK_WAVE_INFO ))
146 {
147 goto error;
148 }
149
150 IFF_Write ( iff, &wvinfo, sizeof ( wvinfo ));
151
152 IFF_CloseChunk ( iff );
153 }
154
155 IFF_CloseForm ( iff );
156
157 return TRUE;
158error:
159
160 return FALSE;
161
162}
163
164static int writeTextForm ( IFF_FILE *iff, BabylonText *text )
165{
166 TXINFO txinfo;
167 WVINFO wvinfo;
168
169 if ( !IFF_NewForm ( iff, FORM_TEXT ))
170 {
171 goto error;
172 }
173
174 txinfo.id = text->ID ();
175 txinfo.revision = text->Revision ();
176
177 if ( !IFF_NewChunk ( iff, CHUNK_INFO ))
178 {
179 goto error;
180 }
181
182 IFF_Write ( iff, &txinfo, sizeof ( txinfo ));
183
184 IFF_CloseChunk ( iff );
185 writeString ( iff, text->Get (), CHUNK_TEXT );
186 writeString ( iff, text->Wave (), CHUNK_WAVE );
187
188 if ( (wvinfo.valid = text->WaveInfo.Valid()) )
189 {
190 wvinfo.lo = text->WaveInfo.Lo ();
191 wvinfo.hi = text->WaveInfo.Hi ();
192
193 if ( !IFF_NewChunk ( iff, CHUNK_WAVE_INFO ))
194 {
195 goto error;
196 }
197
198 IFF_Write ( iff, &wvinfo, sizeof ( wvinfo ));
199
200 IFF_CloseChunk ( iff );
201 }
202
203 IFF_CloseForm ( iff );
204
205 return TRUE;
206error:
207
208 return FALSE;
209
210}
211
212int WriteMainDB(TransDB *db, const char *filename, CBabylonDlg *dlg )
213{
214 BabylonText *text;
216 ListSearch sh_label;
217 ListSearch sh_text;
218 int count = 0;
219 IFF_FILE *iff = NULL;
220 DBINFO dbinfo;
221 int ok = FALSE;
222
223 if ( dlg )
224 {
225 dlg->InitProgress ( db->NumLabels ());
226 }
227
228
229 if ( !( iff = IFF_New ( filename )))
230 {
231 goto error;
232 }
233
234 if ( !IFF_NewForm ( iff, FORM_BABYLONDB ) )
235 {
236 goto error;
237 }
238
239 dbinfo.next_id = db->ID ();
240 dbinfo.num_labels = db->NumLabels ();
241
242 if ( !IFF_NewChunk ( iff, CHUNK_INFO ))
243 {
244 goto error;
245 }
246
247 IFF_Write ( iff, &dbinfo, sizeof ( dbinfo ));
248
249 IFF_CloseChunk ( iff );
250 IFF_CloseForm ( iff );
251
252 text = db->FirstObsolete ( sh_text );
253
254 while ( text )
255 {
256 if ( !writeTextForm ( iff, text ) )
257 {
258 goto error;
259 }
260 text = db->NextObsolete ( sh_text );
261 }
262
263
264
265 label = db->FirstLabel ( sh_label );
266
267 while ( label )
268 {
269 LBINFO lbinfo;
270
271 if ( !IFF_NewForm ( iff, FORM_LABEL ))
272 {
273 goto error;
274 }
275
276 lbinfo.max_len = label->MaxLen ();
277
278 if ( !IFF_NewChunk ( iff, CHUNK_INFO ))
279 {
280 goto error;
281 }
282
283 IFF_Write ( iff, &lbinfo, sizeof ( lbinfo ));
284
285 IFF_CloseChunk ( iff );
286
287 writeString ( iff, label->Name (), CHUNK_NAME );
288 writeString ( iff, label->Comment (), CHUNK_COMMENT );
289 writeString ( iff, label->Context (), CHUNK_CONTEXT );
290 writeString ( iff, label->Speaker (), CHUNK_SPEAKER );
291 writeString ( iff, label->Listener (), CHUNK_LISTENER );
292 IFF_CloseForm ( iff );
293
294 text = label->FirstText ( sh_text );
295
296 while ( text )
297 {
298 Translation *trans;
299 ListSearch sh_trans;
300 if ( !writeTextForm ( iff, text ) )
301 {
302 goto error;
303 }
304
305 trans = text->FirstTranslation ( sh_trans );
306
307 while ( trans )
308 {
309 if ( !writeTransForm ( iff, trans ) )
310 {
311 goto error;
312 }
313
314 trans = text->NextTranslation ( sh_trans );
315 }
316
317 text = label->NextText ( sh_text );
318 }
319
320 count++;
321 if ( dlg )
322 {
323 dlg->SetProgress ( count );
324 }
325 label = db->NextLabel ( sh_label );
326 }
327
328 ok = TRUE;
329 db->ClearChanges ();
330
331error:
332 if ( iff )
333 {
334 IFF_Close ( iff );
335 }
336
337 return ok;
338}
339
340int LoadMainDB(TransDB *db, const char *filename, void (*cb) (void) )
341{
343 BabylonText *text = NULL;
344 Translation *trans = NULL;
345 int count = 0;
346 IFF_FILE *iff = NULL;
347 DBINFO dbinfo;
348 int ok = FALSE;
349
350
351 if ( !(iff = IFF_Load ( filename ) ) )
352 {
353 goto error;
354 }
355
356 if ( !IFF_NextForm ( iff ) || iff->FormID != FORM_BABYLONDB )
357 {
358 goto error;
359 }
360
361 dbinfo.next_id = -1;
362 dbinfo.num_labels = 0;
363
364 while ( IFF_NextChunk ( iff ))
365 {
366 switch (iff->ChunkID )
367 {
368 case CHUNK_INFO:
369 IFF_READ ( iff, &dbinfo, sizeof ( dbinfo ), error );
370 break;
371 }
372 }
373
374 db->SetID ( dbinfo.next_id );
375
376 while ( IFF_NextForm ( iff ) )
377 {
378 switch ( iff->FormID )
379 {
380 case FORM_LABEL:
381 {
382 LBINFO lbinfo;
383 // new label
384
385 if ( text )
386 {
387 if ( label )
388 {
389 label->AddText ( text );
390 }
391 else
392 {
393 db->AddObsolete ( text );
394 }
395
396 text = NULL;
397 }
398
399 if ( label )
400 {
401 count++;
402 db->AddLabel ( label );
403 label = NULL;
404 if ( cb )
405 {
406 cb ();
407 }
408 }
409
410 if ( ! (label = new BabylonLabel ()))
411 {
412 goto error;
413 }
414
415 while ( IFF_NextChunk ( iff ))
416 {
417 switch ( iff->ChunkID )
418 {
419 case CHUNK_INFO:
420 IFF_READ ( iff, &lbinfo, sizeof (lbinfo), error );
421 label->SetMaxLen ( lbinfo.max_len );
422 break;
423 case CHUNK_COMMENT:
424 readString ( iff, buffer );
425 label->SetComment ( buffer );
426 break;
427 case CHUNK_CONTEXT:
428 readString ( iff, buffer );
429 label->SetContext ( buffer );
430 break;
431 case CHUNK_SPEAKER:
432 readString ( iff, buffer );
433 label->SetSpeaker ( buffer );
434 break;
435 case CHUNK_LISTENER:
436 readString ( iff, buffer );
437 label->SetListener ( buffer );
438 break;
439 case CHUNK_NAME:
440 readString ( iff, buffer );
441 label->SetName ( buffer );
442 break;
443 }
444 }
445 break;
446 }
447 case FORM_TEXT:
448 {
449 TXINFO txinfo;
450
451 if ( text )
452 {
453 if ( label )
454 {
455 label->AddText ( text );
456 }
457 else
458 {
459 db->AddObsolete ( text );
460 }
461
462 text = NULL;
463 }
464
465 if ( ! (text = new BabylonText ()))
466 {
467 goto error;
468 }
469
470 while ( IFF_NextChunk ( iff ))
471 {
472 switch ( iff->ChunkID )
473 {
474 case CHUNK_INFO:
475 IFF_READ ( iff, &txinfo, sizeof (txinfo), error );
476 text->SetID ( txinfo.id );
477 text->SetRevision ( txinfo.revision );
478 break;
479 case CHUNK_TEXT:
480 readString ( iff, buffer );
481 text->Set ( buffer );
482 break;
483
484 case CHUNK_WAVE:
485 readString ( iff, buffer );
486 text->SetWave ( buffer );
487 break;
488 case CHUNK_WAVE_INFO:
489 {
490 WVINFO wvinfo;
491 IFF_READ ( iff, &wvinfo, sizeof (wvinfo), error );
492 text->WaveInfo.SetValid ( wvinfo.valid );
493 text->WaveInfo.SetLo ( wvinfo.lo );
494 text->WaveInfo.SetHi ( wvinfo.hi );
495 break;
496 }
497 }
498
499 }
500 break;
501 }
502 case FORM_TRANS:
503 {
504 TRINFO trinfo;
505
506 if ( ! (trans = new Translation ()))
507 {
508 goto error;
509 }
510
511 while ( IFF_NextChunk ( iff ))
512 {
513 switch ( iff->ChunkID )
514 {
515 case CHUNK_INFO:
516 IFF_READ ( iff, &trinfo, sizeof (trinfo), error );
517 trans->SetLangID ( trinfo.lang );
518 trans->SetRevision ( trinfo.revision );
519 break;
520 case CHUNK_TEXT:
521 readString ( iff, buffer );
522 trans->Set ( buffer );
523 break;
524
525 case CHUNK_COMMENT:
526 readString ( iff, buffer );
527 trans->SetComment ( buffer );
528 break;
529 case CHUNK_WAVE_INFO:
530 {
531 WVINFO wvinfo;
532 IFF_READ ( iff, &wvinfo, sizeof (wvinfo), error );
533 trans->WaveInfo.SetValid ( wvinfo.valid );
534 trans->WaveInfo.SetLo ( wvinfo.lo );
535 trans->WaveInfo.SetHi ( wvinfo.hi );
536 }
537 break;
538
539 }
540
541 }
542 if ( text )
543 {
544 text->AddTranslation ( trans );
545 }
546 else
547 {
548 delete trans;
549 }
550 trans = NULL;
551
552 break;
553 }
554 }
555 }
556
557 if ( text )
558 {
559 if ( label )
560 {
561 label->AddText ( text );
562 }
563 else
564 {
565 db->AddObsolete ( text );
566 }
567
568 text = NULL;
569 }
570
571 if ( label )
572 {
573 count++;
574 db->AddLabel ( label );
575 label = NULL;
576 if ( cb )
577 {
578 cb ();
579 }
580 }
581
582 ok = TRUE;
583
584error:
585
586 if ( label )
587 {
588 delete label;
589 }
590
591 if ( text )
592 {
593 delete text;
594 }
595
596 if ( trans )
597 {
598 delete trans;
599 }
600
601 if ( iff )
602 {
603 IFF_Close ( iff );
604 }
605
606 db->ClearChanges ();
607
608 if ( !ok )
609 {
610 db->Clear ();
611 }
612
613 return ok;
614}
615
616
617int GetLabelCountDB ( char *filename )
618{
619 IFF_FILE *iff = NULL;
620 DBINFO dbinfo;
621 int count = 0;
622
623
624 if ( !(iff = IFF_Open ( filename ) ) )
625 {
626 goto error;
627 }
628
629 if ( !IFF_NextForm ( iff ) || iff->FormID != FORM_BABYLONDB )
630 {
631 goto error;
632 }
633
634 dbinfo.next_id = -1;
635 dbinfo.num_labels = 0;
636
637 while ( IFF_NextChunk ( iff ))
638 {
639 switch (iff->ChunkID )
640 {
641 case CHUNK_INFO:
642 IFF_READ ( iff, &dbinfo, sizeof ( dbinfo ), error );
643 break;
644 }
645 }
646
647
648 count = dbinfo.num_labels;
649
650error:
651 if ( iff )
652 {
653 IFF_Close ( iff );
654 }
655 return count;
656}
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
unsigned long DWORD
Definition bittype.h:57
#define IFF_NEWCHUNK(iff, id, label)
Definition iff.h:100
#define IFF_READ(iff, data, size, label)
Definition iff.h:98
#define IFF_WRITE(iff, data, size, label)
Definition iff.h:99
LangID
Definition TransDB.h:69
int Revision(void)
Definition TransDB.h:246
void SetRevision(int new_rev)
Definition TransDB.h:247
int ID(void)
Definition TransDB.h:232
void SetID(int new_id)
Definition TransDB.h:231
void Set(OLECHAR *string)
Definition TransDB.cpp:1237
OLECHAR * Wave(void)
Definition TransDB.h:243
OLECHAR * Get(void)
Definition TransDB.h:235
Translation * FirstTranslation(ListSearch &sh)
Definition TransDB.cpp:1081
CWaveInfo WaveInfo
Definition TransDB.h:212
void SetWave(OLECHAR *string)
Definition TransDB.h:238
Translation * NextTranslation(ListSearch &sh)
Definition TransDB.cpp:1093
void AddTranslation(Translation *trans)
Definition TransDB.cpp:1068
void SetProgress(int pos)
void InitProgress(int range)
int Valid(void)
Definition TransDB.h:107
void SetValid(int new_valid)
Definition TransDB.h:110
DWORD Hi(void)
Definition TransDB.h:109
void SetLo(DWORD new_lo)
Definition TransDB.h:111
DWORD Lo(void)
Definition TransDB.h:108
void SetHi(DWORD new_hi)
Definition TransDB.h:112
int NumLabels(void)
Definition TransDB.cpp:251
void SetID(int new_id)
Definition TransDB.h:401
BabylonLabel * FirstLabel(ListSearch &sh)
Definition TransDB.cpp:257
BabylonText * NextObsolete(ListSearch &sh)
Definition TransDB.cpp:293
void AddLabel(BabylonLabel *label)
Definition TransDB.cpp:149
void ClearChanges(void)
Definition TransDB.cpp:425
int ID(void)
Definition TransDB.h:400
BabylonText * FirstObsolete(ListSearch &sh)
Definition TransDB.cpp:281
void AddObsolete(BabylonText *text)
Definition TransDB.cpp:174
BabylonLabel * NextLabel(ListSearch &sh)
Definition TransDB.cpp:269
int Clear(void)
Definition TransDB.cpp:377
int Revision(void)
Definition TransDB.h:183
void SetRevision(int new_rev)
Definition TransDB.h:184
CWaveInfo WaveInfo
Definition TransDB.h:161
void Set(OLECHAR *string)
Definition TransDB.h:174
OLECHAR * Get(void)
Definition TransDB.h:176
OLECHAR * Comment(void)
Definition TransDB.h:181
void SetLangID(LangID new_id)
Definition TransDB.h:168
LangID GetLangID(void)
Definition TransDB.h:185
void SetComment(OLECHAR *string)
Definition TransDB.h:179
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
IFF_FILE * IFF_New(const char *name)
Definition iff.cpp:360
IFF_FILE * IFF_Load(const char *name)
Definition iff.cpp:129
IFF_FILE * IFF_Open(const char *name)
Definition iff.cpp:93
int IFF_NextChunk(IFF_FILE *iff)
Definition iff.cpp:275
void IFF_Close(IFF_FILE *iff)
Definition iff.cpp:311
#define CHUNK_TEXT
Definition loadsave.cpp:36
#define MAX_BUFFER
Definition loadsave.cpp:42
int LoadMainDB(TransDB *db, const char *filename, void(*cb)(void))
Definition loadsave.cpp:340
#define CHUNK_COMMENT
Definition loadsave.cpp:32
#define FORM_LABEL
Definition loadsave.cpp:29
#define CHUNK_INFO
Definition loadsave.cpp:39
#define CHUNK_CONTEXT
Definition loadsave.cpp:33
int GetLabelCountDB(char *filename)
Definition loadsave.cpp:617
int WriteMainDB(TransDB *db, const char *filename, CBabylonDlg *dlg)
Definition loadsave.cpp:212
#define CHUNK_SPEAKER
Definition loadsave.cpp:34
#define CHUNK_NAME
Definition loadsave.cpp:40
#define FORM_TRANS
Definition loadsave.cpp:31
#define CHUNK_WAVE_INFO
Definition loadsave.cpp:38
#define CHUNK_LISTENER
Definition loadsave.cpp:35
#define CHUNK_WAVE
Definition loadsave.cpp:37
#define FORM_BABYLONDB
Definition loadsave.cpp:28
#define FORM_TEXT
Definition loadsave.cpp:30
int num_labels
Definition loadsave.cpp:47
int next_id
Definition loadsave.cpp:48
Definition iff.h:50
int ChunkID
Definition iff.h:54
int FormID
Definition iff.h:53
int ChunkSize
Definition iff.h:56
int max_len
Definition loadsave.cpp:54
int revision
Definition loadsave.cpp:68
LangID lang
Definition loadsave.cpp:67
int id
Definition loadsave.cpp:60
int revision
Definition loadsave.cpp:61
DWORD lo
Definition loadsave.cpp:75
int valid
Definition loadsave.cpp:74
DWORD hi
Definition loadsave.cpp:76
#define label
Definition template.h:41