merge from isle/master

This commit is contained in:
Christian Semmler 2024-12-20 11:54:06 -07:00
commit e73f60e2c6
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
33 changed files with 1562 additions and 239 deletions

View File

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

View File

@ -6,6 +6,8 @@
// File name verified by multiple assertions, e.g. BETA10 0x10018391
class Act3Ammo;
struct LegoBuildingInfo;
struct LegoPlantInfo;
class LegoWorld;
// VTABLE: LEGO1 0x100d7668 LegoPathActor
@ -118,17 +120,19 @@ class Act3Brickster : public Act3Actor {
// Act3Brickster::`scalar deleting destructor'
private:
MxS32 FUN_10042300();
MxFloat m_unk0x20; // 0x20
MxFloat m_unk0x24; // 0x24
LegoWorld* m_world; // 0x28
undefined4 m_unk0x2c; // 0x2c
undefined4 m_unk0x30; // 0x30
LegoPlantInfo* m_pInfo; // 0x2c
LegoBuildingInfo* m_bInfo; // 0x30
LegoAnimActorStruct* m_shootAnim; // 0x34
undefined4 m_unk0x38; // 0x38
Mx3DPointFloat m_unk0x3c; // 0x3c
MxFloat m_unk0x50; // 0x50
undefined4 m_unk0x54; // 0x54
undefined m_unk0x58; // 0x58
MxFloat m_unk0x54; // 0x54
MxU8 m_unk0x58; // 0x58
};
// VTABLE: LEGO1 0x100d7920 LegoPathActor
@ -149,7 +153,7 @@ class Act3Shark : public LegoAnimActor {
void Animate(float p_time) override; // vtable+0x70
// LegoAnimActor vtable
virtual MxResult FUN_10042ce0(Act3Ammo* p_ammo); // vtable+0x10
virtual MxResult EatPizza(Act3Ammo* p_ammo); // vtable+0x10
MxFloat GetUnknown0x2c() { return m_unk0x2c; }
@ -159,8 +163,8 @@ class Act3Shark : public LegoAnimActor {
// Act3Shark::`scalar deleting destructor'
private:
list<Act3Ammo*> m_unk0x1c; // 0x1c
Act3Ammo* m_unk0x28; // 0x28
list<Act3Ammo*> m_eatPizzas; // 0x1c
Act3Ammo* m_nextPizza; // 0x28
MxFloat m_unk0x2c; // 0x2c
LegoWorld* m_world; // 0x30
LegoAnimActorStruct* m_unk0x34; // 0x34

View File

@ -15,7 +15,7 @@ class Act3Ammo : public LegoPathActor {
c_donut = 0x02,
c_valid = 0x04,
c_bit4 = 0x08,
c_bit5 = 0x10
c_sharkFood = 0x10
};
Act3Ammo();
@ -64,17 +64,17 @@ class Act3Ammo : public LegoPathActor {
// FUNCTION: BETA10 0x10021d90
MxU32 IsBit4() { return m_ammoFlag & c_bit4; }
void SetBit5(MxBool p_bit5)
void SetSharkFood(MxBool p_sharkFood)
{
if (p_bit5) {
m_ammoFlag |= c_bit5;
if (p_sharkFood) {
m_ammoFlag |= c_sharkFood;
}
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; }

View File

@ -48,6 +48,7 @@ class HelicopterState : public LegoState {
};
// VTABLE: LEGO1 0x100d40f8
// VTABLE: BETA10 0x101b9880
// SIZE 0x230
class Helicopter : public IslePathActor {
public:
@ -55,6 +56,7 @@ class Helicopter : public IslePathActor {
~Helicopter() override; // vtable+0x00
// FUNCTION: LEGO1 0x10003070
// FUNCTION: BETA10 0x1002b300
const char* ClassName() const override // vtable+0x0c
{
// STRING: LEGO1 0x100f0130
@ -62,6 +64,7 @@ class Helicopter : public IslePathActor {
}
// FUNCTION: LEGO1 0x10003080
// FUNCTION: BETA10 0x1002b330
MxBool IsA(const char* p_name) const override // vtable+0x10
{
return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name);
@ -77,6 +80,7 @@ class Helicopter : public IslePathActor {
void CreateState();
void FUN_10004640(const Matrix4& p_matrix);
void FUN_10004670(const Matrix4& p_matrix);
// SYNTHETIC: LEGO1 0x10003210
// Helicopter::`scalar deleting destructor'

View File

@ -38,6 +38,7 @@ class LegoCameraController : public LegoPointOfViewController {
void SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up);
void FUN_10012290(float p_angle);
void FUN_10012320(float p_angle);
MxResult FUN_100123b0(Matrix4& p_matrix);
void FUN_100123e0(const Matrix4& p_transform, MxU32 p_und);
Mx3DPointFloat GetWorldUp();
Mx3DPointFloat GetWorldLocation();

View File

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

View File

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

View File

@ -5,12 +5,14 @@
#include "legophonemelist.h"
#include "mxvideomanager.h"
#include <d3drm.h>
#include <ddraw.h>
class Lego3DManager;
class LegoROI;
class MxDirect3D;
class MxStopWatch;
struct ViewportAppData;
namespace Tgl
{
@ -70,40 +72,52 @@ class LegoVideoManager : public MxVideoManager {
inline void DrawCursor();
Tgl::Renderer* m_renderer; // 0x64
Lego3DManager* m_3dManager; // 0x68
LegoROI* m_viewROI; // 0x6c
undefined4 m_unk0x70; // 0x70
MxDirect3D* m_direct3d; // 0x74
undefined4 m_unk0x78[27]; // 0x78
MxBool m_render3d; // 0xe4
MxBool m_unk0xe5; // 0xe5
MxBool m_unk0xe6; // 0xe6
PALETTEENTRY m_paletteEntries[256]; // 0xe7
undefined m_padding0x4e7; // 0x4e7
LegoPhonemeList* m_phonemeRefList; // 0x4e8
MxBool m_isFullscreenMovie; // 0x4ec
MxPalette* m_palette; // 0x4f0
MxStopWatch* m_stopWatch; // 0x4f4
double m_elapsedSeconds; // 0x4f8
MxBool m_fullScreenMovie; // 0x500
MxBool m_drawCursor; // 0x501
MxS32 m_cursorXCopy; // 0x504
MxS32 m_cursorYCopy; // 0x508
MxS32 m_cursorX; // 0x50c
MxS32 m_cursorY; // 0x510
LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514
RECT m_cursorRect; // 0x518
LPDIRECTDRAWSURFACE m_unk0x528; // 0x528
MxBool m_drawFPS; // 0x52c
RECT m_fpsRect; // 0x530
HFONT m_arialFont; // 0x540
SIZE m_fpsSize; // 0x544
MxFloat m_unk0x54c; // 0x54c
MxFloat m_unk0x550; // 0x550
MxBool m_unk0x554; // 0x554
MxBool m_paused; // 0x555
undefined m_pad0x556[0x39]; // 0x556
Tgl::Renderer* m_renderer; // 0x64
Lego3DManager* m_3dManager; // 0x68
LegoROI* m_viewROI; // 0x6c
undefined4 m_unk0x70; // 0x70
MxDirect3D* m_direct3d; // 0x74
undefined4 m_unk0x78[27]; // 0x78
MxBool m_render3d; // 0xe4
MxBool m_unk0xe5; // 0xe5
MxBool m_unk0xe6; // 0xe6
PALETTEENTRY m_paletteEntries[256]; // 0xe7
LegoPhonemeList* m_phonemeRefList; // 0x4e8
MxBool m_isFullscreenMovie; // 0x4ec
MxPalette* m_palette; // 0x4f0
MxStopWatch* m_stopWatch; // 0x4f4
double m_elapsedSeconds; // 0x4f8
MxBool m_fullScreenMovie; // 0x500
MxBool m_drawCursor; // 0x501
MxS32 m_cursorXCopy; // 0x504
MxS32 m_cursorYCopy; // 0x508
MxS32 m_cursorX; // 0x50c
MxS32 m_cursorY; // 0x510
LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514
RECT m_cursorRect; // 0x518
LPDIRECTDRAWSURFACE m_unk0x528; // 0x528
MxBool m_drawFPS; // 0x52c
RECT m_fpsRect; // 0x530
HFONT m_arialFont; // 0x540
SIZE m_fpsSize; // 0x544
MxFloat m_unk0x54c; // 0x54c
MxFloat m_unk0x550; // 0x550
MxBool m_unk0x554; // 0x554
MxBool m_paused; // 0x555
D3DVALUE m_back; // 0x558
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

View File

@ -4,9 +4,12 @@
#include "act3ammo.h"
#include "anim/legoanim.h"
#include "define.h"
#include "legobuildingmanager.h"
#include "legocachesoundmanager.h"
#include "legolocomotionanimpresenter.h"
#include "legopathedgecontainer.h"
#include "legoplantmanager.h"
#include "legoplants.h"
#include "legosoundmanager.h"
#include "misc.h"
#include "mxdebug.h"
@ -318,11 +321,188 @@ MxResult Act3Cop::FUN_10040350(Act3Ammo& p_ammo, const Vector3&)
return FUN_10040360();
}
// STUB: LEGO1 0x10040360
// STUB: BETA10 0x10018c6a
// FUNCTION: LEGO1 0x10040360
// FUNCTION: BETA10 0x10018c6a
MxResult Act3Cop::FUN_10040360()
{
// TODO
LegoPathEdgeContainer* grec = NULL;
Act3* a3 = (Act3*) m_world;
MxMatrix local74(m_unk0xec);
Vector3 local2c(local74[3]);
Vector3 local20(local74[2]);
Mx3DPointFloat local7c;
local7c = a3->m_brickster->GetROI()->GetLocal2World()[3];
local7c -= local2c;
if (local7c.LenSquared() < 144.0f) {
local7c = a3->m_brickster->GetROI()->GetLocal2World()[3];
Mx3DPointFloat local5c(a3->m_brickster->GetROI()->GetLocal2World()[2]);
LegoPathBoundary* boundary = a3->m_brickster->GetBoundary();
grec = new LegoPathEdgeContainer();
assert(grec);
MxFloat local34;
if (m_pathController->FUN_10048310(
grec,
local2c,
local20,
m_boundary,
local7c,
local5c,
boundary,
LegoUnknown100db7f4::c_bit1,
&local34
) != SUCCESS) {
delete grec;
grec = NULL;
}
}
if (grec == NULL) {
float local18;
for (MxS32 i = 0; i < MAX_DONUTS; i++) {
Act3Ammo* donut = &a3->m_donuts[i];
assert(donut);
if (donut->IsValid() && donut->GetActorState() == c_initial) {
LegoROI* proi = donut->GetROI();
assert(proi);
MxMatrix locald0 = proi->GetLocal2World();
Vector3 local88(locald0[3]);
Mx3DPointFloat localec(local88);
localec -= local88;
LegoPathEdgeContainer* r2 = new LegoPathEdgeContainer();
assert(r2);
MxFloat locald8;
LegoPathEdgeContainer *local138, *local134, *local140, *local13c; // unused
if (m_pathController->FUN_10048310(
r2,
local2c,
local20,
m_boundary,
local88,
localec,
donut->GetBoundary(),
LegoUnknown100db7f4::c_bit1,
&locald8
) == SUCCESS &&
(grec == NULL || locald8 < local18)) {
if (grec != NULL) {
local134 = local138 = grec;
delete grec;
}
grec = r2;
local18 = locald8;
}
if (grec != r2) {
local13c = local140 = r2;
delete r2;
}
}
}
if (grec == NULL) {
MxS32 random = rand() % (MxS32) sizeOfArray(g_copDest);
Vector3 localf8(g_copDest[random].m_unk0x08);
Vector3 local108(g_copDest[random].m_unk0x14);
grec = new LegoPathEdgeContainer();
LegoPathBoundary* boundary = g_copDest[random].m_boundary;
if (boundary != NULL) {
MxFloat local100;
LegoPathEdgeContainer *local150, *local14c; // unused
if (m_pathController->FUN_10048310(
grec,
local2c,
local20,
m_boundary,
localf8,
local108,
boundary,
LegoUnknown100db7f4::c_bit1,
&local100
) != SUCCESS) {
local14c = local150 = grec;
delete grec;
grec = NULL;
}
}
}
}
if (grec != NULL) {
LegoPathEdgeContainer *local158, *local154; // unused
if (m_grec != NULL) {
local154 = local158 = 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;
}
else {
Mx3DPointFloat local128;
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);
local128 = *v2;
local128 -= *v1;
local128 *= m_unk0xe4;
local128 += *v1;
local128 *= -1.0f;
local128 += m_grec->m_position;
local128.Unitize();
m_grec->m_direction = local128;
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]);
Vector3 v4(m_unk0xec[3]);
v3 = v4;
v3 -= vecUnk;
v3.Unitize();
v1.EqualsCross(&v2, &v3);
v1.Unitize();
v2.EqualsCross(&v3, &v1);
VTable0x9c();
}
return SUCCESS;
}
@ -346,13 +526,13 @@ MxResult Act3Cop::VTable0x9c()
Act3Brickster::Act3Brickster()
{
m_world = NULL;
m_unk0x2c = 0;
m_unk0x30 = 0;
m_pInfo = NULL;
m_bInfo = NULL;
m_shootAnim = NULL;
m_unk0x38 = 0;
m_unk0x20 = 0.0f;
m_unk0x24 = 0.0f;
m_unk0x54 = 0;
m_unk0x54 = 0.0f;
SetActorState(c_disabled);
m_unk0x58 = 0;
@ -386,11 +566,174 @@ void Act3Brickster::ParseAction(char* p_extra)
assert(m_shootAnim);
}
// STUB: LEGO1 0x10041050
// STUB: BETA10 0x100197d7
// FUNCTION: LEGO1 0x10041050
// FUNCTION: BETA10 0x100197d7
void Act3Brickster::Animate(float p_time)
{
// TODO
if (m_lastTime <= m_unk0x20 && m_unk0x20 <= p_time) {
SetWorldSpeed(5.0f);
}
if (m_unk0x38 != 3 && m_unk0x38 != 4) {
Act3Actor::Animate(p_time);
}
if (m_unk0x54 < p_time) {
((Act3*) m_world)->FUN_10072ad0(5);
m_unk0x54 = p_time + 15000.0f;
}
switch (m_unk0x38) {
case 1:
FUN_100417c0();
break;
case 2:
m_unk0x58++;
m_unk0x20 = p_time + 2000.0f;
SetWorldSpeed(3.0f);
assert(SoundManager()->GetCacheSoundManager());
if (m_unk0x58 >= 8) {
((Act3*) m_world)->FUN_10072ad0(6);
}
else {
SoundManager()->GetCacheSoundManager()->Play("eatpz", NULL, FALSE);
}
FUN_100417c0();
break;
case 3:
assert(m_shootAnim && m_pInfo);
if (m_unk0x50 < p_time) {
while (m_pInfo->m_unk0x16) {
PlantManager()->FUN_10026c50(m_pInfo->m_entity);
}
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("thpt", NULL, FALSE);
m_unk0x58 = 0;
FUN_100417c0();
}
else {
MxMatrix local70;
local70 = m_unk0xec;
Vector3 local14(local70[0]);
Vector3 local28(local70[1]);
Vector3 localc(local70[2]);
Vector3 local20(local70[3]);
localc = local20;
localc -= m_pInfo->m_position;
localc.Unitize();
local14.EqualsCross(&local28, &localc);
local14.Unitize();
local28.EqualsCross(&localc, &local14);
assert(!m_cameraFlag);
LegoTreeNode* root = m_shootAnim->GetAnimTreePtr()->GetRoot();
float time = p_time - (m_unk0x50 - m_shootAnim->GetDuration());
for (MxS32 i = 0; i < root->GetNumChildren(); i++) {
LegoROI::FUN_100a8e80(root->GetChild(i), local70, time, m_shootAnim->GetROIMap());
}
}
m_lastTime = p_time;
break;
case 4:
assert(m_shootAnim && m_bInfo);
if (m_unk0x50 < p_time) {
((Act3*) m_world)->FUN_10073a60();
m_unk0x58 = 0;
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("thpt", NULL, FALSE);
while (m_bInfo->m_unk0x11 > 0 || m_bInfo->m_unk0x11 == -1) {
if (!BuildingManager()->FUN_10030110(m_bInfo)) {
break;
}
}
FUN_100417c0();
}
else {
MxMatrix locale4;
locale4 = m_unk0xec;
Vector3 local88(locale4[0]);
Vector3 local9c(locale4[1]);
Vector3 local80(locale4[2]);
Vector3 local94(locale4[3]);
local80 = local94;
assert(m_bInfo->m_entity && m_bInfo->m_entity->GetROI());
local80 -= m_unk0x3c;
local80.Unitize();
local88.EqualsCross(&local9c, &local80);
local88.Unitize();
local9c.EqualsCross(&local80, &local88);
assert(!m_cameraFlag);
LegoTreeNode* root = m_shootAnim->GetAnimTreePtr()->GetRoot();
float time = p_time - (m_unk0x50 - m_shootAnim->GetDuration());
for (MxS32 i = 0; i < root->GetNumChildren(); i++) {
LegoROI::FUN_100a8e80(root->GetChild(i), locale4, time, m_shootAnim->GetROIMap());
}
}
m_lastTime = p_time;
break;
case 5:
if (m_grec == NULL) {
assert(m_shootAnim && m_pInfo);
m_unk0x38 = 3;
m_unk0x50 = p_time + m_shootAnim->GetDuration();
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("xarrow", NULL, FALSE);
}
else {
FUN_10042300();
}
break;
case 6:
if (m_grec == NULL) {
assert(m_shootAnim && m_bInfo);
m_unk0x38 = 4;
m_unk0x50 = p_time + m_shootAnim->GetDuration();
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("xarrow", NULL, FALSE);
BuildingManager()->ScheduleAnimation(m_bInfo->m_entity, 0, FALSE, TRUE);
m_unk0x3c = m_bInfo->m_entity->GetROI()->GetLocal2World()[3];
}
else {
FUN_10042300();
}
break;
case 7:
default:
FUN_10042300();
break;
case 8:
m_unk0x24 = p_time + 10000.0f;
m_unk0x38 = 9;
break;
case 9:
if (m_unk0x24 < p_time) {
FUN_100417c0();
}
else if (m_unk0x24 - 9000.0f < p_time) {
FUN_10042300();
}
break;
}
}
// FUNCTION: LEGO1 0x100416b0
@ -414,7 +757,7 @@ MxResult Act3Brickster::HitActor(LegoPathActor* p_actor, MxBool p_bool)
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);
}
@ -440,14 +783,333 @@ MxResult Act3Brickster::FUN_100417a0(Act3Ammo& p_ammo, const Vector3&)
return SUCCESS;
}
// STUB: LEGO1 0x100417c0
// STUB: BETA10 0x1001a407
// FUNCTION: LEGO1 0x100417c0
// FUNCTION: BETA10 0x1001a407
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]);
Vector3 v4(m_unk0xec[3]);
v3 = v4;
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;
}
// FUNCTION: LEGO1 0x10042300
// FUNCTION: BETA10 0x1001b017
MxS32 Act3Brickster::FUN_10042300()
{
// 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;
}
// FUNCTION: LEGO1 0x10042990
// FUNCTION: BETA10 0x1001b6e2
void Act3Brickster::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4)
@ -475,14 +1137,14 @@ MxResult Act3Brickster::VTable0x9c()
Act3Shark::Act3Shark()
{
m_unk0x2c = 0.0f;
m_unk0x28 = NULL;
m_nextPizza = NULL;
}
// FUNCTION: LEGO1 0x10042ce0
MxResult Act3Shark::FUN_10042ce0(Act3Ammo* p_ammo)
MxResult Act3Shark::EatPizza(Act3Ammo* p_ammo)
{
p_ammo->SetBit5(TRUE);
m_unk0x1c.push_back(p_ammo);
p_ammo->SetSharkFood(TRUE);
m_eatPizzas.push_back(p_ammo);
return SUCCESS;
}
@ -491,18 +1153,18 @@ void Act3Shark::Animate(float p_time)
{
LegoROI** roiMap = m_unk0x34->GetROIMap();
if (m_unk0x28 == NULL) {
if (m_unk0x1c.size() > 0) {
m_unk0x28 = m_unk0x1c.front();
m_unk0x1c.pop_front();
if (m_nextPizza == NULL) {
if (m_eatPizzas.size() > 0) {
m_nextPizza = m_eatPizzas.front();
m_eatPizzas.pop_front();
m_unk0x2c = p_time;
roiMap[1] = m_unk0x28->GetROI();
roiMap[1] = m_nextPizza->GetROI();
m_unk0x3c = roiMap[1]->GetLocal2World()[3];
roiMap[1]->SetVisibility(TRUE);
roiMap[2]->SetVisibility(TRUE);
}
if (m_unk0x28 == NULL) {
if (m_nextPizza == NULL) {
return;
}
}
@ -531,8 +1193,8 @@ void Act3Shark::Animate(float p_time)
}
else {
roiMap[1] = m_unk0x38;
((Act3*) m_world)->RemovePizza(*m_unk0x28);
m_unk0x28 = NULL;
((Act3*) m_world)->RemovePizza(*m_nextPizza);
m_nextPizza = NULL;
roiMap[1]->SetVisibility(FALSE);
roiMap[2]->SetVisibility(FALSE);
}

View File

@ -419,7 +419,7 @@ void Act3Ammo::Animate(float p_time)
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->m_brickster->FUN_100417c0();
}

View File

@ -14,6 +14,8 @@
#include "legoworld.h"
#include "misc.h"
#include "mxdebug.h"
#include "mxmisc.h"
#include "mxtimer.h"
#include "mxtransitionmanager.h"
#include "scripts.h"
@ -405,7 +407,7 @@ void Helicopter::Animate(float p_time)
Vector3 v2(m_unk0x1a8[3]);
float* loc = m_unk0x1a8[3];
mat.SetIdentity();
m_unk0x1f4.Unknown6(mat, f2);
m_unk0x1f4.BETA_1004aaa0(mat, f2);
v2.SetVector(loc);
v2 -= v;
v2 *= f2;
@ -425,10 +427,47 @@ void Helicopter::Animate(float p_time)
}
}
// STUB: LEGO1 0x100042a0
// FUNCTION: LEGO1 0x100042a0
void Helicopter::FUN_100042a0(const Matrix4& p_matrix)
{
// TODO
MxMatrix local48;
MxMatrix local90;
Vector3 vec1(local48[3]); // local98 // esp+0x30
Vector3 vec2(local90[3]); // localac // esp+0x1c
Vector3 vec3(m_unk0x1a8[0]); // locala8 // esp+0x20
Vector3 vec4(m_unk0x1a8[1]); // localb8 // esp+0x10
Vector3 vec5(m_unk0x1a8[2]); // EDI
Vector3 vec6(m_unk0x1a8[3]); // locala0 // esp+0x28
m_world->GetCamera()->FUN_100123b0(local48);
m_unk0x1a8.SetIdentity();
local90 = p_matrix;
vec2[1] += 20.0f;
vec4 = vec2;
vec4 -= vec1;
vec4.Unitize();
vec5[0] = vec5[2] = 0.0f;
vec5[1] = -1.0f;
vec3.EqualsCross(&vec4, &vec5);
vec3.Unitize();
vec4.EqualsCross(&vec5, &vec3);
vec6 = vec2;
local90 = m_unk0x1a8;
m_unk0x160 = local48;
vec1.Clear();
vec2.Clear();
m_unk0x1f0 = Timer()->GetTime();
m_unk0x1f4.BETA_1004a9f0(local48);
m_unk0x1f4.FUN_10004620(local90);
m_unk0x1f4.FUN_10004520();
}
// FUNCTION: LEGO1 0x10004640
@ -439,3 +478,12 @@ void Helicopter::FUN_10004640(const Matrix4& 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

@ -359,7 +359,7 @@ void LegoCarBuild::VTable0x70()
m_unk0x2a0 = sqrt((MxDouble) DISTSQRD2(m_unk0x290, m_unk0x298));
m_unk0x25c.Unknown1(m_unk0x178, m_unk0x208);
m_unk0x25c.BETA_1004a9b0(m_unk0x178, m_unk0x208);
}
// FUNCTION: LEGO1 0x10023130
@ -407,7 +407,7 @@ void LegoCarBuild::FUN_10023130(MxLong p_x, MxLong p_y)
MxFloat local1c = sqrt((double) (NORMSQRD2(local20))) / m_unk0x2a0;
m_unk0x25c.Unknown6(local78, local1c);
m_unk0x25c.BETA_1004aaa0(local78, local1c);
local78[3][0] = m_unk0x178[3][0] + local18[0];
local78[3][1] = m_unk0x178[3][1] + local18[1];

