From 2233da39d8374f34b5eb965c530950e7b20cec97 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 28 Aug 2023 05:49:15 -0400 Subject: [PATCH] Implement/match MxDisplaySurface::Create (#115) --- LEGO1/mxdisplaysurface.cpp | 102 +++++++++++++++++++++++++++++++++++-- LEGO1/mxdisplaysurface.h | 2 +- LEGO1/mxomni.h | 3 +- LEGO1/mxrect32.h | 10 ++-- LEGO1/mxvideoparam.h | 6 ++- 5 files changed, 112 insertions(+), 11 deletions(-) diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index edf1cb1a..4f02aeb6 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -1,4 +1,5 @@ #include "mxdisplaysurface.h" +#include "mxomni.h" DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); @@ -45,10 +46,105 @@ MxResult MxDisplaySurface::Init(MxVideoParam &p_videoParam, LPDIRECTDRAWSURFACE return result; } -// OFFSET: LEGO1 0x100ba7f0 STUB -MxResult MxDisplaySurface::Create(MxVideoParam *p_videoParam) +// OFFSET: LEGO1 0x100ba7f0 +MxResult MxDisplaySurface::Create(MxVideoParam &p_videoParam) { - return 0; + DDSURFACEDESC ddsd; + MxResult result = FAILURE; + LPDIRECTDRAW lpDirectDraw = MVideoManager()->GetDirectDraw(); + HWND hWnd = MxOmni::GetInstance()->GetWindowHandle(); + + this->m_initialized = TRUE; + this->m_videoParam = p_videoParam; + + if (!this->m_videoParam.flags().GetFullScreen()) + this->m_videoParam.flags().SetFlipSurfaces(FALSE); + + if (!this->m_videoParam.flags().GetFlipSurfaces()) { + this->m_videoParam.SetBackBuffers(1); + } + else { + MxU32 backBuffers = this->m_videoParam.GetBackBuffers(); + + if (backBuffers < 1) + this->m_videoParam.SetBackBuffers(1); + else if (backBuffers > 2) + this->m_videoParam.SetBackBuffers(2); + + this->m_videoParam.flags().SetBackBuffers(TRUE); + } + + if (this->m_videoParam.flags().GetFullScreen()) { + MxS32 width = this->m_videoParam.GetRect().m_right - this->m_videoParam.GetRect().m_left + 1; + MxS32 height = this->m_videoParam.GetRect().m_bottom - this->m_videoParam.GetRect().m_top + 1; + + if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)) + goto done; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (lpDirectDraw->GetDisplayMode(&ddsd)) + goto done; + + MxS32 bitdepth = !this->m_videoParam.flags().Get16Bit() ? 8 : 16; + + if (ddsd.dwWidth != width || ddsd.dwHeight != height || ddsd.ddpfPixelFormat.dwRGBBitCount != bitdepth) { + if (lpDirectDraw->SetDisplayMode(width, height, bitdepth)) + goto done; + } + } + + if (this->m_videoParam.flags().GetFlipSurfaces()) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwBackBufferCount = this->m_videoParam.GetBackBuffers(); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) + goto done; + + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + + if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2)) + goto done; + } + else { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) + goto done; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; + ddsd.dwWidth = this->m_videoParam.GetRect().m_right - this->m_videoParam.GetRect().m_left + 1; + ddsd.dwHeight = this->m_videoParam.GetRect().m_bottom - this->m_videoParam.GetRect().m_top + 1; + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN; + + if (!this->m_videoParam.flags().GetBackBuffers()) + ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL)) + goto done; + } + + memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); + this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); + + if (!this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { + if (!lpDirectDraw->CreateClipper(0, &this->m_ddClipper, NULL) && + !this->m_ddClipper->SetHWnd(0, hWnd) && + !this->m_ddSurface1->SetClipper(this->m_ddClipper)) + result = SUCCESS; + } + +done: + return result; } // OFFSET: LEGO1 0x100baa90 diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index aef3d5d5..c76266d7 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -20,7 +20,7 @@ class MxDisplaySurface : public MxCore void Reset(); virtual MxResult Init(MxVideoParam &p_videoParam, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper); - virtual MxResult Create(MxVideoParam *p_videoParam); + virtual MxResult Create(MxVideoParam &p_videoParam); virtual void Clear(); virtual void SetPalette(MxPalette *p_palette); virtual void vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index fb0a9f3e..bbaf4cb0 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -38,6 +38,7 @@ class MxOmni : public MxCore virtual MxResult Create(MxOmniCreateParam &p); // vtable+18 virtual void Destroy(); // vtable+1c static void SetInstance(MxOmni* instance); + HWND GetWindowHandle() const { return this->m_windowHandle; } MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; } MxNotificationManager* GetNotificationManager() const { return this->m_notificationManager; } MxTickleManager* GetTickleManager() const { return this->m_tickleManager; } @@ -53,7 +54,7 @@ class MxOmni : public MxCore static MxOmni* g_instance; MxString m_mediaPath; // 0x8 - HWND *m_windowHandle; // 0x18; + HWND m_windowHandle; // 0x18; MxObjectFactory *m_objectFactory; // 0x1C MxVariableTable* m_variableTable; //0x20 MxTickleManager* m_tickleManager; //0x24 diff --git a/LEGO1/mxrect32.h b/LEGO1/mxrect32.h index 8ba5f6d6..53b5b1eb 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/mxrect32.h @@ -5,7 +5,7 @@ class MxRect32 { public: MxRect32() { } - MxRect32(int p_left, int p_top, int p_right, int p_bottom) + MxRect32(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) { this->m_left = p_left; this->m_top = p_top; @@ -13,10 +13,10 @@ class MxRect32 this->m_bottom = p_bottom; } - int m_left; - int m_top; - int m_right; - int m_bottom; + MxS32 m_left; + MxS32 m_top; + MxS32 m_right; + MxS32 m_bottom; }; #endif // MXRECT32_H diff --git a/LEGO1/mxvideoparam.h b/LEGO1/mxvideoparam.h index 2376e5db..ba18579d 100644 --- a/LEGO1/mxvideoparam.h +++ b/LEGO1/mxvideoparam.h @@ -24,12 +24,16 @@ class MxVideoParam inline MxVideoParamFlags &flags() { return m_flags; } inline void SetPalette(MxPalette *p_palette) { this->m_palette = p_palette; } + inline void SetBackBuffers(MxU32 p_backBuffers) { this->m_backBuffers = p_backBuffers; } + + inline MxRect32 &GetRect() { return this->m_rect; } inline MxPalette *GetPalette() { return this->m_palette; } + inline MxU32 GetBackBuffers() { return this->m_backBuffers; } private: MxRect32 m_rect; MxPalette *m_palette; - unsigned int m_backBuffers; + MxU32 m_backBuffers; MxVideoParamFlags m_flags; int m_unk1c; char *m_deviceId;