diff --git a/vrclient_x64/gen_wrapper.py b/vrclient_x64/gen_wrapper.py index c510d82b..bdd93fac 100755 --- a/vrclient_x64/gen_wrapper.py +++ b/vrclient_x64/gen_wrapper.py @@ -91,6 +91,17 @@ files = [ ), ] +path_conversions = [ + { + "parent_name": "SetActionManifestPath", + "l2w_names":[], + "l2w_lens":[], + "w2l_names": ["pchActionManifestPath"], + "w2l_arrays": [False], + "return_is_size": False + } +] + aliases = { #Some interface versions are not present in the public SDK #headers, but are actually requested by games. It would be nice @@ -211,6 +222,21 @@ def display_sdkver(s): def strip_ns(name): return name.replace("vr::","") +def get_path_converter(parent): + for conv in path_conversions: + if conv["parent_name"] in parent.spelling: + if None in conv["l2w_names"]: + return conv + if type(parent) == clang.cindex.Type: + children = list(parent.get_fields()) + else: + children = list(parent.get_children()) + for child in children: + if child.spelling in conv["w2l_names"] or \ + child.spelling in conv["l2w_names"]: + return conv + return None + def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, existing_methods, iface_version): used_name = method.spelling if used_name in existing_methods: @@ -283,13 +309,23 @@ def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, e cpp.write(")\n{\n") cpp_h.write(");\n") - char_param_is_unix_path = "GetAppInstallDir" in used_name or \ - "GetItemInstallInfo" in used_name - path_param_name = None - path_size_param_name = None + path_conv = get_path_converter(method) - if char_param_is_unix_path: - cfile.write(" uint32 path_result;\n") + if path_conv: + for i in range(len(path_conv["w2l_names"])): + if path_conv["w2l_arrays"][i]: + cfile.write(" const char **lin_%s = steamclient_dos_to_unix_stringlist(%s);\n" % (path_conv["w2l_names"][i], path_conv["w2l_names"][i])) + # TODO + pass + else: + cfile.write(" char lin_%s[PATH_MAX];\n" % path_conv["w2l_names"][i]) + cfile.write(" steamclient_dos_path_to_unix_path(%s, lin_%s);\n" % (path_conv["w2l_names"][i], path_conv["w2l_names"][i])) + if None in path_conv["l2w_names"]: + cfile.write(" const char *path_result;\n") + elif path_conv["return_is_size"]: + cfile.write(" uint32 path_result;\n") + elif len(path_conv["l2w_names"]) > 0: + cfile.write(" %s path_result;\n" % method.result_type.spelling) if do_lin_to_win: cpp.write(" %s lin;\n" % do_lin_to_win[0]) @@ -304,7 +340,7 @@ def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, e if method.result_type.kind == clang.cindex.TypeKind.VOID: cfile.write(" ") cpp.write(" ") - elif char_param_is_unix_path: + elif path_conv and (len(path_conv["l2w_names"]) > 0 or path_conv["return_is_size"]): cfile.write(" path_result = ") cpp.write(" return ") elif returns_record: @@ -344,37 +380,37 @@ def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, e cpp.write(", ") else: first = False - if char_param_is_unix_path: - if param.type.spelling == "char *": - path_param_name = param.spelling - elif not path_param_name is None and \ - (param.type.spelling == "uint32" or - param.type.spelling == "int"): - path_size_param_name = param.spelling if param.spelling == "": cfile.write(", _%s" % unnamed) cpp.write("(%s)_%s" % (param.type.spelling, unnamed)) unnamed = chr(ord(unnamed) + 1) else: - cfile.write(", %s" % param.spelling) if do_lin_to_win and do_lin_to_win[1] == param.spelling or \ do_wrap and do_wrap[1] == param.spelling: + cfile.write(", %s" % param.spelling) cpp.write("&lin") if do_lin_to_win and \ (do_lin_to_win[0] == "VREvent_t" or \ do_lin_to_win[0] == "VRControllerState001_t"): next_is_size = True elif do_unwrap and do_unwrap[1] == param.spelling: + cfile.write(", %s" % param.spelling) cpp.write("struct_%s_%s_unwrap(%s)" % (strip_ns(do_unwrap[0]), display_sdkver(sdkver), do_unwrap[1])) + elif path_conv and param.spelling in path_conv["w2l_names"]: + cfile.write(", %s ? lin_%s : NULL" % (param.spelling, param.spelling)) + cpp.write("(%s)%s" % (param.type.spelling, param.spelling)) elif next_is_size: + cfile.write(", %s" % param.spelling) next_is_size = False if param.type.spelling == "uint32_t": cpp.write("sizeof(lin)") else: cpp.write("(%s)%s" % (param.type.spelling, param.spelling)) elif "&" in param.type.spelling: + cfile.write(", %s" % param.spelling) cpp.write("*%s" % param.spelling) else: + cfile.write(", %s" % param.spelling) cpp.write("(%s)%s" % (param.type.spelling, param.spelling)) if should_gen_wrapper: cfile.write(")") @@ -388,8 +424,18 @@ def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, e cpp.write(");\n") if returns_record: cfile.write(" return _r;\n") - if char_param_is_unix_path and not path_param_name is None and not path_size_param_name is None: - cfile.write(" return steamclient_unix_path_to_dos_path(path_result, %s, %s);\n" % (path_param_name, path_size_param_name)) + if path_conv and len(path_conv["l2w_names"]) > 0: + for i in range(len(path_conv["l2w_names"])): + assert(path_conv["l2w_names"][i]) #otherwise, no name means string is in return value. needs special handling. + cfile.write(" ") + if path_conv["return_is_size"]: + cfile.write("path_result = ") + cfile.write("steamclient_unix_path_to_dos_path(path_result, %s, %s, %s);\n" % (path_conv["l2w_names"][i], path_conv["l2w_names"][i], path_conv["l2w_lens"][i])) + cfile.write(" return path_result;\n") + if path_conv: + for i in range(len(path_conv["w2l_names"])): + if path_conv["w2l_arrays"][i]: + cfile.write(" steamclient_free_stringlist(lin_%s);\n" % path_conv["w2l_names"][i]) if do_lin_to_win: cpp.write(" struct_%s_%s_lin_to_win(&lin, %s);\n" % (strip_ns(do_lin_to_win[0]), display_sdkver(sdkver), do_lin_to_win[1])) cpp.write(" return _ret;\n") @@ -975,7 +1021,7 @@ for sdkver in sdk_versions: if not os.path.isfile(input_name): continue index = clang.cindex.Index.create() - tu = index.parse(input_name, args=['-x', 'c++', '-std=c++11', '-DGNUC', '-Iopenvr_%s/' % sdkver, '-I/usr/lib/clang/7.0.0/include/']) + tu = index.parse(input_name, args=['-x', 'c++', '-std=c++11', '-DGNUC', '-Iopenvr_%s/' % sdkver, '-I/usr/lib/clang/7.0.1/include/']) diagnostics = list(tu.diagnostics) if len(diagnostics) > 0: diff --git a/vrclient_x64/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_x64/vrclient_main.c index b36829a5..f5ce0ae7 100644 --- a/vrclient_x64/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_x64/vrclient_main.c @@ -52,6 +52,53 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) return TRUE; } +#define IS_ABSOLUTE(x) (*x == '/' || *x == '\\' || (*x && *(x + 1) == ':')) + +/* returns non-zero on success, zero on failure */ +bool steamclient_dos_path_to_unix_path(const char *src, char *dst) +{ + *dst = 0; + + if(!src || !*src) + return 0; + + if(IS_ABSOLUTE(src)){ + /* absolute path, use wine conversion */ + WCHAR srcW[PATH_MAX]; + char *unix_path; + uint32_t r; + + r = MultiByteToWideChar(CP_UNIXCP, 0, src, -1, srcW, PATH_MAX); + if(r == 0) + return 0; + + unix_path = wine_get_unix_file_name(srcW); + if(!unix_path){ + WARN("Unable to convert DOS filename to unix: %s\n", src); + return 0; + } + + strncpy(dst, unix_path, PATH_MAX); + + HeapFree(GetProcessHeap(), 0, unix_path); + }else{ + /* relative path, just fix up backslashes */ + const char *s; + char *d; + + for(s = src, d = dst; *src; ++s, ++d){ + if(*s == '\\') + *d = '/'; + else + *d = *s; + } + + *d = 0; + } + + return 1; +} + static BOOL array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) { SIZE_T max_capacity, new_capacity; diff --git a/vrclient_x64/vrclient_x64/vrclient_private.h b/vrclient_x64/vrclient_x64/vrclient_private.h index 6dbd4863..9ef5c689 100644 --- a/vrclient_x64/vrclient_x64/vrclient_private.h +++ b/vrclient_x64/vrclient_x64/vrclient_private.h @@ -1,4 +1,5 @@ #include +#include /* 32-bit Mac doesn't support Vulkan and thus DXVK */ #if !defined(__APPLE__) || defined(__x86_64__) @@ -37,6 +38,7 @@ typedef struct __winX winX; void *create_win_interface(const char *name, void *linux_side); unsigned int steamclient_unix_path_to_dos_path(unsigned int api_result, char *inout, unsigned int inout_bytes); +bool steamclient_dos_path_to_unix_path(const char *src, char *dst); void *create_LinuxMatchmakingServerListResponse(void *win); #ifndef __cplusplus diff --git a/vrclient_x64/vrclient_x64/winIVRInput.c b/vrclient_x64/vrclient_x64/winIVRInput.c index da8c3dea..276667f0 100644 --- a/vrclient_x64/vrclient_x64/winIVRInput.c +++ b/vrclient_x64/vrclient_x64/winIVRInput.c @@ -28,8 +28,10 @@ typedef struct __winIVRInput_IVRInput_005 { DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_005_SetActionManifestPath, 12) EVRInputError __thiscall winIVRInput_IVRInput_005_SetActionManifestPath(winIVRInput_IVRInput_005 *_this, const char * pchActionManifestPath) { + char lin_pchActionManifestPath[PATH_MAX]; + steamclient_dos_path_to_unix_path(pchActionManifestPath, lin_pchActionManifestPath); TRACE("%p\n", _this); - return cppIVRInput_IVRInput_005_SetActionManifestPath(_this->linux_side, pchActionManifestPath); + return cppIVRInput_IVRInput_005_SetActionManifestPath(_this->linux_side, pchActionManifestPath ? lin_pchActionManifestPath : NULL); } DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_005_GetActionSetHandle, 20) @@ -301,8 +303,10 @@ typedef struct __winIVRInput_IVRInput_004 { DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_004_SetActionManifestPath, 12) EVRInputError __thiscall winIVRInput_IVRInput_004_SetActionManifestPath(winIVRInput_IVRInput_004 *_this, const char * pchActionManifestPath) { + char lin_pchActionManifestPath[PATH_MAX]; + steamclient_dos_path_to_unix_path(pchActionManifestPath, lin_pchActionManifestPath); TRACE("%p\n", _this); - return cppIVRInput_IVRInput_004_SetActionManifestPath(_this->linux_side, pchActionManifestPath); + return cppIVRInput_IVRInput_004_SetActionManifestPath(_this->linux_side, pchActionManifestPath ? lin_pchActionManifestPath : NULL); } DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_004_GetActionSetHandle, 20) @@ -520,8 +524,10 @@ typedef struct __winIVRInput_IVRInput_003 { DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_003_SetActionManifestPath, 12) EVRInputError __thiscall winIVRInput_IVRInput_003_SetActionManifestPath(winIVRInput_IVRInput_003 *_this, const char * pchActionManifestPath) { + char lin_pchActionManifestPath[PATH_MAX]; + steamclient_dos_path_to_unix_path(pchActionManifestPath, lin_pchActionManifestPath); TRACE("%p\n", _this); - return cppIVRInput_IVRInput_003_SetActionManifestPath(_this->linux_side, pchActionManifestPath); + return cppIVRInput_IVRInput_003_SetActionManifestPath(_this->linux_side, pchActionManifestPath ? lin_pchActionManifestPath : NULL); } DEFINE_THISCALL_WRAPPER(winIVRInput_IVRInput_003_GetActionSetHandle, 20)