mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
* patterns/texheaders: Added pattern for Arma 3 texHeaders.bin * magic/arma3: Added texHeaders.bin magic * patterns/texheaders: Added test file * patterns/paa: Small improvements Added extra data description, and better indication of internally compressed data mipmap data. * patterns/a3: Moved Arma 3 patterns into common folder * patterns/a3: Added pattern for MLOD P3D * patterns/a3: Added pattern for RAP * magic/arma3: Added P3D and RAP to magic file * patterns/a3: Added test files for P3D and RAP * patterns/a3: Small correction to type names in TexHeaders format
166 lines
4.2 KiB
Rust
166 lines
4.2 KiB
Rust
#pragma author MrClock
|
|
#pragma description Arma 3 binary configuration format
|
|
|
|
#pragma endian little
|
|
|
|
#pragma MIME application/x.a3-rap
|
|
|
|
fn get_data_description() {
|
|
return "The RAP format is the binarized/\"rapified\" version of configuration files for Arma 3. Plain text configuration, material definition, scenario description and other files using the configuration syntax are rapified during the PBO packing process. The game can work with the plain text versions (they are actually rapified during boot), but properly converting them into the binary format ahead of time makes the booting easier.";
|
|
};
|
|
|
|
import std.mem;
|
|
import std.string;
|
|
import std.core;
|
|
import std.io;
|
|
|
|
using asciiz = std::string::NullString [[format("formatAsciiz")]];
|
|
|
|
/*
|
|
Item counts are stored in 7-bit encoded integers. In each byte the top bit signals
|
|
if the next byte belongs to the number as well.
|
|
*/
|
|
struct CompressedUint {
|
|
u8 extras[while(std::mem::read_unsigned($, 1) & 0x80)];
|
|
u8 last;
|
|
} [[sealed,transform("transformCompressedUint"),format("formatCompressedUint")]];
|
|
|
|
enum MemberType: u8 {
|
|
CLASS = 0,
|
|
LITERAL = 1,
|
|
ARRAY = 2,
|
|
EXTERNAL = 3,
|
|
DELETE = 4,
|
|
ARRAY_EXTENSION = 5
|
|
};
|
|
|
|
enum ValueType: u8 {
|
|
STRING = 0,
|
|
FLOAT = 1,
|
|
INTEGER = 2,
|
|
ARRAY = 3,
|
|
VARIABLE = 4
|
|
};
|
|
|
|
using Array;
|
|
|
|
struct ArrayItem {
|
|
ValueType type;
|
|
match (type) {
|
|
(ValueType::STRING): asciiz value;
|
|
(ValueType::FLOAT): float value;
|
|
(ValueType::INTEGER): s32 value;
|
|
(ValueType::ARRAY): Array value;
|
|
(ValueType::VARIABLE): asciiz value;
|
|
}
|
|
} [[format("formatArrayItem")]];
|
|
|
|
struct Array {
|
|
CompressedUint count_items;
|
|
ArrayItem items[count_items];
|
|
} [[format("formatArray")]];
|
|
|
|
using ClassBody;
|
|
|
|
struct Member {
|
|
MemberType type;
|
|
|
|
match(type) {
|
|
(MemberType::CLASS): {
|
|
asciiz name;
|
|
ClassBody *body : u32;
|
|
}
|
|
(MemberType::LITERAL): {
|
|
ValueType subtype;
|
|
asciiz name;
|
|
match (subtype) {
|
|
(ValueType::STRING): asciiz value;
|
|
(ValueType::FLOAT): float value;
|
|
(ValueType::INTEGER): s32 value;
|
|
(_): std::error(std::format("Unexpected subtype for literal: {}", subtype));
|
|
}
|
|
}
|
|
(MemberType::ARRAY | MemberType::ARRAY_EXTENSION): {
|
|
asciiz name;
|
|
Array value;
|
|
}
|
|
(MemberType::EXTERNAL): {
|
|
asciiz name;
|
|
}
|
|
(MemberType::DELETE): {
|
|
asciiz name;
|
|
}
|
|
}
|
|
} [[format("formatMember")]];
|
|
|
|
using Enums;
|
|
|
|
struct ClassBody {
|
|
asciiz parent_name;
|
|
CompressedUint count_members;
|
|
|
|
Member members[count_members];
|
|
u8 *pointer : u32 [[comment("In the root body this points to the enum list.\nIn all others it points to the next body on the same level.")]];
|
|
};
|
|
|
|
struct EnumItem {
|
|
asciiz name;
|
|
s32 value;
|
|
} [[format("formatEnumItem")]];
|
|
|
|
struct Enums {
|
|
u32 count_items;
|
|
EnumItem items[count_items];
|
|
};
|
|
|
|
struct RAP {
|
|
char signature[4];
|
|
u32;
|
|
u32;
|
|
Enums *enums : u32;
|
|
ClassBody root;
|
|
};
|
|
|
|
fn formatAsciiz(ref asciiz value) {
|
|
return std::format("\"{0:s}\"", value);
|
|
};
|
|
|
|
fn transformCompressedUint(ref CompressedUint value) {
|
|
u64 result = 0;
|
|
for (u8 i = 0, i < sizeof(value.extras), i += 1) {
|
|
result += (value.extras[i] & 0x7F) << (7*i);
|
|
}
|
|
|
|
result += value.last << (sizeof(value.extras) * 7);
|
|
|
|
return result;
|
|
};
|
|
|
|
fn formatCompressedUint(ref CompressedUint value) {
|
|
return value;
|
|
};
|
|
|
|
fn formatArrayItem(ref ArrayItem value) {
|
|
return value.value;
|
|
};
|
|
|
|
fn formatArray(ref Array value) {
|
|
return "{...}";
|
|
};
|
|
|
|
fn formatMember(ref Member item) {
|
|
match (item.type) {
|
|
(MemberType::CLASS): return std::format("class {0:s} {{...}};", item.name);
|
|
(MemberType::LITERAL): return std::format("{0:s} = {1};", item.name, item.value);
|
|
(MemberType::ARRAY): return std::format("{0:s}[] = {{...}};", item.name);
|
|
(MemberType::EXTERNAL): return std::format("class {0:s};", item.name);
|
|
(MemberType::DELETE): return std::format("del {0:s};", item.name);
|
|
}
|
|
};
|
|
|
|
fn formatEnumItem(ref EnumItem value) {
|
|
return std::format("{0:s} = {1}", item.name, item.value);
|
|
};
|
|
|
|
RAP file @ 0x0000;
|