diff --git a/CMakeLists.txt b/CMakeLists.txt index 392d4dbe..39112c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,12 @@ add_library(lego1 SHARED 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 @@ -237,6 +243,7 @@ endif() if (ISLE_USE_DX5) target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") + target_link_libraries(lego1 PRIVATE d3drm) endif() # Link libraries diff --git a/LEGO1/mxdirect3drm.cpp b/LEGO1/mxdirect3drm.cpp new file mode 100644 index 00000000..ee0701cb --- /dev/null +++ b/LEGO1/mxdirect3drm.cpp @@ -0,0 +1,65 @@ +#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 new file mode 100644 index 00000000..97fc16dc --- /dev/null +++ b/LEGO1/mxdirect3drm.h @@ -0,0 +1,47 @@ + +#include "mxdirect3drmdevice.h" + +#include "ddraw.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; +}; \ No newline at end of file diff --git a/LEGO1/mxdirect3drmclasses.cpp b/LEGO1/mxdirect3drmclasses.cpp new file mode 100644 index 00000000..39423a11 --- /dev/null +++ b/LEGO1/mxdirect3drmclasses.cpp @@ -0,0 +1,96 @@ +#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 new file mode 100644 index 00000000..f82ca69c --- /dev/null +++ b/LEGO1/mxdirect3drmclasses.h @@ -0,0 +1,95 @@ + +#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; +}; \ No newline at end of file diff --git a/LEGO1/mxdirect3drmdevice.cpp b/LEGO1/mxdirect3drmdevice.cpp new file mode 100644 index 00000000..cac15221 --- /dev/null +++ b/LEGO1/mxdirect3drmdevice.cpp @@ -0,0 +1,105 @@ +#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 new file mode 100644 index 00000000..989effe9 --- /dev/null +++ b/LEGO1/mxdirect3drmdevice.h @@ -0,0 +1,52 @@ + +#include "mxtypes.h" + +#include "d3drm.h" + +#include "mxdirect3drmobject.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; +}; \ No newline at end of file diff --git a/LEGO1/mxdirect3drmobject.cpp b/LEGO1/mxdirect3drmobject.cpp new file mode 100644 index 00000000..032a9137 --- /dev/null +++ b/LEGO1/mxdirect3drmobject.cpp @@ -0,0 +1,5 @@ +#include "mxdirect3drmobject.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(IMxDirect3DRMObject, 0x4); diff --git a/LEGO1/mxdirect3drmobject.h b/LEGO1/mxdirect3drmobject.h new file mode 100644 index 00000000..f3e05567 --- /dev/null +++ b/LEGO1/mxdirect3drmobject.h @@ -0,0 +1,14 @@ + +#include "mxtypes.h" +#include "d3d.h" + +#include "d3drm.h" + +// VTABLE 0x100db980 +class IMxDirect3DRMObject +{ +public: + virtual ~IMxDirect3DRMObject() {} + + virtual IUnknown **GetHandle() = 0; +}; \ No newline at end of file diff --git a/LEGO1/mxdirect3drmtexture.cpp b/LEGO1/mxdirect3drmtexture.cpp new file mode 100644 index 00000000..8463606c --- /dev/null +++ b/LEGO1/mxdirect3drmtexture.cpp @@ -0,0 +1,166 @@ +#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 new file mode 100644 index 00000000..7803755e --- /dev/null +++ b/LEGO1/mxdirect3drmtexture.h @@ -0,0 +1,73 @@ + +#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 new file mode 100644 index 00000000..6b8e006e --- /dev/null +++ b/LEGO1/mxdirect3drmviewport.cpp @@ -0,0 +1,189 @@ +#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 new file mode 100644 index 00000000..4049e1c1 --- /dev/null +++ b/LEGO1/mxdirect3drmviewport.h @@ -0,0 +1,76 @@ + +#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; +};