mirror of
https://github.com/ValveSoftware/Proton.git
synced 2025-01-16 08:38:16 +03:00
parent
957ce193f9
commit
ad8cbcfc2d
@ -603,6 +603,40 @@ PATH_CONV = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Method:
|
||||||
|
def __init__(self, sdkver, abi, cursor, index, override):
|
||||||
|
self._sdkver = sdkver
|
||||||
|
self._abi = abi
|
||||||
|
|
||||||
|
self._cursor = cursor
|
||||||
|
self._index = index
|
||||||
|
self._override = override
|
||||||
|
|
||||||
|
self.result_type = cursor.result_type
|
||||||
|
self.spelling = cursor.spelling
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
if self._override > 1: return f'{self.spelling}_{self._override}'
|
||||||
|
return self.spelling
|
||||||
|
|
||||||
|
def get_arguments(self):
|
||||||
|
return self._cursor.get_arguments()
|
||||||
|
|
||||||
|
def get_children(self):
|
||||||
|
return self._cursor.get_children()
|
||||||
|
|
||||||
|
|
||||||
|
class Destructor(Method):
|
||||||
|
def __init__(self, sdkver, abi, cursor, index, override):
|
||||||
|
super().__init__(sdkver, abi, cursor, index, override)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
if self._override > 1: return f'destructor_{self._override}'
|
||||||
|
return 'destructor'
|
||||||
|
|
||||||
|
|
||||||
class Class:
|
class Class:
|
||||||
def __init__(self, sdkver, abi, cursor):
|
def __init__(self, sdkver, abi, cursor):
|
||||||
self._sdkver = sdkver
|
self._sdkver = sdkver
|
||||||
@ -615,6 +649,28 @@ class Class:
|
|||||||
self.version = self.spelling[1:].upper()
|
self.version = self.spelling[1:].upper()
|
||||||
self.version = all_versions[sdkver][self.version]
|
self.version = all_versions[sdkver][self.version]
|
||||||
|
|
||||||
|
self._methods = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def methods(self):
|
||||||
|
if self._methods:
|
||||||
|
return self._methods
|
||||||
|
|
||||||
|
overrides = {}
|
||||||
|
is_method = lambda c: c.kind == CursorKind.CXX_METHOD and c.is_virtual_method()
|
||||||
|
in_vtable = lambda c: is_method(c) or c.kind == CursorKind.DESTRUCTOR
|
||||||
|
|
||||||
|
self._methods = []
|
||||||
|
for i, method in enumerate(filter(in_vtable, self._cursor.get_children())):
|
||||||
|
index, override = overrides.get(method.spelling, (i, 1))
|
||||||
|
overrides[method.spelling] = (index, override + 1)
|
||||||
|
if method.kind == CursorKind.DESTRUCTOR:
|
||||||
|
self._methods.append(Destructor(self._sdkver, self._abi, method, index, override))
|
||||||
|
else:
|
||||||
|
self._methods.append(Method(self._sdkver, self._abi, method, index, override))
|
||||||
|
|
||||||
|
return self._methods
|
||||||
|
|
||||||
def get_children(self):
|
def get_children(self):
|
||||||
return self._cursor.get_children()
|
return self._cursor.get_children()
|
||||||
|
|
||||||
@ -681,10 +737,10 @@ def struct_needs_conversion(struct):
|
|||||||
struct_conversion_cache[sdkver][name] = struct_needs_conversion_nocache(struct)
|
struct_conversion_cache[sdkver][name] = struct_needs_conversion_nocache(struct)
|
||||||
return struct_conversion_cache[sdkver][name]
|
return struct_conversion_cache[sdkver][name]
|
||||||
|
|
||||||
def handle_destructor(cfile, classname, winclassname, method):
|
def handle_destructor(cfile, winclassname):
|
||||||
cfile.write(f"DEFINE_THISCALL_WRAPPER({winclassname}_destructor, 4)\n")
|
cfile.write(f"DEFINE_THISCALL_WRAPPER({winclassname}_destructor, 4)\n")
|
||||||
cfile.write(f"void __thiscall {winclassname}_destructor({winclassname} *_this)\n{{/* never called */}}\n\n")
|
cfile.write(f"void __thiscall {winclassname}_destructor({winclassname} *_this)\n{{/* never called */}}\n\n")
|
||||||
return "destructor"
|
|
||||||
|
|
||||||
def get_path_converter(parent):
|
def get_path_converter(parent):
|
||||||
for conv in PATH_CONV:
|
for conv in PATH_CONV:
|
||||||
@ -708,20 +764,6 @@ def to_c_bool(b):
|
|||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
|
|
||||||
def method_unique_name(method, existing_methods):
|
|
||||||
used_name = method.spelling
|
|
||||||
if used_name in existing_methods:
|
|
||||||
number = 2
|
|
||||||
while used_name in existing_methods:
|
|
||||||
idx = existing_methods.index(used_name)
|
|
||||||
used_name = f"{method.spelling}_{number}"
|
|
||||||
number = number + 1
|
|
||||||
existing_methods.insert(idx, used_name)
|
|
||||||
else:
|
|
||||||
existing_methods.append(used_name)
|
|
||||||
return used_name
|
|
||||||
|
|
||||||
|
|
||||||
def underlying_type(decl):
|
def underlying_type(decl):
|
||||||
if type(decl) is Cursor:
|
if type(decl) is Cursor:
|
||||||
decl = decl.type
|
decl = decl.type
|
||||||
@ -763,17 +805,17 @@ def declspec(decl, name):
|
|||||||
return f'{decl.spelling}{name}'
|
return f'{decl.spelling}{name}'
|
||||||
|
|
||||||
|
|
||||||
def handle_method_hpp(method_name, cppname, method, cpp_h):
|
def handle_method_hpp(method, cppname, cpp_h):
|
||||||
ret = f'{method.result_type.spelling} '
|
ret = f'{method.result_type.spelling} '
|
||||||
if ret.startswith("ISteam"): ret = 'void *'
|
if ret.startswith("ISteam"): ret = 'void *'
|
||||||
|
|
||||||
params = [declspec(p, "") for p in method.get_arguments()]
|
params = [declspec(p, "") for p in method.get_arguments()]
|
||||||
params = ['void *'] + params
|
params = ['void *'] + params
|
||||||
|
|
||||||
cpp_h.write(f'extern {ret}{cppname}_{method_name}({", ".join(params)});\n')
|
cpp_h.write(f'extern {ret}{cppname}_{method.name}({", ".join(params)});\n')
|
||||||
|
|
||||||
|
|
||||||
def handle_method_cpp(method_name, classname, cppname, method, cpp):
|
def handle_method_cpp(method, classname, cppname, cpp):
|
||||||
ret = f'{method.result_type.spelling} '
|
ret = f'{method.result_type.spelling} '
|
||||||
if ret.startswith("ISteam"): ret = 'void *'
|
if ret.startswith("ISteam"): ret = 'void *'
|
||||||
|
|
||||||
@ -790,7 +832,7 @@ def handle_method_cpp(method_name, classname, cppname, method, cpp):
|
|||||||
names = ['linux_side'] + names
|
names = ['linux_side'] + names
|
||||||
params = ['void *linux_side'] + params
|
params = ['void *linux_side'] + params
|
||||||
|
|
||||||
cpp.write(f'{ret}{cppname}_{method_name}({", ".join(params)})\n')
|
cpp.write(f'{ret}{cppname}_{method.name}({", ".join(params)})\n')
|
||||||
cpp.write("{\n")
|
cpp.write("{\n")
|
||||||
|
|
||||||
for name, param in sorted(need_convert.items()):
|
for name, param in sorted(need_convert.items()):
|
||||||
@ -853,7 +895,7 @@ def handle_method_cpp(method_name, classname, cppname, method, cpp):
|
|||||||
cpp.write("}\n\n")
|
cpp.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
def handle_method_c(method_name, winclassname, cppname, method, cfile):
|
def handle_method_c(method, winclassname, cppname, cfile):
|
||||||
returns_record = method.result_type.get_canonical().kind == TypeKind.RECORD
|
returns_record = method.result_type.get_canonical().kind == TypeKind.RECORD
|
||||||
if returns_record:
|
if returns_record:
|
||||||
parambytes = 8 #_this + return pointer
|
parambytes = 8 #_this + return pointer
|
||||||
@ -865,14 +907,14 @@ def handle_method_c(method_name, winclassname, cppname, method, cfile):
|
|||||||
parambytes += 4
|
parambytes += 4
|
||||||
else:
|
else:
|
||||||
parambytes += int(math.ceil(param.type.get_size()/4.0) * 4)
|
parambytes += int(math.ceil(param.type.get_size()/4.0) * 4)
|
||||||
cfile.write(f"DEFINE_THISCALL_WRAPPER({winclassname}_{method_name}, {parambytes})\n")
|
cfile.write(f"DEFINE_THISCALL_WRAPPER({winclassname}_{method.name}, {parambytes})\n")
|
||||||
if method.result_type.spelling.startswith("ISteam"):
|
if method.result_type.spelling.startswith("ISteam"):
|
||||||
cfile.write(f"win{method.result_type.spelling} ")
|
cfile.write(f"win{method.result_type.spelling} ")
|
||||||
elif returns_record:
|
elif returns_record:
|
||||||
cfile.write(f"{method.result_type.spelling} *")
|
cfile.write(f"{method.result_type.spelling} *")
|
||||||
else:
|
else:
|
||||||
cfile.write(f"{method.result_type.spelling} ")
|
cfile.write(f"{method.result_type.spelling} ")
|
||||||
cfile.write(f'__thiscall {winclassname}_{method_name}({winclassname} *_this')
|
cfile.write(f'__thiscall {winclassname}_{method.name}({winclassname} *_this')
|
||||||
if returns_record:
|
if returns_record:
|
||||||
cfile.write(f", {method.result_type.spelling} *_r")
|
cfile.write(f", {method.result_type.spelling} *_r")
|
||||||
unnamed = 'a'
|
unnamed = 'a'
|
||||||
@ -915,17 +957,17 @@ def handle_method_c(method_name, winclassname, cppname, method, cfile):
|
|||||||
else:
|
else:
|
||||||
cfile.write(" return ")
|
cfile.write(" return ")
|
||||||
|
|
||||||
should_do_cb_wrap = "GetAPICallResult" in method_name
|
should_do_cb_wrap = "GetAPICallResult" in method.name
|
||||||
should_gen_wrapper = not method_needs_manual_handling(cppname, method_name) and \
|
should_gen_wrapper = not method_needs_manual_handling(cppname, method.name) and \
|
||||||
(method.result_type.spelling.startswith("ISteam") or \
|
(method.result_type.spelling.startswith("ISteam") or \
|
||||||
method_name.startswith("GetISteamGenericInterface"))
|
method.name.startswith("GetISteamGenericInterface"))
|
||||||
|
|
||||||
if should_do_cb_wrap:
|
if should_do_cb_wrap:
|
||||||
cfile.write(f"do_cb_wrap(0, &{cppname}_{method_name}, _this->linux_side")
|
cfile.write(f"do_cb_wrap(0, &{cppname}_{method.name}, _this->linux_side")
|
||||||
else:
|
else:
|
||||||
if should_gen_wrapper:
|
if should_gen_wrapper:
|
||||||
cfile.write("create_win_interface(pchVersion,\n ")
|
cfile.write("create_win_interface(pchVersion,\n ")
|
||||||
cfile.write(f"{cppname}_{method_name}(_this->linux_side")
|
cfile.write(f"{cppname}_{method.name}(_this->linux_side")
|
||||||
unnamed = 'a'
|
unnamed = 'a'
|
||||||
for param in list(method.get_children()):
|
for param in list(method.get_children()):
|
||||||
if param.kind == CursorKind.PARM_DECL:
|
if param.kind == CursorKind.PARM_DECL:
|
||||||
@ -1008,25 +1050,32 @@ WINE_DEFAULT_DEBUG_CHANNEL(steamclient);
|
|||||||
cfile.write(" vtable_ptr *vtable;\n")
|
cfile.write(" vtable_ptr *vtable;\n")
|
||||||
cfile.write(" void *linux_side;\n")
|
cfile.write(" void *linux_side;\n")
|
||||||
cfile.write(f"}} {winclassname};\n\n")
|
cfile.write(f"}} {winclassname};\n\n")
|
||||||
methods = []
|
|
||||||
for child in klass.get_children():
|
for method in klass.methods:
|
||||||
if child.kind == CursorKind.CXX_METHOD and \
|
if type(method) is Destructor:
|
||||||
child.is_virtual_method():
|
continue
|
||||||
method_name = method_unique_name(child, methods)
|
handle_method_hpp(method, cppname, cpp_h)
|
||||||
handle_method_hpp(method_name, cppname, child, cpp_h)
|
|
||||||
if not method_needs_manual_handling(cppname, method_name):
|
for method in klass.methods:
|
||||||
handle_method_cpp(method_name, klass.spelling, cppname, child, cpp)
|
if type(method) is Destructor:
|
||||||
handle_method_c(method_name, winclassname, cppname, child, cfile)
|
continue
|
||||||
elif child.kind == CursorKind.DESTRUCTOR:
|
if method_needs_manual_handling(cppname, method.spelling):
|
||||||
methods.append(handle_destructor(cfile, klass.spelling, winclassname, child))
|
continue
|
||||||
|
handle_method_cpp(method, klass.spelling, cppname, cpp)
|
||||||
|
|
||||||
|
for method in klass.methods:
|
||||||
|
if type(method) is Destructor:
|
||||||
|
handle_destructor(cfile, winclassname)
|
||||||
|
else:
|
||||||
|
handle_method_c(method, winclassname, cppname, cfile)
|
||||||
|
|
||||||
cfile.write(f"extern vtable_ptr {winclassname}_vtable;\n\n")
|
cfile.write(f"extern vtable_ptr {winclassname}_vtable;\n\n")
|
||||||
cfile.write("#ifndef __GNUC__\n")
|
cfile.write("#ifndef __GNUC__\n")
|
||||||
cfile.write("void __asm_dummy_vtables(void) {\n")
|
cfile.write("void __asm_dummy_vtables(void) {\n")
|
||||||
cfile.write("#endif\n")
|
cfile.write("#endif\n")
|
||||||
cfile.write(f" __ASM_VTABLE({winclassname},\n")
|
cfile.write(f" __ASM_VTABLE({winclassname},\n")
|
||||||
for method in methods:
|
for method in sorted(klass.methods, key=lambda x: (x._index, -x._override)):
|
||||||
cfile.write(f" VTABLE_ADD_FUNC({winclassname}_{method})\n")
|
cfile.write(f" VTABLE_ADD_FUNC({winclassname}_{method.name})\n")
|
||||||
cfile.write(" );\n")
|
cfile.write(" );\n")
|
||||||
cfile.write("#ifndef __GNUC__\n")
|
cfile.write("#ifndef __GNUC__\n")
|
||||||
cfile.write("}\n")
|
cfile.write("}\n")
|
||||||
@ -1037,7 +1086,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(steamclient);
|
|||||||
else:
|
else:
|
||||||
cfile.write(f" {winclassname} *r = alloc_mem_for_iface(sizeof({winclassname}), \"{klass.version}\");\n")
|
cfile.write(f" {winclassname} *r = alloc_mem_for_iface(sizeof({winclassname}), \"{klass.version}\");\n")
|
||||||
cfile.write(" TRACE(\"-> %p\\n\", r);\n")
|
cfile.write(" TRACE(\"-> %p\\n\", r);\n")
|
||||||
cfile.write(f" r->vtable = alloc_vtable(&{winclassname}_vtable, {len(methods)}, \"{klass.version}\");\n")
|
cfile.write(f" r->vtable = alloc_vtable(&{winclassname}_vtable, {len(klass.methods)}, \"{klass.version}\");\n")
|
||||||
cfile.write(" r->linux_side = linux_side;\n")
|
cfile.write(" r->linux_side = linux_side;\n")
|
||||||
cfile.write(" return r;\n}\n\n")
|
cfile.write(" return r;\n}\n\n")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user