Bootstrap decomp of Tgl rendering library (#293)

* Bootstrap decomp of D3DRM rendering code

* This PR kicks off work on decompiling the D3D Retained Mode (D3DRM)
  rendering part of the codebase.

* High level overview:

* There is a base IMxDirect3DRMObject class which all of the D3DRM
  rendering objects inherit from. Its only virtual method is one to get
  the underlying object handle.

* A hierarchy of abstract classes inherits from this base class, which
  I've called "IMxDirect3DRM<class>". These classes only have pure
  virtual methods on them and don't contain any data.

* Each one of the abstract classes has exactly one concrete
  implementation, which I've called "MxDirect3DRM<class>". These classes
  have exactly one piece of data, which is a pointer to the underlying
  D3D Retained Mode object.

* If the classes need to store additional data, they store it in a
  userdata blob which is attached to the D3DRM object rather than the
  additional data being stored in the class itself.

* I've worked out about twice this many classes related to D3DRM
  rendering so far but the PR was getting large enough as is, so I'm
  cutting it here for now.

* I decomped sufficiently many methods of these classe to convince
  myself that the above observations are correct. About 60% of the
  decomped methods here are perfect matches, including at least one
  non-trivial method per class.

* Formatting

* Restructure changes using Tgl naming / details

* Restructure the changes to use the naming that we know from Tgl.

* Fill in some parts of the implementation I couldn't initially figure
  out using the details from Tgl (got more 100% matches).

* Move d3drm link requirement

* Fixups FloatMatrix -> FloatMatrix4

* Fix order

* Full fix for ordering problems

* Put back accidentally removed include.

* Fix call which should have been Release

* Use new and delete for DeepClone

* Missing Tgl:: on CreateRenderer

* Revert change to bool return value.

* Rename Something -> Unk

* Return paramter naming convention to what Tgl used

* Add scalar ddtor to verify inline destructor

* Fix order

* Change malloc/free -> new/delete in Tgl

* Remove duplicate destructor.

* Check all inline destructors

* Fix dtor comments

* Third time's the charm

* Alphabetical sort

* Decomp adjustments

* Add d3drm files to clang-format

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
This commit is contained in:
Mark Langen
2023-12-07 04:10:42 -08:00
committed by GitHub
parent 8bf0bde6b9
commit 260772e374
15 changed files with 1976 additions and 186 deletions

View File

@@ -1,27 +1,22 @@
#ifndef TGL_H
#define TGL_H
#ifdef _WIN32
#ifndef _tgl_h
#define _tgl_h
#include "tglvector.h"
#define NOMINMAX // to avoid conflict with STL
#include <d3d.h>
#include <ddraw.h>
#include <windows.h> // HWND
#endif /* _WIN32 */
#include "tglVector.h"
#include <windows.h>
namespace Tgl
{
// ???
enum ColorModel {
// Note: Not used in shipped game, no way to verify contents.
Ramp,
RGB
};
// ???
enum ShadingModel {
Wireframe,
UnlitFlat,
@@ -30,7 +25,6 @@ enum ShadingModel {
Phong
};
// ?????
enum LightType {
Ambient,
Point,
@@ -39,7 +33,6 @@ enum LightType {
ParallelPoint
};
// ???
enum ProjectionType {
Perspective,
Orthographic
@@ -50,39 +43,39 @@ enum TextureMappingMode {
PerspectiveCorrect
};
// Not in the Tgl leak, inferred from the assembly
enum MaterialMode {
FromParent,
FromFrame,
FromMesh,
};
struct PaletteEntry {
unsigned char m_red;
unsigned char m_green;
unsigned char m_blue;
};
#ifdef _WIN32
struct DeviceDirectDrawCreateData {
const GUID* m_driverGUID;
HWND m_hWnd; // ??? derive from m_pDirectDraw
IDirectDraw* m_pDirectDraw;
IDirectDrawSurface* m_pFrontBuffer; // ??? derive from m_pDirectDraw
IDirectDrawSurface* m_pBackBuffer;
IDirectDrawPalette* m_pPalette; // ??? derive from m_pDirectDraw
int m_isFullScreen; // ??? derive from m_pDirectDraw
};
struct DeviceDirect3DCreateData {
IDirect3D* m_pDirect3D;
IDirect3DDevice* m_pDirect3DDevice;
};
#else
struct DeviceDirectDrawCreateData {
const GUID* m_driverGUID;
HWND m_hWnd;
IDirectDraw* m_pDirectDraw;
IDirectDrawSurface* m_pFrontBuffer;
IDirectDrawSurface* m_pBackBuffer;
struct DeviceDirectDrawCreateData {};
#endif
//////////////////////////////////////////////////////////////////////////////
//
// Result (return value type)
// These have possibly been removed in the shipped game
// (Put them back if we can verify when we find a callsite
// which constructs this type)
// IDirectDrawPalette* m_pPalette;
// int m_isFullScreen;
};
// Result type used for all methods in the Tgl API
enum Result {
Error = 0,
Success = 1
@@ -93,10 +86,7 @@ inline int Succeeded(Result result)
return (result == Success);
}
//////////////////////////////////////////////////////////////////////////////
//
// Forward declarations
class Renderer;
class Object;
class Device;
@@ -106,30 +96,24 @@ class Camera;
class Group;
class Mesh;
class Texture;
class Unk;
//////////////////////////////////////////////////////////////////////////////
//
// Object
// VTABLE 0x100db980
class Object {
public:
virtual ~Object() {}
// returns pointer to implementation data
virtual void* ImplementationDataPtr() = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Renderer
// ??? for now until we figured out how an app should pass the Renderer around
Renderer* CreateRenderer();
// VTABLE 0x100db948
class Renderer : public Object {
public:
virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0;
// vtable+0x08
virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0;
virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0;
// vtable+0x10
virtual View* CreateView(
const Device*,
const Camera*,
@@ -139,34 +123,12 @@ public:
unsigned long height
) = 0;
virtual Camera* CreateCamera() = 0;
virtual Light* CreateLight(LightType, double r, double g, double b) = 0;
virtual Light* CreateLight(LightType, float r, float g, float b) = 0;
virtual Group* CreateGroup(const Group* pParent = 0) = 0;
// pTextureCoordinates is pointer to array of vertexCount elements
// (each element being two floats), or NULL
// pFaceData is faceCount tuples, each of format
// [vertex1index, ... vertexNindex], where N = vertexPerFaceCount
virtual Mesh* CreateMesh(
unsigned long vertexCount,
const float (*pVertices)[3],
const float (*pTextureCoordinates)[2],
unsigned long faceCount,
unsigned long vertexPerFaceCount,
unsigned long* pFaceData
) = 0;
// pTextureCoordinates is pointer to array of vertexCount elements
// (each element being two floats), or NULL
// pFaceData is:
// [face1VertexCount face1Vertex1index, ... face1VertexMindex
// face2VertexCount face2Vertex1index, ... face2VertexNindex
// ...
// 0]
virtual Mesh* CreateMesh(
unsigned long vertexCount,
const float (*pVertices)[3],
const float (*pTextureCoordinates)[2],
unsigned long* pFaceData
) = 0;
// vtable+0x20
virtual Unk* CreateUnk() = 0;
virtual Texture* CreateTexture() = 0;
virtual Texture* CreateTexture(
int width,
int height,
@@ -176,61 +138,54 @@ public:
int paletteEntryCount,
const PaletteEntry* pEntries
) = 0;
virtual Texture* CreateTexture() = 0;
virtual Result SetTextureDefaultShadeCount(unsigned long) = 0;
// vtable+0x30
virtual Result SetTextureDefaultColorCount(unsigned long) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Device
Renderer* CreateRenderer();
// VTABLE 0x100db9b8
class Device : public Object {
public:
// vtable+0x08
virtual unsigned long GetWidth() = 0;
virtual unsigned long GetHeight() = 0;
// vtable+0x10
virtual Result SetColorModel(ColorModel) = 0;
virtual Result SetShadingModel(ShadingModel) = 0;
virtual Result SetShadeCount(unsigned long) = 0;
virtual Result SetDither(int) = 0;
// vtable+0x20
virtual Result Update() = 0;
// ??? should this be handled by app ???
// ??? this needs to be called when the window on which the device is ...
// is being activated
virtual void HandleActivate(int bActivate) = 0;
// ??? this needs to be called when the window on which this device is based
// needs to be repainted
virtual void HandlePaint(void*) = 0;
#ifdef _DEBUG
virtual unsigned long GetDrawnTriangleCount() = 0;
#endif
virtual void InitFromD3DDevice(Device*) = 0;
virtual void InitFromWindowsDevice(Device*) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// View
// VTABLE 0x100dba28
class View : public Object {
public:
virtual Result Add(const Light*) = 0;
virtual Result Remove(const Light*) = 0;
// vtable+0x10
virtual Result SetCamera(const Camera*) = 0;
virtual Result SetProjection(ProjectionType) = 0;
virtual Result SetFrustrum(double frontClippingDistance, double backClippingDistance, double degrees) = 0;
virtual Result SetBackgroundColor(double r, double g, double b) = 0;
virtual Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) = 0;
virtual Result SetBackgroundColor(float r, float g, float b) = 0;
// vtable+0x20
virtual Result GetBackgroundColor(float* r, float* g, float* b) = 0;
virtual Result Clear() = 0;
virtual Result Render(const Group*) = 0;
// ??? needed for fine grain control when using DirectDraw/D3D ???
virtual Result Render(const Light*) = 0;
virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) = 0;
// ??? for now: used by Mesh Cost calculation
virtual Result TransformWorldToScreen(const double world[3], double screen[4]) = 0;
// vtable+0x30
virtual Result TransformWorldToScreen(const float world[3], float screen[4]) = 0;
virtual Result TransformScreenToWorld(const float screen[4], float world[3]) = 0;
// Pick():
// x, y:
@@ -264,102 +219,94 @@ public:
) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Camera
// VTABLE 0x100dbae8
class Camera : public Object {
public:
#if 0
virtual Result SetPosition(const double[3]) = 0;
virtual Result SetOrientation(const double direction[3],
const double up[3]) = 0;
#endif
virtual Result SetTransformation(const FloatMatrix4&) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Light
// VTABLE 0x100dbb08
class Light : public Object {
public:
#if 0
virtual Result SetPosition(const double[3]) = 0;
virtual Result SetOrientation(const double direction[3],
const double up[3]) = 0;
#endif
virtual Result SetTransformation(const FloatMatrix4&) = 0;
virtual Result SetColor(float r, float g, float b) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Group
class Group : public Object {
public:
#if 0
virtual Result SetPosition(const double[3]) = 0;
virtual Result SetOrientation(const double direction[3],
const double up[3]) = 0;
#endif
// TODO: The type was changed from `FloatMatrix` to `Matrix` to make code in UpdateWorldData match.
// However, this is unlikely to be correct and will have to be figured out at some point.
virtual Result SetTransformation(const Matrix4&) = 0;
// ??? not yet fully implemented
virtual Result SetColor(double r, double g, double b) = 0;
virtual Result SetTexture(const Texture*) = 0;
virtual Result Add(const Group*) = 0;
virtual Result Add(const Mesh*) = 0;
virtual Result Remove(const Group*) = 0;
virtual Result Remove(const Mesh*) = 0;
virtual Result RemoveAll() = 0;
// ??? for now: used by Mesh Cost calculation
virtual Result TransformLocalToWorld(const double local[3], double world[3]) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Mesh
// VTABLE 0x100dbbb0
class Mesh : public Object {
public:
// ??? also on Group
virtual Result SetColor(double r, double g, double b) = 0;
virtual Result SetColor(float r, float g, float b, float a) = 0;
virtual Result SetTexture(const Texture*) = 0;
virtual Result SetTextureMappingMode(TextureMappingMode) = 0;
virtual Result GetTexture(Texture*&) = 0;
virtual Result SetTextureMappingMode(ProjectionType) = 0;
virtual Result SetShadingModel(ShadingModel) = 0;
#ifdef _DEBUG
virtual Result GetBoundingBox(float min[3], float max[3]) = 0;
virtual unsigned long GetFaceCount() = 0;
virtual unsigned long GetVertexCount() = 0;
#endif
// Clone data in underlying group
virtual Mesh* DeepClone(Unk*) = 0;
// Just get another Group pointing to the same underlying data
virtual Mesh* ShallowClone(Unk*) = 0;
};
//////////////////////////////////////////////////////////////////////////////
//
// Texture
// VTABLE 0x100dbaa0
class Group : public Object {
public:
virtual Result SetTransformation(const FloatMatrix4&) = 0;
virtual Result SetColor(float r, float g, float b, float a) = 0;
virtual Result SetTexture(const Texture*) = 0;
virtual Result GetTexture(Texture*&) = 0;
virtual Result SetMaterialMode(MaterialMode) = 0;
virtual Result Add(const Group*) = 0;
virtual Result Add(const Mesh*) = 0;
virtual Result Remove(const Group*) = 0;
virtual Result Remove(const Mesh*) = 0;
virtual Result RemoveAll() = 0;
// This is TransformLocalToWorld in the leak, however it seems
// to have been replaced by something else in the shipped code.
virtual Result Unknown() = 0;
};
// Don't know what this is. Seems like another Tgl object which
// was not in the leaked Tgl code. My suspicion is that it's
// some kind of builder class for creating meshes.
// VTABLE 0x100dbb30
class Unk : public Object {
public:
virtual Result SetMeshData(
unsigned long faceCount,
unsigned long vertexCount,
const float (*pPositions)[3],
const float (*pNormals)[3],
const float (*pTextureCoordinates)[2],
unsigned long vertexPerFaceCount,
unsigned long* pFaceData
) = 0;
virtual Result GetBoundingBox(float min[3], float max[3]) = 0;
virtual Unk* Clone() = 0;
};
// VTABLE 0x100dbb68
class Texture : public Object {
public:
virtual Result SetTexels(
int width,
int height,
int bitsPerTexel,
const void* pTexels,
int pTexelsArePersistent
) = 0;
virtual Result SetPalette(int entryCount, const PaletteEntry* pEntries) = 0;
};
// vtable+0x08
virtual Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels) = 0;
virtual void FillRowsOfTexture(int y, int height, void* pBuffer) = 0;
//////////////////////////////////////////////////////////////////////////////
// vtable+0x10
virtual Result Changed(int texelsChanged, int paletteChanged) = 0;
virtual Result GetBufferAndPalette(
int* pWidth,
int* pHeight,
int* pDepth,
void** ppBuffer,
int* pPaletteSize,
PaletteEntry** ppPalette
) = 0;
virtual Result SetPalette(int entryCount, PaletteEntry* pEntries) = 0;
};
} // namespace Tgl
#endif // TGL_H
#endif /* _tgl_h */