diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index 0aec323e..620b9656 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -1,6 +1,6 @@ #include "mxdisplaysurface.h" -#include "mxomni.h" +#include "legoomni.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); @@ -54,7 +54,7 @@ void MxDisplaySurface::FUN_100ba640() hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); } - if (hr != S_OK) { + if (hr != DD_OK) { return; } @@ -68,7 +68,7 @@ void MxDisplaySurface::FUN_100ba640() m_ddSurface2->Unlock(desc.lpSurface); if (m_videoParam.Flags().GetFlipSurfaces()) { - m_ddSurface1->Flip(NULL, 1); + m_ddSurface1->Flip(NULL, DDFLIP_WAIT); } } } @@ -223,18 +223,218 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) { } -// STUB: LEGO1 0x100bacc0 -MxBool MxDisplaySurface::VTable0x28( - MxBitmap* p_bitmap, - MxS32 p_left, - MxS32 p_top, - MxS32 p_right, - MxS32 p_bottom, - MxS32 p_width, - MxS32 p_height +// FUNCTION: LEGO1 0x100bacc0 +void MxDisplaySurface::VTable0x28( + MxBitmap* p_bitmap, // a2 + MxS32 p_left, // a3 + MxS32 p_top, // a4 + MxS32 p_right, // a5 + MxS32 p_bottom, // a6 + MxS32 p_width, // a7 + MxS32 p_height // a8 ) { - return 0; + if (FUN_100b6e10( + 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 + )) { + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + m_ddSurface2->Restore(); + hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); + } + + if (hr == DD_OK) { + BITMAPINFOHEADER* biHeader = p_bitmap->GetBmiHeader(); + MxU8* data; + + switch (biHeader->biCompression) { + case BI_RGB: { + MxS32 rowsBeforeTop; + if (p_bitmap->GetBmiHeight() < 0) + rowsBeforeTop = 0; + else + rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - p_top - 1; + data = p_bitmap->GetBitmapData() + p_left + (p_bitmap->GetBmiStride() * rowsBeforeTop); + break; + } + case BI_RGB_TOPDOWN: + data = p_bitmap->GetBitmapData(); + break; + default: { + MxS32 rowsBeforeTop; + if (p_bitmap->GetBmiHeight() < 0) + rowsBeforeTop = 0; + else + rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - 1; + data = p_bitmap->GetBitmapData() + (p_bitmap->GetBmiStride() * rowsBeforeTop); + } + } + + if (m_videoParam.Flags().GetF1bit3()) { + p_bottom *= 2; + p_right *= 2; + + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + OutputDebugStr("Flag, Case 8bit"); + MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch); + MxLong stride; + + if (biHeader->biCompression == BI_RGB_TOPDOWN || p_bitmap->GetBmiHeight() < 0) + stride = p_bitmap->GetBmiStride(); + else + stride = -p_bitmap->GetBmiStride(); + + MxLong v22 = stride - p_width; + MxLong v55 = ddsd.lPitch - (2 * p_width); + + while (p_height--) { + MxU8* surfaceBefore = surface; + + for (MxS32 i = 0; p_width > i; *(surface - 1) = *(data - 1)) { + MxU8 element = *data++; + surface += 2; + ++i; + *(surface - 2) = element; + } + + data += v22; + MxU8* dest = surface + v55; + + memcpy(dest, surfaceBefore, 2 * p_width); + surface = dest + ddsd.lPitch; + } + break; + } + case 16: { + MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch); + MxLong stride; + + if (biHeader->biCompression == BI_RGB_TOPDOWN || p_bitmap->GetBmiHeight() < 0) + stride = p_bitmap->GetBmiStride(); + else + stride = -p_bitmap->GetBmiStride(); + + MxLong v31 = 4 * p_width; + MxLong v56 = stride - p_width; + MxS32 v61 = p_width; + MxLong v62 = ddsd.lPitch - (4 * p_width); + MxU16* p16BitPal = m_16bitPal; + + if (stride != p_width || v62) { + OutputDebugStr("Flag, Case 16bit A"); + while (p_height--) { + MxU8* surfaceBefore = surface; + + if (v61 > 0) { + MxS32 v38 = v61; + do { + MxU32 element = *data++; + element = p16BitPal[element]; + + surface += 4; + *((MxU16*) surface - 2) = element; + --v38; + *((MxU16*) surface - 2) = element; + } while (v38); + } + + data += v56; + MxU8* dest = &surface[v62]; + + memcpy(dest, surfaceBefore, 4 * ((MxU32) (4 * p_width) >> 2)); + surface = dest + ddsd.lPitch; + } + } + else { + OutputDebugStr("Flag, Case 16bit B"); + while (p_height--) { + MxU8* surfaceBefore = surface; + + if (v61 > 0) { + MxS32 v34 = v61; + do { + MxU32 element = *data++; + element = p16BitPal[element]; + + surface += 4; + *((MxU16*) surface - 2) = element; + --v34; + *((MxU16*) surface - 2) = element; + } while (v34); + } + + memcpy(surface, surfaceBefore, v31); + surface += ddsd.lPitch; + } + } + } + } + } + else { + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + OutputDebugStr("No flag, Case 8bit"); + MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch); + MxLong stride; + + if (biHeader->biCompression == BI_RGB_TOPDOWN || p_bitmap->GetBmiHeight() < 0) + stride = p_bitmap->GetBmiStride(); + else + stride = -p_bitmap->GetBmiStride(); + + MxLong v57 = ddsd.lPitch; + while (p_height--) { + MxU8* prevData = data; + data += stride; + memcpy(surface, prevData, p_width); + surface += v57; + } + break; + } + case 16: { + OutputDebugStr("No flag, Case 16bit"); + MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch); + MxLong stride; + + if (biHeader->biCompression == BI_RGB_TOPDOWN || p_bitmap->GetBmiHeight() < 0) + stride = p_bitmap->GetBmiStride(); + else + stride = -p_bitmap->GetBmiStride(); + + MxLong v50 = stride - p_width; + MxLong j = ddsd.lPitch - (2 * p_width); + + for (MxU32 v51 = 0; p_height > v51; v51++) { + for (MxU32 k = 0; p_width > k; k++) { + MxU8 v53 = *data++; + surface += 2; + //*(MxU16*) (surface - 2) = *(MxU16*) (*(MxU32*) (&m_16bitPal) + 2 * v53); + *(MxU16*) (surface - 2) = m_16bitPal[v53]; + } + data += v50; + surface += j; + } + } + } + } + + m_ddSurface2->Unlock(ddsd.lpSurface); + } + } } // STUB: LEGO1 0x100bb1d0 @@ -269,7 +469,7 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p DDSURFACEDESC ddsd; memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (m_ddSurface2->Lock(NULL, &ddsd, 1, NULL) == S_OK) { + if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) { MxU8* surface = (MxU8*) ddsd.lpSurface; MxS32 height = m_videoParam.GetRect().GetHeight(); @@ -284,7 +484,7 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p OutputDebugString("MxDisplaySurface::Display error\n"); } } - m_ddSurface1->Flip(NULL, 1); + m_ddSurface1->Flip(NULL, DDFLIP_WAIT); } else { POINT point = {0, 0}; diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 39a2fda8..c5e97d86 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -35,7 +35,7 @@ class MxDisplaySurface : public MxCore { undefined4, undefined4 ); // vtable+0x24 - virtual MxBool VTable0x28( + virtual void VTable0x28( MxBitmap* p_bitmap, MxS32 p_left, MxS32 p_top,