[Scummvm-git-logs] scummvm-tools master -> ab94ef33f00aeac77443df3c0deadfeb6687fa96
sev-
noreply at scummvm.org
Sat Aug 12 23:02:04 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm-tools' repo located at https://github.com/scummvm/scummvm-tools .
Summary:
ab94ef33f0 TOOLS: Added qtvr.hexpat for parseing QTVR files in ImHex to engines/director
Commit: ab94ef33f00aeac77443df3c0deadfeb6687fa96
https://github.com/scummvm/scummvm-tools/commit/ab94ef33f00aeac77443df3c0deadfeb6687fa96
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-08-13T01:00:40+02:00
Commit Message:
TOOLS: Added qtvr.hexpat for parseing QTVR files in ImHex to engines/director
Changed paths:
A engines/director/qtvr.hexpat
diff --git a/engines/director/qtvr.hexpat b/engines/director/qtvr.hexpat
new file mode 100644
index 00000000..1a0d40cd
--- /dev/null
+++ b/engines/director/qtvr.hexpat
@@ -0,0 +1,693 @@
+#pragma endian big
+
+
+#include <std/core.pat>
+#include <std/fxpt.pat>
+#include <std/io.pat>
+#include <std/math.pat>
+#include <std/mem.pat>
+#include <std/string.pat>
+#include <std/time.pat>
+#include <type/byte.pat>
+#include <type/guid.pat>
+#include <type/size.pat>
+
+#define MIN_BOX_SIZE 8
+
+fn contents_size(u128 base_offset, u64 size) {
+ s128 end = size == 0 ? std::mem::size() : base_offset + size;
+ end = std::math::min(end, std::mem::size());
+ s128 offset_signed = $;
+ return end - offset_signed;
+};
+
+
+struct Atom {
+ type::Size32 box_size;
+ char box_type[4];
+
+ if (box_size == 1) {
+ type::Size64 box_size;
+ }
+};
+
+struct FullAtom : Atom {
+ u8 version;
+ u24 flags;
+};
+
+fn to_float(auto value) {
+ return std::string::parse_float(std::string::to_string(value));
+};
+fn format_fixed(u32 value, u32 precision) {
+ // double cast is broken it seems
+ return to_float(value) + to_float(1 << precision);
+};
+
+fn format_fixed_signed(s32 value, u32 precision) {
+ float val = value >> precision;
+ s32 second_val = value & ( 1 << precision - 1);
+ float comma = second_val / ( 1 << precision + 1);
+ return val + comma;
+};
+
+using fixed_s32 = s32 [[format("format_fixed_signed_32")]];
+using fixed_u32 = u32 [[format("format_fixed_32")]];
+fn format_fixed_signed_32(s32 value) {
+ return format_fixed_signed(value, 16);
+};
+fn format_fixed_32(s32 value) {
+ return format_fixed(value, 16);
+};
+
+using fixed_s16 = s16 [[format("format_fixed_16")]];
+fn format_fixed_16(u16 value) {
+ return format_fixed(value, 8);
+};
+using normal_s32 = s32 [[format("format_normal_32")]];
+fn format_normal_32(auto value) {
+ return format_fixed(value, 30);
+};
+
+struct Matrix {
+ fixed_s32 matrix_00;
+ fixed_s32 matrix_01;
+ fixed_s32 matrix_02;
+ fixed_s32 matrix_10;
+ fixed_s32 matrix_11;
+ fixed_s32 matrix_12;
+ normal_s32 matrix_20;
+ normal_s32 matrix_21;
+ normal_s32 matrix_22;
+} [[format("format_matrix")]];
+
+fn format_matrix(auto matrix) {
+ return std::format("[ [ {}, {}, {} ], [ {}, {}, {} ], [ {}, {}, {} ] ]",
+ format_fixed_32(matrix.matrix_00), format_fixed_32(matrix.matrix_01), format_fixed_32(matrix.matrix_02),
+ format_fixed_32(matrix.matrix_10), format_fixed_32(matrix.matrix_11), format_fixed_32(matrix.matrix_12),
+ format_normal_32(matrix.matrix_20), format_normal_32(matrix.matrix_21), format_normal_32(matrix.matrix_22));
+};
+
+using UnknownAtom;
+
+struct CTYPAtom : Atom {
+ char id[4];
+};
+
+// moov -> udta
+struct UserDataChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("ctyp"): CTYPAtom ctyp;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+} [[inline]];
+
+
+struct UserDataAtom : Atom {
+ UserDataChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+
+ // handle optional padding
+ // ToDo? improve it?
+ u128 current_pos = $;
+ u32 trailingZero @ $;
+ $ = current_pos;
+
+ $ += contents_size(addressof(this), box_size);
+};
+
+
+fn appears_to_contain_boxes(ref u128 contents_offset, u128 contents_size) {
+ u128 current_offset = contents_offset;
+ while (true) {
+ u32 current_size_raw @ current_offset;
+ u32 current_size = be u32(current_size_raw);
+ current_offset += current_size;
+ if (current_offset == contents_offset || current_offset >= (contents_offset + contents_size)) {
+ break;
+ }
+ }
+ return current_offset == (contents_offset + contents_size);
+};
+
+struct UnknownAtomSelector {
+ Atom atom_header [[hidden]];
+ $ = addressof(this);
+ UnknownAtom unknown [[name(atom_header.box_type)]];
+ std::print("unkown: " + atom_header.box_type);
+} [[inline]];
+
+struct UnknownAtom : Atom {
+ if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
+ UnknownAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE && std::mem::size() - $ > MIN_BOX_SIZE)];
+ } else {
+ $ += sizeof(u32);
+ if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
+ $ -= sizeof(u32);
+ u8 version;
+ u24 flags;
+ UnknownAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE && std::mem::size() - $ > MIN_BOX_SIZE)];
+ } else {
+ $ -= sizeof(u32);
+ }
+ }
+ u128 next_offset = std::math::min($ + contents_size(addressof(this), box_size), std::mem::size());
+ if (next_offset > $) {
+ u8 unknown_data[next_offset - $] [[sealed]];
+ } else {
+ $ = next_offset;
+ }
+ std::print("unkown atom: {}: {}", box_type, $);
+} [[format("format_box_type")]];
+
+fn format_box_type(auto box) {
+ return box.box_type;
+};
+
+// original has formatting
+// original parses times as datetimes
+
+struct MovieHeaderAtom : FullAtom {
+ u32 creation_time;
+ u32 modification_time;
+ u32 timescale;
+ u32 duration;
+ fixed_s32 rate;
+ fixed_s16 volume;
+ padding[10];
+ Matrix matrix;
+ u32 preview_time;
+ u32 preview_duration;
+ u32 poster_time;
+ u32 selection_time;
+ u32 selection_duration;
+ u32 current_time;
+ u32 next_track_id;
+}[[format("format_mvhd")]];
+
+struct TrackHeaderAtom : FullAtom {
+ u32 creation_time;
+ u32 modification_time;
+ u32 track_id;
+ padding[sizeof(u32)];
+ u32 duration;
+ padding[sizeof(u32) * 2];
+ s16 layer;
+ u16 alternate_group;
+ fixed_s16 volume;
+ padding[sizeof(u16)];
+ Matrix matrix;
+ fixed_u32 track_width;
+ fixed_u32 track_height;
+};
+
+using EditListAtom;
+
+struct EditAtom : Atom {
+ EditListAtom edits[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+ $ += contents_size(addressof(this), box_size);
+};
+
+// moov -> trak -> edts -> elst
+struct EditListEntry<DurationT, TimeT> {
+ DurationT segment_duration;
+ TimeT media_time;
+ s16 media_rate_integer;
+ s16 media_rate_fraction;
+};
+
+struct EditListAtom : FullAtom {
+ u32 entry_count;
+ EditListEntry<u32, s32> entries[entry_count];
+ $ += contents_size(addressof(this), box_size);
+};
+
+using MediaHeaderAtom;
+using HandlerAtom;
+
+using SampleTableChildAtomSelector;
+
+struct SampleTableAtom : Atom {
+ SampleTableChildAtomSelector children[while(contents_size(addressof(this), box_size) > 0)];
+};
+
+struct DataPointer32 {
+ u8* pointer : u32;
+} [[inline]];
+
+struct ChunkOffsetAtom : FullAtom {
+ u32 entry_count;
+ DataPointer32 chunk_offset[entry_count];
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct UnknownSampleEntryChildSelector {
+ Atom box_header [[hidden]];
+
+ $ = addressof(this);
+ match(atom_header.box_type) {
+ (_): UnknownAtom unknown [[name(box_header.box_type)]];
+ }
+} [[inline]];
+
+struct SampleEntry : Atom {
+ padding[sizeof(u8) * 6];
+ u16 data_reference_index;
+};
+
+struct UnknownSampleEntry : SampleEntry {
+ if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
+ UnknownSampleEntryChildSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+ }
+ $ += contents_size(addressof(this), box_size);
+};
+
+enum VisualSampleDepth : u16 {
+ ColourNoAlpha = 0x0018,
+};
+
+struct VisualSampleEntry : SampleEntry {
+ u16 version;
+ u16 revision;
+ char vendor[4];
+ u32 temporal_quality;
+ u32 spatial_quality;
+ u16 width;
+ u16 height;
+ fixed_u32 horizresolution;
+ fixed_u32 vertresolution;
+ padding[sizeof(u32)];
+ u16 frame_count_per_sample;
+ u8 compressorname_size [[hidden]];
+ char compressorname[compressorname_size];
+ $ = addressof(compressorname_size) + 32;
+ u16 depth;
+ s16 colorTableID;
+ if (colorTableID != -1 ) {
+ std::print("Special color table");
+ }
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct PanoSampleDescription: Atom {
+ // https://developer.apple.com/library/archive/technotes/tn/tn1035.html
+ std::print("pano located at: 0x{:X}", addressof(this));
+ padding[sizeof(u32)];
+ padding[sizeof(u32)];
+
+ s16 majorVersion;
+ s16 minorVersion;
+ s32 sceneTrackID;
+ s32 loResSceneTrackID;
+ padding[sizeof(u32) * 6];
+ s32 hotspotTrackID;
+ padding[sizeof(u32) * 9];
+ fixed_s32 hPanStart;
+ fixed_s32 hPanEnd;
+ fixed_s32 vPanTop;
+ fixed_s32 vPanBottom; // TODO: number is off...
+ fixed_s32 minimumZoom;
+ fixed_s32 maximumZoom;
+
+ // Info for highest res version of scene track
+
+ s32 sceneSizeX;
+ s32 sceneSizeY;
+ s32 numFrames;
+ padding[sizeof(u16)];
+ s16 sceneNumFramesX;
+ s16 sceneNumFramesY;
+ s16 sceneColorDepth;
+
+ // Info for highest res version of hotSpot track
+ s32 hotSpotSizeX;
+ s32 hotSpotSizeY;
+ padding[sizeof(u16)];
+ s16 hotSponNumFramesX;
+ s16 hotSpotNumFrameY;
+ s16 hotsportColorDepth;
+
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct SampleEntrySelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+ match(atom_header.box_type) {
+ ("cvid"): VisualSampleEntry cvid;
+ ("smc "): VisualSampleEntry smc;
+ ("pano"): PanoSampleDescription pano;
+ (_): UnknownSampleEntry unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct SampleDescriptionAtom : FullAtom {
+ u32 entry_count;
+ SampleEntrySelector children[entry_count];
+ $ += contents_size(addressof(this), box_size);
+};
+
+
+
+// moov -> trak -> mdia -> minf -> stbl -> stts
+struct TimeToSampleEntry {
+ u32 sample_count;
+ u32 sample_delta;
+} [[format("format_stts_entry")]];
+
+fn format_stts_entry(auto stts_entry) {
+ return std::format("count = {}, delta = {}", stts_entry.sample_count, stts_entry.sample_delta);
+};
+
+struct TimeToSampleAtom : FullAtom {
+ u32 entry_count;
+ TimeToSampleEntry entries[entry_count] [[format("count_samples")]];
+ $ += contents_size(addressof(this), box_size);
+};
+
+fn count_samples(auto entries) {
+ u128 count = 0;
+ for (u32 i = 0, i < std::core::member_count(entries), i += 1) {
+ count += entries[i].sample_count;
+ }
+ return std::format("{} samples total", count);
+};
+
+// moov -> trak -> mdia -> minf -> stbl -> stsc
+struct SampleToChunkAtomEntry {
+ u32 first_chunk;
+ u32 samples_per_chunk;
+ u32 sample_description_index;
+} [[format("format_stsc_entry")]];
+
+fn format_stsc_entry(auto stsc_entry) {
+ return std::format("first_chunk = {}, samples_per_chunk = {}, sample_description_index = {}",
+ stsc_entry.first_chunk, stsc_entry.samples_per_chunk, stsc_entry.sample_description_index);
+};
+
+struct SampleToChunkAtom : FullAtom {
+ u32 entry_count;
+ SampleToChunkAtomEntry entries[entry_count];
+ $ += contents_size(addressof(this), box_size);
+};
+
+using SampleSizeAtom;
+struct SampleTableChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("stsd"): SampleDescriptionAtom stsd;
+ ("stsz"): SampleSizeAtom stsz;
+ ("stco"): ChunkOffsetAtom stco;
+ ("stts"): TimeToSampleAtom stts;
+ ("stsc"): SampleToChunkAtom stsc;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct SampleSizeAtom : FullAtom {
+ u32 sample_size;
+ u32 sample_count;
+ if (sample_size == 0) {
+ u32 entry_size[sample_count];
+ }
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct VideoMediaHeaderAtom : FullAtom {
+ u16 graphicsmode;
+ u16 opcolor[3];
+ $ += contents_size(addressof(this), box_size);
+};
+
+
+// moov -> trak -> mdia -> minf -> dinf
+using DataReferenceAtom;
+
+struct DataEntryAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+ match(atom_header.box_type) {
+ ("alis"): FullAtom alis;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct DataReferenceAtom : FullAtom {
+ u32 entry_count;
+ DataEntryAtomSelector children[entry_count];
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct DataInformationChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+ match(atom_header.box_type) {
+ ("dref"): DataReferenceAtom dref;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct DataInformationAtom : Atom {
+ DataInformationChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+};
+
+struct BaseMediaInfoAtom: FullAtom {
+ u16 graphics_mode;
+ u16 opcolor_1;
+ u16 opcolor_2;
+ u16 opcolor_3;
+ u16 balance;
+ padding[sizeof(u16)];
+};
+
+struct PanoMediaEntry {
+ u32 nodeID;
+ u32 time;
+};
+
+struct PanoMediaInfoAtom: Atom {
+ std::print("pINF: 0x{:X}", $);
+ std::string::SizedString<u8> name;
+ // string is padded till the 32nd byte.
+ // this is the beginning of the atom, including the 8 byte.
+ padding[40-($ - addressof(this))];
+ u32 defNodeId;
+ fixed_s32 defZoom;
+ s32 reserved;
+ s16 pad;
+ s16 numEntries;
+ PanoMediaEntry entries[numEntries];
+ $ += contents_size(addressof(this), box_size);
+
+}[[hex::visualize("hex_viewer", this)]];
+
+struct STPanoMediaInfoChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+ match(atom_header.box_type) {
+ ("pInf"): PanoMediaInfoAtom pInf;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+} [[inline]];
+
+struct STPanoMediaInfoAtom: Atom {
+ STPanoMediaInfoChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+};
+
+struct GMHDChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("gmin"): BaseMediaInfoAtom gmin;
+ ("STpn"): STPanoMediaInfoAtom STpn;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct GMHDAtom: Atom {
+ GMHDChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+ $ += contents_size(addressof(this), box_size);
+};
+
+struct MediaInformationChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("stbl"): SampleTableAtom stbl;
+ ("hdlr"): HandlerAtom hdlr;
+ ("vmhd"): VideoMediaHeaderAtom vmhd;
+ ("dinf"): DataInformationAtom dinf;
+ ("gmhd"): GMHDAtom gmhd;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+} [[inline]];
+
+struct MediaInformationAtom : Atom {
+ MediaInformationChildAtomSelector children[while(contents_size(addressof(this), box_size) > 0)];
+};
+
+struct MediaChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("mdhd"): MediaHeaderAtom mdhd;
+ ("hdlr"): HandlerAtom hdlr;
+ ("minf"): MediaInformationAtom minf;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+
+} [[inline]];
+
+struct MediaAtom : Atom {
+ MediaChildAtomSelector children[while (contents_size(addressof(this), box_size) > 0)];
+};
+
+struct TrackChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("tkhd"): TrackHeaderAtom tkhd;
+ ("mdia"): MediaAtom mdia;
+ ("edts"): EditAtom edts;
+ (_): UnknownAtom unknown [[name(atom_header.box_type)]];
+ }
+} [[inline]];
+
+struct TrackAtom : Atom {
+ TrackChildAtomSelector children[while(contents_size(addressof(this), box_size) > 0)];
+};
+str current_handler;
+
+// (mdia|meta) -> hdlr
+struct HandlerAtom : FullAtom {
+
+ char component_type[4];
+ char component_subtype[4];
+ char component_manufacturer[4];
+ u32 component_flags;
+ u32 component_flags_mask;
+ if (box_size > 32) {
+ std::string::SizedString<u8> name;
+ }
+};
+
+fn format_hdlr(auto hdlr) {
+ if (std::core::has_member(hdlr, "name")) {
+ return std::format("hdlr (type={}, name={})", hdlr.handler_type, hdlr.name.name);
+ }
+ return std::format("hdlr (type={})", hdlr.handler_type);
+};
+
+
+
+struct MediaHeaderAtom : FullAtom {
+
+ u32 creation_time;
+ u32 modification_time;
+ u32 timescale;
+ u32 duration;
+ u16 language;
+ u16 quality;
+
+} [[format("format_mdhd")]];
+
+fn format_mdhd(auto mdhd) {
+ return std::format("mdhd {{ duration = {} }}",
+ format_duration(mdhd.duration, mdhd.timescale));
+};
+
+fn format_duration(auto duration, auto timescale) {
+ float duration_f = duration;
+ float timescale_f = timescale;
+ float total_seconds = duration_f / timescale_f;
+ u128 minutes = std::math::floor(total_seconds / 60);
+ float seconds = total_seconds - (minutes * 60);
+ if (minutes > 0) {
+ return std::format("{:02d}:{:06.3f}", minutes, seconds);
+ } else {
+ return std::format("{:.3f}s", seconds);
+ }
+};
+
+fn format_mvhd(auto mvhd) {
+ return "mvhd { duration = " + format_duration(mvhd.duration, mvhd.timescale) + " }";
+};
+
+struct MovieChildAtomSelector {
+ Atom atom_header [[hidden]];
+
+ $ = addressof(this);
+
+ match(atom_header.box_type) {
+ ("mvhd"): MovieHeaderAtom mvhd;
+ ("trak"): TrackAtom trak;
+ ("udta"): UserDataAtom udta;
+ (_): UnknownAtomSelector unknown [[name(atom_header.box_type)]];
+ }
+} [[inline]];
+
+struct MovieAtom: Atom {
+ MovieChildAtomSelector children[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
+};
+
+
+// mdat
+struct MediaDataAtom : Atom {
+ u8 data[contents_size(addressof(this), box_size)] [[sealed]];
+};
+
+fn string_trim_end(ref str string, u128 amount) {
+ u128 length = std::string::length(string);
+ return std::string::substr(string, 0, length - amount);
+};
+
+fn format_box_array(auto atom_array) {
+ str result = "[ ";
+ u64 i;
+ for (i = 0, i < std::core::member_count(atom_array), i += 1) {
+ result = result + atom_array[i].atom_header.box_type + ", ";
+ }
+ return string_trim_end(result, 2) + " ]";
+};
+
+
+struct RootAtom {
+ Atom atom_header [[hidden]];
+ $ = addressof(this);
+ if ($ + contents_size(addressof(this), atom_header.box_size) <= std::mem::size()) {
+
+ match(atom_header.box_type) {
+ ("moov"): MovieAtom moov;
+ ("mdat"): MediaDataAtom mdat;
+ (_): UnknownAtomSelector unknown [[name(atom_header.box_type)]];
+ }
+ } else {
+ $ = std::mem::size();
+ }
+
+} [[inline]];
+
+RootAtom atoms[while(std::mem::size() - $ > MIN_BOX_SIZE)] @ 0x00 [[format("format_box_array")]];
More information about the Scummvm-git-logs
mailing list