While working on Märchen Maze translation I checked if other Namcot games use the same image encoding format. It appears that not only some Namcot games use it but there are Pack-In-Video games as well. Maybe the same subcontractor studio was involved.
Anyway, here is the list of the games I checked so far.
The encoding is pretty simple. The image is split in 32 bytes blocs. Each bloc can be encoded using one of he following 4 techniques :
- 0 filled : the bloc is filled with 0. A plain old memset is enough.
1
memset
(out, 0, 32)
- Sparse : the bloc contains 0 bytes. The first 4 bytes indicates if the corresponding bloc byte is 0 or read from the data buffer.
1234567891011121314151617
uint8_t
*input;
// pointer to encoded input data.
uint8_t
*out;
// pointer to output data.
// ...
// sparse_decode
int
i, j;
uint8_t
*header = input;
uint8_t
*data = input+4;
uint8_t
bit;
for
(i=0; i<4; i++)
{
bit = header[i];
for
(j=0; j<8; j++)
{
*out++ = (bit & 1) ? *data++ : 0x00;
bit >>= 1;
}
}
- XOR Sparse : Just like the “sparse” encoding but the bloc was previously processed using a sequence of xor on each consecutive 16 bytes in order to increase the number of 0 in the bloc.
123456789
sparse_decode(out, input);
// xor
for
(i=0; i<16; i+=2)
{
out[i+0x02] ^= out[i+0x00];
out[i+0x03] ^= out[i+0x01];
out[i+0x12] ^= out[i+0x10];
out[i+0x13] ^= out[i+0x11];
}
- Raw : the bloc data is stored unencoded, just call
1
memcpy
(out, data, 32)
The encoding type is packed in 4 bits stored separately from the image data. This means that a byte stores the encoding type for 4 blocs.
The pseudo code for the whole decoding routine looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | uint8_t *encoding; // pointer to the bloc encoding type array. uint8_t *data; // pointer to the encoded image data. uint8_t *out; // pointer to the output image data. size_t bloc_count; uint8_t current_bloc_encoding; int i; for (i=0; i<bloc_count; i++) { current_bloc_encoding = (encoding[i/4] >> (i%4)) & 0x03; switch (current_bloc_encoding) { case 0: // zero filled. memset (out, 0, 32); break ; case 1: // sparse. sparse_decode(out, data); break ; case 2: // XOR sparse. sparse_decode(out, data); xor (out); break ; case 3: // raw data. memcpy (out, data, 32); data += 32; break ; } out += 32; } |
- Source code for Märchen Maze, Obocchama Kun and Zipang.
- Source code for World Jockey.