Merge branch 'master' into complete-helicopter

This commit is contained in:
Christian Semmler 2024-12-19 17:08:45 -07:00 committed by GitHub
commit b1c8690eac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 660 additions and 141 deletions

View File

@ -130,6 +130,7 @@ class Act3 : public LegoWorld {
void FUN_10073400(); void FUN_10073400();
void FUN_10073430(); void FUN_10073430();
void GoodEnding(const Matrix4& p_destination); void GoodEnding(const Matrix4& p_destination);
void BadEnding(const Matrix4& p_destination);
void FUN_10073a60(); void FUN_10073a60();
// BETA indicates that the following classes access certain members directly. // BETA indicates that the following classes access certain members directly.

View File

@ -153,7 +153,7 @@ class Act3Shark : public LegoAnimActor {
void Animate(float p_time) override; // vtable+0x70 void Animate(float p_time) override; // vtable+0x70
// LegoAnimActor vtable // LegoAnimActor vtable
virtual MxResult FUN_10042ce0(Act3Ammo* p_ammo); // vtable+0x10 virtual MxResult EatPizza(Act3Ammo* p_ammo); // vtable+0x10
MxFloat GetUnknown0x2c() { return m_unk0x2c; } MxFloat GetUnknown0x2c() { return m_unk0x2c; }
@ -163,8 +163,8 @@ class Act3Shark : public LegoAnimActor {
// Act3Shark::`scalar deleting destructor' // Act3Shark::`scalar deleting destructor'
private: private:
list<Act3Ammo*> m_unk0x1c; // 0x1c list<Act3Ammo*> m_eatPizzas; // 0x1c
Act3Ammo* m_unk0x28; // 0x28 Act3Ammo* m_nextPizza; // 0x28
MxFloat m_unk0x2c; // 0x2c MxFloat m_unk0x2c; // 0x2c
LegoWorld* m_world; // 0x30 LegoWorld* m_world; // 0x30
LegoAnimActorStruct* m_unk0x34; // 0x34 LegoAnimActorStruct* m_unk0x34; // 0x34

View File

@ -15,7 +15,7 @@ class Act3Ammo : public LegoPathActor {
c_donut = 0x02, c_donut = 0x02,
c_valid = 0x04, c_valid = 0x04,
c_bit4 = 0x08, c_bit4 = 0x08,
c_bit5 = 0x10 c_sharkFood = 0x10
}; };
Act3Ammo(); Act3Ammo();
@ -64,17 +64,17 @@ class Act3Ammo : public LegoPathActor {
// FUNCTION: BETA10 0x10021d90 // FUNCTION: BETA10 0x10021d90
MxU32 IsBit4() { return m_ammoFlag & c_bit4; } MxU32 IsBit4() { return m_ammoFlag & c_bit4; }
void SetBit5(MxBool p_bit5) void SetSharkFood(MxBool p_sharkFood)
{ {
if (p_bit5) { if (p_sharkFood) {
m_ammoFlag |= c_bit5; m_ammoFlag |= c_sharkFood;
} }
else { else {
m_ammoFlag &= ~c_bit5; m_ammoFlag &= ~c_sharkFood;
} }
} }
MxU32 IsBit5() { return m_ammoFlag & c_bit5; } MxU32 IsSharkFood() { return m_ammoFlag & c_sharkFood; }
MxFloat GetUnknown0x158() { return m_unk0x158; } MxFloat GetUnknown0x158() { return m_unk0x158; }

View File

@ -80,6 +80,7 @@ class Helicopter : public IslePathActor {
void CreateState(); void CreateState();
void FUN_10004640(const Matrix4& p_matrix); void FUN_10004640(const Matrix4& p_matrix);
void FUN_10004670(const Matrix4& p_matrix);
// SYNTHETIC: LEGO1 0x10003210 // SYNTHETIC: LEGO1 0x10003210
// Helicopter::`scalar deleting destructor' // Helicopter::`scalar deleting destructor'

View File

@ -137,6 +137,7 @@ class LegoPathActor : public LegoActor {
// FUNCTION: LEGO1 0x10002de0 // FUNCTION: LEGO1 0x10002de0
virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8 virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8
// FUNCTION: BETA10 0x1001ca40
LegoPathBoundary* GetBoundary() { return m_boundary; } LegoPathBoundary* GetBoundary() { return m_boundary; }
// FUNCTION: BETA10 0x1001c860 // FUNCTION: BETA10 0x1001c860

View File

@ -22,9 +22,7 @@ class Vector3;
// VTABLE: LEGO1 0x100d7da8 // VTABLE: LEGO1 0x100d7da8
// SIZE 0x40 // SIZE 0x40
struct LegoPathCtrlEdge : public LegoUnknown100db7f4 { struct LegoPathCtrlEdge : public LegoUnknown100db7f4 {};
inline MxU32 FUN_10048c40(const Vector3& p_position);
};
struct LegoPathCtrlEdgeCompare { struct LegoPathCtrlEdgeCompare {
MxU32 operator()(const LegoPathCtrlEdge* p_lhs, const LegoPathCtrlEdge* p_rhs) const MxU32 operator()(const LegoPathCtrlEdge* p_lhs, const LegoPathCtrlEdge* p_rhs) const

View File

@ -5,12 +5,14 @@
#include "legophonemelist.h" #include "legophonemelist.h"
#include "mxvideomanager.h" #include "mxvideomanager.h"
#include <d3drm.h>
#include <ddraw.h> #include <ddraw.h>
class Lego3DManager; class Lego3DManager;
class LegoROI; class LegoROI;
class MxDirect3D; class MxDirect3D;
class MxStopWatch; class MxStopWatch;
struct ViewportAppData;
namespace Tgl namespace Tgl
{ {
@ -70,40 +72,52 @@ class LegoVideoManager : public MxVideoManager {
inline void DrawCursor(); inline void DrawCursor();
Tgl::Renderer* m_renderer; // 0x64 Tgl::Renderer* m_renderer; // 0x64
Lego3DManager* m_3dManager; // 0x68 Lego3DManager* m_3dManager; // 0x68
LegoROI* m_viewROI; // 0x6c LegoROI* m_viewROI; // 0x6c
undefined4 m_unk0x70; // 0x70 undefined4 m_unk0x70; // 0x70
MxDirect3D* m_direct3d; // 0x74 MxDirect3D* m_direct3d; // 0x74
undefined4 m_unk0x78[27]; // 0x78 undefined4 m_unk0x78[27]; // 0x78
MxBool m_render3d; // 0xe4 MxBool m_render3d; // 0xe4
MxBool m_unk0xe5; // 0xe5 MxBool m_unk0xe5; // 0xe5
MxBool m_unk0xe6; // 0xe6 MxBool m_unk0xe6; // 0xe6
PALETTEENTRY m_paletteEntries[256]; // 0xe7 PALETTEENTRY m_paletteEntries[256]; // 0xe7
undefined m_padding0x4e7; // 0x4e7 LegoPhonemeList* m_phonemeRefList; // 0x4e8
LegoPhonemeList* m_phonemeRefList; // 0x4e8 MxBool m_isFullscreenMovie; // 0x4ec
MxBool m_isFullscreenMovie; // 0x4ec MxPalette* m_palette; // 0x4f0
MxPalette* m_palette; // 0x4f0 MxStopWatch* m_stopWatch; // 0x4f4
MxStopWatch* m_stopWatch; // 0x4f4 double m_elapsedSeconds; // 0x4f8
double m_elapsedSeconds; // 0x4f8 MxBool m_fullScreenMovie; // 0x500
MxBool m_fullScreenMovie; // 0x500 MxBool m_drawCursor; // 0x501
MxBool m_drawCursor; // 0x501 MxS32 m_cursorXCopy; // 0x504
MxS32 m_cursorXCopy; // 0x504 MxS32 m_cursorYCopy; // 0x508
MxS32 m_cursorYCopy; // 0x508 MxS32 m_cursorX; // 0x50c
MxS32 m_cursorX; // 0x50c MxS32 m_cursorY; // 0x510
MxS32 m_cursorY; // 0x510 LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514
LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514 RECT m_cursorRect; // 0x518
RECT m_cursorRect; // 0x518 LPDIRECTDRAWSURFACE m_unk0x528; // 0x528
LPDIRECTDRAWSURFACE m_unk0x528; // 0x528 MxBool m_drawFPS; // 0x52c
MxBool m_drawFPS; // 0x52c RECT m_fpsRect; // 0x530
RECT m_fpsRect; // 0x530 HFONT m_arialFont; // 0x540
HFONT m_arialFont; // 0x540 SIZE m_fpsSize; // 0x544
SIZE m_fpsSize; // 0x544 MxFloat m_unk0x54c; // 0x54c
MxFloat m_unk0x54c; // 0x54c MxFloat m_unk0x550; // 0x550
MxFloat m_unk0x550; // 0x550 MxBool m_unk0x554; // 0x554
MxBool m_unk0x554; // 0x554 MxBool m_paused; // 0x555
MxBool m_paused; // 0x555 D3DVALUE m_back; // 0x558
undefined m_pad0x556[0x39]; // 0x556 D3DVALUE m_front; // 0x55c
float m_cameraWidth; // 0x560
float m_cameraHeight; // 0x564
D3DVALUE m_fov; // 0x55c
IDirect3DRMFrame* m_camera; // 0x56c
D3DRMPROJECTIONTYPE m_projection; // 0x570
ViewportAppData* m_appdata; // 0x574
D3DRMRENDERQUALITY m_quality; // 0x578
DWORD m_shades; // 0x57c
D3DRMTEXTUREQUALITY m_textureQuality; // 0x580
DWORD m_rendermode; // 0x584
BOOL m_dither; // 0x588
DWORD m_bufferCount; // 0x58c
}; };
// SYNTHETIC: LEGO1 0x1007ab20 // SYNTHETIC: LEGO1 0x1007ab20

View File

@ -579,7 +579,7 @@ MxResult Act3Brickster::HitActor(LegoPathActor* p_actor, MxBool p_bool)
assert(m_world); assert(m_world);
if (a3->m_pizzas[index].IsValid() && !a3->m_pizzas[index].IsBit5()) { if (a3->m_pizzas[index].IsValid() && !a3->m_pizzas[index].IsSharkFood()) {
a3->EatPizza(index); a3->EatPizza(index);
} }
@ -605,19 +605,329 @@ MxResult Act3Brickster::FUN_100417a0(Act3Ammo& p_ammo, const Vector3&)
return SUCCESS; return SUCCESS;
} }
// STUB: LEGO1 0x100417c0 // FUNCTION: LEGO1 0x100417c0
// STUB: BETA10 0x1001a407 // FUNCTION: BETA10 0x1001a407
MxResult Act3Brickster::FUN_100417c0() MxResult Act3Brickster::FUN_100417c0()
{ {
// TODO m_pInfo = NULL;
m_bInfo = NULL;
m_unk0x38 = 0;
LegoPathEdgeContainer* grec = NULL;
Act3* a3 = (Act3*) m_world;
MxMatrix local70(m_unk0xec);
Vector3 local28(local70[3]);
Vector3 local20(local70[2]);
if (m_unk0x58 < 8 && m_unk0x24 + 5000.0f < m_lastTime) {
float local18;
for (MxS32 i = 0; i < MAX_PIZZAS; i++) {
Act3Ammo* pizza = &a3->m_pizzas[i];
assert(pizza);
if (pizza->IsValid() && !pizza->IsSharkFood() && pizza->GetActorState() == c_initial) {
LegoROI* proi = pizza->GetROI();
assert(proi);
MxMatrix locald0 = proi->GetLocal2World();
Vector3 local88(locald0[3]);
Mx3DPointFloat localec(local88);
localec -= local28;
if (localec.LenSquared() > 1600.0f) {
((Act3*) m_world)->m_shark->EatPizza(pizza);
}
else {
LegoPathEdgeContainer* r2 = new LegoPathEdgeContainer();
assert(r2);
MxFloat locald8;
LegoPathEdgeContainer *local16c, *local168, *local174, *local170; // unused
if (m_pathController->FUN_10048310(
r2,
local28,
local20,
m_boundary,
local88,
localec,
pizza->GetBoundary(),
LegoUnknown100db7f4::c_bit1,
&locald8
) == SUCCESS &&
(grec == NULL || locald8 < local18)) {
if (grec != NULL) {
local168 = local16c = grec;
delete grec;
}
grec = r2;
local18 = locald8;
}
if (grec != r2) {
local170 = local174 = r2;
delete r2;
}
}
}
}
}
if (grec == NULL) {
MxS32 length = 0;
LegoPlantInfo* pInfo = PlantManager()->GetInfoArray(length);
Mx3DPointFloat local108;
Mx3DPointFloat local138;
MxS32 local120 = -1;
MxU32 local110 = FALSE;
LegoPathBoundary* localf4 = NULL;
LegoBuildingInfo* bInfo = BuildingManager()->GetInfoArray(length);
float local124;
for (MxS32 i = 0; i < length; i++) {
if (bInfo[i].m_unk0x11 < 0 && bInfo[i].m_boundary != NULL && bInfo[i].m_entity != NULL && i != 0 &&
(local120 == -1 || i != 15)) {
Mx3DPointFloat local188(bInfo[i].m_x, bInfo[i].m_y, bInfo[i].m_z);
local138 = local188;
local138 -= local28;
float length = local138.LenSquared();
if (local120 < 0 || length < local124) {
local110 = TRUE;
local120 = i;
local124 = length;
}
}
}
if (local120 != -1) {
if (local110) {
m_bInfo = &bInfo[local120];
localf4 = m_bInfo->m_boundary;
Mx3DPointFloat local19c(m_bInfo->m_x, m_bInfo->m_y, m_bInfo->m_z);
local108 = local19c;
}
else {
m_pInfo = &pInfo[local120];
localf4 = m_pInfo->m_boundary;
Mx3DPointFloat local1b0(m_pInfo->m_x, m_pInfo->m_y, m_pInfo->m_z);
local108 = local1b0;
}
}
if (localf4 != NULL) {
assert(m_pInfo || m_bInfo);
grec = new LegoPathEdgeContainer();
local138 = local108;
local138 -= local28;
local138.Unitize();
MxFloat local13c;
LegoPathEdgeContainer *local1c0, *local1bc; // unused
if (m_pathController->FUN_10048310(
grec,
local28,
local20,
m_boundary,
local108,
local138,
localf4,
LegoUnknown100db7f4::c_bit1,
&local13c
) != SUCCESS) {
local1bc = local1c0 = grec;
if (grec != NULL) {
delete grec;
}
grec = NULL;
assert(0);
}
}
else {
((Act3*) m_world)->BadEnding(m_roi->GetLocal2World());
return SUCCESS;
}
}
if (grec != NULL) {
Mx3DPointFloat local150;
LegoPathEdgeContainer *local1c4, *local1c8; // unused
if (m_grec != NULL) {
local1c4 = local1c8 = m_grec;
delete m_grec;
}
m_grec = grec;
Mx3DPointFloat vecUnk;
if (m_grec->size() == 0) {
vecUnk = m_grec->m_position;
m_boundary = m_grec->m_boundary;
m_grec->m_direction = m_unk0xec[3];
m_grec->m_direction -= vecUnk;
local150 = m_grec->m_direction;
}
else {
LegoEdge* edge = m_grec->back().m_edge;
Vector3* v1 = edge->CWVertex(*m_grec->m_boundary);
Vector3* v2 = edge->CCWVertex(*m_grec->m_boundary);
assert(v1 && v2);
local150 = *v2;
local150 -= *v1;
local150 *= m_unk0xe4;
local150 += *v1;
local150 *= -1.0f;
local150 += m_grec->m_position;
local150.Unitize();
m_grec->m_direction = local150;
edge = m_grec->front().m_edge;
LegoPathBoundary* boundary = m_grec->front().m_boundary;
v1 = edge->CWVertex(*boundary);
v2 = edge->CCWVertex(*boundary);
vecUnk = *v2;
vecUnk -= *v1;
vecUnk *= m_unk0xe4;
vecUnk += *v1;
}
Vector3 v1(m_unk0xec[0]);
Vector3 v2(m_unk0xec[1]);
Vector3 v3(m_unk0xec[2]);
v3 = m_unk0xec[3];
v3 -= vecUnk;
v3.Unitize();
v1.EqualsCross(&v2, &v3);
v1.Unitize();
v2.EqualsCross(&v3, &v1);
VTable0x9c();
if (m_pInfo != NULL) {
m_unk0x38 = 5;
}
else if (m_bInfo != NULL) {
m_unk0x38 = 6;
}
}
return SUCCESS; return SUCCESS;
} }
// STUB: LEGO1 0x10042300 // FUNCTION: LEGO1 0x10042300
// STUB: BETA10 0x1001b017 // FUNCTION: BETA10 0x1001b017
MxS32 Act3Brickster::FUN_10042300() MxS32 Act3Brickster::FUN_10042300()
{ {
// TODO // TODO: Has poor inlining, can be fixed by changing the assignment operator in vector.h
// See extended comment in vector.h for operator=
Act3* a3 = (Act3*) m_world;
assert(a3 && a3->m_cop1 && a3->m_cop2);
assert(a3->m_cop1->GetROI() && a3->m_cop2->GetROI() && GetROI());
Mx3DPointFloat local64[2];
Mx3DPointFloat local38;
Mx3DPointFloat local18;
MxS32 local1c = 0;
float local24[2];
local64[0] = a3->m_cop1->GetROI()->GetLocal2World()[3];
local64[1] = a3->m_cop2->GetROI()->GetLocal2World()[3];
local38 = GetROI()->GetLocal2World()[3];
local18 = local64[0];
local18 -= local38;
local24[0] = local18.LenSquared();
local18 = local64[1];
local18 -= local38;
local24[1] = local18.LenSquared();
if (local24[1] < local24[0]) {
local1c = 1;
}
if (local24[local1c] < 225.0f) {
m_unk0x38 = 8;
if (m_grec != NULL) {
delete m_grec;
m_grec = NULL;
}
if (m_pInfo != NULL) {
m_pInfo = NULL;
}
assert(m_boundary && m_destEdge && m_roi);
LegoPathBoundary* boundaries[2];
LegoUnknown100db7f4* maxE = NULL;
boundaries[0] = m_boundary;
if (m_destEdge->FUN_10048c40(local38)) {
boundaries[1] = (LegoPathBoundary*) m_destEdge->OtherFace(m_boundary);
}
else {
boundaries[1] = NULL;
}
float local78, local98;
for (MxS32 i = 0; i < (MxS32) sizeOfArray(boundaries); i++) {
if (boundaries[i] != NULL) {
for (MxS32 j = 0; j < boundaries[i]->GetNumEdges(); j++) {
LegoUnknown100db7f4* e = boundaries[i]->GetEdges()[j];
if (e->GetMask0x03()) {
Mx3DPointFloat local94(*e->GetPointA());
local94 += *e->GetPointB();
local94 /= 2.0f;
local18 = local94;
local18 -= local64[local1c];
local98 = local18.LenSquared();
local94 -= local38;
local18 = local64[local1c];
local18 -= local38;
if (maxE == NULL || (local18.Dot(&local94, &local18) < 0.0f && local78 < local98)) {
maxE = e;
m_boundary = boundaries[i];
local78 = local98;
}
}
}
}
}
assert(maxE);
m_destEdge = maxE;
if (m_boundary != boundaries[0]) {
m_unk0xe4 = 1.0 - m_unk0xe4;
}
VTable0x9c();
}
return -1; return -1;
} }
@ -648,14 +958,14 @@ MxResult Act3Brickster::VTable0x9c()
Act3Shark::Act3Shark() Act3Shark::Act3Shark()
{ {
m_unk0x2c = 0.0f; m_unk0x2c = 0.0f;
m_unk0x28 = NULL; m_nextPizza = NULL;
} }
// FUNCTION: LEGO1 0x10042ce0 // FUNCTION: LEGO1 0x10042ce0
MxResult Act3Shark::FUN_10042ce0(Act3Ammo* p_ammo) MxResult Act3Shark::EatPizza(Act3Ammo* p_ammo)
{ {
p_ammo->SetBit5(TRUE); p_ammo->SetSharkFood(TRUE);
m_unk0x1c.push_back(p_ammo); m_eatPizzas.push_back(p_ammo);
return SUCCESS; return SUCCESS;
} }
@ -664,18 +974,18 @@ void Act3Shark::Animate(float p_time)
{ {
LegoROI** roiMap = m_unk0x34->GetROIMap(); LegoROI** roiMap = m_unk0x34->GetROIMap();
if (m_unk0x28 == NULL) { if (m_nextPizza == NULL) {
if (m_unk0x1c.size() > 0) { if (m_eatPizzas.size() > 0) {
m_unk0x28 = m_unk0x1c.front(); m_nextPizza = m_eatPizzas.front();
m_unk0x1c.pop_front(); m_eatPizzas.pop_front();
m_unk0x2c = p_time; m_unk0x2c = p_time;
roiMap[1] = m_unk0x28->GetROI(); roiMap[1] = m_nextPizza->GetROI();
m_unk0x3c = roiMap[1]->GetLocal2World()[3]; m_unk0x3c = roiMap[1]->GetLocal2World()[3];
roiMap[1]->SetVisibility(TRUE); roiMap[1]->SetVisibility(TRUE);
roiMap[2]->SetVisibility(TRUE); roiMap[2]->SetVisibility(TRUE);
} }
if (m_unk0x28 == NULL) { if (m_nextPizza == NULL) {
return; return;
} }
} }
@ -704,8 +1014,8 @@ void Act3Shark::Animate(float p_time)
} }
else { else {
roiMap[1] = m_unk0x38; roiMap[1] = m_unk0x38;
((Act3*) m_world)->RemovePizza(*m_unk0x28); ((Act3*) m_world)->RemovePizza(*m_nextPizza);
m_unk0x28 = NULL; m_nextPizza = NULL;
roiMap[1]->SetVisibility(FALSE); roiMap[1]->SetVisibility(FALSE);
roiMap[2]->SetVisibility(FALSE); roiMap[2]->SetVisibility(FALSE);
} }

View File

@ -419,7 +419,7 @@ void Act3Ammo::Animate(float p_time)
assert(m_world); assert(m_world);
if (m_world->m_pizzas[index].IsValid() && !m_world->m_pizzas[index].IsBit5()) { if (m_world->m_pizzas[index].IsValid() && !m_world->m_pizzas[index].IsSharkFood()) {
m_world->EatPizza(index); m_world->EatPizza(index);
m_world->m_brickster->FUN_100417c0(); m_world->m_brickster->FUN_100417c0();
} }

View File

@ -481,3 +481,12 @@ void Helicopter::FUN_10004640(const Matrix4& p_matrix)
FUN_100042a0(p_matrix); FUN_100042a0(p_matrix);
} }
} }
// FUNCTION: LEGO1 0x10004670
void Helicopter::FUN_10004670(const Matrix4& p_matrix)
{
if (m_state->m_unk0x08 != 4 && m_state->m_unk0x08 != 5) {
m_state->m_unk0x08 = 5;
FUN_100042a0(p_matrix);
}
}

View File

@ -336,7 +336,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
} }
MxU32 version, status; MxU32 version, status;
MxS16 count, area, act; MxS16 count, actArea;
const char* lightPosition; const char* lightPosition;
Read(&fileStorage, &version); Read(&fileStorage, &version);
@ -348,8 +348,8 @@ MxResult LegoGameState::Load(MxULong p_slot)
Read(&fileStorage, &m_unk0x24); Read(&fileStorage, &m_unk0x24);
Read(&fileStorage, &act); Read(&fileStorage, &actArea);
SetCurrentAct((Act) act); SetCurrentAct((Act) actArea);
Read(&fileStorage, &m_actorId); Read(&fileStorage, &m_actorId);
if (m_actorId) { if (m_actorId) {
@ -406,13 +406,13 @@ MxResult LegoGameState::Load(MxULong p_slot)
} }
} }
Read(&fileStorage, &area); Read(&fileStorage, &actArea);
if (m_currentAct == 0) { if (m_currentAct == 0) {
m_unk0x42c = e_undefined; m_unk0x42c = e_undefined;
} }
else { else {
m_unk0x42c = (Area) area; m_unk0x42c = (Area) actArea;
} }
result = SUCCESS; result = SUCCESS;

