mirror of
https://github.com/LostArtefacts/TR2X.git
synced 2024-12-13 08:26:47 +00:00
172 lines
4.8 KiB
Python
Executable File
172 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import re
|
|
from collections.abc import Callable, Iterable
|
|
from dataclasses import dataclass
|
|
from enum import StrEnum
|
|
from pathlib import Path
|
|
|
|
from tr2x.ida_progress import Symbol, parse_progress_file
|
|
from tr2x.paths import TR2X_PROGRESS_FILE, TR2X_SRC_DIR
|
|
|
|
FUNCS_H_FILE = TR2X_SRC_DIR / "global/funcs.h"
|
|
VARS_H_FILE = TR2X_SRC_DIR / "global/vars.h"
|
|
TYPES_H_FILE = TR2X_SRC_DIR / "global/types.h"
|
|
|
|
|
|
COMMON_HEADER = [
|
|
"// This file is autogenerated. To update it, run tools/generate_funcs.",
|
|
"",
|
|
"#pragma once",
|
|
"",
|
|
]
|
|
|
|
|
|
def make_func_pointer_define(function: Symbol) -> str:
|
|
if match := re.match(
|
|
r"(?P<ret_type>.+?\W)(?P<func_name>\b\w+)\s*\((?P<args>.+)\);?",
|
|
function.signature,
|
|
):
|
|
ret_type = match.group("ret_type").strip()
|
|
func_name = match.group("func_name").strip()
|
|
args = match.group("args").strip()
|
|
return f"#define {func_name} (({ret_type} (*)({args})){function.offset_str})"
|
|
return ""
|
|
|
|
|
|
def make_var_pointer_define(variable: Symbol) -> str:
|
|
if match := re.match(
|
|
r"^"
|
|
r"(?P<ret_type>.+?)\s*"
|
|
r"\("
|
|
r"\s*\*(?P<call_type>.*?\s)\s*(?P<func_name>\w+)"
|
|
r"(?P<array_def>\[[^\]]*?\]+)?"
|
|
r"\)\s*"
|
|
r"\((?P<args>.+)\)"
|
|
r";?$",
|
|
variable.signature,
|
|
):
|
|
ret_type = match.group("ret_type")
|
|
call_type = match.group("call_type")
|
|
array_def = match.group("array_def")
|
|
func_name = match.group("func_name")
|
|
args = match.group("args")
|
|
if array_def:
|
|
return f"#define {func_name} (*(({ret_type}({call_type} *(*){array_def})({args})){variable.offset_str}))"
|
|
else:
|
|
return f"#define {func_name} (*({ret_type}({call_type}**)({args})){variable.offset_str})"
|
|
|
|
if match := re.match(
|
|
r"^"
|
|
r"(?P<ret_type>.+?)\s*"
|
|
r"(?P<var_name>\b\w+)\s*"
|
|
r"(?P<array_def>(?:\[[^\]]*?\])*)"
|
|
r"(\s*=\s*(?P<value_def>.*?))?"
|
|
r";?"
|
|
r"(\s*\/\/\s*(?P<comment>.*))?"
|
|
r"$",
|
|
variable.signature,
|
|
):
|
|
ret_type = match.group("ret_type")
|
|
var_name = match.group("var_name")
|
|
array_def = match.group("array_def")
|
|
value_def = match.group("value_def")
|
|
comment = match.group("comment")
|
|
if not array_def and not value_def and comment == "no-dereferencing":
|
|
return f"#define {var_name} (({ret_type}){variable.offset_str})"
|
|
if array_def:
|
|
return f"#define {var_name} (*({ret_type}(*){array_def}){variable.offset_str})"
|
|
elif value_def:
|
|
return f"#define {var_name} (*({ret_type}*){variable.offset_str}) // = {value_def}"
|
|
else:
|
|
return f"#define {var_name} (*({ret_type}*){variable.offset_str})"
|
|
|
|
print("warn: unrecognized signature", variable.signature)
|
|
return ""
|
|
|
|
|
|
def make_funcs_h(functions: list[Symbol]) -> None:
|
|
header = [
|
|
*COMMON_HEADER,
|
|
'#include "global/types.h"',
|
|
"",
|
|
"// clang-format off",
|
|
]
|
|
footer = ["// clang-format on"]
|
|
|
|
defines = []
|
|
for function in functions:
|
|
if "+" not in function.flags and (
|
|
define := make_func_pointer_define(function)
|
|
):
|
|
defines.append(define)
|
|
|
|
FUNCS_H_FILE.write_text("\n".join([*header, *defines, *footer]) + "\n")
|
|
|
|
|
|
def make_vars_h(variables: list[Symbol]) -> None:
|
|
header = [
|
|
*COMMON_HEADER,
|
|
'#include "global/types.h"',
|
|
'#include "inject_util.h"',
|
|
"",
|
|
"// clang-format off",
|
|
"extern const char *g_TR2XVersion;",
|
|
]
|
|
footer = [
|
|
"",
|
|
"// clang-format on",
|
|
]
|
|
|
|
defines = []
|
|
for variable in sorted(variables, key=lambda symbol: symbol.offset):
|
|
if "+" not in variable.flags and (
|
|
define := make_var_pointer_define(variable)
|
|
):
|
|
defines.append(define)
|
|
|
|
VARS_H_FILE.write_text("\n".join([*header, *defines, *footer]) + "\n")
|
|
|
|
|
|
def make_types_h(types: list[str]) -> None:
|
|
header = [
|
|
*COMMON_HEADER,
|
|
"#include <ddraw.h>",
|
|
"#include <ddrawi.h>",
|
|
"#include <d3dhal.h>",
|
|
"#include <dsound.h>",
|
|
"#include <stdbool.h>",
|
|
"#include <stdint.h>",
|
|
"#include <windows.h>",
|
|
"",
|
|
"#pragma pack(push, 1)",
|
|
"",
|
|
"// clang-format off",
|
|
]
|
|
footer = [
|
|
"",
|
|
"// clang-format on",
|
|
]
|
|
|
|
TYPES_H_FILE.write_text(
|
|
"\n".join(
|
|
[
|
|
*header,
|
|
"\n\n".join([definition.strip() for definition in types]),
|
|
*footer,
|
|
]
|
|
)
|
|
+ "\n"
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
progress_file = parse_progress_file(TR2X_PROGRESS_FILE)
|
|
|
|
make_funcs_h(progress_file.functions)
|
|
make_vars_h(progress_file.variables)
|
|
make_types_h(progress_file.types)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|