Descomprimir el antiguo formato de compresión de animación

imagen



Un día vi varios videos en YouTube relacionados con los personajes del programa Vocaloid (no es una descripción muy precisa, pero seguiré llamándolo simplemente vocaloids). Uno de esos videos fue el llamado PV del juego Hatsune Miku: Project DIVA 2nd. A saber, las relaciones de la canción de The Idolmaster, que fue interpretada por los vocaloides Megurine Luka y Kagamine Rin. Ambos personajes son de Crypton Future Media. Después de navegar por la red, me di cuenta de que nadie podía convertir las animaciones de este juego. ¿Pero por qué? Sobre esto bajo el corte.



El juego en sí usa Alchemy Engine, que fue desarrollado por Intrinsic Graphics y luego comprado por Vicarious Visions. Esto se puede ver en los archivos con extensión ".igb" (en adelante, IGB), así como en las líneas correspondientes en ellos. Los archivos en sí son binarios. Buscando un poco en Google, encontré un guión de Comrade. minmode para el conocido programa Noesis en ciertos círculos . Lo lanzamos, con el script arrojado a la carpeta, intentamos abrir el archivo de animación y ... Obtenemos la calabaza.



imagen



Como camarada. minmode en su publicación en DeviantArt, este script no puede leer animaciones comprimidas por algunos Enbaya. En Google Patents solo pude encontrar similares . Las patentes en sí mismas ya tienen entre 19 y 20 años, así que supongo que el algoritmo de compresión en sí también es antiguo. Y el sitio entambién da pistas sobre esto (solo disponible a través del archivo web). Después de buscar un poco más, me di cuenta de que este algoritmo formaba parte de un determinado ProGATE de la empresa Enbaya. Pero eso no nos da nada.



Volvamos al IGB. Al reescribir el código IGB que pude encontrar, así como al usar el script Noesis en C #, la imagen comenzó a aclararse.



A continuación, daré una tabla de elementos, ya que estaba alineada en los archivos IGB de este juego (perdón por la torpeza. No puedo hacer otra cosa). Daré solo los elementos que necesitamos



Aclaración - * Lista - una matriz de elementos *



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


De esta manera pude poner mis manos en los datos sin procesar para estudiarlos más a fondo. Con la ayuda de PPSSPP, Ghidra y un complemento , comencé a estudiar el binario del juego. Realmente no recuerdo exactamente cómo encontré las funciones necesarias, pero daré funciones específicas de EBOOT.BIN de ULJM05681 [o NPJH50300] (en este caso, este es el primer Project Diva 2nd, y no el segundo, la llamada Versión Bargain o Project Diva 2nd #) :



0x08A08050 - inicialización de la función de descompresión basada en el encabezado de igData

0x08A0876C - solicitud de datos en un momento específico (sí. Enbaya trabaja con tiempo, no con marcos).



El código en sí se descompila y se publica en GitLab . Está escrito en C. Se compila tanto en Visual Studio como en gcc. Funciona tanto en x86 como en x64.



No entraré en el algoritmo en sí. Mi código te lo dirá mejor por mí.



Pero en resumen, Enbaya usa delta para datos de desplazamiento y cuaternión. Aplica el delta simplemente sumándolo / restando a / de los datos anteriores / actuales. La traducción permanece como está y el cuaternión se normaliza para su uso posterior. El algoritmo le permite retroceder en el tiempo sin volver a cargar el archivo. Además, no funciona con una velocidad de fotogramas, sino con muestras por segundo. Para hacer esto, almacena dos estados en la memoria, la muestra anterior y la siguiente, y el motor mismo interpola el valor entre ellos. Sin embargo, debido al hecho de que tenemos datos en el archivo en todas partes en forma de entero, tenemos que dividirlo por algo (más precisamente, multiplicarlo, por ejemplo, por 0,0002) para obtener un número fraccionario. Este número se indica en el título. Debido a esta división (en realidad multiplicación, pero no la esencia), con cada suma y resta, la precisión se desvía un poco.



Y eso es todo. Para ser honesto, me divertí revirtiéndolo todo. Espero que mi trabajo no haya sido en vano.



PD Usando los datos de igSkeleton, ya podemos obtener la animación terminada y exportarla, por ejemplo, a Maya. A través del mismo Noesis.






All Articles