Implement MxDisplaySurface::VTable0x44 (#467)

* Update mxdisplaysurface.cpp

* add arguments to header

* Fix glitched bitmaps

* WIP fixes

* Match

* Fix

* Changes

* Fixes

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
This commit is contained in:
Misha 2024-01-20 14:31:07 -05:00 committed by GitHub
parent 961282e3c6
commit ea5f9b4886
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 145 additions and 31 deletions

View file

@ -83,7 +83,12 @@ class MxDisplaySurface : public MxCore {
); // vtable+0x38
virtual void GetDC(HDC* p_hdc); // vtable+0x3c
virtual void ReleaseDC(HDC p_hdc); // vtable+0x40
virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); // vtable+0x44
virtual LPDIRECTDRAWSURFACE VTable0x44(
MxBitmap* p_bitmap,
undefined4* p_ret,
undefined4 p_doNotWriteToSurface,
undefined4 p_transparent
); // vtable+0x44
void ClearScreen();
static LPDIRECTDRAWSURFACE FUN_100bc070();

View file

@ -328,30 +328,7 @@ void MxDisplaySurface::VTable0x28(
}
if (hr == DD_OK) {
MxU8* data;
switch (p_bitmap->GetBmiHeader()->biCompression) {
case BI_RGB: {
MxS32 rowsBeforeTop;
if (p_bitmap->GetBmiHeight() < 0)
rowsBeforeTop = p_top;
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);
}
}
MxU8* data = p_bitmap->GetStart(p_left, p_top);
if (m_videoParam.Flags().GetF1bit3()) {
p_bottom *= 2;
@ -564,10 +541,142 @@ void MxDisplaySurface::ReleaseDC(HDC p_hdc)
this->m_ddSurface2->ReleaseDC(p_hdc);
}
// STUB: LEGO1 0x100bbc60
LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4)
// FUNCTION: LEGO1 0x100bbc60
LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
MxBitmap* p_bitmap,
undefined4* p_ret,
undefined4 p_doNotWriteToSurface,
undefined4 p_transparent
)
{
LPDIRECTDRAWSURFACE surface = NULL;
LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw();
MVideoManager();
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (draw->GetDisplayMode(&ddsd))
return NULL;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.dwWidth = p_bitmap->GetBmiWidth();
ddsd.dwHeight = p_bitmap->GetBmiHeightAbs();
*p_ret = 0;
ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
if (draw->CreateSurface(&ddsd, &surface, NULL) != S_OK) {
if (*p_ret) {
*p_ret = 0;
// Try creating bitmap surface in vram if system ram ran out
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (draw->CreateSurface(&ddsd, &surface, NULL) != S_OK) {
surface = NULL;
}
}
else
surface = NULL;
}
if (surface) {
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != S_OK) {
surface->Release();
surface = NULL;
goto done;
}
if (p_doNotWriteToSurface) {
goto done;
}
MxU8* bitmapSrcPtr = p_bitmap->GetStart(0, 0);
MxU16* surfaceData = (MxU16*) ddsd.lpSurface;
MxLong widthNormal = p_bitmap->GetBmiWidth();
MxLong heightAbs = p_bitmap->GetBmiHeightAbs();
// TODO: Probably p_bitmap->GetAdjustedStride()
MxS32 rowSeek = p_bitmap->GetBmiStride();
if (p_bitmap->GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap->GetBmiHeight() >= 0)
rowSeek = -rowSeek;
MxLong newPitch = ddsd.lPitch;
switch (ddsd.ddpfPixelFormat.dwRGBBitCount) {
case 8: {
for (MxS32 y = heightAbs; y > 0; y--) {
memcpy(surfaceData, bitmapSrcPtr, p_bitmap->GetBmiHeight());
bitmapSrcPtr += rowSeek;
surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch);
}
surface->Unlock(ddsd.lpSurface);
if (p_transparent && surface) {
DDCOLORKEY key;
key.dwColorSpaceHighValue = 0;
key.dwColorSpaceLowValue = 0;
surface->SetColorKey(DDCKEY_SRCBLT, &key);
}
break;
}
case 16:
if (m_16bitPal == NULL) {
if (surface) {
surface->Release();
}
return NULL;
}
else {
rowSeek -= p_bitmap->GetBmiWidth();
newPitch -= 2 * p_bitmap->GetBmiWidth();
if (p_transparent) {
for (MxS32 y = heightAbs; y > 0; y--) {
for (MxS32 x = widthNormal; x > 0; x--) {
if (*bitmapSrcPtr) {
*surfaceData = m_16bitPal[*bitmapSrcPtr];
}
else {
*surfaceData = 31775;
}
bitmapSrcPtr++;
surfaceData++;
}
bitmapSrcPtr += rowSeek;
surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch);
}
DDCOLORKEY key;
key.dwColorSpaceHighValue = 31775;
key.dwColorSpaceLowValue = 31775;
surface->SetColorKey(DDCKEY_SRCBLT, &key);
}
else {
for (MxS32 y = heightAbs; y > 0; y--) {
for (MxS32 x = widthNormal; x > 0; x--) {
*surfaceData++ = m_16bitPal[*bitmapSrcPtr++];
}
bitmapSrcPtr += rowSeek;
surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch);
}
}
surface->Unlock(ddsd.lpSurface);
}
}
}
done:
return surface;
}
// STUB: LEGO1 0x100bc070