Difference between revisions of "Palette file"
From Worms Knowledge Base
m (→Example code: static save method) |
m (Corrected BinaryReader variable name in load code) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{ParentArticle|[[File formats]]}} | {{ParentArticle|[[File formats]]}} | ||
− | W:A and WWP use the Microsoft [[w: | + | W:A and WWP use the Microsoft [[w:Resource_Interchange_File_Format|RIFF file format]] to store their color palettes used in the frontend. The palette files all reside in the "Graphics" directory and its subfolders. |
== File format == | == File format == | ||
Line 9: | Line 9: | ||
* 4-byte PAL signature "PAL " (note the space / 0x20 at the end) | * 4-byte PAL signature "PAL " (note the space / 0x20 at the end) | ||
− | The PAL files then include 4 different chunks, of which only the "data" chunk is important. The | + | The PAL files then include 4 different chunks, of which only the "data" chunk is important. The other chunks "offl", "tran" and "unde" are all 32 bytes long, filled with 0x00. Their purpose remains unknown since they can be deleted and the game still accepts the PAL files. |
Like other RIFF chunks, the data chunk starts with its signature and length: | Like other RIFF chunks, the data chunk starts with its signature and length: | ||
* 4-byte data chunk signature "data" | * 4-byte data chunk signature "data" | ||
Line 26: | Line 26: | ||
The following C# example code can be used to load PAL files: | The following C# example code can be used to load PAL files: | ||
− | public static | + | public static List<Color> LoadPal(string filename) |
{ | { | ||
List<Color> colors = new List<Color>(); | List<Color> colors = new List<Color>(); | ||
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); | FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); | ||
− | using (BinaryReader | + | using (BinaryReader br = new BinaryReader(stream)) |
{ | { | ||
− | // RIFF | + | // RIFF header |
string riff = ReadByteString(br, 4); // "RIFF" | string riff = ReadByteString(br, 4); // "RIFF" | ||
− | int dataSize = | + | int dataSize = br.ReadInt32(); |
string type = ReadByteString(br, 4); // "PAL " | string type = ReadByteString(br, 4); // "PAL " | ||
− | // Data | + | // Data chunk |
string chunkType = ReadByteString(br, 4); // "data" | string chunkType = ReadByteString(br, 4); // "data" | ||
− | int chunkSize = | + | int chunkSize = br.ReadInt32(); |
− | short palVersion = | + | short palVersion = br.ReadInt16(); // always 0x0300 |
− | short palEntries = | + | short palEntries = br.ReadInt16(); |
// Colors | // Colors | ||
for (int i = 0; i < palEntries; i++) | for (int i = 0; i < palEntries; i++) | ||
{ | { | ||
− | byte red = | + | byte red = br.ReadByte(); |
− | byte green = | + | byte green = br.ReadByte(); |
− | byte blue = | + | byte blue = br.ReadByte(); |
− | byte flags = | + | byte flags = br.ReadByte(); // always 0x00 |
colors.Add(Color.FromArgb(red, green, blue)); | colors.Add(Color.FromArgb(red, green, blue)); | ||
} | } | ||
} | } | ||
+ | return colors; | ||
} | } | ||
Line 70: | Line 71: | ||
using (BinaryWriter bw = new BinaryWriter(stream)) | using (BinaryWriter bw = new BinaryWriter(stream)) | ||
{ | { | ||
− | // RIFF | + | // RIFF header |
WriteStringBytes(bw, "RIFF"); | WriteStringBytes(bw, "RIFF"); | ||
bw.Write(length); | bw.Write(length); | ||
WriteStringBytes(bw, "PAL "); | WriteStringBytes(bw, "PAL "); | ||
− | // Data | + | // Data chunk |
WriteStringBytes(bw, "data"); | WriteStringBytes(bw, "data"); | ||
bw.Write(colors.Count * 4 + 4); | bw.Write(colors.Count * 4 + 4); | ||
Line 81: | Line 82: | ||
bw.Write((short)colors.Count); | bw.Write((short)colors.Count); | ||
+ | // Colors | ||
foreach (Color color in colors) | foreach (Color color in colors) | ||
{ | { | ||
Line 100: | Line 102: | ||
== External links == | == External links == | ||
− | * [http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..\html\book\Toolkt40\MMREF3.INF+2264 RIFF file format description] | + | * [[w:Resource_Interchange_File_Format|RIFF File Format]] on Wikipedia |
+ | * [http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..\html\book\Toolkt40\MMREF3.INF+2264 RIFF PAL file format description] |
Latest revision as of 11:19, 10 August 2012
W:A and WWP use the Microsoft RIFF file format to store their color palettes used in the frontend. The palette files all reside in the "Graphics" directory and its subfolders.
File format
As like every other RIFF file, the PAL files start off with the RIFF header:
- 4-byte RIFF signature "RIFF"
- 4-byte file length in bytes (excluding the RIFF header)
- 4-byte PAL signature "PAL " (note the space / 0x20 at the end)
The PAL files then include 4 different chunks, of which only the "data" chunk is important. The other chunks "offl", "tran" and "unde" are all 32 bytes long, filled with 0x00. Their purpose remains unknown since they can be deleted and the game still accepts the PAL files. Like other RIFF chunks, the data chunk starts with its signature and length:
- 4-byte data chunk signature "data"
- 4-byte data chunk size excluding the chunk header
- 2-byte PAL version. This version is always 0x0300.
- 2-byte color entry count. This determines how many colors are following.
Each color consists of 4 bytes holding the following data:
- 1-byte red amount of color
- 1-byte green amount of color
- 1-byte blue amount of color
- 1-byte "flags" - W:A PAL files always have the 0x00 flag, so no flag is set.
Example code
The following C# example code can be used to load PAL files:
public static List<Color> LoadPal(string filename) { List<Color> colors = new List<Color>(); FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); using (BinaryReader br = new BinaryReader(stream)) { // RIFF header string riff = ReadByteString(br, 4); // "RIFF" int dataSize = br.ReadInt32(); string type = ReadByteString(br, 4); // "PAL " // Data chunk string chunkType = ReadByteString(br, 4); // "data" int chunkSize = br.ReadInt32(); short palVersion = br.ReadInt16(); // always 0x0300 short palEntries = br.ReadInt16(); // Colors for (int i = 0; i < palEntries; i++) { byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte(); byte flags = br.ReadByte(); // always 0x00 colors.Add(Color.FromArgb(red, green, blue)); } } return colors; } private static string ReadByteString(BinaryReader br, int length) { return ASCIIEncoding.GetString(br.ReadBytes(length)); }
This C# example code can be used to save PAL files:
public static void SavePal(string filename, List<Color> colors) { // Calculate file length int length = 4 + 4 + 4 + 4 + 2 + 2 + colors.Count * 4; FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); using (BinaryWriter bw = new BinaryWriter(stream)) { // RIFF header WriteStringBytes(bw, "RIFF"); bw.Write(length); WriteStringBytes(bw, "PAL "); // Data chunk WriteStringBytes(bw, "data"); bw.Write(colors.Count * 4 + 4); bw.Write(0x0300); // PAL version bw.Write((short)colors.Count); // Colors foreach (Color color in colors) { bw.Write((byte)color.R); bw.Write((byte)color.G); bw.Write((byte)color.B); bw.Write((byte)0); // Flag in W:A always 0x00 } } } private static void WriteStringBytes(BinaryWriter bw, string value) { bw.Write(ASCIIEncoding.GetBytes(value)); }
See also
- Worms PAL Editor - does not save the 3 useless chunks, with no side-effect in the game
External links
- RIFF File Format on Wikipedia
- RIFF PAL file format description