View File

@ -920,68 +920,6 @@ MxResult LegoPathController::FUN_10048310(
return FAILURE; return FAILURE;
} }
// FUNCTION: LEGO1 0x10048c40
// FUNCTION: BETA10 0x1001cc90
inline MxU32 LegoPathCtrlEdge::FUN_10048c40(const Vector3& p_position)
{
MxFloat localc, local10;
MxU32 result = FALSE;
if (m_unk0x28[0] > 0.001 || m_unk0x28[0] < -0.001) {
localc = (p_position[0] - (*m_pointA)[0]) / m_unk0x28[0];
if (localc < 0 || localc > 1) {
return FALSE;
}
result = TRUE;
}
else {
if (p_position[0] > (*m_pointA)[0] + 0.001 || p_position[0] < (*m_pointA)[0] - 0.001) {
return FALSE;
}
}
if (m_unk0x28[1] > 0.001 || m_unk0x28[1] < -0.001) {
local10 = (p_position[1] - (*m_pointA)[1]) / m_unk0x28[1];
if (result) {
if (localc > local10 + 0.001 || localc < local10 - 0.001) {
return FALSE;
}
}
else {
result = TRUE;
localc = local10;
}
}
else {
if (p_position[1] > (*m_pointA)[1] + 0.001 || p_position[1] < (*m_pointA)[1] - 0.001) {
return FALSE;
}
}
if (m_unk0x28[2] > 0.001 || m_unk0x28[2] < -0.001) {
local10 = (p_position[2] - (*m_pointA)[2]) / m_unk0x28[2];
if (result) {
if (localc > local10 + 0.001 || localc < local10 - 0.001) {
return FALSE;
}
}
else {
return TRUE;
}
}
else {
if (p_position[2] > (*m_pointA)[2] + 0.001 || p_position[2] < (*m_pointA)[2] - 0.001) {
return FALSE;
}
}
return TRUE;
}
// FUNCTION: LEGO1 0x1004a240 // FUNCTION: LEGO1 0x1004a240
// FUNCTION: BETA10 0x100b9160 // FUNCTION: BETA10 0x100b9160
MxS32 LegoPathController::FUN_1004a240( MxS32 LegoPathController::FUN_1004a240(

View File

@ -561,18 +561,112 @@ void LegoVideoManager::FUN_1007c520()
InputManager()->SetUnknown335(TRUE); InputManager()->SetUnknown335(TRUE);
} }
// STUB: LEGO1 0x1007c560 extern void ViewportDestroyCallback(IDirect3DRMObject*, void*);
// FUNCTION: LEGO1 0x1007c560
int LegoVideoManager::EnableRMDevice() int LegoVideoManager::EnableRMDevice()
{ {
// TODO IDirect3DRMViewport* viewport;
return 0;
if (!m_paused) {
return -1;
}
TglImpl::DeviceImpl* deviceImpl = (TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice();
IDirect3DRMDevice2* d3drmDev2 = NULL;
IDirect3D2* d3d2 = m_direct3d->Direct3D();
IDirect3DDevice2* d3dDev2 = m_direct3d->Direct3DDevice();
int result = -1;
IDirect3DRM2* d3drm2 = ((TglImpl::RendererImpl*) m_renderer)->ImplementationData();
m_direct3d->RestoreSurfaces();
if (d3drm2->CreateDeviceFromD3D(d3d2, d3dDev2, &d3drmDev2) == D3DRM_OK) {
viewport = NULL;
deviceImpl->SetImplementationData(d3drmDev2);
if (d3drm2->CreateViewport(d3drmDev2, m_camera, 0, 0, m_cameraWidth, m_cameraHeight, &viewport) == D3DRM_OK) {
viewport->SetBack(m_back);
viewport->SetFront(m_front);
viewport->SetField(m_fov);
viewport->SetCamera(m_camera);
viewport->SetProjection(m_projection);
viewport->SetAppData((DWORD) m_appdata);
d3drmDev2->SetQuality(m_quality);
d3drmDev2->SetShades(m_shades);
d3drmDev2->SetTextureQuality(m_textureQuality);
d3drmDev2->SetRenderMode(m_rendermode);
d3drmDev2->SetDither(m_dither);
d3drmDev2->SetBufferCount(m_bufferCount);
m_camera->Release();
if (viewport->AddDestroyCallback(ViewportDestroyCallback, m_appdata) == D3DRM_OK) {
((TglImpl::ViewImpl*) m_3dManager->GetLego3DView()->GetView())->SetImplementationData(viewport);
m_paused = 0;
result = 0;
}
}
}
return result;
} }
// STUB: LEGO1 0x1007c740 // FUNCTION: LEGO1 0x1007c740
int LegoVideoManager::DisableRMDevice() int LegoVideoManager::DisableRMDevice()
{ {
// TODO if (m_paused) {
return 0; return -1;
}
IDirect3DRMDevice2* d3drmDev2 =
((TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice())->ImplementationData();
if (d3drmDev2 != NULL) {
IDirect3DRMViewportArray* viewportArray = NULL;
if (d3drmDev2->GetViewports(&viewportArray) == D3DRM_OK && viewportArray != NULL) {
if (viewportArray->GetSize() == 1) {
IDirect3DRMViewport* viewport = NULL;
if (viewportArray->GetElement(0, &viewport) == D3DRM_OK) {
m_back = viewport->GetBack();
m_front = viewport->GetFront();
m_cameraWidth = viewport->GetWidth();
m_cameraHeight = viewport->GetHeight();
m_fov = viewport->GetField();
viewport->GetCamera(&m_camera);
m_projection = viewport->GetProjection();
m_appdata = (ViewportAppData*) viewport->GetAppData();
viewportArray->Release();
viewport->Release();
viewport->DeleteDestroyCallback(ViewportDestroyCallback, this->m_appdata);
viewport->Release();
m_paused = 1;
m_direct3d->Direct3D()->AddRef();
m_direct3d->Direct3DDevice()->AddRef();
}
else {
viewportArray->Release();
}
}
}
m_quality = d3drmDev2->GetQuality();
m_shades = d3drmDev2->GetShades();
m_textureQuality = d3drmDev2->GetTextureQuality();
m_rendermode = d3drmDev2->GetRenderMode();
m_dither = d3drmDev2->GetDither();
m_bufferCount = d3drmDev2->GetBufferCount();
d3drmDev2->Release();
}
if (m_paused) {
return 0;
}
else {
return -1;
}
} }
// FUNCTION: LEGO1 0x1007c930 // FUNCTION: LEGO1 0x1007c930

View File

@ -844,6 +844,29 @@ void Act3::DebugCopter(
} }
} }
// FUNCTION: LEGO1 0x100739c0
// FUNCTION: BETA10 0x10016cc4
void Act3::BadEnding(const Matrix4& p_destination)
{
assert(m_cop1 && m_cop2 && m_brickster && m_state);
m_cop1->SetActorState(LegoPathActor::c_disabled);
m_cop2->SetActorState(LegoPathActor::c_disabled);
m_brickster->SetActorState(LegoPathActor::c_disabled);
m_unk0x4220.Clear();
m_copter->FUN_10004670(p_destination);
DebugPrintf("In Bad Ending...");
DebugCopter(
m_copter->GetROI()->GetLocal2World(),
p_destination,
m_copter->m_unk0x160,
m_copter->m_unk0x1a8,
m_copter->m_unk0x1f4
);
}
// FUNCTION: LEGO1 0x10073a60 // FUNCTION: LEGO1 0x10073a60
void Act3::FUN_10073a60() void Act3::FUN_10073a60()
{ {

View File

@ -19,6 +19,12 @@ struct LegoEdge {
LegoResult FUN_1002ddc0(LegoWEEdge& p_face, Vector3& p_point); LegoResult FUN_1002ddc0(LegoWEEdge& p_face, Vector3& p_point);
// FUNCTION: BETA10 0x1001cb80
Vector3* GetPointA() { return m_pointA; }
// FUNCTION: BETA10 0x1001cbb0
Vector3* GetPointB() { return m_pointB; }
// SYNTHETIC: LEGO1 0x1009a4a0 // SYNTHETIC: LEGO1 0x1009a4a0
// LegoEdge::`scalar deleting destructor' // LegoEdge::`scalar deleting destructor'

View File

@ -93,6 +93,8 @@ struct LegoUnknown100db7f4 : public LegoEdge {
// FUNCTION: BETA10 0x1001cc60 // FUNCTION: BETA10 0x1001cc60
LegoU32 GetMask0x03() { return m_flags & (c_bit1 | c_bit2); } LegoU32 GetMask0x03() { return m_flags & (c_bit1 | c_bit2); }
inline LegoU32 FUN_10048c40(const Vector3& p_position);
// SYNTHETIC: LEGO1 0x1009a6c0 // SYNTHETIC: LEGO1 0x1009a6c0
// LegoUnknown100db7f4::`scalar deleting destructor' // LegoUnknown100db7f4::`scalar deleting destructor'
@ -101,4 +103,66 @@ struct LegoUnknown100db7f4 : public LegoEdge {
float m_unk0x3c; // 0x3c float m_unk0x3c; // 0x3c
}; };
// FUNCTION: LEGO1 0x10048c40
// FUNCTION: BETA10 0x1001cc90
inline LegoU32 LegoUnknown100db7f4::FUN_10048c40(const Vector3& p_position)
{
LegoFloat localc, local10;
LegoU32 result = FALSE;
if (m_unk0x28[0] > 0.001 || m_unk0x28[0] < -0.001) {
localc = (p_position[0] - (*m_pointA)[0]) / m_unk0x28[0];
if (localc < 0 || localc > 1) {
return FALSE;
}
result = TRUE;
}
else {
if (p_position[0] > (*m_pointA)[0] + 0.001 || p_position[0] < (*m_pointA)[0] - 0.001) {
return FALSE;
}
}
if (m_unk0x28[1] > 0.001 || m_unk0x28[1] < -0.001) {
local10 = (p_position[1] - (*m_pointA)[1]) / m_unk0x28[1];
if (result) {
if (localc > local10 + 0.001 || localc < local10 - 0.001) {
return FALSE;
}
}
else {
result = TRUE;
localc = local10;
}
}
else {
if (p_position[1] > (*m_pointA)[1] + 0.001 || p_position[1] < (*m_pointA)[1] - 0.001) {
return FALSE;
}
}
if (m_unk0x28[2] > 0.001 || m_unk0x28[2] < -0.001) {
local10 = (p_position[2] - (*m_pointA)[2]) / m_unk0x28[2];
if (result) {
if (localc > local10 + 0.001 || localc < local10 - 0.001) {
return FALSE;
}
}
else {
return TRUE;
}
}
else {
if (p_position[2] > (*m_pointA)[2] + 0.001 || p_position[2] < (*m_pointA)[2] - 0.001) {
return FALSE;
}
}
return TRUE;
}
#endif // __LEGOUNKNOWN100DB7F4_H #endif // __LEGOUNKNOWN100DB7F4_H

View File

@ -33,6 +33,9 @@ class Mx3DPointFloat : public Vector3 {
// FUNCTION: LEGO1 0x10003c10 // FUNCTION: LEGO1 0x10003c10
virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88
// FUNCTION: BETA10 0x10015240
// ??4Mx3DPointFloat@@QAEAAV0@ABV0@@Z
// FUNCTION: BETA10 0x10013460 // FUNCTION: BETA10 0x10013460
float& operator[](int idx) { return m_data[idx]; } float& operator[](int idx) { return m_data[idx]; }

View File

@ -151,8 +151,25 @@ class Vector2 {
virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70 virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70
// FUNCTION: LEGO1 0x10002260 // FUNCTION: LEGO1 0x10002260
// FUNCTION: BETA10 0x100110c0
virtual void SetVector(const Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c virtual void SetVector(const Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c
// Note: it's unclear whether Vector3::operator= has been defined explicitly
// with the same function body as Vector2& operator=. The BETA indicates that;
// however, it makes LEGO1 0x10010be0 disappear and worsens matches in
// at least these functions:
// LEGO1 0x100109b0
// LEGO1 0x10023130
// LEGO1 0x1002de10
// LEGO1 0x10050a80
// LEGO1 0x10053980
// LEGO1 0x100648f0
// LEGO1 0x10064b50
// LEGO1 0x10084030
// LEGO1 0x100a9410
// However, defining it as in the BETA improves at least these functions:
// LEGO1 0x10042300
// SYNTHETIC: LEGO1 0x10010be0 // SYNTHETIC: LEGO1 0x10010be0
// SYNTHETIC: BETA10 0x100121e0 // SYNTHETIC: BETA10 0x100121e0
// Vector3::operator= // Vector3::operator=

View File

@ -149,6 +149,7 @@ class DeviceImpl : public Device {
void InitFromWindowsDevice(Device*) override; void InitFromWindowsDevice(Device*) override;
IDirect3DRMDevice2* ImplementationData() const { return m_data; } IDirect3DRMDevice2* ImplementationData() const { return m_data; }
void SetImplementationData(IDirect3DRMDevice2* device) { m_data = device; }
friend class RendererImpl; friend class RendererImpl;
@ -199,6 +200,7 @@ class ViewImpl : public View {
) override; ) override;
IDirect3DRMViewport* ImplementationData() const { return m_data; } IDirect3DRMViewport* ImplementationData() const { return m_data; }
void SetImplementationData(IDirect3DRMViewport* viewport) { m_data = viewport; }
static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*); static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*);

View File

@ -86,10 +86,46 @@ void TglD3DRMIMAGE::Destroy()
delete m_image.palette; delete m_image.palette;
} }
// STUB: LEGO1 0x100a13e0 inline static int IsPowerOfTwo(int v)
{
int m = 0;
while (v > 2 && m == 0) {
m = v % 2;
v /= 2;
}
return v == 2 && m == 0;
}
// FUNCTION: LEGO1 0x100a13e0
Result TglD3DRMIMAGE::CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer) Result TglD3DRMIMAGE::CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer)
{ {
return Error; if (!(IsPowerOfTwo(width) && IsPowerOfTwo(height) && width % 4 == 0)) {
return Error;
}
m_image.width = width;
m_image.height = height;
m_image.depth = depth;
m_image.bytes_per_line = width;
if (!m_texelsAllocatedByClient) {
delete[] m_image.buffer1;
m_image.buffer1 = NULL;
}
if (useBuffer) {
m_texelsAllocatedByClient = 1;
m_image.buffer1 = (char*) pBuffer;
}
else {
m_image.buffer1 = new char[width * height];
memcpy(m_image.buffer1, pBuffer, width * height);
m_texelsAllocatedByClient = 0;
}
return Success;
} }
// FUNCTION: LEGO1 0x100a1510 // FUNCTION: LEGO1 0x100a1510

View File

@ -80,6 +80,8 @@ inline Result ViewRestoreFrameAfterRender(
return result; return result;
} }
// FIXME: from LEGO1/tgl/d3drm/view.cpp
// FUNCTION: LEGO1 0x100a1240 // FUNCTION: LEGO1 0x100a1240
void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg) void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg)
{ {