diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 605d0626..e7848c02 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -5,12 +5,14 @@ #include "legophonemelist.h" #include "mxvideomanager.h" +#include #include class Lego3DManager; class LegoROI; class MxDirect3D; class MxStopWatch; +struct ViewportAppData; namespace Tgl { @@ -70,40 +72,52 @@ private: inline void DrawCursor(); - Tgl::Renderer* m_renderer; // 0x64 - Lego3DManager* m_3dManager; // 0x68 - LegoROI* m_viewROI; // 0x6c - undefined4 m_unk0x70; // 0x70 - MxDirect3D* m_direct3d; // 0x74 - undefined4 m_unk0x78[27]; // 0x78 - MxBool m_render3d; // 0xe4 - MxBool m_unk0xe5; // 0xe5 - MxBool m_unk0xe6; // 0xe6 - PALETTEENTRY m_paletteEntries[256]; // 0xe7 - undefined m_padding0x4e7; // 0x4e7 - LegoPhonemeList* m_phonemeRefList; // 0x4e8 - MxBool m_isFullscreenMovie; // 0x4ec - MxPalette* m_palette; // 0x4f0 - MxStopWatch* m_stopWatch; // 0x4f4 - double m_elapsedSeconds; // 0x4f8 - MxBool m_fullScreenMovie; // 0x500 - MxBool m_drawCursor; // 0x501 - MxS32 m_cursorXCopy; // 0x504 - MxS32 m_cursorYCopy; // 0x508 - MxS32 m_cursorX; // 0x50c - MxS32 m_cursorY; // 0x510 - LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514 - RECT m_cursorRect; // 0x518 - LPDIRECTDRAWSURFACE m_unk0x528; // 0x528 - MxBool m_drawFPS; // 0x52c - RECT m_fpsRect; // 0x530 - HFONT m_arialFont; // 0x540 - SIZE m_fpsSize; // 0x544 - MxFloat m_unk0x54c; // 0x54c - MxFloat m_unk0x550; // 0x550 - MxBool m_unk0x554; // 0x554 - MxBool m_paused; // 0x555 - undefined m_pad0x556[0x39]; // 0x556 + Tgl::Renderer* m_renderer; // 0x64 + Lego3DManager* m_3dManager; // 0x68 + LegoROI* m_viewROI; // 0x6c + undefined4 m_unk0x70; // 0x70 + MxDirect3D* m_direct3d; // 0x74 + undefined4 m_unk0x78[27]; // 0x78 + MxBool m_render3d; // 0xe4 + MxBool m_unk0xe5; // 0xe5 + MxBool m_unk0xe6; // 0xe6 + PALETTEENTRY m_paletteEntries[256]; // 0xe7 + LegoPhonemeList* m_phonemeRefList; // 0x4e8 + MxBool m_isFullscreenMovie; // 0x4ec + MxPalette* m_palette; // 0x4f0 + MxStopWatch* m_stopWatch; // 0x4f4 + double m_elapsedSeconds; // 0x4f8 + MxBool m_fullScreenMovie; // 0x500 + MxBool m_drawCursor; // 0x501 + MxS32 m_cursorXCopy; // 0x504 + MxS32 m_cursorYCopy; // 0x508 + MxS32 m_cursorX; // 0x50c + MxS32 m_cursorY; // 0x510 + LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514 + RECT m_cursorRect; // 0x518 + LPDIRECTDRAWSURFACE m_unk0x528; // 0x528 + MxBool m_drawFPS; // 0x52c + RECT m_fpsRect; // 0x530 + HFONT m_arialFont; // 0x540 + SIZE m_fpsSize; // 0x544 + MxFloat m_unk0x54c; // 0x54c + MxFloat m_unk0x550; // 0x550 + MxBool m_unk0x554; // 0x554 + MxBool m_paused; // 0x555 + D3DVALUE m_back; // 0x558 + D3DVALUE m_front; // 0x55c + float m_cameraWidth; // 0x560 + float m_cameraHeight; // 0x564 + D3DVALUE m_fov; // 0x55c + IDirect3DRMFrame* m_camera; // 0x56c + D3DRMPROJECTIONTYPE m_projection; // 0x570 + ViewportAppData* m_appdata; // 0x574 + D3DRMRENDERQUALITY m_quality; // 0x578 + DWORD m_shades; // 0x57c + D3DRMTEXTUREQUALITY m_textureQuality; // 0x580 + DWORD m_rendermode; // 0x584 + BOOL m_dither; // 0x588 + DWORD m_bufferCount; // 0x58c }; // SYNTHETIC: LEGO1 0x1007ab20 diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 70fae9aa..7c5a2cbb 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -561,18 +561,112 @@ void LegoVideoManager::FUN_1007c520() InputManager()->SetUnknown335(TRUE); } -// STUB: LEGO1 0x1007c560 +extern void ViewportDestroyCallback(IDirect3DRMObject*, void*); + +// FUNCTION: LEGO1 0x1007c560 int LegoVideoManager::EnableRMDevice() { - // TODO - return 0; + IDirect3DRMViewport* viewport; + + if (!m_paused) { + return -1; + } + + TglImpl::DeviceImpl* deviceImpl = (TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice(); + IDirect3DRMDevice2* d3drmDev2 = NULL; + IDirect3D2* d3d2 = m_direct3d->Direct3D(); + IDirect3DDevice2* d3dDev2 = m_direct3d->Direct3DDevice(); + + int result = -1; + IDirect3DRM2* d3drm2 = ((TglImpl::RendererImpl*) m_renderer)->ImplementationData(); + + m_direct3d->RestoreSurfaces(); + + if (d3drm2->CreateDeviceFromD3D(d3d2, d3dDev2, &d3drmDev2) == D3DRM_OK) { + viewport = NULL; + deviceImpl->SetImplementationData(d3drmDev2); + + if (d3drm2->CreateViewport(d3drmDev2, m_camera, 0, 0, m_cameraWidth, m_cameraHeight, &viewport) == D3DRM_OK) { + viewport->SetBack(m_back); + viewport->SetFront(m_front); + viewport->SetField(m_fov); + viewport->SetCamera(m_camera); + viewport->SetProjection(m_projection); + viewport->SetAppData((DWORD) m_appdata); + d3drmDev2->SetQuality(m_quality); + d3drmDev2->SetShades(m_shades); + d3drmDev2->SetTextureQuality(m_textureQuality); + d3drmDev2->SetRenderMode(m_rendermode); + d3drmDev2->SetDither(m_dither); + d3drmDev2->SetBufferCount(m_bufferCount); + m_camera->Release(); + + if (viewport->AddDestroyCallback(ViewportDestroyCallback, m_appdata) == D3DRM_OK) { + ((TglImpl::ViewImpl*) m_3dManager->GetLego3DView()->GetView())->SetImplementationData(viewport); + m_paused = 0; + result = 0; + } + } + } + + return result; } -// STUB: LEGO1 0x1007c740 +// FUNCTION: LEGO1 0x1007c740 int LegoVideoManager::DisableRMDevice() { - // TODO - return 0; + if (m_paused) { + return -1; + } + + IDirect3DRMDevice2* d3drmDev2 = + ((TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice())->ImplementationData(); + + if (d3drmDev2 != NULL) { + IDirect3DRMViewportArray* viewportArray = NULL; + + if (d3drmDev2->GetViewports(&viewportArray) == D3DRM_OK && viewportArray != NULL) { + if (viewportArray->GetSize() == 1) { + IDirect3DRMViewport* viewport = NULL; + + if (viewportArray->GetElement(0, &viewport) == D3DRM_OK) { + m_back = viewport->GetBack(); + m_front = viewport->GetFront(); + m_cameraWidth = viewport->GetWidth(); + m_cameraHeight = viewport->GetHeight(); + m_fov = viewport->GetField(); + viewport->GetCamera(&m_camera); + m_projection = viewport->GetProjection(); + m_appdata = (ViewportAppData*) viewport->GetAppData(); + viewportArray->Release(); + viewport->Release(); + viewport->DeleteDestroyCallback(ViewportDestroyCallback, this->m_appdata); + viewport->Release(); + m_paused = 1; + m_direct3d->Direct3D()->AddRef(); + m_direct3d->Direct3DDevice()->AddRef(); + } + else { + viewportArray->Release(); + } + } + } + + m_quality = d3drmDev2->GetQuality(); + m_shades = d3drmDev2->GetShades(); + m_textureQuality = d3drmDev2->GetTextureQuality(); + m_rendermode = d3drmDev2->GetRenderMode(); + m_dither = d3drmDev2->GetDither(); + m_bufferCount = d3drmDev2->GetBufferCount(); + d3drmDev2->Release(); + } + + if (m_paused) { + return 0; + } + else { + return -1; + } } // FUNCTION: LEGO1 0x1007c930 diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 652ecef2..14acce2a 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -149,6 +149,7 @@ public: void InitFromWindowsDevice(Device*) override; IDirect3DRMDevice2* ImplementationData() const { return m_data; } + void SetImplementationData(IDirect3DRMDevice2* device) { m_data = device; } friend class RendererImpl; @@ -199,6 +200,7 @@ public: ) override; IDirect3DRMViewport* ImplementationData() const { return m_data; } + void SetImplementationData(IDirect3DRMViewport* viewport) { m_data = viewport; } static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*); diff --git a/LEGO1/tgl/d3drm/texture.cpp b/LEGO1/tgl/d3drm/texture.cpp index a51a5c0b..d02b8840 100644 --- a/LEGO1/tgl/d3drm/texture.cpp +++ b/LEGO1/tgl/d3drm/texture.cpp @@ -86,10 +86,46 @@ void TglD3DRMIMAGE::Destroy() delete m_image.palette; } -// STUB: LEGO1 0x100a13e0 +inline static int IsPowerOfTwo(int v) +{ + int m = 0; + + while (v > 2 && m == 0) { + m = v % 2; + v /= 2; + } + + return v == 2 && m == 0; +} + +// FUNCTION: LEGO1 0x100a13e0 Result TglD3DRMIMAGE::CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer) { - return Error; + if (!(IsPowerOfTwo(width) && IsPowerOfTwo(height) && width % 4 == 0)) { + return Error; + } + + m_image.width = width; + m_image.height = height; + m_image.depth = depth; + m_image.bytes_per_line = width; + + if (!m_texelsAllocatedByClient) { + delete[] m_image.buffer1; + m_image.buffer1 = NULL; + } + + if (useBuffer) { + m_texelsAllocatedByClient = 1; + m_image.buffer1 = (char*) pBuffer; + } + else { + m_image.buffer1 = new char[width * height]; + memcpy(m_image.buffer1, pBuffer, width * height); + m_texelsAllocatedByClient = 0; + } + + return Success; } // FUNCTION: LEGO1 0x100a1510 diff --git a/LEGO1/tgl/d3drm/view.cpp b/LEGO1/tgl/d3drm/view.cpp index b9fca8e9..3c2ea1d9 100644 --- a/LEGO1/tgl/d3drm/view.cpp +++ b/LEGO1/tgl/d3drm/view.cpp @@ -80,6 +80,8 @@ inline Result ViewRestoreFrameAfterRender( return result; } +// FIXME: from LEGO1/tgl/d3drm/view.cpp + // FUNCTION: LEGO1 0x100a1240 void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg) {