Uncompressing the ancient animation compression format

image



One day I watched various videos on YouTube related to the characters of the Vocaloid program (not quite an accurate description, but from now on I will just call it Vocaloid). One such video was the so-called PV from the game Hatsune Miku: Project DIVA 2nd. Namely, the song relations from The Idolmaster, which was performed by vocaloids Megurine Luka and Kagamine Rin. Both characters are from Crypton Future Media. After surfing the net, I realized that no one was able to convert the animations from this game? But why? About this under the cut.



The game itself uses the Alchemy Engine, which was developed by Intrinsic Graphics and later bought by Vicarious Visions. This can be seen from the files with the ".igb" extension (hereinafter - IGB), as well as the corresponding lines in them. The files themselves are binary. Googling a little, I found a script from Comrade. minmode for the well-known Noesis program in certain circles . We launch it, with the script thrown into the folder, try to open the animation file and ... We get the pumpkin.



image



As comrade. minmode in his post on DeviantArt, this script cannot read animation compressed by some Enbaya. On Google Patents I could only find similar . The patents themselves are already 19-20 years old, so I assume that the compression algorithm itself is also ancient. And the site itselfhints at this too (only available via the web archive). After searching a little more, I realized that this algorithm was part of a certain ProGATE from the Enbaya company. But that doesn't give us anything.



Let's go back to the IGB. By rewriting the IGB code that I could find, as well as using the Noesis script in C #, the picture began to clear up.



Below I will give a table of elements, as it was lined up in the IGB files in this game (sorry for being clumsy. I can't do otherwise). I will give only the elements we need



Clarification - * List - an array of elements *



igAnimationDatabase
--igSkeletonList
---igSkeleton - , , ,   
----igSkeletonBoneInfoList
-----igSkeletonBoneInfo -  
--igAnimationList
---igAnimation -  
----igAnimationBindingList
-----igAnimationBinding -   igSkeleton.      
----igAnimationTrackList
-----igAnimationTrack -   
------igEnbayaTransformSource
-------igEnbayaAnimationSource
--------igData -      Enbaya
igData -   ,     .


This way I was able to get the raw data for further study. With the help of PPSSPP, Ghidra and a plugin for it, I began to study the game binary. I don't really remember exactly how I found the necessary functions, but I will give specific functions from EBOOT.BIN from ULJM05681 [or NPJH50300] (in this case, this is the first Project Diva 2nd, and not the second, the so-called Bargain Version or Project Diva 2nd #) :



0x08A08050 - initialization of the decompression function based on the header from igData

0x08A0876C - request for data at a specific time (yes. Enbaya works with time, not frames).



The code itself is decompiled and posted on GitLab . It is written in C. Compiles in both Visual Studio and gcc. Works in both x86 and x64.



I won't go into the algorithm itself. My code will tell you better for me.



But in short, Enbaya uses a delta for displacement and quaternion data. It applies the delta by simply adding / subtracting it to / from the previous / current data. The translation remains as it is, and the quaternion is normalized for later use. The algorithm allows you to go back in time without reloading the file. Moreover, it operates not with a frame rate, but with samples per second. To do this, it stores two states in memory - the previous sample and the next, and the engine itself interpolates the value between them. However, due to the fact that the data in the file is everywhere in integer form, we must divide it by something (more precisely, multiply it, for example, by 0.0002) to get a fractional number. This number is indicated in the title. Because of this division (actually multiplication, but not the essence), with each addition and subtraction, the accuracy drifts a little.



And that's all. To be honest, I had fun reversing it all. I hope that my work was not in vain.



PS Using the igSkeleton data, we can already get the finished animation and export it, for example, to Maya. Through the same Noesis.






All Articles