From 51fc69e49facc67ec74127d4214356d4627e7769 Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:12:10 -0400 Subject: [PATCH 01/14] Various DirectDraw items (#1411) --- LEGO1/mxdirectx/mxdirect3d.cpp | 104 ++++++++++++++---------- LEGO1/mxdirectx/mxdirect3d.h | 26 ++++-- LEGO1/mxdirectx/mxdirectdraw.cpp | 132 +++++++++++++++++++++---------- LEGO1/mxdirectx/mxdirectdraw.h | 14 +++- LEGO1/mxdirectx/mxdirectxinfo.h | 1 + 5 files changed, 184 insertions(+), 93 deletions(-) diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index fbdb14e4..028b7ced 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -12,21 +12,24 @@ DECOMP_SIZE_ASSERT(MxDirect3D, 0x894) } // FUNCTION: LEGO1 0x1009b0a0 +// FUNCTION: BETA10 0x1011b220 MxDirect3D::MxDirect3D() { - this->m_pDirect3d = NULL; - this->m_pDirect3dDevice = NULL; - this->m_bTexturesDisabled = FALSE; - this->m_assignedDevice = NULL; + m_pDirect3d = NULL; + m_pDirect3dDevice = NULL; + m_bTexturesDisabled = FALSE; + m_currentDeviceInfo = NULL; } // FUNCTION: LEGO1 0x1009b140 +// FUNCTION: BETA10 0x1011b2c3 MxDirect3D::~MxDirect3D() { Destroy(); } // FUNCTION: LEGO1 0x1009b1a0 +// FUNCTION: BETA10 0x1011b333 BOOL MxDirect3D::Create( HWND hWnd, BOOL fullscreen_1, @@ -40,22 +43,33 @@ BOOL MxDirect3D::Create( ) { BOOL success = FALSE; - BOOL ret = MxDirectDraw::Create( - hWnd, - fullscreen_1, - surface_fullscreen, - onlySystemMemory, - width, - height, - bpp, - pPaletteEntries, - paletteEntryCount - ); + assert(m_currentDeviceInfo); - if (ret && D3DCreate() && D3DSetMode()) { - success = TRUE; + if (!MxDirectDraw::Create( + hWnd, + fullscreen_1, + surface_fullscreen, + onlySystemMemory, + width, + height, + bpp, + pPaletteEntries, + paletteEntryCount + )) { + goto done; } + if (!D3DCreate()) { + goto done; + } + + if (!D3DSetMode()) { + goto done; + } + + success = TRUE; + +done: if (!success) { FUN_1009d920(); } @@ -64,24 +78,26 @@ BOOL MxDirect3D::Create( } // FUNCTION: LEGO1 0x1009b210 +// FUNCTION: BETA10 0x1011b41d void MxDirect3D::Destroy() { RELEASE(m_pDirect3dDevice); RELEASE(m_pDirect3d); - if (this->m_assignedDevice) { - delete m_assignedDevice; - this->m_assignedDevice = NULL; + if (m_currentDeviceInfo) { + delete m_currentDeviceInfo; + m_currentDeviceInfo = NULL; } - if (m_pCurrentDeviceModesList) { - m_pCurrentDeviceModesList = NULL; + if (m_currentDevInfo) { + m_currentDevInfo = NULL; } MxDirectDraw::Destroy(); } // FUNCTION: LEGO1 0x1009b290 +// FUNCTION: BETA10 0x1011b50a void MxDirect3D::DestroyButNotDirectDraw() { RELEASE(m_pDirect3dDevice); @@ -90,6 +106,7 @@ void MxDirect3D::DestroyButNotDirectDraw() } // FUNCTION: LEGO1 0x1009b2d0 +// FUNCTION: BETA10 0x1011b592 BOOL MxDirect3D::D3DCreate() { HRESULT result; @@ -103,46 +120,50 @@ BOOL MxDirect3D::D3DCreate() } // FUNCTION: LEGO1 0x1009b310 +// FUNCTION: BETA10 0x1011b617 BOOL MxDirect3D::D3DSetMode() { - if (m_assignedDevice->m_flags & MxAssignedDevice::c_hardwareMode) { + assert(m_currentDeviceInfo); + + if (m_currentDeviceInfo->m_flags & MxAssignedDevice::c_hardwareMode) { if (m_bOnlySoftRender) { Error("Failed to place vital surfaces in video memory for hardware driver", DDERR_GENERIC); return FALSE; } - if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + if (m_currentDeviceInfo->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { m_bTexturesDisabled = FALSE; } else { m_bTexturesDisabled = TRUE; } - if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_assignedDevice))) { + if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_currentDeviceInfo))) { return FALSE; } } else { - if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + if (m_currentDeviceInfo->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { m_bTexturesDisabled = FALSE; } else { m_bTexturesDisabled = TRUE; } - if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_assignedDevice))) { + if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_currentDeviceInfo))) { return FALSE; } } - HRESULT result = m_pDirect3d->CreateDevice(m_assignedDevice->m_guid, m_pBackBuffer, &m_pDirect3dDevice); + LPDIRECTDRAWSURFACE backBuf = BackBuffer(); + HRESULT result = m_pDirect3d->CreateDevice(m_currentDeviceInfo->m_guid, backBuf, &m_pDirect3dDevice); if (result != DD_OK) { Error("Create D3D device failed", result); return FALSE; } - DeviceModesInfo::Mode mode = m_currentMode; + DeviceModesInfo::Mode mode = *CurrentMode(); if (IsFullScreen()) { if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { @@ -151,8 +172,8 @@ BOOL MxDirect3D::D3DSetMode() } } - LPDIRECTDRAWSURFACE frontBuffer = m_pFrontBuffer; - LPDIRECTDRAWSURFACE backBuffer = m_pBackBuffer; + LPDIRECTDRAWSURFACE frontBuffer = FrontBuffer(); + LPDIRECTDRAWSURFACE backBuffer = BackBuffer(); DDSURFACEDESC desc; memset(&desc, 0, sizeof(desc)); @@ -161,7 +182,7 @@ BOOL MxDirect3D::D3DSetMode() if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { unsigned char* surface = (unsigned char*) desc.lpSurface; - for (int i = mode.height; i > 0; i--) { + for (int i = 0; i < mode.height; i++) { memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); surface += desc.lPitch; } @@ -172,14 +193,14 @@ BOOL MxDirect3D::D3DSetMode() OutputDebugString("MxDirect3D::D3DSetMode() back lock failed\n"); } - if (m_bFullScreen) { + if (IsFullScreen()) { memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { unsigned char* surface = (unsigned char*) desc.lpSurface; - for (int i = mode.height; i > 0; i--) { + for (int i = 0; i < mode.height; i++) { memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); surface += desc.lPitch; } @@ -195,6 +216,7 @@ BOOL MxDirect3D::D3DSetMode() } // FUNCTION: LEGO1 0x1009b5a0 +// FUNCTION: BETA10 0x1011babb int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice) { int depth; @@ -230,10 +252,10 @@ int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice) // FUNCTION: BETA10 0x1011bbca BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device) { - if (m_assignedDevice) { - delete m_assignedDevice; - m_assignedDevice = NULL; - m_pCurrentDeviceModesList = NULL; + if (m_currentDeviceInfo) { + delete m_currentDeviceInfo; + m_currentDeviceInfo = NULL; + m_currentDevInfo = NULL; } MxAssignedDevice* d = new MxAssignedDevice; @@ -287,15 +309,15 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri d->m_desc = device.m_HELDesc; } - m_assignedDevice = d; - m_pCurrentDeviceModesList = d->m_deviceInfo; + m_currentDeviceInfo = d; + m_currentDevInfo = d->m_deviceInfo; break; } } } } - if (!m_assignedDevice) { + if (!m_currentDeviceInfo) { delete d; return FALSE; } diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index 04621791..f37c2c17 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -9,6 +9,7 @@ #include <d3d.h> // VTABLE: LEGO1 0x100db800 +// VTABLE: BETA10 0x101c1af8 // SIZE 0x894 class MxDirect3D : public MxDirectDraw { public: @@ -29,9 +30,13 @@ public: void Destroy() override; // vtable+0x08 void DestroyButNotDirectDraw() override; // vtable+0x0c - MxAssignedDevice* AssignedDevice() { return this->m_assignedDevice; } - IDirect3D2* Direct3D() { return this->m_pDirect3d; } - IDirect3DDevice2* Direct3DDevice() { return this->m_pDirect3dDevice; } + MxAssignedDevice* AssignedDevice() { return m_currentDeviceInfo; } + + // FUNCTION: BETA10 0x100d8b40 + IDirect3D2* Direct3D() { return m_pDirect3d; } + + // FUNCTION: BETA10 0x100d8b70 + IDirect3DDevice2* Direct3DDevice() { return m_pDirect3dDevice; } BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device); @@ -42,14 +47,19 @@ protected: int ZBufferDepth(MxAssignedDevice* p_assignedDevice); // SYNTHETIC: LEGO1 0x1009b120 + // SYNTHETIC: BETA10 0x1011c0f0 // MxDirect3D::`scalar deleting destructor' private: - MxAssignedDevice* m_assignedDevice; // 0x880 - IDirect3D2* m_pDirect3d; // 0x884 - IDirect3DDevice2* m_pDirect3dDevice; // 0x888 - BOOL m_bTexturesDisabled; // 0x88c - undefined4 m_unk0x890; // 0x890 + MxAssignedDevice* m_currentDeviceInfo; // 0x880 + IDirect3D2* m_pDirect3d; // 0x884 + IDirect3DDevice2* m_pDirect3dDevice; // 0x888 + BOOL m_bTexturesDisabled; // 0x88c + undefined4 m_unk0x890; // 0x890 }; +// GLOBAL: LEGO1 0x100dd1b0 +// GLOBAL: BETA10 0x101c2de8 +// IID_IDirect3D2 + #endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectx/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp index b6279636..50628293 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -2,6 +2,8 @@ #include "decomp.h" +#include <assert.h> + DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880) #define RELEASE(x) \ @@ -15,9 +17,11 @@ DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880) #endif // GLOBAL: LEGO1 0x10100c68 +// GLOBAL: BETA10 0x101ff1c4 BOOL g_isPaletteIndexed8 = 0; // FUNCTION: LEGO1 0x1009d490 +// FUNCTION: BETA10 0x1012036a MxDirectDraw::MxDirectDraw() { m_pFrontBuffer = NULL; @@ -26,6 +30,7 @@ MxDirectDraw::MxDirectDraw() m_pClipper = NULL; m_pPalette = NULL; m_pDirectDraw = NULL; + m_bIsOnPrimaryDevice = TRUE; m_pText1Surface = NULL; m_pText2Surface = NULL; m_hWndMain = NULL; @@ -39,32 +44,31 @@ MxDirectDraw::MxDirectDraw() m_pFatalErrorHandler = NULL; m_pErrorHandlerArg = NULL; m_pFatalErrorHandlerArg = NULL; - m_pCurrentDeviceModesList = NULL; - m_bIsOnPrimaryDevice = TRUE; + m_currentDevInfo = NULL; m_hFont = NULL; } // FUNCTION: LEGO1 0x1009d530 +// FUNCTION: BETA10 0x1012048f MxDirectDraw::~MxDirectDraw() { Destroy(); - if (m_pCurrentDeviceModesList != NULL) { - delete m_pCurrentDeviceModesList; - m_pCurrentDeviceModesList = NULL; + if (m_currentDevInfo != NULL) { + delete m_currentDevInfo; + m_currentDevInfo = NULL; } } // FUNCTION: LEGO1 0x1009d570 +// FUNCTION: BETA10 0x101204fe int MxDirectDraw::GetPrimaryBitDepth() { - DWORD dwRGBBitCount; + DWORD dwRGBBitCount = 8; LPDIRECTDRAW pDDraw; DDSURFACEDESC ddsd; - HRESULT result = DirectDrawCreate(NULL, &pDDraw, NULL); - dwRGBBitCount = 8; - if (!result) { + if (!DirectDrawCreate(NULL, &pDDraw, NULL)) { memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); @@ -78,6 +82,7 @@ int MxDirectDraw::GetPrimaryBitDepth() } // FUNCTION: LEGO1 0x1009d5e0 +// FUNCTION: BETA10 0x1012058c BOOL MxDirectDraw::Create( HWND hWnd, BOOL fullscreen, @@ -90,17 +95,19 @@ BOOL MxDirectDraw::Create( int paletteEntryCount ) { + assert(m_currentDevInfo); + m_hWndMain = hWnd; CacheOriginalPaletteEntries(); - if (!RecreateDirectDraw(&m_pCurrentDeviceModesList->m_guid)) { + if (!RecreateDirectDraw(&m_currentDevInfo->m_guid)) { return FALSE; } m_bFlipSurfaces = surface_fullscreen; m_bOnlySystemMemory = onlySystemMemory; - m_bIsOnPrimaryDevice = !m_pCurrentDeviceModesList->m_guid; + m_bIsOnPrimaryDevice = m_currentDevInfo->m_guid ? FALSE : TRUE; if (!m_bIsOnPrimaryDevice) { fullscreen = TRUE; @@ -122,6 +129,7 @@ BOOL MxDirectDraw::Create( } // FUNCTION: LEGO1 0x1009d690 +// FUNCTION: BETA10 0x101206ca BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID) { RELEASE(m_pDirectDraw); @@ -129,6 +137,7 @@ BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID) } // FUNCTION: LEGO1 0x1009d6c0 +// FUNCTION: BETA10 0x10120733 BOOL MxDirectDraw::CacheOriginalPaletteEntries() { HDC hdc; @@ -142,11 +151,9 @@ BOOL MxDirectDraw::CacheOriginalPaletteEntries() } // FUNCTION: LEGO1 0x1009d700 +// FUNCTION: BETA10 0x1012078c BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen) { - int reservedLowEntryCount = 10; - int reservedHighEntryCount = 10; - int arraySize = sizeOfArray(m_paletteEntries); HDC hdc; int i; @@ -156,24 +163,26 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa ReleaseDC(NULL, hdc); } - for (i = 0; i < reservedLowEntryCount; i++) { + for (i = 0; i < 10; i++) { m_paletteEntries[i].peFlags = 0x80; } - for (i = reservedLowEntryCount; i < 142; i++) { + for (; i < 142; i++) { m_paletteEntries[i].peFlags = 0x44; } - for (i = 142; i < arraySize - reservedHighEntryCount; i++) { + for (; i < 246; i++) { m_paletteEntries[i].peFlags = 0x84; } - for (i = 256 - reservedHighEntryCount; i < 256; i++) { + for (; i < 256; i++) { m_paletteEntries[i].peFlags = 0x80; } if (paletteEntryCount != 0) { - for (i = reservedLowEntryCount; (i < paletteEntryCount) && (i < 256 - reservedHighEntryCount); i++) { + assert(paletteEntryCount <= (sizeof(m_paletteEntries) / sizeof(m_paletteEntries[0]))); + + for (i = 10; (i < paletteEntryCount) && (i < 246); i++) { m_paletteEntries[i].peRed = pPaletteEntries[i].peRed; m_paletteEntries[i].peGreen = pPaletteEntries[i].peGreen; m_paletteEntries[i].peBlue = pPaletteEntries[i].peBlue; @@ -194,6 +203,7 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa } // FUNCTION: LEGO1 0x1009d800 +// FUNCTION: BETA10 0x10120971 void MxDirectDraw::Destroy() { DestroyButNotDirectDraw(); @@ -204,13 +214,14 @@ void MxDirectDraw::Destroy() m_bIsOnPrimaryDevice = TRUE; - if (m_pCurrentDeviceModesList != NULL) { - delete m_pCurrentDeviceModesList; - m_pCurrentDeviceModesList = NULL; + if (m_currentDevInfo != NULL) { + delete m_currentDevInfo; + m_currentDevInfo = NULL; } } // FUNCTION: LEGO1 0x1009d860 +// FUNCTION: BETA10 0x10120a18 void MxDirectDraw::DestroyButNotDirectDraw() { RestoreOriginalPaletteEntries(); @@ -232,6 +243,7 @@ void MxDirectDraw::DestroyButNotDirectDraw() } // FUNCTION: LEGO1 0x1009d920 +// FUNCTION: BETA10 0x10120b9e void MxDirectDraw::FUN_1009d920() { RestoreOriginalPaletteEntries(); @@ -244,8 +256,11 @@ void MxDirectDraw::FUN_1009d920() } // FUNCTION: LEGO1 0x1009d960 +// FUNCTION: BETA10 0x10120d61 BOOL MxDirectDraw::DDInit(BOOL fullscreen) { + assert(m_pDirectDraw); + HRESULT result; if (fullscreen) { @@ -268,12 +283,15 @@ BOOL MxDirectDraw::DDInit(BOOL fullscreen) } // FUNCTION: LEGO1 0x1009d9d0 +// FUNCTION: BETA10 0x10120e45 BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp) { DeviceModesInfo::Mode mode = {width, height, bpp}; - for (int i = 0; i < m_pCurrentDeviceModesList->m_count; i++) { - if (m_pCurrentDeviceModesList->m_modeArray[i] == mode) { + assert(m_currentDevInfo); + + for (int i = 0; i < m_currentDevInfo->m_count; i++) { + if (m_currentDevInfo->m_modeArray[i] == mode) { return TRUE; } } @@ -282,6 +300,7 @@ BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp) } // FUNCTION: LEGO1 0x1009da20 +// FUNCTION: BETA10 0x10120efb void EnableResizing(HWND p_hwnd, BOOL p_flag) { static DWORD g_dwStyle; @@ -298,17 +317,17 @@ void EnableResizing(HWND p_hwnd, BOOL p_flag) } // FUNCTION: LEGO1 0x1009da80 +// FUNCTION: BETA10 0x10120f68 BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) { HRESULT result; if (m_bFullScreen) { - LPDIRECTDRAW lpDD; - EnableResizing(m_hWndMain, FALSE); +#ifndef BETA10 if (!m_bIsOnPrimaryDevice) { - lpDD = NULL; + LPDIRECTDRAW lpDD = NULL; result = DirectDrawCreate(0, &lpDD, 0); if (result == DD_OK) { result = lpDD->SetCooperativeLevel(m_hWndMain, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT); @@ -317,11 +336,12 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) } } } +#endif if (!IsSupportedMode(width, height, bpp)) { - width = m_pCurrentDeviceModesList->m_modeArray[0].width; - height = m_pCurrentDeviceModesList->m_modeArray[0].height; - bpp = m_pCurrentDeviceModesList->m_modeArray[0].bitsPerPixel; + width = m_currentDevInfo->m_modeArray[0].width; + height = m_currentDevInfo->m_modeArray[0].height; + bpp = m_currentDevInfo->m_modeArray[0].bitsPerPixel; } m_bIgnoreWMSIZE = TRUE; @@ -412,20 +432,29 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) } // create debug text only in windowed mode? - return m_bFullScreen || CreateTextSurfaces(); + if (!m_bFullScreen) { + if (!CreateTextSurfaces()) { + return FALSE; + } + } + + return TRUE; } // FUNCTION: LEGO1 0x1009dd80 +// FUNCTION: BETA10 0x1012137f HRESULT MxDirectDraw::CreateDDSurface( LPDDSURFACEDESC p_lpDDSurfDesc, LPDIRECTDRAWSURFACE FAR* p_lpDDSurface, IUnknown FAR* p_pUnkOuter ) { - return m_pDirectDraw->CreateSurface(p_lpDDSurfDesc, p_lpDDSurface, p_pUnkOuter); + HRESULT res = m_pDirectDraw->CreateSurface(p_lpDDSurfDesc, p_lpDDSurface, p_pUnkOuter); + return res; } // FUNCTION: LEGO1 0x1009dda0 +// FUNCTION: BETA10 0x101213bb BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf) { HRESULT result; @@ -441,6 +470,7 @@ BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSU } // FUNCTION: LEGO1 0x1009ddf0 +// FUNCTION: BETA10 0x10121430 BOOL MxDirectDraw::DDCreateSurfaces() { HRESULT result; @@ -518,13 +548,14 @@ BOOL MxDirectDraw::DDCreateSurfaces() } // FUNCTION: LEGO1 0x1009e020 +// FUNCTION: BETA10 0x10121700 void MxDirectDraw::FUN_1009e020() { HRESULT result; byte* line; DDSURFACEDESC ddsd; - int j; int count = m_bFlipSurfaces ? 2 : 1; + int value = 0; for (int i = 0; i < count; i++) { memset(&ddsd, 0, sizeof(ddsd)); @@ -543,8 +574,8 @@ void MxDirectDraw::FUN_1009e020() // clear backBuffer line = (byte*) ddsd.lpSurface; - for (j = ddsd.dwHeight; j--;) { - memset(line, 0, ddsd.dwWidth); + for (int j = ddsd.dwHeight; j--;) { + memset(line, value, ddsd.dwWidth); line += ddsd.lPitch; } @@ -557,6 +588,7 @@ void MxDirectDraw::FUN_1009e020() } // FUNCTION: LEGO1 0x1009e110 +// FUNCTION: BETA10 0x101219de BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface) { HRESULT result; @@ -589,18 +621,21 @@ BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurf } // FUNCTION: LEGO1 0x1009e210 +// FUNCTION: BETA10 0x10121aea BOOL MxDirectDraw::TextToTextSurface1(const char* text) { return TextToTextSurface(text, m_pText1Surface, m_text1SizeOnSurface); } // FUNCTION: LEGO1 0x1009e230 +// FUNCTION: BETA10 0x10121b1e BOOL MxDirectDraw::TextToTextSurface2(const char* text) { return TextToTextSurface(text, m_pText2Surface, m_text2SizeOnSurface); } // FUNCTION: LEGO1 0x1009e250 +// FUNCTION: BETA10 0x10121b52 BOOL MxDirectDraw::CreateTextSurfaces() { HRESULT result; @@ -680,6 +715,7 @@ BOOL MxDirectDraw::CreateTextSurfaces() } // FUNCTION: LEGO1 0x1009e4d0 +// FUNCTION: BETA10 0x10121e87 BOOL MxDirectDraw::RestoreSurfaces() { HRESULT result; @@ -738,6 +774,7 @@ BOOL MxDirectDraw::RestoreSurfaces() } // FUNCTION: LEGO1 0x1009e5e0 +// FUNCTION: BETA10 0x10122087 BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) { HRESULT result; // eax @@ -769,6 +806,7 @@ BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) } // FUNCTION: LEGO1 0x1009e6a0 +// FUNCTION: BETA10 0x10122166 int MxDirectDraw::Pause(BOOL p_pause) { if (p_pause) { @@ -811,6 +849,7 @@ int MxDirectDraw::Pause(BOOL p_pause) } // FUNCTION: LEGO1 0x1009e750 +// FUNCTION: BETA10 0x101223c9 BOOL MxDirectDraw::RestorePaletteEntries() { @@ -831,6 +870,7 @@ BOOL MxDirectDraw::RestorePaletteEntries() } // FUNCTION: LEGO1 0x1009e7a0 +// FUNCTION: BETA10 0x10122458 BOOL MxDirectDraw::RestoreOriginalPaletteEntries() { if (m_bPrimaryPalettized) { @@ -854,6 +894,7 @@ BOOL MxDirectDraw::RestoreOriginalPaletteEntries() } // FUNCTION: LEGO1 0x1009e7f0 +// FUNCTION: BETA10 0x101224d9 int MxDirectDraw::FlipToGDISurface() { @@ -871,22 +912,27 @@ int MxDirectDraw::FlipToGDISurface() } // FUNCTION: LEGO1 0x1009e830 +// FUNCTION: BETA10 0x101225b9 void MxDirectDraw::Error(const char* p_message, int p_error) { - // at LEGO1 0x10100c70, needs no annotation + // ~GLOBAL: LEGO1 0x10100c70 + // ~GLOBAL: BETA10 0x101ff1cc static BOOL g_isInsideError = FALSE; - if (!g_isInsideError) { - g_isInsideError = TRUE; - Destroy(); - if (m_pErrorHandler) { - m_pErrorHandler(p_message, p_error, m_pErrorHandlerArg); - } - g_isInsideError = FALSE; + if (g_isInsideError) { + return; } + + g_isInsideError = TRUE; + Destroy(); + if (m_pErrorHandler) { + m_pErrorHandler(p_message, p_error, m_pErrorHandlerArg); + } + g_isInsideError = FALSE; } // FUNCTION: LEGO1 0x1009e880 +// FUNCTION: BETA10 0x10122630 const char* MxDirectDraw::ErrorToString(HRESULT p_error) { switch (p_error) { diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h index 975204a7..75b0f965 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.h +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -7,6 +7,7 @@ #include <windows.h> // VTABLE: LEGO1 0x100db818 +// VTABLE: BETA10 0x101c1b10 // SIZE 0x880 class MxDirectDraw { public: @@ -32,10 +33,20 @@ public: virtual void DestroyButNotDirectDraw(); // vtable+0x0c IDirectDraw* DirectDraw() { return m_pDirectDraw; } + + // FUNCTION: BETA10 0x100d8ab0 IDirectDrawSurface* FrontBuffer() { return m_pFrontBuffer; } + + // FUNCTION: BETA10 0x100d8ae0 IDirectDrawSurface* BackBuffer() { return m_pBackBuffer; } + + // FUNCTION: BETA10 0x100d8b10 IDirectDrawClipper* Clipper() { return m_pClipper; } + // FUNCTION: BETA10 0x1011c190 + DeviceModesInfo::Mode* CurrentMode() { return &m_currentMode; } + + // FUNCTION: BETA10 0x1011c170 BOOL IsFullScreen() { return m_bFullScreen; } BOOL IsSupportedMode(int width, int height, int bpp); @@ -72,6 +83,7 @@ protected: void FUN_1009d920(); // SYNTHETIC: LEGO1 0x1009d510 + // SYNTHETIC: BETA10 0x10122f80 // MxDirectDraw::`scalar deleting destructor' protected: @@ -102,7 +114,7 @@ protected: void* m_pErrorHandlerArg; // 0x864 void* m_pFatalErrorHandlerArg; // 0x868 int m_pauseCount; // 0x86c - DeviceModesInfo* m_pCurrentDeviceModesList; // 0x870 + DeviceModesInfo* m_currentDevInfo; // 0x870 DeviceModesInfo::Mode m_currentMode; // 0x874 }; diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h index 0371b276..ac68af79 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.h +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -10,6 +10,7 @@ struct DeviceModesInfo { // SIZE 0x0c struct Mode { + // FUNCTION: BETA10 0x10122fc0 int operator==(const Mode& p_mode) const { return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel)); From 67c71cb9e6d41d28ca57f845f72569ee0ecc143a Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sat, 15 Mar 2025 14:19:09 -0700 Subject: [PATCH 02/14] Match `MxControlPresenter::HasTickleStatePassed` (#1412) --- LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index 3449423e..39f9be2a 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -296,9 +296,14 @@ void MxControlPresenter::Enable(MxBool p_enable) // FUNCTION: LEGO1 0x100448a0 MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) { - MxCompositePresenterList::iterator it = m_list.begin(); - for (MxS16 i = m_unk0x4e; i > 0; i--, it++) { - } + MxCompositePresenterList::const_iterator it = m_list.begin(); + +#ifdef COMPAT_MODE + advance(it, m_unk0x4e); +#else + // Uses forward iterator logic instead of bidrectional for some reason. + _Advance(it, m_unk0x4e, forward_iterator_tag()); +#endif return (*it)->HasTickleStatePassed(p_tickleState); } From 401fa7674e110fe2b7696735e6442f601d6e880b Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 14:19:11 -0700 Subject: [PATCH 03/14] Match `MxBackgroundAudioManager::FadeInOrFadeOut` (#1413) --- LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 49b4c28d..d89f5cd4 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -163,6 +163,7 @@ void MxBackgroundAudioManager::FUN_1007ef40() } // FUNCTION: LEGO1 0x1007f0e0 +// FUNCTION: BETA10 0x100e8d8d void MxBackgroundAudioManager::FadeInOrFadeOut() { MxS32 volume, compare; @@ -178,12 +179,10 @@ void MxBackgroundAudioManager::FadeInOrFadeOut() } if (volume < compare) { - volume = Min(volume + m_speed, compare); - m_unk0xa0->SetVolume(volume); + m_unk0xa0->SetVolume(volume + m_speed < compare ? volume + m_speed : compare); } else if (compare < volume) { - volume = Max(volume - m_speed, compare); - m_unk0xa0->SetVolume(volume); + m_unk0xa0->SetVolume(volume - m_speed > compare ? volume - m_speed : compare); } else { m_unk0xa0->SetVolume(volume); From e9467864d867f989d531c33f1adab4f61caa9040 Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 14:57:23 -0700 Subject: [PATCH 04/14] Match `LegoHideAnimPresenter::FUN_1006db60` (#1414) * Match `LegoHideAnimPresenter::FUN_1006db60` * Remove comment --- .../lego/legoomni/src/video/legohideanimpresenter.cpp | 3 +-- LEGO1/lego/sources/anim/legoanim.h | 3 +++ LEGO1/lego/sources/geom/legowegedge.h | 11 ++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp index 0aef42bd..64a06a08 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -118,8 +118,7 @@ void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time) if (boundary != NULL) { newB = data->FUN_100a0990(p_time); - boundary->GetFlag0x10(); - // TODO: Match + previousB = boundary->GetFlag0x10(); boundary->SetFlag0x10(newB); } } diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index 00cbafdb..0df350a9 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -189,6 +189,7 @@ public: // FUNCTION: BETA10 0x1005abc0 LegoU16 GetUnknown0x20() { return m_unk0x20; } + // FUNCTION: BETA10 0x1005d5c0 LegoU16 GetUnknown0x22() { return m_unk0x22; } // FUNCTION: BETA10 0x10073b80 @@ -222,6 +223,8 @@ public: { return CreateLocalTransform((LegoFloat) p_time, p_matrix); } + + // FUNCTION: BETA10 0x1005d580 LegoBool FUN_100a0990(LegoTime p_time) { return FUN_100a0990((LegoFloat) p_time); } inline static void GetTranslation( diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index af32c3ea..7ff23c10 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -45,7 +45,15 @@ public: LegoS32 VTable0x04() override; // vtable+0x04 // FUNCTION: BETA10 0x100270c0 - LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } + LegoU32 GetFlag0x10() + { + if (m_flags & c_bit5) { + return FALSE; + } + else { + return TRUE; + } + } // TODO: Other BETA10 reference at 0x1001c9e0, not sure what is going on // FUNCTION: BETA10 0x1001ff80 @@ -57,6 +65,7 @@ public: // FUNCTION: BETA10 0x1001c9b0 const LegoChar* GetName() { return m_name; } + // FUNCTION: BETA10 0x1005d5f0 void SetFlag0x10(LegoU32 p_disable) { if (p_disable) { From a301f84566f3dbf90c57967239799d9ba8654252 Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 14:58:48 -0700 Subject: [PATCH 05/14] Match `LegoAnimPresenterSetCompare` comparison (#1415) --- LEGO1/lego/legoomni/include/legopathboundary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h index 3499c24d..a2a2d6ba 100644 --- a/LEGO1/lego/legoomni/include/legopathboundary.h +++ b/LEGO1/lego/legoomni/include/legopathboundary.h @@ -21,7 +21,7 @@ struct LegoPathActorSetCompare { }; struct LegoAnimPresenterSetCompare { - MxBool operator()(const LegoAnimPresenter* p_lhs, const LegoAnimPresenter* p_rhs) const + MxU32 operator()(const LegoAnimPresenter* p_lhs, const LegoAnimPresenter* p_rhs) const { return (COMPARE_POINTER_TYPE) p_lhs < (COMPARE_POINTER_TYPE) p_rhs; } From aa6038619657103e5feff83756109ec387cc83d1 Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 14:59:10 -0700 Subject: [PATCH 06/14] Match `MxStreamController::RemoveSubscriber` (#1416) --- LEGO1/omni/src/stream/mxstreamcontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index 958fa371..dadd03ca 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -87,7 +87,7 @@ void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber) // FUNCTION: BETA10 0x1014e7b4 void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) { - m_subscribers.Remove(p_subscriber); + m_subscribers.remove(p_subscriber); } // FUNCTION: LEGO1 0x100c1690 From 1027a80d9e0a6df9e124fff63adccd41d69e452c Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 15:02:13 -0700 Subject: [PATCH 07/14] Match `MxEventPresenter::PutData` (#1417) --- LEGO1/omni/src/event/mxeventpresenter.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/LEGO1/omni/src/event/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp index 05c94de0..f819b68c 100644 --- a/LEGO1/omni/src/event/mxeventpresenter.cpp +++ b/LEGO1/omni/src/event/mxeventpresenter.cpp @@ -8,6 +8,8 @@ #include "mxmisc.h" #include "mxvariabletable.h" +#include <assert.h> + DECOMP_SIZE_ASSERT(MxEventPresenter, 0x54); // FUNCTION: LEGO1 0x100c2b70 @@ -90,6 +92,7 @@ void MxEventPresenter::StartingTickle() } // FUNCTION: LEGO1 0x100c2ef0 +// FUNCTION: BETA10 0x10152d26 MxResult MxEventPresenter::PutData() { AUTOLOCK(m_criticalSection); @@ -102,10 +105,15 @@ MxResult MxEventPresenter::PutData() const char* data = (const char*) m_currentChunk->GetData(); MxVariableTable* variableTable = VariableTable(); - const char* key = data; - const char* value = &data[strlen(data) + 1]; - strlen(value); - variableTable->SetVariable(key, value); + const char* name = data; + assert(name); + data += strlen(data) + 1; + + const char* value = data; + assert(value); + data += strlen(data) + 1; + + variableTable->SetVariable(name, value); } if (m_currentTickleState == e_streaming) { From 6220ab32c3fed5f7ab5f10b437b84a51b24ad2de Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Sun, 16 Mar 2025 15:19:13 -0700 Subject: [PATCH 08/14] Match `FUN_100b7220` (#1418) --- LEGO1/omni/src/common/mxutilities.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/LEGO1/omni/src/common/mxutilities.cpp b/LEGO1/omni/src/common/mxutilities.cpp index 7845d88f..a9f8712e 100644 --- a/LEGO1/omni/src/common/mxutilities.cpp +++ b/LEGO1/omni/src/common/mxutilities.cpp @@ -146,9 +146,20 @@ void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32)) } // FUNCTION: LEGO1 0x100b7220 +// FUNCTION: BETA10 0x10136f37 void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags) { - p_action->SetFlags(!p_setFlags ? p_action->GetFlags() & ~p_newFlags : p_action->GetFlags() | p_newFlags); + MxU32 oldFlags = p_action->GetFlags(); + MxU32 newFlags; + + if (p_setFlags) { + newFlags = oldFlags | p_newFlags; + } + else { + newFlags = oldFlags & ~p_newFlags; + } + + p_action->SetFlags(newFlags); if (p_action->IsA("MxDSMultiAction")) { MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); From 20bcea0c815ec463d2d9e27c7aa80b2540127fce Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Sun, 16 Mar 2025 19:47:06 -0400 Subject: [PATCH 09/14] Fix address for MxRect constructor (#1419) --- LEGO1/omni/include/mxgeometry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/omni/include/mxgeometry.h b/LEGO1/omni/include/mxgeometry.h index 073b5471..99a6e420 100644 --- a/LEGO1/omni/include/mxgeometry.h +++ b/LEGO1/omni/include/mxgeometry.h @@ -369,7 +369,6 @@ public: MxRect32(MxS32 p_l, MxS32 p_t, MxS32 p_r, MxS32 p_b) : MxRect<MxS32>(p_l, p_t, p_r, p_b) {} #ifndef COMPAT_MODE - // FUNCTION: LEGO1 0x100b6fc0 // FUNCTION: BETA10 0x10137060 MxRect32(MxPoint32& p_p, MxSize32& p_s) : MxRect<MxS32>(p_p, p_s) {} #else @@ -406,6 +405,7 @@ public: // TEMPLATE: BETA10 0x10031800 // ??0?$MxRect@H@@QAE@XZ +// TEMPLATE: LEGO1 0x100b6fc0 // TEMPLATE: BETA10 0x10031860 // ??0?$MxRect@H@@QAE@ABV?$MxPoint@H@@ABV?$MxSize@H@@@Z From 466c3452012f91cc8f4d72c9798c83f0c17711cf Mon Sep 17 00:00:00 2001 From: Anonymous Maarten <madebr@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:29:15 +0100 Subject: [PATCH 10/14] cmake: smartheap and libcmt are first in link order (#1420) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63ce08c7..c4681228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,6 +427,7 @@ function(add_lego_libraries NAME) # Link libraries target_link_libraries(${NAME} PRIVATE + ${ARG_LINK_LIBRARIES} dinput misc${ARG_SUFFIX} geom${ARG_SUFFIX} @@ -459,7 +460,7 @@ endfunction() set(lego1_link_libraries ) if (ISLE_USE_SMARTHEAP) - list(APPEND lego1_link_libraries SmartHeap::SmartHeap) + list(APPEND lego1_link_libraries SmartHeap::SmartHeap libcmt) endif() if(ISLE_BUILD_LEGO1) From 8821593b63a1e12d96c7b09893851a097e74e0ce Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:25:40 -0400 Subject: [PATCH 11/14] Improve MxControlPresenter::FUN_10044270 (#1422) --- .../legoomni/include/mxcontrolpresenter.h | 17 ++- .../src/common/mxcontrolpresenter.cpp | 125 +++++++++--------- .../src/control/legocontrolmanager.cpp | 3 +- LEGO1/omni/src/common/mxutilities.cpp | 5 +- 4 files changed, 74 insertions(+), 76 deletions(-) diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 8fcfecc7..8ecfeacf 100644 --- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -5,7 +5,6 @@ #include "mxcompositepresenter.h" class LegoControlManagerNotificationParam; -class MxVideoPresenter; // VTABLE: LEGO1 0x100d7b88 // VTABLE: BETA10 0x101bf5d0 @@ -48,18 +47,18 @@ public: virtual void VTable0x6c(MxS16 p_unk0x4e); // vtable+0x6c MxBool FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter); - MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter); + MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter); MxS16 GetUnknown0x4e() { return m_unk0x4e; } private: - undefined2 m_unk0x4c; // 0x4c - MxS16 m_unk0x4e; // 0x4e - MxBool m_unk0x50; // 0x50 - undefined2 m_unk0x52; // 0x52 - undefined2 m_unk0x54; // 0x54 - undefined2 m_unk0x56; // 0x56 - MxS16* m_unk0x58; // 0x58 + MxS16 m_unk0x4c; // 0x4c + MxS16 m_unk0x4e; // 0x4e + MxBool m_unk0x50; // 0x50 + MxS16 m_unk0x52; // 0x52 + MxS16 m_unk0x54; // 0x54 + MxS16 m_unk0x56; // 0x56 + MxS16* m_states; // 0x58 }; // SYNTHETIC: LEGO1 0x100440f0 diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index 39f9be2a..a90e962b 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -4,10 +4,12 @@ #include "legocontrolmanager.h" #include "mxdsmultiaction.h" #include "mxmisc.h" +#include "mxstillpresenter.h" #include "mxticklemanager.h" #include "mxtimer.h" #include "mxutilities.h" -#include "mxvideopresenter.h" + +#include <assert.h> DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) @@ -18,15 +20,15 @@ MxControlPresenter::MxControlPresenter() m_unk0x4e = -1; m_unk0x50 = FALSE; m_unk0x52 = 0; - m_unk0x58 = 0; + m_states = NULL; m_unk0x54 = 0; } // FUNCTION: LEGO1 0x10044110 MxControlPresenter::~MxControlPresenter() { - if (m_unk0x58) { - delete m_unk0x58; + if (m_states) { + delete m_states; } } @@ -72,46 +74,41 @@ void MxControlPresenter::EndAction() // FUNCTION: LEGO1 0x10044270 // FUNCTION: BETA10 0x100eae68 -MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter) +MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter) { + assert(p_presenter); + MxStillPresenter* presenter = (MxStillPresenter*) p_presenter; + if (m_unk0x4c == 3) { - MxVideoPresenter* frontPresenter = (MxVideoPresenter*) m_list.front(); + MxStillPresenter* map = (MxStillPresenter*) m_list.front(); + assert(map && map->IsA("MxStillPresenter")); - if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < p_presenter->GetDisplayZ()) { - if (p_presenter->VTable0x7c()) { - MxS32 height = frontPresenter->GetHeight(); - MxS32 width = frontPresenter->GetWidth(); + if (presenter == map || map->GetDisplayZ() < presenter->GetDisplayZ()) { + if (presenter->VTable0x7c()) { + MxRect32 rect(0, 0, map->GetWidth() - 1, map->GetHeight() - 1); + rect += map->GetLocation(); - if (frontPresenter->GetLocation().GetX() <= p_x && - p_x < width - 1 + frontPresenter->GetLocation().GetX() && - frontPresenter->GetLocation().GetY() <= p_y && - p_y < height - 1 + frontPresenter->GetLocation().GetY()) { - MxU8* start; - - if (frontPresenter->GetAlphaMask() == NULL) { - start = frontPresenter->GetBitmap()->GetStart( - p_x - frontPresenter->GetLocation().GetX(), - p_y - frontPresenter->GetLocation().GetY() - ); - } - else { - start = NULL; - } + if (rect.GetLeft() <= p_x && p_x < rect.GetRight() && rect.GetTop() <= p_y && p_y < rect.GetBottom()) { + // DECOMP: Beta uses GetBitmapStart() here, but that causes more diffs for retail. + MxU8* start = map->GetAlphaMask() + ? NULL + : map->GetBitmap()->GetStart(p_x - rect.GetLeft(), p_y - rect.GetTop()); m_unk0x56 = 0; - if (m_unk0x58 == NULL) { - if (*start != 0) { - m_unk0x56 = 1; - } - } - else { - for (MxS16 i = 1; i <= *m_unk0x58; i++) { - if (m_unk0x58[i] == *start) { + if (m_states) { + for (MxS16 i = 1; i <= *m_states; i++) { + // TODO: Can we match without the cast here? + if (m_states[i] == (MxS16) *start) { m_unk0x56 = i; break; } } } + else { + if (*start != 0) { + m_unk0x56 = 1; + } + } if (m_unk0x56) { return TRUE; @@ -121,29 +118,18 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* } } else { - if (ContainsPresenter(m_list, p_presenter)) { + if (ContainsPresenter(m_list, presenter)) { if (m_unk0x4c == 2) { - MxS32 width = p_presenter->GetWidth(); - MxS32 height = p_presenter->GetHeight(); + MxS32 width = presenter->GetWidth(); + MxS32 height = presenter->GetHeight(); if (m_unk0x52 == 2 && m_unk0x54 == 2) { - MxS16 val; - if (p_x < p_presenter->GetLocation().GetX() + width / 2) { - val = 3; - if (p_y < p_presenter->GetLocation().GetY() + height / 2) { - val = 1; - } - m_unk0x56 = val; - return TRUE; + if (p_x < presenter->GetX() + width / 2) { + m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 3 : 1; } - - val = 4; - if (p_y < p_presenter->GetLocation().GetY() + height / 2) { - val = 2; + else { + m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 4 : 2; } - - m_unk0x56 = val; - return TRUE; } } else { @@ -173,7 +159,7 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerNotificationParam* p_p } break; case c_notificationButtonDown: - if (FUN_10044270(p_param->GetX(), p_param->GetY(), (MxVideoPresenter*) p_presenter)) { + if (FUN_10044270(p_param->GetX(), p_param->GetY(), p_presenter)) { p_param->SetClickedObjectId(m_action->GetObjectId()); p_param->SetClickedAtom(m_action->GetAtomId().GetInternal()); VTable0x6c(m_unk0x56); @@ -221,6 +207,7 @@ void MxControlPresenter::ReadyTickle() } // FUNCTION: LEGO1 0x10044640 +// FUNCTION: BETA10 0x100eb5e3 void MxControlPresenter::ParseExtra() { MxU16 extraLength; @@ -234,27 +221,35 @@ void MxControlPresenter::ParseExtra() char output[256]; if (KeyValueStringParse(output, g_strSTYLE, extraCopy)) { - char* str = strtok(output, g_parseExtraTokens); + char* token = strtok(output, g_parseExtraTokens); - if (!strcmpi(str, g_strTOGGLE)) { + if (!strcmpi(token, g_strTOGGLE)) { m_unk0x4c = 1; } - else if (!strcmpi(str, g_strGRID)) { + else if (!strcmpi(token, g_strGRID)) { m_unk0x4c = 2; - m_unk0x52 = atoi(strtok(NULL, g_parseExtraTokens)); - m_unk0x54 = atoi(strtok(NULL, g_parseExtraTokens)); + token = strtok(NULL, g_parseExtraTokens); + assert(token); + m_unk0x52 = atoi(token); + + token = strtok(NULL, g_parseExtraTokens); + assert(token); + m_unk0x54 = atoi(token); } - else if (!strcmpi(str, g_strMAP)) { + else if (!strcmpi(token, g_strMAP)) { m_unk0x4c = 3; - str = strtok(NULL, g_parseExtraTokens); + token = strtok(NULL, g_parseExtraTokens); - if (str) { - MxS16 count = atoi(str); - m_unk0x58 = new MxS16[count + 1]; - *m_unk0x58 = count; + if (token) { + MxS16 numStates = atoi(token); + m_states = new MxS16[numStates + 1]; + assert(numStates); + *m_states = numStates; - for (MxS16 i = 1; i <= count; i++) { - m_unk0x58[i] = atoi(strtok(NULL, g_parseExtraTokens)); + for (MxS16 i = 1; i <= numStates; i++) { + token = strtok(NULL, g_parseExtraTokens); + assert(token); + m_states[i] = atoi(token); } } } diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index 3a47f2da..8dd094f9 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -144,12 +144,13 @@ void LegoControlManager::FUN_100293c0(MxU32 p_objectId, const char* p_atom, MxS1 } // FUNCTION: LEGO1 0x100294e0 +// FUNCTION: BETA10 0x1007c92f MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y) { if (m_presenterList) { MxPresenterListCursor cursor(m_presenterList); MxPresenter* control; - MxVideoPresenter* presenter = (MxVideoPresenter*) VideoManager()->GetPresenterAt(p_x, p_y); + MxPresenter* presenter = VideoManager()->GetPresenterAt(p_x, p_y); if (presenter) { while (cursor.Next(control)) { diff --git a/LEGO1/omni/src/common/mxutilities.cpp b/LEGO1/omni/src/common/mxutilities.cpp index a9f8712e..365d6b18 100644 --- a/LEGO1/omni/src/common/mxutilities.cpp +++ b/LEGO1/omni/src/common/mxutilities.cpp @@ -81,6 +81,7 @@ void MakeSourceName(char* p_output, const char* p_input) } // FUNCTION: LEGO1 0x100b7050 +// FUNCTION: BETA10 0x10136c19 MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_string) { MxBool didMatch = FALSE; @@ -92,7 +93,8 @@ MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_ assert(string); strcpy(string, p_string); - for (char* token = strtok(string, ", \t\r\n:"); token; token = strtok(NULL, ", \t\r\n:")) { + const char* delim = ", \t\r\n:"; + for (char* token = strtok(string, delim); token; token = strtok(NULL, delim)) { len -= (strlen(token) + 1); if (strcmpi(token, p_command) == 0) { @@ -116,6 +118,7 @@ MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_ } // FUNCTION: LEGO1 0x100b7170 +// FUNCTION: BETA10 0x10136e12 MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter) { for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) { From 3b63506648381a227cdab3e4f2a66fa7e593bb45 Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Thu, 3 Apr 2025 17:10:11 -0400 Subject: [PATCH 12/14] Fix FUN_10044270 (#1423) --- LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index a90e962b..17beb3c1 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -84,7 +84,7 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_pre assert(map && map->IsA("MxStillPresenter")); if (presenter == map || map->GetDisplayZ() < presenter->GetDisplayZ()) { - if (presenter->VTable0x7c()) { + if (map->VTable0x7c()) { MxRect32 rect(0, 0, map->GetWidth() - 1, map->GetHeight() - 1); rect += map->GetLocation(); From 93d6c18c9ab04ec011113aa770b6d8d102fe87a2 Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:18:00 -0400 Subject: [PATCH 13/14] Fix AlphaMask functions (#1425) --- LEGO1/omni/include/mxbitmap.h | 4 +-- LEGO1/omni/src/video/mxvideopresenter.cpp | 43 ++++------------------- 2 files changed, 8 insertions(+), 39 deletions(-) diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h index b671ba64..45821479 100644 --- a/LEGO1/omni/include/mxbitmap.h +++ b/LEGO1/omni/include/mxbitmap.h @@ -115,7 +115,7 @@ public: MxLong GetDataSize() const { return AlignToFourByte(m_bmiHeader->biWidth) * GetBmiHeightAbs(); } // FUNCTION: BETA10 0x1002c4b0 - MxBool IsTopDown() + MxBool IsTopDown() const { if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) { return TRUE; @@ -130,7 +130,7 @@ public: : -p_bitmap->AlignToFourByte(p_bitmap->GetBmiWidth())) // FUNCTION: BETA10 0x1002c320 - MxU8* GetStart(MxS32 p_left, MxS32 p_top) + MxU8* GetStart(MxS32 p_left, MxS32 p_top) const { if (m_bmiHeader->biCompression == BI_RGB) { return m_data + p_left + diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index 7e7c9822..58a55995 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -15,17 +15,12 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0x0c); MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) { m_width = p_bitmap.GetBmiWidth(); - // DECOMP: ECX becomes word-sized if these are not two separate actions. - MxLong height = p_bitmap.GetBmiHeightAbs(); - m_height = height; + m_height = p_bitmap.GetBmiHeightAbs(); MxS32 size = ((m_width * m_height) / 8) + 1; m_bitmask = new MxU8[size]; memset(m_bitmask, 0, size); - MxU32 rowsBeforeTop; - MxU8* bitmapSrcPtr; - // The goal here is to enable us to walk through the bitmap's rows // in order, regardless of the orientation. We want to end up at the // start of the first row, which is either at position 0, or at @@ -34,37 +29,13 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) // Reminder: Negative biHeight means this is a top-down DIB. // Otherwise it is bottom-up. - switch (p_bitmap.GetBmiHeader()->biCompression) { - case BI_RGB: { - if (p_bitmap.GetBmiHeight() < 0) { - rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; - } - bitmapSrcPtr = p_bitmap.GetImage() + (p_bitmap.GetBmiStride() * rowsBeforeTop); - break; - } - case BI_RGB_TOPDOWN: - bitmapSrcPtr = p_bitmap.GetImage(); - break; - default: { - if (p_bitmap.GetBmiHeight() < 0) { - rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; - } - bitmapSrcPtr = p_bitmap.GetImage() + (p_bitmap.GetBmiStride() * rowsBeforeTop); - } - } + MxU8* bitmapSrcPtr = p_bitmap.GetStart(0, 0); // How many bytes are there for each row of the bitmap? // (i.e. the image stride) // If this is a bottom-up DIB, we will walk it in reverse. - // TODO: Same rounding trick as in MxBitmap - MxS32 rowSeek = ((m_width + 3) & -4); - if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() > 0) { + MxS32 rowSeek = p_bitmap.AlignToFourByte(m_width); + if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() >= 0) { rowSeek = -rowSeek; } @@ -76,9 +47,7 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) MxU8* tPtr = bitmapSrcPtr; for (MxS32 i = 0; i < m_width; i++) { if (*tPtr) { - // TODO: Second CDQ instruction for abs() should not be there. - MxU32 shift = abs(offset) & 7; - m_bitmask[offset / 8] |= (1 << abs((MxS32) shift)); + m_bitmask[offset / 8] |= (1 << (offset % 8)); } tPtr++; offset++; @@ -116,7 +85,7 @@ MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y) } MxS32 pos = p_y * m_width + p_x; - return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0; + return m_bitmask[pos / 8] & (1 << (pos % 8)) ? 1 : 0; } // FUNCTION: LEGO1 0x100b2760 From 4ec020ed8937344bbeeca43e6a786cd3b385c2ae Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Sun, 6 Apr 2025 10:36:13 -0400 Subject: [PATCH 14/14] MxVideoPresenter::IsHit to 100% (#1428) --- LEGO1/omni/src/video/mxvideopresenter.cpp | 41 +++-------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index 58a55995..93a886a5 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -174,47 +174,14 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY()); } - MxLong heightAbs = m_frameBitmap->GetBmiHeightAbs(); + MxRect32 rect(0, 0, m_frameBitmap->GetBmiWidth(), m_frameBitmap->GetBmiHeightAbs()); + rect += GetLocation(); - MxLong minX = m_location.GetX(); - MxLong minY = m_location.GetY(); - - MxLong maxY = minY + heightAbs; - MxLong maxX = minX + m_frameBitmap->GetBmiWidth(); - - if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) { + if (p_x < rect.GetLeft() || p_x >= rect.GetRight() || p_y < rect.GetTop() || p_y >= rect.GetBottom()) { return FALSE; } - MxU8* pixel; - - MxLong biCompression = m_frameBitmap->GetBmiHeader()->biCompression; - MxLong height = m_frameBitmap->GetBmiHeight(); - MxLong seekRow; - - // DECOMP: Same basic layout as AlphaMask constructor - // The idea here is to again seek to the correct place in the bitmap's - // m_data buffer. The x,y args are (most likely) screen x and y, so we - // need to shift that to coordinates local to the bitmap by removing - // the MxPresenter location x and y coordinates. - if (biCompression == BI_RGB) { - if (biCompression == BI_RGB_TOPDOWN || height < 0) { - seekRow = p_y - m_location.GetY(); - } - else { - height = height > 0 ? height : -height; - seekRow = height - p_y - 1 + m_location.GetY(); - } - pixel = m_frameBitmap->GetBmiStride() * seekRow + m_frameBitmap->GetImage() - m_location.GetX() + p_x; - } - else if (biCompression == BI_RGB_TOPDOWN) { - pixel = m_frameBitmap->GetImage(); - } - else { - height = height > 0 ? height : -height; - height--; - pixel = m_frameBitmap->GetBmiStride() * height + m_frameBitmap->GetImage(); - } + MxU8* pixel = m_frameBitmap->GetStart(p_x - rect.GetLeft(), p_y - rect.GetTop()); if (GetBit4()) { return (MxBool) *pixel;