source: doc/ccfiles4.txt

Last change on this file was 5, checked in by chronos, 8 years ago
  • Added: Various data format descriptions.
File size: 21.0 KB
Line 
1
2 COMMAND & CONQUER FILE FORMATS
3
4Revision 4
5
6by Vladan Bato (bat22@geocities.com)
7
8This document explains the file formats used by Command & Conquer.
9
10Command & Conquer is a tradmark of Westwood Studios, Inc.
11Command & Conquer is Copyright (C)1995 Westwood Studios, Inc.
12
13The information provided here is meant for programmers that want to make
14editor and utilites for Command & Conquer. My explanation might not be
15the best one, but it should be enough.
16
17I can't guarantee that the information in here is correct. If you find any
18errors, please report them to me.
19
20In this document I'll use Pascal notation, and any code samples will be in
21Pascal....
22I wanted to rewrite them in C, but I don't have the time to test the code.
23So, to avoid any risks, I'll use the code from Mix Manager.
24
25In case you don't know, the information contained here has been used to
26make the program Mix Manager, which contains a lot of conversion utilities
27for the various formats. For more info, check my homepage (see the end of the
28document).
29
30===================
31 1. THE .MIX FILES
32===================
33
34You probably already know the format of these files, but I will add a
35description here for completeness.
36
37The MIX file consists of two parts :
38-A header including the index of all the files contained within
39-A body containing all the files
40
41It's format is :
42
43 Header : record
44 NumFiles : word; {Number of files in MIX}
45 DataSize : longint; {Size of body}
46 Index : array [1..NumFiles] of
47 record
48 ID : longint; {File ID}
49 Start : longint; {Offset of file from the start of the body}
50 Size : longint; {file size}
51 end;
52 end;
53
54The ID field is computed from the original filename, which is not stored in
55the MIX.
56The records are always sorted by the ID field (the numbers are signed
57longints).
58Note that the offsets are relative to the start of the body so to find the
59actual offset in the MIX you have to add the size of the header which is
60NumFiles*12+6
61
62===================
63 2. THE .PAL FILES
64===================
65
66The most easiest files....
67These files contain the palette in the same format used by VGA cards.
68
69 Palette : array [0..255] of record
70 red,green,blue:byte;
71 end;
72
73Note that only the first 6 bits of each number are used, giving a total of
74262144 possible colors (as opposed to the 8 bits used by .PCX files for
75example).
76
77=================================
78 3. THE TEMPLATE AND .BIN FILES
79=================================
80
81The Template files contain the map graphics, and can be found in the
82theater specific MIX files (TEMPERAT.MIX, WINTER.MIX, DESERT.MIX).
83The .BIN files contain the maps for the missions and are used in conjunction
84with the .INI files.
85
86I won't explain them here. They are explained with great detail in the
87document titled "Command & Conquer maps" I wrote some time ago.
88The said document can be found on my homepage.
89
90===================
91 5. THE .SHP FILES
92===================
93
94The .SHP files contain almost all the graphics : units, structures, trees,...
95The header has the following structure :
96
97 Header : record
98 NumImages : word; {Number of images}
99 A,B : word; {Unknown}
100 Width,
101 Height : word; {Width and Height of the images}
102 C : longint; {Unknown}
103 end;
104
105If you know something about those unknown fields, please e-mail me.
106Following that there's an array of records, one for each image :
107
108 Offsets : array [0..NumImages+1] of
109 record
110 Offset : longint; {Offset and format of image in file}
111 RefOffs : longint; {Offset and format of image on
112 which it is based}
113 end;
114
115The most significant byte (last) of the Offset and RefOffs fields
116contains the format, while the lower three are used for the offset.
117The format byte can have one of the three values : 80h, 40h, 20h.
118I will call the three image formats Format80, Format40 and Format20.
119
120The Format80 images are compressed with a compression method I'll explain
121later.
122
123The Format40 images must be xor-ed with a Format80 image. That's what the
124RefOffs field is used for. It tells which Format80 image they are
125based upon. The Format40 will be explained in detail later.
126
127The Format20 images use the same format as the Format40, the difference is
128that they are xor-ed with the image that precedes them in the file. That can
129be either in Format20 or in Format40.
130The offset part of the RefOffs field contains the number of the first
131Format40 image in the chain, and the format field is always 48h.
132
133Here's an example :
134
1350) Off0(three bytes) 80h 000000h 00h
1361) Off1(three bytes) 80h 000000h 00h
1372) Off2(three bytes) 40h Off1 80h
1383) Off3(three bytes) 80h 000000h 00h
1394) Off4(three bytes) 40h Off1 80h
1405) Off5(three bytes) 20h 000400h 48h
1416) Off6(three bytes) 20h 000400h 48h
1427) Off7(three bytes) 40h Off3 80h
143
144For example to draw image 7, you have to draw the image 3 first (whose offset
145and format are given) and then xor image 7 over it.
146
147To draw image 6, you have to xor it over the previous image, i.e. 5, which
148is format20 again, that means that it has to be xor-ed over image 4, which
149is in format40, i.e. it must be xor-ed over the image in format80 it has a
150reference to. In this case it's image 1. Thus the chain is 1,4,5,6.
151This is one way to see it, the other could be :
152Image 6 is in Format20, the RefOffs field contains the number of the first
153Format40 image in the chain, in this case image 4. To draw Image 4, the
154Image 1 has to be drawn first, next is image 4, and then all the images
155from the 4th to the 6th have to be xor-ed over the previous.
156
157I made some experiments and found out that you don't have to use the
158Format40 and Format20 images. I tried converting all of them into Format80
159and it worked.
160
161Also, when changing graphics, note that all the unit and structure graphics
162should be drawn using the GDI colors, which will be automatically converted
163for the other sides.
164The palette you should use is one of those found in DESERT.MIX, WINTER.MIX
165and TEMPERAT.MIX. The GDI colors are colors 0B0h-0BFh. The other colors
166won't be converted and will remain the same for all the sides (be sure to
167use only the colors that are the same all three palettes).
168
169The above applies only to the graphics that appear in all three theaters
170(the .SHP file found in CONQUER.MIX). The graphics for the structures and
171overlays that appear in a single theater (found inside the theater specific
172MIX) can use the palette entries that are unique for that theater (and will
173be shown with garbled colors in the others).
174
175Also a special color is used for shadows. It's color 04h. In the palettes
176it's bright green, but C&C puts a shadow instead of it. I don't know how
177the shadows are calculated however.
178
179You should've noticed that the array has NumImages+2 elements when only
180NumImages elements are needed. The last one contains zeros, and the one before
181that points to the end of the file. These two can be used to identify the file
182as a .SHP.
183
184Here's the description of the compression formats : Format80 and Format40.
185
186----------
187 Format80
188----------
189
190There are several different commands, with different sizes : form 1 to 5
191bytes.
192The positions mentioned below always refer to the destination buffer (i.e.
193the uncompressed image). The relative positions are relative to the current
194position in the destination buffer, which is one byte beyond the last written
195byte.
196
197I will give some sample code at the end.
198
199(1) 1 byte
200 +---+---+---+---+---+---+---+---+
201 | 1 | 0 | | | | | | |
202 +---+---+---+---+---+---+---+---+
203 \_______________________/
204 |
205 Count
206
207 This one means : copy next Count bytes as is from Source to Dest.
208
209(2) 2 bytes
210 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
211 | 0 | | | | | | | | | | | | | | | | |
212 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
213 \___________/\__________________________________________________/
214 | |
215 Count-3 Relative Pos.
216
217 This means copy Count bytes from Dest at Current Pos.-Rel. Pos. to
218 Current position.
219 Note that you have to add 3 to the number you find in the bits 4-6 of the
220 first byte to obtain the Count.
221 Note that if the Rel. Pos. is 1, that means repeat Count times the previous
222 byte.
223
224(3) 3 bytes
225 +---+---+---+---+---+---+---+---+ +---------------+---------------+
226 | 1 | 1 | | | | | | | | | |
227 +---+---+---+---+---+---+---+---+ +---------------+---------------+
228 \_______________________/ Pos
229 |
230 Count-3
231
232 Copy Count bytes from Pos, where Pos is absolute from the start of the
233 destination buffer. (Pos is a word, that means that the images can't be
234 larger than 64K)
235
236(4) 4 bytes
237 +---+---+---+---+---+---+---+---+ +-------+-------+ +-------+
238 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | | | | |
239 +---+---+---+---+---+---+---+---+ +-------+-------+ +-------+
240 Count Color
241
242 Write Color Count times.
243 (Count is a word, color is a byte)
244
245(5) 5 bytes
246 +---+---+---+---+---+---+---+---+ +-------+-------+ +-------+-------+
247 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | | | | | | |
248 +---+---+---+---+---+---+---+---+ +-------+-------+ +-------+-------+
249 Count Pos
250
251 Copy Count bytes from Dest. starting at Pos. Pos is absolute from the start
252 of the Destination buffer.
253 Both Count and Pos are words.
254
255These are all the commands I found out. Maybe there are other ones, but I
256haven't seen them yet.
257
258All the images end with a 80h command.
259
260To make things more clearer here's a piece of code that will uncompress the
261image.
262
263 DP = destination pointer
264 SP = source pointer
265 Source and Dest are the two buffers
266
267
268 SP:=0;
269 DP:=0;
270 repeat
271 Com:=Source[SP];
272 inc(SP);
273 b7:=Com shr 7; {b7 is bit 7 of Com}
274 case b7 of
275 0 : begin {copy command (2)}
276 {Count is bits 4-6 + 3}
277 Count:=(Com and $7F) shr 4 + 3;
278 {Position is bits 0-3, with bits 0-7 of next byte}
279 Posit:=(Com and $0F) shl 8+Source[SP];
280 Inc(SP);
281 {Starting pos=Cur pos. - calculated value}
282 Posit:=DP-Posit;
283 for i:=Posit to Posit+Count-1 do
284 begin
285 Dest[DP]:=Dest[i];
286 Inc(DP);
287 end;
288 end;
289 1 : begin
290 {Check bit 6 of Com}
291 b6:=(Com and $40) shr 6;
292 case b6 of
293 0 : begin {Copy as is command (1)}
294 Count:=Com and $3F; {mask 2 topmost bits}
295 if Count=0 then break; {EOF marker}
296 for i:=1 to Count do
297 begin
298 Dest[DP]:=Source[SP];
299 Inc(DP);
300 Inc(SP);
301 end;
302 end;
303 1 : begin {large copy, very large copy and fill commands}
304 {Count = (bits 0-5 of Com) +3}
305 {if Com=FEh then fill, if Com=FFh then very large copy}
306 Count:=Com and $3F;
307 if Count<$3E then {large copy (3)}
308 begin
309 Inc(Count,3);
310 {Next word = pos. from start of image}
311 Posit:=Word(Source[SP]);
312 Inc(SP,2);
313 for i:=Posit to Posit+Count-1 do
314 begin
315 Dest[DP]:=Dest[i];
316 Inc(DP);
317 end;
318 end
319 else if Count=$3F then {very large copy (5)}
320 begin
321 {next 2 words are Count and Pos}
322 Count:=Word(Source[SP]);
323 Posit:=Word(Source[SP+2]);
324 Inc(SP,4);
325 for i:=Posit to Posit+Count-1 do
326 begin
327 Dest[DP]:=Dest[i];
328 Inc(DP);
329 end;
330 end else
331 begin {Count=$3E, fill (4)}
332 {Next word is count, the byte after is color}
333 Count:=Word(Source[SP]);
334 Inc(SP,2);
335 b:=Source[SP];
336 Inc(SP);
337 for i:=0 to Count-1 do
338 begin
339 Dest[DP]:=b;
340 inc(DP);
341 end;
342 end;
343 end;
344 end;
345 end;
346 end;
347 until false;
348
349Note that you won't be able to compile this code, because the typecasting
350won't work. (But I'm sure you'll be able to fix it).
351
352
353----------
354 Format40
355----------
356
357As I said before the images in Format40 must be xor-ed over a previous image,
358or against a black screen (as in the .WSA format).
359It is used when there are only minor changes between an image and a following
360one.
361
362Here I'll assume that the old image is in Dest, and that the Dest pointer is
363set to the beginning of that buffer.
364
365As for the Format80, there are many commands :
366
367
368(1) 1 byte
369 byte
370 +---+---+---+---+---+---+---+---+
371 | 1 | | | | | | | |
372 +---+---+---+---+---+---+---+---+
373 \___________________________/
374 |
375 Count
376
377 Skip count bytes in Dest (move the pointer forward).
378
379(2) 3 bytes
380 byte word
381 +---+---+---+---+---+---+---+---+ +---+-----+-------+
382 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | ... | |
383 +---+---+---+---+---+---+---+---+ +---+-----+-------+
384 \_____________/
385 |
386 Count
387
388 Skip count bytes.
389
390(3) 3 bytes
391 byte word
392 +---+---+---+---+---+---+---+---+ +---+---+-----+-------+
393 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 0 | ... | |
394 +---+---+---+---+---+---+---+---+ +---+---+-----+-------+
395 \_____________/
396 |
397 Count
398
399 Xor next count bytes. That means xor count bytes from Source with bytes
400 in Dest.
401
402(4) 4 bytes
403 byte word byte
404 +---+---+---+---+---+---+---+---+ +---+---+-----+-------+ +-------+
405 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | ... | | | |
406 +---+---+---+---+---+---+---+---+ +---+---+-----+-------+ +-------+
407 \_____________/ value
408 |
409 Count
410
411 Xor next count bytes in Dest with value.
412
4135) 1 byte
414 byte
415 +---+---+---+---+---+---+---+---+
416 | 0 | | | | | | | |
417 +---+---+---+---+---+---+---+---+
418 \___________________________/
419 |
420 Count
421
422 Xor next count bytes from source with dest.
423
4246) 3 bytes
425 byte byte byte
426 +---+---+---+---+---+---+---+---+ +-------+ +-------+
427 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | |
428 +---+---+---+---+---+---+---+---+ +-------+ +-------+
429 Count Value
430
431 Xor next count bytes with value.
432
433
434All images end with a 80h 00h 00h command.
435
436I think these are all the commands, but there might be some other.
437If you find anything new, please e-mail me.
438
439As before here's some code :
440
441 DP = destination pointer
442 SP = source pointer
443 Source is buffer containing the Format40 data
444 Dest is the buffer containing the image over which the second has
445 to be xor-ed
446
447
448 SP:=0;
449 DP:=0;
450 repeat
451 Com:=Source[SP];
452 Inc(SP);
453
454 if (Com and $80)<>0 then {if bit 7 set}
455 begin
456 if Com<>$80 then {small skip command (1)}
457 begin
458 Count:=Com and $7F;
459 Inc(DP,Count);
460 end
461 else {Big commands}
462 begin
463 Count:=Word(Source[SP]);
464 if Count=0 then break;
465 Inc(SP,2);
466
467 Tc:=(Count and $C000) shr 14; {Tc=two topmost bits of count}
468
469 case Tc of
470 0,1 : begin {Big skip (2)}
471 Inc(DP,Count);
472 end;
473 2 : begin {big xor (3)}
474 Count:=Count and $3FFF;
475 for i:=1 to Count do
476 begin
477 Dest[DP]:=Dest[DP] xor Source[SP];
478 Inc(DP);
479 Inc(SP);
480 end;
481 end;
482 3 : begin {big repeated xor (4)}
483 Count:=Count and $3FFF;
484 b:=Source[SP];
485 Inc(SP);
486 for i:=1 to Count do
487 begin
488 Dest[DP]:=Dest[DP] xor b;
489 Inc(DP);
490 end;
491 end;
492 end;
493 end;
494 end else {xor command}
495 begin
496 Count:=Com;
497 if Count=0 then
498 begin {repeated xor (6)}
499 Count:=Source[SP];
500 Inc(SP);
501 b:=Source[SP];
502 Inc(SP);
503 for i:=1 to Count do
504 begin
505 Dest[DP]:=Dest[DP] xor b;
506 Inc(DP);
507 end;
508 end else {copy xor (5)}
509 for i:=1 to Count do
510 begin
511 Dest[DP]:=Dest[DP] xor Source[SP];
512 Inc(DP);
513 Inc(SP);
514 end;
515 end;
516 until false;
517
518
519
520===================
521 6. THE .CPS FILES
522===================
523
524The .CPS files contain 320x200x256 images. The images are compressed with the
525Format80 compression method. They may or may not contain a palette.
526
527The header has the following structure :
528
529 Header : record
530 Size : word; {File size - 2}
531 Unknown : word; {Always 0004h}
532 ImSize : word; {Size of uncompressed image (always 0FA00h)}
533 Palette : longint; {Is there a palette ?}
534 end;
535
536If Palette is 03000000h then there's a palette after the header, otherwise
537the image follows.
538CPS file without palette can be found in the SETUP.MIX file, and they all use
539the Palette that can be found inside the same .MIX.
540
541The image that follows the palette (or the Header) is in Format80 which is
542explained above.
543
544===================
545 7. THE .WSA FILES
546===================
547
548
549WSA files contain short animations and can be found in the GENERAL.MIX files.
550They are basically a series of Format40 images, that are then compressed with
551Format80.
552
553The header is :
554
555 Header : record
556 NumFrames : word; {Number of frames}
557 X,Y : word; {Position on screen of the upper left corner}
558 W,H : word; {Width and height of the images}
559 Delta : longint; {Frames/Sec = Delta/(2^10)}
560 end;
561
562Following that there's an array of offsets :
563
564 Offsets : array [0..NumFrames+1] of longint;
565
566The obtain the actual offset, you have to add 300h. That is the size of the
567palette that follows the Offsets array.
568As for .SHP files the two last offsets have a special meaning.
569If the last offset is 0 then the one before it points to the end of file
570(after you added 300h of course).
571If the last one is <>0 then it points to the end of the file, and the
572one before it points to a special frame that gives you the difference between
573the last and the first frame. This is used when you have to loop the
574animation.
575
576As I said before, the images are in Format40 but are then compressed with
577Format80. That means that you first have to uncompress the Format80 and then
578decode the Format40 image you obtain.
579The first frame should be xor-ed over a black image (filled with zeros), all
580the other are xor-ed over the previous one.
581
582There is a variant of the file without the palette that can be found in
583SETUP.MIX but I wasn't able to decode it (maybe there are some commands I
584don't know about)...
585
586=====================
587 8. ADDITIONAL NOTES
588=====================
589
590The VQA files (that contain movies) have been decoded by Aaron Glover
591(arn@ibm.net), and are explained in a document he wrote up.
592You can find the document on my homepage (or ask him directly).
593
594What is still missing are the .AUD files.
595It seems that the AUD files use some kind of lossy sound compression,
596which means that it is almost impossible to decode them.
597However if someone manages to work them out, I'd really appreciate some
598info.
599
600I know my explanations are not very good, but you'll have to bear them,
601unless someone else wants to rewrite this.
602
603============
604 9. CREDITS
605============
606
607I wish to thank the following people :
608
609-Andrew Griffin (buggy@adam.com.au) for starting it all.
610-Aaron Glover (arn@ibm.net) and
611 Denis Moeller (d.moeller@rendsburg.netsurf.de) for their work on .SHP files.
612-Aaron Glover for decoding the VQA files.
613-Carl Kenner (andrew.kenner@unisa.edu.au) for the info on .CPS files.
614
615
616Vladan Bato (bat22@geocities.com)
617http://www.geocities.com/SiliconValley/8682
618
Note: See TracBrowser for help on using the repository browser.