Merge pull request from foxtacles/mergeisle5

Merge from isledecomp/isle
This commit is contained in:
Christian Semmler 2025-04-06 08:49:51 -07:00 committed by GitHub
commit fc93e1eadf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 319 additions and 269 deletions

View file

@ -21,7 +21,7 @@ struct LegoPathActorSetCompare {
}; };
struct LegoAnimPresenterSetCompare { struct LegoAnimPresenterSetCompare {
MxBool operator()(const LegoAnimPresenter* p_lhs, const LegoAnimPresenter* p_rhs) const MxU32 operator()(const LegoAnimPresenter* p_lhs, const LegoAnimPresenter* p_rhs) const
{ {
return (COMPARE_POINTER_TYPE) p_lhs < (COMPARE_POINTER_TYPE) p_rhs; return (COMPARE_POINTER_TYPE) p_lhs < (COMPARE_POINTER_TYPE) p_rhs;
} }

View file

@ -5,7 +5,6 @@
#include "mxcompositepresenter.h" #include "mxcompositepresenter.h"
class LegoControlManagerNotificationParam; class LegoControlManagerNotificationParam;
class MxVideoPresenter;
// VTABLE: LEGO1 0x100d7b88 // VTABLE: LEGO1 0x100d7b88
// VTABLE: BETA10 0x101bf5d0 // VTABLE: BETA10 0x101bf5d0
@ -48,18 +47,18 @@ public:
virtual void VTable0x6c(MxS16 p_unk0x4e); // vtable+0x6c virtual void VTable0x6c(MxS16 p_unk0x4e); // vtable+0x6c
MxBool FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter); MxBool FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter);
MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter); MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter);
MxS16 GetUnknown0x4e() { return m_unk0x4e; } MxS16 GetUnknown0x4e() { return m_unk0x4e; }
private: private:
undefined2 m_unk0x4c; // 0x4c MxS16 m_unk0x4c; // 0x4c
MxS16 m_unk0x4e; // 0x4e MxS16 m_unk0x4e; // 0x4e
MxBool m_unk0x50; // 0x50 MxBool m_unk0x50; // 0x50
undefined2 m_unk0x52; // 0x52 MxS16 m_unk0x52; // 0x52
undefined2 m_unk0x54; // 0x54 MxS16 m_unk0x54; // 0x54
undefined2 m_unk0x56; // 0x56 MxS16 m_unk0x56; // 0x56
MxS16* m_unk0x58; // 0x58 MxS16* m_states; // 0x58
}; };
// SYNTHETIC: LEGO1 0x100440f0 // SYNTHETIC: LEGO1 0x100440f0

View file

