Difference between revisions of "Palette file"
From Worms Knowledge Base
m (→Example code: static save method) |
m (→Example code: commentary optimizations) |
||
Line 32: | Line 32: | ||
using (BinaryReader reader = new BinaryReader(stream)) | using (BinaryReader reader = new BinaryReader(stream)) | ||
{ | { | ||
− | // RIFF | + | // RIFF header |
string riff = ReadByteString(br, 4); // "RIFF" | string riff = ReadByteString(br, 4); // "RIFF" | ||
int dataSize = reader.ReadInt32(); | int dataSize = reader.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 = reader.ReadInt32(); | int chunkSize = reader.ReadInt32(); | ||
Line 70: | Line 70: | ||
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 81: | ||
bw.Write((short)colors.Count); | bw.Write((short)colors.Count); | ||
+ | // Colors | ||
foreach (Color color in colors) | foreach (Color color in colors) | ||
{ | { |
Revision as of 11:23, 5 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 purpose of 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 void LoadPal(string filename) { List<Color> colors = new List<Color>(); FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); using (BinaryReader reader = new BinaryReader(stream)) { // RIFF header string riff = ReadByteString(br, 4); // "RIFF" int dataSize = reader.ReadInt32(); string type = ReadByteString(br, 4); // "PAL " // Data chunk string chunkType = ReadByteString(br, 4); // "data" int chunkSize = reader.ReadInt32(); short palVersion = reader.ReadInt16(); // always 0x0300 short palEntries = reader.ReadInt16(); // Colors for (int i = 0; i < palEntries; i++) { byte red = reader.ReadByte(); byte green = reader.ReadByte(); byte blue = reader.ReadByte(); byte flags = reader.ReadByte(); // always 0x00 colors.Add(Color.FromArgb(red, green, blue)); } } } 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