View File

@ -2794,8 +2794,8 @@ void LegoAnimationManager::FUN_100648f0(LegoTranInfo* p_tranInfo, MxLong p_unk0x
LegoLocation* location = NavController()->GetLocation(p_tranInfo->m_location);
if (location != NULL) {
CalcLocalTransform(location->m_position, location->m_direction, location->m_up, m_unk0x484);
m_unk0x4cc.Unknown1(m_unk0x43c, m_unk0x484);
m_unk0x4cc.Unknown7();
m_unk0x4cc.BETA_1004a9b0(m_unk0x43c, m_unk0x484);
m_unk0x4cc.FUN_10004520();
}
else {
p_tranInfo->m_flags &= ~LegoTranInfo::c_bit1;
@ -2829,7 +2829,7 @@ void LegoAnimationManager::FUN_10064b50(MxLong p_time)
sub[1] = (m_unk0x484[3][1] - m_unk0x43c[3][1]) * und;
sub[2] = (m_unk0x484[3][2] - m_unk0x43c[3][2]) * und;
m_unk0x4cc.Unknown6(mat, (float) (p_time - m_unk0x434) / 1000.0f);
m_unk0x4cc.BETA_1004aaa0(mat, (float) (p_time - m_unk0x434) / 1000.0f);
VPV3(mat[3], m_unk0x43c[3], sub);
mat[3][3] = 1.0f;

View File

@ -336,7 +336,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
}
MxU32 version, status;
MxS16 count, area, act;
MxS16 count, actArea;
const char* lightPosition;
Read(&fileStorage, &version);
@ -348,8 +348,8 @@ MxResult LegoGameState::Load(MxULong p_slot)
Read(&fileStorage, &m_unk0x24);
Read(&fileStorage, &act);
SetCurrentAct((Act) act);
Read(&fileStorage, &actArea);
SetCurrentAct((Act) actArea);
Read(&fileStorage, &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) {
m_unk0x42c = e_undefined;
}
else {
m_unk0x42c = (Area) area;
m_unk0x42c = (Area) actArea;
}
result = SUCCESS;

View File

@ -140,6 +140,20 @@ void LegoCameraController::FUN_10012320(float p_angle)
m_matrix1.RotateY(p_angle);
}
// FUNCTION: LEGO1 0x100123b0
MxResult LegoCameraController::FUN_100123b0(Matrix4& p_matrix)
{
if (m_lego3DView) {
ViewROI* pov = m_lego3DView->GetPointOfView();
if (pov) {
p_matrix = pov->GetLocal2World();
return SUCCESS;
}
}
return FAILURE;
}
// FUNCTION: LEGO1 0x100123e0
// FUNCTION: BETA10 0x10068cb2
void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und)

