Skip to content

Commit 55ab783

Browse files
authored
Patch to replace console model in secret dog room (#1184)
1 parent a294cee commit 55ab783

File tree

13 files changed

+441
-104
lines changed

13 files changed

+441
-104
lines changed

Common/GfxUtils.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ HRESULT GfxCreateTextureFromFileW(LPDIRECT3DDEVICE8 device, LPCWSTR srcFile, LPD
311311
return hr;
312312
}
313313

314-
HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, DWORD fileSize, LPDIRECT3DTEXTURE8* dstTexture) {
314+
HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, DWORD fileSize, LPDIRECT3DTEXTURE8* dstTexture, BOOL* hasTransparency) {
315315
if (!device || (!fileMem || !fileSize) || !dstTexture) {
316316
return D3DERR_INVALIDCALL;
317317
}
@@ -323,10 +323,13 @@ HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, D
323323
int channels = 0;
324324
pixels = stbi_load_from_memory((stbi_uc const*)fileMem, (int)fileSize, &width, &height, &channels, STBI_rgb_alpha);
325325

326+
BOOL hasTransPixels = FALSE;
326327
if (pixels) {
327328
// convert ABGR -> ARGB
328329
for (int i = 0, numPixels = width * height; i < numPixels; ++i) {
329330
std::swap(pixels[i * 4 + 0], pixels[i * 4 + 2]);
331+
332+
hasTransPixels = hasTransPixels | (pixels[i * 4 + 3] != 0xFF);
330333
}
331334
}
332335

@@ -352,6 +355,10 @@ HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, D
352355
}
353356
}
354357

358+
if (SUCCEEDED(hr) && hasTransparency) {
359+
*hasTransparency = hasTransPixels;
360+
}
361+
355362
stbi_image_free(pixels);
356363

357364
return hr;

Common/GfxUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
HRESULT GfxCreateTextureFromFileA(LPDIRECT3DDEVICE8 device, LPCSTR srcFile, LPDIRECT3DTEXTURE8* dstTexture, DWORD flags);
1212
HRESULT GfxCreateTextureFromFileW(LPDIRECT3DDEVICE8 device, LPCWSTR srcFile, LPDIRECT3DTEXTURE8* dstTexture, DWORD flags);
1313

14-
HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, DWORD fileSize, LPDIRECT3DTEXTURE8* dstTexture);
14+
HRESULT GfxCreateTextureFromFileInMem(LPDIRECT3DDEVICE8 device, void* fileMem, DWORD fileSize, LPDIRECT3DTEXTURE8* dstTexture, BOOL* hasTransparency = nullptr);
1515

1616
#ifdef UNICODE
1717
#define GfxCreateTextureFromFile GfxCreateTextureFromFileW

