Extracting Lode Runner 2's graphics data
A description of the XPK graphics format
Reverse-engineering of XPK format done by
Toastline of SPG
I think that the X in XPK stands for "extended," and the PK is short
for "Pak." Presage used to use .prs and .prd files, .prs having
contained Pak resources in them, which I believe were images. I
think the d in prd stood for directory, as they serve as a sort of
directory for the prs. PRX is almost exactly the result of taking the
prd and sticking it into a file with the prs immediately after it. I
think the X in PRX is also short for "extended." I also think the PRX
spec allows it to include arbitrary data types, and the prs spec did
Inside most of the .PRX files
in the game Lode
, there are sections of data which store
images. I have figured out how this is done and now you can learn
it and perhaps make a better extractor
than I have. Mine is clumsy and
not perfectly reliable, so I encourage someone to do so, in fact!
This page describes XPKs which are not under the influence of an
XMV. For the fun
ways that those change the things, see "43_XMV_and_XUI_resources.txt".
I'll use GearWG.PRX as an example, first.
The first XPK resource starts with this metadata:
58 50 4B 00 E8 03 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 F7 07 00 00
Where 58 50 4B is XPK in ascii. F7 07 00 00 is the size of the resource
plus this metadata section, in little endian form, in bytes. That's
starting at the very beginning of the entry (so the last address in the
resource plus this section would be 0000 07F6 big-endian). I
don't know what the rest is. It's possible that not all of this
Then there's this thing which IS where I think the resource
starts. At this point I will treat the resource, for descriptive
purposes, as its own file. So think of this next series of bytes
as being at the addresses 00-03, instead of considering their position
inside the larger .PRX file.
A5 7E 70 01
These will always be the same.
Then the next 12 bytes in this particular resource are
B0 02 00 01 00 00 01 74 00 00 01 84
The first two bytes tell you what kind of XPK this is. These bytes can
also be B001 or C002. B002 uses a
palette and run-length encoding, as you will see. The 4th byte here,
which is 01, is the number of images. Usually
it will be 01, but
sometimes multiple images are stored that use one palette, and you'll
need to know how many there are to read them properly. Maybe the
byte before that is part of it too, but I haven't seen any occasions
where there were that many frames. 01 74 tells what byte the
palette ends on, minus one. So the last byte that is part of the
palette is byte 175 (hexadecimal). I don't know what 01 84 is,
but those bytes can not be consistently used to find the end of a
Then the palette starts. Each colour is 2 bytes long. The first
and the last one is
See the colour section in "tables.txt" to
learn how this works.
After that is what I call the divider. The entry we're looking at has
this in that section:
00 00 00 00 00 28 00 36 00 00 00 00 00 28 00 35 00 00 00 04
As far as I can tell, the first 4 bytes are always zeroes.
The bytes 00 28 are the x size in pixels, and the bytes 00 36 are the y
size in pixels.
The next 4 bytes do something probably. I don't know what. I
think they're always zero as well.
The next 00 28 and then the 00 35 are offsets of some kind. I'm not
entirely sure how they work, but it's not something obvious.
Also as far as I can tell, the last 4 bytes are always 00 00 00 04.
Once the divider is over, comes the first row of the image.
wx yz - start of a new line which
is wxyz bytes long (this will only occur at new rows before anything is
drawn in them. Commonly, wx is 00, but it does not have to be.)
Then there's the data that goes into drawing the row.
0x - draws x+1 blank pixels
1x - draws x+17 blank pixels
2x - draws x+33 blank pixels
3x - draws x+49 blank pixels
4x - draws x+1 pixels, of the
colours specified in the x+1 following bytes
5x - draws x+17 pixels, of the
colours specified in the x+17 following bytes
6x - draws x+33 pixels, of the
colours specified in the x+33 following bytes
7x - draws x+49 pixels, of the
colours specified in the x+49 following bytes
8x yz - draws x+2 pixels of colour
9x yz - draws x+18 pixels of
ax yz - draws x+34 pixels of
bx yz - draws x+50 pixels of
cx yz - draws 1 pixel of colour yz
with alpha (I made a table)
dx yz - draws 1 pixel of colour yz
with different alpha (I made a table)
ex yz - same as cx yz?
fx yz - same as dx yz?
I have question marks on those last 2 because they seem to be true, but
it's possible that they are not always.
Once a row is completed (so you've read wxyz more bytes) there is
another wxyz to read, and so on until the end of the image.
Reverse-engineering of XPK done by Toastline of SPG