View File

@ -920,68 +920,6 @@ MxResult LegoPathController::FUN_10048310(
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: BETA10 0x100b9160
MxS32 LegoPathController::FUN_1004a240(

View File

@ -19,6 +19,8 @@
#include "tgl/d3drm/impl.h"
#include "viewmanager/viewroi.h"
#include <stdio.h>
DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590)
DECOMP_SIZE_ASSERT(MxStopWatch, 0x18)
DECOMP_SIZE_ASSERT(MxFrequencyMeter, 0x20)
@ -390,10 +392,125 @@ inline void LegoVideoManager::DrawCursor()
->BltFast(m_cursorXCopy, m_cursorYCopy, m_cursorSurface, &m_cursorRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);
}
// STUB: LEGO1 0x1007bbc0
// FUNCTION: LEGO1 0x1007bbc0
void LegoVideoManager::DrawFPS()
{
// TODO
char zeros[8] = "0000.00";
if (m_unk0x528 == NULL) {
m_arialFont = CreateFontA(
12,
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_DONTCARE | VARIABLE_PITCH,
"Arial"
);
HDC dc = GetDC(NULL);
SelectObject(dc, m_arialFont);
GetTextExtentPointA(dc, zeros, strlen(zeros), &m_fpsSize);
ReleaseDC(NULL, dc);
m_unk0x528 = m_displaySurface->FUN_100bc8b0(m_fpsSize.cx, m_fpsSize.cy);
SetRect(&m_fpsRect, 0, 0, m_fpsSize.cx, m_fpsSize.cy);
if (m_unk0x528 == NULL) {
DeleteObject(m_arialFont);
m_arialFont = NULL;
return;
}
DDCOLORKEY colorKey;
memset(&colorKey, 0, sizeof(colorKey));
m_unk0x528->SetColorKey(DDCKEY_SRCBLT, &colorKey);
DDSURFACEDESC surfaceDesc;
memset(&surfaceDesc, 0, sizeof(surfaceDesc));
surfaceDesc.dwSize = sizeof(surfaceDesc);
if (m_unk0x528->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL) != DD_OK) {
m_unk0x528->Release();
DeleteObject(m_arialFont);
m_unk0x528 = NULL;
m_arialFont = NULL;
}
else {
DWORD i;
char* ptr = (char*) surfaceDesc.lpSurface;
for (i = 0; i < surfaceDesc.dwHeight; i++) {
memset(ptr, 0, surfaceDesc.dwWidth * surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8);
ptr += surfaceDesc.lPitch;
}
m_unk0x528->Unlock(surfaceDesc.lpSurface);
m_unk0x54c = Timer()->GetTime();
m_unk0x550 = 1.f;
}
}
else {
if (Timer()->GetTime() > m_unk0x54c + 5000.f) {
char buffer[32];
MxFloat time = (Timer()->GetTime() - m_unk0x54c) / 1000.0f;
MxS32 nb = sprintf(buffer, "%.02f", m_unk0x550 / time);
m_unk0x54c = Timer()->GetTime();
DDSURFACEDESC surfaceDesc;
memset(&surfaceDesc, 0, sizeof(surfaceDesc));
surfaceDesc.dwSize = sizeof(surfaceDesc);
if (m_unk0x528->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL) == DD_OK) {
DWORD i;
char* ptr = (char*) surfaceDesc.lpSurface;
for (i = 0; i < surfaceDesc.dwHeight; i++) {
memset(ptr, 0, surfaceDesc.dwWidth * surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8);
ptr += surfaceDesc.lPitch;
}
m_unk0x528->Unlock(surfaceDesc.lpSurface);
}
HDC dc;
if (m_unk0x528->GetDC(&dc) != DD_OK) {
m_unk0x528->Release();
m_unk0x528 = NULL;
DeleteObject(m_arialFont);
m_arialFont = NULL;
return;
}
SelectObject(dc, m_arialFont);
SetTextColor(dc, RGB(255, 255, 0));
SetBkColor(dc, RGB(0, 0, 0));
SetBkMode(dc, OPAQUE);
GetTextExtentPoint32A(dc, buffer, nb, &m_fpsSize);
RECT rect;
SetRect(&rect, 0, 0, m_fpsSize.cx, m_fpsSize.cy);
ExtTextOutA(dc, 0, 0, ETO_OPAQUE, &rect, buffer, nb, NULL);
m_unk0x528->ReleaseDC(dc);
m_unk0x550 = 1.f;
}
else {
m_unk0x550 += 1.f;
}
if (m_unk0x528 != NULL) {
m_displaySurface->GetDirectDrawSurface2()
->BltFast(20, 20, m_unk0x528, &m_fpsRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);
m_3dManager->GetLego3DView()->GetView()->ForceUpdate(20, 20, m_fpsRect.right, m_fpsRect.bottom);
}
}
}
// FUNCTION: LEGO1 0x1007c080
@ -531,7 +648,7 @@ void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue)
// FUNCTION: LEGO1 0x1007c4c0
void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride)
{
this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride);
m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride);
}
// FUNCTION: LEGO1 0x1007c4d0
@ -561,18 +678,112 @@ void LegoVideoManager::FUN_1007c520()
InputManager()->SetUnknown335(TRUE);
}
// STUB: LEGO1 0x1007c560
extern void ViewportDestroyCallback(IDirect3DRMObject*, void*);
// FUNCTION: LEGO1 0x1007c560
int LegoVideoManager::EnableRMDevice()
{
// TODO
return 0;
IDirect3DRMViewport* viewport;
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()
{
// TODO
return 0;
if (m_paused) {
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

View File

@ -845,6 +845,36 @@ 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
void Act3::FUN_10073a60()
{
m_unk0x421e--;
m_helicopterDots[m_unk0x421e]->Enable(FALSE);
}
// FUNCTION: LEGO1 0x10073a90
void Act3::Enable(MxBool p_enable)
{

View File

@ -878,9 +878,9 @@ inline void LegoAnimNodeData::GetTranslation(
c[3] = p_rotationKeys[i + 1].GetAngle();
}
b.Unknown4(a);
b.Unknown5(c);
b.Unknown6(
b.BETA_10180b80(a);
b.BETA_10180bc0(c);
b.BETA_1004aaa0(
p_matrix,
(p_time - p_rotationKeys[i].GetTime()) / (p_rotationKeys[i + 1].GetTime() - p_rotationKeys[i].GetTime())
);

View File

@ -19,6 +19,12 @@ struct LegoEdge {
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
// LegoEdge::`scalar deleting destructor'

View File

@ -93,6 +93,8 @@ struct LegoUnknown100db7f4 : public LegoEdge {
// FUNCTION: BETA10 0x1001cc60
LegoU32 GetMask0x03() { return m_flags & (c_bit1 | c_bit2); }
inline LegoU32 FUN_10048c40(const Vector3& p_position);
// SYNTHETIC: LEGO1 0x1009a6c0
// LegoUnknown100db7f4::`scalar deleting destructor'
@ -101,4 +103,66 @@ struct LegoUnknown100db7f4 : public LegoEdge {
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

View File

@ -33,6 +33,9 @@ class Mx3DPointFloat : public Vector3 {
// FUNCTION: LEGO1 0x10003c10
virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88
// FUNCTION: BETA10 0x10015240
// ??4Mx3DPointFloat@@QAEAAV0@ABV0@@Z
// FUNCTION: BETA10 0x10013460
float& operator[](int idx) { return m_data[idx]; }
@ -102,35 +105,36 @@ class UnknownMx4DPointFloat {
UnknownMx4DPointFloat() : m_unk0x30(0) {}
// FUNCTION: BETA10 0x1004a9b0
void Unknown1(Matrix4& p_m1, Matrix4& p_m2)
void BETA_1004a9b0(Matrix4& p_m1, Matrix4& p_m2)
{
Unknown2(p_m1);
Unknown3(p_m2);
BETA_1004a9f0(p_m1);
FUN_10004620(p_m2);
}
// FUNCTION: BETA10 0x1004a9f0
void Unknown2(Matrix4& p_m)
void BETA_1004a9f0(Matrix4& p_m)
{
p_m.ToQuaternion(m_unk0x00);
m_unk0x30 |= c_bit1;
}
// FUNCTION: LEGO1 0x10004620
// FUNCTION: BETA10 0x1004aa30
void Unknown3(Matrix4& p_m)
void FUN_10004620(Matrix4& p_m)
{
p_m.ToQuaternion(m_unk0x18);
m_unk0x30 |= c_bit2;
}
// FUNCTION: BETA10 0x10180b80
void Unknown4(Vector4& p_v)
void BETA_10180b80(Vector4& p_v)
{
m_unk0x00 = p_v;
m_unk0x30 |= c_bit1;
}
// FUNCTION: BETA10 0x10180bc0
void Unknown5(Vector4& p_v)
void BETA_10180bc0(Vector4& p_v)
{
m_unk0x18 = p_v;
m_unk0x30 |= c_bit2;
@ -140,8 +144,8 @@ class UnknownMx4DPointFloat {
const Vector4& GetUnknown0x18() const { return m_unk0x18; }
undefined4 GetUnknown0x30() const { return m_unk0x30; }
inline int Unknown6(Matrix4& p_matrix, float p_f);
inline void Unknown7();
inline int BETA_1004aaa0(Matrix4& p_matrix, float p_f);
inline long FUN_10004520();
private:
inline int FUN_100040a0(Vector4& p_v, float p_f);
@ -152,7 +156,7 @@ class UnknownMx4DPointFloat {
};
// FUNCTION: BETA10 0x1004aaa0
int UnknownMx4DPointFloat::Unknown6(Matrix4& p_matrix, float p_f)
int UnknownMx4DPointFloat::BETA_1004aaa0(Matrix4& p_matrix, float p_f)
{
float data[4];
Vector4 v(data);
@ -165,22 +169,27 @@ int UnknownMx4DPointFloat::Unknown6(Matrix4& p_matrix, float p_f)
}
}
inline void UnknownMx4DPointFloat::Unknown7()
// FUNCTION: LEGO1 0x10004520
inline long UnknownMx4DPointFloat::FUN_10004520()
{
if (m_unk0x30) {
Mx4DPointFloat v1;
Mx4DPointFloat v2;
v1 = m_unk0x00;
v1 += m_unk0x18;
v2 = m_unk0x00;
v2 -= m_unk0x18;
if (v1.Dot(&v1, &v1) < v2.Dot(&v2, &v2)) {
m_unk0x18 *= -1.0f;
}
if (!m_unk0x30) {
return -1;
}
Mx4DPointFloat v1;
Mx4DPointFloat v2;
v1 = m_unk0x00;
v1 += m_unk0x18;
v2 = m_unk0x00;
v2 -= m_unk0x18;
if (v1.Dot(&v1, &v1) < v2.Dot(&v2, &v2)) {
m_unk0x18 *= -1.0f;
}
return 0;
}
// FUNCTION: LEGO1 0x100040a0

View File

@ -99,16 +99,18 @@ class MxDisplaySurface : public MxCore {
LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return m_ddSurface2; }
MxVideoParam& GetVideoParam() { return m_videoParam; }
void FUN_100bb500(
MxU8** p_bitmapData,
MxU8** p_surfaceData,
void DrawTransparentRLE(
MxU8*& p_bitmapData,
MxU8*& p_surfaceData,
MxU32 p_bitmapSize,
MxS32 p_width,
MxS32 p_height,
MxLong p_pitch,
MxU32 p_bpp
MxU8 p_bpp
);
LPDIRECTDRAWSURFACE FUN_100bc8b0(MxS32 width, MxS32 height);
private:
MxU8 CountTotalBitsSetTo1(MxU32 p_param);
MxU8 CountContiguousBitsSetTo1(MxU32 p_param);

View File

@ -338,42 +338,47 @@ MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_
}
// FUNCTION: LEGO1 0x100c6df0
// FUNCTION: BETA10 0x10157e0a
MxU8* MxDSBuffer::SkipToData()
{
MxU8* result = NULL;
if (m_pIntoBuffer != NULL) {
do {
MxU32* ptr = (MxU32*) m_pIntoBuffer;
switch (*ptr) {
case FOURCC('L', 'I', 'S', 'T'):
case FOURCC('R', 'I', 'F', 'F'):
m_pIntoBuffer = (MxU8*) (ptr + 3);
break;
while (TRUE) {
switch (*(MxU32*) m_pIntoBuffer) {
case FOURCC('M', 'x', 'O', 'b'):
case FOURCC('M', 'x', 'C', 'h'):
result = m_pIntoBuffer;
m_pIntoBuffer = (MxU8*) ptr + ((ptr[1] & 1) + ptr[1]);
m_pIntoBuffer = (MxU8*) ((MxU32*) m_pIntoBuffer + 2);
if (m_pBuffer + (m_writeOffset - 8) < m_pIntoBuffer) {
m_pIntoBuffer2 = result;
m_pIntoBuffer += (*(MxU32*) (m_pIntoBuffer + 4) & 1) + *(MxU32*) (m_pIntoBuffer + 4);
m_pIntoBuffer += 8;
if (m_pBuffer + m_writeOffset - 8 < m_pIntoBuffer) {
m_pIntoBuffer = NULL;
return result;
}
goto done;
case FOURCC('M', 'x', 'D', 'a'):
case FOURCC('M', 'x', 'S', 't'):
m_pIntoBuffer = (MxU8*) (ptr + 2);
m_pIntoBuffer += 8;
break;
case FOURCC('M', 'x', 'H', 'd'):
m_pIntoBuffer = (MxU8*) ptr + (ptr[1] + 8);
m_pIntoBuffer += *(MxU32*) (m_pIntoBuffer + 4) + 8;
break;
case FOURCC('L', 'I', 'S', 'T'):
case FOURCC('R', 'I', 'F', 'F'):
m_pIntoBuffer += 12;
break;
default:
m_pIntoBuffer = NULL;
m_pIntoBuffer2 = NULL;
return NULL;
result = NULL;
goto done;
}
} while (m_pIntoBuffer <= m_pBuffer + (m_writeOffset - 8));
if (m_pIntoBuffer > m_pBuffer + m_writeOffset - 8) {
m_pIntoBuffer = NULL;
goto done;
}
}
}
done:
m_pIntoBuffer2 = result;

View File

@ -529,7 +529,7 @@ void MxDisplaySurface::VTable0x30(
MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch);
if (p_und) {
MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage;
FUN_100bb500(&data, &surface, size, p_width, p_height, ddsd.lPitch, 8);
DrawTransparentRLE(data, surface, size, p_width, p_height, ddsd.lPitch, 8);
}
else {
MxLong stride = -p_width + GetAdjustedStride(p_bitmap);
@ -555,7 +555,7 @@ void MxDisplaySurface::VTable0x30(
MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch);
if (p_und) {
MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage;
FUN_100bb500(&data, &surface, size, p_width, p_height, ddsd.lPitch, 16);
DrawTransparentRLE(data, surface, size, p_width, p_height, ddsd.lPitch, 16);
}
else {
MxLong stride = -p_width + GetAdjustedStride(p_bitmap);
@ -584,19 +584,159 @@ void MxDisplaySurface::VTable0x30(
m_ddSurface2->Unlock(ddsd.lpSurface);
}
// STUB: LEGO1 0x100bb500
// STUB: BETA10 0x10140cd6
void MxDisplaySurface::FUN_100bb500(
MxU8** p_bitmapData,
MxU8** p_surfaceData,
// FUNCTION: LEGO1 0x100bb500
// FUNCTION: BETA10 0x10140cd6
void MxDisplaySurface::DrawTransparentRLE(
MxU8*& p_bitmapData,
MxU8*& p_surfaceData,
MxU32 p_bitmapSize,
MxS32 p_width,
MxS32 p_height,
MxLong p_pitch,
MxU32 p_bpp
MxU8 p_bpp
)
{
// TODO
/* Assumes partial RLE for the bitmap: only the skipped pixels are compressed.
The drawn pixels are uncompressed. The procedure is:
1. Read 3 bytes from p_bitmapData. Skip this many pixels on the surface.
2. Read 3 bytes from p_bitmapData. Draw this many pixels on the surface.
3. Repeat until the end of p_bitmapData is reached. */
MxU8* end = p_bitmapData + p_bitmapSize;
MxU8* surfCopy = p_surfaceData; // unused?
// The total number of pixels drawn or skipped
MxU32 count = 0;
// Used in both 8 and 16 bit branches
MxU32 skipCount;
MxU32 drawCount;
MxU32 t;
if (p_bpp == 16) {
// DECOMP: why goto?
goto sixteen_bit;
}
while (p_bitmapData < end) {
skipCount = *p_bitmapData++;
t = *p_bitmapData++;
skipCount += t << 8;
t = *p_bitmapData++;
skipCount += t << 16;
MxS32 rowRemainder = p_width - count % p_width;
count += skipCount;
if (skipCount >= rowRemainder) {
p_surfaceData += rowRemainder; // skip the rest of this row
skipCount -= rowRemainder;
p_surfaceData += p_pitch - p_width; // seek to start of next row
p_surfaceData += p_pitch * (skipCount / p_width); // skip entire rows if any
}
// skip any pixels at the start of this row
p_surfaceData += skipCount % p_width;
if (p_bitmapData >= end) {
break;
}
drawCount = *p_bitmapData++;
t = *p_bitmapData++;
drawCount += t << 8;
t = *p_bitmapData++;
drawCount += t << 16;
rowRemainder = p_width - count % p_width;
count += drawCount;
if (drawCount >= rowRemainder) {
memcpy(p_surfaceData, p_bitmapData, rowRemainder);
p_surfaceData += rowRemainder;
p_bitmapData += rowRemainder;
drawCount -= rowRemainder;
// seek to start of bitmap on this screen row
p_surfaceData += p_pitch - p_width;
MxS32 rows = drawCount / p_width;
for (MxU32 i = 0; i < rows; i++) {
memcpy(p_surfaceData, p_bitmapData, p_width);
p_bitmapData += p_width;
p_surfaceData += p_pitch;
}
}
MxS32 tail = drawCount % p_width;
memcpy(p_surfaceData, p_bitmapData, tail);
p_surfaceData += tail;
p_bitmapData += tail;
}
return;
sixteen_bit:
while (p_bitmapData < end) {
skipCount = *p_bitmapData++;
t = *p_bitmapData++;
skipCount += t << 8;
t = *p_bitmapData++;
skipCount += t << 16;
MxS32 rowRemainder = p_width - count % p_width;
count += skipCount;
if (skipCount >= rowRemainder) {
p_surfaceData += 2 * rowRemainder;
skipCount -= rowRemainder;
p_surfaceData += p_pitch - 2 * p_width;
p_surfaceData += p_pitch * (skipCount / p_width);
}
p_surfaceData += 2 * (skipCount % p_width);
if (p_bitmapData >= end) {
break;
}
drawCount = *p_bitmapData++;
t = *p_bitmapData++;
drawCount += t << 8;
t = *p_bitmapData++;
drawCount += t << 16;
rowRemainder = p_width - count % p_width;
count += drawCount;
if (drawCount >= rowRemainder) {
// memcpy
for (MxU32 j = 0; j < rowRemainder; j++) {
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
p_surfaceData += 2;
}
drawCount -= rowRemainder;
p_surfaceData += p_pitch - 2 * p_width;
MxS32 rows = drawCount / p_width;
for (MxU32 i = 0; i < rows; i++) {
// memcpy
for (MxS32 j = 0; j < p_width; j++) {
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
p_surfaceData += 2;
}
p_surfaceData += p_pitch - 2 * p_width;
}
}
MxS32 tail = drawCount % p_width;
// memcpy
for (MxS32 j = 0; j < tail; j++) {
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
p_surfaceData += 2;
}
}
}
// STUB: LEGO1 0x100bb850
@ -952,3 +1092,39 @@ MxBool MxDisplaySurface::VTable0x2c(
{
return 0;
}
// FUNCTION: LEGO1 0x100bc8b0
LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bc8b0(MxS32 width, MxS32 height)
{
LPDIRECTDRAWSURFACE surface = NULL;
LPDIRECTDRAW ddraw = MVideoManager()->GetDirectDraw();
MxVideoParam& unused = MVideoManager()->GetVideoParam();
DDSURFACEDESC surfaceDesc;
memset(&surfaceDesc, 0, sizeof(surfaceDesc));
surfaceDesc.dwSize = sizeof(surfaceDesc);
if (ddraw->GetDisplayMode(&surfaceDesc) != DD_OK) {
return NULL;
}
if (surfaceDesc.ddpfPixelFormat.dwRGBBitCount != 16) {
return NULL;
}
surfaceDesc.dwWidth = width;
surfaceDesc.dwHeight = height;
surfaceDesc.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
surfaceDesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
if (ddraw->CreateSurface(&surfaceDesc, &surface, NULL) != DD_OK) {
surfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
surfaceDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (ddraw->CreateSurface(&surfaceDesc, &surface, NULL) != DD_OK) {
return NULL;
}
}
return surface;
}

View File

@ -151,8 +151,25 @@ class Vector2 {
virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70
// FUNCTION: LEGO1 0x10002260
// FUNCTION: BETA10 0x100110c0
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: BETA10 0x100121e0
// Vector3::operator=

View File

@ -49,28 +49,23 @@ Result DeviceImpl::SetDither(int dither)
return ResultVal(m_data->SetDither(dither));
}
// Probably wrong, not sure what's going on in this method.
// FUNCTION: LEGO1 0x100a2ce0
void DeviceImpl::InitFromD3DDevice(Device*)
void DeviceImpl::HandleActivate(WORD wParam)
{
// Device argument is intentionally unused.
IDirect3DRMWinDevice* winDevice;
if (ResultVal(m_data->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) {
m_data->InitFromD3D((LPDIRECT3D) &winDevice, (LPDIRECT3DDEVICE) m_data);
winDevice->HandleActivate(wParam);
winDevice->Release();
}
}
// Really don't know what's going on here. Seems it will call down to Init
// but the decomp suggests it otherwise looks the same as InitFromD3D but Init
// takes widly different parameters.
// FUNCTION: LEGO1 0x100a2d20
void DeviceImpl::InitFromWindowsDevice(Device*)
void DeviceImpl::HandlePaint(HDC p_dc)
{
// Device argument is intentionally unused.
IDirect3DRMWinDevice* winDevice;
if (SUCCEEDED(m_data->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) {
// m_data->Init(??);
winDevice->HandlePaint(p_dc);
winDevice->Release();
}
}
@ -80,3 +75,6 @@ Result DeviceImpl::Update()
{
return ResultVal(m_data->Update());
}
// GLOBAL: LEGO1 0x100dd1d0
// IID_IDirect3DRMWinDevice

View File

@ -106,14 +106,89 @@ Result GroupImpl::Remove(const Group* pGroup)
return ResultVal(m_data->DeleteVisual(pGroupImpl->m_data));
}
// STUB: LEGO1 0x100a34b0
// FUNCTION: LEGO1 0x100a34b0
Result GroupImpl::RemoveAll()
{
return Error;
IDirect3DRMVisualArray* visuals;
IDirect3DRMFrame2* frame = m_data;
Result result = (Result) SUCCEEDED(frame->GetVisuals(&visuals));
if (result == Success) {
for (int i = 0; i < (int) visuals->GetSize(); i++) {
IDirect3DRMVisual* visual;
result = (Result) SUCCEEDED(visuals->GetElement(i, &visual));
frame->DeleteVisual(visual);
visual->Release();
}
visuals->Release();
}
return result;
}
// STUB: LEGO1 0x100a3540
Result GroupImpl::Unknown()
// FUNCTION: LEGO1 0x100a3540
Result GroupImpl::Bounds(D3DVECTOR* p_min, D3DVECTOR* p_max)
{
return Error;
D3DRMBOX size;
IDirect3DRMFrame2* frame = m_data;
size.min.x = 88888.f;
size.min.y = 88888.f;
size.min.z = 88888.f;
size.max.x = -88888.f;
size.max.y = -88888.f;
size.max.z = -88888.f;
IDirect3DRMVisualArray* visuals;
Result result = (Result) SUCCEEDED(frame->GetVisuals(&visuals));
if (result == Success) {
int i;
for (i = 0; i < (int) visuals->GetSize(); i++) {
IDirect3DRMVisual* visual;
visuals->GetElement(i, &visual);
IDirect3DRMMesh* mesh;
/*
* BUG: should be:
* visual->QueryInterface(IID_IDirect3DRMMesh, (void**)&mesh));
*/
result = (Result) SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMMeshBuilder, (void**) &mesh));
if (result == Success) {
D3DRMBOX box;
result = (Result) SUCCEEDED(mesh->GetBox(&box));
if (size.max.y < box.max.y) {
size.max.y = box.max.y;
}
if (size.max.z < box.max.z) {
size.max.z = box.max.z;
}
if (box.min.x < size.min.x) {
size.min.x = box.min.x;
}
if (box.min.y < size.min.y) {
size.min.y = box.min.y;
}
if (box.min.z < size.min.z) {
size.min.z = box.min.z;
}
if (size.max.x < box.max.x) {
size.max.x = box.max.x;
}
mesh->Release();
}
visual->Release();
}
visuals->Release();
}
*p_min = size.min;
*p_max = size.max;
return result;
}

View File

@ -145,10 +145,11 @@ class DeviceImpl : public Device {
// vtable+0x20
Result Update() override;
void InitFromD3DDevice(Device*) override;
void InitFromWindowsDevice(Device*) override;
void HandleActivate(WORD) override;
void HandlePaint(HDC) override;
IDirect3DRMDevice2* ImplementationData() const { return m_data; }
void SetImplementationData(IDirect3DRMDevice2* device) { m_data = device; }
friend class RendererImpl;
@ -199,6 +200,7 @@ class ViewImpl : public View {
) override;
IDirect3DRMViewport* ImplementationData() const { return m_data; }
void SetImplementationData(IDirect3DRMViewport* viewport) { m_data = viewport; }
static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*);
@ -333,7 +335,7 @@ class GroupImpl : public Group {
Result RemoveAll() override;
// vtable+0x30
Result Unknown() override;
Result Bounds(D3DVECTOR* p_min, D3DVECTOR* p_max) override;
IDirect3DRMFrame2* ImplementationData() const { return m_data; }
@ -543,4 +545,7 @@ inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DR
// SYNTHETIC: LEGO1 0x100a3d80
// TglImpl::MeshImpl::`scalar deleting destructor'
// GLOBAL: LEGO1 0x100dd1e0
// IID_IDirect3DRMMeshBuilder
} /* namespace TglImpl */

View File

@ -86,10 +86,46 @@ void TglD3DRMIMAGE::Destroy()
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)
{
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

View File

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

View File

@ -171,8 +171,8 @@ class Device : public Object {
// vtable+0x20
virtual Result Update() = 0;
virtual void InitFromD3DDevice(Device*) = 0;
virtual void InitFromWindowsDevice(Device*) = 0;
virtual void HandleActivate(WORD) = 0;
virtual void HandlePaint(HDC) = 0;
// SYNTHETIC: LEGO1 0x100a2350
// Tgl::Device::~Device
@ -305,7 +305,7 @@ class Group : public Object {
// This is TransformLocalToWorld in the leak, however it seems
// to have been replaced by something else in the shipped code.
virtual Result Unknown() = 0;
virtual Result Bounds(D3DVECTOR*, D3DVECTOR*) = 0;
// SYNTHETIC: LEGO1 0x100a2510
// Tgl::Group::~Group

View File

@ -31,5 +31,6 @@ targets:
- LegoWorld
ignore-functions:
# strcpy, strlen, ... (arguments are imported incorrectly)
- 0x100f8ad0
- 0x100fa200
- 0x100f9780