diff --git a/patches/d3dx9_36_controller/0001-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-return-defa.patch b/patches/d3dx9_36_controller/0001-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-return-defa.patch new file mode 100644 index 00000000..6652fa66 --- /dev/null +++ b/patches/d3dx9_36_controller/0001-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-return-defa.patch @@ -0,0 +1,27 @@ +From 1772b5826cbd3adef3f5c09e6c0138a8d367fc8b Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 28 Sep 2023 09:14:00 +1000 +Subject: [PATCH 1/3] d3dx9: D3DXLoadMeshHierarchyFromXInMemory return default + Animation Controller + +--- + dlls/d3dx9_36/mesh.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c +index 8aa4ece69fb..442b56a7e19 100644 +--- a/dlls/d3dx9_36/mesh.c ++++ b/dlls/d3dx9_36/mesh.c +@@ -4019,7 +4019,8 @@ HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memo + if (anim_controller) + { + *anim_controller = NULL; +- FIXME("Animation controller creation not implemented.\n"); ++ /*FIXME("Animation controller creation not implemented.\n");*/ ++ D3DXCreateAnimationController(1, 1, 1, 1, anim_controller); + } + + cleanup: +-- +2.40.1 + diff --git a/patches/d3dx9_36_controller/0002-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-support-emp.patch b/patches/d3dx9_36_controller/0002-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-support-emp.patch new file mode 100644 index 00000000..7d40a940 --- /dev/null +++ b/patches/d3dx9_36_controller/0002-d3dx9-D3DXLoadMeshHierarchyFromXInMemory-support-emp.patch @@ -0,0 +1,169 @@ +From c79c2913f06f0fe703f00ca324270e0551ca7027 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 28 Sep 2023 12:35:29 +1000 +Subject: [PATCH] d3dx9: D3DXLoadMeshHierarchyFromXInMemory support empty mesh. + +--- + dlls/d3dx9_36/mesh.c | 36 ++++++++++++++++++++++++----- + dlls/d3dx9_36/tests/mesh.c | 46 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 77 insertions(+), 5 deletions(-) + +diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c +index 442b56a7e19..c85a9774fdd 100644 +--- a/dlls/d3dx9_36/mesh.c ++++ b/dlls/d3dx9_36/mesh.c +@@ -3506,6 +3506,16 @@ HRESULT WINAPI D3DXLoadSkinMeshFromXof(struct ID3DXFileData *filedata, DWORD opt + hr = parse_mesh(filedata, &mesh_data, provide_flags); + if (FAILED(hr)) goto cleanup; + ++ if (mesh_data.num_vertices == 0) ++ { ++ if (adjacency_out) *adjacency_out = NULL; ++ if (materials_out) *materials_out = NULL; ++ if (effects_out) *effects_out = NULL; ++ *mesh_out = NULL; ++ hr = D3D_OK; ++ goto cleanup; ++ } ++ + total_vertices = mesh_data.num_vertices; + if (mesh_data.fvf & D3DFVF_NORMAL) { + /* duplicate vertices with multiple normals */ +@@ -3815,7 +3825,8 @@ static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options + hr = filedata_get_name(filedata, &name); + if (FAILED(hr)) goto cleanup; + +- hr = alloc_hier->lpVtbl->CreateMeshContainer(alloc_hier, name, &mesh_data, ++ if (mesh_data.pMesh) ++ hr = alloc_hier->lpVtbl->CreateMeshContainer(alloc_hier, name, &mesh_data, + materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL, + effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL, + num_materials, +@@ -4201,13 +4212,21 @@ static HRESULT parse_frame(struct ID3DXFileData *filedata, DWORD options, struct + hr = E_OUTOFMEMORY; + goto err; + } +- list_add_tail(container_list, &container->entry); +- container->transform = transform; + + hr = D3DXLoadSkinMeshFromXof(child, options, device, + (provide_flags & PROVIDE_ADJACENCY) ? &container->adjacency : NULL, + (provide_flags & PROVIDE_MATERIALS) ? &container->materials : NULL, + NULL, &container->num_materials, NULL, &container->mesh); ++ ++ if (container->mesh) ++ { ++ list_add_tail(container_list, &container->entry); ++ container->transform = transform; ++ } ++ else ++ { ++ HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, container); ++ } + } else if (IsEqualGUID(&type, &TID_D3DRMFrameTransformMatrix)) { + D3DXMATRIX new_transform; + hr = parse_transform_matrix(child, &new_transform); +@@ -4295,13 +4314,20 @@ HRESULT WINAPI D3DXLoadMeshFromXInMemory(const void *memory, DWORD memory_size, + hr = E_OUTOFMEMORY; + goto cleanup; + } +- list_add_tail(&container_list, &container_ptr->entry); +- D3DXMatrixIdentity(&container_ptr->transform); + + hr = D3DXLoadSkinMeshFromXof(filedata, options, device, + (provide_flags & PROVIDE_ADJACENCY) ? &container_ptr->adjacency : NULL, + (provide_flags & PROVIDE_MATERIALS) ? &container_ptr->materials : NULL, + NULL, &container_ptr->num_materials, NULL, &container_ptr->mesh); ++ if (container_ptr->mesh) ++ { ++ list_add_tail(&container_list, &container_ptr->entry); ++ D3DXMatrixIdentity(&container_ptr->transform); ++ } ++ else ++ { ++ HeapFree(GetProcessHeap(), 0, container_ptr); ++ } + } else if (IsEqualGUID(&guid, &TID_D3DRMFrame)) { + hr = parse_frame(filedata, options, device, &identity, &container_list, provide_flags); + } +diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c +index ce0f238412d..21428f12e26 100644 +--- a/dlls/d3dx9_36/tests/mesh.c ++++ b/dlls/d3dx9_36/tests/mesh.c +@@ -2068,6 +2068,14 @@ static void D3DXLoadMeshTest(void) + "}" + "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" + "}"; ++ static const char framed_xfile2[] = ++ "xof 0303txt 0032" ++ "Frame Box01 {" ++ "Mesh { 0;; 0;;" ++ "MeshNormals { 0;; 0;; }" ++ "}" ++ "}"; ++ + static const WORD framed_index_buffer[] = { 0, 1, 2 }; + static const D3DXVECTOR3 framed_vertex_buffers[3][3] = { + {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}}, +@@ -2513,6 +2521,19 @@ static void D3DXLoadMeshTest(void) + frame_hier = NULL; + } + ++ hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile2, sizeof(framed_xfile2) - 1, ++ D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); ++ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); ++ if (SUCCEEDED(hr)) { ++ D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; ++ ++ ok(!strcmp(frame_hier->Name, "Box01"), "Expected '', got '%s'\n", frame_hier->Name); ++ ok(container == NULL, "Expected NULL, got %p\n", container); ++ ++ hr = D3DXFrameDestroy(frame_hier, &alloc_hier); ++ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); ++ frame_hier = NULL; ++ } + + hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); +@@ -11426,6 +11447,9 @@ static void test_load_skin_mesh_from_xof(void) + "1;" + "3; 0, 1, 2;;" + "}"; ++ static const char simple_xfile_empty[] = ++ "xof 0303txt 0032" ++ "Mesh { 0;; 0;; }"; + static const D3DVERTEXELEMENT9 expected_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, +@@ -11537,6 +11561,28 @@ static void test_load_skin_mesh_from_xof(void) + mesh->lpVtbl->Release(mesh); + adjacency->lpVtbl->Release(adjacency); + file_data->lpVtbl->Release(file_data); ++ ++ /* Empty Mesh Test */ ++ file_data = get_mesh_data(simple_xfile_empty, sizeof(simple_xfile_empty) - 1); ++ ok(!!file_data, "Failed to load mesh data.\n"); ++ ++ adjacency = materials = effects = (void *)0xdeadbeef; ++ count = ~0u; ++ skin_info = (void *)0xdeadbeef; ++ mesh = (void *)0xdeadbeef; ++ ++ hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count, ++ &skin_info, &mesh); ++ todo_wine ok(hr == D3DXERR_LOADEDMESHASNODATA, "Got unexpected hr %#lx.\n", hr); ++ ok(!adjacency, "Got unexpected value %p.\n", adjacency); ++ ok(!materials, "Got unexpected value %p.\n", materials); ++ ok(!effects, "Got unexpected value %p.\n", effects); ++ ok(count == ~0u, "Got unexpected value %lu.\n", count); ++ ok(skin_info == (void *)0xdeadbeef, "Got unexpected value %p.\n", skin_info); ++ ok(!mesh, "Got unexpected value %p.\n", mesh); ++ ++ file_data->lpVtbl->Release(file_data); ++ + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); + DestroyWindow(hwnd); +-- +2.42.0 + diff --git a/patches/d3dx9_36_controller/0003-d3dx9-HACK-D3DXIntersect-Assign-hit-to-FALSE.patch b/patches/d3dx9_36_controller/0003-d3dx9-HACK-D3DXIntersect-Assign-hit-to-FALSE.patch new file mode 100644 index 00000000..de827945 --- /dev/null +++ b/patches/d3dx9_36_controller/0003-d3dx9-HACK-D3DXIntersect-Assign-hit-to-FALSE.patch @@ -0,0 +1,28 @@ +From 164c33e29bfe06d99c58c1ee73dfd6f31dc4c663 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Sat, 30 Sep 2023 10:18:54 +1000 +Subject: [PATCH] d3dx9: [HACK] D3DXIntersect - Assign hit to FALSE + +This functions needs to be implement to make "Humanity Asset" to work correctly. + +Added to stop the Infinite loop - Doesn't make the game playable. +--- + dlls/d3dx9_36/mesh.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c +index 822b2d7d410..fdc642c4e0c 100644 +--- a/dlls/d3dx9_36/mesh.c ++++ b/dlls/d3dx9_36/mesh.c +@@ -7645,6 +7645,8 @@ HRESULT WINAPI D3DXIntersect(ID3DXBaseMesh *mesh, const D3DXVECTOR3 *ray_pos, co + FIXME("mesh %p, ray_pos %p, ray_dir %p, hit %p, face_index %p, u %p, v %p, distance %p, all_hits %p, " + "count_of_hits %p stub!\n", mesh, ray_pos, ray_dir, hit, face_index, u, v, distance, all_hits, count_of_hits); + ++ *hit = FALSE; ++ + return E_NOTIMPL; + } + +-- +2.42.0 + diff --git a/patches/d3dx9_36_controller/definition b/patches/d3dx9_36_controller/definition new file mode 100644 index 00000000..95d8d1af --- /dev/null +++ b/patches/d3dx9_36_controller/definition @@ -0,0 +1,4 @@ +Fixes: [39876] d3dx9: D3DXLoadMeshHierarchyFromXInMemory return a dummy ID3DXAnimationController. + +# This allow Humanity Asset to get in game - Doesn't make the game playable though. +# Requires D3DXIntersect to be implemented.