From 4983da422c56e71f193658273ee337d7286928fa Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 4 Jul 2025 14:47:24 +0200 Subject: [PATCH 1/2] OpenGL: Respect max supported texture size (#518) --- miniwin/src/d3drm/backends/opengl1/actual.cpp | 7 +++++++ miniwin/src/d3drm/backends/opengl1/actual.h | 1 + miniwin/src/d3drm/backends/opengl1/renderer.cpp | 17 ++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/miniwin/src/d3drm/backends/opengl1/actual.cpp b/miniwin/src/d3drm/backends/opengl1/actual.cpp index b1a464d5..a86ebec1 100644 --- a/miniwin/src/d3drm/backends/opengl1/actual.cpp +++ b/miniwin/src/d3drm/backends/opengl1/actual.cpp @@ -42,6 +42,13 @@ void GL11_DestroyTexture(GLuint texId) glDeleteTextures(1, &texId); } +int GL11_GetMaxTextureSize() +{ + GLint maxTextureSize = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + return maxTextureSize; +} + GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUi) { GLuint texId; diff --git a/miniwin/src/d3drm/backends/opengl1/actual.h b/miniwin/src/d3drm/backends/opengl1/actual.h index 9460119c..87f33687 100644 --- a/miniwin/src/d3drm/backends/opengl1/actual.h +++ b/miniwin/src/d3drm/backends/opengl1/actual.h @@ -64,6 +64,7 @@ struct GLMeshCacheEntry { void GL11_InitState(); void GL11_LoadExtensions(); void GL11_DestroyTexture(GLuint texId); +int GL11_GetMaxTextureSize(); GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI); void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture); void GL11_DestroyMesh(GLMeshCacheEntry& cache); diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 8c43d14a..00088da9 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -132,10 +132,21 @@ static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi) SDL_Surface* finalSurface = working; - int newW = NextPowerOfTwo(working->w); - int newH = NextPowerOfTwo(working->h); + int newW = working->w; + int newH = working->h; + if (!useNPOT) { + newW = NextPowerOfTwo(newW); + newH = NextPowerOfTwo(newH); + } + int max = GL11_GetMaxTextureSize(); + if (newW > max) { + newW = max; + } + if (newH > max) { + newH = max; + } - if (!useNPOT && (newW != working->w || newH != working->h)) { + if (newW != working->w || newH != working->h) { SDL_Surface* resized = SDL_CreateSurface(newW, newH, working->format); if (!resized) { SDL_Log("SDL_CreateSurface (resize) failed: %s", SDL_GetError()); From 0d2cbd50d58eb217311c8ceb2160bd1ce76acb8e Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 4 Jul 2025 14:48:01 +0200 Subject: [PATCH 2/2] Fake mosaic transition (#516) --- .../legoomni/include/mxtransitionmanager.h | 4 +- .../src/common/mxtransitionmanager.cpp | 128 ++++++++++++++++++ LEGO1/omni/include/mxdisplaysurface.h | 3 + LEGO1/omni/src/video/mxdisplaysurface.cpp | 3 - 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index dd9dc9ed..7c31daf7 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -48,7 +48,8 @@ class MxTransitionManager : public MxCore { e_mosaic, e_wipeDown, e_windows, - e_broken // Unknown what this is supposed to be, it locks the game up + e_broken, // Unknown what this is supposed to be, it locks the game up + e_fakeMosaic }; MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); @@ -68,6 +69,7 @@ class MxTransitionManager : public MxCore { void WipeDownTransition(); void WindowsTransition(); void BrokenTransition(); + void FakeMosaicTransition(); void SubmitCopyRect(LPDDSURFACEDESC p_ddsc); void SetupCopyRect(LPDDSURFACEDESC p_ddsc); diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp index 6fd211c6..1987b6cd 100644 --- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp @@ -84,6 +84,9 @@ MxResult MxTransitionManager::Tickle() case e_broken: BrokenTransition(); break; + case e_fakeMosaic: + FakeMosaicTransition(); + break; } return SUCCESS; } @@ -613,3 +616,128 @@ void MxTransitionManager::configureMxTransitionManager(TransitionType p_transiti { g_transitionManagerConfig = p_transitionManagerConfig; } + +int g_colorOffset; +int GetColorIndexWithLocality(int p_col, int p_row) +{ + int islandX = p_col / 8; + int islandY = p_row / 8; // Dvide screen in 8x6 tiles + + int island = islandY * 8 + islandX; // tile id + + if (SDL_rand(3) > island / 8) { + return 6 + SDL_rand(2); // emulate sky + } + + if (SDL_rand(16) > 2) { + island += SDL_rand(3) - 1 + (SDL_rand(3) - 1) * 8; // blure tiles + } + + int hash = (island + g_colorOffset) * 2654435761u; + int scrambled = (hash >> 16) % 32; + + int finalIndex = scrambled + SDL_rand(3) - 1; + return finalIndex % 32; +} + +void MxTransitionManager::FakeMosaicTransition() +{ + if (m_animationTimer == 16) { + m_animationTimer = 0; + EndTransition(TRUE); + return; + } + + if (m_animationTimer == 0) { + g_colorOffset = SDL_rand(32); + for (MxS32 i = 0; i < 64; i++) { + m_columnOrder[i] = i; + } + for (MxS32 i = 0; i < 64; i++) { + MxS32 swap = SDL_rand(64); + std::swap(m_columnOrder[i], m_columnOrder[swap]); + } + for (MxS32 i = 0; i < 48; i++) { + m_randomShift[i] = SDL_rand(64); + } + } + + DDSURFACEDESC ddsd = {}; + ddsd.dwSize = sizeof(ddsd); + HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); + if (res == DDERR_SURFACELOST) { + m_ddSurface->Restore(); + res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); + } + + if (res == DD_OK) { + SubmitCopyRect(&ddsd); + + static const MxU8 g_palette[32][3] = { + {0x00, 0x00, 0x00}, {0x12, 0x1e, 0x50}, {0x00, 0x22, 0x6c}, {0x14, 0x2d, 0x9f}, {0x0e, 0x36, 0xb0}, + {0x0e, 0x39, 0xd0}, {0x47, 0x96, 0xe2}, {0x79, 0xaa, 0xca}, {0xff, 0xff, 0xff}, {0xc9, 0xcd, 0xcb}, + {0xad, 0xad, 0xab}, {0xa6, 0x91, 0x8e}, {0xaf, 0x59, 0x49}, {0xc0, 0x00, 0x00}, {0xab, 0x18, 0x18}, + {0x61, 0x0c, 0x0c}, {0x04, 0x38, 0x12}, {0x2c, 0x67, 0x28}, {0x4a, 0xb4, 0x6b}, {0x94, 0xb7, 0x7c}, + {0xb6, 0xb9, 0x87}, {0x52, 0x4a, 0x67}, {0x87, 0x8d, 0x8a}, {0xa6, 0x91, 0x8e}, {0xf8, 0xee, 0xdc}, + {0xf4, 0xe2, 0xc3}, {0x87, 0x8d, 0x8a}, {0xba, 0x9f, 0x12}, {0xb5, 0x83, 0x00}, {0x6a, 0x44, 0x27}, + {0x36, 0x37, 0x34}, {0x2b, 0x23, 0x0f} + }; + + MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; + + for (MxS32 col = 0; col < 64; col++) { + if (m_animationTimer * 4 > m_columnOrder[col]) { + continue; + } + if (m_animationTimer * 4 + 3 < m_columnOrder[col]) { + continue; + } + + for (MxS32 row = 0; row < 48; row++) { + MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); + MxS32 yStart = 10 * row; + + int paletteIndex = GetColorIndexWithLocality(xShift / 10, row); + + const MxU8* color = g_palette[paletteIndex]; + + for (MxS32 y = 0; y < 10; y++) { + MxU8* dest = (MxU8*) ddsd.lpSurface + (yStart + y) * ddsd.lPitch + xShift * bytesPerPixel; + switch (bytesPerPixel) { + case 1: + memset(dest, paletteIndex, 10); + break; + case 2: { + MxU32 pixel = RGB555_CREATE(color[2], color[1], color[0]); + MxU16* p = (MxU16*) dest; + for (MxS32 i = 0; i < 10; i++) { + p[i] = pixel; + } + break; + } + default: { + MxU32 pixel = RGB8888_CREATE(color[2], color[1], color[0], 255); + MxU32* p = (MxU32*) dest; + for (MxS32 i = 0; i < 10; i++) { + p[i] = pixel; + } + break; + } + } + } + } + } + + SetupCopyRect(&ddsd); + m_ddSurface->Unlock(ddsd.lpSurface); + + if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) { + VideoManager() + ->GetDisplaySurface() + ->GetDirectDrawSurface1() + ->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); + } + + m_animationTimer++; + } +} diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 3a3dcd08..aa30b543 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -12,6 +12,9 @@ #include #endif +#define RGB555_CREATE(R, G, B) (((R) << 10) | (G) << 5 | (B) << 0) +#define RGB8888_CREATE(R, G, B, A) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) + class MxBitmap; class MxPalette; diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index b10330f2..c07f475e 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -18,9 +18,6 @@ DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); -#define RGB555_CREATE(R, G, B) (((R) << 10) | (G) << 5 | (B) << 0) -#define RGB8888_CREATE(R, G, B, A) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) - // GLOBAL: LEGO1 0x1010215c MxU32 g_unk0x1010215c = 0;