Common/ModelGLTF.cpp

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ bool ModelGLTF::LoadFromFile(const std::string& filePath, IDirect3DDevice8* devi
232232
const int bonesIdx = map_contains(prim.attributes, std::string("JOINTS_0")) ? prim.attributes.at("JOINTS_0") : -1;
233233
const int weightsIdx = map_contains(prim.attributes, std::string("WEIGHTS_0")) ? prim.attributes.at("WEIGHTS_0") : -1;
234234

235+
if (uvIdx == -1) {
236+
section.numVertices = 0;
237+
continue;
238+
}
239+
235240
const tinygltf::Accessor& posAcc = model.accessors[posIdx];
236241
const tinygltf::Accessor& normAcc = model.accessors[normIdx];
237242
const tinygltf::Accessor* colorAcc = (colorIdx != -1) ? &model.accessors[colorIdx] : nullptr;
@@ -243,7 +248,7 @@ bool ModelGLTF::LoadFromFile(const std::string& filePath, IDirect3DDevice8* devi
243248
assert(posAcc.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT && posAcc.type == TINYGLTF_TYPE_VEC3);
244249
assert(normAcc.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT && normAcc.type == TINYGLTF_TYPE_VEC3);
245250
if (colorAcc) {
246-
assert((colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT || colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT || colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) && colorAcc->type == TINYGLTF_TYPE_VEC4);
251+
assert((colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT || colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT || colorAcc->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) && (colorAcc->type == TINYGLTF_TYPE_VEC4 || colorAcc->type == TINYGLTF_TYPE_VEC3));
247252
}
248253
assert(uvAcc.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT && uvAcc.type == TINYGLTF_TYPE_VEC2);
249254

@@ -377,9 +382,9 @@ bool ModelGLTF::LoadFromFile(const std::string& filePath, IDirect3DDevice8* devi
377382
mTextures.resize(model.images.size());
378383
for (size_t i = 0, n = model.images.size(); i < n; ++i) {
379384
const tinygltf::Image& img = model.images[i];
380-
IUnknownPtr<IDirect3DTexture8>& texture = mTextures[i];
385+
Texture& tex = mTextures[i];
381386

382-
HRESULT hr = GfxCreateTextureFromFileInMem(device, (void*)img.image.data(), img.image.size(), texture.ReleaseAndGetAddressOf());
387+
HRESULT hr = GfxCreateTextureFromFileInMem(device, (void*)img.image.data(), img.image.size(), tex.texture.ReleaseAndGetAddressOf(), &tex.transparent);
383388
if (FAILED(hr)) {
384389
return false;
385390
}
@@ -482,7 +487,7 @@ void ModelGLTF::Update(const float deltaInSeconds, const D3DXMATRIX& globalXForm
482487
}
483488
}
484489

485-
HRESULT ModelGLTF::Draw(IDirect3DDevice8* device) {
490+
HRESULT ModelGLTF::Draw(IDirect3DDevice8* device, BOOL enableTransparency) {
486491
const DWORD vertexSize = (mVertexType == VertexType::PosNormalTexcoord) ? sizeof(Vertex_PNT) : sizeof(Vertex_PNCT);
487492

488493
HRESULT hr = S_OK;
@@ -496,17 +501,42 @@ HRESULT ModelGLTF::Draw(IDirect3DDevice8* device) {
496501
const uint8_t* vertices = mXFormedVertices.data();
497502
const uint16_t* indices = mIndices.data();
498503

499-
uint32_t lastTextureIdx = ~0u;
500-
for (const ModelGLTF::Mesh& mesh : mMeshes) {
501-
for (const ModelGLTF::Section& section : mesh.sections) {
502-
if (section.textureIdx != lastTextureIdx) {
503-
device->SetTexture(0, mTextures[section.textureIdx].GetPtr());
504-
lastTextureIdx = section.textureIdx;
505-
}
504+
const size_t numPasses = enableTransparency ? 2 : 1;
505+
for (size_t pass = 0; pass < numPasses; ++pass) {
506+
uint32_t lastTextureIdx = ~0u;
507+
508+
for (const ModelGLTF::Mesh& mesh : mMeshes) {
509+
for (const ModelGLTF::Section& section : mesh.sections) {
510+
if (!section.numVertices) {
511+
continue;
512+
}
513+
514+
const Texture& tex = mTextures[section.textureIdx];
515+
if (enableTransparency) {
516+
if (pass == 0 && tex.transparent) {
517+
continue;
518+
} else if (pass == 1 && !tex.transparent) {
519+
continue;
520+
}
521+
}
522+
523+
if (section.textureIdx != lastTextureIdx) {
524+
device->SetTexture(0, mTextures[section.textureIdx].texture.GetPtr());
525+
lastTextureIdx = section.textureIdx;
526+
}
527+
528+
if (mUploadToGPU) {
529+
device->SetIndices(mIB.GetPtr(), section.vbOffset);
530+
device->SetStreamSource(0, mVB.GetPtr(), vertexSize);
506531

507-
hr = device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, section.numVertices, section.numIndices / 3u, indices + section.ibOffset, D3DFMT_INDEX16, vertices + section.vbOffset * vertexSize, vertexSize);
508-
if (FAILED(hr)) {
509-
return hr;
532+
hr = device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, section.numVertices, section.ibOffset, section.numIndices / 3u);
533+
} else {
534+
hr = device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, section.numVertices, section.numIndices / 3u, indices + section.ibOffset, D3DFMT_INDEX16, vertices + section.vbOffset * vertexSize, vertexSize);
535+
}
536+
537+
if (FAILED(hr)) {
538+
return hr;
539+
}
510540
}
511541
}
512542
}
@@ -557,7 +587,7 @@ size_t ModelGLTF::GetNumTextures() const {
557587
}
558588

559589
IDirect3DTexture8* ModelGLTF::GetTexture(const size_t idx) const {
560-
return mTextures[idx].GetPtr();
590+
return mTextures[idx].texture.GetPtr();
561591
}
562592

563593
const ModelGLTF::SceneNode* ModelGLTF::GetRootNode() const {

Common/ModelGLTF.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,19 @@ class ModelGLTF {
6767
std::vector<D3DXMATRIX> invBindMatrices;
6868
};
6969

70+
struct Texture {
71+
IUnknownPtr<IDirect3DTexture8> texture;
72+
BOOL transparent;
73+
};
74+
7075
public:
7176
ModelGLTF() = delete;
7277
ModelGLTF(const VertexType vtype, const bool uploadToGPU);
7378
~ModelGLTF();
7479

7580
bool LoadFromFile(const std::string& filePath, IDirect3DDevice8* device);
7681
void Update(const float deltaInSeconds, const D3DXMATRIX& globalXForm, float* customTimer = nullptr);
77-
HRESULT Draw(IDirect3DDevice8* device);
82+
HRESULT Draw(IDirect3DDevice8* device, BOOL enableTransparency = FALSE);
7883

7984
size_t GetNumMeshes() const;
8085
const Mesh& GetMesh(const size_t idx) const;
@@ -119,7 +124,7 @@ class ModelGLTF {
119124

120125
std::vector<Mesh> mMeshes;
121126

122-
using TexturesArray = std::vector<IUnknownPtr<IDirect3DTexture8>>;
127+
using TexturesArray = std::vector<Texture>;
123128
TexturesArray mTextures;
124129

125130
// scene

Common/Settings.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,3 @@ void __stdcall ParseCallback(char* lpName, char* lpValue, void*);
396396
void LogSettings();
397397
void UpdateConfigDefaults();
398398
void UpdateScaleResolution();
399-
400-

Patches/ActorDrawingHook.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "ActorDrawingHook.h"
2+
#include "Patches.h"
3+
#include "Common\Utils.h"
4+
5+
static std::vector<ActorDrawTopCallbackFn> sPrologueFunctions;
6+
static std::vector<ActorDrawTopCallbackFn> sEpilogueFunctions;
7+
8+
static void(__cdecl* ActorDrawTop)(ModelOffsetTable*, void*) = nullptr;
9+
10+
static bool sActorDrawTopFnPatched = false;
11+
12+
static void __cdecl PatchedActorDrawTop(ModelOffsetTable* pOffsetTable, void* arg2) {
13+
bool shouldSkipActualDraw = false;
14+
for (auto& fn : sPrologueFunctions) {
15+
if (fn(pOffsetTable, arg2)) {
16+
shouldSkipActualDraw = true;
17+
}
18+
}
19+
20+
if (!shouldSkipActualDraw) {
21+
ActorDrawTop(pOffsetTable, arg2);
22+
}
23+
24+
for (auto& fn : sEpilogueFunctions) {
25+
fn(pOffsetTable, arg2);
26+
}
27+
}
28+
29+
static void PatchActorDrawTop() {
30+
if (sActorDrawTopFnPatched) {
31+
return;
32+
}
33+
34+
switch (GameVersion) {
35+
case SH2V_10:
36+
ActorDrawTop = reinterpret_cast<decltype(ActorDrawTop)>(0x501F90);
37+
WriteCalltoMemory(reinterpret_cast<BYTE*>(0x50EB2B), PatchedActorDrawTop, 5);
38+
break;
39+
40+
case SH2V_11:
41+
ActorDrawTop = reinterpret_cast<decltype(ActorDrawTop)>(0x5022C0);
42+
WriteCalltoMemory(reinterpret_cast<BYTE*>(0x50EE5B), PatchedActorDrawTop, 5);
43+
break;
44+
45+
case SH2V_DC:
46+
ActorDrawTop = reinterpret_cast<decltype(ActorDrawTop)>(0x501BE0);
47+
WriteCalltoMemory(reinterpret_cast<BYTE*>(0x50E77B), PatchedActorDrawTop, 5);
48+
break;
49+
}
50+
51+
sActorDrawTopFnPatched = true;
52+
}
53+
54+
void RegisterActorDrawTopPrologue(const ActorDrawTopCallbackFn& prologueFn) {
55+
PatchActorDrawTop();
56+
57+
sPrologueFunctions.push_back(prologueFn);
58+
}
59+
60+
void RegisterActorDrawTopEpilogue(const ActorDrawTopCallbackFn& epilogueFn) {
61+
PatchActorDrawTop();
62+
63+
sEpilogueFunctions.push_back(epilogueFn);
64+
}

Patches/ActorDrawingHook.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#pragma once
2+
#define WIN32_LEAN_AND_MEAN
3+
#include <Windows.h>
4+
#include "Wrappers\d3d8\DirectX81SDK\include\d3d8.h"
5+
#include <functional>
6+
7+
struct ModelOffsetTable {
8+
int field_0;
9+
int field_4;
10+
int skeleton_points_offset;
11+
int skeleton_point_count;
12+
int skeleton_index_buffer_part_1_offset;
13+
int field_14;
14+
int skeleton_index_buffer_part_2_offset;
15+
int field_1C;
16+
int materialCount;
17+
unsigned int materialsOffset;
18+
int field_2C;
19+
unsigned int offset_30;
20+
int field_34;
21+
unsigned int offset_38;
22+
int field_3C;
23+
unsigned int offset_40;
24+
int field_44;
25+
int field_48;
26+
int field_4C;
27+
int field_50;
28+
};
29+
30+
struct ModelGeometryData {
31+
UINT numVertices;
32+
IDirect3DIndexBuffer8* indexBuffer;
33+
void* vertices;
34+
void* unknown;
35+
};
36+
37+
struct ModelMaterial {
38+
int materialLength;
39+
int reserved0;
40+
int unkU16Count0;
41+
unsigned int unkU16Array0Offset;
42+
int unkU16Count1;
43+
unsigned int unkU16Array1Offset;
44+
int unkU16Count2;
45+
unsigned int unkU16Array2Offset;
46+
unsigned int samplerStatesOffset;
47+
char materialType;
48+
char unkMaterialSubtype;
49+
char poseId;
50+
char unkByte0x27;
51+
int cullMode;
52+
float unkDiffuseFloat;
53+
float unkAmbientFloat;
54+
float specularHighlightScale;
55+
ModelGeometryData* geomData;
56+
int reserved2;
57+
float diffuseX;
58+
float diffuseR;
59+
float diffuseG;
60+
float diffuseB;
61+
float ambientX;
62+
float ambientR;
63+
float ambientG;
64+
float ambientB;
65+
float specularX;
66+
float specularR;
67+
float specularG;
68+
float specularB;
69+
int reserved3;
70+
int unkIndex;
71+
int primCount;
72+
int reserved4;
73+
};
74+
75+
using ActorDrawTopCallbackFn = std::function<bool(ModelOffsetTable*, void*)>;
76+
77+
void RegisterActorDrawTopPrologue(const ActorDrawTopCallbackFn& prologueFn);
78+
void RegisterActorDrawTopEpilogue(const ActorDrawTopCallbackFn& epilogueFn);

0 commit comments

Comments
 (0)