From 2a9676238f97747319d5786fc4d09b22db6bdbae Mon Sep 17 00:00:00 2001 From: tympanicblock61 <99092380+tympanicblock61@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:54:19 -0500 Subject: [PATCH] pattern: Add lua 4.0 pattern (#465) * add lua 4.0 pattern * fix offset the top level function is at * Update README.md --------- Co-authored-by: Nik --- README.md | 1 + patterns/lua40.hexpat | 133 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 patterns/lua40.hexpat diff --git a/README.md b/README.md index 6687304..aadeb3d 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format | | KTX | `image/ktx` | [`patterns/ktx.hexpat`](patterns/ktx.hexpat) | Khronos TeXture 1.0 | | LOC | | [`patterns/loc.hexpat`](patterns/loc.hexpat) | Minecraft Legacy Console Edition Language file | +| Lua 4.0 | | [`patterns/lua40.hexpat`](patterns/lua40.hexpat) | Lua 4.0 bytecode | | LUC | | [`patterns/popcap_luc.hexpat`](patterns/popcap_luc.hexpat) | PopCap's proprietary Lua bytecode | | Lua 5.1 | | [`patterns/lua51.hexpat`](patterns/lua51.hexpat) | Lua 5.1 bytecode | | Lua 5.2 | | [`patterns/lua52.hexpat`](patterns/lua52.hexpat) | Lua 5.2 bytecode | diff --git a/patterns/lua40.hexpat b/patterns/lua40.hexpat new file mode 100644 index 0000000..6e30e04 --- /dev/null +++ b/patterns/lua40.hexpat @@ -0,0 +1,133 @@ +#pragma description Lua 4.0 bytecode +#pragma magic [ 1B 4C 75 61 40 ] @ 0x00 +// based off of https://www.lua.org/source/4.0/dump.c.html + +import std.io; + +namespace impl { + fn format_LuaString(auto string) { + if (string.size == 0) { + return "None"; + } + return std::format("\"{}\"", string.data); + }; + + fn format_Version(auto ver) { + return std::format("Ver. {}.{}", ver.major, ver.minor); + }; +} +using LuaFunction; + +bitfield Version { + minor : 4; + major : 4; +} [[format("impl::format_Version")]]; + +struct LuaBinaryHeader { + u8 id_chunk; + char magic[3]; + Version version; + u8 endianness; + u8 size_of_int; + u8 size_of_size_t; + u8 size_of_instruction; // ??? + u8 size_INSTRUCTION; // SIZE_INSTRUCTION in Lua 4 source + u8 size_OP; // SIZE_OP + u8 size_B; // SIZE_B + u8 size_number; // sizeof(Number) + + if (size_number == 4) { + u32 TEST_NUMBER; + } else { + u64 TEST_NUMBER; + } +}; + +LuaBinaryHeader header @ 0; + +struct LuaString { + if (header.size_of_size_t == 4) { + u32 size; + } else { + u64 size; + } + + if (size > 0) { + char data[size]; + } +}[[format("impl::format_LuaString")]]; + +struct Vector { + if (header.size_of_int == 4) { + u32 size; + } else { + u64 size; + } + if (size > 0) { + T values[size]; + } +}; + +struct LocalVar { + LuaString varname; + if (header.size_of_int == 4) { + u32 startpc; + u32 endpc; + } else { + u64 startpc; + u64 endpc; + + } +}; + +struct LuaDebugInfo { + Vector localVar; + if (header.size_of_int == 4) { + Vector lineInfo; // i think this is correct + } else { + Vector lineInfo; + } + +}; + +bitfield LuaNumber { + raw : header.size_number; +}; + +struct LuaConstants{ + Vector stringConstants; + if (header.size_of_int == 4) { + Vector intConstants; + } else { + Vector intConstants; + } + Vector protos; +}; + +struct LuaFunction { + LuaString source; + if (header.size_of_int == 4) { + u32 linedefined; + u32 numparams; + } else { + u64 linedefined; + u64 numparams; + } + u8 is_vararg; + + if (header.size_of_int == 4) { + u32 maxstacksize; + } else { + u64 maxstacksize; + } + + LuaDebugInfo debugInfo; + LuaConstants luaConstants; + if (header.size_of_int == 4) { + Vector code; + } else { + Vector code; + } +}; + +LuaFunction toplevelFunction @ sizeof(header);; // Lua header size is not always the same