@ -163,6 +163,7 @@ void MxBackgroundAudioManager::FUN_1007ef40()
} }
// FUNCTION: LEGO1 0x1007f0e0 // FUNCTION: LEGO1 0x1007f0e0
// FUNCTION: BETA10 0x100e8d8d
void MxBackgroundAudioManager::FadeInOrFadeOut() void MxBackgroundAudioManager::FadeInOrFadeOut()
{ {
MxS32 volume, compare; MxS32 volume, compare;
@ -178,12 +179,10 @@ void MxBackgroundAudioManager::FadeInOrFadeOut()
} }
if (volume < compare) { if (volume < compare) {
volume = Min(volume + m_speed, compare); m_unk0xa0->SetVolume(volume + m_speed < compare ? volume + m_speed : compare);
m_unk0xa0->SetVolume(volume);
} }
else if (compare < volume) { else if (compare < volume) {
volume = Max(volume - m_speed, compare); m_unk0xa0->SetVolume(volume - m_speed > compare ? volume - m_speed : compare);
m_unk0xa0->SetVolume(volume);
} }
else { else {
m_unk0xa0->SetVolume(volume); m_unk0xa0->SetVolume(volume);

View file

@ -4,12 +4,13 @@
#include "legocontrolmanager.h" #include "legocontrolmanager.h"
#include "mxdsmultiaction.h" #include "mxdsmultiaction.h"
#include "mxmisc.h" #include "mxmisc.h"
#include "mxstillpresenter.h"
#include "mxticklemanager.h" #include "mxticklemanager.h"
#include "mxtimer.h" #include "mxtimer.h"
#include "mxutilities.h" #include "mxutilities.h"
#include "mxvideopresenter.h"
#include <SDL3/SDL_stdinc.h> #include <SDL3/SDL_stdinc.h>
#include <assert.h>
DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c)
@ -20,15 +21,15 @@ MxControlPresenter::MxControlPresenter()
m_unk0x4e = -1; m_unk0x4e = -1;
m_unk0x50 = FALSE; m_unk0x50 = FALSE;
m_unk0x52 = 0; m_unk0x52 = 0;
m_unk0x58 = 0; m_states = NULL;
m_unk0x54 = 0; m_unk0x54 = 0;
} }
// FUNCTION: LEGO1 0x10044110 // FUNCTION: LEGO1 0x10044110
MxControlPresenter::~MxControlPresenter() MxControlPresenter::~MxControlPresenter()
{ {
if (m_unk0x58) { if (m_states) {
delete m_unk0x58; delete m_states;
} }
} }
@ -74,46 +75,41 @@ void MxControlPresenter::EndAction()
// FUNCTION: LEGO1 0x10044270 // FUNCTION: LEGO1 0x10044270
// FUNCTION: BETA10 0x100eae68 // FUNCTION: BETA10 0x100eae68
MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter) MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter)
{ {
assert(p_presenter);
MxStillPresenter* presenter = (MxStillPresenter*) p_presenter;
if (m_unk0x4c == 3) { if (m_unk0x4c == 3) {
MxVideoPresenter* frontPresenter = (MxVideoPresenter*) m_list.front(); MxStillPresenter* map = (MxStillPresenter*) m_list.front();
assert(map && map->IsA("MxStillPresenter"));
if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < p_presenter->GetDisplayZ()) { if (presenter == map || map->GetDisplayZ() < presenter->GetDisplayZ()) {
if (p_presenter->VTable0x7c()) { if (map->VTable0x7c()) {
MxS32 height = frontPresenter->GetHeight(); MxRect32 rect(0, 0, map->GetWidth() - 1, map->GetHeight() - 1);
MxS32 width = frontPresenter->GetWidth(); rect += map->GetLocation();
if (frontPresenter->GetLocation().GetX() <= p_x && if (rect.GetLeft() <= p_x && p_x < rect.GetRight() && rect.GetTop() <= p_y && p_y < rect.GetBottom()) {
p_x < width - 1 + frontPresenter->GetLocation().GetX() && // DECOMP: Beta uses GetBitmapStart() here, but that causes more diffs for retail.
frontPresenter->GetLocation().GetY() <= p_y && MxU8* start = map->GetAlphaMask()
p_y < height - 1 + frontPresenter->GetLocation().GetY()) { ? NULL
MxU8* start; : map->GetBitmap()->GetStart(p_x - rect.GetLeft(), p_y - rect.GetTop());
if (frontPresenter->GetAlphaMask() == NULL) {
start = frontPresenter->GetBitmap()->GetStart(
p_x - frontPresenter->GetLocation().GetX(),
p_y - frontPresenter->GetLocation().GetY()
);
}
else {
start = NULL;
}
m_unk0x56 = 0; m_unk0x56 = 0;
if (m_unk0x58 == NULL) { if (m_states) {
if (*start != 0) { for (MxS16 i = 1; i <= *m_states; i++) {
m_unk0x56 = 1; // TODO: Can we match without the cast here?
} if (m_states[i] == (MxS16) *start) {
}
else {
for (MxS16 i = 1; i <= *m_unk0x58; i++) {
if (m_unk0x58[i] == *start) {
m_unk0x56 = i; m_unk0x56 = i;
break; break;
} }
} }
} }
else {
if (*start != 0) {
m_unk0x56 = 1;
}
}
if (m_unk0x56) { if (m_unk0x56) {
return TRUE; return TRUE;
@ -123,29 +119,18 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter*
} }
} }
else { else {
if (ContainsPresenter(m_list, p_presenter)) { if (ContainsPresenter(m_list, presenter)) {
if (m_unk0x4c == 2) { if (m_unk0x4c == 2) {
MxS32 width = p_presenter->GetWidth(); MxS32 width = presenter->GetWidth();
MxS32 height = p_presenter->GetHeight(); MxS32 height = presenter->GetHeight();
if (m_unk0x52 == 2 && m_unk0x54 == 2) { if (m_unk0x52 == 2 && m_unk0x54 == 2) {
MxS16 val; if (p_x < presenter->GetX() + width / 2) {
if (p_x < p_presenter->GetLocation().GetX() + width / 2) { m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 3 : 1;
val = 3;
if (p_y < p_presenter->GetLocation().GetY() + height / 2) {
val = 1;
}
m_unk0x56 = val;
return TRUE;
} }
else {
val = 4; m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 4 : 2;
if (p_y < p_presenter->GetLocation().GetY() + height / 2) {
val = 2;
} }
m_unk0x56 = val;
return TRUE;
} }
} }
else { else {
@ -175,7 +160,7 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerNotificationParam* p_p
} }
break; break;
case c_notificationButtonDown: case c_notificationButtonDown:
if (FUN_10044270(p_param->GetX(), p_param->GetY(), (MxVideoPresenter*) p_presenter)) { if (FUN_10044270(p_param->GetX(), p_param->GetY(), p_presenter)) {
p_param->SetClickedObjectId(m_action->GetObjectId()); p_param->SetClickedObjectId(m_action->GetObjectId());
p_param->SetClickedAtom(m_action->GetAtomId().GetInternal()); p_param->SetClickedAtom(m_action->GetAtomId().GetInternal());
VTable0x6c(m_unk0x56); VTable0x6c(m_unk0x56);
@ -223,6 +208,7 @@ void MxControlPresenter::ReadyTickle()
} }
// FUNCTION: LEGO1 0x10044640 // FUNCTION: LEGO1 0x10044640
// FUNCTION: BETA10 0x100eb5e3
void MxControlPresenter::ParseExtra() void MxControlPresenter::ParseExtra()
{ {
MxU16 extraLength; MxU16 extraLength;
@ -236,27 +222,35 @@ void MxControlPresenter::ParseExtra()
char output[256]; char output[256];
if (KeyValueStringParse(output, g_strSTYLE, extraCopy)) { if (KeyValueStringParse(output, g_strSTYLE, extraCopy)) {
char* str = strtok(output, g_parseExtraTokens); char* token = strtok(output, g_parseExtraTokens);
if (!SDL_strcasecmp(str, g_strTOGGLE)) { if (!SDL_strcasecmp(token, g_strTOGGLE)) {
m_unk0x4c = 1; m_unk0x4c = 1;
} }
else if (!SDL_strcasecmp(str, g_strGRID)) { else if (!SDL_strcasecmp(token, g_strGRID)) {
m_unk0x4c = 2; m_unk0x4c = 2;
m_unk0x52 = atoi(strtok(NULL, g_parseExtraTokens)); token = strtok(NULL, g_parseExtraTokens);
m_unk0x54 = atoi(strtok(NULL, g_parseExtraTokens)); assert(token);
m_unk0x52 = atoi(token);
token = strtok(NULL, g_parseExtraTokens);
assert(token);
m_unk0x54 = atoi(token);
} }
else if (!SDL_strcasecmp(str, g_strMAP)) { else if (!SDL_strcasecmp(token, g_strMAP)) {
m_unk0x4c = 3; m_unk0x4c = 3;
str = strtok(NULL, g_parseExtraTokens); token = strtok(NULL, g_parseExtraTokens);
if (str) { if (token) {
MxS16 count = atoi(str); MxS16 numStates = atoi(token);
m_unk0x58 = new MxS16[count + 1]; m_states = new MxS16[numStates + 1];
*m_unk0x58 = count; assert(numStates);
*m_states = numStates;
for (MxS16 i = 1; i <= count; i++) { for (MxS16 i = 1; i <= numStates; i++) {
m_unk0x58[i] = atoi(strtok(NULL, g_parseExtraTokens)); token = strtok(NULL, g_parseExtraTokens);
assert(token);
m_states[i] = atoi(token);
} }
} }
} }
@ -298,9 +292,14 @@ void MxControlPresenter::Enable(MxBool p_enable)
// FUNCTION: LEGO1 0x100448a0 // FUNCTION: LEGO1 0x100448a0
MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState)
{ {
MxCompositePresenterList::iterator it = m_list.begin(); MxCompositePresenterList::const_iterator it = m_list.begin();
for (MxS16 i = m_unk0x4e; i > 0; i--, it++) {
} #ifdef COMPAT_MODE
advance(it, m_unk0x4e);
#else
// Uses forward iterator logic instead of bidrectional for some reason.
_Advance(it, m_unk0x4e, forward_iterator_tag());
#endif
return (*it)->HasTickleStatePassed(p_tickleState); return (*it)->HasTickleStatePassed(p_tickleState);
} }

View file

@ -144,12 +144,13 @@ void LegoControlManager::FUN_100293c0(MxU32 p_objectId, const char* p_atom, MxS1
} }
// FUNCTION: LEGO1 0x100294e0 // FUNCTION: LEGO1 0x100294e0
// FUNCTION: BETA10 0x1007c92f
MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y) MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y)
{ {
if (m_presenterList) { if (m_presenterList) {
MxPresenterListCursor cursor(m_presenterList); MxPresenterListCursor cursor(m_presenterList);
MxPresenter* control; MxPresenter* control;
MxVideoPresenter* presenter = (MxVideoPresenter*) VideoManager()->GetPresenterAt(p_x, p_y); MxPresenter* presenter = VideoManager()->GetPresenterAt(p_x, p_y);
if (presenter) { if (presenter) {
while (cursor.Next(control)) { while (cursor.Next(control)) {

View file

@ -118,8 +118,7 @@ void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time)
if (boundary != NULL) { if (boundary != NULL) {
newB = data->FUN_100a0990(p_time); newB = data->FUN_100a0990(p_time);
boundary->GetFlag0x10(); previousB = boundary->GetFlag0x10();
// TODO: Match
boundary->SetFlag0x10(newB); boundary->SetFlag0x10(newB);
} }
} }

View file

@ -189,6 +189,7 @@ public:
// FUNCTION: BETA10 0x1005abc0 // FUNCTION: BETA10 0x1005abc0
LegoU16 GetUnknown0x20() { return m_unk0x20; } LegoU16 GetUnknown0x20() { return m_unk0x20; }
// FUNCTION: BETA10 0x1005d5c0
LegoU16 GetUnknown0x22() { return m_unk0x22; } LegoU16 GetUnknown0x22() { return m_unk0x22; }
// FUNCTION: BETA10 0x10073b80 // FUNCTION: BETA10 0x10073b80
@ -222,6 +223,8 @@ public:
{ {
return CreateLocalTransform((LegoFloat) p_time, p_matrix); return CreateLocalTransform((LegoFloat) p_time, p_matrix);
} }
// FUNCTION: BETA10 0x1005d580
LegoBool FUN_100a0990(LegoTime p_time) { return FUN_100a0990((LegoFloat) p_time); } LegoBool FUN_100a0990(LegoTime p_time) { return FUN_100a0990((LegoFloat) p_time); }
inline static void GetTranslation( inline static void GetTranslation(

View file

@ -45,7 +45,15 @@ public:
LegoS32 VTable0x04() override; // vtable+0x04 LegoS32 VTable0x04() override; // vtable+0x04
// FUNCTION: BETA10 0x100270c0 // FUNCTION: BETA10 0x100270c0
LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } LegoU32 GetFlag0x10()
{
if (m_flags & c_bit5) {
return FALSE;
}
else {
return TRUE;
}
}
// TODO: Other BETA10 reference at 0x1001c9e0, not sure what is going on // TODO: Other BETA10 reference at 0x1001c9e0, not sure what is going on
// FUNCTION: BETA10 0x1001ff80 // FUNCTION: BETA10 0x1001ff80
@ -57,6 +65,7 @@ public:
// FUNCTION: BETA10 0x1001c9b0 // FUNCTION: BETA10 0x1001c9b0
const LegoChar* GetName() { return m_name; } const LegoChar* GetName() { return m_name; }
// FUNCTION: BETA10 0x1005d5f0
void SetFlag0x10(LegoU32 p_disable) void SetFlag0x10(LegoU32 p_disable)
{ {
if (p_disable) { if (p_disable) {

View file

@ -13,21 +13,24 @@ DECOMP_SIZE_ASSERT(MxDirect3D, 0x894)
} }
// FUNCTION: LEGO1 0x1009b0a0 // FUNCTION: LEGO1 0x1009b0a0
// FUNCTION: BETA10 0x1011b220
MxDirect3D::MxDirect3D() MxDirect3D::MxDirect3D()
{ {
this->m_pDirect3d = NULL; m_pDirect3d = NULL;
this->m_pDirect3dDevice = NULL; m_pDirect3dDevice = NULL;
this->m_bTexturesDisabled = FALSE; m_bTexturesDisabled = FALSE;
this->m_assignedDevice = NULL; m_currentDeviceInfo = NULL;
} }
// FUNCTION: LEGO1 0x1009b140 // FUNCTION: LEGO1 0x1009b140
// FUNCTION: BETA10 0x1011b2c3
MxDirect3D::~MxDirect3D() MxDirect3D::~MxDirect3D()
{ {
Destroy(); Destroy();
} }
// FUNCTION: LEGO1 0x1009b1a0 // FUNCTION: LEGO1 0x1009b1a0
// FUNCTION: BETA10 0x1011b333
BOOL MxDirect3D::Create( BOOL MxDirect3D::Create(
HWND hWnd, HWND hWnd,
BOOL fullscreen_1, BOOL fullscreen_1,
@ -41,29 +44,33 @@ BOOL MxDirect3D::Create(
) )
{ {
BOOL success = FALSE; BOOL success = FALSE;
BOOL ret = MxDirectDraw::Create( assert(m_currentDeviceInfo);
hWnd,
fullscreen_1,
surface_fullscreen,
onlySystemMemory,
width,
height,
bpp,
pPaletteEntries,
paletteEntryCount
);
if (!ret) { if (!MxDirectDraw::Create(
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirectDraw::Create failed"); hWnd,
fullscreen_1,
surface_fullscreen,
onlySystemMemory,
width,
height,
bpp,
pPaletteEntries,
paletteEntryCount
)) {
goto done;
} }
if (ret && D3DCreate() && D3DSetMode()) { if (!D3DCreate()) {
success = TRUE; goto done;
}
else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "D3DCreate()/D3DSetMode failed");
} }
if (!D3DSetMode()) {
goto done;
}
success = TRUE;
done:
if (!success) { if (!success) {
FUN_1009d920(); FUN_1009d920();
} }
@ -72,24 +79,26 @@ BOOL MxDirect3D::Create(
} }
// FUNCTION: LEGO1 0x1009b210 // FUNCTION: LEGO1 0x1009b210
// FUNCTION: BETA10 0x1011b41d
void MxDirect3D::Destroy() void MxDirect3D::Destroy()
{ {
RELEASE(m_pDirect3dDevice); RELEASE(m_pDirect3dDevice);
RELEASE(m_pDirect3d); RELEASE(m_pDirect3d);
if (this->m_assignedDevice) { if (m_currentDeviceInfo) {
delete m_assignedDevice; delete m_currentDeviceInfo;
this->m_assignedDevice = NULL; m_currentDeviceInfo = NULL;
} }
if (m_pCurrentDeviceModesList) { if (m_currentDevInfo) {
m_pCurrentDeviceModesList = NULL; m_currentDevInfo = NULL;
} }
MxDirectDraw::Destroy(); MxDirectDraw::Destroy();
} }
// FUNCTION: LEGO1 0x1009b290 // FUNCTION: LEGO1 0x1009b290
// FUNCTION: BETA10 0x1011b50a
void MxDirect3D::DestroyButNotDirectDraw() void MxDirect3D::DestroyButNotDirectDraw()
{ {
RELEASE(m_pDirect3dDevice); RELEASE(m_pDirect3dDevice);
@ -98,6 +107,7 @@ void MxDirect3D::DestroyButNotDirectDraw()
} }
// FUNCTION: LEGO1 0x1009b2d0 // FUNCTION: LEGO1 0x1009b2d0
// FUNCTION: BETA10 0x1011b592
BOOL MxDirect3D::D3DCreate() BOOL MxDirect3D::D3DCreate()
{ {
HRESULT result; HRESULT result;
@ -111,46 +121,50 @@ BOOL MxDirect3D::D3DCreate()
} }
// FUNCTION: LEGO1 0x1009b310 // FUNCTION: LEGO1 0x1009b310
// FUNCTION: BETA10 0x1011b617
BOOL MxDirect3D::D3DSetMode() BOOL MxDirect3D::D3DSetMode()
{ {
if (m_assignedDevice->m_flags & MxAssignedDevice::c_hardwareMode) { assert(m_currentDeviceInfo);
if (m_currentDeviceInfo->m_flags & MxAssignedDevice::c_hardwareMode) {
if (m_bOnlySoftRender) { if (m_bOnlySoftRender) {
Error("Failed to place vital surfaces in video memory for hardware driver", DDERR_GENERIC); Error("Failed to place vital surfaces in video memory for hardware driver", DDERR_GENERIC);
return FALSE; return FALSE;
} }
if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { if (m_currentDeviceInfo->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) {
m_bTexturesDisabled = FALSE; m_bTexturesDisabled = FALSE;
} }
else { else {
m_bTexturesDisabled = TRUE; m_bTexturesDisabled = TRUE;
} }
if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_assignedDevice))) { if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_currentDeviceInfo))) {
return FALSE; return FALSE;
} }
} }
else { else {
if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { if (m_currentDeviceInfo->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) {
m_bTexturesDisabled = FALSE; m_bTexturesDisabled = FALSE;
} }
else { else {
m_bTexturesDisabled = TRUE; m_bTexturesDisabled = TRUE;
} }
if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_assignedDevice))) { if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_currentDeviceInfo))) {
return FALSE; return FALSE;
} }
} }
HRESULT result = m_pDirect3d->CreateDevice(m_assignedDevice->m_guid, m_pBackBuffer, &m_pDirect3dDevice); LPDIRECTDRAWSURFACE backBuf = BackBuffer();
HRESULT result = m_pDirect3d->CreateDevice(m_currentDeviceInfo->m_guid, backBuf, &m_pDirect3dDevice);
if (result != DD_OK) { if (result != DD_OK) {
Error("Create D3D device failed", result); Error("Create D3D device failed", result);
return FALSE; return FALSE;
} }
DeviceModesInfo::Mode mode = m_currentMode; DeviceModesInfo::Mode mode = *CurrentMode();
if (IsFullScreen()) { if (IsFullScreen()) {
if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) {
@ -159,8 +173,8 @@ BOOL MxDirect3D::D3DSetMode()
} }
} }
LPDIRECTDRAWSURFACE frontBuffer = m_pFrontBuffer; LPDIRECTDRAWSURFACE frontBuffer = FrontBuffer();
LPDIRECTDRAWSURFACE backBuffer = m_pBackBuffer; LPDIRECTDRAWSURFACE backBuffer = BackBuffer();
DDSURFACEDESC desc; DDSURFACEDESC desc;
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
@ -169,7 +183,7 @@ BOOL MxDirect3D::D3DSetMode()
if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) {
unsigned char* surface = (unsigned char*) desc.lpSurface; unsigned char* surface = (unsigned char*) desc.lpSurface;
for (int i = mode.height; i > 0; i--) { for (int i = 0; i < mode.height; i++) {
memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8);
surface += desc.lPitch; surface += desc.lPitch;
} }
@ -180,14 +194,14 @@ BOOL MxDirect3D::D3DSetMode()
SDL_Log("MxDirect3D::D3DSetMode() back lock failed\n"); SDL_Log("MxDirect3D::D3DSetMode() back lock failed\n");
} }
if (m_bFullScreen) { if (IsFullScreen()) {
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) {
unsigned char* surface = (unsigned char*) desc.lpSurface; unsigned char* surface = (unsigned char*) desc.lpSurface;
for (int i = mode.height; i > 0; i--) { for (int i = 0; i < mode.height; i++) {
memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8);
surface += desc.lPitch; surface += desc.lPitch;
} }
@ -203,6 +217,7 @@ BOOL MxDirect3D::D3DSetMode()
} }
// FUNCTION: LEGO1 0x1009b5a0 // FUNCTION: LEGO1 0x1009b5a0
// FUNCTION: BETA10 0x1011babb
int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice) int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice)
{ {
int depth; int depth;
@ -238,10 +253,10 @@ int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice)
// FUNCTION: BETA10 0x1011bbca // FUNCTION: BETA10 0x1011bbca
BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device) BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device)
{ {
if (m_assignedDevice) { if (m_currentDeviceInfo) {
delete m_assignedDevice; delete m_currentDeviceInfo;
m_assignedDevice = NULL; m_currentDeviceInfo = NULL;
m_pCurrentDeviceModesList = NULL; m_currentDevInfo = NULL;
} }
MxAssignedDevice* d = new MxAssignedDevice; MxAssignedDevice* d = new MxAssignedDevice;
@ -295,15 +310,15 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri
d->m_desc = device.m_HELDesc; d->m_desc = device.m_HELDesc;
} }
m_assignedDevice = d; m_currentDeviceInfo = d;
m_pCurrentDeviceModesList = d->m_deviceInfo; m_currentDevInfo = d->m_deviceInfo;
break; break;
} }
} }
} }
} }
if (!m_assignedDevice) { if (!m_currentDeviceInfo) {
delete d; delete d;
return FALSE; return FALSE;
} }

