1 |
|
---|
2 | COMMAND & CONQUER FILE FORMATS
|
---|
3 |
|
---|
4 | Revision 4
|
---|
5 |
|
---|
6 | by Vladan Bato (bat22@geocities.com)
|
---|
7 |
|
---|
8 | This document explains the file formats used by Command & Conquer.
|
---|
9 |
|
---|
10 | Command & Conquer is a tradmark of Westwood Studios, Inc.
|
---|
11 | Command & Conquer is Copyright (C)1995 Westwood Studios, Inc.
|
---|
12 |
|
---|
13 | The information provided here is meant for programmers that want to make
|
---|
14 | editor and utilites for Command & Conquer. My explanation might not be
|
---|
15 | the best one, but it should be enough.
|
---|
16 |
|
---|
17 | I can't guarantee that the information in here is correct. If you find any
|
---|
18 | errors, please report them to me.
|
---|
19 |
|
---|
20 | In this document I'll use Pascal notation, and any code samples will be in
|
---|
21 | Pascal....
|
---|
22 | I wanted to rewrite them in C, but I don't have the time to test the code.
|
---|
23 | So, to avoid any risks, I'll use the code from Mix Manager.
|
---|
24 |
|
---|
25 | In case you don't know, the information contained here has been used to
|
---|
26 | make the program Mix Manager, which contains a lot of conversion utilities
|
---|
27 | for the various formats. For more info, check my homepage (see the end of the
|
---|
28 | document).
|
---|
29 |
|
---|
30 | ===================
|
---|
31 | 1. THE .MIX FILES
|
---|
32 | ===================
|
---|
33 |
|
---|
34 | You probably already know the format of these files, but I will add a
|
---|
35 | description here for completeness.
|
---|
36 |
|
---|
37 | The 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 |
|
---|
41 | It'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 |
|
---|
54 | The ID field is computed from the original filename, which is not stored in
|
---|
55 | the MIX.
|
---|
56 | The records are always sorted by the ID field (the numbers are signed
|
---|
57 | longints).
|
---|
58 | Note that the offsets are relative to the start of the body so to find the
|
---|
59 | actual offset in the MIX you have to add the size of the header which is
|
---|
60 | NumFiles*12+6
|
---|
61 |
|
---|
62 | ===================
|
---|
63 | 2. THE .PAL FILES
|
---|
64 | ===================
|
---|
65 |
|
---|
66 | The most easiest files....
|
---|
67 | These 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 |
|
---|
73 | Note that only the first 6 bits of each number are used, giving a total of
|
---|
74 | 262144 possible colors (as opposed to the 8 bits used by .PCX files for
|
---|
75 | example).
|
---|
76 |
|
---|
77 | =================================
|
---|
78 | 3. THE TEMPLATE AND .BIN FILES
|
---|
79 | =================================
|
---|
80 |
|
---|
81 | The Template files contain the map graphics, and can be found in the
|
---|
82 | theater specific MIX files (TEMPERAT.MIX, WINTER.MIX, DESERT.MIX).
|
---|
83 | The .BIN files contain the maps for the missions and are used in conjunction
|
---|
84 | with the .INI files.
|
---|
85 |
|
---|
86 | I won't explain them here. They are explained with great detail in the
|
---|
87 | document titled "Command & Conquer maps" I wrote some time ago.
|
---|
88 | The said document can be found on my homepage.
|
---|
89 |
|
---|
90 | ===================
|
---|
91 | 5. THE .SHP FILES
|
---|
92 | ===================
|
---|
93 |
|
---|
94 | The .SHP files contain almost all the graphics : units, structures, trees,...
|
---|
95 | The 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 |
|
---|
105 | If you know something about those unknown fields, please e-mail me.
|
---|
106 | Following 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 |
|
---|
115 | The most significant byte (last) of the Offset and RefOffs fields
|
---|
116 | contains the format, while the lower three are used for the offset.
|
---|
117 | The format byte can have one of the three values : 80h, 40h, 20h.
|
---|
118 | I will call the three image formats Format80, Format40 and Format20.
|
---|
119 |
|
---|
120 | The Format80 images are compressed with a compression method I'll explain
|
---|
121 | later.
|
---|
122 |
|
---|
123 | The Format40 images must be xor-ed with a Format80 image. That's what the
|
---|
124 | RefOffs field is used for. It tells which Format80 image they are
|
---|
125 | based upon. The Format40 will be explained in detail later.
|
---|
126 |
|
---|
127 | The Format20 images use the same format as the Format40, the difference is
|
---|
128 | that they are xor-ed with the image that precedes them in the file. That can
|
---|
129 | be either in Format20 or in Format40.
|
---|
130 | The offset part of the RefOffs field contains the number of the first
|
---|
131 | Format40 image in the chain, and the format field is always 48h.
|
---|
132 |
|
---|
133 | Here's an example :
|
---|
134 |
|
---|
135 | 0) Off0(three bytes) 80h 000000h 00h
|
---|
136 | 1) Off1(three bytes) 80h 000000h 00h
|
---|
137 | 2) Off2(three bytes) 40h Off1 80h
|
---|
138 | 3) Off3(three bytes) 80h 000000h 00h
|
---|
139 | 4) Off4(three bytes) 40h Off1 80h
|
---|
140 | 5) Off5(three bytes) 20h 000400h 48h
|
---|
141 | 6) Off6(three bytes) 20h 000400h 48h
|
---|
142 | 7) Off7(three bytes) 40h Off3 80h
|
---|
143 |
|
---|
144 | For example to draw image 7, you have to draw the image 3 first (whose offset
|
---|
145 | and format are given) and then xor image 7 over it.
|
---|
146 |
|
---|
147 | To draw image 6, you have to xor it over the previous image, i.e. 5, which
|
---|
148 | is format20 again, that means that it has to be xor-ed over image 4, which
|
---|
149 | is in format40, i.e. it must be xor-ed over the image in format80 it has a
|
---|
150 | reference to. In this case it's image 1. Thus the chain is 1,4,5,6.
|
---|
151 | This is one way to see it, the other could be :
|
---|
152 | Image 6 is in Format20, the RefOffs field contains the number of the first
|
---|
153 | Format40 image in the chain, in this case image 4. To draw Image 4, the
|
---|
154 | Image 1 has to be drawn first, next is image 4, and then all the images
|
---|
155 | from the 4th to the 6th have to be xor-ed over the previous.
|
---|
156 |
|
---|
157 | I made some experiments and found out that you don't have to use the
|
---|
158 | Format40 and Format20 images. I tried converting all of them into Format80
|
---|
159 | and it worked.
|
---|
160 |
|
---|
161 | Also, when changing graphics, note that all the unit and structure graphics
|
---|
162 | should be drawn using the GDI colors, which will be automatically converted
|
---|
163 | for the other sides.
|
---|
164 | The palette you should use is one of those found in DESERT.MIX, WINTER.MIX
|
---|
165 | and TEMPERAT.MIX. The GDI colors are colors 0B0h-0BFh. The other colors
|
---|
166 | won't be converted and will remain the same for all the sides (be sure to
|
---|
167 | use only the colors that are the same all three palettes).
|
---|
168 |
|
---|
169 | The 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
|
---|
171 | overlays that appear in a single theater (found inside the theater specific
|
---|
172 | MIX) can use the palette entries that are unique for that theater (and will
|
---|
173 | be shown with garbled colors in the others).
|
---|
174 |
|
---|
175 | Also a special color is used for shadows. It's color 04h. In the palettes
|
---|
176 | it's bright green, but C&C puts a shadow instead of it. I don't know how
|
---|
177 | the shadows are calculated however.
|
---|
178 |
|
---|
179 | You should've noticed that the array has NumImages+2 elements when only
|
---|
180 | NumImages elements are needed. The last one contains zeros, and the one before
|
---|
181 | that points to the end of the file. These two can be used to identify the file
|
---|
182 | as a .SHP.
|
---|
183 |
|
---|
184 | Here's the description of the compression formats : Format80 and Format40.
|
---|
185 |
|
---|
186 | ----------
|
---|
187 | Format80
|
---|
188 | ----------
|
---|
189 |
|
---|
190 | There are several different commands, with different sizes : form 1 to 5
|
---|
191 | bytes.
|
---|
192 | The positions mentioned below always refer to the destination buffer (i.e.
|
---|
193 | the uncompressed image). The relative positions are relative to the current
|
---|
194 | position in the destination buffer, which is one byte beyond the last written
|
---|
195 | byte.
|
---|
196 |
|
---|
197 | I 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 |
|
---|
255 | These are all the commands I found out. Maybe there are other ones, but I
|
---|
256 | haven't seen them yet.
|
---|
257 |
|
---|
258 | All the images end with a 80h command.
|
---|
259 |
|
---|
260 | To make things more clearer here's a piece of code that will uncompress the
|
---|
261 | image.
|
---|
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 |
|
---|
349 | Note that you won't be able to compile this code, because the typecasting
|
---|
350 | won't work. (But I'm sure you'll be able to fix it).
|
---|
351 |
|
---|
352 |
|
---|
353 | ----------
|
---|
354 | Format40
|
---|
355 | ----------
|
---|
356 |
|
---|
357 | As I said before the images in Format40 must be xor-ed over a previous image,
|
---|
358 | or against a black screen (as in the .WSA format).
|
---|
359 | It is used when there are only minor changes between an image and a following
|
---|
360 | one.
|
---|
361 |
|
---|
362 | Here I'll assume that the old image is in Dest, and that the Dest pointer is
|
---|
363 | set to the beginning of that buffer.
|
---|
364 |
|
---|
365 | As 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 |
|
---|
413 | 5) 1 byte
|
---|
414 | byte
|
---|
415 | +---+---+---+---+---+---+---+---+
|
---|
416 | | 0 | | | | | | | |
|
---|
417 | +---+---+---+---+---+---+---+---+
|
---|
418 | \___________________________/
|
---|
419 | |
|
---|
420 | Count
|
---|
421 |
|
---|
422 | Xor next count bytes from source with dest.
|
---|
423 |
|
---|
424 | 6) 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 |
|
---|
434 | All images end with a 80h 00h 00h command.
|
---|
435 |
|
---|
436 | I think these are all the commands, but there might be some other.
|
---|
437 | If you find anything new, please e-mail me.
|
---|
438 |
|
---|
439 | As 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 |
|
---|
524 | The .CPS files contain 320x200x256 images. The images are compressed with the
|
---|
525 | Format80 compression method. They may or may not contain a palette.
|
---|
526 |
|
---|
527 | The 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 |
|
---|
536 | If Palette is 03000000h then there's a palette after the header, otherwise
|
---|
537 | the image follows.
|
---|
538 | CPS file without palette can be found in the SETUP.MIX file, and they all use
|
---|
539 | the Palette that can be found inside the same .MIX.
|
---|
540 |
|
---|
541 | The image that follows the palette (or the Header) is in Format80 which is
|
---|
542 | explained above.
|
---|
543 |
|
---|
544 | ===================
|
---|
545 | 7. THE .WSA FILES
|
---|
546 | ===================
|
---|
547 |
|
---|
548 |
|
---|
549 | WSA files contain short animations and can be found in the GENERAL.MIX files.
|
---|
550 | They are basically a series of Format40 images, that are then compressed with
|
---|
551 | Format80.
|
---|
552 |
|
---|
553 | The 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 |
|
---|
562 | Following that there's an array of offsets :
|
---|
563 |
|
---|
564 | Offsets : array [0..NumFrames+1] of longint;
|
---|
565 |
|
---|
566 | The obtain the actual offset, you have to add 300h. That is the size of the
|
---|
567 | palette that follows the Offsets array.
|
---|
568 | As for .SHP files the two last offsets have a special meaning.
|
---|
569 | If the last offset is 0 then the one before it points to the end of file
|
---|
570 | (after you added 300h of course).
|
---|
571 | If the last one is <>0 then it points to the end of the file, and the
|
---|
572 | one before it points to a special frame that gives you the difference between
|
---|
573 | the last and the first frame. This is used when you have to loop the
|
---|
574 | animation.
|
---|
575 |
|
---|
576 | As I said before, the images are in Format40 but are then compressed with
|
---|
577 | Format80. That means that you first have to uncompress the Format80 and then
|
---|
578 | decode the Format40 image you obtain.
|
---|
579 | The first frame should be xor-ed over a black image (filled with zeros), all
|
---|
580 | the other are xor-ed over the previous one.
|
---|
581 |
|
---|
582 | There is a variant of the file without the palette that can be found in
|
---|
583 | SETUP.MIX but I wasn't able to decode it (maybe there are some commands I
|
---|
584 | don't know about)...
|
---|
585 |
|
---|
586 | =====================
|
---|
587 | 8. ADDITIONAL NOTES
|
---|
588 | =====================
|
---|
589 |
|
---|
590 | The VQA files (that contain movies) have been decoded by Aaron Glover
|
---|
591 | (arn@ibm.net), and are explained in a document he wrote up.
|
---|
592 | You can find the document on my homepage (or ask him directly).
|
---|
593 |
|
---|
594 | What is still missing are the .AUD files.
|
---|
595 | It seems that the AUD files use some kind of lossy sound compression,
|
---|
596 | which means that it is almost impossible to decode them.
|
---|
597 | However if someone manages to work them out, I'd really appreciate some
|
---|
598 | info.
|
---|
599 |
|
---|
600 | I know my explanations are not very good, but you'll have to bear them,
|
---|
601 | unless someone else wants to rewrite this.
|
---|
602 |
|
---|
603 | ============
|
---|
604 | 9. CREDITS
|
---|
605 | ============
|
---|
606 |
|
---|
607 | I 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 |
|
---|
616 | Vladan Bato (bat22@geocities.com)
|
---|
617 | http://www.geocities.com/SiliconValley/8682
|
---|
618 |
|
---|