123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- --[[
- Sample output: https://pastebin.com/raw/ciay6HXj
- File name: "no message" (no extension)
- Instructions:
- Symlink this file into the GI working directory
- That's usually where GenshinImpact.exe is.
- Function description:
- sb_1184180413 c-call function with args
- Hints for modifying this script:
- 1) There is mostly no error handling in GI!
- 2) Run the script in Lua CLI (i.e. 'lua "no message"') to check for syntax errors
- 3) Uncomment functions until you see basic log information again
- ]]
- local HOOK_RECURSIVE = true -- more precise hooks, but may stall the game
- local LH = {} -- file-wide access
- local function dump(val, depth, seen)
- depth = depth or 0
- seen = seen or {}
- if seen[val] then return "<CIRCULAR REF>" end
- if depth > 10 then return "<TOO DEEP>" end
- if val == nil then return "nil" end
- local txt = {}
- if type(val) == "table" then
- seen[val] = true
- txt[#txt + 1] = "{"
- for k, v in pairs(val) do
- txt[#txt + 1] = string.rep("\t", depth + 1) ..
- ("[\"%s\"] = %s"):format(tostring(k), dump(v, depth + 1, seen))
- end
- txt[#txt + 1] = string.rep("\t", depth) .. "}"
- elseif type(val) == "string" then
- txt[#txt + 1] = '"' .. val:gsub('\n', "$LF"):gsub('"', '\\"') .. '"'
- else
- txt[#txt + 1] = tostring(val)
- end
- return table.concat(txt, "\n")
- end
- local F = io.open("lualog_" .. os.date("%H%M-%S") .. ".txt", "a")
- F:write("=== LOG START: " .. os.date() .. "\n")
- local function LOG(msg)
- F:write(msg)
- F:write("\n")
- end
- -- HOOK FUNCTIONS
- table.unpack = table.unpack or unpack -- Lua compatibility
- local hooked = {}
- local function hook_wrapper(func, name, ...)
- LOG(("> CALL %s = %s"):format(name, dump({...}, 1)))
- local ret_vals = {func(...)}
- LOG(("< RET %s = %s"):format(name, dump(ret_vals, 1)))
- LH.interval_func()
- return table.unpack(ret_vals)
- end
- local function hook_recursive(tb, k, v, path)
- path = path or ""
- v = v or tb[k] or tb
- if hooked[v] then
- return
- end
- -- If a custom table is provided, hook all functions
- if type(v) == "table" then
- if not HOOK_RECURSIVE and v ~= _G then
- return
- end
- if v == table or v == io or v == math
- or v == debug or v == string then
- return
- end
- -- Traverse table to hook all functions
- hooked[v] = true
- for k2, v2 in pairs(v) do
- if type(v2) == "table" then
- hook_recursive(v, k2, v2, path..k2..".")
- else
- hook_recursive(v, k2, v2, path)
- end
- end
- return
- end
- if type(v) ~= "function" then
- return
- end
- -- Do not hook common functions to avoid recursion
- if k == "tostring" or k == "type" or k == "sethook" or k == "typeof"
- or k == "ipairs" or k == "pairs" or k == "next" or k == "select"
- or k == "print"
- or k == "rawset" or k == "rawget"
- or k == "setmetatable" or k == "getmetatable" then
- return
- end
- LOG("HOOK " .. path .. k)
- tb[k] = function(...)
- return hook_wrapper(v, path .. k, ...)
- end
- hooked[tb[k]] = true
- end
- -- INTERVAL-TRIGGERED FUNCTIONS
- -- socket.gettime() cannot be loaded
- local last_time = 0
- local get_time = os.time
- local set_hook = debug.sethook
- LH.interval_func = function()
- if get_time() < last_time + 2 then
- return
- end
- last_time = get_time()
- LOG("=== DUMP OF _G")
- LOG(dump(_G))
- hook_recursive(_G)
- -- Manual function triggering
- set_hook(LH.interval_func, "r", 1000)
- end
- set_hook(LH.interval_func, "rl", 1)
- hook_recursive(_G)
- rawget(_G, "test call, returns nil")
|