https://modenc.renegadeprojects.com/api.php?action=feedcontributions&user=84.204.126.170&feedformat=atomModEnc - User contributions [en]2024-03-29T10:32:18ZUser contributionsMediaWiki 1.30.0https://modenc.renegadeprojects.com/index.php?title=CSF_File_Format&diff=13337CSF File Format2007-06-04T20:16:50Z<p>84.204.126.170: corrected by VK(tm)</p>
<hr />
<div>CSF files hold stringtables for RA2/YR (also for Generals/ZH and probably others).<br><br />
For more information about what a CSF file is, go to the [[CSF|CSF page]].<br />
<br />
On this page you will find a guide to how the format is built up.<br />
<br />
==The Header==<br />
The header of a CSF file is 0x18 bytes long.<br><br />
It is built up like this:<br />
<br />
{| cellspacing="2" cellpadding="4" style="border-collapse: collapse; border: 1px solid #000000;background:#F0F0F0;"<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Offset<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Type<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-left: 1px solid #000000;border-right: 1px solid #000000;"|Description<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x0<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|char[4]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''" FSC"'''<br>CSF header identifier<br>If this is not " FSC", the game will not load the file.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x4<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|<br />
'''CSF Version'''<br>The version number of the CSF format.<br>RA2, YR, Generals, ZH and the BFME series use version 3.<br>Nox uses version 2.<br>Nothing is known about the actual difference between the versions.<br><br />
Thanks to Siberian GRemlin for providing this information ([http://www.ppmsite.com/forum/viewtopic.php?p=130667#130667 see here])!<br />
|-<br />
!bgcolor="#e5e5e5" style="border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x8<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|<br />
'''NumLabels'''<br>The total amount of labels in the stringtable.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-right: 1px solid #000000;border-top: 1px solid #000000;"|0xC<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|<br />
'''NumExtraValues'''<br>The total amount of extra values in the stringtable.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x10<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|<br />
'''(nothing)'''<br>This is not read or used by the game, which means it is useless.<br>If you want, you can store an extra information tag there, if your program could use one (assuming you want to write a program that reads CSF files).<br />
|-<br />
!bgcolor="#e5e5e5" style="border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x14<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|<br />
'''Language'''<br>The language value for this stringtable.<br>See below for a list<br />
|}<br />
<br />
<br />
===Language===<br />
The language DWORD can have the following values (others will be recognized as "Unknown"):<br />
0 = US (English)*<br />
1 = UK (English)<br />
2 = German*<br />
3 = French*<br />
4 = Spanish<br />
5 = Italian<br />
6 = Japanese<br />
7 = Jabberwockie<br />
8 = Korean*<br />
9 = Chinese*<br />
>9 = Unknown<br />
&#42; RA2/YR has been released in this language.<br />
<br />
==Labels==<br />
<br />
[[Category:File Formats]]<br />
After the header, the label data follows.<br />
<br />
A label can be considered an entry in the stringtable (e.g. "GUI:OK" is a label).<br><br />
Each label can have a '''name''' (e.g. "NAME:MTNK"), a '''value''' (e.g. "Grizzly Tank") and an '''extra value''' (no example in the original ra2.csf/ra2md.csf).<br><br />
While the name and the extra value are ASCII strings, the value is a Unicode string (in order to support Korean, Chinese, etc).<br />
<br />
Now let's come to how the data is stored in the CSF file:<br />
<br />
===Label header===<br />
The label data begins with a label header, which is built up like this:<br />
{| cellspacing="2" cellpadding="4" style="border-collapse: collapse; border: 1px solid #000000;background:#F0F0F0;"<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Offset<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Type<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-left: 1px solid #000000;border-right: 1px solid #000000;"|Description<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x0<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|char[4]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''" LBL"'''<br>Label identifier<br>If this is not " LBL", the game will not recognize the following data as label data and read the next 4 bytes.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x4<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''Number of sub-strings'''<br>This is the number of sub-strings.Usual value is 1<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x8<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''LabelNameLength'''<br>This value holds the size of the label name that follows.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0xC<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|char[LabelNameLength]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''LabelName'''<br>A '''non'''-zero-terminated string that is as long as the DWORD at 0x8 says. If it is longer, the rest will be cut off.<br />
|}<br />
The first label in ra2md.csf can be found at 0x18.<br>'''Note:''' Spaces, tabs and line breaks will be formatted out of the label's name, therefore they cannot be used.<br />
<br />
===Values===<br />
Directly after the label header, the value data follows.<br><br />
This is how it is built up:<br />
{| cellspacing="2" cellpadding="4" style="border-collapse: collapse; border: 1px solid #000000;background:#F0F0F0;"<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Offset<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;"|Type<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-left: 1px solid #000000;border-right: 1px solid #000000;"|Description<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x0<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|char[4]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''" RTS''' or '''"WRTS"'''<br>Identifier<br>" RTS" means that there is '''no''' extra value for this label.<br><br />
"WRTS" means that after the value data, data for the extra value follows (see below).<br><br />
Everything else is invalid.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x4<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''ValueLength'''<br>This holds the length of the Unicode string (the value) that follows.<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x8<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|byte[ValueLength*2]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''Value'''<br>This holds the '''encoded''' value of the label.<br>Note that this is ValueLength*2 bytes long, because the value is a Unicode string, i.e. every character is a word instead of a byte.<br><br />
To decode the value to a Unicode string, '''not''' every byte of the value data (or substract it from 0xFF, see below for an example).<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x8+ValueLength*2<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|DWORD<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''ExtraValueLength'''<br>This holds the length of the extra value string that follow.<br><br />
This only applies if the identifier is "WRTS" and not " RTS".<br />
|-<br />
!bgcolor="#e5e5e5" style="border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-top: 1px solid #000000;"|0x8+ValueLength*2+0x4<br />
|style="border-left: 1px solid #aaaaaa;border-right: 1px solid #aaaaaa;border-top: 1px solid #aaaaaa;"|char[ExtraValueLength]<br />
|style="border: 1px solid #aaaaaa;"|<br />
'''ExtraValue'''<br>Like the label name, a non-zero-terminated string that is as long as ExtraValueLength says. If it is longer, the rest will be cut off.<br />
|}<br />
====Decoding the value====<br />
To decode the value to a Unicode string, '''not''' every byte of the value data (or substract it from 0xFF).<br><br />
An example in C++:<br />
int ValueDataLength = ValueLength << 1<br />
for(int i = 0; i < ValueDataLen;i++)<br />
{<br />
ValueData[i]=~ValueData[i]<br />
}</div>84.204.126.170