From 1f582eb6106315654576475322640d98427ac0c5 Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 22 Dec 2024 22:21:07 -0500 Subject: [PATCH 1/2] Implement `MxDisplaySurface::VTable0x24` (#1261) * MxDisplaySurface::VTable0x24 * Fix stride/length check in vtable24 and vtable28 --- LEGO1/omni/include/mxdisplaysurface.h | 16 +-- LEGO1/omni/src/video/mxdisplaysurface.cpp | 155 ++++++++++++++++++++-- 2 files changed, 153 insertions(+), 18 deletions(-) diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 43606bd0..066e11d2 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -27,14 +27,14 @@ class MxDisplaySurface : public MxCore { virtual void Destroy(); // vtable+0x1c virtual void SetPalette(MxPalette* p_palette); // vtable+0x20 virtual void VTable0x24( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4 + LPDDSURFACEDESC p_desc, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height ); // vtable+0x24 virtual void VTable0x28( MxBitmap* p_bitmap, diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 647de44a..d22c059b 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -398,7 +398,7 @@ void MxDisplaySurface::VTable0x28( MxU16* p16bitPal = m_16bitPal; MxS32 i; - if (stride || length) { + if (!stride && !length) { while (height--) { MxU8* surfaceBefore = surface; @@ -1063,18 +1063,153 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() return NULL; } -// STUB: LEGO1 0x100bc200 +// FUNCTION: LEGO1 0x100bc200 void MxDisplaySurface::VTable0x24( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4 + LPDDSURFACEDESC p_desc, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height ) { + // DECOMP: Almost an exact copy of VTable0x28, except that it uses the argument DDSURFACEDESC + // instead of getting one from GetDisplayMode. + if (!GetRectIntersection( + p_bitmap->GetBmiWidth(), + p_bitmap->GetBmiHeightAbs(), + m_videoParam.GetRect().GetWidth(), + m_videoParam.GetRect().GetHeight(), + &p_left, + &p_top, + &p_right, + &p_bottom, + &p_width, + &p_height + )) { + return; + } + + MxU8* data = p_bitmap->GetStart(p_left, p_top); + + if (m_videoParam.Flags().GetF1bit3()) { + p_bottom *= 2; + p_right *= 2; + + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + MxU8* surface = (MxU8*) p_desc->lpSurface + p_right + (p_bottom * p_desc->lPitch); + MxLong stride = -p_width + GetAdjustedStride(p_bitmap); + + MxLong length = -2 * p_width + p_desc->lPitch; + while (p_height--) { + MxU8* surfaceBefore = surface; + + for (MxS32 i = 0; p_width > i; i++) { + *surface++ = *data; + *surface++ = *data++; + } + + data += stride; + surface += length; + + memcpy(surface, surfaceBefore, 2 * p_width); + surface += p_desc->lPitch; + } + break; + } + case 16: { + MxU8* surface = (MxU8*) p_desc->lpSurface + (2 * p_right) + (p_bottom * p_desc->lPitch); + MxLong stride = -p_width + GetAdjustedStride(p_bitmap); + + MxS32 length = -4 * p_width + p_desc->lPitch; + MxS32 height = p_height; + MxS32 width = p_width; + MxS32 copyWidth = width * 4; + MxU16* p16bitPal = m_16bitPal; + + MxS32 i; + if (!stride && !length) { + while (height--) { + MxU8* surfaceBefore = surface; + + for (i = 0; i < width; i++) { + MxU16 element = p16bitPal[*data]; + *(MxU16*) surface = element; + surface += 2; + *(MxU16*) surface = element; + + data++; + surface += 2; + } + + memcpy(surface, surfaceBefore, copyWidth); + surface += p_desc->lPitch; + } + } + else { + while (height--) { + MxU8* surfaceBefore = surface; + + for (i = 0; i < width; i++) { + MxU16 element = p16bitPal[*data]; + *(MxU16*) surface = element; + surface += 2; + *(MxU16*) surface = element; + + data++; + surface += 2; + } + + data += stride; + surface += length; + + memcpy(surface, surfaceBefore, p_width * 4); + surface += p_desc->lPitch; + } + } + break; + } + default: + break; + } + } + else { + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + MxU8* surface = (MxU8*) p_desc->lpSurface + p_right + (p_bottom * p_desc->lPitch); + MxLong stride = GetAdjustedStride(p_bitmap); + + MxLong length = p_desc->lPitch; + while (p_height--) { + memcpy(surface, data, p_width); + data += stride; + surface += length; + } + break; + } + case 16: { + MxU8* surface = (MxU8*) p_desc->lpSurface + (2 * p_right) + (p_bottom * p_desc->lPitch); + MxLong stride = -p_width + GetAdjustedStride(p_bitmap); + + MxLong length = -2 * p_width + p_desc->lPitch; + for (MxS32 i = 0; i < p_height; i++) { + for (MxS32 j = 0; j < p_width; j++) { + *(MxU16*) surface = m_16bitPal[*data++]; + surface += 2; + } + + data += stride; + surface += length; + } + break; + } + default: + break; + } + } } // STUB: LEGO1 0x100bc630 From 48c327ca5a0f06cdd3182b24938195f60e4a8f9c Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Mon, 23 Dec 2024 10:17:36 -0500 Subject: [PATCH 2/2] Implement MxDisplaySurface::VTable0x2c (#1262) * Implement MxDisplaySurface::VTable0x2c * fix header namespace * Incorporate improvements from @madebr branch * Naming * Naming --------- Co-authored-by: Christian Semmler Co-authored-by: Anonymous Maarten --- LEGO1/omni/include/mxdisplaysurface.h | 22 +++--- LEGO1/omni/src/video/mxdisplaysurface.cpp | 95 +++++++++++++++++++---- tools/ncc/skip.yml | 1 + 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 066e11d2..a6925e3d 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -45,16 +45,16 @@ class MxDisplaySurface : public MxCore { MxS32 p_width, MxS32 p_height ); // vtable+0x28 - virtual MxBool VTable0x2c( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool + virtual void VTable0x2c( + LPDDSURFACEDESC p_desc, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, + MxBool p_RLE ); // vtable+0x2c virtual void VTable0x30( MxBitmap* p_bitmap, @@ -64,7 +64,7 @@ class MxDisplaySurface : public MxCore { MxS32 p_bottom, MxS32 p_width, MxS32 p_height, - MxBool p_und + MxBool p_RLE ); // vtable+0x30 virtual undefined4 VTable0x34( undefined4, diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index d22c059b..2d179d01 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -491,7 +491,7 @@ void MxDisplaySurface::VTable0x30( MxS32 p_bottom, MxS32 p_width, MxS32 p_height, - MxBool p_und + MxBool p_RLE ) { if (!GetRectIntersection( @@ -527,7 +527,7 @@ void MxDisplaySurface::VTable0x30( switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { case 8: { MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch); - if (p_und) { + if (p_RLE) { MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage; DrawTransparentRLE(data, surface, size, p_width, p_height, ddsd.lPitch, 8); } @@ -553,7 +553,7 @@ void MxDisplaySurface::VTable0x30( } case 16: { MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch); - if (p_und) { + if (p_RLE) { MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage; DrawTransparentRLE(data, surface, size, p_width, p_height, ddsd.lPitch, 16); } @@ -1212,20 +1212,85 @@ void MxDisplaySurface::VTable0x24( } } -// STUB: LEGO1 0x100bc630 -MxBool MxDisplaySurface::VTable0x2c( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool +// FUNCTION: LEGO1 0x100bc630 +void MxDisplaySurface::VTable0x2c( + LPDDSURFACEDESC p_desc, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, + MxBool p_RLE ) { - return 0; + // DECOMP: Almost an exact copy of VTable0x28, except that it uses the argument DDSURFACEDESC + // instead of getting one from GetDisplayMode. + if (!GetRectIntersection( + p_bitmap->GetBmiWidth(), + p_bitmap->GetBmiHeightAbs(), + m_videoParam.GetRect().GetWidth(), + m_videoParam.GetRect().GetHeight(), + &p_left, + &p_top, + &p_right, + &p_bottom, + &p_width, + &p_height + )) { + return; + } + + MxU8* src = p_bitmap->GetStart(p_left, p_top); + + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + MxLong destStride = p_desc->lPitch; + MxU8* dest = (MxU8*) p_desc->lpSurface + p_right + (p_bottom * p_desc->lPitch); + + if (p_RLE) { + DrawTransparentRLE(src, dest, p_bitmap->GetBmiHeader()->biSizeImage, p_width, p_height, p_desc->lPitch, 8); + } + else { + MxLong srcSkip = GetAdjustedStride(p_bitmap) - p_width; + MxLong destSkip = destStride - p_width; + + for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) { + for (MxS32 j = 0; j < p_width; j++, src++, dest++) { + if (*src) { + *dest = *src; + } + } + } + } + break; + } + case 16: { + MxLong destStride = p_desc->lPitch; + MxU8* dest = (MxU8*) p_desc->lpSurface + (2 * p_right) + (p_bottom * p_desc->lPitch); + + if (p_RLE) { + DrawTransparentRLE(src, dest, p_bitmap->GetBmiHeader()->biSizeImage, p_width, p_height, p_desc->lPitch, 16); + } + else { + MxLong srcStride = GetAdjustedStride(p_bitmap); + MxLong srcSkip = srcStride - p_width; + MxLong destSkip = destStride - 2 * p_width; + + for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) { + for (MxS32 j = 0; j < p_width; j++, src++, dest += 2) { + if (*src != 0) { + *(MxU16*) dest = m_16bitPal[*src]; + } + } + } + } + break; + } + default: + break; + } } // FUNCTION: LEGO1 0x100bc8b0 diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index 4f39ddc8..06c6e0a5 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -13,6 +13,7 @@ m_HELDesc: 'Allow this variable name' p_HWDesc: 'Allow this variable name' p_HELDesc: 'Allow this variable name' e_RAMStream: 'Allow this enum constant' +p_RLE: 'Allow this parameter name' p_milliseconds: 'Probably a bug with function call' m_increaseAmount: "Can't currently detect member in union" m_increaseFactor: "Can't currently detect member in union"