isle/LEGO1/mxvideomanager.cpp

339 lines
6.9 KiB
C++
Raw Normal View History

#include "mxvideomanager.h"
#include "mxautolocker.h"
#include "mxpresenter.h"
#include "mxticklemanager.h"
#include "legoomni.h"
DECOMP_SIZE_ASSERT(MxVideoManager, 0x64)
// OFFSET: LEGO1 0x100be1f0
MxVideoManager::MxVideoManager()
{
Init();
}
// OFFSET: LEGO1 0x100be270
void MxVideoManager::vtable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height)
{
}
// OFFSET: LEGO1 0x100be2a0
MxVideoManager::~MxVideoManager()
{
Destroy(TRUE);
}
// OFFSET: LEGO1 0x100be320
MxResult MxVideoManager::Init()
{
LEGO1: MxPalette (#56) * MxPalette - add missing member variables, Detach function * mb * MxPalette: give bob the builder his constructor * push progress, gn * avoid hexadecimal Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com> * fix MxPalette::GetDefaultPalette Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com> * aaaaaaaaaaaaaa * Revert "fix MxPalette::GetDefaultPalette" This reverts commit 63f2215737d3bcd286f67dcf1a04fdf8a234d41b. * Implement MxPalette::Clone (doesn't match) * fix MxPalette structure and match ctor/dtor * Matching progress for MxPalette::GetDefaultPalette * Implement ApplySystemEntriesToPalette except the memcpy calls * implement SetSkyColor (doesn't match) * Use MxTypes instead of generics * prefer decimal values than hex for m_entries * Update mxpalette.cpp * Push MxPalette progress - read comments in code. * improved MxPalette::operator==, will be 100% when MSVC feels like making it so * improved MxPalette::SetSkyColor, will be 100% when MSVC feels like making it so * improved MxPalette::Clone, will be 100% when MSVC feels like making it so * Fixes - reordered the functions in order of where they are in the hex because recmp.py sometimes kept saying it couldn't find the symbol (??) - clone returns a pointer, not a ref - worked a bit on setpalette/applysysentriestopalette * Match GetDefaultPalette a bit more * fix: MxPalette::GetDefaultPalette is now 100% matching * fix: MxPalette::ApplySystemEntriesToPalette is now 100% matching * tidy: rename `DC` var in GetDefaultPalette to `hdc` * fix: MxPalette::SetPalette is now functionally matching Not assembly matching yet because of MSVC weirdness. At some point it will probably start matching, because the structure seems to be accurate. * fix: MxPalette rgbquad ctor functionally matches Not quite ASM matching yet because of weird register allocation mismatches. * fix: I forgot to commit mxpalette.h... * tidy: use Mx* primitives instead of builtins * refactor: remove MxPalette::FromBitmapPalette * fix: call ApplySystemEntriesToPalette from MxPalette(const RGBQUAD *) * rename MxPalette::SetPalette to MxPalette::SetEntries * fix: I once again forgot to commit mxpalette.h... * feat: add/match MxPalette::Reset [0x100BF490] * fix: add MVideoManager() to mxomni header * refactor: change unk50 in MxVideoManager to LPDIRECTDRAW * feat: add/match MxPalette::CreateNativePalette [0x100BF000] * fix: MxPalette::SetSkyColor is 100% matching * Annotate MxPalette members' offsets * Annotate the global default aplette * use hex size * remove unnecessary variable offset listing * Update LEGO1/mxpalette.cpp --------- Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com> Co-authored-by: Christian Semmler <mail@csemmler.com> Co-authored-by: ktkaufman03 <ktkaufman@wpi.edu> Co-authored-by: MattKC <34096995+itsmattkc@users.noreply.github.com>
2023-07-16 01:51:24 -04:00
this->m_pDirectDraw = NULL;
this->m_pDDSurface = NULL;
this->m_displaySurface = NULL;
this->m_region = NULL;
this->m_videoParam.SetPalette(NULL);
this->m_unk60 = FALSE;
return SUCCESS;
}
// OFFSET: LEGO1 0x100be340
void MxVideoManager::Destroy(MxBool p_fromDestructor)
{
if (m_thread) {
m_thread->Terminate();
delete m_thread;
}
else
TickleManager()->UnregisterClient(this);
m_criticalSection.Enter();
if (m_displaySurface)
delete m_displaySurface;
if (m_region)
delete m_region;
if (m_videoParam.GetPalette())
delete m_videoParam.GetPalette();
if (m_unk60) {
if (m_pDirectDraw)
m_pDirectDraw->Release();
if (m_pDDSurface)
m_pDDSurface->Release();
}
Init();
m_criticalSection.Leave();
if (!p_fromDestructor)
MxMediaManager::Destroy();
}
// OFFSET: LEGO1 0x100be3e0
void MxVideoManager::UpdateRegion()
{
if (m_region->vtable20() == FALSE) {
MxS32 left, top, right, bottom;
MxRect32 &regionRect = m_region->GetRect();
left = m_videoParam.GetRect().m_left;
if (left <= regionRect.m_left)
left = regionRect.m_left;
top = regionRect.m_top;
if (top <= m_videoParam.GetRect().m_top)
top = m_videoParam.GetRect().m_top;
right = regionRect.m_right;
if (right >= m_videoParam.GetRect().m_right)
right = m_videoParam.GetRect().m_right;
bottom = m_videoParam.GetRect().m_bottom;
if (bottom >= regionRect.m_bottom)
bottom = regionRect.m_bottom;
m_displaySurface->Display(
left, top, left, top,
right - left + 1, bottom - top + 1
);
}
}
// OFFSET: LEGO1 0x100be440
void MxVideoManager::SortPresenterList()
{
if (this->m_presenters->GetCount() <= 1)
return;
MxPresenterListCursor a(this->m_presenters);
MxPresenterListCursor b(this->m_presenters);
MxU32 count = this->m_presenters->GetCount() - 1;
MxBool finished;
if (count != 0) {
do {
a.Reset();
b.Head();
finished = TRUE;
for (MxU32 i = count; i != 0; i--) {
MxPresenter *p_a, *p_b;
a.Next(p_a);
b.Next(p_b);
if (p_a->GetDisplayZ() < p_b->GetDisplayZ()) {
a.SetValue(p_b);
b.SetValue(p_a);
finished = FALSE;
}
}
} while (!finished && --count != 0);
}
}
// OFFSET: LEGO1 0x100be600
MxResult MxVideoManager::vtable0x28(
MxVideoParam &p_videoParam,
LPDIRECTDRAW p_pDirectDraw,
LPDIRECTDRAWSURFACE p_pDDSurface,
LPDIRECTDRAWSURFACE p_ddSurface1,
LPDIRECTDRAWSURFACE p_ddSurface2,
LPDIRECTDRAWCLIPPER p_ddClipper,
MxU32 p_frequencyMS,
MxBool p_createThread)
{
MxBool locked = FALSE;
MxResult status = FAILURE;
m_unk60 = FALSE;
if (MxMediaManager::InitPresenters() != SUCCESS)
goto done;
m_criticalSection.Enter();
locked = TRUE;
m_videoParam = p_videoParam;
m_region = new MxRegion();
if (!m_region)
goto done;
m_pDirectDraw = p_pDirectDraw;
m_pDDSurface = p_pDDSurface;
MxPalette *palette;
if (p_videoParam.GetPalette() == NULL) {
palette = new MxPalette();
m_videoParam.SetPalette(palette);
if (!palette)
goto done;
}
else {
palette = p_videoParam.GetPalette()->Clone();
m_videoParam.SetPalette(palette);
if (!palette)
goto done;
}
m_displaySurface = new MxDisplaySurface();
if (m_displaySurface && m_displaySurface->Init(m_videoParam, p_ddSurface1, p_ddSurface2, p_ddClipper) == SUCCESS) {
m_displaySurface->SetPalette(m_videoParam.GetPalette());
if (p_createThread) {
m_thread = new MxTickleThread(this, p_frequencyMS);
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
goto done;
}
else
TickleManager()->RegisterClient(this, p_frequencyMS);
status = SUCCESS;
}
done:
if (status != SUCCESS)
Destroy();
if (locked)
m_criticalSection.Leave();
return status;
}
// OFFSET: LEGO1 0x100be820
MxResult MxVideoManager::Create(
MxVideoParam &p_videoParam,
MxU32 p_frequencyMS,
MxBool p_createThread)
{
MxBool locked = FALSE;
MxResult status = FAILURE;
m_unk60 = TRUE;
if (MxMediaManager::InitPresenters() != SUCCESS)
goto done;
m_criticalSection.Enter();
locked = TRUE;
m_videoParam = p_videoParam;
m_region = new MxRegion();
if (!m_region)
goto done;
if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK)
goto done;
if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK)
goto done;
MxPalette *palette;
if (p_videoParam.GetPalette() == NULL) {
palette = new MxPalette();
m_videoParam.SetPalette(palette);
if (!palette)
goto done;
}
else {
palette = p_videoParam.GetPalette()->Clone();
m_videoParam.SetPalette(palette);
if (!palette)
goto done;
}
m_displaySurface = new MxDisplaySurface();
if (m_displaySurface && m_displaySurface->Create(m_videoParam) == SUCCESS) {
m_displaySurface->SetPalette(m_videoParam.GetPalette());
if (p_createThread) {
m_thread = new MxTickleThread(this, p_frequencyMS);
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
goto done;
}
else
TickleManager()->RegisterClient(this, p_frequencyMS);
status = SUCCESS;
}
done:
if (status != SUCCESS)
Destroy();
if (locked)
m_criticalSection.Leave();
return status;
}
// OFFSET: LEGO1 0x100bea50
void MxVideoManager::Destroy()
{
Destroy(FALSE);
}
// OFFSET: LEGO1 0x100bea60
void MxVideoManager::InvalidateRect(MxRect32 &p_rect)
{
m_criticalSection.Enter();
if (m_region)
m_region->vtable18(p_rect);
m_criticalSection.Leave();
}
// OFFSET: LEGO1 0x100bea90
MxResult MxVideoManager::Tickle()
{
MxAutoLocker lock(&this->m_criticalSection);
SortPresenterList();
MxPresenter *presenter;
MxPresenterListCursor cursor(this->m_presenters);
while (cursor.Next(presenter))
presenter->Tickle();
cursor.Reset();
while (cursor.Next(presenter))
presenter->PutData();
UpdateRegion();
m_region->Reset();
return SUCCESS;
}
// OFFSET: LEGO1 0x100bebe0
MxResult MxVideoManager::RealizePalette(MxPalette *p_palette)
{
PALETTEENTRY paletteEntries[256];
this->m_criticalSection.Enter();
if (p_palette && this->m_videoParam.GetPalette()) {
p_palette->GetEntries(paletteEntries);
this->m_videoParam.GetPalette()->SetEntries(paletteEntries);
this->m_displaySurface->SetPalette(this->m_videoParam.GetPalette());
}
this->m_criticalSection.Leave();
return SUCCESS;
}