SPU
file structure
Brought
to you by the ESS Open Firmware Team
file
structure is
table 1 + table 2 + table 3
words
and dwords are in big endian
Table 1
offset size description
0x0 0x2 Offset to table
3. If table 3 is not present, it will
point 1 byte past the end of the file.
0x2 0x2 Offset to table
2.
0x4 ??? variable length
picture data. Format described below.
Table 2
Set of commands. Presented here in the order the commands are
usually placed into the table (hence the offset).
0x0 0x5/6 Unknown initial values. May be version of SPU & table loc.
examples:
image1.spu
: 00 08 03 c6 00 (table offset)
image2.spu
: 00 00 06 62 01 (table offset + 18)
111.spu
:00 00 00 5d 00 01 (table offset
+ 19)
a8image1.spu :
00 00 03 48 00 (table offset)
yamalogo.spu :00 00 0b 73 00 01 (table offset + 19)
logo.spu
:00 00 00 69 00 01 (table offset
+ 19)
First two bytes are usually 0. Older images may have other values, but the newest
images always have 0.
The next 2 bytes are either the table 2 offset, or
the table 2 offset + 0x18 or 0x19.
If it is the table 2 offset + 0x19, then there will
be an additional 0 after it. This is
typical for the newer images.
Following that will be either a 0 or 1. Newer images have a 1.
0x6 0x1 Command 0x03:
Set palette
0x7 0x2 Palette, one
nibble per color. Defaults listed
below. Changes as per table 3.
0x0 = black
0x1 = dk red
0x2 = dk green
0x3 = dk yellow (brown)
0x4 = dk blue
0x5 = dk purple
0x6 = dk cyan
0x7 = lt grey
0x8 = dk grey
0x9 = red
0xa = green
0xb = yellow
0xc = blue
0xd = purple
0xe = cyan
0xf = white
0x9 0x1 Command
0x04: Set contrast / intensity
(transparency)
0xa 0x1 High nibble =
emph2, low nibble = emph1
0xb 0x1 High nibble =
pattern, Low nibble = back
0xc 0x1 Command
0x05: Set Initial Coordinates
0xd 0x3 Horizontal
(0x1001 * start line + bitmap width - 1)
0x10 0x3 Vertical (0x1001 * start col + bitmap height - 1)
0x13 0x1 Command
0x06: Image 1/Image 2 Offsets
0x14 0x2 Always 0x0004
(Start of Image 1)
0x16 0x2 Offset to the
start of the second half of the interlaced image.
0x18 0x1 Command
0xFF: Time Delay
0x19 0x2 Time parameter
1: Usually starts at 5 and increments
6n, where n = value of fade in, last, or fade out.
0x1b 0x2 Time parameter
2: Starts at 0x5d and increases 8 each
step. If fade in is done, this will start at 0x65 to force the image to not be
displayed at all during the 0x5d time frame.
The
remainder of table 2 consists of commands as above. The exact
commands
are created depending upon the settings of fade in / last / fade out.
If Fade
In is > 0, then there will be 8 command sets of 0xff & 0x04 to fade in
the
image. The time the image stays on the
screen will be encoded with
one set
of 0xff & 0x04 commands, but if there is a fade in then there may be
other
commands setting the palette, etc. Fade
out will follow, also
with 8
command sets if the setting is > 0.
???? 0x1 Command
0x02: End Of Commands. Note:
This is NOT always present.
Sometimes it just does 0xff as padding. Most recent files include this value.
The
ending bytes are followed by 0xff to pad to the nearest DWORD (not less
than 1
0xff).
Table 3
(only present if the image is a logo.
Screensaver images are logos).
0x40 bytes.
structure
is 15 palette DWORDs indicating color.
Format is in YUV. Values
are
rounded to the nearest 0x10.
Y =
(0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr =
(0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb =
-(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
00108080
- black
0030c070
- dk red
00505060
- dk green
00709040
- dk yellow
002070c0
- dk blue
0040b0a0
- dk purple
00604090
- dk cyan
00b08080
- lt grey
00808080
- dk grey
0050f060
- lt red
00902030
- lt green
00d09010
- lt yellow
003070f0
- lt blue
0070e0d0
- lt purple
00b010a0
- lt cyan
00f08080
- white
That is
the default order, assigning index 0 to 15 in order. However,
this
order can be modified causing the index values to mean something
different. Eg, if you were to swap dk red and black,
then dk red
becomes
index 0, and black becomes index 1.
Variable
Length Picture Data format
Lines
are interlaced. Therefore, there must
be an even number of lines.
Next
line always starts on a byte boundary.
Picture
is always a 4 color picture. The 4
colors map to the 4 colors in the palette.
eg, if
the palette is 0x57f0, then
lo byte lo nibble = 0,
lo byte hi nibble = f,
hi byte lo nibble = 7,
hi byte hi nibble = 5.
and those colors correspond to the
colors in the palette (5 = dk purple).
The RLE
encoding is similar to the gaussian distributed data optimal coding
method,
but has been modified.
Decode
from hi nibble to lo nibble (reading extra nibbles marked by 'y'), from the start of the image as follows:
0000 =
lo byte lo nibble, repeat to end of line (end of scan line mark)
0001 =
lo byte hi nibble, repeat to end of line (end of scan line mark)
0002 =
hi byte lo nibble, repeat to end of line (end of scan line mark)
0003 =
hi byte hi nibble, repeat to end of line (end of scan line mark)
0004-f
= not valid
01yy 64 of lo byte lo nibble
02yy 128 of lo byte lo nibble
03yy 212 of lo byte lo nibble
04y 16 of lo byte lo nibble
05y 20 of lo byte lo nibble
06y 24 of lo byte lo nibble
07y 28 of lo byte lo nibble
08y 32 of lo byte lo nibble
09y 36 of lo byte lo nibble
0ay 40 of lo byte lo nibble
0by 44 of lo byte lo nibble
0cy 48 of lo byte lo nibble
0dy 52 of lo byte lo nibble
0ey 56 of lo byte lo nibble
0fy 60 of lo byte lo nibble
1y 4 of lo byte lo nibble
2y 8 of lo byte lo nibble
3y 12 of lo byte lo nibble
4 = lo
byte lo nibble one pixel
5 = lo
byte hi nibble one pixel
6 = hi
byte lo nibble one pixel
7 = hi
byte hi nibble one pixel
8 = 2 of lo byte lo nibble
9 = 2 of lo byte hi nibble
a = 2 of hi byte lo nibble
b = 2 of hi byte hi nibble
c = 3 of lo byte lo nibble
d = 3 of lo byte hi nibble
e = 3 of hi byte lo nibble
f = 3 of hi byte hi nibble
For
example. Suppose image is 6x6. Image data is:
00 00
49 a0 00 00 47 65 70 00 00 47 56 70 00 00 4a 90 00 00 00 00
row
#1: 0000 means repeat pal #0 to end of
row.
000000
next
interlaced row is 3.
row
#3: 4 means a single instance of pal
#0. 9 indicates 2 instances of pal #1.
a indicates 2 instance of pal #2.
0000 = repeat to end of row pal #0.
The remaining 0 is discarded to be
byte aligned.
011220
next
interlaced row is 5.
row
#5: 47657 correspond to one pixel each,
the 0000 means repeat 0. We discard the
remaining 0, and
since the pic is already 5 pixels wide, the repeat is ignored.
032130
row
#2: 47567, similar to prior row. 0000, again -- same occurance.
031230
row
#4: 4 is a single pixel pal #0, a is 2
pixels of pal #2. 9 is 2 pixels of pal #1. 0000, again discard
0 and ignore since we have already
hit the target size.
022110
row
#6: 0000 Same as row #1. Repeat pal #0 to end of row.
000000
Put
together in order, you get:
000000
031230
011220
022110
032130
000000
Here are
some examples to illustrate the more complex items.
Suppose
you had a "01 25" sequence in
the image. That would be equivalent to 0x0155
/ 4 = 0x55 with a remainder of 1. That
means 85 (decimal) repeating pixels of pal #1.
01 02 =
0x0102. 0x0102/4 = 64 (decimal)
repeating sequences of pal #2.
0a 66 =
0x0a6. 0x0a6 / 4 = 41 (decimal) sequences of pal # 3. The 6 on the end (of 0a 66) would indicate that the sequence is
followed by a single pixel of pal #2.