From b24ae3663847db9be50f2a2c6ddec12025dbbb36 Mon Sep 17 00:00:00 2001 From: DmitriLeon2000 Date: Tue, 9 Sep 2025 18:22:02 +0200 Subject: [PATCH] patterns: Add .gmf (Game Maker 3.x Data) pattern file and its test files (#438) * Add .fas and .was pattern files (Oska DeskMates) * Update .was pattern file * Update .was/.wa3 pattern file * Update README.md * Update README.md * Update .fas & .was pattern files * Update README.md * Update fas_oskasoftware_old.hexpat * Added WAS test file * Update WAS test file * Update was_oskasoftware.hexpat * Update was_oskasoftware.hexpat * Update fas_oskasoftware_old.hexpat * Update fas_oskasoftware.hexpat * Update README.md Replacing backward slashes with forward ones in the `WAS` row. * Update fas_oskasoftware_old.hexpat * Update was_oskasoftware.hexpat * Add files via upload * Add Game Maker 3.x Data pattern * Update gmf.hexpat --- patterns/gmf.hexpat | 229 ++++++++++++++++++ .../test_data/gmf.hexpat/gmf.hexpat.gmf | Bin 0 -> 5671 bytes .../test_data/gmf.hexpat/gmf.hexpat_data/help | Bin 0 -> 207 bytes 3 files changed, 229 insertions(+) create mode 100644 patterns/gmf.hexpat create mode 100644 tests/patterns/test_data/gmf.hexpat/gmf.hexpat.gmf create mode 100644 tests/patterns/test_data/gmf.hexpat/gmf.hexpat_data/help diff --git a/patterns/gmf.hexpat b/patterns/gmf.hexpat new file mode 100644 index 0000000..13f4f43 --- /dev/null +++ b/patterns/gmf.hexpat @@ -0,0 +1,229 @@ +#pragma author DmitriLeon2000 +#pragma description Game Maker 3.x data +#pragma endian little + +import std.mem; +import std.io; + +struct Colors { + u8 red [[color("FF0000")]]; + u8 green [[color("00FF00")]]; + u8 blue [[color("0000FF")]]; + padding[1]; +} [[static, color(std::format("{:02X}{:02X}{:02X}", red, green, blue)), + hex::inline_visualize("color", red, green, blue, 255)]]; + +struct PascalString { + u32 length; + char data[length]; +}; + +struct BitmapData { + u8 type[2]; + u32 size; + u8 data[size-6] [[sealed]]; +}; + +enum BackgroundType : s32 { + Solid = 0, + Image = 1, + Gradient = 2, + None = 3 +}; + +enum BackImageStyle : s32 { + Tile = 0, + Stretch = 1, + Scrolling = 2, + LeftTop = 3 +}; + +enum Transition : u32 { + None = 0, + CreateFromLeft = 1, + CreateFromRight = 2, + CreateFromTop = 3, + CreateFromBottom = 4, + CreateFromCenter = 5, + ShiftFromLeft = 6, + ShiftFromRight = 7, + ShiftFromTop = 8, + ShiftFromBottom = 9, + PushFromLeft = 10, + PushFromRight = 11, + PushFromTop = 12, + PushFromBottom = 13 +}; + +struct SpriteBoundingBox { + u32 left, right, bottom, top; +}; + +enum ActionID : s32 { + EnumerateActions = 0, + EndAction = 1, + MoveFixed = 101, + ReverseHorizontal = 102, + ReverseVertical = 103, + JumpPosition = 104, + JumpRandom = 105, + Bounce = 106, + SetSpeedHorizontal = 111, + SetSpeedVertical = 112, + SetGravity = 121, + SetFriction = 122, + MoveFree = 131, + SetAlarm = 201, + InstanceCreate = 311, + InstanceDestroy = 312, + InstanceChange = 313, + PositionDestroy = 321, + Sound = 401, + ShowMessage = 411, + SetScore = 421, + DisplayHighscore = 431, + GoToRoom = 501, + EndGame = 511, + Sleep = 521, + ExitEvent = 601, + CheckPlaceFree = 701, + CheckInstanceNumber = 702, + CheckPlaceObject = 703, + CheckPlaceCollision = 704, + CheckQuestion = 721, + Else = 751, + CheckExpression = 801, + ExecuteCode = 811, + SetVariable = 821, + BlockStart = 901, + BlockEnd = 902, + DrawImage = 1001, + DrawText = 1002, + SetFont = 1003 +}; + +struct GameObjectAction { + s32 version_verify [[hidden]]; + ActionID action_id; + s32 apply_to; // -1 - self; -2 - not available + bool relative; + padding[3]; + u32 param_count; + PascalString params[param_count]; + s32 action_group; +}; + +struct GameObjectSubEvent { + s32 subevent_number; + s32 version_verify [[hidden]]; + u32 action_count; + GameObjectAction actions[action_count]; +}; + +struct GameObjectEvent { + GameObjectSubEvent subevents[while(std::mem::read_unsigned($, 4) != 0xFFFFFFFF)]; + padding[4]; +}; + +struct GameSprite { + s32 version_verify [[hidden]]; + s32 width, height; + SpriteBoundingBox bounding_box1; + u32 image_count; + BitmapData images[image_count]; + SpriteBoundingBox bounding_box2; +}; + +struct GameObject { + s32 version_verify [[hidden]]; + PascalString name; + bool solid; + padding[3]; + bool active; + padding[3]; + if (version_verify >= 320) + u32 parent_id; + GameObjectEvent events[13]; + // Events: 0 - Create, 1 - Destroy, 2 - Alarm, 3 - Step, 4 - Collision, + // 5 - Meeting, 6 - Mouse, 7 - Keyboard, 8 - Other, 9 - Drawing + // 10 - Create duplicate, 11-13 - unused + s32 cap [[hidden]]; + GameSprite sprite; +} [[name(name.data)]]; + +struct GameRoomView { + bool enabled; + padding[3]; + if (parent.version_verify >= 320) + s32 left, top, left_cell, top_cell; + u32 width; + u32 height; + if (parent.version_verify >= 320) { + u32 border_horiz, border_vert; + } else + u32 border; + u32 object_to_follow; +}; + +struct GameRoomInstance { + s32 left, top, object_index; +}; + +struct GameRoom { + u32 version_verify [[hidden]]; + PascalString name; + Colors back_color1; + if (version_verify >= 320) { + Colors back_color2; + bool vertical_gradient; + padding[3]; + } + // specify the name of the external image file from the data folder + PascalString back_image_name; + BackgroundType back_type; + BackImageStyle back_image_style; + s32 back_scroll_speed_horizontal, back_scroll_speed_vertical; + s32 speed, width, height, cell_size; + if (version_verify >= 320) { + bool enable_views; + padding[3]; + GameRoomView views[4]; + } else + GameRoomView view; + if (version_verify >= 320) { + Transition transition; + u32 transition_time, transition_steps; + } + u32 instance_count; + GameRoomInstance instances[instance_count]; +} [[name(name.data)]]; + +struct GameSound { + u32 version_verify [[hidden]]; + PascalString name; + u32 reserved; + // specify the name of the external audio file from the data folder + PascalString filename; + bool allow_for_sound_effects; + padding[3]; + u32 buffer_count; +} [[name(name.data)]]; + +struct GMF { + u32 version; + u32 verification[2]; + u32 version_verify_options [[hidden]]; + u32 option_count; + PascalString options[option_count]; + u32 version_verify_objects [[hidden]]; + u32 object_count; + GameObject objects[object_count]; + u32 version_verify_rooms [[hidden]]; + u32 room_count; + GameRoom rooms[room_count]; + u32 version_verify_sounds [[hidden]]; + u32 sound_count; + GameSound sounds[sound_count]; +}; + +GMF gmf @ 0x0; diff --git a/tests/patterns/test_data/gmf.hexpat/gmf.hexpat.gmf b/tests/patterns/test_data/gmf.hexpat/gmf.hexpat.gmf new file mode 100644 index 0000000000000000000000000000000000000000..ddb8bd64a84a61f4486494a09ae88c59b7427342 GIT binary patch literal 5671 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 TQU(uD$m!P%yotdzXn=eVhxSGl literal 0 HcmV?d00001 diff --git a/tests/patterns/test_data/gmf.hexpat/gmf.hexpat_data/help b/tests/patterns/test_data/gmf.hexpat/gmf.hexpat_data/help new file mode 100644 index 0000000000000000000000000000000000000000..5fba4b3984d35ca1fe1eae957d8d098bcc109595 GIT binary patch literal 207 zcmXwyO%B2!5QXd3#5-_;23lM+-RM1LLt#K7p=O}EXnJ?Ys+*U|eDCLSXqpwMdIctz zxQl%R)twbM^j>~6nH-eV!wP=RwN8l-2|mXJ-rfuqtWsPlnlx^V)Q