mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Add pattern and magic for Arma 3 RTM (#478)
* patterns/rtm: Added pattern for Arma 3 plain RTM * magic/arma3: Added plain RTM to magic file * patterns/rtm: Added test file * patterns/rtm: Changed function parameters to refs * patterns/rtm: Replaced RTM test file * patterns/rtm: Added extra description to RTM pattern * pattern/bmtr: Added BMTR pattern, magic and test file
This commit is contained in:
@@ -36,7 +36,9 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
|||||||
| ARC | | [`patterns/arc.hexpat`](patterns/arc.hexpat) | Minecraft Legacy Console Edition ARC files |
|
| ARC | | [`patterns/arc.hexpat`](patterns/arc.hexpat) | Minecraft Legacy Console Edition ARC files |
|
||||||
| ARIA2 | | [`patterns/aria2.hexpat`](patterns/aria2.hexpat) | ARIA2 Download Manager Control files |
|
| ARIA2 | | [`patterns/aria2.hexpat`](patterns/aria2.hexpat) | ARIA2 Download Manager Control files |
|
||||||
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
|
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
|
||||||
| Arma 3 PAA | | [`patterns/a3_paa.hexpat`](patterns/a3_paa.hexpat) | Arma 3 PAA texture file |
|
| Arma 3 PAA | `image/x.a3-paa` | [`patterns/a3_paa.hexpat`](patterns/a3_paa.hexpat) | Arma 3 PAA texture file |
|
||||||
|
| Arma 3 RTM | `application/x.a3-rtm` | [`patterns/a3_rtm.hexpat`](patterns/a3_rtm.hexpat) | Arma 3 RTM animation file (plain) |
|
||||||
|
| Arma 3 RTM (binarized) | `application/x.a3-bmtr` | [`patterns/a3_bmtr.hexpat`](patterns/a3_bmtr.hexpat) | Arma 3 RTM animation file (binarized) |
|
||||||
| Assassin's Creed: Unity | | [`patterns/AC Unity`](patterns/Assassin's Creed: Unity) | Assassin's Creed: Unity archive files -- .forge & .data (compressed and decompressed) -- |
|
| Assassin's Creed: Unity | | [`patterns/AC Unity`](patterns/Assassin's Creed: Unity) | Assassin's Creed: Unity archive files -- .forge & .data (compressed and decompressed) -- |
|
||||||
| Bastion | | [`patterns/bastion/*`](https://gitlab.com/EvelynTSMG/imhex-bastion-pats) | Various [Bastion](https://en.wikipedia.org/wiki/Bastion_(video_game)) files |
|
| Bastion | | [`patterns/bastion/*`](https://gitlab.com/EvelynTSMG/imhex-bastion-pats) | Various [Bastion](https://en.wikipedia.org/wiki/Bastion_(video_game)) files |
|
||||||
| BeyondCompare BCSS | | [`patterns/bcss.hexpat`](patterns/bcss.hexpat) | BeyondCompare Snapshot (BCSS) file |
|
| BeyondCompare BCSS | | [`patterns/bcss.hexpat`](patterns/bcss.hexpat) | BeyondCompare Snapshot (BCSS) file |
|
||||||
|
|||||||
@@ -13,3 +13,13 @@
|
|||||||
>0 leshort 0x1555 RGBA5 format
|
>0 leshort 0x1555 RGBA5 format
|
||||||
>0 leshort 0x8888 RGBA8 format
|
>0 leshort 0x8888 RGBA8 format
|
||||||
>0 leshort 0x8080 Grayscale format
|
>0 leshort 0x8080 Grayscale format
|
||||||
|
|
||||||
|
# Arma 3 RTM animation
|
||||||
|
0 string RTM_ Arma 3 RTM animation file (plain)
|
||||||
|
!:mime application/x.a3-rtm
|
||||||
|
!:ext rtm
|
||||||
|
|
||||||
|
# Arma 3 binarized RTM animation
|
||||||
|
0 string BMTR Arma 3 binarized RTM animation file
|
||||||
|
!:mime application/x.a3-bmtr
|
||||||
|
!:ext rtm
|
||||||
|
|||||||
129
patterns/a3_bmtr.hexpat
Normal file
129
patterns/a3_bmtr.hexpat
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#pragma author MrClock
|
||||||
|
#pragma description Arma 3 RTM animation format (binarized)
|
||||||
|
|
||||||
|
#pragma endian little
|
||||||
|
|
||||||
|
#pragma MIME application/x.a3-bmtr
|
||||||
|
|
||||||
|
fn get_data_description() {
|
||||||
|
return "Binarized RTM (BMTR) animation files are the PBO packed versions of plain RTMs.\n Binarized files are optimized for use by the game engine, and they are not editable.\nBone transformations are stored as relative quaternion-vector pairs.\nData blocks are conditionally LZO1X compressed (these are not supported by this pattern).";
|
||||||
|
};
|
||||||
|
|
||||||
|
import std.string;
|
||||||
|
import std.sys;
|
||||||
|
import type.float16;
|
||||||
|
|
||||||
|
using asciiz = std::string::NullString [[format("formatAsciiz")]];
|
||||||
|
using half = type::float16 ;
|
||||||
|
struct s16float {
|
||||||
|
s16 data;
|
||||||
|
} [[sealed,static,transform("transforms16float"), format("transforms16float")]];
|
||||||
|
|
||||||
|
struct Property {
|
||||||
|
padding[4];
|
||||||
|
asciiz name;
|
||||||
|
float phase;
|
||||||
|
asciiz value;
|
||||||
|
} [[format("formatProperty")]];
|
||||||
|
|
||||||
|
struct Vector<DataType> {
|
||||||
|
DataType x [[comment("+Left/-Right")]];
|
||||||
|
DataType y [[comment("+Up/-Down (UNUSED)")]];
|
||||||
|
DataType z [[comment("+Forward/-Backward")]];
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct Quaternion {
|
||||||
|
s16float x;
|
||||||
|
s16float y;
|
||||||
|
s16float z;
|
||||||
|
s16float w;
|
||||||
|
} [[static,format("formatQuaternion")]];
|
||||||
|
|
||||||
|
struct Transform {
|
||||||
|
Quaternion orientation;
|
||||||
|
Vector<half> position [[format("formatVectorHalf")]];
|
||||||
|
} [[static]];
|
||||||
|
|
||||||
|
struct Frame {
|
||||||
|
u32 count_bones;
|
||||||
|
bool compressed = count_bones * sizeof(Transform) >= 1024;
|
||||||
|
if (parent.version > 4) {
|
||||||
|
u8 lzo_flag;
|
||||||
|
compressed = lzo_flag > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compressed) {
|
||||||
|
std::error("Transformations are LZO compressed and compressed length is unknown");
|
||||||
|
} else {
|
||||||
|
Transform transforms[count_bones];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BMTR {
|
||||||
|
char signature[4];
|
||||||
|
u32 version;
|
||||||
|
padding[1];
|
||||||
|
Vector<float> motion [[format("formatVectorFloat")]];
|
||||||
|
u32 count_frames;
|
||||||
|
padding[4];
|
||||||
|
u32 count_bones;
|
||||||
|
u32 count_bones_again;
|
||||||
|
|
||||||
|
std::assert_warn(count_bones == count_bones_again, "Mismatch between bone counts");
|
||||||
|
|
||||||
|
asciiz bones[count_bones];
|
||||||
|
|
||||||
|
if (version >= 4) {
|
||||||
|
padding[4];
|
||||||
|
u32 count_properties;
|
||||||
|
Property properties[count_properties];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 count_phases;
|
||||||
|
std::assert_warn(count_frames == count_phases, "Frame and phase counts do not match");
|
||||||
|
|
||||||
|
bool compressed = count_phases * sizeof(float) >= 1024;
|
||||||
|
if (version > 4) {
|
||||||
|
u8 lzo_flag;
|
||||||
|
compressed = lzo_flag > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compressed) {
|
||||||
|
std::error("Phases are LZO compressed and compressed length is unknown");
|
||||||
|
} else {
|
||||||
|
float phases[count_phases];
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame frames[count_frames];
|
||||||
|
};
|
||||||
|
|
||||||
|
fn transforms16float(ref s16float value) {
|
||||||
|
return float(value.data) / 16384;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatAsciiz(ref asciiz value) {
|
||||||
|
return std::format("\"{:s}\"", value);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatProperty(ref Property prop) {
|
||||||
|
return std::format("\"{0:s}\" = \"{1:s}\" @ {2:.4f}", prop.name, prop.value, prop.phase);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatVectorHalf(ref Vector<half> vec) {
|
||||||
|
return std::format(
|
||||||
|
"[{0}, {1}, {2}]",
|
||||||
|
type::impl::format_float16(vec.x),
|
||||||
|
type::impl::format_float16(vec.y),
|
||||||
|
type::impl::format_float16(vec.z)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatVectorFloat(ref Vector<float> vec) {
|
||||||
|
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}]", vec.x, vec.y, vec.z);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatQuaternion(ref Quaternion q) {
|
||||||
|
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}, {3:.2f}]", q.x, q.y, q.z, q.w);
|
||||||
|
};
|
||||||
|
|
||||||
|
BMTR file @ 0x0000;
|
||||||
93
patterns/a3_rtm.hexpat
Normal file
93
patterns/a3_rtm.hexpat
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#pragma author MrClock
|
||||||
|
#pragma description Arma 3 RTM animation format (plain)
|
||||||
|
|
||||||
|
#pragma endian little
|
||||||
|
|
||||||
|
#pragma MIME application/x.a3-rtm
|
||||||
|
|
||||||
|
fn get_data_description() {
|
||||||
|
return "Plain RTM animation files are used in animation authoring for Arma 3.\nThey can be created and edited in Object Builder.\nBone transformations are stored as absolute transformation matrices.\nPlain RTMs must be converted to their \"binarized\" versions by an appropriate PBO packing tool for use in game.";
|
||||||
|
};
|
||||||
|
|
||||||
|
import std.mem;
|
||||||
|
import std.sys;
|
||||||
|
import std.string;
|
||||||
|
import std.io;
|
||||||
|
|
||||||
|
using lascii = std::string::SizedString<u8> [[format("formatLascii")]];
|
||||||
|
|
||||||
|
struct Property {
|
||||||
|
float phase;
|
||||||
|
lascii name;
|
||||||
|
lascii value;
|
||||||
|
} [[format("formatProperty")]];
|
||||||
|
|
||||||
|
struct Bone {
|
||||||
|
char name[32];
|
||||||
|
} [[sealed,static,transform("transformBone"),format("formatBone")]];
|
||||||
|
|
||||||
|
struct Transform {
|
||||||
|
Bone bone;
|
||||||
|
float matrix[12] [[comment("4x4 transformation matrix (with last row omitted)")]];
|
||||||
|
} [[static,format("formatTransform")]];
|
||||||
|
|
||||||
|
struct Frame {
|
||||||
|
float phase;
|
||||||
|
Transform transforms[parent.count_bones];
|
||||||
|
} [[static,format("formatFrame")]];
|
||||||
|
|
||||||
|
struct Vector {
|
||||||
|
float x [[comment("+Left/-Right")]];
|
||||||
|
float y [[comment("+Up/-Down (UNUSED)")]];
|
||||||
|
float z [[comment("+Forward/-Backward")]];
|
||||||
|
} [[static,format("formatVector")]];
|
||||||
|
|
||||||
|
struct RTM {
|
||||||
|
if (std::mem::read_string($, 8) == "RTM_MDAT") {
|
||||||
|
char properties_signature[8];
|
||||||
|
padding[4];
|
||||||
|
u32 count_properties;
|
||||||
|
Property properties[count_properties];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::assert(std::mem::read_string($, 8) == "RTM_0101", "Missing animation data");
|
||||||
|
|
||||||
|
char animation_signature[8];
|
||||||
|
Vector motion;
|
||||||
|
u32 count_frames;
|
||||||
|
u32 count_bones;
|
||||||
|
Bone bones[count_bones];
|
||||||
|
Frame frames[count_frames];
|
||||||
|
|
||||||
|
std::assert_warn(std::mem::eof(), "Data ended before EOF");
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatLascii(ref lascii value) {
|
||||||
|
return std::format("\"{:s}\"", value);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatProperty(ref Property prop) {
|
||||||
|
return std::format("\"{0:s}\" = \"{1:s}\" @ {2:.4f}", prop.name, prop.value, prop.phase);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn transformBone(ref Bone value) {
|
||||||
|
return std::string::to_string(value.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatBone(ref Bone value) {
|
||||||
|
return std::format("\"{0:s}\"", value);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatTransform(ref Transform transform) {
|
||||||
|
return std::format("\"{0:s}\" transform", transform.bone);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatFrame(ref Frame frame) {
|
||||||
|
return std::format("frame @ {0:.4f}", frame.phase);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatVector(ref Vector vec) {
|
||||||
|
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}]", vec.x, vec.y, vec.z);
|
||||||
|
};
|
||||||
|
|
||||||
|
RTM file @ 0x0000;
|
||||||
BIN
tests/patterns/test_data/a3_bmtr.hexpat.rtm
Normal file
BIN
tests/patterns/test_data/a3_bmtr.hexpat.rtm
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 247 B |
BIN
tests/patterns/test_data/a3_rtm.hexpat.rtm
Normal file
BIN
tests/patterns/test_data/a3_rtm.hexpat.rtm
Normal file
Binary file not shown.
Reference in New Issue
Block a user