I know Visual Basic 6
No problem, I translated everything from C# to VB .Net but I'll be able to rewrite it into VB6 this weekend. (I forgot I didn't have VB6 at home.)
Once I recieve your code, would I be able to just reverse the procedure to generate working SPR files? Or would I be coding a recompression scheme from scratch?
No, the code I'm writting is to decompress the images because I thought of doing that to help you, or anyone else, understand the format. I could decide to write a recompressor, but don't count on that as I'm not too fond of coding.
I have no problem helping you do it or even write some pseudocode. (As the saying goes: "Give a man a fish; you have fed him for today. Teach a man to fish; and you have fed him for a lifetime". That, and that I really hate programming.)
It's not complicated; you just have to know where to find the elements and these files have few things inside. The compression mechanism implies you have to search for the repetition of a color of your choice.
I'm asking this because I'm not very familiar with converting between file formats, file headers, how things are stored, etc, and although I don't have a problem with coding my own routines, in fact I can't wait, I'd like to know that it's feasible to do so.
It's as simple as reading/writing/seeking inside binary files. The best thing you could do is learn the format, try to rewrite it in your own terms and do the coding.
I think it's possible to rebuild a SPR from a group of images even from scratch, and that the game accepts it as valid. If you keep the same width and height as the original image it should accept them.
I'm not 100% sure about this, because the game could be expecting "something" from the data. As an example, if the game allocates M bytes of memory to load the compressed data into a buffer and your compressed data is bigger, you'll end up overwriting memory you weren't supposed to overwrite.
The easiest way to test this is to get the biggest compressed image, decompress it and save it uncompressed (but encoded) to the same SPR; then run the game.
Now, I have something else to ask of you because I'm having some problems. I posted to Mirex's trashbin (
http://bin.mypage.sk/FILES/SPR_img.zip) some images. I need you to tell me what the colors should be (or give me a link to a picture with them) as I'm not much of a gamer and don't recognize the game.
I included the VB .Net code I used to generate them just in case you want to look a bit. As I said, I'll rewrite it to VB6. The only public function there (last one) takes the source file, the "table" from where you want to take the image (at the moment 0 works fine), the image index, a color to substitute the compressed pixels and the destination file. It exports the specified image to a BMP file. The other functions are auxiliary and private.
I'm not sure BMP is the right format to export to, but as there are a lot of editors/converters you can use, I thought it was fine. I say this because there are transparency and masks that other formats support better. Oh, I convert the images from 16bpp to 24bpp. I think there are 16bpp BMPs, but I'm not sure about the kind of support they have.
(I took the info on BMP from Wikipedia.)
As is, the code has some bugs:
- Colors are wrong. (Or I'm not used to those new colorful games.
)
- Some re-interpretation for colors may be needed as I'm really using 15bpp and discarding the 16th bit.
- Output BMP is flipped because I forgot BMPs start at the bottom and go up.
- Only works fine with "table" 0. I have some problems with "table" 1.
- VB .Net arrays suck. (I'm used to C and VB6 kinds of arrays.)
Maybe I overcomplicated things with the description I gave in a previous post, so here is a simplification (I hope).
The general structure for SPRs is:
- Signature.
- Image count.
- Widths for all the images. (Array from 0 To image_count-1)
- Heights for all the images. (Array 0 To image_count-1)
- Pointer to second table ("table 1").
- First table ("table 0"):
- Pointers to images. (Array from 0 To image_count-1)
- Collection of compressed images. (image_count images.)
- Pointer to end of secod table or third table?
- Second table ("table 1"):
- Pointers to images. (Array from 0 To image_count-1)
- Collection of compressed images. (image_count images.)
And sometimes "table 1" data is missing. (I'm looking into it.)
Now, the trick to work with those files is to know where each element starts, its size and the encoding.
a) The signature seems to be the same in all the files you posted:
- It starts at offset 0.
- Its size is 11 bytes (including the 0x00).
- The encoding doesn't matter, but in ASCII it's the string "DCSPRITE10" followed by the byte 00.
b) The image count tells the total number of images that are stored inside the SPR file.
- It starts at offset 11. (Because the signature is fixed.)
- Its size is 4 bytes.
- It's the representation of a 32-bit integer.
c) The widths for the images are an array of integer with the widths in pixels.
- It starts at offset 15.
- Its size is '4*image_count' because each element is 4 bytes long.
- Each element represents a 32-bit integer.
d) The heights for the images are an array of integers with the heights in pixels.
- It starts at offset '15+4*image_count'.
- Its size is '4*image_count' because each element is 4 bytes long.
- Each element represents a 32-bit integer.
e) The pointer to the second table tells where in the file the pointers to the second group of compressed images start.
- It starts at offset '15+4*image_count*2'.
- Its size is 4 bytes.
- It's the representation of a 32-bit integer.
Note: This is not a direct offset in the file, but it has to be multiplied by 2 and added to a base offset instead. (* See below.)
f) The first table of pointers tells where each image from the first table can be found in the file.
- It starts at offset '15+4*image_count*2+4'
- Its size is '4*image_count' as each element is 4 bytes long.
- Each element represents a 32-bit integer.
Note: Each element is not a direct offset in the file, but they have to be multiplied by 2 and added to a base offset instead. (* See below.)
g) The collection of compressed images for the first table has all the images from the first table in compressed form.
- It starts at offset '15+4*image_count*2+4+4*image_count'.
- Its size is variable and it depends on the size of the images and the compression obtained.
- Each element is a compressed image and is described somewhere else.
h) Not sure how to interpret the pointer to the end of the second table (or third table).
- It's start is determined by the pointer explained in (e).
- Its size is 4 bytes.
- It's the representation of a 32-bit integer.
Note: This is not a direct offset in the file, but it has to be multiplied by 2 and added to a base offset instead. (** See below.)
i) The first table of pointers tells where each image from the second table can be found in the file.
- Its start is determined by adding 4 to the offset of (h).
- Its size is '4*image_count' as each element is 4 bytes long.
- Each element represents a 32-bit integer.
Note: Each element is not a direct offset in the file, but they have to be multiplied by 2 and added to a base offset instead. (** See below.)
j) The collection of compressed images for the second table has all the images from the second table in compressed form.
- It starts '4+4*image_count' bytes after the start of the array seen in (h).
- Its size is variable and it depends on the size of the images and the compression obtained.
- Each element is a compressed image and is described somewhere else.
(*) As the size of the data inside the images is always a multiple of 2 bytes, the pointers seem to be expressed as half-words (16 bits) instead of bytes, so they have to be multiplied by 2.
These pointers (multiplied by 2) are relative to a base offset. In the case of the pointers described in (e) and (f), the base offset is the start of (g).
(**) Similar to (*), but the base offset for the pointers in (h) and (i) is the start of (j).
I left out the explanation for the compression, but I'll explain it in some other post.
I think this explanation is more simple than the previous one (I may be wrong) and if you decide to make an editing tool for SPRs, I'll recommend you take your time to understand the general outline of the files. A pencil and paper, plus a hex-editor should help you a lot.
Try to find the start of all the components and then the blocks of data: you'll notice similar elements and such.
About file modification of SPRs, don't try to add new images to the existing files: just copy the data you can take from the original file (with the modifications necessary to create a valid SPR) and add/remove the data you want.
Another thing you can do is export all the images at once, modify them and rebuild the SPR. This is probably easier to do than writing functions for individual images, but you'll need more disk space at once.
-------------------------
Edit: Corrected the tables a little bit as I was missing a field.