From 4287fb4b8f6f6a26d533ec18e496c85f22c4bcfe Mon Sep 17 00:00:00 2001 From: TheIndra55 Date: Fri, 16 Aug 2024 22:39:00 +0200 Subject: [PATCH] Implement DRAW_DrawLines in TRA --- src/cdc/render/PCPrimitivePool.cpp | 42 ++++++++++++++++++ src/cdc/render/PCPrimitivePool.h | 42 ++++++++++++++++++ src/cdc/render/PCVertexPool.cpp | 9 ++++ src/cdc/render/PCVertexPool.h | 54 +++++++++++++++++++++++ src/cdc/render/TransientHeapAllocator.cpp | 14 ++++++ src/cdc/render/TransientHeapAllocator.h | 15 +++++++ src/render/Draw.cpp | 51 ++++++++++----------- 7 files changed, 199 insertions(+), 28 deletions(-) create mode 100644 src/cdc/render/PCPrimitivePool.cpp create mode 100644 src/cdc/render/PCPrimitivePool.h create mode 100644 src/cdc/render/PCVertexPool.cpp create mode 100644 src/cdc/render/PCVertexPool.h create mode 100644 src/cdc/render/TransientHeapAllocator.cpp create mode 100644 src/cdc/render/TransientHeapAllocator.h diff --git a/src/cdc/render/PCPrimitivePool.cpp b/src/cdc/render/PCPrimitivePool.cpp new file mode 100644 index 0000000..33c9560 --- /dev/null +++ b/src/cdc/render/PCPrimitivePool.cpp @@ -0,0 +1,42 @@ +#include "PCPrimitivePool.h" +#include "util/Hooking.h" + +void* cdc::PCPrimitivePool::AllocateVertices(unsigned int numVerts) +{ + unsigned int baseOffset; + auto vertices = m_vertexPool.Create(numVerts, &baseOffset); + auto offset = 0; + + auto currentPrimitive = m_currentPrimitive->currentPrimitive; + + if (currentPrimitive && currentPrimitive->vertexBuffer == vertices) + { + offset = currentPrimitive->numVertices * m_stride; + currentPrimitive->numVertices += numVerts; + } + else + { + auto primitive = (PartialPrimitive*)m_pFrameHeap->Alloc(sizeof(PartialPrimitive)); + + primitive->baseOffset = baseOffset; + primitive->next = nullptr; + primitive->numVertices = numVerts; + primitive->vertexBuffer = vertices; + + if (m_currentPrimitive->currentPrimitive) + { + m_currentPrimitive->currentPrimitive->next = primitive; + } + else + { + m_currentPrimitive->firstPrimitive = primitive; + } + + m_currentPrimitive->currentPrimitive = primitive; + } + + m_currentPrimitive->totalNumVertices += numVerts; + m_totalNumVertices += numVerts; + + return (char*)vertices->m_pVertexData + offset; +} \ No newline at end of file diff --git a/src/cdc/render/PCPrimitivePool.h b/src/cdc/render/PCPrimitivePool.h new file mode 100644 index 0000000..29d8972 --- /dev/null +++ b/src/cdc/render/PCPrimitivePool.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include "TransientHeapAllocator.h" +#include "PCVertexPool.h" + +namespace cdc +{ + class PCPrimitivePool + { + private: + TransientHeapAllocator* m_pFrameHeap; + + PCBasicVertexPool m_vertexPool; + D3DPRIMITIVETYPE m_primType; + + unsigned int m_primVerts; + unsigned int m_totalNumVertices; + unsigned int m_stride; + + struct PartialPrimitive + { + PCDynamicVertexBuffer* vertexBuffer; + unsigned int numVertices; + unsigned int baseOffset; + PartialPrimitive* next; + }; + + struct Primitive + { + PartialPrimitive* firstPrimitive; + PartialPrimitive* currentPrimitive; + unsigned int totalNumVertices; + }; + + Primitive* m_currentPrimitive; + + public: + void* AllocateVertices(unsigned int numVerts); + }; +} \ No newline at end of file diff --git a/src/cdc/render/PCVertexPool.cpp b/src/cdc/render/PCVertexPool.cpp new file mode 100644 index 0000000..966c065 --- /dev/null +++ b/src/cdc/render/PCVertexPool.cpp @@ -0,0 +1,9 @@ +#include "PCVertexPool.h" +#include "util/Hooking.h" + +cdc::PCDynamicVertexBuffer* cdc::PCBasicVertexPool::Create(unsigned int numVertices, unsigned int* baseOffsetInVerts) +{ + auto addr = GET_ADDRESS(0xECDE60, 0x61F840, 0x000000); + + return Hooking::ThisCallReturn(addr, this, numVertices, baseOffsetInVerts); +} \ No newline at end of file diff --git a/src/cdc/render/PCVertexPool.h b/src/cdc/render/PCVertexPool.h new file mode 100644 index 0000000..1f81849 --- /dev/null +++ b/src/cdc/render/PCVertexPool.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include "TransientHeapAllocator.h" + +namespace cdc +{ + class PCVertexFormat + { + }; + + class PCVertexBufferMemPool + { + }; + + class PCVertexBuffer + { + public: + virtual ~PCVertexBuffer() = 0; + + virtual unsigned int GetBaseVertexIndex() = 0; + virtual IDirect3DVertexBuffer9* GetD3DVertexBuffer() = 0; + virtual IDirect3DVertexDeclaration9* GetD3DVertexDeclaration() = 0; + virtual unsigned int GetNumVertices() = 0; + virtual unsigned __int16 GetStride() = 0; + }; + + class PCDynamicVertexBuffer : public PCVertexBuffer + { + public: + IDirect3DVertexBuffer9* m_pD3DVertexBuffer; + void* m_pVertexData; + PCVertexFormat* m_pVertexFormat; + unsigned int m_baseVertexIndex; + unsigned int m_numVertices; + }; + + class PCBasicVertexPool + { + private: + PCVertexFormat* m_pVertexFormat; + cdc::PCVertexBufferMemPool* m_pVertexBufferMemPool; + TransientHeapAllocator* m_pFrameHeap; + IDirect3DVertexBuffer9* m_pLastVB; + cdc::PCDynamicVertexBuffer* m_pLastSharedVB; + unsigned int m_nVertices; + + public: + PCDynamicVertexBuffer* Create(unsigned int numVertices, unsigned int* baseOffsetInVerts); + + virtual ~PCBasicVertexPool() { }; + }; +} \ No newline at end of file diff --git a/src/cdc/render/TransientHeapAllocator.cpp b/src/cdc/render/TransientHeapAllocator.cpp new file mode 100644 index 0000000..872fea5 --- /dev/null +++ b/src/cdc/render/TransientHeapAllocator.cpp @@ -0,0 +1,14 @@ +#include "TransientHeapAllocator.h" + +char* cdc::TransientHeapAllocator::Alloc(unsigned int size) +{ + auto ptr = m_freePtr; + + if (ptr + size > m_size) + { + return nullptr; + } + + m_freePtr += size; + return &m_pHeap[ptr]; +} \ No newline at end of file diff --git a/src/cdc/render/TransientHeapAllocator.h b/src/cdc/render/TransientHeapAllocator.h new file mode 100644 index 0000000..aeb87c4 --- /dev/null +++ b/src/cdc/render/TransientHeapAllocator.h @@ -0,0 +1,15 @@ +#pragma once + +namespace cdc +{ + class TransientHeapAllocator + { + private: + char* m_pHeap; + unsigned int m_size; + unsigned int m_freePtr; + + public: + char* Alloc(unsigned int size); + }; +} \ No newline at end of file diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index fde86f3..1f4baa8 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -1,6 +1,11 @@ #include "Draw.h" #include "util/Hooking.h" +#ifdef TRAE +#include "cdc/render/PCDeviceManager.h" +#include "cdc/render/PCPrimitivePool.h" +#endif + void TRANS_TransToDrawVertexV4f(DRAWVERTEX* v, cdc::Vector3* vec) { auto addr = GET_ADDRESS(0x402EF0, 0x402F20, 0x49F990); @@ -40,9 +45,27 @@ void DRAW_DrawQuads(int flags, int tpage, DRAWVERTEX* verts, int numquads) void DRAW_DrawLines(LINEVERTEX* verts, int numlines) { +#ifndef TRAE auto addr = GET_ADDRESS(0x406120, 0x000000, 0x5BFCD0); Hooking::Call(addr, verts, numlines); +#else + // The DRAW_DrawLines method has been optimized away in Anniversary + // the code below is a reimplementation of the code from Legend + if (cdc::PCDeviceManager::s_pInstance->IsStatusOk()) + { + auto linePool = *(cdc::PCPrimitivePool**)0x7545E0; + auto vertices = (LINEVERTEX*)linePool->AllocateVertices(numlines * 2); + + for (int i = 0; i < numlines * 2; i++) + { + vertices[i] = verts[i]; + + // Swap RGBA to ARGB + vertices[i].color = (verts[i].color << 24) | (verts[i].color >> 8); + } + } +#endif } void DRAW_DrawTriangles(int flags, int tpage, DRAWVERTEX* verts, int numtris) @@ -111,33 +134,6 @@ void DrawPlane(cdc::Vector3* v0, cdc::Vector3* v1, int color) void DrawLine(cdc::Vector3* v0, cdc::Vector3* v1, int color) { -#ifdef TRAE - DRAWVERTEX verts[6]; - - auto v2 = *v1; - auto v3 = *v0; - - v2.z += 20.f; - v3.z += 20.f; - v2.y += 20.f; - v3.y += 20.f; - - TransformToDrawVertex(verts, v0); - TransformToDrawVertex(&verts[1], &v2); - TransformToDrawVertex(&verts[2], v1); - TransformToDrawVertex(&verts[3], &v3); - TransformToDrawVertex(&verts[4], v1); - TransformToDrawVertex(&verts[5], v0); - - verts[0].color = color; - verts[1].color = color; - verts[2].color = color; - verts[3].color = color; - verts[4].color = color; - verts[5].color = color; - - DRAW_DrawTriangles(2, 0, verts, 2); -#else LINEVERTEX lines[2]; TransformToLineVertex(lines, v0); @@ -147,7 +143,6 @@ void DrawLine(cdc::Vector3* v0, cdc::Vector3* v1, int color) lines[1].color = color; DRAW_DrawLines(lines, 1); -#endif } void DrawBoundingBox(cdc::Vector3* v0, cdc::Vector3* v1, int color)