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 <werwolv98@gmail.com>
This commit is contained in:
tympanicblock61
2025-12-05 15:54:19 -05:00
committed by GitHub
parent ee340409db
commit 2a9676238f
2 changed files with 134 additions and 0 deletions

View File

@@ -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 |

133
patterns/lua40.hexpat Normal file
View File

@@ -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<T> {
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> localVar;
if (header.size_of_int == 4) {
Vector<u32> lineInfo; // i think this is correct
} else {
Vector<u64> lineInfo;
}
};
bitfield LuaNumber {
raw : header.size_number;
};
struct LuaConstants{
Vector<LuaString> stringConstants;
if (header.size_of_int == 4) {
Vector<u32> intConstants;
} else {
Vector<u64> intConstants;
}
Vector<LuaFunction> 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<u32> code;
} else {
Vector<u64> code;
}
};
LuaFunction toplevelFunction @ sizeof(header);; // Lua header size is not always the same