View file

@ -9,6 +9,7 @@
#include <d3d.h> #include <d3d.h>
// VTABLE: LEGO1 0x100db800 // VTABLE: LEGO1 0x100db800
// VTABLE: BETA10 0x101c1af8
// SIZE 0x894 // SIZE 0x894
class MxDirect3D : public MxDirectDraw { class MxDirect3D : public MxDirectDraw {
public: public:
@ -29,9 +30,13 @@ public:
void Destroy() override; // vtable+0x08 void Destroy() override; // vtable+0x08
void DestroyButNotDirectDraw() override; // vtable+0x0c void DestroyButNotDirectDraw() override; // vtable+0x0c
MxAssignedDevice* AssignedDevice() { return this->m_assignedDevice; } MxAssignedDevice* AssignedDevice() { return m_currentDeviceInfo; }
IDirect3D2* Direct3D() { return this->m_pDirect3d; }
IDirect3DDevice2* Direct3DDevice() { return this->m_pDirect3dDevice; } // FUNCTION: BETA10 0x100d8b40
IDirect3D2* Direct3D() { return m_pDirect3d; }
// FUNCTION: BETA10 0x100d8b70
IDirect3DDevice2* Direct3DDevice() { return m_pDirect3dDevice; }
BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device); BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device);
@ -42,14 +47,19 @@ protected:
int ZBufferDepth(MxAssignedDevice* p_assignedDevice); int ZBufferDepth(MxAssignedDevice* p_assignedDevice);
// SYNTHETIC: LEGO1 0x1009b120 // SYNTHETIC: LEGO1 0x1009b120
// SYNTHETIC: BETA10 0x1011c0f0
// MxDirect3D::`scalar deleting destructor' // MxDirect3D::`scalar deleting destructor'
private: private:
MxAssignedDevice* m_assignedDevice; // 0x880 MxAssignedDevice* m_currentDeviceInfo; // 0x880
IDirect3D2* m_pDirect3d; // 0x884 IDirect3D2* m_pDirect3d; // 0x884
IDirect3DDevice2* m_pDirect3dDevice; // 0x888 IDirect3DDevice2* m_pDirect3dDevice; // 0x888
BOOL m_bTexturesDisabled; // 0x88c BOOL m_bTexturesDisabled; // 0x88c
undefined4 m_unk0x890; // 0x890 undefined4 m_unk0x890; // 0x890
}; };
// GLOBAL: LEGO1 0x100dd1b0
// GLOBAL: BETA10 0x101c2de8
// IID_IDirect3D2
#endif // MXDIRECT3D_H #endif // MXDIRECT3D_H

