mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Add ADTFDAT pattern (#368)
This commit is contained in:
@@ -25,6 +25,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
|------|------|------|-------------|
|
||||
| 3DS | | [`patterns/3ds.hexpat`](patterns/3ds.hexpat) | Autodesk 3DS Max Model file |
|
||||
| 7Z | | [`patterns/7z.hexpat`](patterns/7z.hexpat) | 7z File Format |
|
||||
| ADTFDAT | | [`patterns/adtfdat.hexpat`](patterns/adtfdat.hexpat) | [ADTFDAT files](https://digitalwerk.gitlab.io/solutions/adtf_content/adtf_base/adtf_file_library) |
|
||||
| ADTS | `audio/x-hx-aac-adts` | [`patterns/adts.hexpat`](patterns/adts.hexpat) | ADTS/AAC audio files |
|
||||
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
|
||||
| ANI | `application/x-navi-animation` | [`patterns/ani.hexpat`](patterns/ani.hexpat) | Windows Animated Cursor file |
|
||||
|
||||
176
patterns/adtfdat.hexpat
Normal file
176
patterns/adtfdat.hexpat
Normal file
@@ -0,0 +1,176 @@
|
||||
#pragma description ADTFDAT File
|
||||
|
||||
#pragma magic [ 49 46 48 44 ] @ 0x00
|
||||
#pragma endian little
|
||||
|
||||
import std.io;
|
||||
import std.mem;
|
||||
import type.time;
|
||||
|
||||
enum FileVersion : u32 {
|
||||
with_history_end_offset = 0x00000301,
|
||||
v500 = 0x00000500
|
||||
};
|
||||
|
||||
bitfield ChunkFlags {
|
||||
key : 1;
|
||||
info : 1;
|
||||
marker : 1;
|
||||
type : 1;
|
||||
trigger : 1;
|
||||
reserved: 11;
|
||||
};
|
||||
|
||||
struct Extension
|
||||
{
|
||||
char identifier[384];
|
||||
u16 stream_id;
|
||||
u8 reserved1[2];
|
||||
u32 user_id;
|
||||
u32 type_id;
|
||||
u32 version_id;
|
||||
u64 data_pos;
|
||||
u64 data_size;
|
||||
u8 reserved[96];
|
||||
u8 payload[data_size] @ data_pos;
|
||||
};
|
||||
|
||||
struct ChunkHeader {
|
||||
u64 time_stamp [[format("format_timestamp_with_offset")]];;
|
||||
u32 ref_master_table_index;
|
||||
u32 offset_to_last;
|
||||
u32 size;
|
||||
u16 stream_id;
|
||||
ChunkFlags flags;
|
||||
u64 stream_index;
|
||||
};
|
||||
|
||||
struct SampleInfo {
|
||||
u8 memory_layout_version;
|
||||
u32 size;
|
||||
u8 payload[size];
|
||||
};
|
||||
|
||||
struct Sample {
|
||||
s64 timestamp [[format("format_timestamp")]];;
|
||||
s32 flags;
|
||||
u64 buffer_size;
|
||||
u8 payload[buffer_size];
|
||||
if (flags & 0x100) {
|
||||
SampleInfo sample_info;
|
||||
}
|
||||
if (flags & 0x200) {
|
||||
u32 substream_id;
|
||||
} else {
|
||||
u32 substream_id = 0 [[export]];
|
||||
}
|
||||
};
|
||||
|
||||
struct Chunk {
|
||||
auto start_address = $;
|
||||
|
||||
ChunkHeader header;
|
||||
|
||||
if (header.size < 32 || start_address + header.size > std::mem::size()) {
|
||||
std::warning(std::format("Invalid header size {} in chunk {} at offset 0x{:X}, last valid chunk at 0x{:X}.", header.size, chunk_index, start_address, last_valid_chunk_offset));
|
||||
break;
|
||||
}
|
||||
|
||||
last_valid_chunk_offset = start_address;
|
||||
|
||||
u8 payload[header.size - 32];
|
||||
|
||||
if (!skip_valid_chunks) {
|
||||
if (!header.flags.info && !header.flags.marker && !header.flags.type && !header.flags.trigger) {
|
||||
try {
|
||||
Sample sample @ addressof(payload);
|
||||
} catch {
|
||||
std::warning(std::format("Invalid sample payload at chunk {} at 0x{:X}", chunk_index, start_address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chunk_index += 1;
|
||||
|
||||
// Padding with 0xEE to the next chunk header
|
||||
std::mem::AlignTo<16>;
|
||||
|
||||
if (skip_valid_chunks) {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
struct Header {
|
||||
u32 file_id;
|
||||
u32 version_id;
|
||||
u32 flags;
|
||||
u32 extension_count;
|
||||
u64 extension_offset;
|
||||
u64 data_offset;
|
||||
u64 data_size;
|
||||
u64 chunk_count;
|
||||
u64 max_chunk_size;
|
||||
u64 duration;
|
||||
type::time64_t filetime;
|
||||
u8 header_byte_order;
|
||||
u64 time_offset [[format("format_timestamp")]];
|
||||
u8 patch_number;
|
||||
u64 first_chunk_offset;
|
||||
u64 continuous_offset;
|
||||
u64 ring_buffer_end_offset;
|
||||
u8 reserved[30];
|
||||
char description[1912];
|
||||
};
|
||||
|
||||
struct IndexedFile {
|
||||
Header header;
|
||||
Extension extensions[header.extension_count] @ header.extension_offset;
|
||||
|
||||
if (header.version_id >= FileVersion::with_history_end_offset &&
|
||||
header.continuous_offset != header.data_offset) {
|
||||
try {
|
||||
Chunk ring_front[while($ < header.continuous_offset)] @ header.first_chunk_offset;
|
||||
Chunk ring_back[while($ < header.ring_buffer_end_offset)] @ header.data_offset;
|
||||
Chunk continueous[header.chunk_count - chunk_index] @ header.continuous_offset;
|
||||
} catch {
|
||||
std::warning("Too many chunks. Performing check only.");
|
||||
skip_valid_chunks = true;
|
||||
chunk_index = 0;
|
||||
Chunk ring_front[while($ < header.continuous_offset)] @ header.first_chunk_offset;
|
||||
Chunk ring_back[while($ < header.ring_buffer_end_offset)] @ header.data_offset;
|
||||
Chunk continueous[while(chunk_index < header.chunk_count)] @ header.continuous_offset;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Chunk chunks[header.chunk_count] @ header.data_offset;
|
||||
} catch {
|
||||
std::warning("Too many chunks. Performing check only.");
|
||||
skip_valid_chunks = true;
|
||||
chunk_index = 0;
|
||||
Chunk chunks[while(chunk_index < header.chunk_count)] @ header.data_offset;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn format_timestamp(u64 data) {
|
||||
double seconds = 0;
|
||||
if (file.header.version_id < FileVersion::v500) {
|
||||
// microseconds
|
||||
seconds = data / double(1000000);
|
||||
} else {
|
||||
// nanoseconds
|
||||
seconds = data / double(1000000000);
|
||||
}
|
||||
|
||||
std::time::Time time64 = std::time::to_utc(seconds);
|
||||
return std::time::format(time64);
|
||||
};
|
||||
|
||||
fn format_timestamp_with_offset(u64 data) {
|
||||
return format_timestamp(data + file.header.time_offset);
|
||||
};
|
||||
|
||||
bool skip_valid_chunks = false;
|
||||
u64 last_valid_chunk_offset = 0;
|
||||
u64 chunk_index = 0;
|
||||
IndexedFile file @ 0x00;
|
||||
BIN
tests/patterns/test_data/adtfdat.hexpat.adtfdat
Normal file
BIN
tests/patterns/test_data/adtfdat.hexpat.adtfdat
Normal file
Binary file not shown.
Reference in New Issue
Block a user