-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How and where the assets are stored? #1
Comments
I've loaded ROM into YY-CHR program, loaded the palette from save state and after scrolling through bits and bytes a bit I've found that viking animation frames, items as well as whole HUD is in plain tile format, so extracting it is not a problem. I haven't been able to find fonts, enemies and tiles this way. Then, I've opened the save state directly in YY-CHR to see if those data are available anywhere in RAM. And there I've found the font: so it looks like the data is somewhat compressed. I'll need some help to get the decompression routine in clean room approach
|
Compressed data structure for lost Viking 2 You can test with compressed data located in 0x0E2583 in rom 0x00 - 0x01 : Size of decompressed data Get the repeat number bits value (8bit), get the lowest bit (keep it for later) then shift right by one the repeat number bits. If the lowest bit is high (value of 1), we copy the next value (byte) of compressed data to the decompressed as is. If the lowest bit is low :
Then we return to the repeat Number and get his lowest byte and shift right by one. When repeat number loop is over we read the next compressed data repeat number and repeat decompressed data is initialized with a 0x1000 size full of 0x00 values. |
great stuff! Will add support for some assets to the game asap :) |
Something doesn't seem to be right. Assuming the data is at 0x0E2583 position in ROM file, the first two bytes (uncompressed data size) decodes to 4512. That's bigger than max size of 0x1000. How's that relate to:
are the bytes 4096 and above not zeroed? Then, the first byte containing repeat bits is 01011000 - assuming that zeros correspond to unpacking of already stored bytes, this decodes to:
I've tried assuming that 0 is copying byte as-is and 1 is copying already-decoded bytes, but then it's still doesn't seem to be right. I'm betting that I'm doing something terribly wrong. ;) |
I've fiddled around the code a bit and it looks like all of repeat bits should be processed instead of stopping after the right-shifted value becomes zero. I've done said change and I've successfully decoded Interplay logo tiles from the address you've specified. Could you confirm that this is the intended behavior? This way, the first repeat byte translates to:
regarding 4.5KB file not fitting in 4096-byte buffer, I guess the zeroing of first bytes is only for sake of RLE so that decompressor can assume that zeros are everywhere and use e.g. end of 4096-byte buffer as a source of repeated zeros. |
This seems correct to me ... |
Ressources offsets are located at 0x050000 ROM offset the first 2 bytes + 0x8000 are the ROM address (little endian) |
The data you've found earlier is at 0x0E2583 in the ROM file. The only thing on the list with lowest byte 83 is
but really not sure about it. Some entries look like the offsets I've found on my own and your transform fits them more. I'll try to find and decompress some stuff tomorrow with your transform and we'll see where it takes me. |
Okay, I guess this can be related to the fact that I don't exactly know how SNES memory map works. I've set the mesen debugger to stop on ROM addr 0x0E2583 being read and it stopped, showing read from 0x9CA583 - your calc works properly here. Now I read that 0x800000 is the start of the memory shadow, so it's the same as 0x1CA583 and by looking at memory view it looks like it, but it's still 0xE8000 off to ROM file data offset. From what I understand the memory mapping can change in SNES on the fly, so the safest bet would be:
Kinda tedious, but doable. Or perhaps:
I'll try to go with this approach and see where it will take me. EDIT: and there's something not right. The 0x84A18 from the table is followed by the 0x90218, by subtracting there's a size of 47104 - it's the same uncompressed data that I've found earlier and it's in the ROM offs 0x8CA18 - 0x98218. By following my algorithm:
Not so easy. Any ideas other than going option 1 or disassembling and figuring out how the game maps the memory? |
Here is a small php method to address to rom offset that works with lost viking 2 mapping
|
Looks good! Works good! |
I've managed to determine if some assets are compressed or not - I've got the rough estimate of their size as stored in ROM by subtracting their stored offset on the asset list from the offset of next asset, and then checked the first u16 (uncompressed size) to see if it's bigger than that size - if yes, there's a chance that asset is compressed. Then, I've started throwing exception when RLE read start is further than 0x1000 and bigger than uncompressed size, because that is probably illegal. All of that filtering have left me 197 decompressed assets. I've looked through all of them with YY-CHR and I've found out that around 40 are holding gfx - some of them were slightly corrupted (e.g. movable block gfx, pushbutton gfx). I'll look through my code to see if I'm making something stupid, otherwise there's something wrong with decompression algo or YY-CHR doesn't visualize the graphics properly. |
There is a condition that I missed to explain : We loop until CopyLoopIndex is equal to 0x1000 (in this case, we set copyLoopIndex to 0 and continue looping) or is equal to CopyLoopSize |
I've checked and it on files listed above and it works! thanks! I'll now review all the remaining assets and see if something else messes up. |
I've successfully decoded most of NPC and enemies gfx - tiles are still elusive for me, but it's perhaps wrong preview tool and/or palette. I've just discovered that there are 47 files starting with |
Last time, I've got stuck at decompressing larger images, e.g. continue screen chars. Images got more corrupted the bigger they were. Found the bug! The decompression routine was flawed. I took a looksie at decompression routine for LV1 at https://github.com/RyanMallon/TheLostVikingsTools/blob/master/liblv/lv_compress.c#L76 and apparently, it used very similar algorithm, but whenever copying the past bytes occured, it used the separate 4096-long circular lookup buffer. After doing the same, it worked like a charm. (different palette btw but image looks less distorted) I wonder what else can be recycled from LV1. Perhaps even its virtual machine? That would be big and allow running original logic on an Amiga - be it by interpreting it on the fly, or by compiling to native code ahead of time. |
So far I've managed to decode most of the data files, including palettes, tilesets, tilemaps, level definitions. Three big areas remain unsolved:
I've found sounds using the snessor and BRR finder, but that method guesses where the samples start and stop, and I have no hard references on neither where each sound is used nor what playback parameters should be set. Also, it would be amazing to find the code responsible for music playback (e.g. custom tracker/sequencer) Regarding scripting, I thought that perhaps LV2 uses virtual machine and bytecode-based scripts as the PC version of LV1 (https://ryiron.wordpress.com/2017/02/01/finding-the-lost-vikings-reversing-a-virtual-machine/) but that doesn't seem to be the case, and other platform versions of LV2 use entirely different file organization/engine. So it looks like to make game logic very accurate, it would require disassembling some 65C816 code. Each level has a list of objects to be spawned, and each object has: position, center point, class id, and two unknown u16 values: unk1 and unk2. The unk2 value seems to be behavior argument/parameter for object, because e.g. pickups share the same class, but unk2 corresponds to the item kind, e.g. 1 is a shield pickup, and 2 is a bomb, etc. Same with switches/doors/keyholes - unk2 indicates a link between them. There are around 164 object classes to reverse, and according to LV1 reversing docs, they might share scripts (e.g. patrolling enemies all have different classes, but their behavior is mostly the same) as it's determined by one of the class definiton field. The other fields might be: collision rectangle dimensions and index of datafile containing graphics frames. Even finding the class definition list would be a big help because it would show relations to gfx files as well as true size boxes - I currently guesstimate them using center point sizes, which doesn't look to be always correct. To find that, it could be done as following:
This would also allow finding where the game texts are stored, because the help box triggers given text on interaction. |
The game seems to have very little code (see screenshot). Perhaps, in the end, I'm not extracting all the files and they are split into multiple packs, and behavior bytecode is still lurking somewhere? Or perhaps entity behaviors for everything except for vikings are heavily recycled, thus having very little footprint. I've ran the full PAL version of the game through Diztinguish in case someone wants to take a stab at disassembling it and writing a spec for missing features. |
One thing that wasn't taken into account in the list of stuff to find are texts - I couldn't find them in plain encoding anywhere in the ROM, neither in ASCII nor in indices corresponding to the game's font, so there's some compression stuff in the works. Here's what I got from Runic in sneslab:
I don't understand the half of it, except for the bank 2 thingy. If I'm correct this corresponds to address 0x10000 in ROM file and apparently there are some 25 byte-long entries in there and there are even some candidates for pointers to the data: The marked address 83077301 converts to ROM position B7301 and that collides with previously detected data, so it can't be valid, but 00839773 is at ROM position 19773 and that's better result because of no collisions. Further finding of close addresses: 83B404 -> ROM 1B404 Gives some sensible bounds for entry at 1B404 which is apparently 63 bytes long. How to decode it is a mystery to me, and most probably it's compressed somehow. My progress of reading those texts directly form ROM is hindered for now, so I guess I need to rip them from RAM somehow for now. |
This game requires extracting all of the assets from the ROM file. How are they stored?
Please don't post original disassembled code or pure extracted assets!
The text was updated successfully, but these errors were encountered: