Nova Format

From ModdingWiki
Jump to navigation Jump to search
Nova Format
Nova Format.png
Format typeImage
HardwareVGA
Colour depth8-bit (VGA)
Minimum size (pixels)0×0
Maximum size (pixels)65535×65535
PaletteExternal
Plane count1
Transparent pixels?No
Hitmap pixels?No
Games

Nova is an image format used in the game Cover Girl Strip Poker. The images typically have extension .PPP, but not all files with that extension in the game folder are images; in fact, the extension seems to be used for all game files that are RLE-compressed.

The image files can easily be identified by the fact that each .PPP image has its own colour palette in an accompanying .PAL file of the same name.

The format is named after the fact all files start with the string "NOVA", which is most likely the signature of the game's lead programmer, Samuel Sebastian Nova.

File format

The entire file, including the header, is compressed with a flag-based RLE compression. The very first step to read the file should be to unpack it.

Compression

The compression used is a flag-based run-length encoding algorithm, with 4-byte repeat commands. Because of its size, repeating sequences that are less than 4 bytes long are not compressed.

The repeat commands have the following structure:

Data type Name Description
BYTE Flag Flag value 0xFF
BYTE Value Value to repeat
UINT16LE Repeat Amount of times to repeat Value

Header

Once unpacked, the file starts with the following header:

Offset Data type Name Description
0x00 UINT32LE Magic1 Magic number: the string "NOVA". As a single UInt32, the value is 0x41564F4E
0x04 UINT16LE Width Image width.
0x06 UINT16LE Height Image height.

Note that for identification purposes, since the "NOVA" string at the start contains no repetitions itself, a quick and accurate preliminary check before doing the full decompression process can be to see if the first three bytes are the string "NOV". The last byte can technically not be guaranteed, since the following width and height could be filled with enough 0x41 values (the letter "A") to trigger its conversion to a run-length command. Still, either the 4th byte should be 0x41, or, as a flag repeat command, the 4th and 5th byte should respectively be 0xFF and 0x41.

Image data

This header is followed by the image data, which is simple linear 8-bit VGA data, to be visualised using the colours from the 256-colour 6-bit VGA palette in the accompanying .PAL file.

Code

RLE Decompression

This code was written by Nyerguds for the Engie File Converter, and is released under the WTF Public License.

public static Byte[] DecompressPppRle(Byte[] data)
{
    Int32 len = data.Length;
    UInt32 expandSize = (UInt32)len * 3;
    Int32 uncompressedSize = data.Length * 3;
    Byte[] bufferOut = new Byte[uncompressedSize];
    Int32 ptr = 0;
    // Decompress flag-based RLE.
    // The flag is 0xFF. It is followed by one byte for the value to fill,
    // and then two bytes for the amount of repetitions.
    Int32 i;
    for (i = 0; i < len; i++)
    {
        Byte value = data[i];
        if (value != 0xFF)
        {
            if (ptr >= bufferOut.Length)
                bufferOut = ExpandBuffer(bufferOut, expandSize);
            bufferOut[ptr++] = value;
        }
        else
        {
            if (i + 3 >= len)
                throw new ArgumentException("Data ends on incomplete repeat command!", "data");
            value = data[++i];
            Int32 repeat = data[++i] + (data[++i] << 8);
            Int32 endPoint = repeat + ptr;
            if (endPoint > bufferOut.Length)
                bufferOut = ExpandBuffer(bufferOut, Math.Max(expandSize, (UInt32)repeat));
            for (; ptr < endPoint; ptr++)
                bufferOut[ptr] = value;
        }
    }
    if (ptr < bufferOut.Length)
    {
        Byte[] bufferSized = new Byte[ptr];
        Array.Copy(bufferOut, 0, bufferSized, 0, ptr);
        bufferOut = bufferSized;
    }
    return bufferOut;
}

private static Byte[] ExpandBuffer(Byte[] bufferOut, UInt32 expandSize)
{
    Byte[] newBuf = new Byte[bufferOut.Length + expandSize];
    Array.Copy(bufferOut, 0, newBuf, 0, bufferOut.Length);
    return newBuf;
}

RLE Compression

This code was written by Nyerguds for the Engie File Converter, and is released under the WTF Public License.

public static Byte[] CompressPppRle(Byte[] data)
{
    Int32 len = data.Length;
    Int32 curBufLen = len;
    // Compressed data should never exceed original size since compression only triggers on sequences of 4 or more,
    // though it could in case of 0xFF bytes, since they always need to be encoded with a flag.
    Byte[] bufferOut = new Byte[curBufLen];
    Int32 ptr = 0;
    for (Int32 i = 0; i < len; i++)
    {
        Byte value = data[i];
        Int32 repeat = i;
        for (; repeat < len && data[repeat] == value; repeat++) { }
        repeat -= i;
        Boolean compress = repeat >= 4 || value == 0xFF;
        Int32 needed = ptr + (compress ? 3 : 0);
        if (curBufLen <= needed)
        {
            // Expand buffer if needed.
            Int32 newLen = Math.Max(curBufLen + len, needed);
            Byte[] newCompressBuffer = new Byte[newLen];
            Array.Copy(bufferOut, 0, newCompressBuffer, 0, curBufLen);
            curBufLen = newLen;
        }
        if (compress)
        {
            i += repeat - 1; // -1 because the loop itself obviously increments it
            do
            {
                Int32 repeat16b = repeat > 0xFFFF ? 0xFFFF : repeat;
                bufferOut[ptr++] = 0xFF;
                bufferOut[ptr++] = value;
                bufferOut[ptr++] = (Byte)repeat16b;
                bufferOut[ptr++] = (Byte)(repeat16b >> 8);
                repeat -= repeat16b;
                // Fix for compressing too-small leftover repeats
                if (repeat < 4 && value != 0xFF)
                    for (; repeat > 0; repeat--)
                        bufferOut[ptr++] = value;
            } while (repeat > 0);
        }
        else
            bufferOut[ptr++] = value;
    }
    Byte[] bufferSized = new Byte[ptr];
    Array.Copy(bufferOut, 0, bufferSized, 0, ptr);
    return bufferSized;
}

Tools

The following tools are able to work with files in this format.

Name PlatformView images in this format? Convert/export to another file/format? Import from another file/format? Access hidden data? Edit metadata? Notes
Engie File Converter WindowsYesYesYesNoN/A