diff --git a/CMakeLists.txt b/CMakeLists.txt index 39112c3e..3940380c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,13 +113,6 @@ add_library(lego1 SHARED LEGO1/mxcontrolpresenter.cpp LEGO1/mxcore.cpp LEGO1/mxcriticalsection.cpp - LEGO1/mxdirect3d.cpp - LEGO1/mxdirect3drm.cpp - LEGO1/mxdirect3drmclasses.cpp - LEGO1/mxdirect3drmdevice.cpp - LEGO1/mxdirect3drmobject.cpp - LEGO1/mxdirect3drmtexture.cpp - LEGO1/mxdirect3drmviewport.cpp LEGO1/mxdirectdraw.cpp LEGO1/mxdiskstreamcontroller.cpp LEGO1/mxdiskstreamprovider.cpp @@ -216,6 +209,15 @@ add_library(lego1 SHARED LEGO1/score.cpp LEGO1/scorestate.cpp LEGO1/skateboard.cpp + LEGO1/tgl/d3drm/camera.cpp + LEGO1/tgl/d3drm/device.cpp + LEGO1/tgl/d3drm/group.cpp + LEGO1/tgl/d3drm/light.cpp + LEGO1/tgl/d3drm/mesh.cpp + LEGO1/tgl/d3drm/renderer.cpp + LEGO1/tgl/d3drm/something.cpp + LEGO1/tgl/d3drm/texture.cpp + LEGO1/tgl/d3drm/view.cpp LEGO1/towtrack.cpp LEGO1/towtrackmissionstate.cpp LEGO1/viewmanager/viewmanager.cpp diff --git a/LEGO1/mxdirect3drm.cpp b/LEGO1/mxdirect3drm.cpp deleted file mode 100644 index 113dd9a5..00000000 --- a/LEGO1/mxdirect3drm.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "mxdirect3drm.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(IMxDirect3DRM, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRM, 0x8); - -// OFFSET: LEGO1 0x1010103c -IDirect3DRM* g_pD3DRM = NULL; - -// Inlined only -MxDirect3DRM::MxDirect3DRM() : m_pD3DRM(NULL) -{ - if (g_pD3DRM == NULL) { - LPDIRECT3DRM handle; - Direct3DRMCreate(&handle); - handle->QueryInterface(IID_IDirect3DRM2, (LPVOID*) &g_pD3DRM); - } - else { - m_pD3DRM->AddRef(); - } - m_pD3DRM = g_pD3DRM; -} - -// Inlined only -MxDirect3DRM::~MxDirect3DRM() -{ - if (m_pD3DRM) { - if (m_pD3DRM->Release() == 0) - g_pD3DRM = NULL; - m_pD3DRM = NULL; - } -} - -// OFFSET: LEGO1 0x100a15e0 -MxDirect3DRM* MxDirect3DRM::Create() -{ - // Not a close match. The separate create function implies that - // the g_pD3DRM handling stuff should be in here rather than in the - // constructor, but the destructor definitely calls Release() on - // g_pD3DRM and that implies the opposite. - return new MxDirect3DRM(); -} - -// OFFSET: LEGO1 0x100a22b0 -IUnknown** MxDirect3DRM::GetHandle() -{ - return (IUnknown**) &m_pD3DRM; -} - -// OFFSET: LEGO1 0x100a1894 STUB -MxDirect3DRMDevice* MxDirect3DRM::CreateDeviceFromD3D(D3DHolder* p_holder) -{ - return NULL; -} - -// OFFSET: LEGO1 0x100a1900 STUB -MxDirect3DRMDevice* MxDirect3DRM::CreateDeviceFromSurface(D3DSurfaceHolder* p_holder) -{ - return NULL; -} diff --git a/LEGO1/mxdirect3drm.h b/LEGO1/mxdirect3drm.h deleted file mode 100644 index e4e109f3..00000000 --- a/LEGO1/mxdirect3drm.h +++ /dev/null @@ -1,42 +0,0 @@ - -#include "ddraw.h" -#include "mxdirect3drmdevice.h" - -// Not sure what the deal is with these small holder structs. They might -// actually be the first part of a larger class because I haven't worked out -// enough code further up the call chain to work my way back to a constructor. -struct D3DHolder { - IDirect3D* m_pDirect3D; - IDirect3DDevice* m_pDirect3DDevice; -}; - -struct D3DSurfaceHolder { - IDirectDraw* m_pDirectDraw; - int unk; - IDirectDrawSurface* m_pDirectDrawSurface; -}; - -// VTABLE 0x100db948 -class IMxDirect3DRM : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRM() {} - - virtual IUnknown** GetHandle() = 0; - virtual MxDirect3DRMDevice* CreateDeviceFromD3D(D3DHolder* p_holder) = 0; -}; - -// VTABLE 0x100db910 -class MxDirect3DRM : public IMxDirect3DRM { -public: - inline MxDirect3DRM(); - virtual ~MxDirect3DRM(); - - static MxDirect3DRM* Create(); - - virtual IUnknown** GetHandle(); - virtual MxDirect3DRMDevice* CreateDeviceFromD3D(D3DHolder* p_holder); - virtual MxDirect3DRMDevice* CreateDeviceFromSurface(D3DSurfaceHolder* p_holder); - -private: - IDirect3DRM* m_pD3DRM; -}; diff --git a/LEGO1/mxdirect3drmclasses.cpp b/LEGO1/mxdirect3drmclasses.cpp deleted file mode 100644 index c797a50a..00000000 --- a/LEGO1/mxdirect3drmclasses.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "mxdirect3drmclasses.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(IMxDirect3DRMFrame, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMFrame, 0x8); - -// OFFSET: LEGO1 0x100a36f0 -IUnknown** MxDirect3DRMFrame::GetHandle() -{ - return (IUnknown**) &m_pDirect3DRMFrame; -} - -// Not 100% confident on this function signature or behavior. -// Known info: Calls GetPosition, then AddTransform, then GetPosition again. -// OFFSET: LEGO1 0x100a3700 -int MxDirect3DRMFrame::AddTransform(D3DRMMATRIX4D* p_matrix, D3DVECTOR* p_oldPosition) -{ - D3DRMMATRIX4D newMatrix; - D3DVECTOR anotherPosition; - memcpy(&newMatrix, p_matrix, sizeof(D3DRMMATRIX4D)); - m_pDirect3DRMFrame->GetPosition(NULL, p_oldPosition); - HRESULT result = m_pDirect3DRMFrame->AddTransform(D3DRMCOMBINE_REPLACE, newMatrix); - m_pDirect3DRMFrame->GetPosition(NULL, &anotherPosition); - return SUCCEEDED(result); -} - -DECOMP_SIZE_ASSERT(IMxDirect3DRMLight, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMLight, 0x8); - -// OFFSET: LEGO1 0x100a3770 -IUnknown** MxDirect3DRMLight::GetHandle() -{ - return (IUnknown**) &m_pFrameWithLight; -} - -// OFFSET: LEGO1 0x100a3780 STUB -int MxDirect3DRMLight::AddTransform(D3DRMMATRIX4D* p_matrix) -{ - return 0; -} - -// OFFSET: LEGO1 0x100a37e0 -int MxDirect3DRMLight::SetColorRGB(float p_r, float p_g, float p_b) -{ - IDirect3DRMLightArray* lightArray; - IDirect3DRMLight* light; - m_pFrameWithLight->GetLights(&lightArray); - lightArray->GetElement(0, &light); - return SUCCEEDED(light->SetColorRGB(p_r, p_g, p_b)); -} - -DECOMP_SIZE_ASSERT(IMxDirect3DRMMesh, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMMesh, 0x8); - -// OFFSET: LEGO1 0x100a3830 -IUnknown** MxDirect3DRMMesh::GetHandle() -{ - return (IUnknown**) &m_pDirect3DRMMesh; -} - -// OFFSET: LEGO1 0x100a3840 STUB -int MxDirect3DRMMesh::SetMeshData( - int p_faceCount, - int p_vertexCount, - void* p_positions, - void* p_normals, - void* p_uvs, - int p_unk1, - int* p_unk2 -) -{ - return 0; -} - -// OFFSET: LEGO1 0x100a3ae0 -int MxDirect3DRMMesh::GetBox(float* p_minVec3, float* p_maxVec3) -{ - D3DRMBOX box; - int ret = SUCCEEDED(m_pDirect3DRMMesh->GetBox(&box)); - if (ret == TRUE) { - p_minVec3[0] = box.min.x; - p_minVec3[1] = box.min.y; - p_minVec3[2] = box.min.z; - p_maxVec3[0] = box.max.x; - p_maxVec3[1] = box.max.y; - p_maxVec3[2] = box.max.z; - } - return ret; -} - -// OFFSET: LEGO1 0x100a3b40 -IMxDirect3DRMMesh* MxDirect3DRMMesh::Clone() -{ - MxDirect3DRMMesh* mesh = new MxDirect3DRMMesh(); - int ret = m_pDirect3DRMMesh->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_pDirect3DRMMesh); - if (ret < 0) { - delete mesh; - mesh = NULL; - } - return mesh; -} diff --git a/LEGO1/mxdirect3drmclasses.h b/LEGO1/mxdirect3drmclasses.h deleted file mode 100644 index 23513877..00000000 --- a/LEGO1/mxdirect3drmclasses.h +++ /dev/null @@ -1,105 +0,0 @@ - -#include "mxdirect3drmobject.h" - -// VTABLE 0x100dbae8 -class IMxDirect3DRMFrame : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMFrame() {} - - virtual IUnknown** GetHandle() = 0; - - // vtable + 0x08 - virtual int AddTransform(D3DRMMATRIX4D* p_matrix, D3DVECTOR* p_oldPosition) = 0; -}; - -// VTABLE 0x100dbad8 -class MxDirect3DRMFrame : IMxDirect3DRMFrame { -public: - MxDirect3DRMFrame() {} - virtual ~MxDirect3DRMFrame() {} - - virtual IUnknown** GetHandle(); - IDirect3DRMFrame* GetFrame() { return m_pDirect3DRMFrame; } - - // vtable + 0x08 - // Not 100% confident on this function signature - virtual int AddTransform(D3DRMMATRIX4D* p_matrix, D3DVECTOR* p_oldPosition); - -private: - IDirect3DRMFrame* m_pDirect3DRMFrame; -}; - -// VTABLE 0x100dbb08 -class IMxDirect3DRMLight : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMLight() {} - - virtual IUnknown** GetHandle() = 0; - - // vtable+0x08 - virtual int AddTransform(D3DRMMATRIX4D* p_matrix) = 0; - virtual int SetColorRGB(float p_r, float p_g, float p_b) = 0; -}; - -// VTABLE 0x100dbaf8 -class MxDirect3DRMLight : public IMxDirect3DRMLight { -public: - MxDirect3DRMLight() {} - virtual ~MxDirect3DRMLight() {} - - virtual IUnknown** GetHandle(); - - // vtable+0x08 - // Not 100% confident on this function signature - virtual int AddTransform(D3DRMMATRIX4D* p_matrix); - virtual int SetColorRGB(float p_r, float p_g, float p_b); - -private: - IDirect3DRMFrame* m_pFrameWithLight; -}; - -// VTABLE 0x100dbb30 -class IMxDirect3DRMMesh : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMMesh() {} - - virtual IUnknown** GetHandle() = 0; - - // vtable+0x08 - virtual int SetMeshData( - int p_faceCount, - int p_vertexCount, - void* p_positions, - void* p_normals, - void* p_uvs, - int p_unk1, - int* p_unk2 - ) = 0; - virtual int GetBox(float* p_minVec3, float* p_maxVec3) = 0; - virtual IMxDirect3DRMMesh* Clone() = 0; -}; - -// VTABLE 0x100dbb18 -class MxDirect3DRMMesh : public IMxDirect3DRMMesh { -public: - MxDirect3DRMMesh() : m_pDirect3DRMMesh(NULL) {} - virtual ~MxDirect3DRMMesh() {} - - virtual IUnknown** GetHandle(); - - // vtable+0x08 - virtual int SetMeshData( - int p_faceCount, - int p_vertexCount, - void* p_positions, - void* p_normals, - void* p_uvs, - int p_unk1, - int* p_unk2 - ); - virtual int GetBox(float* p_minVec3, float* p_maxVec3); - virtual IMxDirect3DRMMesh* Clone(); - -private: - IDirect3DRMMesh* m_pDirect3DRMMesh; -}; diff --git a/LEGO1/mxdirect3drmdevice.cpp b/LEGO1/mxdirect3drmdevice.cpp deleted file mode 100644 index 605fa994..00000000 --- a/LEGO1/mxdirect3drmdevice.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "mxdirect3drmdevice.h" - -#include "d3drmwin.h" -#include "decomp.h" - -DECOMP_SIZE_ASSERT(IMxDirect3DRMDevice, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMDevice, 0x8); - -// OFFSET: LEGO1 0x100a2bf0 -IUnknown** MxDirect3DRMDevice::GetHandle() -{ - return (IUnknown**) &m_pD3DRMDevice; -} - -// OFFSET: LEGO1 0x100a2c00 -int MxDirect3DRMDevice::GetWidth() -{ - return m_pD3DRMDevice->GetWidth(); -} - -// OFFSET: LEGO1 0x100a2c10 -int MxDirect3DRMDevice::GetHeight() -{ - return m_pD3DRMDevice->GetHeight(); -} - -// OFFSET: LEGO1 0x100a2c20 -int MxDirect3DRMDevice::unknown1() -{ - return 1; -} - -// Matching behavior, codegen differs in register alloc and timing of access. -// OFFSET: LEGO1 0x100a2c30 -int MxDirect3DRMDevice::SetQuality(MxDirect3DRMDeviceQuality p_quality) -{ - D3DRMRENDERQUALITY quality; - switch (p_quality) { - case Wireframe: - quality = D3DRMRENDER_WIREFRAME; - break; - case UnlitFlat: - quality = D3DRMRENDER_UNLITFLAT; - break; - case Flat: - quality = D3DRMRENDER_FLAT; - break; - case Gouraud: - quality = D3DRMRENDER_GOURAUD; - break; - case Phong: - quality = D3DRMRENDER_PHONG; - break; - default: - quality = D3DRMRENDER_FLAT; - } - return SUCCEEDED(m_pD3DRMDevice->SetQuality(quality)); -} - -// OFFSET: LEGO1 0x100a2ca0 -int MxDirect3DRMDevice::SetShades(MxU32 p_shades) -{ - return SUCCEEDED(m_pD3DRMDevice->SetShades(p_shades)); -} - -// OFFSET: LEGO1 0x100a2cc0 -int MxDirect3DRMDevice::SetDither(int p_dither) -{ - return SUCCEEDED(m_pD3DRMDevice->SetDither(p_dither)); -} - -// OFFSET: LEGO1 0x100a2d60 -int MxDirect3DRMDevice::Update() -{ - return SUCCEEDED(m_pD3DRMDevice->Update()); -} - -// Probably wrong, not sure what's going on in this method. -// OFFSET: LEGO1 0x100a2ce0 -void MxDirect3DRMDevice::InitFromD3D() -{ - IDirect3DRMWinDevice* winDevice; - if (SUCCEEDED(m_pD3DRMDevice->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) { - m_pD3DRMDevice->InitFromD3D((LPDIRECT3D) &winDevice, (LPDIRECT3DDEVICE) m_pD3DRMDevice); - winDevice->Release(); - } -} - -// Really don't know what's going on here. Seems it will call down to Init -// but the decomp suggests it otherwise looks the same as InitFromD3D but Init -// takes widly different parameters. -// OFFSET: LEGO1 0x100a2d20 -void MxDirect3DRMDevice::Init() -{ - IDirect3DRMWinDevice* winDevice; - if (SUCCEEDED(m_pD3DRMDevice->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) { - // m_pD3DRMDevice->Init(); - winDevice->Release(); - } -} diff --git a/LEGO1/mxdirect3drmdevice.h b/LEGO1/mxdirect3drmdevice.h deleted file mode 100644 index 3166ce0c..00000000 --- a/LEGO1/mxdirect3drmdevice.h +++ /dev/null @@ -1,47 +0,0 @@ - -#include "d3drm.h" -#include "mxdirect3drmobject.h" -#include "mxtypes.h" - -// VTABLE 0x100db9b8 -class IMxDirect3DRMDevice : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMDevice() {} - - virtual IUnknown** GetHandle() = 0; -}; - -enum MxDirect3DRMDeviceQuality { - Wireframe = 0x0, - UnlitFlat = 0x1, - Flat = 0x2, - Gouraud = 0x3, - Phong = 0x4, -}; - -// VTABLE 0x100db988 -class MxDirect3DRMDevice : public IMxDirect3DRMDevice { -public: - MxDirect3DRMDevice() {} - virtual ~MxDirect3DRMDevice() {} - - virtual IUnknown** GetHandle(); - - // 0x08 in vtable - virtual int GetWidth(); - virtual int GetHeight(); - - // 0x10 in vtable - virtual int unknown1(); - virtual int SetQuality(MxDirect3DRMDeviceQuality p_quality); - virtual int SetShades(MxU32 p_shades); - virtual int SetDither(int p_dither); - - // 0x20 in vtable - virtual int Update(); - virtual void InitFromD3D(); - virtual void Init(); - -private: - IDirect3DRMDevice* m_pD3DRMDevice; -}; diff --git a/LEGO1/mxdirect3drmobject.cpp b/LEGO1/mxdirect3drmobject.cpp deleted file mode 100644 index 032a9137..00000000 --- a/LEGO1/mxdirect3drmobject.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "mxdirect3drmobject.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(IMxDirect3DRMObject, 0x4); diff --git a/LEGO1/mxdirect3drmobject.h b/LEGO1/mxdirect3drmobject.h deleted file mode 100644 index 25c6c13d..00000000 --- a/LEGO1/mxdirect3drmobject.h +++ /dev/null @@ -1,12 +0,0 @@ - -#include "d3d.h" -#include "d3drm.h" -#include "mxtypes.h" - -// VTABLE 0x100db980 -class IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMObject() {} - - virtual IUnknown** GetHandle() = 0; -}; diff --git a/LEGO1/mxdirect3drmtexture.cpp b/LEGO1/mxdirect3drmtexture.cpp deleted file mode 100644 index f8ed0915..00000000 --- a/LEGO1/mxdirect3drmtexture.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "mxdirect3drmtexture.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(IMxDirect3DRMTexture, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMTexture, 0x8); -DECOMP_SIZE_ASSERT(MxD3DRMIMAGE, 0x40); - -// OFFSET: LEGO1 0x100a1330 -MxD3DRMIMAGE::MxD3DRMIMAGE( - int p_width, - int p_height, - int p_depth, - void* p_buffer, - int p_useBuffer, - int p_paletteSize, - PaletteEntry* p_palette -) -{ - m_image.aspectx = 1; - m_image.aspecty = 1; - m_image.width = 0; - m_image.height = 0; - m_image.depth = 0; - m_image.rgb = 0; - m_image.bytes_per_line = 0; - m_image.buffer1 = NULL; - m_image.buffer2 = NULL; - m_image.red_mask = 0xFF; - m_image.green_mask = 0xFF; - m_image.blue_mask = 0xFF; - m_image.alpha_mask = 0xFF; - m_image.palette_size = 0; - m_image.palette = NULL; - m_extra = 0; - if (p_buffer != NULL) { - CreateBuffer(p_width, p_height, p_depth, p_buffer, p_useBuffer); - } - if (p_palette != NULL) { - InitializePalette(p_paletteSize, p_palette); - } -} - -// OFFSET: LEGO1 0x100a13e0 STUB -int MxD3DRMIMAGE::CreateBuffer(int p_width, int p_height, int p_depth, void* p_buffer, int p_useBuffer) -{ - return 0; -} - -// OFFSET: LEGO1 0x100a13b0 -void MxD3DRMIMAGE::Destroy() -{ - if (m_extra == 0) { - free(m_image.buffer1); - } - free(m_image.palette); -} - -// OFFSET: LEGO1 0x100a1510 -void MxD3DRMIMAGE::FillRowsOfTexture(int p_y, int p_height, char* p_content) -{ - // The purpose is clearly this but I can't get the assembly to line up. - memcpy((char*) m_image.buffer1 + (p_y * m_image.bytes_per_line), p_content, p_height * m_image.bytes_per_line); -} - -// OFFSET: LEGO1 0x100a1550 -int MxD3DRMIMAGE::InitializePalette(int p_paletteSize, PaletteEntry* p_palette) -{ - if (m_image.palette_size != p_paletteSize) { - if (m_image.palette != NULL) { - free(m_image.palette); - m_image.palette = NULL; - m_image.palette_size = 0; - } - if (p_paletteSize > 0) { - m_image.palette = (D3DRMPALETTEENTRY*) malloc(4 * p_paletteSize); - m_image.palette_size = p_paletteSize; - } - } - if (p_paletteSize > 0) { - for (int i = 0; i < p_paletteSize; i++) { - m_image.palette[i].red = p_palette[i].r; - m_image.palette[i].green = p_palette[i].g; - m_image.palette[i].blue = p_palette[i].b; - m_image.palette[i].flags = D3DRMPALETTE_READONLY; - } - } - return TRUE; -} - -// OFFSET: LEGO1 0x100a3d70 -IUnknown** MxDirect3DRMTexture::GetHandle() -{ - return (IUnknown**) &m_pDirect3DRMTexture; -} - -// OFFSET: LEGO1 0x100a3c10 -int MxDirect3DRMTexture::SetBuffer(int p_width, int p_height, int p_depth, void* p_buffer) -{ - // Haven't tried very hard to get a very good match here yet, the control - // flow for the result handling is a bit annoying. - MxD3DRMIMAGE* image = GetImageData(); - int result = image->CreateBuffer(p_width, p_height, p_depth, p_buffer, TRUE); - if (result == TRUE) { - if (!SUCCEEDED(m_pDirect3DRMTexture->Changed(TRUE, FALSE))) { - result = FALSE; - } - } - return result; -} - -// OFFSET: LEGO1 0x100a3c60 -void MxDirect3DRMTexture::FillRowsOfTexture(int p_y, int p_height, void* p_buffer) -{ - MxD3DRMIMAGE* image = GetImageData(); - image->FillRowsOfTexture(p_y, p_height, (char*) p_buffer); -} - -// OFFSET: LEGO1 0x100a3c90 -int MxDirect3DRMTexture::Changed(int p_pixelsChanged, int p_paletteChanged) -{ - return SUCCEEDED(m_pDirect3DRMTexture->Changed(p_pixelsChanged, p_paletteChanged)); -} - -// OFFSET: LEGO1 0x100a3d00 -int MxDirect3DRMTexture::GetBufferAndPalette( - int* p_width, - int* p_height, - int* p_depth, - void** p_buffer, - int* p_paletteSize, - MxD3DRMIMAGE::PaletteEntry** p_palette -) -{ - // Something really doesn't match here, not sure what's up. - MxD3DRMIMAGE* image = GetImageData(); - *p_width = image->m_image.width; - *p_height = image->m_image.height; - *p_depth = image->m_image.depth; - *p_buffer = image->m_image.buffer1; - *p_paletteSize = image->m_image.palette_size; - for (int i = 0; i < image->m_image.palette_size; i++) { - p_palette[i]->r = image->m_image.palette[i].red; - p_palette[i]->g = image->m_image.palette[i].green; - p_palette[i]->b = image->m_image.palette[i].blue; - } - return TRUE; -} - -// OFFSET: LEGO1 0x100a3d40 -int MxDirect3DRMTexture::InitializePalette(int p_paletteSize, MxD3DRMIMAGE::PaletteEntry* p_palette) -{ - // Not 100% confident this is supposed to directly be forwarding arguments, - // but it probably is given FillRowsOfTexture matches doing that. - MxD3DRMIMAGE* image = GetImageData(); - image->InitializePalette(p_paletteSize, p_palette); - m_pDirect3DRMTexture->Changed(FALSE, TRUE); - return TRUE; -} - -// OFFSET: LEGO1 0x100a1300 -void MxDirect3DRMTexture::OnDestroyed() -{ - delete GetImageData(); - m_pDirect3DRMTexture->SetAppData(NULL); -} diff --git a/LEGO1/mxdirect3drmtexture.h b/LEGO1/mxdirect3drmtexture.h deleted file mode 100644 index 949845e5..00000000 --- a/LEGO1/mxdirect3drmtexture.h +++ /dev/null @@ -1,88 +0,0 @@ - -#include "mxdirect3drmobject.h" - -// No vtable, this is just a simple wrapper around D3DRMIMAGE -class MxD3DRMIMAGE { -public: - struct PaletteEntry { - unsigned char r; - unsigned char g; - unsigned char b; - }; - - MxD3DRMIMAGE( - int p_width, - int p_height, - int p_depth, - void* p_buffer, - int p_useBuffer, - int p_paletteSize, - PaletteEntry* p_palette - ); - ~MxD3DRMIMAGE() { Destroy(); } - - int CreateBuffer(int p_width, int p_height, int p_depth, void* p_buffer, int p_useBuffer); - void Destroy(); - void FillRowsOfTexture(int p_y, int p_height, char* p_content); - int InitializePalette(int p_paletteSize, PaletteEntry* p_palette); - - D3DRMIMAGE m_image; - int m_extra; -}; - -// VTABLE 0x100dbb68 -class IMxDirect3DRMTexture : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMTexture() {} - - virtual IUnknown** GetHandle() = 0; - - // vtable+0x08 - virtual int SetBuffer(int p_width, int p_height, int p_depth, void* p_buffer) = 0; - virtual void FillRowsOfTexture(int p_y, int p_height, void* p_buffer) = 0; - - // vtable+0x10 - virtual int Changed(int p_pixelsChanged, int p_paletteChanged) = 0; - virtual int GetBufferAndPalette( - int* p_width, - int* p_height, - int* p_depth, - void** p_buffer, - int* p_paletteSize, - MxD3DRMIMAGE::PaletteEntry** p_palette - ) = 0; - virtual int InitializePalette(int p_paletteSize, MxD3DRMIMAGE::PaletteEntry* p_palette) = 0; -}; - -// VTABLE 0x100dbb48 -class MxDirect3DRMTexture : public IMxDirect3DRMTexture { -public: - MxDirect3DRMTexture() {} - virtual ~MxDirect3DRMTexture() {} - - virtual IUnknown** GetHandle(); - - // vtable+0x08 - virtual int SetBuffer(int p_width, int p_height, int p_depth, void* p_buffer); - virtual void FillRowsOfTexture(int p_y, int p_height, void* p_buffer); - - // vtable+0x10 - virtual int Changed(int p_pixelsChanged, int p_paletteChanged); - virtual int GetBufferAndPalette( - int* p_width, - int* p_height, - int* p_depth, - void** p_buffer, - int* p_paletteSize, - MxD3DRMIMAGE::PaletteEntry** p_palette - ); - virtual int InitializePalette(int p_paletteSize, MxD3DRMIMAGE::PaletteEntry* p_palette); - - // Not virtual - void OnDestroyed(); - -private: - inline MxD3DRMIMAGE* GetImageData() { return (MxD3DRMIMAGE*) m_pDirect3DRMTexture->GetAppData(); } - - IDirect3DRMTexture* m_pDirect3DRMTexture; -}; diff --git a/LEGO1/mxdirect3drmviewport.cpp b/LEGO1/mxdirect3drmviewport.cpp deleted file mode 100644 index 0e22afdf..00000000 --- a/LEGO1/mxdirect3drmviewport.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "mxdirect3drmviewport.h" - -#include "decomp.h" - -#include - -DECOMP_SIZE_ASSERT(IMxDirect3DRMViewport, 0x4); -DECOMP_SIZE_ASSERT(MxDirect3DRMViewport, 0x8); - -struct MxDirect3DRMViewportData { - IDirect3DRMFrame* m_pDirect3DRMFrame; - IDirect3DRMFrame* m_pCamera; - IDirect3DRMFrame* m_pCameraParent; - float m_backgroundRGB[3]; -}; - -// OFFSET: LEGO1 0x100a2d80 -IUnknown** MxDirect3DRMViewport::GetHandle() -{ - return (IUnknown**) &m_pDirect3DRMViewport; -} - -// OFFSET: LEGO1 0x100a2d90 -int MxDirect3DRMViewport::AddLight(MxDirect3DRMFrame* p_frame) -{ - IDirect3DRMFrame* frame = p_frame->GetFrame(); - return SUCCEEDED(GetViewportData()->m_pDirect3DRMFrame->AddChild(frame)); -} - -// OFFSET: LEGO1 0x100a2dc0 -int MxDirect3DRMViewport::DeleteLight(MxDirect3DRMFrame* p_frame) -{ - IDirect3DRMFrame* frame = p_frame->GetFrame(); - return SUCCEEDED(GetViewportData()->m_pDirect3DRMFrame->DeleteChild(frame)); -} - -// Disassembly is not close, not sure what's going wrong. -// OFFSET: LEGO1 0x100a2df0 -int MxDirect3DRMViewport::SetCamera(MxDirect3DRMFrame* p_camera) -{ - IDirect3DRMViewport* viewport = GetViewport(); - IDirect3DRMFrame* camera = p_camera->GetFrame(); - MxDirect3DRMViewportData* data = GetViewportData(); - if (data->m_pCameraParent) { - data->m_pCameraParent->DeleteChild(data->m_pCamera); - // Another call goes here, not sure what. - data->m_pCameraParent->Release(); - } - data->m_pCamera = camera; - data->m_pCameraParent = NULL; - return SUCCEEDED(viewport->SetCamera(camera)); -} - -// OFFSET: LEGO1 0x100a2e70 -int MxDirect3DRMViewport::SetProjection(int p_type) -{ - D3DRMPROJECTIONTYPE proj; - switch (p_type) { - case 0: - proj = D3DRMPROJECT_PERSPECTIVE; - break; - case 1: - proj = D3DRMPROJECT_ORTHOGRAPHIC; - break; - default: - proj = D3DRMPROJECT_PERSPECTIVE; - } - return SUCCEEDED(GetViewport()->SetProjection(proj)); -} - -// OFFSET: LEGO1 0x100a2eb0 -int MxDirect3DRMViewport::SetPlanes(float p_near, float p_far, float p_FoV) -{ - int ret; - float field = tanf(((p_FoV * 0.5f) * (5 / 9)) * 3.141592653589793); - // Not very confident about this code, seems like p_near may actually be - // multiplied by something before being passed to SetFront. - if (ret = SUCCEEDED(m_pDirect3DRMViewport->SetFront(p_near))) { - if (ret = SUCCEEDED(m_pDirect3DRMViewport->SetBack(p_far))) { - ret = SUCCEEDED(m_pDirect3DRMViewport->SetField(field)); - } - } - return ret; -} - -// OFFSET: LEGO1 0x100a2f30 -int MxDirect3DRMViewport::SetBackgroundRGB(float p_r, float p_g, float p_b) -{ - int ret = TRUE; - MxDirect3DRMViewportData* data = GetViewportData(); - data->m_backgroundRGB[0] = p_r; - data->m_backgroundRGB[1] = p_g; - data->m_backgroundRGB[2] = p_b; - if (data->m_pCameraParent) { - ret = data->m_pCameraParent->SetSceneBackgroundRGB(p_r, p_g, p_b) < 0 ? FALSE : TRUE; - } - return ret; -} - -// OFFSET: LEGO1 0x100a2f80 -int MxDirect3DRMViewport::GetBackgroundRGB(float* p_r, float* p_g, float* p_b) -{ - MxDirect3DRMViewportData* data = GetViewportData(); - *p_r = data->m_backgroundRGB[0]; - *p_g = data->m_backgroundRGB[1]; - *p_b = data->m_backgroundRGB[2]; - return TRUE; -} - -// OFFSET: LEGO1 0x100a2fb0 -int MxDirect3DRMViewport::Clear() -{ - return SUCCEEDED(m_pDirect3DRMViewport->Clear()); -} - -// OFFSET: LEGO1 0x100a2fd0 SetCameraParent -int MxDirect3DRMViewport::SetCameraParent(MxDirect3DRMFrame* p_frame) -{ - // Not close yet due to missing calls below. - IDirect3DRMViewport* viewport = GetViewport(); - IDirect3DRMFrame* newParent = p_frame->GetFrame(); - MxDirect3DRMViewportData* data = GetViewportData(); - IDirect3DRMFrame* oldParent = data->m_pCameraParent; - if (newParent != oldParent) { - if (oldParent != NULL) { - oldParent->DeleteChild(data->m_pCamera); - // Another call goes here, not sure what. - oldParent->Release(); - } - data->m_pCameraParent = newParent; - oldParent = data->m_pDirect3DRMFrame; - if (newParent != NULL) { - newParent - ->SetSceneBackgroundRGB(data->m_backgroundRGB[0], data->m_backgroundRGB[1], data->m_backgroundRGB[2]); - newParent->AddChild(data->m_pCamera); - // Another call goes here, not sure what. - newParent->AddRef(); - } - } - return SUCCEEDED(viewport->Render(newParent)); -} - -// OFFSET: LEGO1 0x100a3080 -int MxDirect3DRMViewport::ForceUpdate(int x, int y, int width, int height) -{ - return SUCCEEDED(m_pDirect3DRMViewport->ForceUpdate(x, y, x + width - 1, y + height - 1)); -} - -// OFFSET: LEGO1 0x100a30f0 Transform -int MxDirect3DRMViewport::Transform(float* p_shiftByVector3, float* p_out) -{ - D3DVECTOR s; - s.x = p_shiftByVector3[0]; - s.y = p_shiftByVector3[1]; - s.z = p_shiftByVector3[2]; - - D3DRMVECTOR4D d; - int ret = m_pDirect3DRMViewport->Transform(&d, &s); - if (SUCCEEDED(ret) == TRUE) { - p_out[0] = d.x; - p_out[1] = d.y; - p_out[2] = d.z; - p_out[3] = d.w; - } - return SUCCEEDED(ret); -} - -// Don't know the types of the parameters for this. -// OFFSET: LEGO1 0x100a30c0 -int MxDirect3DRMViewport::unk(int p_1, int p_2, int p_3, int p_4, int p_5, int p_6) -{ - return unkInternal(m_pDirect3DRMViewport, p_1, p_2, p_3, p_4, p_5, p_6); -} - -// OFFSET: LEGO1 0x100a1290 -int MxDirect3DRMViewport::unkInternal( - IDirect3DRMViewport* p_viewport, - int p_1, - int p_2, - int p_3, - int p_4, - int p_5, - int p_6 -) -{ - return 0; -} diff --git a/LEGO1/mxdirect3drmviewport.h b/LEGO1/mxdirect3drmviewport.h deleted file mode 100644 index f681ab71..00000000 --- a/LEGO1/mxdirect3drmviewport.h +++ /dev/null @@ -1,74 +0,0 @@ - -#include "mxdirect3drmclasses.h" - -// VTABLE 0x100dba28 -class IMxDirect3DRMViewport : public IMxDirect3DRMObject { -public: - virtual ~IMxDirect3DRMViewport() {} - - virtual IUnknown** GetHandle() = 0; - - // vtable+0x08 - virtual int AddLight(MxDirect3DRMFrame* p_frame) = 0; - virtual int DeleteLight(MxDirect3DRMFrame* p_frame) = 0; - - // vtable+0x10 - virtual int SetCamera(MxDirect3DRMFrame* p_camera) = 0; - virtual int SetProjection(int p_type) = 0; - virtual int SetPlanes(float p_near, float p_far, float p_FoV) = 0; - virtual int SetBackgroundRGB(float p_r, float p_g, float p_b) = 0; - - // vtable+0x20 - virtual int GetBackgroundRGB(float* p_r, float* p_g, float* p_b) = 0; - virtual int Clear() = 0; - virtual int SetCameraParent(MxDirect3DRMFrame* p_frame) = 0; - virtual int ForceUpdate(int x, int y, int width, int height) = 0; - - // vtable+0x30 - virtual int Transform(float* p_shiftByVector3, float* p_out) = 0; - virtual int InverseTransform(D3DRMVECTOR4D* p_in, float* p_outVector3) = 0; - virtual int unk(int p_1, int p_2, int p_3, int p_4, int p_5, int p_6) = 0; -}; - -struct MxDirect3DRMViewportData; - -// VTABLE 0x100db9e8 -class MxDirect3DRMViewport : public IMxDirect3DRMViewport { -public: - MxDirect3DRMViewport() {} - virtual ~MxDirect3DRMViewport() {} - - virtual IUnknown** GetHandle(); - IDirect3DRMViewport* GetViewport() { return m_pDirect3DRMViewport; } - - // vtable+0x08 - virtual int AddLight(MxDirect3DRMFrame* p_frame); - virtual int DeleteLight(MxDirect3DRMFrame* p_frame); - - // vtable+0x10 - virtual int SetCamera(MxDirect3DRMFrame* p_camera); - virtual int SetProjection(int p_type); - virtual int SetPlanes(float p_near, float p_far, float p_FoV); - virtual int SetBackgroundRGB(float p_r, float p_g, float p_b); - - // vtable+0x20 - virtual int GetBackgroundRGB(float* p_r, float* p_g, float* p_b); - virtual int Clear(); - virtual int SetCameraParent(MxDirect3DRMFrame* p_frame); - virtual int ForceUpdate(int x, int y, int width, int height); - - // vtable+0x30 - virtual int Transform(float* p_shiftByVector3, float* p_out); - virtual int InverseTransform(D3DRMVECTOR4D* p_in, float* p_outVector3); - virtual int unk(int p_1, int p_2, int p_3, int p_4, int p_5, int p_6); - -private: - static int unkInternal(IDirect3DRMViewport* p_viewport, int p_1, int p_2, int p_3, int p_4, int p_5, int p_6); - - inline MxDirect3DRMViewportData* GetViewportData() - { - return (MxDirect3DRMViewportData*) m_pDirect3DRMViewport->GetAppData(); - } - - IDirect3DRMViewport* m_pDirect3DRMViewport; -}; diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp new file mode 100644 index 00000000..3d8e1912 --- /dev/null +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -0,0 +1,39 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(Camera, 0x4); +DECOMP_SIZE_ASSERT(CameraImpl, 0x8); + +// Inlined only +CameraImpl::~CameraImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a36f0 +void* CameraImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a3700 +Result CameraImpl::SetTransformation(const FloatMatrix& p_matrix) +{ + D3DRMMATRIX4D helper; + D3DRMMATRIX4D* pTransformation = Translate(p_matrix, helper); + + D3DVECTOR position; + Result result; + Result result2; + + result2 = ResultVal(m_data->GetPosition(0, &position)); + result = ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *pTransformation)); + // The did this second call just to assert on the return value + result2 = ResultVal(m_data->GetPosition(0, &position)); + + return result; +} \ No newline at end of file diff --git a/LEGO1/tgl/d3drm/device.cpp b/LEGO1/tgl/d3drm/device.cpp new file mode 100644 index 00000000..e30a1730 --- /dev/null +++ b/LEGO1/tgl/d3drm/device.cpp @@ -0,0 +1,91 @@ +#include "impl.h" + +#include + +using namespace TglImpl; + +// Inlined only +DeviceImpl::~DeviceImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a2bf0 +void* DeviceImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a2c00 +unsigned long DeviceImpl::GetWidth() +{ + return m_data->GetWidth(); +} + +// OFFSET: LEGO1 0x100a2c10 +unsigned long DeviceImpl::GetHeight() +{ + return m_data->GetHeight(); +} + +// OFFSET: LEGO1 0x100a2c20 +Result DeviceImpl::SetColorModel(ColorModel) +{ + return Success; +} + +// OFFSET: LEGO1 0x100a2c30 +Result DeviceImpl::SetShadingModel(ShadingModel p_model) +{ + // Doesn't match well even though we know this is exactly + // the original code thanks to the jump table. + D3DRMRENDERQUALITY renderQuality = Translate(p_model); + return ResultVal(m_data->SetQuality(renderQuality)); +} + +// OFFSET: LEGO1 0x100a2ca0 +Result DeviceImpl::SetShadeCount(unsigned long p_shadeCount) +{ + return ResultVal(m_data->SetShades(p_shadeCount)); +} + +// OFFSET: LEGO1 0x100a2cc0 +Result DeviceImpl::SetDither(int p_dither) +{ + return ResultVal(m_data->SetDither(p_dither)); +} + +// OFFSET: LEGO1 0x100a2d60 +Result DeviceImpl::Update() +{ + return ResultVal(m_data->Update()); +} + +// Probably wrong, not sure what's going on in this method. +// OFFSET: LEGO1 0x100a2ce0 +void DeviceImpl::InitFromD3DDevice(Device*) +{ + // Device argument is intentionally unused. + IDirect3DRMWinDevice* winDevice; + if (ResultVal(m_data->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) { + m_data->InitFromD3D((LPDIRECT3D) &winDevice, (LPDIRECT3DDEVICE) m_data); + winDevice->Release(); + } +} + +// Really don't know what's going on here. Seems it will call down to Init +// but the decomp suggests it otherwise looks the same as InitFromD3D but Init +// takes widly different parameters. +// OFFSET: LEGO1 0x100a2d20 +void DeviceImpl::InitFromWindowsDevice(Device*) +{ + // Device argument is intentionally unused. + IDirect3DRMWinDevice* winDevice; + if (SUCCEEDED(m_data->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) { + // m_data->Init(??); + winDevice->Release(); + } +} diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp new file mode 100644 index 00000000..c968a08d --- /dev/null +++ b/LEGO1/tgl/d3drm/group.cpp @@ -0,0 +1,129 @@ +#include "impl.h" + +using namespace TglImpl; + +// Inlined only +GroupImpl::~GroupImpl() +{ + if (m_data) { + free(m_data); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a31d0 +void* GroupImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a31e0 +Result GroupImpl::SetTransformation(const FloatMatrix& p_matrix) +{ + D3DRMMATRIX4D helper; + D3DRMMATRIX4D* matrix = Translate(p_matrix, helper); + return ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *matrix)); +} + +// OFFSET: LEGO1 0x100a3240 +Result GroupImpl::SetColor(float p_r, float p_g, float p_b, float p_a) +{ + // The first instruction makes no sense here: + // cmp dword ptr [esp + 0x10], 0 + // This compares a, which we know is a float because it immediately + // gets passed into D3DRMCreateColorRGBA, but does the comparison + // as though it's an int?? + if (*reinterpret_cast(&p_a) > 0) { + D3DCOLOR color = D3DRMCreateColorRGBA(p_r, p_g, p_b, p_a); + return ResultVal(m_data->SetColor(color)); + } + else { + return ResultVal(m_data->SetColorRGB(p_r, p_a, p_b)); + } +} + +// OFFSET: LEGO1 0x100a32b0 +Result GroupImpl::SetTexture(const Texture* p_texture) +{ + IDirect3DRMTexture* texture = p_texture ? static_cast(p_texture)->ImplementationData() : NULL; + return ResultVal(m_data->SetTexture(texture)); +} + +// OFFSET: LEGO1 0x100a32e0 +Result GroupImpl::GetTexture(Texture*& p_texture) +{ + IDirect3DRMTexture* texture; + TextureImpl* holder = new TextureImpl(); + Result result = ResultVal(m_data->GetTexture(&texture)); + if (result) { + // Seems to actually call the first virtual method of holder here + // but that doesn't make any sense since it passes three arguments + // to the method (self + string constant? + an offset?). + + // This line makes the start of the function match and is what I + // would expect to see there but it clearly isn't what's actually + // there. + holder->SetImplementation(texture); + } + p_texture = holder; + return Success; +} + +// OFFSET: LEGO1 0x100a33c0 +Result GroupImpl::SetMaterialMode(MaterialMode p_mode) +{ + D3DRMMATERIALMODE mode; + switch (p_mode) + { + case FromParent: + mode = D3DRMMATERIAL_FROMPARENT; + break; + case FromFrame: + mode = D3DRMMATERIAL_FROMFRAME; + break; + case FromMesh: + mode = D3DRMMATERIAL_FROMMESH; + break; + } + return ResultVal(m_data->SetMaterialMode(mode)); +} + +// OFFSET: LEGO1 0x100a3430 +Result GroupImpl::Add(const Group* p_group) +{ + const GroupImpl* group = static_cast(p_group); + return ResultVal(m_data->AddVisual(group->m_data)); +} + +// OFFSET: LEGO1 0x100a3410 +Result GroupImpl::Add(const Mesh* p_mesh) +{ + const MeshImpl* mesh = static_cast(p_mesh); + return ResultVal(m_data->AddVisual(mesh->ImplementationData()->groupMesh)); +} + +// OFFSET: LEGO1 0x100a3450 +Result GroupImpl::Remove(const Group* p_group) +{ + const GroupImpl* group = static_cast(p_group); + return ResultVal(m_data->DeleteVisual(group->m_data)); +} + +// OFFSET: LEGO1 0x100a3480 +Result GroupImpl::Remove(const Mesh* p_mesh) +{ + const MeshImpl* mesh = static_cast(p_mesh); + return ResultVal(m_data->DeleteVisual(mesh->ImplementationData()->groupMesh)); +} + +// OFFSET: LEGO1 0x100a34b0 STUB +Result GroupImpl::RemoveAll() +{ + return Error; +} + +// OFFSET: LEGO1 0x100a34c0 STUB +Result GroupImpl::Unknown() +{ + return Error; +} diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h new file mode 100644 index 00000000..f46f959f --- /dev/null +++ b/LEGO1/tgl/d3drm/impl.h @@ -0,0 +1,418 @@ + +#include "../../decomp.h" +#include "../tgl.h" + +#include + +// Forward declare D3D types +struct IDirect3DRM; +struct IDirect3DRMDevice; +struct IDirect3DRMViewport; +struct IDirect3DRMFrame; +struct IDirect3DRMMesh; +struct IDirect3DRMMeshBuilder; +struct IDirect3DRMTexture; + +namespace TglImpl +{ + +using namespace Tgl; + +// Utility function used by implementations +inline Result ResultVal(HRESULT p_result) +{ + return SUCCEEDED(p_result) ? Success : Error; +} + +// Forward declare implementations +class RendererImpl; +class DeviceImpl; +class ViewImpl; +class LightImpl; +class CameraImpl; +class GroupImpl; +class MeshImpl; +class TextureImpl; + +// VTABLE 0x100db910 +class RendererImpl : public Renderer { +public: + RendererImpl() : m_data(0) {} + ~RendererImpl() { Destroy(); }; + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Device* CreateDevice(const DeviceDirect3DCreateData&); + virtual Device* CreateDevice(const DeviceDirectDrawCreateData&); + + // vtable+0x10 + virtual View* CreateView( + const Device*, + const Camera*, + unsigned long p_x, + unsigned long p_y, + unsigned long p_width, + unsigned long p_height + ); + virtual Camera* CreateCamera(); + virtual Light* CreateLight(LightType, float p_r, float p_g, float p_b); + virtual Group* CreateGroup(const Group* p_parent); + + // vtable+0x20 + virtual Something* CreateSomething(); + virtual Texture* CreateTexture(); + virtual Texture* CreateTexture( + int p_width, + int p_height, + int p_bitsPerTexel, + const void* p_pTexels, + int p_pTexelsArePersistent, + int p_paletteEntryCount, + const PaletteEntry* p_pEntries + ); + virtual Result SetTextureDefaultShadeCount(unsigned long); + + // vtable+0x30 + virtual Result SetTextureDefaultColorCount(unsigned long); + +public: + inline Result Create(); + inline void Destroy(); + +private: + IDirect3DRM* m_data; +}; + +// VTABLE 0x100db988 +class DeviceImpl : public Device { +public: + DeviceImpl() : m_data(0) {} + ~DeviceImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual unsigned long GetWidth(); + virtual unsigned long GetHeight(); + + // vtable+0x10 + virtual Result SetColorModel(ColorModel); + virtual Result SetShadingModel(ShadingModel); + virtual Result SetShadeCount(unsigned long); + virtual Result SetDither(int); + + // vtable+0x20 + virtual Result Update(); + virtual void InitFromD3DDevice(Device*); + virtual void InitFromWindowsDevice(Device*); + + inline IDirect3DRMDevice* ImplementationData() const { return m_data; } + + friend class RendererImpl; + +private: + IDirect3DRMDevice* m_data; +}; + +// VTABLE 0x100db9e8 +class ViewImpl : public View { +public: + ViewImpl() : m_data(0) {} + ~ViewImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result Add(const Light*); + virtual Result Remove(const Light*); + + // vtable+0x10 + virtual Result SetCamera(const Camera*); + virtual Result SetProjection(ProjectionType); + virtual Result SetFrustrum(float p_frontClippingDistance, float p_backClippingDistance, float p_degrees); + virtual Result SetBackgroundColor(float p_r, float p_g, float p_b); + + // vtable+0x20 + virtual Result GetBackgroundColor(float* p_r, float* p_g, float* p_b); + virtual Result Clear(); + virtual Result Render(const Light*); + virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height); + + // vtable+0x30 + virtual Result TransformWorldToScreen(const float world[3], float screen[4]); + virtual Result TransformScreenToWorld(const float screen[4], float world[3]); + virtual Result Pick( + unsigned long p_x, + unsigned long p_y, + const Group** p_ppGroupsToPickFrom, + int p_groupsToPickFromCount, + const Group**& p_rppPickedGroups, + int& p_rPickedGroupCount + ); + + inline IDirect3DRMViewport* ImplementationData() const { return m_data; } + + static Result ViewportCreateAppData(IDirect3DRM*, IDirect3DRMViewport*, IDirect3DRMFrame*); + + friend class RendererImpl; + +private: + IDirect3DRMViewport* m_data; +}; + +// VTABLE 0x100dbad8 +class CameraImpl : public Camera { +public: + CameraImpl() : m_data(0) {} + ~CameraImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetTransformation(const FloatMatrix&); + + inline IDirect3DRMFrame* ImplementationData() const { return m_data; } + + friend class RendererImpl; + +private: + IDirect3DRMFrame* m_data; +}; + +// VTABLE 0x100dbaf8 +class LightImpl : public Light { +public: + LightImpl() : m_data(0) {} + ~LightImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetTransformation(const FloatMatrix&); + virtual Result SetColor(float p_r, float p_g, float p_b); + + inline IDirect3DRMFrame* ImplementationData() const { return m_data; } + + friend class RendererImpl; + +private: + IDirect3DRMFrame* m_data; +}; + +// VTABLE 0x100dbb88 +class MeshImpl : public Mesh { +public: + MeshImpl() : m_data(0) {} + ~MeshImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetColor(float p_r, float p_g, float p_b, float p_a); + virtual Result SetTexture(const Texture*); + + // vtable+0x10 + virtual Result GetTexture(Texture*&); + virtual Result SetTextureMappingMode(ProjectionType); + virtual Result SetShadingModel(ShadingModel); + virtual Mesh* DeepClone(Something*); + + // vtable+0x20 + virtual Mesh* ShallowClone(Something*); + + struct MeshData { + IDirect3DRMMesh* groupMesh; + int groupIndex; + }; + + inline MeshData* ImplementationData() const { return m_data; } + + friend class RendererImpl; + +private: + MeshData* m_data; +}; + +// VTABLE 0x100dba68 +class GroupImpl : public Group { +public: + GroupImpl() : m_data(0) {} + ~GroupImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetTransformation(const FloatMatrix&); + virtual Result SetColor(float p_r, float p_g, float p_b, float p_a); + + // vtable+0x10 + virtual Result SetTexture(const Texture*); + virtual Result GetTexture(Texture*&); + virtual Result SetMaterialMode(MaterialMode); + virtual Result Add(const Group*); + + // vtable+0x20 + virtual Result Add(const Mesh*); + virtual Result Remove(const Group*); + virtual Result Remove(const Mesh*); + virtual Result RemoveAll(); + + // vtable+0x30 + virtual Result Unknown(); + + friend class RendererImpl; + +private: + IDirect3DRMFrame* m_data; +}; + +// VTABLE 0x100dbb18 +class SomethingImpl : public Something { +public: + SomethingImpl() : m_data(0) {} + ~SomethingImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetMeshData( + unsigned long p_faceCount, + unsigned long p_vertexCount, + const float (*p_positions)[3], + const float (*p_normals)[3], + const float (*p_textureCoordinates)[2], + unsigned long p_vertexPerFaceCount, + unsigned long* p_faceData + ); + virtual Result GetBoundingBox(float p_min[3], float p_max[3]); + + // vtable+0x10 + virtual Something* Clone(); + + inline IDirect3DRMMesh* ImplementationData() const { return m_data; } + + friend class RendererImpl; + +private: + IDirect3DRMMesh* m_data; +}; + +// No vtable, this is just a simple wrapper around D3DRMIMAGE +class TglD3DRMIMAGE { +public: + TglD3DRMIMAGE( + int p_width, + int p_height, + int p_depth, + void* p_buffer, + int p_useBuffer, + int p_paletteSize, + PaletteEntry* p_palette + ); + ~TglD3DRMIMAGE() { Destroy(); } + + Result CreateBuffer(int p_width, int p_height, int p_depth, void* p_buffer, int p_useBuffer); + void Destroy(); + void FillRowsOfTexture(int p_y, int p_height, char* p_content); + Result InitializePalette(int p_paletteSize, PaletteEntry* p_palette); + + D3DRMIMAGE m_image; + int m_texelsAllocatedByClient; +}; + +// VTABLE 0x100dbb48 +class TextureImpl : public Texture { +public: + TextureImpl() : m_data(0) {} + ~TextureImpl(); + + virtual void* ImplementationDataPtr(); + + // vtable+0x08 + virtual Result SetTexels(int p_width, int p_height, int p_bitsPerTexel, void* p_texels); + virtual void FillRowsOfTexture(int p_y, int p_height, void* p_buffer); + + // vtable+0x10 + virtual Result Changed(int p_texelsChanged, int p_paletteChanged); + virtual Result GetBufferAndPalette( + int* p_width, + int* p_height, + int* p_depth, + void** p_buffer, + int* p_paletteSize, + PaletteEntry** p_palette + ); + virtual Result SetPalette(int p_entryCount, PaletteEntry* p_entries); + + inline IDirect3DRMTexture* ImplementationData() const { return m_data; } + inline void SetImplementation(IDirect3DRMTexture* data) { m_data = data; } + + friend class RendererImpl; + + static Result SetImage(IDirect3DRMTexture* p_self, TglD3DRMIMAGE* p_image); + +private: + IDirect3DRMTexture* m_data; +}; + +// Translation helpers +inline D3DRMRENDERQUALITY Translate(ShadingModel p_tglShadingModel) +{ + D3DRMRENDERQUALITY renderQuality; + + switch (p_tglShadingModel) { + case Wireframe: + renderQuality = D3DRMRENDER_WIREFRAME; + break; + case UnlitFlat: + renderQuality = D3DRMRENDER_UNLITFLAT; + break; + case Flat: + renderQuality = D3DRMRENDER_FLAT; + break; + case Gouraud: + renderQuality = D3DRMRENDER_GOURAUD; + break; + case Phong: + renderQuality = D3DRMRENDER_PHONG; + break; + default: + renderQuality = D3DRMRENDER_FLAT; + break; + } + + return renderQuality; +} + +inline D3DRMPROJECTIONTYPE Translate(ProjectionType p_tglProjectionType) +{ + D3DRMPROJECTIONTYPE projectionType; + switch (p_tglProjectionType) { + case Perspective: + projectionType = D3DRMPROJECT_PERSPECTIVE; + break; + case Orthographic: + projectionType = D3DRMPROJECT_ORTHOGRAPHIC; + break; + default: + projectionType = D3DRMPROJECT_PERSPECTIVE; + break; + } + return projectionType; +} + +// Yes this function serves no purpose, originally they intended it to +// convert from doubles to floats but ended up using floats throughout +// the software stack. +inline D3DRMMATRIX4D* Translate(const FloatMatrix& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) +{ + for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) { + for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) { + rD3DRMMatrix4x4[i][j] = D3DVAL(tglMatrix4x4[i][j]); + } + } + return &rD3DRMMatrix4x4; +} + +} /* namespace TglImpl */ diff --git a/LEGO1/tgl/d3drm/light.cpp b/LEGO1/tgl/d3drm/light.cpp new file mode 100644 index 00000000..96db0fd6 --- /dev/null +++ b/LEGO1/tgl/d3drm/light.cpp @@ -0,0 +1,39 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(Light, 0x4); +DECOMP_SIZE_ASSERT(LightImpl, 0x8); + +// Inlined only +LightImpl::~LightImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a3770 +void* LightImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a3780 +Result LightImpl::SetTransformation(const FloatMatrix& p_matrix) +{ + D3DRMMATRIX4D helper; + D3DRMMATRIX4D* matrix = Translate(p_matrix, helper); + return ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *matrix)); +} + +// OFFSET: LEGO1 0x100a37e0 +Result LightImpl::SetColor(float p_r, float p_g, float p_b) +{ + IDirect3DRMLightArray* lightArray; + IDirect3DRMLight* light; + m_data->GetLights(&lightArray); + lightArray->GetElement(0, &light); + return ResultVal(light->SetColorRGB(p_r, p_g, p_b)); +} \ No newline at end of file diff --git a/LEGO1/tgl/d3drm/mesh.cpp b/LEGO1/tgl/d3drm/mesh.cpp new file mode 100644 index 00000000..f9c8a17d --- /dev/null +++ b/LEGO1/tgl/d3drm/mesh.cpp @@ -0,0 +1,166 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(D3DRMVERTEX, 0x24); + +DECOMP_SIZE_ASSERT(Mesh, 0x4); +DECOMP_SIZE_ASSERT(MeshImpl, 0x8); + +// Inlined only +MeshImpl::~MeshImpl() +{ + if (m_data) { + free(m_data); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a3ed0 +void* MeshImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a3ee0 +Result MeshImpl::SetColor(float p_r, float p_g, float p_b, float p_a) +{ + // The first instruction makes no sense here: + // cmp dword ptr [esp + 0x10], 0 + // This compares a, which we know is a float because it immediately + // gets passed into D3DRMCreateColorRGBA, but does the comparison + // as though it's an int?? + if (*reinterpret_cast(&p_a) > 0) { + D3DCOLOR color = D3DRMCreateColorRGBA(p_r, p_g, p_b, p_a); + return ResultVal(m_data->groupMesh->SetGroupColor(m_data->groupIndex, color)); + } + else { + return ResultVal(m_data->groupMesh->SetGroupColorRGB(m_data->groupIndex, p_r, p_g, p_b)); + } +} + +// OFFSET: LEGO1 0x100a3f50 +Result MeshImpl::SetTexture(const Texture* p_texture) +{ + IDirect3DRMTexture* texture = p_texture ? static_cast(p_texture)->ImplementationData() : NULL; + return ResultVal(m_data->groupMesh->SetGroupTexture(m_data->groupIndex, texture)); +} + +// OFFSET: LEGO1 0x100a4330 +Result MeshImpl::GetTexture(Texture*& p_texture) +{ + IDirect3DRMTexture* texture; + TextureImpl* holder = new TextureImpl(); + Result result = ResultVal(m_data->groupMesh->GetGroupTexture(m_data->groupIndex, &texture)); + if (result) { + // Seems to actually call the first virtual method of holder here + // but that doesn't make any sense since it passes three arguments + // to the method (self + string constant? + an offset?). + + // This line makes the start of the function match and is what I + // would expect to see there but it clearly isn't what's actually + // there. + holder->SetImplementation(texture); + } + p_texture = holder; + return Success; +} + +// OFFSET: LEGO1 0x100a3f80 +Result MeshImpl::SetTextureMappingMode(ProjectionType p_projType) +{ + if (p_projType == Perspective) { + return ResultVal(m_data->groupMesh->SetGroupMapping(m_data->groupIndex, D3DRMMAP_PERSPCORRECT)); + } + else { + return ResultVal(m_data->groupMesh->SetGroupMapping(m_data->groupIndex, 0)); + } +} + +// OFFSET: LEGO1 0x100a3fc0 +Result MeshImpl::SetShadingModel(ShadingModel p_model) +{ + D3DRMRENDERQUALITY mode; + switch (p_model) { + case Wireframe: + mode = D3DRMRENDER_WIREFRAME; + break; + case UnlitFlat: + mode = D3DRMRENDER_UNLITFLAT; + break; + case Flat: + mode = D3DRMRENDER_FLAT; + break; + case Gouraud: + mode = D3DRMRENDER_GOURAUD; + break; + case Phong: + mode = D3DRMRENDER_PHONG; + break; + } + return ResultVal(m_data->groupMesh->SetGroupQuality(m_data->groupIndex, mode)); +} + +// OFFSET: LEGO1 0x100a4030 +Mesh* MeshImpl::DeepClone(Something* p_mesh) +{ + // Create group + MeshImpl* newSomething = new MeshImpl(); + MeshData* data = new MeshData(); + newSomething->m_data = data; + + // Query information from old group + DWORD dataSize; + unsigned int vcount, fcount, vperface; + m_data->groupMesh->GetGroup(m_data->groupIndex, &vcount, &fcount, &vperface, &dataSize, NULL); + unsigned int* faceBuffer = (unsigned int*) malloc(dataSize * sizeof(unsigned int)); + m_data->groupMesh->GetGroup(m_data->groupIndex, &vcount, &fcount, &vperface, &dataSize, faceBuffer); + // We expect vertex to be sized 0x24, checked at start of file. + D3DRMVERTEX* vertexBuffer = (D3DRMVERTEX*) malloc(vcount * sizeof(D3DRMVERTEX)); + m_data->groupMesh->GetVertices(m_data->groupIndex, 0, vcount, vertexBuffer); + LPDIRECT3DRMTEXTURE textureRef; + m_data->groupMesh->GetGroupTexture(m_data->groupIndex, &textureRef); + D3DRMMAPPING mapping = m_data->groupMesh->GetGroupMapping(m_data->groupIndex); + D3DRMRENDERQUALITY quality = m_data->groupMesh->GetGroupQuality(m_data->groupIndex); + D3DCOLOR color = m_data->groupMesh->GetGroupColor(m_data->groupIndex); + + // Push information to new group + SomethingImpl* target = static_cast(p_mesh); + D3DRMGROUPINDEX index; + target->ImplementationData()->AddGroup(vcount, fcount, vperface, faceBuffer, &index); + newSomething->m_data->groupIndex = index; + target->ImplementationData()->SetVertices(index, 0, vcount, vertexBuffer); + target->ImplementationData()->SetGroupTexture(index, textureRef); + target->ImplementationData()->SetGroupMapping(index, mapping); + target->ImplementationData()->SetGroupQuality(index, quality); + Result result = ResultVal(target->ImplementationData()->SetGroupColor(index, color)); + + // Cleanup + if (faceBuffer) + free(faceBuffer); + if (vertexBuffer) + free(vertexBuffer); + if (result == Error) { + delete newSomething; + newSomething = NULL; + } + + return newSomething; +} + +// OFFSET: LEGO1 0x100a4240 +Mesh* MeshImpl::ShallowClone(Something* p_mesh) +{ + MeshImpl* newGroup = new MeshImpl(); + MeshData* newData = new MeshData(); + newGroup->m_data = newData; + if (newData) { + newData->groupIndex = m_data->groupIndex; + newData->groupMesh = static_cast(p_mesh)->ImplementationData(); + } + else { + delete newGroup; + newGroup = NULL; + } + return newGroup; +} \ No newline at end of file diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp new file mode 100644 index 00000000..a3ac9895 --- /dev/null +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -0,0 +1,322 @@ +#include "impl.h" + +using namespace TglImpl; + +// OFFSET: LEGO1 0x100a15e0 +Renderer* CreateRenderer() +{ + RendererImpl* renderer = new RendererImpl(); + if (!renderer->Create()) { + delete renderer; + renderer = NULL; + } + return renderer; +} + +// OFFSET: LEGO1 0x1010103c +IDirect3DRM* g_pD3DRM = NULL; + +// Inlined only +Result RendererImpl::Create() +{ + if (g_pD3DRM) { + g_pD3DRM->AddRef(); + } + else { + LPDIRECT3DRM handle; + Direct3DRMCreate(&handle); + handle->QueryInterface(IID_IDirect3DRM2, (LPVOID*) &g_pD3DRM); + } + m_data = g_pD3DRM; + return (m_data != NULL) ? Success : Error; +} + +// Inlined only +void RendererImpl::Destroy() +{ + if (m_data) { + if (m_data->Release() == 0) + g_pD3DRM = NULL; + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a22b0 +void* RendererImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a1894 +Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& p_data) +{ + DeviceImpl* device = new DeviceImpl(); + HRESULT result = m_data->CreateDeviceFromD3D(p_data.m_pDirect3D, p_data.m_pDirect3DDevice, &device->m_data); + if (!SUCCEEDED(result)) { + delete device; + device = NULL; + } + return device; +} + +// OFFSET: LEGO1 0x10101040 +static int gSetBufferCount = 1; + +// OFFSET: LEGO1 0x100a1900 +Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& p_data) +{ + DeviceImpl* device = new DeviceImpl(); + HRESULT result = m_data->CreateDeviceFromSurface( + const_cast(p_data.m_driverGUID), + p_data.m_pDirectDraw, + p_data.m_pBackBuffer, + &device->m_data + ); + if (SUCCEEDED(result) && p_data.m_pBackBuffer && gSetBufferCount) { + device->m_data->SetBufferCount(2); + } + if (!SUCCEEDED(result)) { + delete device; + device = NULL; + } + return device; +} + +inline Result RendererCreateView( + IDirect3DRM* p_renderer, + IDirect3DRMDevice* p_device, + IDirect3DRMFrame* p_camera, + IDirect3DRMViewport*& p_view, + unsigned long p_x, + unsigned long p_y, + unsigned long p_width, + unsigned long p_height +) +{ + Result result = ResultVal(p_renderer->CreateViewport(p_device, p_camera, p_x, p_y, p_width, p_height, &p_view)); + if (Succeeded(result)) { + result = ViewImpl::ViewportCreateAppData(p_renderer, p_view, p_camera); + if (!Succeeded(result)) { + p_view->Release(); + p_view = NULL; + } + } + return result; +} + +// OFFSET: LEGO1 0x100a1a00 +View* RendererImpl::CreateView( + const Device* p_device, + const Camera* p_camera, + unsigned long p_x, + unsigned long p_y, + unsigned long p_width, + unsigned long p_height +) +{ + ViewImpl* view = new ViewImpl(); + Result result = RendererCreateView( + m_data, + static_cast(p_device)->m_data, + static_cast(p_camera)->m_data, + view->m_data, + p_x, + p_y, + p_width, + p_height + ); + if (!result) { + delete view; + view = NULL; + } + return view; +} + +// OFFSET: LEGO1 0x100a1c30 +Camera* RendererImpl::CreateCamera() +{ + CameraImpl* camera = new CameraImpl(); + if (FAILED(m_data->CreateFrame(NULL, &camera->m_data))) { + delete camera; + camera = NULL; + } + return camera; +} + +// OFFSET: LEGO1 0x100a1cf0 +Light* RendererImpl::CreateLight(LightType p_type, float p_r, float p_g, float p_b) +{ + LightImpl* newLight = new LightImpl(); + D3DRMLIGHTTYPE translatedType; + switch (p_type) { + case Ambient: + translatedType = D3DRMLIGHT_AMBIENT; + break; + case Point: + translatedType = D3DRMLIGHT_POINT; + break; + case Spot: + translatedType = D3DRMLIGHT_SPOT; + break; + case Directional: + translatedType = D3DRMLIGHT_DIRECTIONAL; + break; + case ParallelPoint: + translatedType = D3DRMLIGHT_PARALLELPOINT; + break; + default: + translatedType = D3DRMLIGHT_AMBIENT; + } + + LPDIRECT3DRMFRAME frame; + Result result = ResultVal(m_data->CreateFrame(NULL, &frame)); + if (Succeeded(result)) { + LPDIRECT3DRMLIGHT d3dLight; + result = ResultVal(m_data->CreateLightRGB(translatedType, p_r, p_g, p_b, &d3dLight)); + if (!Succeeded(result)) { + frame->Release(); + } + else { + result = ResultVal(frame->AddLight(d3dLight)); + if (!Succeeded(result)) { + d3dLight->Release(); + frame->Release(); + } + else { + d3dLight->Release(); + newLight->m_data = frame; + } + } + } + if (!Succeeded(result)) { + delete newLight; + newLight = NULL; + } + return newLight; +} + +inline Result RendererCreateGroup(IDirect3DRM* p_renderer, IDirect3DRMFrame* p_parent, IDirect3DRMFrame*& p_group) +{ + Result result = ResultVal(p_renderer->CreateFrame(NULL, &p_group)); + if (Succeeded(result) && p_parent) { + result = ResultVal(p_parent->AddVisual(p_group)); + if (!Succeeded(result)) { + p_group->Release(); + p_group = NULL; + } + } + return result; +} + +// OFFSET: LEGO1 0x100a1b20 +Group* RendererImpl::CreateGroup(const Group* p_parent) +{ + GroupImpl* group = new GroupImpl(); + Result result = + RendererCreateGroup(m_data, p_parent ? static_cast(p_parent)->m_data : NULL, group->m_data); + if (!result) { + delete group; + group = NULL; + } + return group; +} + +// OFFSET: LEGO1 0x100a1e90 +Something* RendererImpl::CreateSomething() +{ + // Note: I'm fairly certain that Something is not what Tgl calls a + // "Mesh", because the methods on Mesh in the Tgl leak line up much + // more closely with a different vtable than the one assigned in + // this method (meaning this method is not creating a Mesh). + // Maybe this method is something like CreateMeshBuilder where the + // Mesh data type in the Tgl leak was split into builder/result? + SomethingImpl* something = new SomethingImpl(); + if (FAILED(m_data->CreateMesh(&something->m_data))) { + delete something; + something = NULL; + } + return something; +} + +inline Result RendererCreateTexture( + IDirect3DRM* p_renderer, + IDirect3DRMTexture*& p_texture, + int p_width, + int p_height, + int p_bytesPerPixel, + void* p_buffer, + int p_useBuffer, + int p_paletteSize, + PaletteEntry* p_palette +) +{ + TglD3DRMIMAGE* image; + Result result; + + image = new TglD3DRMIMAGE(p_width, p_height, p_bytesPerPixel, p_buffer, p_useBuffer, p_paletteSize, p_palette); + result = ResultVal(p_renderer->CreateTexture(&image->m_image, &p_texture)); + if (Succeeded(result)) { + result = TextureImpl::SetImage(p_texture, image); + if (!Succeeded(result)) { + p_texture->Release(); + p_texture = NULL; + delete image; + } + } + else { + delete image; + } + return result; +} + +// OFFSET: LEGO1 0x100a20d0 +Texture* RendererImpl::CreateTexture() +{ + TextureImpl* texture = new TextureImpl(); + if (!Succeeded(RendererCreateTexture(m_data, texture->m_data, 0, 0, 0, NULL, FALSE, 0, NULL))) { + delete texture; + texture = NULL; + } + return texture; +} + +// OFFSET: LEGO1 0x100a1f50 +Texture* RendererImpl::CreateTexture( + int p_width, + int p_height, + int p_bitsPerTexel, + const void* p_pTexels, + int p_texelsArePersistent, + int p_paletteEntryCount, + const PaletteEntry* p_pEntries +) +{ + TextureImpl* texture = new TextureImpl(); + if (!Succeeded(RendererCreateTexture( + m_data, + texture->m_data, + p_width, + p_height, + p_bitsPerTexel, + const_cast(p_pTexels), + p_texelsArePersistent, + p_paletteEntryCount, + const_cast(p_pEntries) + ))) { + delete texture; + texture = NULL; + } + return texture; +} + +// OFFSET: LEGO1 0x100a2270 +Result RendererImpl::SetTextureDefaultShadeCount(unsigned long p_shadeCount) +{ + return ResultVal(m_data->SetDefaultTextureShades(p_shadeCount)); +} + +// OFFSET: LEGO1 0x100a2290 +Result RendererImpl::SetTextureDefaultColorCount(unsigned long p_colorCount) +{ + return ResultVal(m_data->SetDefaultTextureColors(p_colorCount)); +} diff --git a/LEGO1/tgl/d3drm/something.cpp b/LEGO1/tgl/d3drm/something.cpp new file mode 100644 index 00000000..1edbb046 --- /dev/null +++ b/LEGO1/tgl/d3drm/something.cpp @@ -0,0 +1,63 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(Something, 0x4); +DECOMP_SIZE_ASSERT(SomethingImpl, 0x8); + +// Inlined only +SomethingImpl::~SomethingImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a3830 +void* SomethingImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a3840 STUB +Result SomethingImpl::SetMeshData( + unsigned long p_faceCount, + unsigned long p_vertexCount, + const float (*p_positions)[3], + const float (*p_normals)[3], + const float (*p_textureCoordinates)[2], + unsigned long p_vertexPerFaceCount, + unsigned long* p_faceData +) +{ + return Error; +} + +// OFFSET: LEGO1 0x100a3ae0 +Result SomethingImpl::GetBoundingBox(float p_min[3], float p_max[3]) +{ + D3DRMBOX box; + Result result = ResultVal(m_data->GetBox(&box)); + if (result == Success) { + p_min[0] = box.min.x; + p_min[1] = box.min.y; + p_min[2] = box.min.z; + p_max[0] = box.max.x; + p_max[1] = box.max.y; + p_max[2] = box.max.z; + } + return result; +} + +// OFFSET: LEGO1 0x100a3b40 +Something* SomethingImpl::Clone() +{ + SomethingImpl* mesh = new SomethingImpl(); + int ret = m_data->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_data); + if (ret < 0) { + delete mesh; + mesh = NULL; + } + return mesh; +} diff --git a/LEGO1/tgl/d3drm/texture.cpp b/LEGO1/tgl/d3drm/texture.cpp new file mode 100644 index 00000000..41712779 --- /dev/null +++ b/LEGO1/tgl/d3drm/texture.cpp @@ -0,0 +1,199 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(TglD3DRMIMAGE, 0x40); + +// OFFSET: LEGO1 0x100a1330 +TglD3DRMIMAGE::TglD3DRMIMAGE( + int p_width, + int p_height, + int p_depth, + void* p_buffer, + int p_useBuffer, + int p_paletteSize, + PaletteEntry* p_palette +) +{ + m_image.aspectx = 1; + m_image.aspecty = 1; + m_image.width = 0; + m_image.height = 0; + m_image.depth = 0; + m_image.rgb = 0; + m_image.bytes_per_line = 0; + m_image.buffer1 = NULL; + m_image.buffer2 = NULL; + m_image.red_mask = 0xFF; + m_image.green_mask = 0xFF; + m_image.blue_mask = 0xFF; + m_image.alpha_mask = 0xFF; + m_image.palette_size = 0; + m_image.palette = NULL; + m_texelsAllocatedByClient = 0; + if (p_buffer != NULL) { + CreateBuffer(p_width, p_height, p_depth, p_buffer, p_useBuffer); + } + if (p_palette != NULL) { + InitializePalette(p_paletteSize, p_palette); + } +} + +// OFFSET: LEGO1 0x100a13e0 STUB +Result TglD3DRMIMAGE::CreateBuffer(int p_width, int p_height, int p_depth, void* p_buffer, int p_useBuffer) +{ + return Error; +} + +// OFFSET: LEGO1 0x100a13b0 +void TglD3DRMIMAGE::Destroy() +{ + if (m_texelsAllocatedByClient == 0) { + free(m_image.buffer1); + } + free(m_image.palette); +} + +// OFFSET: LEGO1 0x100a1510 +void TglD3DRMIMAGE::FillRowsOfTexture(int p_y, int p_height, char* p_content) +{ + // The purpose is clearly this but I can't get the assembly to line up. + memcpy((char*) m_image.buffer1 + (p_y * m_image.bytes_per_line), p_content, p_height * m_image.bytes_per_line); +} + +// OFFSET: LEGO1 0x100a1550 +Result TglD3DRMIMAGE::InitializePalette(int p_paletteSize, PaletteEntry* p_palette) +{ + // This function is a 100% match if the PaletteEntry class is copied + // into into the TglD3DRMIMAGE class instead of being a global struct. + if (m_image.palette_size != p_paletteSize) { + if (m_image.palette != NULL) { + free(m_image.palette); + m_image.palette = NULL; + m_image.palette_size = 0; + } + if (p_paletteSize > 0) { + m_image.palette = (D3DRMPALETTEENTRY*) malloc(4 * p_paletteSize); + m_image.palette_size = p_paletteSize; + } + } + if (p_paletteSize > 0) { + for (int i = 0; i < p_paletteSize; i++) { + m_image.palette[i].red = p_palette[i].m_red; + m_image.palette[i].green = p_palette[i].m_green; + m_image.palette[i].blue = p_palette[i].m_blue; + m_image.palette[i].flags = D3DRMPALETTE_READONLY; + } + } + return Success; +} + +// Inlined only +TextureImpl::~TextureImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a3d70 +void* TextureImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +inline TglD3DRMIMAGE* TextureGetImage(IDirect3DRMTexture* p_texture) +{ + return reinterpret_cast(p_texture->GetAppData()); +} + +// OFFSET: LEGO1 0x100a3c10 +Result TextureImpl::SetTexels(int p_width, int p_height, int p_bitsPerTexel, void* p_texels) +{ + TglD3DRMIMAGE* image = TextureGetImage(m_data); + Result result = image->CreateBuffer(p_width, p_height, p_bitsPerTexel, p_texels, TRUE); + if (Succeeded(result)) { + result = ResultVal(m_data->Changed(TRUE, FALSE)); + } + return result; +} + +// OFFSET: LEGO1 0x100a3c60 +void TextureImpl::FillRowsOfTexture(int p_y, int p_height, void* p_buffer) +{ + TglD3DRMIMAGE* image = TextureGetImage(m_data); + image->FillRowsOfTexture(p_y, p_height, (char*) p_buffer); +} + +// OFFSET: LEGO1 0x100a3c90 +Result TextureImpl::Changed(int p_texelsChanged, int p_paletteChanged) +{ + return ResultVal(m_data->Changed(p_texelsChanged, p_paletteChanged)); +} + +// OFFSET: LEGO1 0x100a3d00 +Result TextureImpl::GetBufferAndPalette( + int* p_width, + int* p_height, + int* p_depth, + void** p_buffer, + int* p_paletteSize, + PaletteEntry** p_palette +) +{ + // Something really doesn't match here, not sure what's up. + TglD3DRMIMAGE* image = TextureGetImage(m_data); + *p_width = image->m_image.width; + *p_height = image->m_image.height; + *p_depth = image->m_image.depth; + *p_buffer = image->m_image.buffer1; + *p_paletteSize = image->m_image.palette_size; + for (int i = 0; i < image->m_image.palette_size; i++) { + p_palette[i]->m_red = image->m_image.palette[i].red; + p_palette[i]->m_green = image->m_image.palette[i].green; + p_palette[i]->m_blue = image->m_image.palette[i].blue; + } + return Success; +} + +// OFFSET: LEGO1 0x100a3d40 +Result TextureImpl::SetPalette(int p_entryCount, PaletteEntry* p_entries) +{ + // Not 100% confident this is supposed to directly be forwarding arguments, + // but it probably is given FillRowsOfTexture matches doing that. + TglD3DRMIMAGE* image = TextureGetImage(m_data); + image->InitializePalette(p_entryCount, p_entries); + m_data->Changed(FALSE, TRUE); + return Success; +} + +// OFFSET: LEGO1 0x100a1300 +void TextureDestroyCallback(IDirect3DRMObject* pObject, void* pArg) +{ + TglD3DRMIMAGE* pImage = reinterpret_cast(pObject->GetAppData()); + delete pImage; + pObject->SetAppData(0); +} + +// OFFSET: LEGO1 0x100a12a0 +Result TextureImpl::SetImage(IDirect3DRMTexture* p_self, TglD3DRMIMAGE* p_image) +{ + unsigned long appData; + Result result; + + appData = reinterpret_cast(p_image); + + // This is here because in the original code they asserted + // on the return value being NULL. + TextureGetImage(p_self); + + result = ResultVal(p_self->SetAppData(appData)); + if (Succeeded(result) && p_image) { + result = ResultVal(p_self->AddDestroyCallback(TextureDestroyCallback, NULL)); + if (!Succeeded(result)) { + p_self->SetAppData(0); + } + } + return result; +} diff --git a/LEGO1/tgl/d3drm/view.cpp b/LEGO1/tgl/d3drm/view.cpp new file mode 100644 index 00000000..ac81da97 --- /dev/null +++ b/LEGO1/tgl/d3drm/view.cpp @@ -0,0 +1,352 @@ +#include "impl.h" + +using namespace TglImpl; + +struct ViewportAppData { + ViewportAppData(IDirect3DRM* p_renderer); + ~ViewportAppData(); + + IDirect3DRMFrame* m_pLightFrame; + IDirect3DRMFrame* m_pCamera; + IDirect3DRMFrame* m_pLastRenderedFrame; + float m_backgroundColorRed; + float m_backgroundColorGreen; + float m_backgroundColorBlue; +}; + +// OFFSET: LEGO1 0x100a10b0 +ViewportAppData::ViewportAppData(IDirect3DRM* p_renderer) +{ + p_renderer->CreateFrame(NULL, &m_pLightFrame); + m_pCamera = NULL; + m_pLastRenderedFrame = NULL; + m_backgroundColorRed = 0.0f; + m_backgroundColorGreen = 0.0f; + m_backgroundColorBlue = 0.0f; +} + +// OFFSET: LEGO1 0x100a10e0 +ViewportAppData::~ViewportAppData() +{ + IDirect3DRMFrameArray* pChildFrames; + IDirect3DRMFrame* pChildFrame = NULL; + m_pLightFrame->GetChildren(&pChildFrames); + for (int i = 0; i < (int) pChildFrames->GetSize(); i++) { + pChildFrames->GetElement(i, &pChildFrame); + m_pLightFrame->DeleteChild(pChildFrame); + pChildFrame->Release(); // GetElement() does AddRef() + } + pChildFrames->Release(); + m_pLightFrame->Release(); +} + +DECOMP_SIZE_ASSERT(ViewportAppData, 0x18); + +inline ViewportAppData* ViewportGetData(IDirect3DRMViewport* p_viewport) +{ + return reinterpret_cast(p_viewport->GetAppData()); +} + +inline IDirect3DRMFrame* ViewportGetLightFrame(IDirect3DRMViewport* p_viewport) +{ + return ViewportGetData(p_viewport)->m_pLightFrame; +} + +// Inlined only +ViewImpl::~ViewImpl() +{ + if (m_data) { + m_data->Release(); + m_data = NULL; + } +} + +// OFFSET: LEGO1 0x100a2d80 +void* ViewImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// OFFSET: LEGO1 0x100a2d90 +Result ViewImpl::Add(const Light* p_light) +{ + const LightImpl* light = static_cast(p_light); + IDirect3DRMFrame* frame = light->ImplementationData(); + return ResultVal(ViewportGetLightFrame(m_data)->AddChild(frame)); +} + +// OFFSET: LEGO1 0x100a2dc0 +Result ViewImpl::Remove(const Light* p_light) +{ + const LightImpl* light = static_cast(p_light); + IDirect3DRMFrame* frame = light->ImplementationData(); + return ResultVal(ViewportGetLightFrame(m_data)->DeleteChild(frame)); +} + +inline Result ViewRestoreFrameAfterRender( + IDirect3DRMFrame* pFrame, + IDirect3DRMFrame* pCamera, + IDirect3DRMFrame* pLightFrame +) +{ + Result result = Success; + if (pFrame) { + // remove camera and light frame from frame that was rendered + // this doesn't destroy the camera as it is still the camera of the viewport... + result = ResultVal(pFrame->DeleteChild(pCamera)); + result = ResultVal(pFrame->DeleteChild(pLightFrame)); + + // decrease frame's ref count (it was increased in ViewPrepareFrameForRender()) + pFrame->Release(); + } + return result; +} + +// OFFSET: LEGO1 0x100a2df0 +Result ViewImpl::SetCamera(const Camera* p_camera) +{ + const CameraImpl* camera = static_cast(p_camera); + IDirect3DRMFrame* frame = camera->ImplementationData(); + + ViewportAppData* pViewportAppData; + Result result; + + pViewportAppData = reinterpret_cast(m_data->GetAppData()); + result = ViewRestoreFrameAfterRender( + pViewportAppData->m_pLastRenderedFrame, + pViewportAppData->m_pCamera, + pViewportAppData->m_pLightFrame + ); + pViewportAppData->m_pCamera = frame; + pViewportAppData->m_pLastRenderedFrame = 0; + + return ResultVal(m_data->SetCamera(frame)); +} + +// OFFSET: LEGO1 0x100a2e70 +Result ViewImpl::SetProjection(ProjectionType p_type) +{ + return ResultVal(m_data->SetProjection(Translate(p_type))); +} + +// OFFSET: LEGO1 0x100a2eb0 +Result ViewImpl::SetFrustrum(float p_frontClippingDistance, float p_backClippingDistance, float p_degrees) +{ + float field = p_frontClippingDistance * tan(DegreesToRadians(p_degrees / 2)); + Result result; + result = ResultVal(m_data->SetFront(p_frontClippingDistance)); + if (Succeeded(result)) { + result = ResultVal(m_data->SetBack(p_backClippingDistance)); + } + if (Succeeded(result)) { + result = ResultVal(m_data->SetField(field)); + } + + return result; +} + +// OFFSET: LEGO1 0x100a2f30 +Result ViewImpl::SetBackgroundColor(float p_r, float p_g, float p_b) +{ + Result ret = Success; + // Note, this method in the shipped game is very diverged from + // the Tgl leak code. + ViewportAppData* data = ViewportGetData(m_data); + data->m_backgroundColorRed = p_r; + data->m_backgroundColorGreen = p_g; + data->m_backgroundColorBlue = p_b; + if (data->m_pLastRenderedFrame) { + ret = ResultVal(data->m_pLastRenderedFrame->SetSceneBackgroundRGB(p_r, p_g, p_b)); + } + return ret; +} + +// OFFSET: LEGO1 0x100a2f80 +Result ViewImpl::GetBackgroundColor(float* p_r, float* p_g, float* p_b) +{ + ViewportAppData* data = ViewportGetData(m_data); + *p_r = data->m_backgroundColorRed; + *p_g = data->m_backgroundColorGreen; + *p_b = data->m_backgroundColorBlue; + return Success; +} + +// OFFSET: LEGO1 0x100a2fb0 +Result ViewImpl::Clear() +{ + return ResultVal(m_data->Clear()); +} + +inline Result ViewPrepareFrameForRender( + IDirect3DRMFrame* pFrame, + IDirect3DRMFrame* pCamera, + IDirect3DRMFrame* pLightFrame, + float backgroundRed, + float backgroundGreen, + float backgroundBlue +) +{ + Result result = Success; + + if (pFrame) { + // set background color + result = ResultVal(pFrame->SetSceneBackgroundRGB(backgroundRed, backgroundGreen, backgroundBlue)); + + // add camera to frame to be rendered + result = ResultVal(pFrame->AddChild(pCamera)); + + // add light frame to frame to be rendered + result = ResultVal(pFrame->AddChild(pLightFrame)); + + // increase ref count of frame to ensure it does not get deleted underneath us + pFrame->AddRef(); + } + + return result; +} + +// OFFSET: LEGO1 0x100a2fd0 +Result ViewImpl::Render(const Light* p_camera) +{ + ViewportAppData* appdata = ViewportGetData(m_data); + + IDirect3DRMFrame* light = static_cast(p_camera)->ImplementationData(); + + IDirect3DRMFrame* lastRendered = appdata->m_pLastRenderedFrame; + if (light != lastRendered) { + if (lastRendered) { + lastRendered->DeleteChild(appdata->m_pCamera); + // Some other call goes here, not sure what. + lastRendered->Release(); + } + appdata->m_pLastRenderedFrame = light; + if (light) { + light->SetSceneBackgroundRGB( + appdata->m_backgroundColorRed, + appdata->m_backgroundColorGreen, + appdata->m_backgroundColorBlue + ); + light->AddChild(appdata->m_pCamera); + // Some other call goes here, not sure what. + light->AddRef(); + } + } + return ResultVal(m_data->Render(light)); +} + +// OFFSET: LEGO1 0x100a3080 +Result ViewImpl::ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) +{ + return ResultVal(m_data->ForceUpdate(x, y, x + width - 1, y + height - 1)); +} + +// OFFSET: LEGO1 0x100a30f0 +Result ViewImpl::TransformWorldToScreen(const float world[3], float screen[4]) +{ + D3DRMVECTOR4D d3dRMScreen; + D3DVECTOR d3dRMWorld; + d3dRMWorld.x = world[0]; + d3dRMWorld.y = world[1]; + d3dRMWorld.z = world[2]; + Result result; + + result = ResultVal(m_data->Transform(&d3dRMScreen, &d3dRMWorld)); + + if (Succeeded(result)) { + screen[0] = d3dRMScreen.x; + screen[1] = d3dRMScreen.y; + screen[2] = d3dRMScreen.z; + screen[3] = d3dRMScreen.w; + } + + return result; +} + +// OFFSET: LEGO1 0x100a3160 +Result ViewImpl::TransformScreenToWorld(const float p_screen[4], float p_world[3]) +{ + // 100% match minus instruction reordering. + D3DVECTOR d3dRMWorld; + D3DRMVECTOR4D d3dScreen; + d3dScreen.x = p_screen[0]; + d3dScreen.y = p_screen[1]; + d3dScreen.z = p_screen[2]; + d3dScreen.w = p_screen[3]; + Result result; + + result = ResultVal(m_data->InverseTransform(&d3dRMWorld, &d3dScreen)); + + if (Succeeded(result)) { + p_world[0] = d3dRMWorld.x; + p_world[1] = d3dRMWorld.y; + p_world[2] = d3dRMWorld.z; + } + + return result; +} + +// OFFSET: LEGO1 0x100a1290 +Result ViewportPickImpl( + IDirect3DRMViewport* p_viewport, + int x, + int y, + const Group** ppGroupsToPickFrom, + int groupsToPickFromCount, + const Group**& rppPickedGroups, + int& rPickedGroupCount +) +{ + // Left unimplemented in shipped game. + return Error; +} + +// OFFSET: LEGO1 0x100a30c0 +Result ViewImpl::Pick( + unsigned long x, + unsigned long y, + const Group** ppGroupsToPickFrom, + int groupsToPickFromCount, + const Group**& rppPickedGroups, + int& rPickedGroupCount +) +{ + return ViewportPickImpl( + m_data, + x, + y, + ppGroupsToPickFrom, + groupsToPickFromCount, + rppPickedGroups, + rPickedGroupCount + ); +} + +// OFFSET: LEGO1 0x100a1240 +void ViewportDestroyCallback(IDirect3DRMObject* p_object, void* p_arg) +{ + ViewportAppData* pViewportAppData = reinterpret_cast(p_arg); + + ViewRestoreFrameAfterRender( + pViewportAppData->m_pLastRenderedFrame, + pViewportAppData->m_pCamera, + pViewportAppData->m_pLightFrame + ); + + delete pViewportAppData; +} + +// OFFSET: LEGO1 0x100a1160 +Result ViewImpl::ViewportCreateAppData(IDirect3DRM* p_device, IDirect3DRMViewport* p_view, IDirect3DRMFrame* p_camera) +{ + ViewportAppData* data = new ViewportAppData(p_device); + data->m_pCamera = p_camera; + Result result = ResultVal(p_view->SetAppData(reinterpret_cast(data))); + if (Succeeded(result)) { + result = ResultVal(p_view->AddDestroyCallback(ViewportDestroyCallback, data)); + } + if (!Succeeded(result)) { + delete data; + p_view->SetAppData(0); + } + return result; +} diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index 5dec4a56..c32353f7 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -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 #include -#include // HWND - -#endif /* _WIN32 */ - -#include "tglVector.h" +#include 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 Something; -////////////////////////////////////////////////////////////////////////////// -// -// 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,98 +123,69 @@ class Renderer : public Object { unsigned long height ) = 0; virtual Camera* CreateCamera() = 0; - virtual Light* CreateLight(LightType, double r, double g, double b) = 0; - virtual Group* CreateGroup(const Group* pParent = 0) = 0; + virtual Light* CreateLight(LightType, float p_r, float p_g, float p_b) = 0; + virtual Group* CreateGroup(const Group* p_parent = 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; - virtual Texture* CreateTexture( - int width, - int height, - int bitsPerTexel, - const void* pTexels, - int pTexelsArePersistent, - int paletteEntryCount, - const PaletteEntry* pEntries - ) = 0; + // vtable+0x20 + virtual Something* CreateSomething() = 0; virtual Texture* CreateTexture() = 0; - + virtual Texture* CreateTexture( + int p_width, + int p_height, + int p_bitsPerTexel, + const void* p_pTexels, + int p_pTexelsArePersistent, + int p_paletteEntryCount, + const PaletteEntry* p_pEntries + ) = 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 p_frontClippingDistance, float p_backClippingDistance, float p_degrees) = 0; + virtual Result SetBackgroundColor(float p_r, float p_g, float p_b) = 0; + // vtable+0x20 + virtual Result GetBackgroundColor(float* p_r, float* p_g, float* p_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 @@ class View : public Object { ) = 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; + virtual Result SetTransformation(const FloatMatrix&) = 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 SetTransformation(const FloatMatrix&) = 0; + virtual Result SetColor(float p_r, float p_g, float p_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 p_r, float p_g, float p_b, float p_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(Something*) = 0; + + // Just get another Group pointing to the same underlying data + virtual Mesh* ShallowClone(Something*) = 0; }; -////////////////////////////////////////////////////////////////////////////// -// -// Texture +// VTABLE 0x100dbaa0 +class Group : public Object { +public: + virtual Result SetTransformation(const FloatMatrix&) = 0; + virtual Result SetColor(float p_r, float p_g, float p_b, float p_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 Something : public Object { +public: + virtual Result SetMeshData( + unsigned long p_faceCount, + unsigned long p_vertexCount, + const float (*p_positions)[3], + const float (*p_normals)[3], + const float (*p_textureCoordinates)[2], + unsigned long p_vertexPerFaceCount, + unsigned long* p_faceData + ) = 0; + virtual Result GetBoundingBox(float p_min[3], float p_max[3]) = 0; + virtual Something* 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 p_width, int p_height, int p_bitsPerTexel, void* p_texels) = 0; + virtual void FillRowsOfTexture(int p_y, int p_height, void* p_buffer) = 0; -////////////////////////////////////////////////////////////////////////////// + // vtable+0x10 + virtual Result Changed(int p_texelsChanged, int p_paletteChanged) = 0; + virtual Result GetBufferAndPalette( + int* p_width, + int* p_height, + int* p_depth, + void** p_buffer, + int* p_paletteSize, + PaletteEntry** p_palette + ) = 0; + virtual Result SetPalette(int p_entryCount, PaletteEntry* p_entries) = 0; +}; } // namespace Tgl -#endif // TGL_H +#endif /* _tgl_h */ diff --git a/LEGO1/tgl/tglvector.h b/LEGO1/tgl/tglvector.h index a617928d..f0fd5ec7 100644 --- a/LEGO1/tgl/tglvector.h +++ b/LEGO1/tgl/tglvector.h @@ -1,7 +1,10 @@ -#ifndef TGLVECTOR_H -#define TGLVECTOR_H +#ifndef _tglVector_h +#define _tglVector_h +// Note: This file is almost an exact copy of the one from +// the leak but using floats instead of doubles, hence the +// strange formatting in some places. -#include "math.h" // ??? sin() in RotateAroundY() +#include "math.h" // sin() in RotateAroundY() #include // offsetof() @@ -72,22 +75,22 @@ inline void Array::operator+=(const Array& rArray) ////////////////////////////////////////////////////////////////////////////// // -// FloatMatrix4 +// FloatMatrix -class FloatMatrix4 : public Array, 4> { +class FloatMatrix : public Array, 4> { public: - FloatMatrix4() {} - FloatMatrix4(const FloatMatrix4& rMatrix) { *this = rMatrix; } - FloatMatrix4(const FloatMatrix4&, const FloatMatrix4&); + FloatMatrix() {} + FloatMatrix(const FloatMatrix& rMatrix) { *this = rMatrix; } + FloatMatrix(const FloatMatrix&, const FloatMatrix&); - void operator*=(const FloatMatrix4&); + void operator*=(const FloatMatrix&); }; ////////////////////////////////////////////////////////////////////////////// // -// FloatMatrix4 implementation +// FloatMatrix implementation -inline FloatMatrix4::FloatMatrix4(const FloatMatrix4& rMatrix1, const FloatMatrix4& rMatrix2) +inline FloatMatrix::FloatMatrix(const FloatMatrix& rMatrix1, const FloatMatrix& rMatrix2) { for (int row = 0; row < 4; row++) { for (int column = 0; column < 4; column++) { @@ -102,11 +105,11 @@ inline FloatMatrix4::FloatMatrix4(const FloatMatrix4& rMatrix1, const FloatMatri } } -inline void FloatMatrix4::operator*=(const FloatMatrix4& rMatrix) +inline void FloatMatrix::operator*=(const FloatMatrix& rMatrix) { - FloatMatrix4 temp(*this, rMatrix); + FloatMatrix temp(*this, rMatrix); - // *this = FloatMatrix4(*this, rMatrix); + // *this = FloatMatrix(*this, rMatrix); *this = temp; } @@ -114,7 +117,7 @@ inline void FloatMatrix4::operator*=(const FloatMatrix4& rMatrix) // // Transformation matrices -class Translation : public FloatMatrix4 { +class Translation : public FloatMatrix { public: Translation(const float[3]); Translation(float x, float y, float z); @@ -123,7 +126,7 @@ class Translation : public FloatMatrix4 { void Init(float x, float y, float z); }; -class Scale : public FloatMatrix4 { +class Scale : public FloatMatrix { public: Scale(const float[3]); Scale(float x, float y, float z); @@ -133,16 +136,15 @@ class Scale : public FloatMatrix4 { void Init(float x, float y, float z); }; -class RotationX : public FloatMatrix4 { +class RotationX : public FloatMatrix { public: RotationX(float radians); }; -class RotationY : public FloatMatrix4 { +class RotationY : public FloatMatrix { public: RotationY(float radians); }; - ////////////////////////////////////////////////////////////////////////////// // // Transformation matrices implementation @@ -274,4 +276,4 @@ inline RotationY::RotationY(float radians) } // namespace Tgl -#endif // TLGVECTOR_H +#endif /* _tglVector_h */