View file

@ -3,6 +3,7 @@
#include "decomp.h" #include "decomp.h"
#include <SDL3/SDL_log.h> #include <SDL3/SDL_log.h>
#include <assert.h>
DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880) DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880)
@ -17,9 +18,11 @@ DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880)
#endif #endif
// GLOBAL: LEGO1 0x10100c68 // GLOBAL: LEGO1 0x10100c68
// GLOBAL: BETA10 0x101ff1c4
BOOL g_isPaletteIndexed8 = 0; BOOL g_isPaletteIndexed8 = 0;
// FUNCTION: LEGO1 0x1009d490 // FUNCTION: LEGO1 0x1009d490
// FUNCTION: BETA10 0x1012036a
MxDirectDraw::MxDirectDraw() MxDirectDraw::MxDirectDraw()
{ {
m_pFrontBuffer = NULL; m_pFrontBuffer = NULL;
@ -28,6 +31,7 @@ MxDirectDraw::MxDirectDraw()
m_pClipper = NULL; m_pClipper = NULL;
m_pPalette = NULL; m_pPalette = NULL;
m_pDirectDraw = NULL; m_pDirectDraw = NULL;
m_bIsOnPrimaryDevice = TRUE;
m_pText1Surface = NULL; m_pText1Surface = NULL;
m_pText2Surface = NULL; m_pText2Surface = NULL;
m_hWndMain = NULL; m_hWndMain = NULL;
@ -41,32 +45,31 @@ MxDirectDraw::MxDirectDraw()
m_pFatalErrorHandler = NULL; m_pFatalErrorHandler = NULL;
m_pErrorHandlerArg = NULL; m_pErrorHandlerArg = NULL;
m_pFatalErrorHandlerArg = NULL; m_pFatalErrorHandlerArg = NULL;
m_pCurrentDeviceModesList = NULL; m_currentDevInfo = NULL;
m_bIsOnPrimaryDevice = TRUE;
m_hFont = NULL; m_hFont = NULL;
} }
// FUNCTION: LEGO1 0x1009d530 // FUNCTION: LEGO1 0x1009d530
// FUNCTION: BETA10 0x1012048f
MxDirectDraw::~MxDirectDraw() MxDirectDraw::~MxDirectDraw()
{ {
Destroy(); Destroy();
if (m_pCurrentDeviceModesList != NULL) { if (m_currentDevInfo != NULL) {
delete m_pCurrentDeviceModesList; delete m_currentDevInfo;
m_pCurrentDeviceModesList = NULL; m_currentDevInfo = NULL;
} }
} }
// FUNCTION: LEGO1 0x1009d570 // FUNCTION: LEGO1 0x1009d570
// FUNCTION: BETA10 0x101204fe
int MxDirectDraw::GetPrimaryBitDepth() int MxDirectDraw::GetPrimaryBitDepth()
{ {
DWORD dwRGBBitCount; DWORD dwRGBBitCount = 8;
LPDIRECTDRAW pDDraw; LPDIRECTDRAW pDDraw;
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
HRESULT result = DirectDrawCreate(NULL, &pDDraw, NULL); if (!DirectDrawCreate(NULL, &pDDraw, NULL)) {
dwRGBBitCount = 8;
if (!result) {
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
@ -80,6 +83,7 @@ int MxDirectDraw::GetPrimaryBitDepth()
} }
// FUNCTION: LEGO1 0x1009d5e0 // FUNCTION: LEGO1 0x1009d5e0
// FUNCTION: BETA10 0x1012058c
BOOL MxDirectDraw::Create( BOOL MxDirectDraw::Create(
HWND hWnd, HWND hWnd,
BOOL fullscreen, BOOL fullscreen,
@ -92,17 +96,19 @@ BOOL MxDirectDraw::Create(
int paletteEntryCount int paletteEntryCount
) )
{ {
assert(m_currentDevInfo);
m_hWndMain = hWnd; m_hWndMain = hWnd;
CacheOriginalPaletteEntries(); CacheOriginalPaletteEntries();
if (!RecreateDirectDraw(&m_pCurrentDeviceModesList->m_guid)) { if (!RecreateDirectDraw(&m_currentDevInfo->m_guid)) {
return FALSE; return FALSE;
} }
m_bFlipSurfaces = surface_fullscreen; m_bFlipSurfaces = surface_fullscreen;
m_bOnlySystemMemory = onlySystemMemory; m_bOnlySystemMemory = onlySystemMemory;
m_bIsOnPrimaryDevice = !m_pCurrentDeviceModesList->m_guid; m_bIsOnPrimaryDevice = m_currentDevInfo->m_guid ? FALSE : TRUE;
if (!m_bIsOnPrimaryDevice) { if (!m_bIsOnPrimaryDevice) {
fullscreen = TRUE; fullscreen = TRUE;
@ -124,6 +130,7 @@ BOOL MxDirectDraw::Create(
} }
// FUNCTION: LEGO1 0x1009d690 // FUNCTION: LEGO1 0x1009d690
// FUNCTION: BETA10 0x101206ca
BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID) BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID)
{ {
RELEASE(m_pDirectDraw); RELEASE(m_pDirectDraw);
@ -131,6 +138,7 @@ BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID)
} }
// FUNCTION: LEGO1 0x1009d6c0 // FUNCTION: LEGO1 0x1009d6c0
// FUNCTION: BETA10 0x10120733
BOOL MxDirectDraw::CacheOriginalPaletteEntries() BOOL MxDirectDraw::CacheOriginalPaletteEntries()
{ {
HDC hdc; HDC hdc;
@ -144,11 +152,9 @@ BOOL MxDirectDraw::CacheOriginalPaletteEntries()
} }
// FUNCTION: LEGO1 0x1009d700 // FUNCTION: LEGO1 0x1009d700
// FUNCTION: BETA10 0x1012078c
BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen) BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen)
{ {
int reservedLowEntryCount = 10;
int reservedHighEntryCount = 10;
int arraySize = sizeOfArray(m_paletteEntries);
HDC hdc; HDC hdc;
int i; int i;
@ -158,24 +164,26 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa
ReleaseDC(NULL, hdc); ReleaseDC(NULL, hdc);
} }
for (i = 0; i < reservedLowEntryCount; i++) { for (i = 0; i < 10; i++) {
m_paletteEntries[i].peFlags = 0x80; m_paletteEntries[i].peFlags = 0x80;
} }
for (i = reservedLowEntryCount; i < 142; i++) { for (; i < 142; i++) {
m_paletteEntries[i].peFlags = 0x44; m_paletteEntries[i].peFlags = 0x44;
} }
for (i = 142; i < arraySize - reservedHighEntryCount; i++) { for (; i < 246; i++) {
m_paletteEntries[i].peFlags = 0x84; m_paletteEntries[i].peFlags = 0x84;
} }
for (i = 256 - reservedHighEntryCount; i < 256; i++) { for (; i < 256; i++) {
m_paletteEntries[i].peFlags = 0x80; m_paletteEntries[i].peFlags = 0x80;
} }
if (paletteEntryCount != 0) { if (paletteEntryCount != 0) {
for (i = reservedLowEntryCount; (i < paletteEntryCount) && (i < 256 - reservedHighEntryCount); i++) { assert(paletteEntryCount <= (sizeof(m_paletteEntries) / sizeof(m_paletteEntries[0])));
for (i = 10; (i < paletteEntryCount) && (i < 246); i++) {
m_paletteEntries[i].peRed = pPaletteEntries[i].peRed; m_paletteEntries[i].peRed = pPaletteEntries[i].peRed;
m_paletteEntries[i].peGreen = pPaletteEntries[i].peGreen; m_paletteEntries[i].peGreen = pPaletteEntries[i].peGreen;
m_paletteEntries[i].peBlue = pPaletteEntries[i].peBlue; m_paletteEntries[i].peBlue = pPaletteEntries[i].peBlue;
@ -196,6 +204,7 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa
} }
// FUNCTION: LEGO1 0x1009d800 // FUNCTION: LEGO1 0x1009d800
// FUNCTION: BETA10 0x10120971
void MxDirectDraw::Destroy() void MxDirectDraw::Destroy()
{ {
DestroyButNotDirectDraw(); DestroyButNotDirectDraw();
@ -206,13 +215,14 @@ void MxDirectDraw::Destroy()
m_bIsOnPrimaryDevice = TRUE; m_bIsOnPrimaryDevice = TRUE;
if (m_pCurrentDeviceModesList != NULL) { if (m_currentDevInfo != NULL) {
delete m_pCurrentDeviceModesList; delete m_currentDevInfo;
m_pCurrentDeviceModesList = NULL; m_currentDevInfo = NULL;
} }
} }
// FUNCTION: LEGO1 0x1009d860 // FUNCTION: LEGO1 0x1009d860
// FUNCTION: BETA10 0x10120a18
void MxDirectDraw::DestroyButNotDirectDraw() void MxDirectDraw::DestroyButNotDirectDraw()
{ {
RestoreOriginalPaletteEntries(); RestoreOriginalPaletteEntries();
@ -234,6 +244,7 @@ void MxDirectDraw::DestroyButNotDirectDraw()
} }
// FUNCTION: LEGO1 0x1009d920 // FUNCTION: LEGO1 0x1009d920
// FUNCTION: BETA10 0x10120b9e
void MxDirectDraw::FUN_1009d920() void MxDirectDraw::FUN_1009d920()
{ {
RestoreOriginalPaletteEntries(); RestoreOriginalPaletteEntries();
@ -246,8 +257,11 @@ void MxDirectDraw::FUN_1009d920()
} }
// FUNCTION: LEGO1 0x1009d960 // FUNCTION: LEGO1 0x1009d960
// FUNCTION: BETA10 0x10120d61
BOOL MxDirectDraw::DDInit(BOOL fullscreen) BOOL MxDirectDraw::DDInit(BOOL fullscreen)
{ {
assert(m_pDirectDraw);
HRESULT result; HRESULT result;
if (fullscreen) { if (fullscreen) {
@ -270,12 +284,15 @@ BOOL MxDirectDraw::DDInit(BOOL fullscreen)
} }
// FUNCTION: LEGO1 0x1009d9d0 // FUNCTION: LEGO1 0x1009d9d0
// FUNCTION: BETA10 0x10120e45
BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp) BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp)
{ {
DeviceModesInfo::Mode mode = {width, height, bpp}; DeviceModesInfo::Mode mode = {width, height, bpp};
for (int i = 0; i < m_pCurrentDeviceModesList->m_count; i++) { assert(m_currentDevInfo);
if (m_pCurrentDeviceModesList->m_modeArray[i] == mode) {
for (int i = 0; i < m_currentDevInfo->m_count; i++) {
if (m_currentDevInfo->m_modeArray[i] == mode) {
return TRUE; return TRUE;
} }
} }
@ -284,6 +301,7 @@ BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp)
} }
// FUNCTION: LEGO1 0x1009da20 // FUNCTION: LEGO1 0x1009da20
// FUNCTION: BETA10 0x10120efb
void EnableResizing(HWND p_hwnd, BOOL p_flag) void EnableResizing(HWND p_hwnd, BOOL p_flag)
{ {
static DWORD g_dwStyle; static DWORD g_dwStyle;
@ -300,17 +318,17 @@ void EnableResizing(HWND p_hwnd, BOOL p_flag)
} }
// FUNCTION: LEGO1 0x1009da80 // FUNCTION: LEGO1 0x1009da80
// FUNCTION: BETA10 0x10120f68
BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp)
{ {
HRESULT result; HRESULT result;
if (m_bFullScreen) { if (m_bFullScreen) {
LPDIRECTDRAW lpDD;
EnableResizing(m_hWndMain, FALSE); EnableResizing(m_hWndMain, FALSE);
#ifndef BETA10
if (!m_bIsOnPrimaryDevice) { if (!m_bIsOnPrimaryDevice) {
lpDD = NULL; LPDIRECTDRAW lpDD = NULL;
result = DirectDrawCreate(0, &lpDD, 0); result = DirectDrawCreate(0, &lpDD, 0);
if (result == DD_OK) { if (result == DD_OK) {
result = lpDD->SetCooperativeLevel(m_hWndMain, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT); result = lpDD->SetCooperativeLevel(m_hWndMain, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
@ -319,11 +337,12 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp)
} }
} }
} }
#endif
if (!IsSupportedMode(width, height, bpp)) { if (!IsSupportedMode(width, height, bpp)) {
width = m_pCurrentDeviceModesList->m_modeArray[0].width; width = m_currentDevInfo->m_modeArray[0].width;
height = m_pCurrentDeviceModesList->m_modeArray[0].height; height = m_currentDevInfo->m_modeArray[0].height;
bpp = m_pCurrentDeviceModesList->m_modeArray[0].bitsPerPixel; bpp = m_currentDevInfo->m_modeArray[0].bitsPerPixel;
} }
m_bIgnoreWMSIZE = TRUE; m_bIgnoreWMSIZE = TRUE;
@ -414,20 +433,29 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp)
} }
// create debug text only in windowed mode? // create debug text only in windowed mode?
return m_bFullScreen || CreateTextSurfaces(); if (!m_bFullScreen) {
if (!CreateTextSurfaces()) {
return FALSE;
}
}
return TRUE;
} }
// FUNCTION: LEGO1 0x1009dd80 // FUNCTION: LEGO1 0x1009dd80
// FUNCTION: BETA10 0x1012137f
HRESULT MxDirectDraw::CreateDDSurface( HRESULT MxDirectDraw::CreateDDSurface(
LPDDSURFACEDESC p_lpDDSurfDesc, LPDDSURFACEDESC p_lpDDSurfDesc,
LPDIRECTDRAWSURFACE FAR* p_lpDDSurface, LPDIRECTDRAWSURFACE FAR* p_lpDDSurface,
IUnknown FAR* p_pUnkOuter IUnknown FAR* p_pUnkOuter
) )
{ {
return m_pDirectDraw->CreateSurface(p_lpDDSurfDesc, p_lpDDSurface, p_pUnkOuter); HRESULT res = m_pDirectDraw->CreateSurface(p_lpDDSurfDesc, p_lpDDSurface, p_pUnkOuter);
return res;
} }
// FUNCTION: LEGO1 0x1009dda0 // FUNCTION: LEGO1 0x1009dda0
// FUNCTION: BETA10 0x101213bb
BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf) BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf)
{ {
HRESULT result; HRESULT result;
@ -443,6 +471,7 @@ BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSU
} }
// FUNCTION: LEGO1 0x1009ddf0 // FUNCTION: LEGO1 0x1009ddf0
// FUNCTION: BETA10 0x10121430
BOOL MxDirectDraw::DDCreateSurfaces() BOOL MxDirectDraw::DDCreateSurfaces()
{ {
HRESULT result; HRESULT result;
@ -520,13 +549,14 @@ BOOL MxDirectDraw::DDCreateSurfaces()
} }
// FUNCTION: LEGO1 0x1009e020 // FUNCTION: LEGO1 0x1009e020
// FUNCTION: BETA10 0x10121700
void MxDirectDraw::FUN_1009e020() void MxDirectDraw::FUN_1009e020()
{ {
HRESULT result; HRESULT result;
byte* line; byte* line;
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
int j;
int count = m_bFlipSurfaces ? 2 : 1; int count = m_bFlipSurfaces ? 2 : 1;
int value = 0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
@ -545,8 +575,8 @@ void MxDirectDraw::FUN_1009e020()
// clear backBuffer // clear backBuffer
line = (byte*) ddsd.lpSurface; line = (byte*) ddsd.lpSurface;
for (j = ddsd.dwHeight; j--;) { for (int j = ddsd.dwHeight; j--;) {
memset(line, 0, ddsd.dwWidth); memset(line, value, ddsd.dwWidth);
line += ddsd.lPitch; line += ddsd.lPitch;
} }
@ -559,6 +589,7 @@ void MxDirectDraw::FUN_1009e020()
} }
// FUNCTION: LEGO1 0x1009e110 // FUNCTION: LEGO1 0x1009e110
// FUNCTION: BETA10 0x101219de
BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface) BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface)
{ {
HRESULT result; HRESULT result;
@ -591,18 +622,21 @@ BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurf
} }
// FUNCTION: LEGO1 0x1009e210 // FUNCTION: LEGO1 0x1009e210
// FUNCTION: BETA10 0x10121aea
BOOL MxDirectDraw::TextToTextSurface1(const char* text) BOOL MxDirectDraw::TextToTextSurface1(const char* text)
{ {
return TextToTextSurface(text, m_pText1Surface, m_text1SizeOnSurface); return TextToTextSurface(text, m_pText1Surface, m_text1SizeOnSurface);
} }
// FUNCTION: LEGO1 0x1009e230 // FUNCTION: LEGO1 0x1009e230
// FUNCTION: BETA10 0x10121b1e
BOOL MxDirectDraw::TextToTextSurface2(const char* text) BOOL MxDirectDraw::TextToTextSurface2(const char* text)
{ {
return TextToTextSurface(text, m_pText2Surface, m_text2SizeOnSurface); return TextToTextSurface(text, m_pText2Surface, m_text2SizeOnSurface);
} }
// FUNCTION: LEGO1 0x1009e250 // FUNCTION: LEGO1 0x1009e250
// FUNCTION: BETA10 0x10121b52
BOOL MxDirectDraw::CreateTextSurfaces() BOOL MxDirectDraw::CreateTextSurfaces()
{ {
HRESULT result; HRESULT result;
@ -682,6 +716,7 @@ BOOL MxDirectDraw::CreateTextSurfaces()
} }
// FUNCTION: LEGO1 0x1009e4d0 // FUNCTION: LEGO1 0x1009e4d0
// FUNCTION: BETA10 0x10121e87
BOOL MxDirectDraw::RestoreSurfaces() BOOL MxDirectDraw::RestoreSurfaces()
{ {
HRESULT result; HRESULT result;
@ -740,6 +775,7 @@ BOOL MxDirectDraw::RestoreSurfaces()
} }
// FUNCTION: LEGO1 0x1009e5e0 // FUNCTION: LEGO1 0x1009e5e0
// FUNCTION: BETA10 0x10122087
BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth)
{ {
HRESULT result; // eax HRESULT result; // eax
@ -771,6 +807,7 @@ BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth)
} }
// FUNCTION: LEGO1 0x1009e6a0 // FUNCTION: LEGO1 0x1009e6a0
// FUNCTION: BETA10 0x10122166
int MxDirectDraw::Pause(BOOL p_pause) int MxDirectDraw::Pause(BOOL p_pause)
{ {
if (p_pause) { if (p_pause) {
@ -813,6 +850,7 @@ int MxDirectDraw::Pause(BOOL p_pause)
} }
// FUNCTION: LEGO1 0x1009e750 // FUNCTION: LEGO1 0x1009e750
// FUNCTION: BETA10 0x101223c9
BOOL MxDirectDraw::RestorePaletteEntries() BOOL MxDirectDraw::RestorePaletteEntries()
{ {
@ -833,6 +871,7 @@ BOOL MxDirectDraw::RestorePaletteEntries()
} }
// FUNCTION: LEGO1 0x1009e7a0 // FUNCTION: LEGO1 0x1009e7a0
// FUNCTION: BETA10 0x10122458
BOOL MxDirectDraw::RestoreOriginalPaletteEntries() BOOL MxDirectDraw::RestoreOriginalPaletteEntries()
{ {
if (m_bPrimaryPalettized) { if (m_bPrimaryPalettized) {
@ -856,6 +895,7 @@ BOOL MxDirectDraw::RestoreOriginalPaletteEntries()
} }
// FUNCTION: LEGO1 0x1009e7f0 // FUNCTION: LEGO1 0x1009e7f0
// FUNCTION: BETA10 0x101224d9
int MxDirectDraw::FlipToGDISurface() int MxDirectDraw::FlipToGDISurface()
{ {
@ -873,23 +913,28 @@ int MxDirectDraw::FlipToGDISurface()
} }
// FUNCTION: LEGO1 0x1009e830 // FUNCTION: LEGO1 0x1009e830
// FUNCTION: BETA10 0x101225b9
void MxDirectDraw::Error(const char* p_message, int p_error) void MxDirectDraw::Error(const char* p_message, int p_error)
{ {
// at LEGO1 0x10100c70, needs no annotation // ~GLOBAL: LEGO1 0x10100c70
// ~GLOBAL: BETA10 0x101ff1cc
static BOOL g_isInsideError = FALSE; static BOOL g_isInsideError = FALSE;
if (!g_isInsideError) { if (g_isInsideError) {
g_isInsideError = TRUE; return;
Destroy();
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirectDraw error: [0x%08x] %s", p_error, p_message);
if (m_pErrorHandler) {
m_pErrorHandler(p_message, p_error, m_pErrorHandlerArg);
}
g_isInsideError = FALSE;
} }
g_isInsideError = TRUE;
Destroy();
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirectDraw error: [0x%08x] %s", p_error, p_message);
if (m_pErrorHandler) {
m_pErrorHandler(p_message, p_error, m_pErrorHandlerArg);
}
g_isInsideError = FALSE;
} }
// FUNCTION: LEGO1 0x1009e880 // FUNCTION: LEGO1 0x1009e880
// FUNCTION: BETA10 0x10122630
const char* MxDirectDraw::ErrorToString(HRESULT p_error) const char* MxDirectDraw::ErrorToString(HRESULT p_error)
{ {
switch (p_error) { switch (p_error) {

View file

@ -8,6 +8,7 @@
#include <windows.h> #include <windows.h>
// VTABLE: LEGO1 0x100db818 // VTABLE: LEGO1 0x100db818
// VTABLE: BETA10 0x101c1b10
// SIZE 0x880 // SIZE 0x880
class MxDirectDraw { class MxDirectDraw {
public: public:
@ -33,10 +34,20 @@ public:
virtual void DestroyButNotDirectDraw(); // vtable+0x0c virtual void DestroyButNotDirectDraw(); // vtable+0x0c
IDirectDraw* DirectDraw() { return m_pDirectDraw; } IDirectDraw* DirectDraw() { return m_pDirectDraw; }
// FUNCTION: BETA10 0x100d8ab0
IDirectDrawSurface* FrontBuffer() { return m_pFrontBuffer; } IDirectDrawSurface* FrontBuffer() { return m_pFrontBuffer; }
// FUNCTION: BETA10 0x100d8ae0
IDirectDrawSurface* BackBuffer() { return m_pBackBuffer; } IDirectDrawSurface* BackBuffer() { return m_pBackBuffer; }
// FUNCTION: BETA10 0x100d8b10
IDirectDrawClipper* Clipper() { return m_pClipper; } IDirectDrawClipper* Clipper() { return m_pClipper; }
// FUNCTION: BETA10 0x1011c190
DeviceModesInfo::Mode* CurrentMode() { return &m_currentMode; }
// FUNCTION: BETA10 0x1011c170
BOOL IsFullScreen() { return m_bFullScreen; } BOOL IsFullScreen() { return m_bFullScreen; }
BOOL IsSupportedMode(int width, int height, int bpp); BOOL IsSupportedMode(int width, int height, int bpp);
@ -73,6 +84,7 @@ protected:
void FUN_1009d920(); void FUN_1009d920();
// SYNTHETIC: LEGO1 0x1009d510 // SYNTHETIC: LEGO1 0x1009d510
// SYNTHETIC: BETA10 0x10122f80
// MxDirectDraw::`scalar deleting destructor' // MxDirectDraw::`scalar deleting destructor'
protected: protected:
@ -103,7 +115,7 @@ protected:
void* m_pErrorHandlerArg; // 0x864 void* m_pErrorHandlerArg; // 0x864
void* m_pFatalErrorHandlerArg; // 0x868 void* m_pFatalErrorHandlerArg; // 0x868
int m_pauseCount; // 0x86c int m_pauseCount; // 0x86c
DeviceModesInfo* m_pCurrentDeviceModesList; // 0x870 DeviceModesInfo* m_currentDevInfo; // 0x870
DeviceModesInfo::Mode m_currentMode; // 0x874 DeviceModesInfo::Mode m_currentMode; // 0x874
}; };

View file

@ -10,6 +10,7 @@
struct DeviceModesInfo { struct DeviceModesInfo {
// SIZE 0x0c // SIZE 0x0c
struct Mode { struct Mode {
// FUNCTION: BETA10 0x10122fc0
int operator==(const Mode& p_mode) const int operator==(const Mode& p_mode) const
{ {
return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel)); return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel));

View file

@ -116,7 +116,7 @@ public:
MxLong GetDataSize() const { return AlignToFourByte(m_bmiHeader->biWidth) * GetBmiHeightAbs(); } MxLong GetDataSize() const { return AlignToFourByte(m_bmiHeader->biWidth) * GetBmiHeightAbs(); }
// FUNCTION: BETA10 0x1002c4b0 // FUNCTION: BETA10 0x1002c4b0
MxBool IsTopDown() MxBool IsTopDown() const
{ {
if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) { if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) {
return TRUE; return TRUE;
@ -131,7 +131,7 @@ public:
: -p_bitmap->AlignToFourByte(p_bitmap->GetBmiWidth())) : -p_bitmap->AlignToFourByte(p_bitmap->GetBmiWidth()))
// FUNCTION: BETA10 0x1002c320 // FUNCTION: BETA10 0x1002c320
MxU8* GetStart(MxS32 p_left, MxS32 p_top) MxU8* GetStart(MxS32 p_left, MxS32 p_top) const
{ {
if (m_bmiHeader->biCompression == BI_RGB) { if (m_bmiHeader->biCompression == BI_RGB) {
return m_data + p_left + return m_data + p_left +

View file

@ -369,7 +369,6 @@ public:
MxRect32(MxS32 p_l, MxS32 p_t, MxS32 p_r, MxS32 p_b) : MxRect<MxS32>(p_l, p_t, p_r, p_b) {} MxRect32(MxS32 p_l, MxS32 p_t, MxS32 p_r, MxS32 p_b) : MxRect<MxS32>(p_l, p_t, p_r, p_b) {}
#ifndef COMPAT_MODE #ifndef COMPAT_MODE
// FUNCTION: LEGO1 0x100b6fc0
// FUNCTION: BETA10 0x10137060 // FUNCTION: BETA10 0x10137060
MxRect32(MxPoint32& p_p, MxSize32& p_s) : MxRect<MxS32>(p_p, p_s) {} MxRect32(MxPoint32& p_p, MxSize32& p_s) : MxRect<MxS32>(p_p, p_s) {}
#else #else
@ -406,6 +405,7 @@ public:
// TEMPLATE: BETA10 0x10031800 // TEMPLATE: BETA10 0x10031800
// ??0?$MxRect@H@@QAE@XZ // ??0?$MxRect@H@@QAE@XZ
// TEMPLATE: LEGO1 0x100b6fc0
// TEMPLATE: BETA10 0x10031860 // TEMPLATE: BETA10 0x10031860
// ??0?$MxRect@H@@QAE@ABV?$MxPoint@H@@ABV?$MxSize@H@@@Z // ??0?$MxRect@H@@QAE@ABV?$MxPoint@H@@ABV?$MxSize@H@@@Z

View file

@ -82,6 +82,7 @@ void MakeSourceName(char* p_output, const char* p_input)
} }
// FUNCTION: LEGO1 0x100b7050 // FUNCTION: LEGO1 0x100b7050
// FUNCTION: BETA10 0x10136c19
MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_string) MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_string)
{ {
MxBool didMatch = FALSE; MxBool didMatch = FALSE;
@ -93,7 +94,8 @@ MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_
assert(string); assert(string);
strcpy(string, p_string); strcpy(string, p_string);
for (char* token = strtok(string, ", \t\r\n:"); token; token = strtok(NULL, ", \t\r\n:")) { const char* delim = ", \t\r\n:";
for (char* token = strtok(string, delim); token; token = strtok(NULL, delim)) {
len -= (strlen(token) + 1); len -= (strlen(token) + 1);
if (SDL_strcasecmp(token, p_command) == 0) { if (SDL_strcasecmp(token, p_command) == 0) {
@ -117,6 +119,7 @@ MxBool KeyValueStringParse(char* p_output, const char* p_command, const char* p_
} }
// FUNCTION: LEGO1 0x100b7170 // FUNCTION: LEGO1 0x100b7170
// FUNCTION: BETA10 0x10136e12
MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter) MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter)
{ {
for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) { for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) {
@ -147,9 +150,20 @@ void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32))
} }
// FUNCTION: LEGO1 0x100b7220 // FUNCTION: LEGO1 0x100b7220
// FUNCTION: BETA10 0x10136f37
void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags) void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags)
{ {
p_action->SetFlags(!p_setFlags ? p_action->GetFlags() & ~p_newFlags : p_action->GetFlags() | p_newFlags); MxU32 oldFlags = p_action->GetFlags();
MxU32 newFlags;
if (p_setFlags) {
newFlags = oldFlags | p_newFlags;
}
else {
newFlags = oldFlags & ~p_newFlags;
}
p_action->SetFlags(newFlags);
if (p_action->IsA("MxDSMultiAction")) { if (p_action->IsA("MxDSMultiAction")) {
MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList());

View file

@ -8,6 +8,8 @@
#include "mxmisc.h" #include "mxmisc.h"
#include "mxvariabletable.h" #include "mxvariabletable.h"
#include <assert.h>
DECOMP_SIZE_ASSERT(MxEventPresenter, 0x54); DECOMP_SIZE_ASSERT(MxEventPresenter, 0x54);
// FUNCTION: LEGO1 0x100c2b70 // FUNCTION: LEGO1 0x100c2b70
@ -90,6 +92,7 @@ void MxEventPresenter::StartingTickle()
} }
// FUNCTION: LEGO1 0x100c2ef0 // FUNCTION: LEGO1 0x100c2ef0
// FUNCTION: BETA10 0x10152d26
MxResult MxEventPresenter::PutData() MxResult MxEventPresenter::PutData()
{ {
AUTOLOCK(m_criticalSection); AUTOLOCK(m_criticalSection);
@ -102,10 +105,15 @@ MxResult MxEventPresenter::PutData()
const char* data = (const char*) m_currentChunk->GetData(); const char* data = (const char*) m_currentChunk->GetData();
MxVariableTable* variableTable = VariableTable(); MxVariableTable* variableTable = VariableTable();
const char* key = data; const char* name = data;
const char* value = &data[strlen(data) + 1]; assert(name);
strlen(value); data += strlen(data) + 1;
variableTable->SetVariable(key, value);
const char* value = data;
assert(value);
data += strlen(data) + 1;
variableTable->SetVariable(name, value);
} }
if (m_currentTickleState == e_streaming) { if (m_currentTickleState == e_streaming) {

View file

@ -87,7 +87,7 @@ void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber)
// FUNCTION: BETA10 0x1014e7b4 // FUNCTION: BETA10 0x1014e7b4
void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber)
{ {
m_subscribers.Remove(p_subscriber); m_subscribers.remove(p_subscriber);
} }
// FUNCTION: LEGO1 0x100c1690 // FUNCTION: LEGO1 0x100c1690

View file

@ -15,17 +15,12 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0x0c);
MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap)
{ {
m_width = p_bitmap.GetBmiWidth(); m_width = p_bitmap.GetBmiWidth();
// DECOMP: ECX becomes word-sized if these are not two separate actions. m_height = p_bitmap.GetBmiHeightAbs();
MxLong height = p_bitmap.GetBmiHeightAbs();
m_height = height;
MxS32 size = ((m_width * m_height) / 8) + 1; MxS32 size = ((m_width * m_height) / 8) + 1;
m_bitmask = new MxU8[size]; m_bitmask = new MxU8[size];
memset(m_bitmask, 0, size); memset(m_bitmask, 0, size);
MxU32 rowsBeforeTop;
MxU8* bitmapSrcPtr;
// The goal here is to enable us to walk through the bitmap's rows // The goal here is to enable us to walk through the bitmap's rows
// in order, regardless of the orientation. We want to end up at the // in order, regardless of the orientation. We want to end up at the
// start of the first row, which is either at position 0, or at // start of the first row, which is either at position 0, or at
@ -34,37 +29,13 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap)
// Reminder: Negative biHeight means this is a top-down DIB. // Reminder: Negative biHeight means this is a top-down DIB.
// Otherwise it is bottom-up. // Otherwise it is bottom-up.
switch (p_bitmap.GetBmiHeader()->biCompression) { MxU8* bitmapSrcPtr = p_bitmap.GetStart(0, 0);
case BI_RGB: {
if (p_bitmap.GetBmiHeight() < 0) {
rowsBeforeTop = 0;
}
else {
rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1;
}
bitmapSrcPtr = p_bitmap.GetImage() + (p_bitmap.GetBmiStride() * rowsBeforeTop);
break;
}
case BI_RGB_TOPDOWN:
bitmapSrcPtr = p_bitmap.GetImage();
break;
default: {
if (p_bitmap.GetBmiHeight() < 0) {
rowsBeforeTop = 0;
}
else {
rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1;
}
bitmapSrcPtr = p_bitmap.GetImage() + (p_bitmap.GetBmiStride() * rowsBeforeTop);
}
}
// How many bytes are there for each row of the bitmap? // How many bytes are there for each row of the bitmap?
// (i.e. the image stride) // (i.e. the image stride)
// If this is a bottom-up DIB, we will walk it in reverse. // If this is a bottom-up DIB, we will walk it in reverse.
// TODO: Same rounding trick as in MxBitmap MxS32 rowSeek = p_bitmap.AlignToFourByte(m_width);
MxS32 rowSeek = ((m_width + 3) & -4); if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() >= 0) {
if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() > 0) {
rowSeek = -rowSeek; rowSeek = -rowSeek;
} }
@ -76,9 +47,7 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap)
MxU8* tPtr = bitmapSrcPtr; MxU8* tPtr = bitmapSrcPtr;
for (MxS32 i = 0; i < m_width; i++) { for (MxS32 i = 0; i < m_width; i++) {
if (*tPtr) { if (*tPtr) {
// TODO: Second CDQ instruction for abs() should not be there. m_bitmask[offset / 8] |= (1 << (offset % 8));
MxU32 shift = abs(offset) & 7;
m_bitmask[offset / 8] |= (1 << abs((MxS32) shift));
} }
tPtr++; tPtr++;
offset++; offset++;
@ -116,7 +85,7 @@ MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y)
} }
MxS32 pos = p_y * m_width + p_x; MxS32 pos = p_y * m_width + p_x;
return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0; return m_bitmask[pos / 8] & (1 << (pos % 8)) ? 1 : 0;
} }
// FUNCTION: LEGO1 0x100b2760 // FUNCTION: LEGO1 0x100b2760
@ -205,47 +174,14 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y)
return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY()); return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY());
} }
MxLong heightAbs = m_frameBitmap->GetBmiHeightAbs(); MxRect32 rect(0, 0, m_frameBitmap->GetBmiWidth(), m_frameBitmap->GetBmiHeightAbs());
rect += GetLocation();
MxLong minX = m_location.GetX(); if (p_x < rect.GetLeft() || p_x >= rect.GetRight() || p_y < rect.GetTop() || p_y >= rect.GetBottom()) {
MxLong minY = m_location.GetY();
MxLong maxY = minY + heightAbs;
MxLong maxX = minX + m_frameBitmap->GetBmiWidth();
if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) {
return FALSE; return FALSE;
} }
MxU8* pixel; MxU8* pixel = m_frameBitmap->GetStart(p_x - rect.GetLeft(), p_y - rect.GetTop());
MxLong biCompression = m_frameBitmap->GetBmiHeader()->biCompression;
MxLong height = m_frameBitmap->GetBmiHeight();
MxLong seekRow;
// DECOMP: Same basic layout as AlphaMask constructor
// The idea here is to again seek to the correct place in the bitmap's
// m_data buffer. The x,y args are (most likely) screen x and y, so we
// need to shift that to coordinates local to the bitmap by removing
// the MxPresenter location x and y coordinates.
if (biCompression == BI_RGB) {
if (biCompression == BI_RGB_TOPDOWN || height < 0) {
seekRow = p_y - m_location.GetY();
}
else {
height = height > 0 ? height : -height;
seekRow = height - p_y - 1 + m_location.GetY();
}
pixel = m_frameBitmap->GetBmiStride() * seekRow + m_frameBitmap->GetImage() - m_location.GetX() + p_x;
}
else if (biCompression == BI_RGB_TOPDOWN) {
pixel = m_frameBitmap->GetImage();
}
else {
height = height > 0 ? height : -height;
height--;
pixel = m_frameBitmap->GetBmiStride() * height + m_frameBitmap->GetImage();
}
if (GetBit4()) { if (GetBit4()) {
return (MxBool) *pixel; return (MxBool) *pixel;