From 61632ea0a7375c402f7d40a4f7816bc9100a4d9a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 20 Aug 2025 14:11:36 -0700 Subject: [PATCH 1/3] Add police widescreen background (#690) * Add Police background * Update bitmap --- assets/main.cpp | 12 +++++++++--- assets/widescreen/Police_Background_Wide.bmp | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 assets/widescreen/Police_Background_Wide.bmp diff --git a/assets/main.cpp b/assets/main.cpp index d239e013..ef269e97 100644 --- a/assets/main.cpp +++ b/assets/main.cpp @@ -20,10 +20,16 @@ void CreateWidescreen() struct AssetView { std::string name; std::string extra; + int32_t z; }; const AssetView widescreenBitmaps[] = { {"GaraDoor_Background_Wide", - "World:current, StartWith:\\Lego\\Scripts\\Isle\\Isle;1160, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161"} + "World:current, StartWith:\\Lego\\Scripts\\Isle\\Isle;1160, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161", + -1}, + {"Police_Background_Wide", + "World:\\lego\\scripts\\police\\police;0, StartWith:\\Lego\\Scripts\\Police\\Police;0, " + "RemoveWith:\\Lego\\Scripts\\Police\\Police;0", + 10} }; si::Interleaf si; @@ -44,9 +50,9 @@ void CreateWidescreen() object->presenter_ = "MxStillPresenter"; object->name_ = asset.name; object->filetype_ = si::MxOb::STL; - object->location_ = si::Vector3(-240.0, 0.0, -1.0); + object->location_ = si::Vector3(-240, 0.0, asset.z); object->direction_ = si::Vector3(0, 0, 0); - object->up_ = si::Vector3(0, 1.0, 0); + object->up_ = si::Vector3(0, 1, 0); if (!object->ReplaceWithFile(file.c_str())) { abort(); diff --git a/assets/widescreen/Police_Background_Wide.bmp b/assets/widescreen/Police_Background_Wide.bmp new file mode 100644 index 00000000..dcbfcc50 --- /dev/null +++ b/assets/widescreen/Police_Background_Wide.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc2cfb5d0522d2cc4cfbaf74d6b1b5f1f2e0512f613e398849a2359d537deff5 +size 538678 From 57e918904cd30e112829a0b366606ac2ecb94bd0 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Wed, 20 Aug 2025 23:58:10 +0200 Subject: [PATCH 2/3] Use 8bit surfaces for 2D content on miniwin (#680) --- .../src/common/mxtransitionmanager.cpp | 4 +- .../legoomni/src/video/legovideomanager.cpp | 2 +- LEGO1/omni/include/mxdisplaysurface.h | 19 +- LEGO1/omni/src/video/mxdisplaysurface.cpp | 372 +++++++----------- LEGO1/omni/src/video/mxvideopresenter.cpp | 5 +- 5 files changed, 155 insertions(+), 247 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp index 7e3d9294..fde06e8f 100644 --- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp @@ -630,7 +630,6 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) // Setup display surface if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::c_bit5) != 0) { MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface(); - MxBool und = FALSE; displaySurface->VTable0x2c( p_ddsc, m_waitIndicator->GetBitmap(), @@ -639,8 +638,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) m_waitIndicator->GetLocation().GetX(), m_waitIndicator->GetLocation().GetY(), m_waitIndicator->GetWidth(), - m_waitIndicator->GetHeight(), - und + m_waitIndicator->GetHeight() ); } else { diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index fe56a353..b0e2a7bf 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -852,7 +852,7 @@ void LegoVideoManager::SetCursorBitmap(const CursorBitmap* p_cursorBitmap) m_cursorRect.bottom = p_cursorBitmap->height; m_cursorRect.right = p_cursorBitmap->width; - m_cursorSurface = MxDisplaySurface::CreateCursorSurface(p_cursorBitmap); + m_cursorSurface = MxDisplaySurface::CreateCursorSurface(p_cursorBitmap, m_videoParam.GetPalette()); if (m_cursorSurface == NULL) { m_drawCursor = FALSE; diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index aa30b543..e0d1a240 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -61,8 +61,7 @@ class MxDisplaySurface : public MxCore { MxS32 p_right, MxS32 p_bottom, MxS32 p_width, - MxS32 p_height, - MxBool p_RLE + MxS32 p_height ); // vtable+0x2c virtual void VTable0x30( MxBitmap* p_bitmap, @@ -71,8 +70,7 @@ class MxDisplaySurface : public MxCore { MxS32 p_right, MxS32 p_bottom, MxS32 p_width, - MxS32 p_height, - MxBool p_RLE + MxS32 p_height ); // vtable+0x30 virtual void Display( MxS32 p_left, @@ -92,23 +90,12 @@ class MxDisplaySurface : public MxCore { ); // vtable+0x44 void ClearScreen(); - static LPDIRECTDRAWSURFACE CreateCursorSurface(const CursorBitmap* p_cursorBitmap); + static LPDIRECTDRAWSURFACE CreateCursorSurface(const CursorBitmap* p_cursorBitmap, MxPalette* p_palette); static LPDIRECTDRAWSURFACE CopySurface(LPDIRECTDRAWSURFACE p_src); LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return m_ddSurface1; } LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return m_ddSurface2; } MxVideoParam& GetVideoParam() { return m_videoParam; } - - void DrawTransparentRLE( - MxU8*& p_bitmapData, - MxU8*& p_surfaceData, - MxU32 p_bitmapSize, - MxS32 p_width, - MxS32 p_height, - MxLong p_pitch, - MxU8 p_bpp - ); - LPDIRECTDRAWSURFACE FUN_100bc8b0(MxS32 p_width, MxS32 p_height); private: diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 71a3808e..387b31b8 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -327,6 +327,7 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) } } +#ifndef MINIWIN MxS32 bitCount = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount; if (bitCount == 8) { return; @@ -378,6 +379,7 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) m_32bitPal[i] = red | green | blue | alpha; } } +#endif } // FUNCTION: LEGO1 0x100bacc0 @@ -412,7 +414,13 @@ void MxDisplaySurface::VTable0x28( ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = p_width; ddsd.dwHeight = p_height; +#ifdef MINIWIN + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 8; +#else ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat; +#endif ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; LPDIRECTDRAWSURFACE tempSurface = nullptr; @@ -422,6 +430,24 @@ void MxDisplaySurface::VTable0x28( return; } +#ifdef MINIWIN + MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo(); + if (bmi) { + PALETTEENTRY pe[256]; + for (int i = 0; i < 256; i++) { + pe[i].peRed = bmi->m_bmiColors[i].rgbRed; + pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen; + pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue; + pe[i].peFlags = PC_NONE; + } + + LPDIRECTDRAWPALETTE palette = nullptr; + if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) { + tempSurface->SetPalette(palette); + palette->Release(); + } + } +#else if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount != 32) { DDCOLORKEY colorKey; if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 8) { @@ -432,6 +458,7 @@ void MxDisplaySurface::VTable0x28( } tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey); } +#endif DDSURFACEDESC tempDesc; memset(&tempDesc, 0, sizeof(tempDesc)); @@ -450,7 +477,7 @@ void MxDisplaySurface::VTable0x28( MxU8* data = p_bitmap->GetStart(p_left, p_top); - MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8; + MxS32 bytesPerPixel = tempDesc.ddpfPixelFormat.dwRGBBitCount / 8; MxU8* surface = (MxU8*) tempDesc.lpSurface; MxLong stride = (bytesPerPixel == 1) ? GetAdjustedStride(p_bitmap) : -p_width + GetAdjustedStride(p_bitmap); @@ -502,8 +529,7 @@ void MxDisplaySurface::VTable0x30( MxS32 p_right, MxS32 p_bottom, MxS32 p_width, - MxS32 p_height, - MxBool p_RLE + MxS32 p_height ) { if (!GetRectIntersection( @@ -526,7 +552,13 @@ void MxDisplaySurface::VTable0x30( ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = p_width; ddsd.dwHeight = p_height; +#ifdef MINIWIN + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 8; +#else ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat; +#endif ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw(); @@ -535,6 +567,25 @@ void MxDisplaySurface::VTable0x30( return; } +#ifdef MINIWIN + MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo(); + if (bmi) { + PALETTEENTRY pe[256]; + for (int i = 0; i < 256; i++) { + pe[i].peRed = bmi->m_bmiColors[i].rgbRed; + pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen; + pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue; + pe[i].peFlags = PC_NONE; + } + + LPDIRECTDRAWPALETTE palette = nullptr; + if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) { + tempSurface->SetPalette(palette); + palette->Release(); + } + } +#endif + DDCOLORKEY colorKey; colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = 0; tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey); @@ -550,38 +601,32 @@ void MxDisplaySurface::VTable0x30( MxU8* data = p_bitmap->GetStart(p_left, p_top); - MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8; + MxS32 bytesPerPixel = tempDesc.ddpfPixelFormat.dwRGBBitCount / 8; MxU8* surface = (MxU8*) tempDesc.lpSurface; - if (p_RLE) { - MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage; - DrawTransparentRLE(data, surface, size, p_width, p_height, tempDesc.lPitch, bytesPerPixel * 8); - } - else { - MxLong stride = -p_width + GetAdjustedStride(p_bitmap); - MxLong length = -bytesPerPixel * p_width + tempDesc.lPitch; + MxLong stride = -p_width + GetAdjustedStride(p_bitmap); + MxLong length = -bytesPerPixel * p_width + tempDesc.lPitch; - for (MxS32 i = 0; i < p_height; i++) { - for (MxS32 j = 0; j < p_width; j++) { - if (*data != 0) { - switch (bytesPerPixel) { - case 1: - *surface = *data; - break; - case 2: - *(MxU16*) surface = m_16bitPal[*data]; - break; - default: - *(MxU32*) surface = m_32bitPal[*data]; - break; - } + for (MxS32 i = 0; i < p_height; i++) { + for (MxS32 j = 0; j < p_width; j++) { + if (*data != 0) { + switch (bytesPerPixel) { + case 1: + *surface = *data; + break; + case 2: + *(MxU16*) surface = m_16bitPal[*data]; + break; + default: + *(MxU32*) surface = m_32bitPal[*data]; + break; } - data++; - surface += bytesPerPixel; } - data += stride; - surface += length; + data++; + surface += bytesPerPixel; } + data += stride; + surface += length; } tempSurface->Unlock(NULL); @@ -591,161 +636,6 @@ void MxDisplaySurface::VTable0x30( tempSurface->Release(); } -// FUNCTION: LEGO1 0x100bb500 -// FUNCTION: BETA10 0x10140cd6 -void MxDisplaySurface::DrawTransparentRLE( - MxU8*& p_bitmapData, - MxU8*& p_surfaceData, - MxU32 p_bitmapSize, - MxS32 p_width, - MxS32 p_height, - MxLong p_pitch, - MxU8 p_bpp -) -{ - /* Assumes partial RLE for the bitmap: only the skipped pixels are compressed. - The drawn pixels are uncompressed. The procedure is: - 1. Read 3 bytes from p_bitmapData. Skip this many pixels on the surface. - 2. Read 3 bytes from p_bitmapData. Draw this many pixels on the surface. - 3. Repeat until the end of p_bitmapData is reached. */ - - MxU8* end = p_bitmapData + p_bitmapSize; - MxU8* surfCopy = p_surfaceData; // unused? - - // The total number of pixels drawn or skipped - MxU32 count = 0; - - // Used in both 8 and 16 bit branches - MxU32 skipCount; - MxU32 drawCount; - MxU32 t; - - if (p_bpp == 16) { - // DECOMP: why goto? - goto sixteen_bit; - } - - while (p_bitmapData < end) { - skipCount = *p_bitmapData++; - t = *p_bitmapData++; - skipCount += t << 8; - t = *p_bitmapData++; - skipCount += t << 16; - - MxS32 rowRemainder = p_width - count % p_width; - count += skipCount; - - if (skipCount >= rowRemainder) { - p_surfaceData += rowRemainder; // skip the rest of this row - skipCount -= rowRemainder; - p_surfaceData += p_pitch - p_width; // seek to start of next row - p_surfaceData += p_pitch * (skipCount / p_width); // skip entire rows if any - } - - // skip any pixels at the start of this row - p_surfaceData += skipCount % p_width; - if (p_bitmapData >= end) { - break; - } - - drawCount = *p_bitmapData++; - t = *p_bitmapData++; - drawCount += t << 8; - t = *p_bitmapData++; - drawCount += t << 16; - - rowRemainder = p_width - count % p_width; - count += drawCount; - - if (drawCount >= rowRemainder) { - memcpy(p_surfaceData, p_bitmapData, rowRemainder); - p_surfaceData += rowRemainder; - p_bitmapData += rowRemainder; - - drawCount -= rowRemainder; - - // seek to start of bitmap on this screen row - p_surfaceData += p_pitch - p_width; - MxS32 rows = drawCount / p_width; - - for (MxU32 i = 0; i < rows; i++) { - memcpy(p_surfaceData, p_bitmapData, p_width); - p_bitmapData += p_width; - p_surfaceData += p_pitch; - } - } - - MxS32 tail = drawCount % p_width; - memcpy(p_surfaceData, p_bitmapData, tail); - p_surfaceData += tail; - p_bitmapData += tail; - } - return; - -sixteen_bit: - while (p_bitmapData < end) { - skipCount = *p_bitmapData++; - t = *p_bitmapData++; - skipCount += t << 8; - t = *p_bitmapData++; - skipCount += t << 16; - - MxS32 rowRemainder = p_width - count % p_width; - count += skipCount; - - if (skipCount >= rowRemainder) { - p_surfaceData += 2 * rowRemainder; - skipCount -= rowRemainder; - p_surfaceData += p_pitch - 2 * p_width; - p_surfaceData += p_pitch * (skipCount / p_width); - } - - p_surfaceData += 2 * (skipCount % p_width); - if (p_bitmapData >= end) { - break; - } - - drawCount = *p_bitmapData++; - t = *p_bitmapData++; - drawCount += t << 8; - t = *p_bitmapData++; - drawCount += t << 16; - - rowRemainder = p_width - count % p_width; - count += drawCount; - - if (drawCount >= rowRemainder) { - // memcpy - for (MxU32 j = 0; j < rowRemainder; j++) { - *((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++]; - p_surfaceData += 2; - } - - drawCount -= rowRemainder; - - p_surfaceData += p_pitch - 2 * p_width; - MxS32 rows = drawCount / p_width; - - for (MxU32 i = 0; i < rows; i++) { - // memcpy - for (MxS32 j = 0; j < p_width; j++) { - *((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++]; - p_surfaceData += 2; - } - - p_surfaceData += p_pitch - 2 * p_width; - } - } - - MxS32 tail = drawCount % p_width; - // memcpy - for (MxS32 j = 0; j < tail; j++) { - *((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++]; - p_surfaceData += 2; - } - } -} - // FUNCTION: LEGO1 0x100bba50 void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height) { @@ -829,7 +719,13 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.dwWidth = p_bitmap->GetBmiWidth(); ddsd.dwHeight = p_bitmap->GetBmiHeightAbs(); +#ifdef MINIWIN + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 8; +#else ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat; +#endif ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; *p_ret = 0; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; @@ -852,6 +748,24 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( } if (surface) { +#ifdef MINIWIN + MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo(); + if (bmi) { + PALETTEENTRY pe[256]; + for (int i = 0; i < 256; i++) { + pe[i].peRed = bmi->m_bmiColors[i].rgbRed; + pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen; + pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue; + pe[i].peFlags = PC_NONE; + } + LPDIRECTDRAWPALETTE palette = nullptr; + if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) { + surface->SetPalette(palette); + palette->Release(); + } + } +#endif + memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); @@ -971,6 +885,21 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CopySurface(LPDIRECTDRAWSURFACE p_src) return NULL; } +#ifdef MINIWIN + LPDIRECTDRAWPALETTE srcPalette = nullptr; + if (p_src->GetPalette(&srcPalette) == DD_OK && srcPalette) { + PALETTEENTRY pe[256]; + if (srcPalette->GetEntries(0, 0, 256, pe) == DD_OK) { + LPDIRECTDRAWPALETTE newPalette = nullptr; + if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &newPalette, NULL) == DD_OK) { + newSurface->SetPalette(newPalette); + newPalette->Release(); + } + } + srcPalette->Release(); + } +#endif + RECT rect = {0, 0, (LONG) ddsd.dwWidth, (LONG) ddsd.dwHeight}; if (newSurface->BltFast(0, 0, p_src, &rect, DDBLTFAST_WAIT) != DD_OK) { @@ -1084,8 +1013,7 @@ void MxDisplaySurface::VTable0x2c( MxS32 p_right, MxS32 p_bottom, MxS32 p_width, - MxS32 p_height, - MxBool p_RLE + MxS32 p_height ) { // DECOMP: Almost an exact copy of VTable0x28, except that it uses the argument DDSURFACEDESC @@ -1111,38 +1039,25 @@ void MxDisplaySurface::VTable0x2c( MxLong destStride = p_desc->lPitch; MxU8* dest = (MxU8*) p_desc->lpSurface + bytesPerPixel * p_right + (p_bottom * destStride); - if (p_RLE) { - DrawTransparentRLE( - src, - dest, - p_bitmap->GetBmiHeader()->biSizeImage, - p_width, - p_height, - destStride, - m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount - ); - } - else { - MxLong srcStride = GetAdjustedStride(p_bitmap); - MxLong srcSkip = srcStride - p_width; - MxLong destSkip = destStride - bytesPerPixel * p_width; - for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) { - for (MxS32 j = 0; j < p_width; j++, src++) { - if (*src != 0) { - switch (bytesPerPixel) { - case 1: - *dest = *src; - break; - case 2: - *(MxU16*) dest = m_16bitPal[*src]; - break; - default: - *(MxU32*) dest = m_32bitPal[*src]; - break; - } + MxLong srcStride = GetAdjustedStride(p_bitmap); + MxLong srcSkip = srcStride - p_width; + MxLong destSkip = destStride - bytesPerPixel * p_width; + for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) { + for (MxS32 j = 0; j < p_width; j++, src++) { + if (*src != 0) { + switch (bytesPerPixel) { + case 1: + *dest = *src; + break; + case 2: + *(MxU16*) dest = m_16bitPal[*src]; + break; + default: + *(MxU32*) dest = m_32bitPal[*src]; + break; } - dest += bytesPerPixel; } + dest += bytesPerPixel; } } } @@ -1183,11 +1098,10 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bc8b0(MxS32 p_width, MxS32 p_height return surface; } -LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_cursorBitmap) +LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_cursorBitmap, MxPalette* p_palette) { LPDIRECTDRAWSURFACE newSurface = NULL; IDirectDraw* draw = MVideoManager()->GetDirectDraw(); - MVideoManager(); DDSURFACEDESC ddsd; memset(&ddsd, 0, sizeof(ddsd)); @@ -1197,14 +1111,19 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ return NULL; } - MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; - MxBool isAlphaAvailable = ((ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == DDPF_ALPHAPIXELS) && - (ddsd.ddpfPixelFormat.dwRGBAlphaBitMask != 0); - ddsd.dwWidth = p_cursorBitmap->width; ddsd.dwHeight = p_cursorBitmap->height; ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN; +#ifdef MINIWIN + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 8; +#endif + + MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; + MxBool isAlphaAvailable = ((ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == DDPF_ALPHAPIXELS) && + (ddsd.ddpfPixelFormat.dwRGBAlphaBitMask != 0); if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) { ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; @@ -1215,6 +1134,10 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ } } +#ifdef MINIWIN + newSurface->SetPalette(p_palette->CreateNativePalette()); +#endif + memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); @@ -1242,6 +1165,8 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ else { pixel = isBlack ? 0 : 0xff; } + surface[x + y * p_cursorBitmap->width] = pixel; + break; } case 2: { MxU16* surface = (MxU16*) ddsd.lpSurface; @@ -1284,8 +1209,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ switch (bytesPerPixel) { case 1: { DDCOLORKEY colorkey; - colorkey.dwColorSpaceHighValue = 0x10; - colorkey.dwColorSpaceLowValue = 0x10; + colorkey.dwColorSpaceHighValue = colorkey.dwColorSpaceLowValue = 0x10; newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey); break; } diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index cd804de1..ee03ab71 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -253,8 +253,7 @@ void MxVideoPresenter::PutFrame() rect.GetLeft(), rect.GetTop(), m_frameBitmap->GetBmiWidth(), - m_frameBitmap->GetBmiHeightAbs(), - TRUE + m_frameBitmap->GetBmiHeightAbs() ); } } @@ -280,7 +279,7 @@ void MxVideoPresenter::PutFrame() } } else { - displaySurface->VTable0x30(m_frameBitmap, 0, 0, GetX(), GetY(), GetWidth(), GetHeight(), FALSE); + displaySurface->VTable0x30(m_frameBitmap, 0, 0, GetX(), GetY(), GetWidth(), GetHeight()); } } else if (m_surface) { From 7c95890cad1619e72d4df30f8e64d0f3988d513f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 20 Aug 2025 15:04:08 -0700 Subject: [PATCH 3/3] Remove obsolete enums in Infocenter (#1677) --- LEGO1/lego/legoomni/include/infocenter.h | 23 +--- LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 101 +++++++++--------- 2 files changed, 53 insertions(+), 71 deletions(-) diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index 888816d1..2826c220 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -119,25 +119,6 @@ struct InfocenterMapEntry { // SIZE 0x1d8 class Infocenter : public LegoWorld { public: - enum Cutscene { - e_noIntro = -1, - e_legoMovie, - e_mindscapeMovie, - e_introMovie, - e_outroMovie, - e_badEndMovie, - e_goodEndMovie - }; - - enum Character { - e_noCharacter = 0, - e_pepper, - e_mama, - e_papa, - e_nick, - e_laura - }; - Infocenter(); ~Infocenter() override; @@ -180,7 +161,7 @@ class Infocenter : public LegoWorld { void UpdateFrameHot(MxBool p_display); void Reset(); - void PlayCutscene(Cutscene p_entityId, MxBool p_scale); + void PlayCutscene(IntroScript::Script p_entityId, MxBool p_scale); void StopCutscene(); void UpdateEnabledGlowControl(MxS32 p_x, MxS32 p_y); @@ -198,7 +179,7 @@ class Infocenter : public LegoWorld { MxS16 m_selectedCharacter; // 0xfc InfocenterState* m_infocenterState; // 0x100 LegoGameState::Area m_destLocation; // 0x104 - Cutscene m_currentCutscene; // 0x108 + IntroScript::Script m_currentCutscene; // 0x108 Radio m_radio; // 0x10c MxStillPresenter* m_dragPresenter; // 0x11c InfocenterMapEntry m_glowInfo[7]; // 0x120 diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index d55dfc85..93664c95 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -4,6 +4,7 @@ #include "credits_actions.h" #include "helicopter.h" #include "infomain_actions.h" +#include "intro_actions.h" #include "jukebox.h" #include "jukebox_actions.h" #include "legoact2.h" @@ -128,13 +129,13 @@ InfomainScript::Script g_bricksterDialogue[2] = { // FUNCTION: LEGO1 0x1006ea20 Infocenter::Infocenter() { - m_selectedCharacter = e_noCharacter; + m_selectedCharacter = LegoActor::c_none; m_dragPresenter = NULL; m_infocenterState = NULL; m_frame = NULL; m_destLocation = LegoGameState::e_undefined; m_currentInfomainScript = InfomainScript::c_noneInfomain; - m_currentCutscene = e_noIntro; + m_currentCutscene = IntroScript::c_noneIntro; memset(&m_glowInfo, 0, sizeof(m_glowInfo)); @@ -306,19 +307,19 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) GameState()->SetActor(m_selectedCharacter); switch (m_selectedCharacter) { - case e_pepper: + case LegoActor::c_pepper: PlayAction(InfomainScript::c_avo901in_RunAnim); break; - case e_mama: + case LegoActor::c_mama: PlayAction(InfomainScript::c_avo902in_RunAnim); break; - case e_papa: + case LegoActor::c_papa: PlayAction(InfomainScript::c_avo903in_RunAnim); break; - case e_nick: + case LegoActor::c_nick: PlayAction(InfomainScript::c_avo904in_RunAnim); break; - case e_laura: + case LegoActor::c_laura: PlayAction(InfomainScript::c_avo905in_RunAnim); break; default: @@ -343,23 +344,23 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) switch (m_infocenterState->m_state) { case InfocenterState::e_playCutscene: switch (m_currentCutscene) { - case e_legoMovie: - PlayCutscene(e_mindscapeMovie, FALSE); + case IntroScript::c_Lego_Movie: + PlayCutscene(IntroScript::c_Mindscape_Movie, FALSE); return 1; - case e_mindscapeMovie: - PlayCutscene(e_introMovie, TRUE); + case IntroScript::c_Mindscape_Movie: + PlayCutscene(IntroScript::c_Intro_Movie, TRUE); return 1; - case e_badEndMovie: + case IntroScript::c_BadEnd_Movie: StopCutscene(); m_infocenterState->m_state = InfocenterState::e_welcomeAnimation; PlayAction(InfomainScript::c_tic092in_RunAnim); - m_currentCutscene = e_noIntro; + m_currentCutscene = IntroScript::c_noneIntro; return 1; - case e_goodEndMovie: + case IntroScript::c_GoodEnd_Movie: StopCutscene(); m_infocenterState->m_state = InfocenterState::e_welcomeAnimation; PlayAction(InfomainScript::c_tic089in_RunAnim); - m_currentCutscene = e_noIntro; + m_currentCutscene = IntroScript::c_noneIntro; return 1; } @@ -367,7 +368,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) StopCutscene(); m_infocenterState->m_state = InfocenterState::e_welcomeAnimation; PlayAction(InfomainScript::c_iic001in_RunAnim); - m_currentCutscene = e_noIntro; + m_currentCutscene = IntroScript::c_noneIntro; if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; @@ -378,17 +379,17 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) m_infocenterState->m_state = InfocenterState::e_welcomeAnimation; switch (m_currentCutscene) { - case e_badEndMovie: + case IntroScript::c_BadEnd_Movie: PlayAction(InfomainScript::c_tic092in_RunAnim); break; - case e_goodEndMovie: + case IntroScript::c_GoodEnd_Movie: PlayAction(InfomainScript::c_tic089in_RunAnim); break; default: PlayAction(InfomainScript::c_iic001in_RunAnim); } - m_currentCutscene = e_noIntro; + m_currentCutscene = IntroScript::c_noneIntro; return 1; case InfocenterState::e_notRegistered: SetROIVisible(g_object2x4red, FALSE); @@ -405,7 +406,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) break; case InfocenterState::e_selectedCharacterAndDestination: if (action->GetObjectId() == m_currentInfomainScript) { - if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != e_noCharacter) { + if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != LegoActor::c_none) { GameState()->SetActor(m_selectedCharacter); } TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -455,7 +456,7 @@ void Infocenter::ReadyWorld() switch (m_infocenterState->m_state) { case InfocenterState::e_newState: - PlayCutscene(e_legoMovie, TRUE); + PlayCutscene(IntroScript::c_Lego_Movie, TRUE); m_infocenterState->m_state = InfocenterState::e_playCutscene; return; case InfocenterState::e_selectedSave: @@ -518,7 +519,7 @@ void Infocenter::ReadyWorld() if (state && state->GetState() == LegoAct2State::c_badEnding) { bg->Enable(TRUE); - PlayCutscene(e_badEndMovie, TRUE); + PlayCutscene(IntroScript::c_BadEnd_Movie, TRUE); m_infocenterState->m_state = InfocenterState::e_playCutscene; return; } @@ -563,14 +564,14 @@ void Infocenter::ReadyWorld() if (state && state->GetState() == Act3State::e_badEnding) { bg->Enable(TRUE); - PlayCutscene(e_badEndMovie, TRUE); + PlayCutscene(IntroScript::c_BadEnd_Movie, TRUE); m_infocenterState->m_state = InfocenterState::e_playCutscene; return; } if (state && state->GetState() == Act3State::e_goodEnding) { bg->Enable(TRUE); - PlayCutscene(e_goodEndMovie, TRUE); + PlayCutscene(IntroScript::c_GoodEnd_Movie, TRUE); m_infocenterState->m_state = InfocenterState::e_playCutscene; return; } @@ -752,19 +753,19 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) switch (m_dragPresenter->GetAction()->GetObjectId()) { case InfomainScript::c_PepperHot_Bitmap: - m_selectedCharacter = e_pepper; + m_selectedCharacter = LegoActor::c_pepper; break; case InfomainScript::c_MamaHot_Bitmap: - m_selectedCharacter = e_mama; + m_selectedCharacter = LegoActor::c_mama; break; case InfomainScript::c_PapaHot_Bitmap: - m_selectedCharacter = e_papa; + m_selectedCharacter = LegoActor::c_papa; break; case InfomainScript::c_NickHot_Bitmap: - m_selectedCharacter = e_nick; + m_selectedCharacter = LegoActor::c_nick; break; case InfomainScript::c_LauraHot_Bitmap: - m_selectedCharacter = e_laura; + m_selectedCharacter = LegoActor::c_laura; break; } @@ -773,7 +774,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) switch (control->GetAction()->GetObjectId()) { case InfomainScript::c_Pepper_Ctl: - if (m_selectedCharacter == e_pepper) { + if (m_selectedCharacter == LegoActor::c_pepper) { m_radio.Stop(); BackgroundAudioManager()->Stop(); PlayAction(InfomainScript::c_Pepper_All_Movie); @@ -781,7 +782,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) } break; case InfomainScript::c_Mama_Ctl: - if (m_selectedCharacter == e_mama) { + if (m_selectedCharacter == LegoActor::c_mama) { m_radio.Stop(); BackgroundAudioManager()->Stop(); PlayAction(InfomainScript::c_Mama_All_Movie); @@ -789,7 +790,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) } break; case InfomainScript::c_Papa_Ctl: - if (m_selectedCharacter == e_papa) { + if (m_selectedCharacter == LegoActor::c_papa) { m_radio.Stop(); BackgroundAudioManager()->Stop(); PlayAction(InfomainScript::c_Papa_All_Movie); @@ -797,7 +798,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) } break; case InfomainScript::c_Nick_Ctl: - if (m_selectedCharacter == e_nick) { + if (m_selectedCharacter == LegoActor::c_nick) { m_radio.Stop(); BackgroundAudioManager()->Stop(); PlayAction(InfomainScript::c_Nick_All_Movie); @@ -805,7 +806,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) } break; case InfomainScript::c_Laura_Ctl: - if (m_selectedCharacter == e_laura) { + if (m_selectedCharacter == LegoActor::c_laura) { m_radio.Stop(); BackgroundAudioManager()->Stop(); PlayAction(InfomainScript::c_Laura_All_Movie); @@ -823,19 +824,19 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) GameState()->SetActor(m_selectedCharacter); switch (m_selectedCharacter) { - case e_pepper: + case LegoActor::c_pepper: PlayAction(InfomainScript::c_avo901in_RunAnim); break; - case e_mama: + case LegoActor::c_mama: PlayAction(InfomainScript::c_avo902in_RunAnim); break; - case e_papa: + case LegoActor::c_papa: PlayAction(InfomainScript::c_avo903in_RunAnim); break; - case e_nick: + case LegoActor::c_nick: PlayAction(InfomainScript::c_avo904in_RunAnim); break; - case e_laura: + case LegoActor::c_laura: PlayAction(InfomainScript::c_avo905in_RunAnim); break; } @@ -894,23 +895,23 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) } else { switch (m_selectedCharacter) { - case e_pepper: + case LegoActor::c_pepper: dialogueToPlay = InfomainScript::c_avo901in_RunAnim; GameState()->SetActorId(m_selectedCharacter); break; - case e_mama: + case LegoActor::c_mama: dialogueToPlay = InfomainScript::c_avo902in_RunAnim; GameState()->SetActorId(m_selectedCharacter); break; - case e_papa: + case LegoActor::c_papa: dialogueToPlay = InfomainScript::c_avo903in_RunAnim; GameState()->SetActorId(m_selectedCharacter); break; - case e_nick: + case LegoActor::c_nick: dialogueToPlay = InfomainScript::c_avo904in_RunAnim; GameState()->SetActorId(m_selectedCharacter); break; - case e_laura: + case LegoActor::c_laura: dialogueToPlay = InfomainScript::c_avo905in_RunAnim; GameState()->SetActorId(m_selectedCharacter); break; @@ -1255,7 +1256,7 @@ MxResult Infocenter::Tickle() } // FUNCTION: LEGO1 0x10070c20 -void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale) +void Infocenter::PlayCutscene(IntroScript::Script p_entityId, MxBool p_scale) { m_currentCutscene = p_entityId; @@ -1265,9 +1266,9 @@ void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale) SetAppCursor(e_cursorNone); VideoManager()->GetDisplaySurface()->ClearScreen(); - if (m_currentCutscene != e_noIntro) { + if (m_currentCutscene != IntroScript::c_noneIntro) { // check if the cutscene is an ending - if (m_currentCutscene >= e_badEndMovie && m_currentCutscene <= e_goodEndMovie) { + if (m_currentCutscene >= IntroScript::c_BadEnd_Movie && m_currentCutscene <= IntroScript::c_GoodEnd_Movie) { Reset(); } @@ -1278,7 +1279,7 @@ void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale) // FUNCTION: LEGO1 0x10070cb0 void Infocenter::StopCutscene() { - if (m_currentCutscene != e_noIntro) { + if (m_currentCutscene != IntroScript::c_noneIntro) { InvokeAction(Extra::ActionType::e_close, *g_introScript, m_currentCutscene, NULL); } @@ -1395,9 +1396,9 @@ void Infocenter::Reset() GameState()->m_savedPreviousArea = LegoGameState::e_undefined; InitializeBitmaps(); - m_selectedCharacter = e_pepper; + m_selectedCharacter = LegoActor::c_pepper; - GameState()->SetActor(e_pepper); + GameState()->SetActor(LegoActor::c_pepper); HelicopterState* state = (HelicopterState*) GameState()->GetState("HelicopterState");