@Burning Feet Man,
Quote: "
From this given information, is there enough for me to get from A to B, as far as extracting the art work goes?
"
Yeah, that's assuming you can get the colour palette from the other file. See here https://github.com/shlainn/game-file-formats/wiki/Constructor-Level-files
Looks like they've used IFF file format, so skimming through those files should be pretty easy. First you ID the header (IFF stamp), after that the data blocks are in chunks. Each chunk has an ID and size. You just loop through the chunks look for the ID's you want, in this case the palette data. The colour entries are probably in triple form, (24bit colour) probably R,G,B or perhaps even B,G,R.
Once you've the colours then what I'd do would be load the entire SPR file into a mem block / bank (in PB terms) since sprite files may contain many frames. The main header is pretty self explanatory, first we pull the first long, which gives the number of frames. Depending on the platform the file was created upon, you might have to flip these bytes (see
http://en.wikipedia.org/wiki/Endianness), we'll assume not for now.
Pseudo PlayBASIC / DarkBASIC styled code: (completely untested)
ThisMemblock = Load_File_To_Memory_Block("Name_Of_Sprite_File.SPR")
NumberOfFrames = Peek Integer(ThisMemblock, 0 ) ; read integer from mem block at offset 0
DIm Frames(NumberOfFrames)
// decode frames
For framelp=0 to NumberOfFrames-1
// Get the offset with the mem block of where this frame starts
FrameDataOffset = PeekInteger(ThisMemblock, 4+(FrameLp*4) )
// does frame have any data ?
if FrameDataOffset<>0
// --------------------------------------------------------------------------------
// decompress frame, here i'm assuming the frame offset is relative to the start
// of the file, it might be relative to it's position it the sprite table
// --------------------------------------------------------------------------------
// Grab the info about the sprite from it's header.
FrameWidth=PeekWORD(ThisMemblock, FrameDataOffset + 4 )
FrameHeight=PeekWORD(ThisMemblock, FrameDataOffset + 6 )
// calc current /start offset of the compressed pixel data for this frame
PixelDataAddress =FrameDataOffset + 8
// Alloc a bank to store the temp pixel data.
// it's probably a good idea to pad this, just in case :)
DecompressedMemBlock = New_MEM_Block ( FrameWidth * FrameHeight)
// --------------------------------------------------------------------------------
// decode the pixel data that makes up to this frame into the temp bank
// --------------------------------------------------------------------------------
MaxPixelCount = FrameWidth * FrameHeight
PixelCount =0
repeat
// read the pixel
ThisPixel = PeekByte(ThisMemBlock, PixelDataAddress)
// is pixel zero ??
if ThisPixel=0
// decode run length fragment (restore run of zeros)
RunSize = PeekByte(ThisMemBlock, PixelDataAddress+1)
For WriteLP=1 to RunSize
POkeByte(DecompressedMemBlock,PixelCount,ThisPixel)
Inc PixelCount
next
// step src offset/pointer forward
PixelDataAddress=PixelDataAddress+2
else
// write the pixel to output bank
POkeByte(DecompressedMemBlock,PixelCount,ThisPixel)
inc PixelDataAddress
Inc PixelCount
endif
// check if we're reached the end of sprite
until PixelCount=>MaxPixelCount
// --------------------------------------------------------------------------------
// At this point the data in the DecompressedMemBlock
// mem block is ready to draw an image from (in theory :) )
// provided the palette colours have been decoded
// --------------------------------------------------------------------------------
ThisImage = New_Image(FrameWidth,FrameHeight)
PixelCount =0
For ylp=0 to FrameHeight-1
For xlp=0 to FrameWidth-1
ThisPixel=PeekByte(DecompressedMemBlock,PixelCount)
// Convert the palette map index into the output RGB colour
ThisRGB = Palette(ThisPixel)
Draw_Dot_To_Image ThisImage,Xlp,ylp,ThisRGB
next
next
// put this frame in our frames array for later use
Frames(FrameLp)=ThisIMage
// delete the temp DecompressedMemBlock mem block
Delete Mem Block DecompressedMemBlock
endif
next
print "done"
Well, this is not necessarily the most efficient method, but you should be able to write something from the bare logic.