Here is the binary template for liwiza.imp, it is built specifically for liwiza.imp and is only usable in 010 Hex Editor:
liwizaIMP.bt (80.54 KB)
It is a byte by byte rundown of the entire RLE for liwiza.imp based on imp.c variable field enumeration. But it is a caveman tool nonetheless. I would like to make a .bt that works for all .imp files however 010 Hex editor uses a custom script that looks like Python and C++ had a baby. I even made a C Program to parse any .imp file and store the offsets in a CSV file along with the values. It seems, because of my very basic skills, that I will have to make a seperate parser for each of the five functions of imp.c in the .imp RLE, that being the Header, Sequence, Facing, Frame and Hotspot. I also isolated the Palette Data and put it in the binary template. The Sequence field array gets created based off the u2 NumSequence value from the Header. The Facing array size also uses this value to determine it's own size, basically 5 multiplied against the NumSequence value- this will tell you how many structs to loop. The Frame and Hotspot array gets it size from the Size value of the Facing struct. The Frame struct is at top near header, the Hotspot struct appears to seek the end of the file, go back 16 bytes, before going back the number of bytes in the Hotspot array variable enumeration, again given by imp.c so I might continue to work on these IMP structure parsers, seems easier and faster than learning the binary template custom script 010 Hex uses. Here is the code if anyone wants to mess with it, I keep it and the imp file in C:\LOMUT FYI:
impheader.c (3.3 KB)
I can compile into an executable maybe in a different post since I will be stitching together a number of parsers into a single program or run them from a different interface or even a GUI.
So I think this is the way we are going to finally fix all the issues. I want to modify lomut.c but right now editing the RLE byte data seems the most promising and best solution. Not only that but I have been looking at .smp and .smk files to get them to work in game or modify them out of game via hex. I have some issues though. I have still been unable to get a fully working sprite in the game this way. Changing bytes defintely affects the hotspot. But I may be doing it wrong, I have tried copy and pasting, setting values to zero for hotspot field. We need to figure out what is going on here. Maybe the last 16 bytes of every file are a Checksum for the Hotspot struct which is worrying me. I have some evidence of this look:
Although I admit I could be losing my mind staring at this code the chances that these 16 bits of data add up to a number in the billions and that number directly translates to a hex code that is equal to the Checksum for 32 bit variables seems like a mathmatical miracle. But this is Lord's of Magic so I am not suprised and have looked at several .imp and can't reproduce the checksum match. I might need to disassemble LoMSE to see if there is any Checksum calls. At least I have a guess of the checksum variable location and we know the algorithm so we can reverse engineer a way to "rehash" the value. Why I think there is a checksum is because I have been unable to modify the Hotspot values and load the .imp into the game without the game crashing. Changing the Width and Height in the Header, (which are the max values for width and height out of all the frames), yields glitched results. Changing the Frame data also gives me glitched results. Changing both also glitches out. Changing both and the Hotspot data definitely glitches out here is what I mean:
As you can see the sprite has been spaghettified, the runs are all over the place. Note this is actually a simplified test sprite and custom .H file that has only 5 frames of Stand animation so I can test it quickly. This water dungeon has a nice grid I've been using to test. Even on a brand new .imp compiled from LOMUT where the initial images are 60 by 60 LOMUT still puts in a byte value of 512 for the Width and Height in the header. Hopefully we dont need to going into the 1 byte RLE pcx.c structs to solve this, but I am conifdent we dont need to do that, the variables in imp.c should be enough. I think in this test sprite since it is an custom sprite even if I change the 512 * 512 values in the header the rest of the RLE seems to be encoding on based off that value, so changing it changes where the runs of pixels start in the RLE. So I may need to make another program that can calculate the Hotspot DispX, DispY and HotX and HotY as well as the Frame struct's width and height. These old RLE run from top corner left to right. So I have had success getting in a rectangle that is perfect size and the hotspot works!!! But it is a rectangle not a sprite, maybe I should start moving my new sprites to the top corner of the 512 * 512 image? That may work but I am not sure what other problems arise.
The only thing I can 100% modify is the palette data with no issue. If I modify the PaletteOffset(the first 1) I think this changes with what Faith the unit is on. In an attempt to create Fire Lizards I changed the Palette offset but it seems like Fire Lizards on the mauruders party had a different color red! Also jsut straight up editing the palette data, which is in there right after frame with a 1 byte padding if odd number Sequences/Frames. Anyway the palette data is just there in HTML format ARGB I think is the order encoded. Anyway this lead to real neat palette swaps that have no HotSpot errors!!! Is this how you made Frozen Shades
Boaster???
Anyway great work guys we are SO CLOSE! What do yall think any ideas/solutions? Maybe I overlooked something? 010 Hex has a free 30 trial to use the .bt if you want to try yourself:
Here is the formula for using the structs to determine Hotspot area:
Type: This indicates whether the frame is a normal frame or a duplicate-back-reference frame. A duplicate-back-reference frame means that it is not stored as a separate frame, but instead it is a reference to a previous frame. This can save space in the file.
HSType: This specifies the type of value that the HSpot variable holds. It can hold either a packed 16-bit XY displacement or an offset to a HotSpot structure.
Width and Height: These variables represent the real width and height of the frame in pixels.
Size: This variable represents the compressed size of the frame, or the uncompressed size if the frame is a duplicate or a type 9 frame. It should be aligned to 4 bytes.
HSpot: This variable holds the Hot Spot data for the frame. It can either hold a packed XY displacement or an offset to a HotSpot structure.
Offset: This variable holds the offset to the frame data or the number of the duplicating frame.
About the HotSpot structure. It contains information about the Hot Spot of a frame, which is the pixel location that is used as the anchor point when the frame is displayed. The HotSpot structure contains the following variables:
DispX and DispY: These variables represent the XY displacement from the virtual Width and Height. They indicate how far the Hot Spot is from the top-left corner of the virtual image.
HotX and HotY: These variables represent the click-point for cursors. They indicate where the user should click if they want to interact with the frame. For units, HotX and HotY may represent the spawning location of the missile or the location of the unit's feet.
Unknown variables: These variables are currently unknown and their purpose is not clear.
To visualize this data in pixel terms, you can use the following formula:
PixelX = DispX + HotX
PixelY = DispY + HotY
This will give you the pixel coordinates of the Hot Spot for the frame.
So maybe there is no Checksum maybe I need to figure out to handle HSType and HSpot as well as the Offset... We can see the promised land folks!