diff --git a/README.md b/README.md index 0b90953..a4b973f 100644 --- a/README.md +++ b/README.md @@ -22,76 +22,77 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | Name | MIME | Path | Description | |------|------|------|-------------| -| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files | -| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries | -| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields | -| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields | -| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") | -| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided | -| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header | -| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers | -| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets | -| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions | | AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log | | AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files | -| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files | -| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files | -| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO | -| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files | | ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout | -| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files | -| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files | -| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files | -| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface | -| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image | -| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system | -| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files | -| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) | -| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) | -| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System | | Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files | -| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding | -| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format | -| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format | -| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format | -| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC | -| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format | -| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams | -| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format | +| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files | | BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format | -| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format | -| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files | -| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files | -| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format | -| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format | -| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob | -| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive | -| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format | -| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format | -| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format | -| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) | -| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM | -| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive | -| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files | -| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format | -| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable | -| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable | -| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) | -| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) | -| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable | -| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file | +| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) | | CCHVA | | [`patterns/cchva.hexpat`](patterns/cchva.hexpat) | Command and Conquer Voxel Animation | | CCVXL | | [`patterns/ccvxl.hexpat`](patterns/ccvxl.hexpat) | Command and Conquer Voxel Model | | CCPAL | | [`patterns/ccpal.hexpat`](patterns/ccpal.hexpat) | Command and Conquer Voxel Palette | -| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format | +| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) | +| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable | +| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format | +| CrashLvl | | [`patterns/Crashlvl.hexpat`](patterns/Crashlvl.hexpat) | Crash Bandicoot - Back in Time (fan game) User created flashback tapes level format | +| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface | +| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format | +| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) | +| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format | +| DTA | | [`patterns/max_v104.hexpat`](patterns/max_v104.hexpat) | Mechanized Assault and Exploration v1.04 (strategy game) save file format | +| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries | +| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log | +| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob | +| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System | +| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format | +| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files | +| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format | +| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files | +| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files | +| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") | +| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) | +| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system | +| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files | | JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format | | Lua 5.4 | | [`patterns/lua54.hexpat`](patterns/lua54.hexpat) | Lua 5.4 bytecode | -| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format | -| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format | +| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable | +| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided | +| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files | +| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format | +| 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 | +| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files | +| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC | +| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format | +| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets | +| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format | +| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields | +| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) | +| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format | +| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files | +| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO | +| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding | +| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file | +| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files | +| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format | +| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions | +| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format | +| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive | +| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format | +| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image | | UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars | -| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log | -| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) | -| CrashLvl | | [`patterns/Crashlvl.hexpat`](patterns/Crashlvl.hexpat) | Crash Bandicoot - Back in Time (fan game) User created flashback tapes level format | +| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) | +| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files | +| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format | +| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header | +| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive | +| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable | +| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM | +| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams | +| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers | +| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format | ### Scripts diff --git a/patterns/max_v104.hexpat b/patterns/max_v104.hexpat new file mode 100644 index 0000000..de15b05 --- /dev/null +++ b/patterns/max_v104.hexpat @@ -0,0 +1,831 @@ +#include +#include + +#pragma array_limit 12544 +#pragma pattern_limit 2000000 +#pragma eval_depth 32 + +enum FileType : u8 +{ + Custom, + Tutorial, + Campaign, + Hot_seat, + Multiplayer, + Demo, + Debug, + Text, + Scenario, + Multi_scenario +}; + +enum PlanetType : u8 +{ + Snowcrab, + Frigia, + Ice_Berg, + The_Cooler, + Ultima_Thule, + Long_Floes, + Iron_Cross, + Splatterscape, + Peak_a_boo, + Valentines_Planet, + Three_Rings, + Great_divide, + New_Luzon, + Middle_Sea, + High_Impact, + Sanctuary, + Islandia, + Hammerhead, + Freckles, + Sandspit, + Great_Circle, + Long_Passage, + Flash_Point, + Bottleneck +}; + +enum TeamType : u8 +{ + None = 0, + Human = 1, + Computer = 2, + Remote = 3, + Eliminated = 4 +}; + +enum TeamIndex : u8 +{ + Red = 0, + Green = 1, + Blue = 2, + Gray = 3 +}; + +enum TeamIndex16 : u16 +{ + Red = 0, + Green = 1, + Blue = 2, + Gray = 3 +}; + +enum PlayMode : u8 +{ + Turn_Based = 0, + Simultaneous_Moves = 1 +}; + +enum TeamClan : u8 +{ + None = 0, + The_Chosen = 1, + Crimson_Path = 2, + Von_Griffin = 3, + Ayers_Hand = 4, + Musashi = 5, + Sacred_Eights = 6, + Seven_Knights = 7, + Axis_Inc = 8 +}; + +enum OpponentType : u8 +{ + Clueless = 0, + Apprentice = 1, + Average = 2, + Expert = 3, + Master = 4, + God = 5 +}; + +enum VictoryType : u8 +{ + Duration = 0, + Score = 1 +}; + +struct IniOptions +{ + s32 world; + s32 turn_timer; + s32 endturn; + s32 start_gold; + s32 play_mode; + s32 victory_type; + s32 victory_limit; + s32 opponent; + s32 raw_resource; + s32 fuel_resource; + s32 gold_resource; + s32 alien_derelicts; +}; + +struct IniPreferences +{ + s32 effects; + s32 click_scroll; + s32 quick_scroll; + s32 fast_movement; + s32 follow_unit; + s32 auto_select; + s32 enemy_halt; +}; + +enum SurfaceType : u8 +{ + Land = 1, + Water = 2, + Coast = 4, + Air = 8 +}; + +enum AiStrategy : u8 +{ + Random, + Defensive, + Missiles, + Air, + Sea, + Scout_horde, + Tank_horde, + Fast_attack, + Combined_arms, + Espionage +}; + +bitfield GridResourceMapEntry +{ + padding : 2; + team_visibility_gray : 1; + team_visibility_blue : 1; + team_visibility_green : 1; + team_visibility_red : 1; + padding : 2; + cargo_amount : 5; + cargo_type_fuel : 1; + cargo_type_gold : 1; + cargo_type_material : 1; +}; + +bitfield UnitFlags +{ + // MSB + requires_slab: 1; + turret_sprite: 1; + sentry_unit: 1; + spinning_turret: 1; + padding: 4; + + hovering: 1; + has_firing_sprite: 1; + fires_missiles: 1; + constructor_unit: 1; + padding: 1; + electronic_unit: 1; + selectable: 1; + standalone: 1; + + mobile_land_unit: 1; + stationary: 1; + padding: 4; + upgradeable: 1; + padding: 1; + + // LSB + ground_cover : 1; + exploding: 1; + animated: 1; + connector_unit: 1; + building: 1; + missile_unit: 1; + mobile_air_unit: 1; + mobile_sea_unit: 1; +}; + +struct Point +{ + s16 x; + s16 y; +}; + +struct ResearchTopicInfo +{ + u32 research_level; + u32 turns_to_complete; + s32 allocation; +}; + +struct ScreenLocation +{ + s8 x; + s8 y; +}; + +struct TeamInfo +{ + Point markers[10]; + TeamType team_type; + s8 field_41; + TeamClan team_clan; + ResearchTopicInfo research_topics[8]; + u32 victory_points; + u16 next_unit_id; + u8 unit_counters[93]; + ScreenLocation screen_location[6]; + u16 score_graph[50]; + u16 selected_unit; + u16 zoom_level; + Point screen_position; + bool gui_button_state_range; + bool gui_button_state_scan; + bool gui_button_state_status; + bool gui_button_state_colors; + bool gui_button_state_hits; + bool gui_button_state_ammo; + bool gui_button_state_names; + bool gui_button_state_minimap_2x; + bool gui_button_state_minimap_tnt; + bool gui_button_state_grid; + bool gui_button_state_survey; + u16 stats_factories_built; + u16 stats_mines_built; + u16 stats_buildings_built; + u16 stats_units_built; + u16 casualties[93]; + u16 stats_gold_spent_on_upgrades; +}; + +struct UnitValues +{ + u16 object_index; + + if(CheckObjectId(object_index, true) == true) + { + u16 class_type; + u16 turns; + u16 hits; + u16 armor; + u16 attack; + u16 speed; + u16 range; + u16 rounds; + bool move_and_fire; + u16 scan; + u16 storage; + u16 ammo; + u16 attack_radius; + u16 agent_adjust; + u16 version; + u8 units_built; + } +}; + +struct Complex +{ + u16 object_index; + + if(CheckObjectId(object_index, true) == true) + { + u16 class_type; + s16 material; + s16 fuel; + s16 gold; + s16 power; + s16 workers; + s16 buildings; + s16 id; + } +}; + +struct TeamUnits +{ + s16 gold; + UnitValues base_unit_values[93]; + UnitValues current_unit_values[93]; + u16 complex_count; + Complex complexes[complex_count]; +}; + +enum UnitType : u16 +{ + UNIT_TYPE_GOLD_REFINERY = 0, + UNIT_TYPE_POWER_STATION = 1, + UNIT_TYPE_POWER_GENERATOR = 2, + UNIT_TYPE_BARRACKS = 3, + UNIT_TYPE_ALIEN_BUILDING_1 = 4, + UNIT_TYPE_RADAR = 5, + UNIT_TYPE_STORAGE_UNIT = 6, + UNIT_TYPE_FUEL_TANK = 7, + UNIT_TYPE_GOLD_VAULT = 8, + UNIT_TYPE_DEPOT = 9, + UNIT_TYPE_HANGAR = 10, + UNIT_TYPE_DOCK = 11, + UNIT_TYPE_CONNECTOR = 12, + UNIT_TYPE_LARGE_RUBBLE_1 = 13, + UNIT_TYPE_SMALL_RUBBLE_1 = 14, + UNIT_TYPE_LARGE_TAPE = 15, + UNIT_TYPE_SMALL_TAPE = 16, + UNIT_TYPE_LARGE_SLAB = 17, + UNIT_TYPE_SMALL_SLAB = 18, + UNIT_TYPE_LARGE_CONES = 19, + UNIT_TYPE_SMALL_CONES = 20, + UNIT_TYPE_ROAD = 21, + UNIT_TYPE_LANDING_PAD = 22, + UNIT_TYPE_SHIPYARD = 23, + UNIT_TYPE_LIGHT_VEHICLE_PLANT = 24, + UNIT_TYPE_HEAVY_VEHICLE_PLANT = 25, + UNIT_TYPE_ALIEN_BUILDING_2 = 26, + UNIT_TYPE_AIR_UNITS_PLANT = 27, + UNIT_TYPE_HABITAT = 28, + UNIT_TYPE_RESEARCH_CENTER = 29, + UNIT_TYPE_ECOSPHERE = 30, + UNIT_TYPE_ALIEN_BUILDING_3 = 31, + UNIT_TYPE_TRAINING_HALL = 32, + UNIT_TYPE_WATER_PLATFORM = 33, + UNIT_TYPE_GUN_TURRET = 34, + UNIT_TYPE_ANTI_AIRCRAFT = 35, + UNIT_TYPE_ARTILLERY = 36, + UNIT_TYPE_MISSILE_LAUNCHER = 37, + UNIT_TYPE_CONCRETE_BLOCK = 38, + UNIT_TYPE_BRIDGE = 39, + UNIT_TYPE_MINING_STATION = 40, + UNIT_TYPE_LAND_MINE = 41, + UNIT_TYPE_SEA_MINE = 42, + UNIT_TYPE_LAND_EXPLOSION = 43, + UNIT_TYPE_AIR_EXPLOSION = 44, + UNIT_TYPE_SEA_EXPLOSION = 45, + UNIT_TYPE_BUILDING_EXPLOSION = 46, + UNIT_TYPE_HIT_EXPLOSION = 47, + UNIT_TYPE_MASTER_BUILDER = 48, + UNIT_TYPE_CONSTRUCTOR = 49, + UNIT_TYPE_SCOUT = 50, + UNIT_TYPE_TANK = 51, + UNIT_TYPE_ASSAULT_GUN = 52, + UNIT_TYPE_ROCKET_LAUNCHER = 53, + UNIT_TYPE_MISSILE_CRAWLER = 54, + UNIT_TYPE_MOBILE_ANTI_AIRCRAFT = 55, + UNIT_TYPE_MINE_LAYER = 56, + UNIT_TYPE_SURVEYOR = 57, + UNIT_TYPE_SCANNER = 58, + UNIT_TYPE_SUPPLY_TRUCK = 59, + UNIT_TYPE_GOLD_TRUCK = 60, + UNIT_TYPE_ENGINEER = 61, + UNIT_TYPE_BULLDOZER = 62, + UNIT_TYPE_REPAIR_UNIT = 63, + UNIT_TYPE_FUEL_TRUCK = 64, + UNIT_TYPE_PERSONNEL_CARRIER = 65, + UNIT_TYPE_INFILTRATOR = 66, + UNIT_TYPE_INFANTRY = 67, + UNIT_TYPE_ESCORT = 68, + UNIT_TYPE_CORVETTE = 69, + UNIT_TYPE_GUNBOAT = 70, + UNIT_TYPE_SUBMARINE = 71, + UNIT_TYPE_SEA_TRANSPORT = 72, + UNIT_TYPE_MISSILE_CRUISER = 73, + UNIT_TYPE_SEA_MINE_LAYER = 74, + UNIT_TYPE_CARGO_SHIP = 75, + UNIT_TYPE_FIGHTER = 76, + UNIT_TYPE_GROUND_ATTACK_PLANE = 77, + UNIT_TYPE_AIR_TRANSPORT = 78, + UNIT_TYPE_AWAC = 79, + UNIT_TYPE_ALIEN_GUNBOAT = 80, + UNIT_TYPE_ALIEN_TANK = 81, + UNIT_TYPE_ALIEN_ASSAULT_GUN = 82, + UNIT_TYPE_ALIEN_ATTACK_PLANE = 83, + UNIT_TYPE_MISSILE = 84, + UNIT_TYPE_TORPEDO = 85, + UNIT_TYPE_ALIEN_MISSILE = 86, + UNIT_TYPE_TANK_PLASMA_BALL = 87, + UNIT_TYPE_ARTILLERY_PLASMA_BALL = 88, + UNIT_TYPE_SMOKE_TRAIL = 89, + UNIT_TYPE_BUBBLE_TRAIL = 90, + UNIT_TYPE_HARVESTER = 91, + UNIT_TYPE_DEAD_WALDO = 92 +}; + +enum OrderType : u8 +{ + ORDER_TYPE_AWAITING = 0x0, + ORDER_TYPE_TRANSFORMING = 0x1, + ORDER_TYPE_MOVING = 0x2, + ORDER_TYPE_FIRING = 0x3, + ORDER_TYPE_ORDER_BUILDING = 0x4, + ORDER_TYPE_ACTIVATE_ORDER = 0x5, + ORDER_TYPE_NEW_ALLOCATE_ORDER = 0x6, + ORDER_TYPE_POWER_ON = 0x7, + ORDER_TYPE_POWER_OFF = 0x8, + ORDER_TYPE_EXPLODING = 0x9, + ORDER_TYPE_UNLOADING = 0xA, + ORDER_TYPE_CLEARING = 0xB, + ORDER_TYPE_SENTRY = 0xC, + ORDER_TYPE_LANDING = 0xD, + ORDER_TYPE_TAKING_OFF = 0xE, + ORDER_TYPE_LOADING = 0xF, + ORDER_TYPE_IDLE = 0x10, + ORDER_TYPE_REPAIRING = 0x11, + ORDER_TYPE_REFUELING = 0x12, + ORDER_TYPE_RELOADING = 0x13, + ORDER_TYPE_TRANSFERRING = 0x14, + ORDER_TYPE_AWAITING_21 = 0x15, + ORDER_TYPE_AWAITING_22 = 0x16, + ORDER_TYPE_AWAITING_23 = 0x17, + ORDER_TYPE_AWAITING_24 = 0x18, + ORDER_TYPE_AWAITING_25 = 0x19, + ORDER_TYPE_DISABLED = 0x1A, + ORDER_TYPE_MOVING_27 = 0x1B, + ORDER_TYPE_REPAIRING_28 = 0x1C, + ORDER_TYPE_TRANSFERRING_29 = 0x1D, + ORDER_TYPE_ATTACKING = 0x1E, + ORDER_TYPE_BUILDING_HALTED = 0x1F +}; + +struct Rect +{ + s32 ulx; + s32 uly; + s32 lrx; + s32 lry; +}; + +struct PathStep +{ + s8 x; + s8 y; +}; + +struct Path +{ + u16 object_index; + + if(CheckObjectId(object_index, true) == true) + { + u16 class_type; + + // Air path + if (class_type == 1) + { + s16 length; + u8 angle; + Point pixel_start; + Point pixel_end; + s32 x_step; + s32 y_step; + s32 delta_x; + s32 delta_y; + } + // Ground path + else if (class_type == 4) + { + Point pixel_end; + s16 index; + s16 steps_count; + PathStep steps[steps_count]; + } + // Builder path + else if (class_type == 2) + { + Point coordinate; + } + else + { + std::assert(0, "Unknown path class"); + } + } +}; + +struct UnitTypeArray +{ + u16 object_count; + + UnitType array[object_count]; +}; + +struct UnitInfo +{ + u16 object_index; + + if(CheckObjectId(object_index, true) == true) + { + u16 class_type; + UnitType unit_type; + + if (unit_type == UnitType::UNIT_TYPE_DEAD_WALDO) + { + std::print("Found Waldo!"); + } + + u16 hash_id; + UnitFlags flags; + Point pixel_position; + Point grid_position; + u16 name_length; + s8 name[name_length]; + Point shadow_offset; + TeamIndex team; + u8 name_index; + u8 brightness; + u8 angle; + u8 visible_to_team[5]; + u8 spotted_by_team[5]; + u8 max_velocity; + u8 velocity; + u8 sound; + u8 scaler_adjust; + Rect sprite_bounds; + Rect shadow_bounds; + u8 turret_angle; + s8 turret_offset_x; + s8 turret_offset_y; + u16 total_images; + u16 image_base; + u16 turret_image_base; + u16 firing_image_base; + u16 connector_image_base; + u16 image_index; + u16 turret_image_index; + u16 image_index_max; + OrderType orders; + u8 state; + OrderType prior_orders; + u8 prior_state; + u8 laying_state; + Point target_grid; + u8 build_time; + u8 total_mining; + u8 raw_mining; + u8 fuel_mining; + u8 gold_mining; + u8 raw_mining_max; + u8 gold_mining_max; + u8 fuel_mining_max; + u8 hits; + u8 speed; + u8 shots; + u8 move_and_fire; + u16 storage; + u8 ammo; + u8 targeting_mode; + u8 enter_mode; + u8 cursor; + u8 recoil_delay; + u8 delayed_reaction; + u8 damaged_this_turn; + u8 research_topic; + u8 moved; + u8 bobbed; + u8 shake_effect_state; + u8 engine; + u8 weapon; + u8 comm; + u8 fuel_distance; + u8 move_fraction; + u8 energized; + u8 repeat_build; + u16 build_rate; + u8 disabled_reaction_fire; + u8 auto_survey; + u32 field_221; + Path path; + u16 connectors; + UnitValues base_values; + Complex complex; + UnitInfo parent_unit; + UnitInfo enemy_unit; + UnitTypeArray build_list; + } +}; + +struct UnitInfoList +{ + u16 unitinfo_count; + UnitInfo units[unitinfo_count]; +}; + +struct HashMapUnitInfo +{ + u16 hash_size; + UnitInfoList map[hash_size]; +}; + +struct MapHash +{ + Point coordinates; + UnitInfoList units; +}; + +struct MapHashList +{ + u16 maphash_count; + MapHash objects[maphash_count]; +}; + +struct HashMapMapHash +{ + u16 hash_size; + s16 x_shift; + MapHashList map[hash_size]; +}; + +struct TeamHeatMaps +{ + u8 heatmap_complete[12544]; + u8 heatmap_stealth_sea[12544]; + u8 heatmap_stealth_land[12544]; +}; + +struct MessageLog +{ + s16 length; + char text[length]; + UnitInfo unit; + Point coordinates; + bool is_alert_message; + u16 resource_id; +}; + +struct MessageLogList +{ + u16 message_log_count; + MessageLog entires[message_log_count]; +}; + +struct AiMap +{ + UnitInfo unit; + TeamIndex16 team; + bool visible_to_team; + Point point; +}; + +struct AiMapList +{ + u16 ai_map_count; + AiMap objects[ai_map_count]; +}; + +struct AiPlayer +{ + TeamIndex16 team; + AiStrategy strategy; + s16 field_3; + s16 field_5; + s16 field_7; + TeamIndex16 target_team; + AiMapList map_list; + u16 has_info_map; + + if (has_info_map) + { + u8 info_map[12544]; + } + + u16 has_mine_map; + + if (has_mine_map) + { + u8 mine_map[12544]; + } + + Point target_location; +}; + +u16 last_object_index; +bool context; + +fn Init() +{ + context = false; + last_object_index = 0; +}; + +fn CheckObjectId(u16 index, bool caller) +{ + bool result = false; + + // ImHex bug workaround + if (context) { context = false; return result; } + + // null object? + if (index == 0) + { + return false; + } + + // already serialized object? + if (last_object_index < index) + { + last_object_index = index; + result = true; + } + + return result; +}; + +struct SaveFile +{ + Init(); + + s16 version; + FileType save_file_type; + char save_game_name[30]; + PlanetType planet; + s16 mission_index; + char team_name_red[30]; + char team_name_green[30]; + char team_name_blue[30]; + char team_name_gray[30]; + TeamType team_type_red; + TeamType team_type_green; + TeamType team_type_blue; + TeamType team_type_gray; + TeamType team_type_alien; + TeamClan team_clan_red; + TeamClan team_clan_green; + TeamClan team_clan_blue; + TeamClan team_clan_gray; + TeamClan team_clan_alien; + u32 rng_seed; + OpponentType opponent; + s16 turn_timer; + s16 endturn; + PlayMode play_mode; + IniOptions options; + SurfaceType surface_map[12544]; + GridResourceMapEntry GridResourceMap[12544]; + TeamInfo team_info_red; + TeamInfo team_info_green; + TeamInfo team_info_blue; + TeamInfo team_info_gray; + TeamIndex active_turn_team; + TeamIndex player_team; + s32 turn_counter; + s16 game_state; + u16 turn_timer_; + IniPreferences preferences; + TeamUnits team_units_red; + TeamUnits team_units_green; + TeamUnits team_units_blue; + TeamUnits team_units_gray; + UnitInfoList unit_info_list_ground_cover_units; + UnitInfoList unit_info_list_mobile_land_sea_units; + UnitInfoList unit_info_list_stationary_units; + UnitInfoList unit_info_list_mobile_air_units; + UnitInfoList unit_info_list_particles; + HashMapUnitInfo hash_map_unit_info; + HashMapMapHash hash_map_map_hash; + + if (team_type_red != TeamType::None) + { + TeamHeatMaps heat_maps_red; + } + + if (team_type_green != TeamType::None) + { + TeamHeatMaps heat_maps_green; + } + + if (team_type_blue != TeamType::None) + { + TeamHeatMaps heat_maps_blue; + } + + if (team_type_gray != TeamType::None) + { + TeamHeatMaps heat_maps_gray; + } + + MessageLogList message_log_red; + MessageLogList message_log_green; + MessageLogList message_log_blue; + MessageLogList message_log_gray; + + if (team_type_red == TeamType::Computer) + { + AiPlayer ai_player_red; + } + + if (team_type_green == TeamType::Computer) + { + AiPlayer ai_player_green; + } + + if (team_type_blue == TeamType::Computer) + { + AiPlayer ai_player_blue; + } + + if (team_type_gray == TeamType::Computer) + { + AiPlayer ai_player_gray; + } + +}; + +SaveFile save @ 0x0; + +std::assert($ == std::mem::size(), "Extra data found after parsed data"); + + diff --git a/tests/patterns/test_data/maxsave.dta b/tests/patterns/test_data/maxsave.dta new file mode 100644 index 0000000..41739ac Binary files /dev/null and b/tests/patterns/test_data/maxsave.dta differ