mirror of
https://github.com/ValveSoftware/Proton
synced 2025-08-31 14:45:23 +00:00
lsteamclient: Generate struct definitions for all abis.
CW-Bug-Id: #22729
This commit is contained in:
committed by
Arkadiusz Hiler
parent
cafc3fb8e7
commit
7c622566cf
@@ -510,6 +510,31 @@ class Struct:
|
||||
def fields(self):
|
||||
return [f for f in self.padded_fields if type(f) is not Padding]
|
||||
|
||||
def write_definition(self, out, prefix):
|
||||
version = all_versions[sdkver][self.name]
|
||||
kind = 'union' if type(self) is Union else 'struct'
|
||||
wrapped = len(prefix) > 0
|
||||
|
||||
out(f'#pragma pack( push, {self.align} )\n')
|
||||
out(f'{kind} {prefix}{version}\n')
|
||||
out(u'{\n')
|
||||
for f in self.padded_fields:
|
||||
if type(f) is Field:
|
||||
out(f' {declspec(f._cursor, f.name, prefix, wrapped)};\n')
|
||||
else:
|
||||
out(f' uint8_t __pad_{f.offset}[{f.size}];\n')
|
||||
out(u'};\n')
|
||||
out(u'#pragma pack( pop )\n\n')
|
||||
|
||||
def write_checks(self, out, prefix):
|
||||
version = all_versions[sdkver][self.name]
|
||||
|
||||
out(f'C_ASSERT( sizeof({prefix}{version}) >= {self.size} );\n')
|
||||
for f in self.fields:
|
||||
out(f'C_ASSERT( offsetof({prefix}{version}, {f.name}) == {f.offset} );\n')
|
||||
out(f'C_ASSERT( sizeof({prefix}{version}().{f.name}) >= {f.size} );\n')
|
||||
out(u'\n')
|
||||
|
||||
def needs_conversion(self, other):
|
||||
if other.id in self._conv_cache:
|
||||
return self._conv_cache[other.id]
|
||||
@@ -751,13 +776,13 @@ def callconv(cursor, prefix):
|
||||
|
||||
|
||||
def declspec_func(decl, name, prefix):
|
||||
ret = declspec(decl.get_result(), "", prefix)
|
||||
params = [declspec(a, "", prefix) for a in decl.argument_types()]
|
||||
ret = declspec(decl.get_result(), "", prefix, False)
|
||||
params = [declspec(a, "", prefix, False) for a in decl.argument_types()]
|
||||
params = ", ".join(params) if len(params) else "void"
|
||||
return f'{ret} ({name})({params})'
|
||||
|
||||
|
||||
def declspec(decl, name, prefix):
|
||||
def declspec(decl, name, prefix, wrapped=False):
|
||||
call = callconv(decl, prefix)
|
||||
if type(decl) is Cursor:
|
||||
decl = decl.type
|
||||
@@ -768,10 +793,16 @@ def declspec(decl, name, prefix):
|
||||
return declspec_func(decl, name, prefix)
|
||||
if decl.kind in (TypeKind.POINTER, TypeKind.LVALUEREFERENCE):
|
||||
decl = decl.get_pointee()
|
||||
return declspec(decl, f"*{call}{const}{name}", prefix)
|
||||
spec = declspec(decl, f"*{call}{const}{name}", prefix, False)
|
||||
if wrapped:
|
||||
return f'{prefix.upper()}PTR({spec}, {name})'
|
||||
return spec
|
||||
if decl.kind == TypeKind.CONSTANTARRAY:
|
||||
decl, count = decl.element_type, decl.element_count
|
||||
return declspec(decl, f"({const}{name})[{count}]", prefix)
|
||||
if wrapped:
|
||||
spec = declspec(decl, const, prefix, False)
|
||||
return f'{prefix.upper()}ARRAY({spec}, {count}, {name})'
|
||||
return declspec(decl, f"({const}{name})[{count}]", prefix, False)
|
||||
|
||||
if len(name):
|
||||
name = f' {name}'
|
||||
@@ -782,6 +813,13 @@ def declspec(decl, name, prefix):
|
||||
return f'uint{decl.get_size() * 8}_t{name}'
|
||||
|
||||
type_name = decl.spelling.removeprefix("const ")
|
||||
if prefix not in (None, "win") and decl.kind == TypeKind.RECORD \
|
||||
and type_name in all_versions[sdkver] \
|
||||
and type_name not in EXEMPT_STRUCTS:
|
||||
if type_name in unique_structs:
|
||||
return f'{const}{all_versions[sdkver][type_name]}{name}'
|
||||
return f'{const}{prefix}{all_versions[sdkver][type_name]}{name}'
|
||||
|
||||
if prefix == "win" and param_needs_conversion(decl):
|
||||
return f"{const}win{type_name}_{sdkver}{name}"
|
||||
if type_name.startswith('ISteam'):
|
||||
@@ -793,6 +831,8 @@ def declspec(decl, name, prefix):
|
||||
if type_name.startswith(('uint', 'unsigned')):
|
||||
return f'{const}uint{decl.get_size() * 8}_t{name}'
|
||||
|
||||
if 'unnamed union' in decl.spelling:
|
||||
return f'{const}struct {{ uint8_t _[{decl.get_size()}]; }}{name}'
|
||||
return f'{decl.spelling}{name}'
|
||||
|
||||
|
||||
@@ -861,20 +901,20 @@ def handle_method_cpp(method, classname, cppname, out):
|
||||
type_name = underlying_typename(param)
|
||||
|
||||
if param.type.kind != TypeKind.POINTER:
|
||||
out(f' {declspec(param, f"lin_{name}", "u_")};\n')
|
||||
out(f' {declspec(param, f"lin_{name}", None)};\n')
|
||||
out(f' win_to_lin_struct_{type_name}_{sdkver}( ¶ms->{name}, &lin_{name} );\n')
|
||||
continue
|
||||
|
||||
pointee = param.type.get_pointee()
|
||||
if pointee.kind == TypeKind.POINTER:
|
||||
need_output[name] = param
|
||||
out(f' {declspec(pointee, f"lin_{name}", "u_")};\n')
|
||||
out(f' {declspec(pointee, f"lin_{name}", None)};\n')
|
||||
continue
|
||||
|
||||
if not pointee.is_const_qualified():
|
||||
need_output[name] = param
|
||||
|
||||
out(f' {declspec(pointee, f"lin_{name}", "u_")};\n')
|
||||
out(f' {declspec(pointee, f"lin_{name}", None)};\n')
|
||||
out(f' win_to_lin_struct_{type_name}_{sdkver}( params->{name}, &lin_{name} );\n')
|
||||
|
||||
for name, param in sorted(manual_convert.items()):
|
||||
@@ -1506,8 +1546,8 @@ for i, name in enumerate(all_structs.keys()):
|
||||
if not versions or sdkver not in versions: continue
|
||||
all_versions[sdkver][name] = versions[sdkver]
|
||||
|
||||
def struct_order(tuple):
|
||||
name, structs = tuple
|
||||
def struct_order(x):
|
||||
name, structs = x if type(x) is tuple else (x, all_structs[x])
|
||||
order = (struct.order for abis in structs.values()
|
||||
for struct in abis.values())
|
||||
return (min(order), name)
|
||||
@@ -1559,6 +1599,129 @@ with open('struct_converters.h', 'a') as file:
|
||||
|
||||
out(u'#endif /* __STRUCT_CONVERTERS_H */\n')
|
||||
|
||||
|
||||
declared = {}
|
||||
|
||||
with open('steamclient_structs_generated.h', 'w') as file:
|
||||
out = file.write
|
||||
|
||||
for name in sorted(unique_structs, key=struct_order):
|
||||
if name in EXEMPT_STRUCTS: continue
|
||||
for sdkver, abis in all_structs[name].items():
|
||||
if name not in all_versions[sdkver]: continue
|
||||
|
||||
version = all_versions[sdkver][name]
|
||||
if f'struct {version}' in declared: continue
|
||||
declared[f'struct {version}'] = True
|
||||
|
||||
kind = 'union' if type(abis['w64']) is Union else 'struct'
|
||||
|
||||
out(f'typedef {kind} {version} {version};\n')
|
||||
abis['w64'].write_definition(out, "")
|
||||
|
||||
for name, structs in all_structs.items():
|
||||
if name in EXEMPT_STRUCTS: continue
|
||||
if name in unique_structs: continue
|
||||
for sdkver, abis in structs.items():
|
||||
if name not in all_versions[sdkver]: continue
|
||||
|
||||
version = all_versions[sdkver][name]
|
||||
if f'typedef {version}' in declared: continue
|
||||
declared[f'typedef {version}'] = True
|
||||
|
||||
kind = 'union' if type(abis['w64']) is Union else 'struct'
|
||||
|
||||
if type(abis['w64']) is Class:
|
||||
out(f'typedef {kind} u_{version} u_{version};\n')
|
||||
out(f'typedef {kind} u_{version} u64_{version};\n')
|
||||
out(f'typedef {kind} u_{version} u32_{version};\n')
|
||||
out(f'typedef {kind} w_{version} w_{version};\n')
|
||||
out(f'typedef {kind} w_{version} w64_{version};\n')
|
||||
out(f'typedef {kind} w_{version} w32_{version};\n')
|
||||
continue
|
||||
|
||||
if abis["w64"].needs_conversion(abis["u64"]):
|
||||
out(f'typedef {kind} u64_{version} u64_{version};\n')
|
||||
else:
|
||||
out(f'typedef {kind} w64_{version} u64_{version};\n')
|
||||
out(f'typedef {kind} w64_{version} w64_{version};\n')
|
||||
|
||||
if abis["w32"].needs_conversion(abis["u32"]):
|
||||
out(f'typedef {kind} u32_{version} u32_{version};\n')
|
||||
else:
|
||||
out(f'typedef {kind} w32_{version} u32_{version};\n')
|
||||
out(f'typedef {kind} w32_{version} w32_{version};\n')
|
||||
|
||||
for name, structs in all_structs.items():
|
||||
if name in EXEMPT_STRUCTS: continue
|
||||
if name in unique_structs: continue
|
||||
for sdkver, abis in structs.items():
|
||||
if name not in all_versions[sdkver]: continue
|
||||
|
||||
version = all_versions[sdkver][name]
|
||||
if f'struct {version}' in declared: continue
|
||||
declared[f'struct {version}'] = True
|
||||
|
||||
kind = 'union' if type(abis['w64']) is Union else 'struct'
|
||||
|
||||
if type(abis['w64']) is Class:
|
||||
abis['w64'].write_definition(out, "w_")
|
||||
abis['u64'].write_definition(out, "u_")
|
||||
continue
|
||||
|
||||
abis['w64'].write_definition(out, "w64_")
|
||||
if abis["w64"].needs_conversion(abis["u64"]):
|
||||
abis['u64'].write_definition(out, "u64_")
|
||||
|
||||
abis['w32'].write_definition(out, "w32_")
|
||||
if abis["w32"].needs_conversion(abis["u32"]):
|
||||
abis['u32'].write_definition(out, "u32_")
|
||||
|
||||
out(u'#ifdef __i386__\n')
|
||||
out(f'typedef w32_{version} w_{version};\n')
|
||||
out(f'typedef u32_{version} u_{version};\n')
|
||||
out(u'#endif\n')
|
||||
out(u'#ifdef __x86_64__\n')
|
||||
out(f'typedef w64_{version} w_{version};\n')
|
||||
out(f'typedef u64_{version} u_{version};\n')
|
||||
out(u'#endif\n')
|
||||
out(u'\n')
|
||||
|
||||
|
||||
with open('unixlib_generated.cpp', 'w') as file:
|
||||
out = file.write
|
||||
|
||||
out(u'/* This file is auto-generated, do not edit. */\n\n')
|
||||
out(u'#include "steamclient_structs.h"\n\n')
|
||||
|
||||
for name in sorted(unique_structs, key=struct_order):
|
||||
for sdkver, abis in all_structs[name].items():
|
||||
if name not in all_versions[sdkver]: continue
|
||||
|
||||
version = all_versions[sdkver][name]
|
||||
if f'checks {version}' in declared: continue
|
||||
declared[f'checks {version}'] = True
|
||||
|
||||
abis['w64'].write_checks(out, "")
|
||||
|
||||
for name, structs in all_structs.items():
|
||||
if name in EXEMPT_STRUCTS: continue
|
||||
if name in unique_structs: continue
|
||||
for sdkver, abis in structs.items():
|
||||
if name not in all_versions[sdkver]: continue
|
||||
|
||||
version = all_versions[sdkver][name]
|
||||
if f'checks {version}' in declared: continue
|
||||
declared[f'checks {version}'] = True
|
||||
|
||||
if type(abis['w64']) is Class:
|
||||
continue
|
||||
|
||||
abis['w64'].write_checks(out, "w64_")
|
||||
abis['u64'].write_checks(out, "u64_")
|
||||
abis['w32'].write_checks(out, "w32_")
|
||||
abis['u32'].write_checks(out, "u32_")
|
||||
|
||||
getapifile = open("cb_getapi_table.dat", "w")
|
||||
cbsizefile = open("cb_getapi_sizes.dat", "w")
|
||||
|
||||
|
Reference in New Issue
Block a user