138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
import json
|
|
import os
|
|
|
|
def resolve_enum_size(size):
|
|
if (size == 1):
|
|
return "byte"
|
|
if (size == 4):
|
|
return "int"
|
|
raise Exception("Unknown size {}".format(size))
|
|
|
|
def write_enum(enum, enumNames):
|
|
namespace = str.capitalize(enum["filename"])
|
|
filename = "Generated/{}/{}.cs".format(namespace, enum["name"])
|
|
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
with open(filename, "w") as f:
|
|
f.write("// AUTOMATICALLY GENERATED, DO NOT EDIT\n")
|
|
f.write("using System.Diagnostics.CodeAnalysis;\n\n")
|
|
f.write("namespace {}\n{{\n".format(namespace))
|
|
f.write(" [SuppressMessage(\"ReSharper\", \"InconsistentNaming\")]\n")
|
|
f.write(" internal enum {} : {}\n {{\n".format(enum["name"], resolve_enum_size(enum["byteSize"]) ))
|
|
for k, v in enum["values"].items():
|
|
f.write(" {} = {},\n".format(v, k))
|
|
f.write(" }\n")
|
|
f.write("}\n")
|
|
enumNames.add(enum["name"])
|
|
|
|
class funcDef:
|
|
def __init__(self, name, returns, parameters):
|
|
self.name = name
|
|
self.returns = returns
|
|
self.parameters = parameters
|
|
|
|
class classDef:
|
|
def __init__(self, namespace, name, file):
|
|
self.namespace = namespace
|
|
self.file = file
|
|
self.name = name
|
|
self.functions = []
|
|
|
|
def register_function(self, func):
|
|
self.functions.append(func)
|
|
|
|
def parse_function(function, classDict):
|
|
splitName = function["name"].split("_")
|
|
classKey = "{}_{}".format(function["filename"], splitName[1])
|
|
if (not classKey in classDict):
|
|
classDict[classKey] = classDef(function["filename"].capitalize(), splitName[1], function["filename"])
|
|
|
|
classDict[classKey].register_function(funcDef(function["name"], function["returns"], function["parameters"]))
|
|
|
|
def parse_type(type, enumSet):
|
|
type = type.strip();
|
|
if (type == "void"):
|
|
return "void"
|
|
if (type == "unsigned char"):
|
|
return "byte"
|
|
if (type == "signed char"):
|
|
return "sbyte"
|
|
if (type == "unsigned short"):
|
|
return "ushort"
|
|
if (type == "bool"):
|
|
return "byte"
|
|
if (type == "float"):
|
|
return "float"
|
|
if (type == "double"):
|
|
return "double"
|
|
if (type == "long unsigned int"):
|
|
return "ulong"
|
|
if (type == "long int"):
|
|
return "long"
|
|
if (type == "unsigned int"):
|
|
return "uint"
|
|
if (type == "int"):
|
|
return "int"
|
|
if (type.endswith("*")):
|
|
return "IntPtr"
|
|
if (type.endswith("&")):
|
|
return "ref " + parse_type(type[:-1], enumSet)
|
|
if (type in enumSet):
|
|
return type
|
|
print("Unhandled type '{}'".format(type))
|
|
return "void"
|
|
|
|
def clean_name(name):
|
|
if (name == "out"):
|
|
return "@out"
|
|
return name
|
|
|
|
def write_class(c, enumSet):
|
|
filename = "Generated/{}/{}.cs".format(c.file.capitalize(), c.name)
|
|
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
with open(filename, "w") as f:
|
|
f.write("// AUTOMATICALLY GENERATED, DO NOT EDIT\n")
|
|
f.write("using System;\n")
|
|
f.write("using System.Runtime.InteropServices;\n\n")
|
|
f.write("namespace {}.Generated\n{{\n".format(c.namespace))
|
|
f.write(" internal static class {}\n {{\n".format(c.name))
|
|
for function in c.functions:
|
|
for parameter in function.parameters:
|
|
f.write(" /// <param name=\"{}\">{}</param>\n".format(parameter["name"], parameter["type"]))
|
|
f.write(" /// <returns>{}</returns>\n".format(function.returns))
|
|
f.write(" [DllImport(\"{}\", CallingConvention = CallingConvention.Cdecl, EntryPoint= \"{}\")]\n".format(c.file, function.name))
|
|
f.write(" internal static extern {} {}(".format(parse_type(function.returns, enumSet), function.name.split("_")[2]))
|
|
isFirst = True
|
|
for parameter in function.parameters:
|
|
if (not isFirst):
|
|
f.write(", ")
|
|
else:
|
|
isFirst = False
|
|
f.write("{} {}".format(parse_type(parameter["type"], enumSet), clean_name(parameter["name"])))
|
|
|
|
f.write(");\n\n")
|
|
f.write(" }\n")
|
|
f.write("}\n")
|
|
|
|
|
|
def parse_create(data, filepath):
|
|
enumSet = set()
|
|
for enum in data["enums"]:
|
|
write_enum(enum, enumSet)
|
|
classDict = dict()
|
|
for function in data["functions"]:
|
|
parse_function(function, classDict)
|
|
print("Registered {} classes from file {}.".format(len(classDict), filepath))
|
|
for _, v in classDict.items():
|
|
write_class(v, enumSet)
|
|
|
|
def handle_file(filepath):
|
|
with open(filepath) as json_file:
|
|
data = json.load(json_file)
|
|
parse_create(data, filepath)
|
|
|
|
def main():
|
|
handle_file("arbutils.json")
|
|
handle_file("creaturelib.json")
|
|
handle_file("pkmnlib.json")
|
|
|
|
main() |