mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-28 10:41:15 +00:00
Merge branch 'master' of https://github.com/tahg/isletahg into extra
This commit is contained in:
commit
8fc00ea7dd
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@ -156,6 +156,13 @@ jobs:
|
||||
python3 tools/vtable/vtable.py legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB .
|
||||
python3 tools/vtable/vtable.py legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .
|
||||
|
||||
- name: Check Variables
|
||||
shell: bash
|
||||
run: |
|
||||
python3 tools/datacmp.py legobin/CONFIG.EXE build/CONFIG.EXE build/CONFIG.PDB .
|
||||
python3 tools/datacmp.py legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB .
|
||||
python3 tools/datacmp.py legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
|
||||
@ -297,7 +297,7 @@
|
||||
// GLOBAL: ISLE 0x4105b0
|
||||
// __shi_TaskRecord
|
||||
|
||||
// GLOBAL: ISLE 0x4125f8
|
||||
// ~GLOBAL: ISLE 0x4125f8
|
||||
// ?_pnhHeap@@3P6AHI@ZA
|
||||
|
||||
// GLOBAL: ISLE 0x412830
|
||||
|
||||
@ -35,8 +35,8 @@ class Act3 : public LegoWorld {
|
||||
MxBool VTable0x64() override; // vtable+0x64
|
||||
void Enable(MxBool p_enable) override; // vtable+0x68
|
||||
|
||||
inline void SetUnkown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; }
|
||||
inline void SetUnkown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; }
|
||||
inline void SetUnknown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; }
|
||||
inline void SetUnknown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10072630
|
||||
// Act3::`scalar deleting destructor'
|
||||
|
||||
@ -20,8 +20,7 @@ class BeachHouseEntity : public BuildingEntity {
|
||||
return !strcmp(p_name, BeachHouseEntity::ClassName()) || BuildingEntity::IsA(p_name);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100153b0
|
||||
MxLong VTable0x50(MxParam& p_param) override { return 0; }
|
||||
MxLong VTable0x50(MxParam& p_param) override;
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1000f970
|
||||
// BeachHouseEntity::`scalar deleting destructor'
|
||||
|
||||
@ -20,8 +20,7 @@ class GasStationEntity : public BuildingEntity {
|
||||
return !strcmp(p_name, GasStationEntity::ClassName()) || BuildingEntity::IsA(p_name);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100151d0
|
||||
MxLong VTable0x50(MxParam& p_param) override { return 0; }
|
||||
MxLong VTable0x50(MxParam& p_param) override;
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1000f890
|
||||
// GasStationEntity::`scalar deleting destructor'
|
||||
|
||||
@ -20,8 +20,7 @@ class InfoCenterEntity : public BuildingEntity {
|
||||
return !strcmp(p_name, InfoCenterEntity::ClassName()) || BuildingEntity::IsA(p_name);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100150c0
|
||||
MxLong VTable0x50(MxParam& p_param) override { return 0; }
|
||||
MxLong VTable0x50(MxParam& p_param) override; // vtable+0x50
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1000f7b0
|
||||
// InfoCenterEntity::`scalar deleting destructor'
|
||||
|
||||
@ -69,6 +69,7 @@ class Isle : public LegoWorld {
|
||||
void FUN_10031590();
|
||||
void FUN_10032620();
|
||||
void FUN_100330e0();
|
||||
void FUN_10033350();
|
||||
void FUN_10032d30(
|
||||
IsleScript::Script p_script,
|
||||
JukeboxScript::Script p_music,
|
||||
|
||||
@ -19,6 +19,8 @@ class LegoAct2 : public LegoWorld {
|
||||
MxBool VTable0x64() override; // vtable+0x64
|
||||
void Enable(MxBool p_enable) override; // vtable+0x68
|
||||
|
||||
inline void SetUnknown0x1150(undefined4 p_unk0x1150) { m_unk0x1150 = p_unk0x1150; }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1004fe20
|
||||
// LegoAct2::`scalar deleting destructor'
|
||||
|
||||
|
||||
@ -28,10 +28,11 @@ class LegoAct2State : public LegoState {
|
||||
// LegoAct2State::`scalar deleting destructor'
|
||||
|
||||
inline undefined4 GetUnknown0x08() { return m_unk0x08; }
|
||||
inline void SetUnknown0x0c(undefined p_unk0x0c) { m_unk0x0c = p_unk0x0c; }
|
||||
|
||||
private:
|
||||
undefined4 m_unk0x08; // 0x08
|
||||
undefined4 m_unk0x0c; // 0x0c
|
||||
undefined m_unk0x0c; // 0x0c
|
||||
};
|
||||
|
||||
#endif // LEGOACT2STATE_H
|
||||
|
||||
@ -10,13 +10,18 @@
|
||||
|
||||
// SIZE 0x18
|
||||
struct Character {
|
||||
char* m_name; // 0x00
|
||||
undefined m_unk0x04; // 0x04
|
||||
MxS8 m_vehicleId; // 0x05
|
||||
undefined m_unk0x06; // 0x06
|
||||
MxBool m_unk0x07; // 0x07
|
||||
undefined m_unk0x08[12]; // 0x08
|
||||
MxBool m_active; // 0x14
|
||||
char* m_name; // 0x00
|
||||
MxBool m_unk0x04; // 0x04
|
||||
MxS8 m_vehicleId; // 0x05
|
||||
undefined m_unk0x06; // 0x06 (unused?)
|
||||
MxBool m_unk0x07; // 0x07
|
||||
MxBool m_unk0x08; // 0x08
|
||||
MxBool m_unk0x09; // 0x09
|
||||
MxU32 m_unk0x0c; // 0x0c
|
||||
MxU32 m_unk0x10; // 0x10
|
||||
MxBool m_active; // 0x14
|
||||
MxU8 m_unk0x15; // 0x15
|
||||
MxU8 m_unk0x16; // 0x16
|
||||
};
|
||||
|
||||
// SIZE 0x08
|
||||
@ -62,10 +67,10 @@ class LegoAnimationManager : public MxCore {
|
||||
void FUN_1005f6d0(MxBool);
|
||||
void FUN_1005f700(MxBool);
|
||||
MxResult LoadScriptInfo(MxS32 p_scriptIndex);
|
||||
MxBool FUN_10060140(char* p_name, MxU32& p_index);
|
||||
MxBool FindVehicle(const char* p_name, MxU32& p_index);
|
||||
MxResult ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info);
|
||||
MxResult ReadModelInfo(LegoFile* p_file, ModelInfo* p_info);
|
||||
void FUN_100603c0();
|
||||
void DeleteAnimations();
|
||||
MxResult StartEntityAction(MxDSAction& p_dsAction, LegoEntity* p_entity);
|
||||
void FUN_10060570(MxBool);
|
||||
undefined4 FUN_10060dc0(
|
||||
|
||||
@ -10,8 +10,8 @@ class LegoBackgroundColor : public MxVariable {
|
||||
LegoBackgroundColor(const char* p_key, const char* p_value);
|
||||
|
||||
void SetValue(const char* p_colorString) override;
|
||||
void SetLights(float p_r, float p_g, float p_b);
|
||||
void SetLights();
|
||||
void SetLightColor(float p_r, float p_g, float p_b);
|
||||
void SetLightColor();
|
||||
void ToggleDayNight(MxBool);
|
||||
void ToggleSkyColor();
|
||||
|
||||
|
||||
@ -47,17 +47,19 @@ class LegoCharacterManager {
|
||||
|
||||
void Init();
|
||||
static void SetCustomizeAnimFile(const char* p_value);
|
||||
static MxBool FUN_10084c00(const LegoChar*);
|
||||
static MxBool Exists(const char* p_key);
|
||||
|
||||
void FUN_100832a0();
|
||||
MxU32 GetRefCount(LegoROI* p_roi);
|
||||
void FUN_10083db0(LegoROI* p_roi);
|
||||
void FUN_10083f10(LegoROI* p_roi);
|
||||
LegoExtraActor* FUN_10084c40(const LegoChar*);
|
||||
LegoCharacterData* Find(const char* p_key);
|
||||
LegoExtraActor* GetActor(const char* p_key);
|
||||
LegoCharacterData* GetData(const char* p_key);
|
||||
LegoCharacterData* GetData(LegoROI* p_roi);
|
||||
MxBool FUN_10084ec0(LegoROI* p_roi);
|
||||
MxU32 FUN_10085140(LegoROI*, MxBool);
|
||||
LegoROI* FUN_10085210(const LegoChar*, LegoChar*, undefined);
|
||||
LegoROI* FUN_10085a80(LegoChar* p_und1, LegoChar* p_und2, undefined p_und3);
|
||||
MxU32 FUN_10085140(LegoROI* p_roi, MxBool p_und);
|
||||
LegoROI* FUN_10085210(const char*, char*, undefined);
|
||||
LegoROI* FUN_10085a80(char* p_und1, char* p_und2, undefined p_und3);
|
||||
|
||||
static const char* GetCustomizeAnimFile() { return g_customizeAnimFile; }
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ void FUN_1003ef00(MxBool);
|
||||
void SetAppCursor(WPARAM p_wparam);
|
||||
MxBool FUN_1003ef60();
|
||||
MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId);
|
||||
MxS32 FUN_1003f050(MxS32);
|
||||
void SetLightPosition(MxU32);
|
||||
MxS32 UpdateLightPosition(MxS32 p_increase);
|
||||
void SetLightPosition(MxS32 p_index);
|
||||
LegoNamedTexture* ReadNamedTexture(LegoFile* p_file);
|
||||
void FUN_1003f540(LegoFile* p_file, const char* p_filename);
|
||||
void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_texture);
|
||||
|
||||
@ -20,7 +20,7 @@ class PoliceEntity : public BuildingEntity {
|
||||
return !strcmp(p_name, PoliceEntity::ClassName()) || BuildingEntity::IsA(p_name);
|
||||
}
|
||||
|
||||
MxLong VTable0x50(MxParam& p_param) override;
|
||||
MxLong VTable0x50(MxParam& p_param) override; // vtable+0x50
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1000f900
|
||||
// PoliceEntity::`scalar deleting destructor'
|
||||
|
||||
@ -19,8 +19,7 @@ class RaceStandsEntity : public BuildingEntity {
|
||||
return !strcmp(p_name, RaceStandsEntity::ClassName()) || BuildingEntity::IsA(p_name);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10015450
|
||||
MxLong VTable0x50(MxParam& p_param) override { return 0; }
|
||||
MxLong VTable0x50(MxParam& p_param) override;
|
||||
|
||||
// SYNTHETIC: LEGO1 0x1000f9e0
|
||||
// RaceStandsEntity::`scalar deleting destructor'
|
||||
|
||||
@ -41,7 +41,7 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction)
|
||||
LegoWorld* world = CurrentWorld();
|
||||
SetWorld(world);
|
||||
if (world->IsA("Act3")) {
|
||||
((Act3*) GetWorld())->SetUnkown420c(this);
|
||||
((Act3*) GetWorld())->SetUnknown420c(this);
|
||||
}
|
||||
world = GetWorld();
|
||||
if (world) {
|
||||
@ -160,7 +160,7 @@ MxU32 Helicopter::VTable0xd4(LegoControlManagerEvent& p_param)
|
||||
switch (p_param.GetClickedObjectId()) {
|
||||
case IsleScript::c_HelicopterArms_Ctl:
|
||||
if (*g_act3Script == script) {
|
||||
((Act3*) CurrentWorld())->SetUnkown4270(2);
|
||||
((Act3*) CurrentWorld())->SetUnknown4270(2);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
else if (m_state->GetUnkown8() != 0) {
|
||||
|
||||
@ -15,11 +15,66 @@ DECOMP_SIZE_ASSERT(Vehicle, 0x8)
|
||||
DECOMP_SIZE_ASSERT(Unknown0x3c, 0x18)
|
||||
|
||||
// GLOBAL: LEGO1 0x100f6d20
|
||||
Vehicle g_vehicles[] = {"bikebd", 0, FALSE, "bikepg", 0, FALSE, "bikerd", 0, FALSE, "bikesy", 0,
|
||||
FALSE, "motoni", 0, FALSE, "motola", 0, FALSE, "board", 0, FALSE};
|
||||
Vehicle g_vehicles[] = {
|
||||
{"bikebd", 0, FALSE},
|
||||
{"bikepg", 0, FALSE},
|
||||
{"bikerd", 0, FALSE},
|
||||
{"bikesy", 0, FALSE},
|
||||
{"motoni", 0, FALSE},
|
||||
{"motola", 0, FALSE},
|
||||
{"board", 0, FALSE}
|
||||
};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f7048
|
||||
Character g_characters[47]; // TODO: Initialize this
|
||||
Character g_characters[47] = {
|
||||
{"pepper", FALSE, 6, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 50, 1},
|
||||
{"mama", FALSE, -1, 0, FALSE, FALSE, FALSE, 1500, 20000, FALSE, 0, 2},
|
||||
{"papa", FALSE, -1, 0, FALSE, FALSE, FALSE, 1500, 20000, FALSE, 0, 3},
|
||||
{"nick", FALSE, 4, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 20, 4},
|
||||
{"laura", FALSE, 5, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 20, 5},
|
||||
{"brickstr", FALSE, -1, 0, FALSE, FALSE, FALSE, 1000, 20000, FALSE, 0, 6},
|
||||
{"studs", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"rhoda", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"valerie", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"snap", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"pt", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"mg", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"bu", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"ml", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"nu", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"na", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"cl", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"en", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"re", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"ro", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"d1", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"d2", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"d3", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"d4", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l1", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l2", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l3", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l4", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l5", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"l6", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"b1", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"b2", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"b3", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"b4", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"cm", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"gd", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"rd", FALSE, 2, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 50, 9},
|
||||
{"pg", FALSE, 1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 50, 8},
|
||||
{"bd", FALSE, 0, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 100, 7},
|
||||
{"sy", FALSE, 3, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 100, 10},
|
||||
{"gn", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"df", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"bs", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"lt", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"st", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"bm", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0},
|
||||
{"jk", FALSE, -1, 0, FALSE, FALSE, TRUE, 1500, 20000, FALSE, 0, 0}
|
||||
};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f74f8
|
||||
MxS32 g_legoAnimationManagerConfig = 1;
|
||||
@ -118,7 +173,7 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex)
|
||||
m_animState->FUN_10065240(m_animCount, m_anims, m_unk0x3fc);
|
||||
}
|
||||
|
||||
FUN_100603c0();
|
||||
DeleteAnimations();
|
||||
|
||||
LegoFile file;
|
||||
|
||||
@ -199,7 +254,7 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex)
|
||||
for (MxS32 m = 0; m < m_anims[j].m_modelCount; m++) {
|
||||
MxU32 n;
|
||||
|
||||
if (FUN_10060140(m_anims[j].m_models[m].m_modelName, n) && m_anims[j].m_models[m].m_unk0x2c) {
|
||||
if (FindVehicle(m_anims[j].m_models[m].m_modelName, n) && m_anims[j].m_models[m].m_unk0x2c) {
|
||||
m_anims[j].m_unk0x2a[count++] = n;
|
||||
if (count > 3) {
|
||||
break;
|
||||
@ -233,16 +288,22 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex)
|
||||
|
||||
done:
|
||||
if (result == FAILURE) {
|
||||
FUN_100603c0();
|
||||
DeleteAnimations();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10060140
|
||||
MxBool LegoAnimationManager::FUN_10060140(char* p_name, MxU32& p_index)
|
||||
// FUNCTION: LEGO1 0x10060140
|
||||
MxBool LegoAnimationManager::FindVehicle(const char* p_name, MxU32& p_index)
|
||||
{
|
||||
// TODO
|
||||
for (MxS32 i = 0; i < _countof(g_vehicles); i++) {
|
||||
if (!strcmpi(p_name, g_vehicles[i].m_name)) {
|
||||
p_index = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -347,10 +408,29 @@ MxResult LegoAnimationManager::ReadModelInfo(LegoFile* p_file, ModelInfo* p_info
|
||||
return result;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100603c0
|
||||
void LegoAnimationManager::FUN_100603c0()
|
||||
// FUNCTION: LEGO1 0x100603c0
|
||||
void LegoAnimationManager::DeleteAnimations()
|
||||
{
|
||||
// TODO
|
||||
undefined unk0x42b = m_unk0x42b;
|
||||
|
||||
if (m_anims != NULL) {
|
||||
for (MxS32 i = 0; i < m_animCount; i++) {
|
||||
delete m_anims[i].m_animName;
|
||||
|
||||
if (m_anims[i].m_models != NULL) {
|
||||
for (MxS32 j = 0; j < m_anims[i].m_modelCount; j++) {
|
||||
delete m_anims[i].m_models[j].m_modelName;
|
||||
}
|
||||
|
||||
delete m_anims[i].m_models;
|
||||
}
|
||||
}
|
||||
|
||||
delete m_anims;
|
||||
}
|
||||
|
||||
Init();
|
||||
m_unk0x42b = unk0x42b;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10060570
|
||||
@ -366,7 +446,7 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt
|
||||
LegoROI* roi = p_entity->GetROI();
|
||||
|
||||
if (p_entity->GetUnknown0x59() == 0) {
|
||||
LegoPathActor* actor = CharacterManager()->FUN_10084c40(roi->GetName());
|
||||
LegoPathActor* actor = CharacterManager()->GetActor(roi->GetName());
|
||||
|
||||
if (actor) {
|
||||
LegoPathController* controller = actor->GetController();
|
||||
|
||||
@ -91,7 +91,7 @@ void LegoBackgroundColor::ToggleDayNight(MxBool p_sun)
|
||||
float convertedR, convertedG, convertedB;
|
||||
ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
|
||||
VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
|
||||
SetLights(convertedR, convertedG, convertedB);
|
||||
SetLightColor(convertedR, convertedG, convertedB);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003c330
|
||||
@ -110,18 +110,39 @@ void LegoBackgroundColor::ToggleSkyColor()
|
||||
float convertedR, convertedG, convertedB;
|
||||
ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
|
||||
VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
|
||||
SetLights(convertedR, convertedG, convertedB);
|
||||
SetLightColor(convertedR, convertedG, convertedB);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1003c400
|
||||
void LegoBackgroundColor::SetLights(float p_r, float p_g, float p_b)
|
||||
// FUNCTION: LEGO1 0x1003c400
|
||||
void LegoBackgroundColor::SetLightColor(float p_r, float p_g, float p_b)
|
||||
{
|
||||
if (!VideoManager()->GetVideoParam().Flags().GetF2bit0()) {
|
||||
// TODO: Computed constants based on what?
|
||||
p_r *= 4.3478260869565215;
|
||||
p_g *= 1.5873015873015872;
|
||||
p_b *= 1.1764705882352942;
|
||||
|
||||
if (p_r > 1.0) {
|
||||
p_r = 1.0;
|
||||
}
|
||||
|
||||
if (p_g > 1.0) {
|
||||
p_g = 1.0;
|
||||
}
|
||||
|
||||
if (p_b > 1.0) {
|
||||
p_b = 1.0;
|
||||
}
|
||||
|
||||
VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(FALSE, p_r, p_g, p_b);
|
||||
VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(TRUE, p_r, p_g, p_b);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003c4b0
|
||||
void LegoBackgroundColor::SetLights()
|
||||
void LegoBackgroundColor::SetLightColor()
|
||||
{
|
||||
float convertedR, convertedG, convertedB;
|
||||
ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
|
||||
SetLights(convertedR, convertedG, convertedB);
|
||||
SetLightColor(convertedR, convertedG, convertedB);
|
||||
}
|
||||
|
||||
@ -17,6 +17,12 @@ DECOMP_SIZE_ASSERT(LegoCharacterManager, 0x08)
|
||||
// GLOBAL: LEGO1 0x100fc4e4
|
||||
char* LegoCharacterManager::g_customizeAnimFile = NULL;
|
||||
|
||||
// GLOBAL: LEGO1 0x100fc4d8
|
||||
MxU32 g_unk0x100fc4d8 = 50;
|
||||
|
||||
// GLOBAL: LEGO1 0x100fc4dc
|
||||
MxU32 g_unk0x100fc4dc = 66;
|
||||
|
||||
// GLOBAL: LEGO1 0x10104f20
|
||||
LegoCharacterData g_characterData[66];
|
||||
|
||||
@ -38,10 +44,26 @@ void LegoCharacterManager::Init()
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100832a0
|
||||
// FUNCTION: LEGO1 0x100832a0
|
||||
void LegoCharacterManager::FUN_100832a0()
|
||||
{
|
||||
// TODO
|
||||
for (MxS32 i = 0; i < _countof(g_characterData); i++) {
|
||||
LegoCharacterData* data = GetData(g_characterData[i].m_name);
|
||||
|
||||
if (data != NULL) {
|
||||
LegoExtraActor* actor = data->m_actor;
|
||||
|
||||
if (actor != NULL && actor->IsA("LegoExtraActor")) {
|
||||
LegoROI* roi = g_characterData[i].m_roi;
|
||||
MxU32 refCount = GetRefCount(roi);
|
||||
|
||||
while (refCount != 0) {
|
||||
FUN_10083db0(roi);
|
||||
refCount = GetRefCount(roi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10083310
|
||||
@ -49,7 +71,7 @@ MxResult LegoCharacterManager::Write(LegoStorage* p_storage)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
for (MxS32 i = 0; i < _countof(g_characterData) - 1; i++) {
|
||||
for (MxS32 i = 0; i < _countof(g_characterData); i++) {
|
||||
LegoCharacterData* data = &g_characterData[i];
|
||||
|
||||
if (p_storage->Write(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) {
|
||||
@ -95,7 +117,7 @@ MxResult LegoCharacterManager::Read(LegoStorage* p_storage)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
for (MxS32 i = 0; i < _countof(g_characterData) - 1; i++) {
|
||||
for (MxS32 i = 0; i < _countof(g_characterData); i++) {
|
||||
LegoCharacterData* data = &g_characterData[i];
|
||||
|
||||
if (p_storage->Read(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) {
|
||||
@ -180,7 +202,7 @@ LegoROI* LegoCharacterManager::GetROI(const char* p_key, MxBool p_createEntity)
|
||||
actor->SetROI(character->m_roi, FALSE, FALSE);
|
||||
actor->FUN_100114e0(0);
|
||||
actor->SetFlag(LegoActor::c_bit2);
|
||||
Find(p_key)->m_actor = actor;
|
||||
GetData(p_key)->m_actor = actor;
|
||||
}
|
||||
|
||||
return character->m_roi;
|
||||
@ -189,6 +211,23 @@ LegoROI* LegoCharacterManager::GetROI(const char* p_key, MxBool p_createEntity)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10083bc0
|
||||
MxU32 LegoCharacterManager::GetRefCount(LegoROI* p_roi)
|
||||
{
|
||||
LegoCharacterMap::iterator it;
|
||||
|
||||
for (it = m_characters->begin(); it != m_characters->end(); it++) {
|
||||
LegoCharacter* character = (*it).second;
|
||||
LegoROI* roi = character->m_roi;
|
||||
|
||||
if (roi == p_roi) {
|
||||
return character->m_refCount;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10083db0
|
||||
void LegoCharacterManager::FUN_10083db0(LegoROI* p_roi)
|
||||
{
|
||||
@ -215,21 +254,21 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key)
|
||||
Tgl::Renderer* renderer = VideoManager()->GetRenderer();
|
||||
ViewLODListManager* lodManager = GetViewLODListManager();
|
||||
LegoTextureContainer* textureContainer = TextureContainer();
|
||||
LegoCharacterData* characterData = Find(p_key);
|
||||
LegoCharacterData* data = GetData(p_key);
|
||||
|
||||
if (characterData == NULL) {
|
||||
if (data == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!strcmpi(p_key, "pep")) {
|
||||
LegoCharacterData* pepper = Find("pepper");
|
||||
LegoCharacterData* pepper = GetData("pepper");
|
||||
|
||||
characterData->m_unk0x0c = pepper->m_unk0x0c;
|
||||
characterData->m_unk0x10 = pepper->m_unk0x10;
|
||||
characterData->m_unk0x14 = pepper->m_unk0x14;
|
||||
data->m_unk0x0c = pepper->m_unk0x0c;
|
||||
data->m_unk0x10 = pepper->m_unk0x10;
|
||||
data->m_unk0x14 = pepper->m_unk0x14;
|
||||
|
||||
for (i = 0; i < _countof(characterData->m_parts); i++) {
|
||||
characterData->m_parts[i] = pepper->m_parts[i];
|
||||
for (i = 0; i < _countof(data->m_parts); i++) {
|
||||
data->m_parts[i] = pepper->m_parts[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +299,7 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key)
|
||||
const char* parentName;
|
||||
char lodName[64];
|
||||
|
||||
LegoCharacterData::Part& part = characterData->m_parts[i];
|
||||
LegoCharacterData::Part& part = data->m_parts[i];
|
||||
|
||||
if (i == 0 || i == 1) {
|
||||
parentName = part.m_unk0x04[part.m_unk0x00[part.m_unk0x08]];
|
||||
@ -338,7 +377,7 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key)
|
||||
);
|
||||
roi->WrappedSetLocalTransform(mat);
|
||||
|
||||
characterData->m_roi = roi;
|
||||
data->m_roi = roi;
|
||||
success = TRUE;
|
||||
|
||||
done:
|
||||
@ -350,25 +389,36 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key)
|
||||
return roi;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10084c00
|
||||
MxBool LegoCharacterManager::FUN_10084c00(const LegoChar*)
|
||||
// FUNCTION: LEGO1 0x10084c00
|
||||
MxBool LegoCharacterManager::Exists(const char* p_key)
|
||||
{
|
||||
// TODO
|
||||
for (MxU32 i = 0; i < _countof(g_characterData); i++) {
|
||||
if (!strcmpi(g_characterData[i].m_name, p_key)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10084c40
|
||||
LegoExtraActor* LegoCharacterManager::FUN_10084c40(const LegoChar*)
|
||||
// FUNCTION: LEGO1 0x10084c40
|
||||
LegoExtraActor* LegoCharacterManager::GetActor(const char* p_key)
|
||||
{
|
||||
LegoCharacterData* data = GetData(p_key);
|
||||
|
||||
if (data != NULL) {
|
||||
return data->m_actor;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10084c60
|
||||
LegoCharacterData* LegoCharacterManager::Find(const char* p_key)
|
||||
LegoCharacterData* LegoCharacterManager::GetData(const char* p_key)
|
||||
{
|
||||
MxU32 i;
|
||||
|
||||
for (i = 0; i < _countof(g_characterData) - 1; i++) {
|
||||
for (i = 0; i < _countof(g_characterData); i++) {
|
||||
if (!strcmpi(g_characterData[i].m_name, p_key)) {
|
||||
break;
|
||||
}
|
||||
@ -381,6 +431,24 @@ LegoCharacterData* LegoCharacterManager::Find(const char* p_key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10084cb0
|
||||
LegoCharacterData* LegoCharacterManager::GetData(LegoROI* p_roi)
|
||||
{
|
||||
MxU32 i;
|
||||
|
||||
for (i = 0; i < _countof(g_characterData); i++) {
|
||||
if (g_characterData[i].m_roi == p_roi) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < _countof(g_characterData)) {
|
||||
return &g_characterData[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10084ec0
|
||||
MxBool LegoCharacterManager::FUN_10084ec0(LegoROI* p_roi)
|
||||
{
|
||||
@ -388,10 +456,19 @@ MxBool LegoCharacterManager::FUN_10084ec0(LegoROI* p_roi)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10085140
|
||||
MxU32 LegoCharacterManager::FUN_10085140(LegoROI*, MxBool)
|
||||
// FUNCTION: LEGO1 0x10085140
|
||||
MxU32 LegoCharacterManager::FUN_10085140(LegoROI* p_roi, MxBool p_und)
|
||||
{
|
||||
// TODO
|
||||
LegoCharacterData* data = GetData(p_roi);
|
||||
|
||||
if (p_und) {
|
||||
return data->m_unk0x14 + g_unk0x100fc4dc;
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
return data->m_unk0x0c + g_unk0x100fc4d8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -415,13 +492,13 @@ void LegoCharacterManager::SetCustomizeAnimFile(const char* p_value)
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10085210
|
||||
LegoROI* LegoCharacterManager::FUN_10085210(const LegoChar*, LegoChar*, undefined)
|
||||
LegoROI* LegoCharacterManager::FUN_10085210(const char*, char*, undefined)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10085a80
|
||||
LegoROI* LegoCharacterManager::FUN_10085a80(LegoChar* p_und1, LegoChar* p_und2, undefined p_und3)
|
||||
LegoROI* LegoCharacterManager::FUN_10085a80(char* p_und1, char* p_und2, undefined p_und3)
|
||||
{
|
||||
return FUN_10085210(p_und1, p_und2, p_und3);
|
||||
}
|
||||
|
||||
@ -350,7 +350,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
|
||||
}
|
||||
} while (status != 2);
|
||||
|
||||
m_backgroundColor->SetLights();
|
||||
m_backgroundColor->SetLightColor();
|
||||
lightPosition = VariableTable()->GetVariable("lightposition");
|
||||
|
||||
if (lightPosition) {
|
||||
@ -1072,7 +1072,7 @@ void LegoGameState::RegisterState(LegoState* p_state)
|
||||
void LegoGameState::Init()
|
||||
{
|
||||
m_backgroundColor->SetValue("set 56 54 68");
|
||||
m_backgroundColor->SetLights();
|
||||
m_backgroundColor->SetLightColor();
|
||||
m_tempBackgroundColor->SetValue("set 56 54 68");
|
||||
VariableTable()->SetVariable("lightposition", "2");
|
||||
SetLightPosition(2);
|
||||
|
||||
@ -14,9 +14,11 @@
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxstreamer.h"
|
||||
#include "mxtypes.h"
|
||||
#include "realtime/realtime.h"
|
||||
|
||||
#include <process.h>
|
||||
#include <string.h>
|
||||
#include <vec.h>
|
||||
|
||||
// STUB: LEGO1 0x1003e050
|
||||
void FUN_1003e050(LegoAnimPresenter* p_presenter)
|
||||
@ -339,22 +341,95 @@ MxBool FUN_1003ef60()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1003f050
|
||||
MxS32 FUN_1003f050(MxS32)
|
||||
// FUNCTION: LEGO1 0x1003f050
|
||||
MxS32 UpdateLightPosition(MxS32 p_increase)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
MxS32 lightPosition = atoi(VariableTable()->GetVariable("lightposition"));
|
||||
|
||||
// Only ever increases by 1 irrespective of p_increase
|
||||
if (p_increase > 0) {
|
||||
lightPosition += 1;
|
||||
if (lightPosition > 5) {
|
||||
lightPosition = 5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lightPosition -= 1;
|
||||
if (lightPosition < 0) {
|
||||
lightPosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SetLightPosition(lightPosition);
|
||||
|
||||
char lightPositionBuffer[32];
|
||||
sprintf(lightPositionBuffer, "%d", lightPosition);
|
||||
|
||||
VariableTable()->SetVariable("lightposition", lightPositionBuffer);
|
||||
|
||||
return lightPosition;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1003f0d0
|
||||
void SetLightPosition(MxU32)
|
||||
// FUNCTION: LEGO1 0x1003f0d0
|
||||
void SetLightPosition(MxS32 p_index)
|
||||
{
|
||||
float lights[6][6] = {
|
||||
{1.0, 0.0, 0.0, -150.0, 50.0, -50.0},
|
||||
{0.809, -0.588, 0.0, -75.0, 50.0, -50.0},
|
||||
{0.0, -1.0, 0.0, 0.0, 150.0, -150.0},
|
||||
{-0.309, -0.951, 0.0, 25.0, 50.0, -50.0},
|
||||
{-0.809, -0.588, 0.0, 75.0, 50.0, -50.0},
|
||||
{-1.0, 0.0, 0.0, 150.0, 50.0, -50.0}
|
||||
};
|
||||
|
||||
Mx3DPointFloat up(1.0, 0.0, 0.0);
|
||||
Mx3DPointFloat direction;
|
||||
Mx3DPointFloat position;
|
||||
|
||||
Tgl::FloatMatrix4 matrix;
|
||||
Matrix4 in(matrix);
|
||||
MxMatrix transform;
|
||||
|
||||
if (p_index < 0) {
|
||||
p_index = 0;
|
||||
}
|
||||
else if (p_index > 5) {
|
||||
p_index = 5;
|
||||
}
|
||||
|
||||
direction = lights[p_index];
|
||||
position = &lights[p_index][3];
|
||||
|
||||
CalcLocalTransform(position, direction, up, transform);
|
||||
SETMAT4(in, transform);
|
||||
|
||||
VideoManager()->Get3DManager()->GetLego3DView()->SetLightTransform(FALSE, matrix);
|
||||
VideoManager()->Get3DManager()->GetLego3DView()->SetLightTransform(TRUE, matrix);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1003f3b0
|
||||
// FUNCTION: LEGO1 0x1003f3b0
|
||||
LegoNamedTexture* ReadNamedTexture(LegoFile* p_file)
|
||||
{
|
||||
return NULL;
|
||||
LegoTexture* texture = NULL;
|
||||
LegoNamedTexture* namedTexture = NULL;
|
||||
MxString string;
|
||||
|
||||
p_file->ReadString(string);
|
||||
|
||||
texture = new LegoTexture();
|
||||
if (texture != NULL) {
|
||||
if (texture->Read(p_file, 0) != SUCCESS) {
|
||||
delete texture;
|
||||
return namedTexture;
|
||||
}
|
||||
|
||||
namedTexture = new LegoNamedTexture(string.GetData(), texture);
|
||||
if (namedTexture == NULL) {
|
||||
delete texture;
|
||||
}
|
||||
}
|
||||
|
||||
return namedTexture;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1003f540
|
||||
|
||||
@ -1,3 +1,39 @@
|
||||
#include "gasstationentity.h"
|
||||
|
||||
#include "act1state.h"
|
||||
#include "isle.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoomni.h"
|
||||
#include "legoutils.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(GasStationEntity, 0x68)
|
||||
|
||||
// FUNCTION: LEGO1 0x100151d0
|
||||
MxLong GasStationEntity::VTable0x50(MxParam& p_param)
|
||||
{
|
||||
if (FUN_1003ef60()) {
|
||||
Act1State* state = (Act1State*) GameState()->GetState("Act1State");
|
||||
|
||||
if (state->GetUnknown18() != 8) {
|
||||
state->SetUnknown18(0);
|
||||
|
||||
if (CurrentActor()->GetActorId() != GameState()->GetActorId()) {
|
||||
CurrentActor()->VTable0xe4();
|
||||
}
|
||||
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->SetDestLocation(LegoGameState::Area::e_garage);
|
||||
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ MxLong HospitalEntity::VTable0x50(MxParam& p_param)
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->SetDestLocation(LegoGameState::Area::e_hospital);
|
||||
|
||||
AnimationManager()->FUN_10061010(NULL);
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,60 @@
|
||||
#include "infocenterentity.h"
|
||||
|
||||
#include "act1state.h"
|
||||
#include "act2main_actions.h"
|
||||
#include "act3.h"
|
||||
#include "act3_actions.h"
|
||||
#include "act3state.h"
|
||||
#include "isle.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoact2.h"
|
||||
#include "legoact2state.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoomni.h"
|
||||
#include "legoutils.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(InfoCenterEntity, 0x68)
|
||||
|
||||
// FUNCTION: LEGO1 0x100150c0
|
||||
MxLong InfoCenterEntity::VTable0x50(MxParam& p_param)
|
||||
{
|
||||
switch (GameState()->GetCurrentAct()) {
|
||||
case LegoGameState::Act::e_act1: {
|
||||
if (CurrentActor()->GetActorId() != GameState()->GetActorId()) {
|
||||
CurrentActor()->VTable0xe4();
|
||||
}
|
||||
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->FUN_10033350();
|
||||
isle->SetDestLocation(LegoGameState::Area::e_infomain);
|
||||
|
||||
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State");
|
||||
act1state->SetUnknown18(0);
|
||||
break;
|
||||
}
|
||||
case LegoGameState::Act::e_act2: {
|
||||
LegoAct2* act2 = (LegoAct2*) FindWorld(*g_act2mainScript, Act2mainScript::c__Act2Main);
|
||||
act2->SetUnknown0x1150(2);
|
||||
|
||||
LegoAct2State* act2state = (LegoAct2State*) GameState()->GetState("LegoAct2State");
|
||||
if (act2state) {
|
||||
act2state->SetUnknown0x0c(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LegoGameState::Act::e_act3:
|
||||
Act3* act3 = (Act3*) FindWorld(*g_act3Script, Act3Script::c__Act3);
|
||||
act3->SetUnknown4270(2);
|
||||
break;
|
||||
}
|
||||
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1,3 +1,36 @@
|
||||
#include "beachhouseentity.h"
|
||||
|
||||
#include "act1state.h"
|
||||
#include "isle.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoomni.h"
|
||||
#include "legoutils.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(BeachHouseEntity, 0x68)
|
||||
|
||||
// FUNCTION: LEGO1 0x100153b0
|
||||
MxLong BeachHouseEntity::VTable0x50(MxParam& p_param)
|
||||
{
|
||||
if (FUN_1003ef60()) {
|
||||
Act1State* state = (Act1State*) GameState()->GetState("Act1State");
|
||||
state->SetUnknown18(0);
|
||||
|
||||
if (CurrentActor()->GetActorId() != GameState()->GetActorId()) {
|
||||
CurrentActor()->VTable0xe4();
|
||||
}
|
||||
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->SetDestLocation(LegoGameState::Area::e_jetskibuild);
|
||||
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ MxLong PoliceEntity::VTable0x50(MxParam& p_param)
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->SetDestLocation(LegoGameState::Area::e_police);
|
||||
|
||||
AnimationManager()->FUN_10061010(NULL);
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,36 @@
|
||||
#include "racestandsentity.h"
|
||||
|
||||
#include "act1state.h"
|
||||
#include "isle.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoomni.h"
|
||||
#include "legoutils.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
#include "mxtransitionmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(RaceStandsEntity, 0x68)
|
||||
|
||||
// FUNCTION: LEGO1 0x10015450
|
||||
MxLong RaceStandsEntity::VTable0x50(MxParam& p_param)
|
||||
{
|
||||
if (FUN_1003ef60()) {
|
||||
Act1State* state = (Act1State*) GameState()->GetState("Act1State");
|
||||
state->SetUnknown18(0);
|
||||
|
||||
if (CurrentActor()->GetActorId() != GameState()->GetActorId()) {
|
||||
CurrentActor()->VTable0xe4();
|
||||
}
|
||||
|
||||
Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle);
|
||||
isle->SetDestLocation(LegoGameState::Area::e_racecarbuild);
|
||||
|
||||
AnimationManager()->FUN_10061010(0);
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar* p_und1)
|
||||
{
|
||||
LegoChar* str;
|
||||
|
||||
if (LegoCharacterManager::FUN_10084c00(p_und1 + 1)) {
|
||||
if (LegoCharacterManager::Exists(p_und1 + 1)) {
|
||||
str = new LegoChar[strlen(p_und1)];
|
||||
|
||||
if (str != NULL) {
|
||||
|
||||
@ -399,11 +399,11 @@ MxLong Isle::HandleClick(LegoControlManagerEvent& p_param)
|
||||
FUN_10031590();
|
||||
break;
|
||||
case IsleScript::c_Observe_GlobeLArrow_Ctl:
|
||||
FUN_1003f050(-1);
|
||||
UpdateLightPosition(-1);
|
||||
FUN_10031590();
|
||||
break;
|
||||
case IsleScript::c_Observe_GlobeRArrow_Ctl:
|
||||
FUN_1003f050(1);
|
||||
UpdateLightPosition(1);
|
||||
FUN_10031590();
|
||||
break;
|
||||
case IsleScript::c_Observe_Draw1_Ctl:
|
||||
@ -1115,3 +1115,9 @@ MxBool Isle::VTable0x64()
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10033350
|
||||
void Isle::FUN_10033350()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
@ -182,3 +182,45 @@ void LegoView1::Destroy()
|
||||
|
||||
LegoView::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100abb60
|
||||
void LegoView1::SetLightTransform(BOOL bDirectionalLight, Tgl::FloatMatrix4& rMatrix)
|
||||
{
|
||||
Tgl::Light* pLight;
|
||||
|
||||
if (bDirectionalLight == FALSE) {
|
||||
pLight = m_pSunLight;
|
||||
}
|
||||
else {
|
||||
pLight = m_pDirectionalLight;
|
||||
}
|
||||
|
||||
SetLightTransform(pLight, rMatrix);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100abb80
|
||||
void LegoView1::SetLightTransform(Tgl::Light* pLight, Tgl::FloatMatrix4& rMatrix)
|
||||
{
|
||||
pLight->SetTransformation(rMatrix);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100abba0
|
||||
void LegoView1::SetLightColor(BOOL bDirectionalLight, float red, float green, float blue)
|
||||
{
|
||||
Tgl::Light* pLight;
|
||||
|
||||
if (bDirectionalLight == FALSE) {
|
||||
pLight = m_pSunLight;
|
||||
}
|
||||
else {
|
||||
pLight = m_pDirectionalLight;
|
||||
}
|
||||
|
||||
SetLightColor(pLight, red, green, blue);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100abbd0
|
||||
void LegoView1::SetLightColor(Tgl::Light* pLight, float red, float green, float blue)
|
||||
{
|
||||
pLight->SetColor(red, green, blue);
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
namespace Tgl
|
||||
{
|
||||
class Camera;
|
||||
}
|
||||
class Light;
|
||||
} // namespace Tgl
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// LegoView
|
||||
@ -64,7 +65,13 @@ class LegoView1 : public LegoView {
|
||||
BOOL Create(const TglSurface::CreateStruct&, Tgl::Renderer*);
|
||||
void Destroy() override; // vtable+0x08
|
||||
|
||||
void SetLightTransform(BOOL bDirectionalLight, Tgl::FloatMatrix4& rMatrix);
|
||||
void SetLightColor(BOOL bDirectionalLight, float red, float green, float blue);
|
||||
|
||||
private:
|
||||
void SetLightTransform(Tgl::Light* pLight, Tgl::FloatMatrix4& rMatrix);
|
||||
void SetLightColor(Tgl::Light* pLight, float red, float green, float blue);
|
||||
|
||||
Tgl::Light* m_pSunLight; // 0x78
|
||||
Tgl::Light* m_pDirectionalLight; // 0x7c
|
||||
Tgl::Light* m_pAmbientLight; // 0x80
|
||||
|
||||
@ -23,9 +23,6 @@ typedef struct {
|
||||
int m_alpha;
|
||||
} ROIColorAlias;
|
||||
|
||||
// GLOBAL: LEGO1 0x100dbe28
|
||||
const double g_normalizeByteToFloat = 1.0 / 255;
|
||||
|
||||
// GLOBAL: LEGO1 0x101011b0
|
||||
ROIColorAlias g_roiColorAliases[22] = {
|
||||
{"lego black", 0x21, 0x21, 0x21, 0}, {"lego black f", 0x21, 0x21, 0x21, 0},
|
||||
@ -529,19 +526,15 @@ LegoBool LegoROI::FUN_100a9bf0(const LegoChar* p_param, float& p_red, float& p_g
|
||||
// FUNCTION: LEGO1 0x100a9c50
|
||||
LegoBool LegoROI::ColorAliasLookup(const LegoChar* p_param, float& p_red, float& p_green, float& p_blue, float& p_alpha)
|
||||
{
|
||||
// TODO: this seems awfully hacky for these devs. is there a dynamic way
|
||||
// to represent `the end of this array` that would improve this?
|
||||
unsigned int i = 0;
|
||||
do {
|
||||
for (MxU32 i = 0; i < _countof(g_roiColorAliases); i++) {
|
||||
if (strcmpi(g_roiColorAliases[i].m_name, p_param) == 0) {
|
||||
p_red = g_roiColorAliases[i].m_red * g_normalizeByteToFloat;
|
||||
p_green = g_roiColorAliases[i].m_green * g_normalizeByteToFloat;
|
||||
p_blue = g_roiColorAliases[i].m_blue * g_normalizeByteToFloat;
|
||||
p_alpha = g_roiColorAliases[i].m_alpha * g_normalizeByteToFloat;
|
||||
p_red = g_roiColorAliases[i].m_red / 255.0;
|
||||
p_green = g_roiColorAliases[i].m_green / 255.0;
|
||||
p_blue = g_roiColorAliases[i].m_blue / 255.0;
|
||||
p_alpha = g_roiColorAliases[i].m_alpha / 255.0;
|
||||
return TRUE;
|
||||
}
|
||||
i++;
|
||||
} while ((int*) &g_roiColorAliases[i] < &g_roiConfig);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -47,6 +47,13 @@ def parse_args() -> argparse.Namespace:
|
||||
parser.add_argument(
|
||||
"--no-color", "-n", action="store_true", help="Do not color the output"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--all",
|
||||
"-a",
|
||||
dest="show_all",
|
||||
action="store_true",
|
||||
help="Only show variables with a problem",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--print-rec-addr",
|
||||
action="store_true",
|
||||
@ -236,7 +243,7 @@ def do_the_comparison(args: argparse.Namespace) -> Iterable[ComparisonItem]:
|
||||
|
||||
# If we are here, we can do the type-aware comparison.
|
||||
compared = []
|
||||
compare_items = mini_cvdump.types.get_scalars(type_name)
|
||||
compare_items = mini_cvdump.types.get_scalars_gapless(type_name)
|
||||
format_str = mini_cvdump.types.get_format_string(type_name)
|
||||
|
||||
orig_data = unpack(format_str, orig_raw)
|
||||
@ -308,8 +315,15 @@ def display_match(result: CompareResult) -> str:
|
||||
)
|
||||
return f"{match_color}{result.name}{colorama.Style.RESET_ALL}"
|
||||
|
||||
var_count = 0
|
||||
problems = 0
|
||||
|
||||
for item in do_the_comparison(args):
|
||||
if not args.verbose and item.result == CompareResult.MATCH:
|
||||
var_count += 1
|
||||
if item.result in (CompareResult.DIFF, CompareResult.ERROR):
|
||||
problems += 1
|
||||
|
||||
if not args.show_all and item.result == CompareResult.MATCH:
|
||||
continue
|
||||
|
||||
address_display = (
|
||||
@ -334,8 +348,14 @@ def display_match(result: CompareResult) -> str:
|
||||
f" {c.offset:5} {value_get(c.name, '(value)'):30} {value_a} : {value_b}"
|
||||
)
|
||||
|
||||
print()
|
||||
if args.verbose:
|
||||
print()
|
||||
|
||||
print(
|
||||
f"{os.path.basename(args.original)} - Variables: {var_count}. Issues: {problems}"
|
||||
)
|
||||
return 0 if problems == 0 else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
raise SystemExit(main())
|
||||
|
||||
@ -69,14 +69,16 @@ def float_replace(self, addr: int, data_size: int) -> Optional[str]:
|
||||
|
||||
return None
|
||||
|
||||
def lookup(self, addr: int) -> Optional[str]:
|
||||
def lookup(self, addr: int, use_cache: bool = True) -> Optional[str]:
|
||||
"""Return a replacement name for this address if we find one."""
|
||||
if (cached := self.replacements.get(addr, None)) is not None:
|
||||
if use_cache and (cached := self.replacements.get(addr, None)) is not None:
|
||||
return cached
|
||||
|
||||
if callable(self.name_lookup):
|
||||
if (name := self.name_lookup(addr)) is not None:
|
||||
self.replacements[addr] = name
|
||||
if use_cache:
|
||||
self.replacements[addr] = name
|
||||
|
||||
return name
|
||||
|
||||
return None
|
||||
@ -110,6 +112,16 @@ def hex_replace_relocated(self, match: re.Match) -> str:
|
||||
|
||||
return match.group(0)
|
||||
|
||||
def hex_replace_annotated(self, match: re.Match) -> str:
|
||||
"""For replacing immediate value operands. Here we replace the value
|
||||
only if the name lookup returns something. Do not use a placeholder."""
|
||||
value = int(match.group(1), 16)
|
||||
placeholder = self.lookup(value, use_cache=False)
|
||||
if placeholder is not None:
|
||||
return match.group(0).replace(match.group(1), placeholder)
|
||||
|
||||
return match.group(0)
|
||||
|
||||
def hex_replace_float(self, match: re.Match) -> str:
|
||||
"""Special case for replacements on float instructions.
|
||||
If the pointer is a float constant, read it from the binary."""
|
||||
@ -178,7 +190,13 @@ def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]:
|
||||
# vtable call, or this->member access.
|
||||
op_str = displace_replace_regex.sub(self.hex_replace_relocated, op_str)
|
||||
|
||||
op_str = immediate_replace_regex.sub(self.hex_replace_relocated, op_str)
|
||||
# In the event of pointer comparison, only replace the immediate value
|
||||
# if it is a known address.
|
||||
if inst.mnemonic == "cmp":
|
||||
op_str = immediate_replace_regex.sub(self.hex_replace_annotated, op_str)
|
||||
else:
|
||||
op_str = immediate_replace_regex.sub(self.hex_replace_relocated, op_str)
|
||||
|
||||
return (inst.mnemonic, op_str)
|
||||
|
||||
def parse_asm(self, data: bytes, start_addr: Optional[int] = 0) -> List[str]:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import re
|
||||
from typing import Dict, Iterator, List, NamedTuple, Optional
|
||||
from typing import Dict, List, NamedTuple, Optional
|
||||
|
||||
|
||||
class CvdumpTypeError(Exception):
|
||||
@ -109,38 +109,10 @@ def scalar_type_format_char(type_name: str) -> str:
|
||||
return char if scalar_type_signed(type_name) else char.upper()
|
||||
|
||||
|
||||
def member_string_iter(
|
||||
members: List[ScalarType], size: Optional[int] = None
|
||||
) -> Iterator[str]:
|
||||
if len(members) == 0:
|
||||
yield "x" * (size or 0)
|
||||
def member_list_to_struct_string(members: List[ScalarType]) -> str:
|
||||
"""Create a string for use with struct.unpack"""
|
||||
|
||||
last_offset = 0
|
||||
last_size = 0
|
||||
for m in members:
|
||||
padding = m.offset - last_offset - last_size
|
||||
if padding > 0:
|
||||
yield "x" * padding
|
||||
|
||||
yield m.format_char
|
||||
last_offset = m.offset
|
||||
last_size = m.size
|
||||
|
||||
if size is not None:
|
||||
padding = size - (last_offset + last_size)
|
||||
if padding > 0:
|
||||
yield "x" * padding
|
||||
|
||||
|
||||
def member_list_to_struct_string(
|
||||
members: List[ScalarType], size: Optional[int] = None
|
||||
) -> str:
|
||||
"""Create a string for use with struct.unpack
|
||||
Will pad to `size` bytes if present."""
|
||||
if len(members) == 0:
|
||||
return "x" * (size or 0)
|
||||
|
||||
format_string = "".join(list(member_string_iter(members, size)))
|
||||
format_string = "".join(m.format_char for m in members)
|
||||
if len(format_string) > 0:
|
||||
return "<" + format_string
|
||||
|
||||
@ -372,11 +344,43 @@ def get_scalars(self, type_key: str) -> List[ScalarType]:
|
||||
for cm in self.get_scalars(m.type)
|
||||
]
|
||||
|
||||
def get_format_string(self, type_key: str) -> str:
|
||||
def get_scalars_gapless(self, type_key: str) -> List[ScalarType]:
|
||||
"""Reduce the given type to a list of scalars so we can
|
||||
compare each component value."""
|
||||
|
||||
obj = self.get(type_key)
|
||||
members = self.get_scalars(type_key)
|
||||
# We need both to pad the data to size
|
||||
return member_list_to_struct_string(members, obj.size)
|
||||
total_size = obj.size
|
||||
|
||||
scalars = self.get_scalars(type_key)
|
||||
|
||||
output = []
|
||||
last_extent = total_size
|
||||
|
||||
# Walk the scalar list in reverse; we assume a gap could not
|
||||
# come at the start of the struct.
|
||||
for scalar in scalars[::-1]:
|
||||
this_extent = scalar.offset + scalar_type_size(scalar.type)
|
||||
size_diff = last_extent - this_extent
|
||||
# We need to add the gap fillers in reverse here
|
||||
for i in range(size_diff - 1, -1, -1):
|
||||
# Push to front
|
||||
output.insert(
|
||||
0,
|
||||
ScalarType(
|
||||
offset=this_extent + i,
|
||||
name="(padding)",
|
||||
type="T_UCHAR",
|
||||
),
|
||||
)
|
||||
|
||||
output.insert(0, scalar)
|
||||
last_extent = scalar.offset
|
||||
|
||||
return output
|
||||
|
||||
def get_format_string(self, type_key: str) -> str:
|
||||
members = self.get_scalars_gapless(type_key)
|
||||
return member_list_to_struct_string(members)
|
||||
|
||||
def read_line(self, line: str):
|
||||
if (match := self.INDEX_RE.match(line)) is not None:
|
||||
|
||||
@ -313,14 +313,27 @@ def test_struct(parser):
|
||||
|
||||
|
||||
def test_struct_padding(parser):
|
||||
"""Struct format string should insert padding characters 'x'
|
||||
where a value is padded to alignment size (probably 4 bytes)"""
|
||||
"""For data comparison purposes, make sure we have no gaps in the
|
||||
list of scalar types. Any gap is filled by an unsigned char."""
|
||||
|
||||
# MxString, padded to 16 bytes. 4 actual members. 2 bytes of padding.
|
||||
assert len(parser.get_scalars("0x4db6")) == 4
|
||||
assert len(parser.get_scalars_gapless("0x4db6")) == 6
|
||||
|
||||
# MxVariable, with two MxStrings (and a vtable)
|
||||
# Fill in the middle gap and the outer gap.
|
||||
assert len(parser.get_scalars("0x22d5")) == 9
|
||||
assert len(parser.get_scalars_gapless("0x22d5")) == 13
|
||||
|
||||
|
||||
def test_struct_format_string(parser):
|
||||
"""Generate the struct.unpack format string using the
|
||||
list of scalars with padding filled in."""
|
||||
# MxString, padded to 16 bytes.
|
||||
assert parser.get_format_string("0x4db6") == "<LLLHxx"
|
||||
assert parser.get_format_string("0x4db6") == "<LLLHBB"
|
||||
|
||||
# MxVariable, with two MxString members.
|
||||
assert parser.get_format_string("0x22d5") == "<LLLLHxxLLLHxx"
|
||||
assert parser.get_format_string("0x22d5") == "<LLLLHBBLLLHBB"
|
||||
|
||||
|
||||
def test_array(parser):
|
||||
|
||||
@ -221,3 +221,38 @@ def substitute_float(_: int, __: int) -> str:
|
||||
inst = DisasmLiteInst(0x1000, 6, "fld", "dword ptr [0x1234]")
|
||||
(_, op_str) = p.sanitize(inst)
|
||||
assert op_str == "dword ptr [g_myFloatVariable]"
|
||||
|
||||
|
||||
def test_pointer_compare():
|
||||
"""A loop on an array could get optimized into comparing on the address
|
||||
that immediately follows the array. This may or may not be a valid address
|
||||
and it may or may not be annotated. To avoid a situation where an
|
||||
erroneous address value would get replaced with a placeholder and silently
|
||||
pass the comparison check, we will only replace an immediate value on the
|
||||
CMP instruction if it is a known address."""
|
||||
|
||||
# 0x1234 and 0x5555 are relocated and so are considered to be addresses.
|
||||
def relocate_lookup(addr: int) -> bool:
|
||||
return addr in (0x1234, 0x5555)
|
||||
|
||||
# Only 0x5555 is a "known" address
|
||||
def name_lookup(addr: int) -> Optional[str]:
|
||||
return "hello" if addr == 0x5555 else None
|
||||
|
||||
p = ParseAsm(relocate_lookup=relocate_lookup, name_lookup=name_lookup)
|
||||
|
||||
# Will always replace on MOV instruction
|
||||
(_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x1234"))
|
||||
assert op_str == "eax, <OFFSET1>"
|
||||
(_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x5555"))
|
||||
assert op_str == "eax, hello"
|
||||
|
||||
# n.b. We have already cached the replacement for 0x1234, but the
|
||||
# special handling for CMP should skip the cache and not use it.
|
||||
|
||||
# Do not replace here
|
||||
(_, op_str) = p.sanitize(mock_inst("cmp", "eax, 0x1234"))
|
||||
assert op_str == "eax, 0x1234"
|
||||
# Should replace here
|
||||
(_, op_str) = p.sanitize(mock_inst("cmp", "eax, 0x5555"))
|
||||
assert op_str == "eax, hello"
|
||||
|
||||
@ -107,7 +107,7 @@ def print_match_verbose(match, show_both_addrs: bool = False, is_plain: bool = F
|
||||
print(f"{addrs}: {match.name} 100% match.\n\n{ok_text}\n\n")
|
||||
else:
|
||||
print(
|
||||
f"{addrs}: {match.name} Effective 100%% match. (Differs in register allocation only)\n\n{ok_text} (still differs in register allocation)\n\n"
|
||||
f"{addrs}: {match.name} Effective 100% match. (Differs in register allocation only)\n\n{ok_text} (still differs in register allocation)\n\n"
|
||||
)
|
||||
else:
|
||||
print_combined_diff(match.udiff, is_plain, show_both_addrs)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user