Difference between revisions of "Palette file"
From Worms Knowledge Base
(Corrected outdated spec link for palletes. Added info about mystery chunks.) |
m (Corrected BinaryReader variable name in load code) |
||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{ParentArticle|[[File formats]]}} | {{ParentArticle|[[File formats]]}} | ||
− | W:A | + | 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 == | |
− | {{ | + | 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 == | ||
+ | * [[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