forked from WerWolv/ImHex-Patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
patterns: Added pattern for ID3 tags (WerWolv#48)
* Add naive first implementation of ID3 patterns * Refine string handling a bit * Optimize structs using the static keyword * Add MIME type pragma and update README
- Loading branch information
1 parent
665c50b
commit 6cb208d
Showing
2 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
#pragma MIME audio/mpeg | ||
|
||
#include <std/mem.pat> | ||
|
||
namespace v1 { | ||
|
||
struct Tag { | ||
char header[3]; | ||
char title[30]; | ||
char artist[30]; | ||
char album[30]; | ||
char year[4]; | ||
char comment[30]; | ||
u8 zero; | ||
u8 track; | ||
u8 genre; | ||
} [[static]]; | ||
|
||
} | ||
|
||
namespace v2 { | ||
|
||
struct SyncSafeInt { | ||
u8 bytes[4]; | ||
} [[sealed, static, format("v2::ssi_value"), transform("v2::ssi_value")]]; | ||
|
||
fn ssi_value(ref SyncSafeInt n) { | ||
u32 result = 0; | ||
for (u8 i = 0, i < 4, i = i + 1) { | ||
u8 byteval = n.bytes[i] & 0x7F; | ||
u8 shift = 7 * (4 - i - 1); | ||
result = result | (byteval << shift); | ||
} | ||
return result; | ||
}; | ||
|
||
struct TagVersion { | ||
u8 major; | ||
u8 revision; | ||
}; | ||
|
||
bitfield TagHeaderFlags { | ||
unsynchronized : 1; | ||
extended : 1; | ||
experimental : 1; | ||
footer : 1; | ||
padding : 4; | ||
}; | ||
|
||
struct TagHeader { | ||
char identifier[3]; | ||
TagVersion version; | ||
TagHeaderFlags flags; | ||
SyncSafeInt size; | ||
} [[static]]; | ||
|
||
bitfield ExtendedFlag { | ||
padding : 1; | ||
update : 1; | ||
crcpresent : 1; | ||
restrictions : 1; | ||
padding : 4; | ||
}; | ||
|
||
struct TagExtendedHeader { | ||
SyncSafeInt size; | ||
u8 nflagbytes; | ||
ExtendedFlag flags[nflagbytes]; | ||
u8 data[size]; | ||
}; | ||
|
||
struct TagFooter { | ||
char identifier[3]; | ||
TagVersion version; | ||
TagHeaderFlags flags; | ||
SyncSafeInt size; | ||
} [[static]]; | ||
|
||
bitfield FrameFlags { | ||
padding : 1; | ||
tagalterpreservation : 1; | ||
filealterpreservation : 1; | ||
readonly : 1; | ||
padding : 5; | ||
groupid : 1; | ||
padding : 2; | ||
compressed : 1; | ||
encrypted : 1; | ||
unzynchronized : 1; | ||
datalengthindicator : 1; | ||
}; | ||
|
||
enum TextEncoding : u8 { | ||
ISO88591 = 0x00, | ||
UTF16BOM = 0x01, | ||
UTF16BE = 0x02, | ||
UTF8 = 0x03, | ||
}; | ||
|
||
struct StringData { | ||
TextEncoding encoding; | ||
if (encoding == TextEncoding::UTF16BOM) { | ||
u16 bom; | ||
char16 data[(parent.size - 3) / 2]; | ||
} else if (encoding == TextEncoding::UTF16BE) | ||
be char16 data[(parent.size - 1) / 2]; | ||
else | ||
char data[parent.size - 1]; | ||
}; | ||
|
||
// Hack to work around the fact, that chars may not be compared | ||
union FrameId { | ||
char cdata[4]; | ||
u8 ndata[4]; | ||
} [[sealed, static, format("v2::impl::format_frame_id")]]; | ||
|
||
namespace impl { | ||
|
||
fn format_frame_id(ref FrameId id) { | ||
return id.cdata; | ||
}; | ||
|
||
} | ||
|
||
struct Frame { | ||
FrameId id; | ||
SyncSafeInt size; | ||
FrameFlags flags; | ||
if (id.ndata[0] == 'T') | ||
StringData data; | ||
else | ||
u8 data[size]; | ||
}; | ||
|
||
fn has_next_frame(u32 size) { | ||
bool hasnext = $ < size; | ||
if (hasnext) { | ||
hasnext = std::mem::read_unsigned($, 1) != 0; | ||
$ = $ - 1; | ||
} | ||
return hasnext; | ||
}; | ||
|
||
struct Tag { | ||
TagHeader header; | ||
if (header.flags.extended) | ||
TagExtendedHeader extendedheader; | ||
Frame frames[while(v2::has_next_frame(header.size))]; | ||
if (header.flags.footer) | ||
TagFooter footer; | ||
}; | ||
|
||
} | ||
|
||
v2::Tag tag @ 0; | ||
v1::Tag oldtag @ std::mem::size() - 128; |