From 894034f9cf1208b921146992ad862a57277d6023 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 12 Dec 2024 11:02:14 -0700 Subject: [PATCH] Implement/match `WriteDefaultTexture` (#1213) --- LEGO1/lego/legoomni/include/legoutils.h | 2 +- LEGO1/lego/legoomni/src/common/legoutils.cpp | 70 +++++++++++++++++++- LEGO1/lego/legoomni/src/worlds/isle.cpp | 18 ++--- LEGO1/lego/sources/misc/legoimage.h | 1 + 4 files changed, 79 insertions(+), 12 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index e0353ba7..ef816382 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -64,7 +64,7 @@ MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_wor MxS32 UpdateLightPosition(MxS32 p_increase); void SetLightPosition(MxS32 p_index); LegoNamedTexture* ReadNamedTexture(LegoFile* p_file); -void FUN_1003f540(LegoFile* p_file, const char* p_filename); +void WriteDefaultTexture(LegoFile* p_file, const char* p_name); void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_namedTexture); void FUN_1003f930(LegoNamedTexture* p_namedTexture); diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 7cde830d..86730b7f 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -686,9 +686,75 @@ LegoNamedTexture* ReadNamedTexture(LegoFile* p_file) return namedTexture; } -// STUB: LEGO1 0x1003f540 -void FUN_1003f540(LegoFile* p_file, const char* p_filename) +// FUNCTION: LEGO1 0x1003f540 +void WriteDefaultTexture(LegoFile* p_file, const char* p_name) { + MxString name(p_name); + LegoTextureInfo* textureInfo = TextureContainer()->Get(p_name); + + if (textureInfo != NULL) { + DDSURFACEDESC desc; + LegoPaletteEntry paletteEntries[256]; + + LPDIRECTDRAWSURFACE surface = textureInfo->m_surface; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { + LegoImage* image = new LegoImage(desc.dwWidth, desc.dwHeight); + + if (image != NULL) { + if (desc.dwWidth == desc.lPitch) { + memcpy(desc.lpSurface, image->GetBits(), desc.dwWidth * desc.dwHeight); + } + else { + MxU8* surface = (MxU8*) desc.lpSurface; + LegoU8* bits = image->GetBits(); + + for (MxS32 i = 0; i < desc.dwHeight; i++) { + memcpy(surface, bits, desc.dwWidth); + surface += desc.lPitch; + bits += desc.dwWidth; + } + } + + surface->Unlock(desc.lpSurface); + + PALETTEENTRY entries[256]; + if (textureInfo->m_palette->GetEntries(0, 0, sizeOfArray(entries), entries) == DD_OK) { + MxS32 i; + for (i = 0; i < sizeOfArray(entries); i++) { + if (entries[i].peFlags != 0) { + break; + } + + paletteEntries[i].SetRed(entries[i].peRed); + paletteEntries[i].SetGreen(entries[i].peGreen); + paletteEntries[i].SetBlue(entries[i].peBlue); + } + + image->SetCount(i); + + if (i > 0) { + // Note: this appears to be a bug. size should be i * sizeof(LegoPaletteEntry) + memcpy(image->GetPalette(), paletteEntries, i); + } + + LegoTexture texture; + texture.SetImage(image); + + p_file->WriteString(name); + texture.Write(p_file); + } + else { + delete image; + } + } + else { + surface->Unlock(desc.lpSurface); + } + } + } } // FUNCTION: LEGO1 0x1003f8a0 diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index ef830926..f53e61ca 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -1334,21 +1334,21 @@ MxResult Act1State::Serialize(LegoFile* p_file) WriteNamedTexture(p_file, m_helicopterWindshield); } else { - FUN_1003f540(p_file, "chwind.gif"); + WriteDefaultTexture(p_file, "chwind.gif"); } if (m_helicopterJetLeft) { WriteNamedTexture(p_file, m_helicopterJetLeft); } else { - FUN_1003f540(p_file, "chjetl.gif"); + WriteDefaultTexture(p_file, "chjetl.gif"); } if (m_helicopterJetRight) { WriteNamedTexture(p_file, m_helicopterJetRight); } else { - FUN_1003f540(p_file, "chjetr.gif"); + WriteDefaultTexture(p_file, "chjetr.gif"); } } @@ -1357,14 +1357,14 @@ MxResult Act1State::Serialize(LegoFile* p_file) WriteNamedTexture(p_file, m_jetskiFront); } else { - FUN_1003f540(p_file, "jsfrnt.gif"); + WriteDefaultTexture(p_file, "jsfrnt.gif"); } if (m_jetskiWindshield) { WriteNamedTexture(p_file, m_jetskiWindshield); } else { - FUN_1003f540(p_file, "jswnsh.gif"); + WriteDefaultTexture(p_file, "jswnsh.gif"); } } @@ -1373,7 +1373,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) WriteNamedTexture(p_file, m_dunebuggyFront); } else { - FUN_1003f540(p_file, "dbfrfn.gif"); + WriteDefaultTexture(p_file, "dbfrfn.gif"); } } @@ -1382,21 +1382,21 @@ MxResult Act1State::Serialize(LegoFile* p_file) WriteNamedTexture(p_file, m_racecarFront); } else { - FUN_1003f540(p_file, "rcfrnt.gif"); + WriteDefaultTexture(p_file, "rcfrnt.gif"); } if (m_racecarBack) { WriteNamedTexture(p_file, m_racecarBack); } else { - FUN_1003f540(p_file, "rcback.gif"); + WriteDefaultTexture(p_file, "rcback.gif"); } if (m_racecarTail) { WriteNamedTexture(p_file, m_racecarTail); } else { - FUN_1003f540(p_file, "rctail.gif"); + WriteDefaultTexture(p_file, "rctail.gif"); } } diff --git a/LEGO1/lego/sources/misc/legoimage.h b/LEGO1/lego/sources/misc/legoimage.h index 7e0fbb17..c62701be 100644 --- a/LEGO1/lego/sources/misc/legoimage.h +++ b/LEGO1/lego/sources/misc/legoimage.h @@ -36,6 +36,7 @@ class LegoImage { LegoU32 GetHeight() { return m_height; } void SetHeight(LegoU32 p_height) { m_height = p_height; } LegoU32 GetCount() { return m_count; } + void SetCount(LegoU32 p_count) { m_count = p_count; } LegoPaletteEntry* GetPalette() { return m_palette; } LegoPaletteEntry& GetPaletteEntry(LegoU32 p_i) { return m_palette[p_i]; } void SetPaletteEntry(LegoU32 p_i, LegoPaletteEntry& p_paletteEntry) { m_palette[p_i] = p_paletteEntry; }