diff --git a/README.md b/README.md index d4b67d4c..89ee9a1a 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files | | mp4 | `video/mp4` | [`patterns/mp4.hexpat`](patterns/mp4.hexpat) | MPEG-4 Part 14 digital multimedia container format | | msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format | +| MSSCMP | | [`patterns/msscmp.hexpat`](patterns/msscmp.hexpat) | Miles Sound System Compressed Archive | | NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files | | NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format | | NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields | diff --git a/patterns/msscmp.hexpat b/patterns/msscmp.hexpat new file mode 100644 index 00000000..81d354f0 --- /dev/null +++ b/patterns/msscmp.hexpat @@ -0,0 +1,85 @@ +#pragma author DexrnZacAttack +#pragma description MSSCMP (Miles Sound System Compressed Archive) +#pragma magic [ 42 41 4E 4B ] @ 0x00 +#pragma magic [ 4B 4E 41 42 ] @ 0x00 +#pragma array_limit 4294967295 +#pragma pattern_limit 4294967295 + +import type.magic; +import std.core; +#ifdef __IMHEX__ + import hex.core; +#endif + +struct FileDataEntry { + u32 nameOffset; + char name[] @ nameOffset; + u32 folderOffset; + char folder[] @ folderOffset; + le u32 fileDataOffset; + padding[8]; + u32 sampleRate; + u32 fileSize; + u8 data[fileSize] @ fileDataOffset; + #ifdef __IMHEX__ + hex::core::add_virtual_file(std::string::to_string(name) + ".binka", data); + #endif +}; + +struct Index2Entry { + u32 entryOffset; + u32 fStructureOffset; + FileDataEntry fileDataEntry @ entryOffset; +}; + +struct MsscmpEntry { + char name[12]; + Index2Entry entries[parent.header.index2EntryCount] @ parent.header.index1LastEntryOffset + 4; +}; + + +struct Header { + padding[4]; // unk + T fileDataOffset; + padding[8]; // unk + T index1Offset; + T index1LastEntryOffset; + if (sizeof(T) == 4) + padding[8]; + else + padding[16]; + + T unkOffset; + T index1EntryCount; + + if (sizeof(T) == 4) + padding[8]; + else + padding[4]; + + u32 index2EntryCount; +}; + +using OldGenHeader = Header; +using NewGenHeader = Header; + +struct MSSCMP { + char magic[4]; + if (magic == "BANK") + std::core::set_endian(std::mem::Endian::Big); + else if (magic == "KNAB") + std::core::set_endian(std::mem::Endian::Little); + else + std::error("Magic does not match BANK or KNAB"); + + u32 check1 @ 0x1c [[hidden]]; // use this to check if old gen or new gen + u32 check2 @ 0x20 [[hidden]]; + + if (check1 == check2) + OldGenHeader header; + else + NewGenHeader header; + MsscmpEntry entry; +}; + +MSSCMP msscmp @ 0x00;