mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-27 10:11:15 +00:00
Merge branch 'master' of https://github.com/tahg/isletahg into page
This commit is contained in:
commit
80ab0ff378
@ -2,7 +2,7 @@ root = true
|
|||||||
|
|
||||||
[*.{py,txt,editorconfig}]
|
[*.{py,txt,editorconfig}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 4
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -20,6 +20,10 @@ jobs:
|
|||||||
# Use minimum supported version
|
# Use minimum supported version
|
||||||
cmake-version: '3.13.x'
|
cmake-version: '3.13.x'
|
||||||
|
|
||||||
|
- name: Patch MSVC 4.2
|
||||||
|
run: |
|
||||||
|
python tools/patch_c2.py msvc420/bin/C2.EXE
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -79,7 +83,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
python3 tools/reccmp/reccmp.py -S ISLEPROGRESS.SVG --svg-icon tools/reccmp/isle.png -H ISLEPROGRESS.HTML legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . | tee ISLEPROGRESS.TXT
|
python3 tools/reccmp/reccmp.py -S ISLEPROGRESS.SVG --svg-icon tools/reccmp/isle.png -H ISLEPROGRESS.HTML legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . | tee ISLEPROGRESS.TXT
|
||||||
python3 tools/reccmp/reccmp.py -S LEGO1PROGRESS.SVG -T 1929 --svg-icon tools/reccmp/lego1.png -H LEGO1PROGRESS.HTML legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . | tee LEGO1PROGRESS.TXT
|
python3 tools/reccmp/reccmp.py -S LEGO1PROGRESS.SVG -T 4252 --svg-icon tools/reccmp/lego1.png -H LEGO1PROGRESS.HTML legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . | tee LEGO1PROGRESS.TXT
|
||||||
|
|
||||||
- name: Compare Accuracy With Current Master
|
- name: Compare Accuracy With Current Master
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
1
.github/workflows/format.yml
vendored
1
.github/workflows/format.yml
vendored
@ -19,6 +19,7 @@ jobs:
|
|||||||
LEGO1/*.cpp LEGO1/*.h \
|
LEGO1/*.cpp LEGO1/*.h \
|
||||||
LEGO1/realtime/*.cpp LEGO1/realtime/*.h \
|
LEGO1/realtime/*.cpp LEGO1/realtime/*.h \
|
||||||
LEGO1/tgl/*.h \
|
LEGO1/tgl/*.h \
|
||||||
|
LEGO1/tgl/d3drm/*.cpp LEGO1/tgl/d3drm/*.h \
|
||||||
LEGO1/viewmanager/*.cpp LEGO1/viewmanager/*.h
|
LEGO1/viewmanager/*.cpp LEGO1/viewmanager/*.h
|
||||||
|
|
||||||
python-format:
|
python-format:
|
||||||
|
|||||||
@ -165,7 +165,7 @@ class-naming-style=PascalCase
|
|||||||
#class-rgx=
|
#class-rgx=
|
||||||
|
|
||||||
# Naming style matching correct constant names.
|
# Naming style matching correct constant names.
|
||||||
const-naming-style=snake_case
|
const-naming-style=UPPER_CASE
|
||||||
|
|
||||||
# Regular expression matching correct constant names. Overrides const-naming-
|
# Regular expression matching correct constant names. Overrides const-naming-
|
||||||
# style. If left empty, constant names will be checked with the set naming
|
# style. If left empty, constant names will be checked with the set naming
|
||||||
@ -511,7 +511,7 @@ ignore-imports=yes
|
|||||||
ignore-signatures=yes
|
ignore-signatures=yes
|
||||||
|
|
||||||
# Minimum lines number of a similarity.
|
# Minimum lines number of a similarity.
|
||||||
min-similarity-lines=4
|
min-similarity-lines=16
|
||||||
|
|
||||||
|
|
||||||
[SPELLING]
|
[SPELLING]
|
||||||
|
|||||||
@ -99,6 +99,7 @@ add_library(lego1 SHARED
|
|||||||
LEGO1/legovehiclebuildstate.cpp
|
LEGO1/legovehiclebuildstate.cpp
|
||||||
LEGO1/legovideomanager.cpp
|
LEGO1/legovideomanager.cpp
|
||||||
LEGO1/legoworld.cpp
|
LEGO1/legoworld.cpp
|
||||||
|
LEGO1/legoworldlist.cpp
|
||||||
LEGO1/legoworldpresenter.cpp
|
LEGO1/legoworldpresenter.cpp
|
||||||
LEGO1/motorcycle.cpp
|
LEGO1/motorcycle.cpp
|
||||||
LEGO1/mxactionnotificationparam.cpp
|
LEGO1/mxactionnotificationparam.cpp
|
||||||
@ -210,6 +211,15 @@ add_library(lego1 SHARED
|
|||||||
LEGO1/registrationbook.cpp
|
LEGO1/registrationbook.cpp
|
||||||
LEGO1/scorestate.cpp
|
LEGO1/scorestate.cpp
|
||||||
LEGO1/skateboard.cpp
|
LEGO1/skateboard.cpp
|
||||||
|
LEGO1/tgl/d3drm/camera.cpp
|
||||||
|
LEGO1/tgl/d3drm/device.cpp
|
||||||
|
LEGO1/tgl/d3drm/group.cpp
|
||||||
|
LEGO1/tgl/d3drm/light.cpp
|
||||||
|
LEGO1/tgl/d3drm/mesh.cpp
|
||||||
|
LEGO1/tgl/d3drm/renderer.cpp
|
||||||
|
LEGO1/tgl/d3drm/texture.cpp
|
||||||
|
LEGO1/tgl/d3drm/unk.cpp
|
||||||
|
LEGO1/tgl/d3drm/view.cpp
|
||||||
LEGO1/towtrack.cpp
|
LEGO1/towtrack.cpp
|
||||||
LEGO1/towtrackmissionstate.cpp
|
LEGO1/towtrackmissionstate.cpp
|
||||||
LEGO1/viewmanager/viewmanager.cpp
|
LEGO1/viewmanager/viewmanager.cpp
|
||||||
@ -241,7 +251,7 @@ if (ISLE_USE_DX5)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Link libraries
|
# Link libraries
|
||||||
target_link_libraries(lego1 PRIVATE ddraw dsound dxguid dinput winmm)
|
target_link_libraries(lego1 PRIVATE ddraw dsound dxguid dinput winmm d3drm)
|
||||||
|
|
||||||
# Make sure filenames are ALL CAPS
|
# Make sure filenames are ALL CAPS
|
||||||
set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1)
|
set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1)
|
||||||
@ -279,8 +289,9 @@ if (MSVC)
|
|||||||
# These flags have been taken from the defaults for a Visual C++ 4.20 project (the compiler the
|
# These flags have been taken from the defaults for a Visual C++ 4.20 project (the compiler the
|
||||||
# game was originally built with) and tweaked slightly to produce more debugging info for reccmp.
|
# game was originally built with) and tweaked slightly to produce more debugging info for reccmp.
|
||||||
# They ensure a recompilation that can be byte/instruction accurate to the original binaries.
|
# They ensure a recompilation that can be byte/instruction accurate to the original binaries.
|
||||||
|
if (ISLE_BUILD_APP)
|
||||||
target_compile_options(isle PRIVATE "/ML$<$<CONFIG:Debug>:d>")
|
target_compile_options(isle PRIVATE "/ML$<$<CONFIG:Debug>:d>")
|
||||||
|
endif()
|
||||||
target_compile_options(lego1 PRIVATE "/MT$<$<CONFIG:Debug>:d>")
|
target_compile_options(lego1 PRIVATE "/MT$<$<CONFIG:Debug>:d>")
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"")
|
set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"")
|
||||||
|
|||||||
@ -18,12 +18,6 @@
|
|||||||
// Impossible to avoid this if using STL map or set.
|
// Impossible to avoid this if using STL map or set.
|
||||||
// This removes most (but not all) occurrences of the warning.
|
// This removes most (but not all) occurrences of the warning.
|
||||||
#pragma warning(disable : 4786)
|
#pragma warning(disable : 4786)
|
||||||
// To really remove *all* of the warnings, we have to employ the following,
|
|
||||||
// obscure workaround from https://www.earthli.com/news/view_article.php?id=376
|
|
||||||
static class msVC6_4786WorkAround {
|
|
||||||
public:
|
|
||||||
msVC6_4786WorkAround() {}
|
|
||||||
} msVC6_4786WorkAround;
|
|
||||||
|
|
||||||
#define MSVC420_VERSION 1020
|
#define MSVC420_VERSION 1020
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "legoutil.h"
|
#include "legoutil.h"
|
||||||
#include "legovideomanager.h"
|
#include "legovideomanager.h"
|
||||||
#include "legoworld.h"
|
#include "legoworld.h"
|
||||||
|
#include "legoworldlist.h"
|
||||||
#include "mxautolocker.h"
|
#include "mxautolocker.h"
|
||||||
#include "mxbackgroundaudiomanager.h"
|
#include "mxbackgroundaudiomanager.h"
|
||||||
#include "mxdsfile.h"
|
#include "mxdsfile.h"
|
||||||
@ -359,7 +360,7 @@ void LegoOmni::Init()
|
|||||||
m_inputMgr = NULL;
|
m_inputMgr = NULL;
|
||||||
m_unk6c = 0;
|
m_unk6c = 0;
|
||||||
m_gifManager = NULL;
|
m_gifManager = NULL;
|
||||||
m_unk78 = 0;
|
m_worldList = NULL;
|
||||||
m_currentWorld = NULL;
|
m_currentWorld = NULL;
|
||||||
m_unk80 = FALSE;
|
m_unk80 = FALSE;
|
||||||
m_currentVehicle = NULL;
|
m_currentVehicle = NULL;
|
||||||
@ -428,9 +429,9 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p)
|
|||||||
m_animationManager = new LegoAnimationManager();
|
m_animationManager = new LegoAnimationManager();
|
||||||
m_buildingManager = new LegoBuildingManager();
|
m_buildingManager = new LegoBuildingManager();
|
||||||
m_gameState = new LegoGameState();
|
m_gameState = new LegoGameState();
|
||||||
// TODO: initialize list at m_unk78
|
m_worldList = new LegoWorldList();
|
||||||
|
|
||||||
if (m_unk6c && m_gifManager && m_unk78 && m_plantManager && m_animationManager && m_buildingManager) {
|
if (m_unk6c && m_gifManager && m_worldList && m_plantManager && m_animationManager && m_buildingManager) {
|
||||||
// TODO: initialize a bunch of MxVariables
|
// TODO: initialize a bunch of MxVariables
|
||||||
RegisterScripts();
|
RegisterScripts();
|
||||||
FUN_1001a700();
|
FUN_1001a700();
|
||||||
|
|||||||
@ -22,6 +22,7 @@ class LegoSoundManager;
|
|||||||
class LegoUnkSaveDataWriter;
|
class LegoUnkSaveDataWriter;
|
||||||
class LegoVideoManager;
|
class LegoVideoManager;
|
||||||
class LegoWorld;
|
class LegoWorld;
|
||||||
|
class LegoWorldList;
|
||||||
class MxAtomId;
|
class MxAtomId;
|
||||||
class MxBackgroundAudioManager;
|
class MxBackgroundAudioManager;
|
||||||
class MxDSFile;
|
class MxDSFile;
|
||||||
@ -118,7 +119,7 @@ class LegoOmni : public MxOmni {
|
|||||||
undefined4 m_unk6c;
|
undefined4 m_unk6c;
|
||||||
LegoInputManager* m_inputMgr; // 0x70
|
LegoInputManager* m_inputMgr; // 0x70
|
||||||
GifManager* m_gifManager;
|
GifManager* m_gifManager;
|
||||||
undefined4 m_unk78;
|
LegoWorldList* m_worldList; // 0x78
|
||||||
LegoWorld* m_currentWorld;
|
LegoWorld* m_currentWorld;
|
||||||
MxBool m_unk80;
|
MxBool m_unk80;
|
||||||
LegoNavController* m_navController; // 0x84
|
LegoNavController* m_navController; // 0x84
|
||||||
|
|||||||
@ -62,6 +62,24 @@ MxResult LegoWorld::SetAsCurrentWorld(MxDSObject& p_dsObject)
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x1001eed0
|
||||||
|
// MxPresenterListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x1001ef40
|
||||||
|
// MxPtrListCursor<MxPresenter>::~MxPtrListCursor<MxPresenter>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x1001ef90
|
||||||
|
// MxListCursor<MxPresenter *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x1001f000
|
||||||
|
// MxPtrListCursor<MxPresenter>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x1001f070
|
||||||
|
// MxListCursor<MxPresenter *>::~MxListCursor<MxPresenter *>
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x1001f0c0
|
||||||
|
// MxPresenterListCursor::~MxPresenterListCursor
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1001f5e0
|
// FUNCTION: LEGO1 0x1001f5e0
|
||||||
MxLong LegoWorld::Notify(MxParam& p_param)
|
MxLong LegoWorld::Notify(MxParam& p_param)
|
||||||
{
|
{
|
||||||
|
|||||||
36
LEGO1/legoworldlist.cpp
Normal file
36
LEGO1/legoworldlist.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "legoworldlist.h"
|
||||||
|
|
||||||
|
#include "legoworld.h"
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100598d0
|
||||||
|
MxS8 LegoWorldList::Compare(LegoWorld* p_a, LegoWorld* p_b)
|
||||||
|
{
|
||||||
|
return p_a == p_b ? 0 : p_a < p_b ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100598f0
|
||||||
|
// MxCollection<LegoWorld *>::Compare
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x10059900
|
||||||
|
// MxCollection<LegoWorld *>::~MxCollection<LegoWorld *>
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x10059950
|
||||||
|
// MxCollection<LegoWorld *>::Destroy
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x10059960
|
||||||
|
// MxList<LegoWorld *>::~MxList<LegoWorld *>
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100599f0
|
||||||
|
void LegoWorldList::Destroy(LegoWorld* p_world)
|
||||||
|
{
|
||||||
|
delete p_world;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x10059ac0
|
||||||
|
// MxCollection<LegoWorld *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x10059b30
|
||||||
|
// MxList<LegoWorld *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x10059be0
|
||||||
|
// MxPtrList<LegoWorld>::`scalar deleting destructor'
|
||||||
27
LEGO1/legoworldlist.h
Normal file
27
LEGO1/legoworldlist.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef LEGOWORLDLIST_H
|
||||||
|
#define LEGOWORLDLIST_H
|
||||||
|
|
||||||
|
#include "mxlist.h"
|
||||||
|
#include "mxtypes.h"
|
||||||
|
|
||||||
|
class LegoWorld;
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d8700
|
||||||
|
// class MxCollection<LegoWorld *>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d8718
|
||||||
|
// class MxList<LegoWorld *>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d8730
|
||||||
|
// class MxPtrList<LegoWorld>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d8680
|
||||||
|
// SIZE 0x18
|
||||||
|
class LegoWorldList : public MxPtrList<LegoWorld> {
|
||||||
|
public:
|
||||||
|
LegoWorldList() : MxPtrList<LegoWorld>(Destroy) {}
|
||||||
|
virtual MxS8 Compare(LegoWorld*, LegoWorld*) override; // vtable+0x14
|
||||||
|
static void Destroy(LegoWorld*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LEGOWORLDLIST_H
|
||||||
@ -19,12 +19,50 @@ MxCompositePresenter::MxCompositePresenter()
|
|||||||
NotificationManager()->Register(this);
|
NotificationManager()->Register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100b61a0
|
||||||
|
// list<MxPresenter *,allocator<MxPresenter *> >::~list<MxPresenter *,allocator<MxPresenter *> >
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b6210
|
||||||
|
// MxCompositePresenter::ClassName
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b6220
|
||||||
|
// MxCompositePresenter::IsA
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100b62d0
|
||||||
|
// MxCompositePresenter::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b62f0
|
||||||
|
// MxCompositePresenterList::~MxCompositePresenterList
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100b6340
|
||||||
|
// List<MxPresenter *>::~List<MxPresenter *>
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b6390
|
// FUNCTION: LEGO1 0x100b6390
|
||||||
MxCompositePresenter::~MxCompositePresenter()
|
MxCompositePresenter::~MxCompositePresenter()
|
||||||
{
|
{
|
||||||
NotificationManager()->Unregister(this);
|
NotificationManager()->Unregister(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b6410
|
||||||
|
MxResult MxCompositePresenter::StartAction(MxStreamController*, MxDSAction*)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b65e0
|
||||||
|
void MxCompositePresenter::EndAction()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b6760
|
||||||
|
MxLong MxCompositePresenter::Notify(MxParam& p)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b67f0
|
// STUB: LEGO1 0x100b67f0
|
||||||
void MxCompositePresenter::VTable0x58()
|
void MxCompositePresenter::VTable0x58()
|
||||||
{
|
{
|
||||||
@ -37,8 +75,40 @@ void MxCompositePresenter::VTable0x5c()
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b6b40
|
// FUNCTION: LEGO1 0x100b6b40
|
||||||
void MxCompositePresenter::VTable0x60(undefined4 p_unknown)
|
void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter)
|
||||||
|
{
|
||||||
|
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||||
|
if (*it == p_presenter) {
|
||||||
|
if (++it == m_list.end()) {
|
||||||
|
if (m_compositePresenter)
|
||||||
|
m_compositePresenter->VTable0x60(this);
|
||||||
|
}
|
||||||
|
else if (m_action->IsA("MxDSSerialAction")) {
|
||||||
|
MxPresenter* presenter = *it;
|
||||||
|
if (presenter->GetCurrentTickleState() == TickleState_Idle)
|
||||||
|
presenter->SetTickleState(TickleState_Ready);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b6bc0
|
||||||
|
void MxCompositePresenter::SetTickleState(TickleState p_tickleState)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b6c30
|
||||||
|
void MxCompositePresenter::Enable(MxBool p_enable)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100b6c80
|
||||||
|
MxBool MxCompositePresenter::HasTickleStatePassed(TickleState p_tickleState)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
#ifndef MXCOMPOSITEPRESENTER_H
|
#ifndef MXCOMPOSITEPRESENTER_H
|
||||||
#define MXCOMPOSITEPRESENTER_H
|
#define MXCOMPOSITEPRESENTER_H
|
||||||
|
|
||||||
|
#include "compat.h" // STL
|
||||||
#include "mxpresenter.h"
|
#include "mxpresenter.h"
|
||||||
#include "mxunklist.h"
|
|
||||||
|
class MxCompositePresenterList : public list<MxPresenter*> {};
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dc618
|
// VTABLE: LEGO1 0x100dc618
|
||||||
// SIZE 0x4c
|
// SIZE 0x4c
|
||||||
@ -11,26 +13,31 @@ class MxCompositePresenter : public MxPresenter {
|
|||||||
MxCompositePresenter();
|
MxCompositePresenter();
|
||||||
virtual ~MxCompositePresenter() override; // vtable+0x0
|
virtual ~MxCompositePresenter() override; // vtable+0x0
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b6210
|
virtual MxLong Notify(MxParam& p) override; // vtable+0x04
|
||||||
|
|
||||||
inline virtual const char* ClassName() const override // vtable+0x0c
|
inline virtual const char* ClassName() const override // vtable+0x0c
|
||||||
{
|
{
|
||||||
// GLOBAL: LEGO1 0x100f0774
|
// GLOBAL: LEGO1 0x100f0774
|
||||||
return "MxCompositePresenter";
|
return "MxCompositePresenter";
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b6220
|
|
||||||
inline virtual MxBool IsA(const char* name) const override // vtable+0x10
|
inline virtual MxBool IsA(const char* name) const override // vtable+0x10
|
||||||
{
|
{
|
||||||
return !strcmp(name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(name);
|
return !strcmp(name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void VTable0x58();
|
virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c
|
||||||
virtual void VTable0x5c();
|
virtual void EndAction() override; // vtable+0x40
|
||||||
virtual void VTable0x60(undefined4 p_unknown);
|
virtual void SetTickleState(TickleState p_tickleState) override; // vtable+0x44
|
||||||
virtual MxBool VTable0x64(undefined4 p_unknown);
|
virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48
|
||||||
|
virtual void Enable(MxBool p_enable) override; // vtable+0x54
|
||||||
|
virtual void VTable0x58(); // vtable+0x58
|
||||||
|
virtual void VTable0x5c(); // vtable+0x5c
|
||||||
|
virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60
|
||||||
|
virtual MxBool VTable0x64(undefined4 p_unknown); // vtable+0x64
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MxUnkList m_list;
|
MxCompositePresenterList m_list; // 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXCOMPOSITEPRESENTER_H
|
#endif // MXCOMPOSITEPRESENTER_H
|
||||||
|
|||||||
@ -26,6 +26,13 @@ class MxDSActionList : public MxList<MxDSAction*> {
|
|||||||
undefined m_unk18;
|
undefined m_unk18;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MxListCursorChild<MxDSAction*> MxDSActionListCursor;
|
// VTABLE: LEGO1 0x100d7e68
|
||||||
|
// class MxListCursor<MxDSAction *>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d7e50
|
||||||
|
class MxDSActionListCursor : public MxListCursor<MxDSAction*> {
|
||||||
|
public:
|
||||||
|
MxDSActionListCursor(MxDSActionList* p_list) : MxListCursor<MxDSAction*>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
#endif // MXDSACTIONLIST_H
|
#endif // MXDSACTIONLIST_H
|
||||||
|
|||||||
@ -34,6 +34,7 @@ class MxDSMediaAction : public MxDSAction {
|
|||||||
void CopyMediaSrcPath(const char* p_mediaSrcPath);
|
void CopyMediaSrcPath(const char* p_mediaSrcPath);
|
||||||
|
|
||||||
inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; }
|
inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; }
|
||||||
|
inline MxS32 GetPaletteManagement() const { return this->m_paletteManagement; }
|
||||||
inline MxLong GetSustainTime() const { return this->m_sustainTime; }
|
inline MxLong GetSustainTime() const { return this->m_sustainTime; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c)
|
DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c)
|
||||||
|
|
||||||
|
// TODO: Should be moved later
|
||||||
|
// SYNTHETIC: LEGO1 0x1004ad10
|
||||||
|
// MxDSActionListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x1004ad80
|
||||||
|
// MxListCursor<MxDSAction *>::~MxListCursor<MxDSAction *>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x1004add0
|
||||||
|
// MxListCursor<MxDSAction *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x1004ae40
|
||||||
|
// MxDSActionListCursor::~MxDSActionListCursor
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c9b90
|
// FUNCTION: LEGO1 0x100c9b90
|
||||||
MxDSMultiAction::MxDSMultiAction()
|
MxDSMultiAction::MxDSMultiAction()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -33,6 +33,18 @@ void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction)
|
|||||||
this->m_unk0xac->Append(string);
|
this->m_unk0xac->Append(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100cbbd0
|
||||||
|
// MxStringListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100cbc40
|
||||||
|
// MxListCursor<MxString>::~MxListCursor<MxString>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100cbc90
|
||||||
|
// MxListCursor<MxString>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100cbd00
|
||||||
|
// MxStringListCursor::~MxStringListCursor
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100cbd50
|
// FUNCTION: LEGO1 0x100cbd50
|
||||||
MxDSSelectAction& MxDSSelectAction::operator=(MxDSSelectAction& p_dsSelectAction)
|
MxDSSelectAction& MxDSSelectAction::operator=(MxDSSelectAction& p_dsSelectAction)
|
||||||
{
|
{
|
||||||
@ -130,3 +142,6 @@ void MxDSSelectAction::Deserialize(char** p_source, MxS16 p_unk24)
|
|||||||
|
|
||||||
*p_source += extraFlag;
|
*p_source += extraFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100cc450
|
||||||
|
// MxListEntry<MxString>::GetValue
|
||||||
|
|||||||
@ -42,11 +42,9 @@ void MxFlcPresenter::CreateBitmap()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b3620
|
// FUNCTION: LEGO1 0x100b3620
|
||||||
void MxFlcPresenter::VTable0x70()
|
void MxFlcPresenter::RealizePalette()
|
||||||
{
|
{
|
||||||
MxPalette* pal = m_bitmap->CreatePalette();
|
MxPalette* palette = m_bitmap->CreatePalette();
|
||||||
MVideoManager()->RealizePalette(pal);
|
MVideoManager()->RealizePalette(palette);
|
||||||
|
delete palette;
|
||||||
if (pal)
|
|
||||||
delete pal;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class MxFlcPresenter : public MxVideoPresenter {
|
|||||||
|
|
||||||
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
||||||
virtual void CreateBitmap() override; // vtable+0x60
|
virtual void CreateBitmap() override; // vtable+0x60
|
||||||
virtual void VTable0x70() override; // vtable+0x70
|
virtual void RealizePalette() override; // vtable+0x70
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FLIC_HEADER* m_flicHeader;
|
FLIC_HEADER* m_flicHeader;
|
||||||
|
|||||||
@ -100,18 +100,10 @@ class MxListCursor : public MxCore {
|
|||||||
MxListEntry<T>* m_match;
|
MxListEntry<T>* m_match;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unclear purpose
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class MxListCursorChild : public MxListCursor<T> {
|
class MxPtrListCursor : public MxListCursor<T*> {
|
||||||
public:
|
public:
|
||||||
MxListCursorChild(MxList<T>* p_list) : MxListCursor<T>(p_list) {}
|
MxPtrListCursor(MxPtrList<T>* p_list) : MxListCursor<T*>(p_list){};
|
||||||
};
|
|
||||||
|
|
||||||
// Unclear purpose
|
|
||||||
template <class T>
|
|
||||||
class MxListCursorChildChild : public MxListCursorChild<T> {
|
|
||||||
public:
|
|
||||||
MxListCursorChildChild(MxList<T>* p_list) : MxListCursorChild<T>(p_list) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@ -21,6 +21,19 @@ void MxMediaPresenter::Destroy()
|
|||||||
Destroy(FALSE);
|
Destroy(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: These probably belong in another class
|
||||||
|
// SYNTHETIC: LEGO1 0x100b46e0
|
||||||
|
// MxStreamChunkListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100b4750
|
||||||
|
// MxListCursor<MxStreamChunk *>::~MxListCursor<MxStreamChunk *>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100b47a0
|
||||||
|
// MxListCursor<MxStreamChunk *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4810
|
||||||
|
// MxStreamChunkListCursor::~MxStreamChunkListCursor
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b54e0
|
// FUNCTION: LEGO1 0x100b54e0
|
||||||
void MxMediaPresenter::Init()
|
void MxMediaPresenter::Init()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -15,7 +15,17 @@ class MxPresenterList : public MxPtrList<MxPresenter> {
|
|||||||
virtual MxS8 Compare(MxPresenter*, MxPresenter*) override; // vtable+0x14
|
virtual MxS8 Compare(MxPresenter*, MxPresenter*) override; // vtable+0x14
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MxListCursorChildChild<MxPresenter*> MxPresenterListCursor;
|
// VTABLE: LEGO1 0x100d6488
|
||||||
|
// class MxListCursor<MxPresenter *>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d6530
|
||||||
|
// class MxPtrListCursor<MxPresenter>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100d6470
|
||||||
|
class MxPresenterListCursor : public MxPtrListCursor<MxPresenter> {
|
||||||
|
public:
|
||||||
|
MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor<MxPresenter>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100d6350
|
// VTABLE: LEGO1 0x100d6350
|
||||||
// class MxCollection<MxPresenter *>
|
// class MxCollection<MxPresenter *>
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "mxpoint32.h"
|
#include "mxpoint32.h"
|
||||||
#include "mxsize32.h"
|
#include "mxsize32.h"
|
||||||
|
|
||||||
|
// SIZE 0x10
|
||||||
class MxRect32 {
|
class MxRect32 {
|
||||||
public:
|
public:
|
||||||
MxRect32() {}
|
MxRect32() {}
|
||||||
|
|||||||
@ -86,6 +86,24 @@ void MxRegion::vtable18(MxRect32& p_rect)
|
|||||||
m_rect.UpdateBounds(p_rect);
|
m_rect.UpdateBounds(p_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c3be0
|
||||||
|
// MxRegionListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c3c50
|
||||||
|
// MxPtrListCursor<MxRegionTopBottom>::~MxPtrListCursor<MxRegionTopBottom>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c3ca0
|
||||||
|
// MxListCursor<MxRegionTopBottom *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c3d10
|
||||||
|
// MxPtrListCursor<MxRegionTopBottom>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c3d80
|
||||||
|
// MxListCursor<MxRegionTopBottom *>::~MxListCursor<MxRegionTopBottom *>
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c3dd0
|
||||||
|
// MxRegionListCursor::~MxRegionListCursor
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c3e20
|
// FUNCTION: LEGO1 0x100c3e20
|
||||||
MxBool MxRegion::vtable1c(MxRect32& p_rect)
|
MxBool MxRegion::vtable1c(MxRect32& p_rect)
|
||||||
{
|
{
|
||||||
@ -105,6 +123,21 @@ MxBool MxRegion::vtable1c(MxRect32& p_rect)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c4790
|
||||||
|
// MxRegionLeftRightListCursor::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c4800
|
||||||
|
// MxPtrListCursor<MxRegionLeftRight>::~MxPtrListCursor<MxRegionLeftRight>
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c4850
|
||||||
|
// MxListCursor<MxRegionLeftRight *>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100c48c0
|
||||||
|
// MxPtrListCursor<MxRegionLeftRight>::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c4930
|
||||||
|
// MxListCursor<MxRegionLeftRight *>::~MxListCursor<MxRegionLeftRight *>
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c4c90
|
// FUNCTION: LEGO1 0x100c4c90
|
||||||
MxRegionTopBottom::MxRegionTopBottom(MxS32 p_top, MxS32 p_bottom)
|
MxRegionTopBottom::MxRegionTopBottom(MxS32 p_top, MxS32 p_bottom)
|
||||||
{
|
{
|
||||||
@ -167,6 +200,15 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c54f0
|
||||||
|
// MxListCursor<MxRegionLeftRight *>::MxListCursor<MxRegionLeftRight *>
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c5560
|
||||||
|
// MxRegionLeftRightListCursor::~MxRegionLeftRightListCursor
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100c55b0
|
||||||
|
// MxListCursor<MxRegionLeftRight *>::operator=
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c55d0
|
// FUNCTION: LEGO1 0x100c55d0
|
||||||
MxRegionTopBottom* MxRegionTopBottom::Clone()
|
MxRegionTopBottom* MxRegionTopBottom::Clone()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,13 +23,21 @@ class MxRegionList : public MxPtrList<MxRegionTopBottom> {
|
|||||||
static void Destroy(MxRegionTopBottom*);
|
static void Destroy(MxRegionTopBottom*);
|
||||||
};
|
};
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dcb88
|
// VTABLE: LEGO1 0x100dcb70
|
||||||
// class MxListCursorChildChild<MxRegionTopBottom *>
|
// class MxPtrListCursor<MxRegionTopBottom>
|
||||||
typedef MxListCursorChildChild<MxRegionTopBottom*> MxRegionListCursor;
|
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dcc10
|
// VTABLE: LEGO1 0x100dcba0
|
||||||
// class MxListCursorChildChild<MxRegionLeftRight *>
|
// class MxListCursor<MxRegionTopBottom *>
|
||||||
typedef MxListCursorChildChild<MxRegionLeftRight*> MxRegionLeftRightListCursor;
|
|
||||||
|
// TODO: The initialize list param type should be MxRegionList, but doing that
|
||||||
|
// drastically reduced the match percentage for MxRegion::vtable18.
|
||||||
|
// It also works with MxPtrList, so we'll do that until we figure this out.
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dcb88
|
||||||
|
class MxRegionListCursor : public MxPtrListCursor<MxRegionTopBottom> {
|
||||||
|
public:
|
||||||
|
MxRegionListCursor(MxPtrList<MxRegionTopBottom>* p_list) : MxPtrListCursor<MxRegionTopBottom>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dcc40
|
// VTABLE: LEGO1 0x100dcc40
|
||||||
// class MxCollection<MxRegionLeftRight *>
|
// class MxCollection<MxRegionLeftRight *>
|
||||||
@ -48,4 +56,16 @@ class MxRegionLeftRightList : public MxPtrList<MxRegionLeftRight> {
|
|||||||
static void Destroy(MxRegionLeftRight*);
|
static void Destroy(MxRegionLeftRight*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dcbf8
|
||||||
|
// class MxPtrListCursor<MxRegionLeftRight>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dcc28
|
||||||
|
// class MxListCursor<MxRegionLeftRight *>
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dcc10
|
||||||
|
class MxRegionLeftRightListCursor : public MxPtrListCursor<MxRegionLeftRight> {
|
||||||
|
public:
|
||||||
|
MxRegionLeftRightListCursor(MxRegionLeftRightList* p_list) : MxPtrListCursor<MxRegionLeftRight>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
#endif // MXREGIONLIST_H
|
#endif // MXREGIONLIST_H
|
||||||
|
|||||||
@ -85,7 +85,7 @@ MxU32 MxSmkPresenter::VTable0x88()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b42c0
|
// FUNCTION: LEGO1 0x100b42c0
|
||||||
void MxSmkPresenter::VTable0x70()
|
void MxSmkPresenter::RealizePalette()
|
||||||
{
|
{
|
||||||
MxPalette* palette = m_bitmap->CreatePalette();
|
MxPalette* palette = m_bitmap->CreatePalette();
|
||||||
MVideoManager()->RealizePalette(palette);
|
MVideoManager()->RealizePalette(palette);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class MxSmkPresenter : public MxVideoPresenter {
|
|||||||
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
||||||
virtual void CreateBitmap() override; // vtable+0x60
|
virtual void CreateBitmap() override; // vtable+0x60
|
||||||
virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68
|
virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68
|
||||||
virtual void VTable0x70() override; // vtable+0x70
|
virtual void RealizePalette() override; // vtable+0x70
|
||||||
virtual MxU32 VTable0x88(); // vtable+0x88
|
virtual MxU32 VTable0x88(); // vtable+0x88
|
||||||
|
|
||||||
struct MxSmack {
|
struct MxSmack {
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include "decomp.h"
|
#include "decomp.h"
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
#include "legoomni.h"
|
#include "legoomni.h"
|
||||||
|
#include "mxcompositepresenter.h"
|
||||||
|
#include "mxdsmediaaction.h"
|
||||||
#include "mxomni.h"
|
#include "mxomni.h"
|
||||||
#include "mxvideomanager.h"
|
#include "mxvideomanager.h"
|
||||||
|
|
||||||
@ -83,8 +85,8 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
|
|
||||||
MxS32 height = GetHeight() - 1;
|
MxS32 height = GetHeight() - 1;
|
||||||
MxS32 width = GetWidth() - 1;
|
MxS32 width = GetWidth() - 1;
|
||||||
MxS32 x = GetLocationX();
|
MxS32 x = m_location.m_x;
|
||||||
MxS32 y = GetLocationY();
|
MxS32 y = m_location.m_y;
|
||||||
|
|
||||||
MxRect32 rect(x, y, width + x, height + y);
|
MxRect32 rect(x, y, width + x, height + y);
|
||||||
MVideoManager()->InvalidateRect(rect);
|
MVideoManager()->InvalidateRect(rect);
|
||||||
@ -98,12 +100,10 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
m_action->GetFlags() & MxDSAction::Flag_Bit4
|
m_action->GetFlags() & MxDSAction::Flag_Bit4
|
||||||
);
|
);
|
||||||
|
|
||||||
if (m_alpha)
|
delete m_alpha;
|
||||||
delete m_alpha;
|
|
||||||
m_alpha = new AlphaMask(*m_bitmap);
|
m_alpha = new AlphaMask(*m_bitmap);
|
||||||
|
|
||||||
if (m_bitmap)
|
delete m_bitmap;
|
||||||
delete m_bitmap;
|
|
||||||
m_bitmap = NULL;
|
m_bitmap = NULL;
|
||||||
|
|
||||||
if (m_unk58 && unk)
|
if (m_unk58 && unk)
|
||||||
@ -113,40 +113,88 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b9f30
|
// FUNCTION: LEGO1 0x100b9f30
|
||||||
void MxStillPresenter::VTable0x70()
|
void MxStillPresenter::RealizePalette()
|
||||||
{
|
{
|
||||||
// TODO
|
MxPalette* palette = m_bitmap->CreatePalette();
|
||||||
|
MVideoManager()->RealizePalette(palette);
|
||||||
|
delete palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b9f60
|
// FUNCTION: LEGO1 0x100b9f60
|
||||||
void MxStillPresenter::StartingTickle()
|
void MxStillPresenter::StartingTickle()
|
||||||
{
|
{
|
||||||
// TODO
|
MxVideoPresenter::StartingTickle();
|
||||||
|
|
||||||
|
if (m_currentTickleState == TickleState_Streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement())
|
||||||
|
RealizePalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b9f90
|
// FUNCTION: LEGO1 0x100b9f90
|
||||||
void MxStillPresenter::StreamingTickle()
|
void MxStillPresenter::StreamingTickle()
|
||||||
{
|
{
|
||||||
// TODO
|
MxStreamChunk* chunk = FUN_100b5650();
|
||||||
|
|
||||||
|
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||||
|
m_chunkTime = chunk->GetTime();
|
||||||
|
NextFrame();
|
||||||
|
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||||
|
m_currentTickleState = TickleState_Repeating;
|
||||||
|
|
||||||
|
if (m_action->GetDuration() == -1 && m_compositePresenter)
|
||||||
|
m_compositePresenter->VTable0x60(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b9ff0
|
// FUNCTION: LEGO1 0x100b9ff0
|
||||||
void MxStillPresenter::RepeatingTickle()
|
void MxStillPresenter::RepeatingTickle()
|
||||||
{
|
{
|
||||||
// TODO
|
if (m_action->GetDuration() != -1) {
|
||||||
|
if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) {
|
||||||
|
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||||
|
m_currentTickleState = TickleState_unk5;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100ba040
|
// FUNCTION: LEGO1 0x100ba040
|
||||||
void MxStillPresenter::VTable0x88(undefined4, undefined4)
|
void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y)
|
||||||
{
|
{
|
||||||
// TODO
|
MxS32 x = m_location.m_x;
|
||||||
|
MxS32 y = m_location.m_y;
|
||||||
|
m_location.m_x = p_x;
|
||||||
|
m_location.m_y = p_y;
|
||||||
|
|
||||||
|
if (IsEnabled()) {
|
||||||
|
MxS32 height = GetHeight() - 1;
|
||||||
|
MxS32 width = GetWidth() - 1;
|
||||||
|
|
||||||
|
MxRect32 rect_a(x, y, width + x, height + y);
|
||||||
|
MxRect32 rect_b(m_location.m_x, m_location.m_y, width + m_location.m_x, height + m_location.m_y);
|
||||||
|
|
||||||
|
MVideoManager()->InvalidateRect(rect_a);
|
||||||
|
MVideoManager()->vtable0x34(rect_a.GetLeft(), rect_a.GetTop(), rect_a.GetWidth(), rect_a.GetHeight());
|
||||||
|
|
||||||
|
MVideoManager()->InvalidateRect(rect_b);
|
||||||
|
MVideoManager()->vtable0x34(rect_b.GetLeft(), rect_b.GetTop(), rect_b.GetWidth(), rect_b.GetHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100ba140
|
// FUNCTION: LEGO1 0x100ba140
|
||||||
void MxStillPresenter::Enable(MxBool p_enable)
|
void MxStillPresenter::Enable(MxBool p_enable)
|
||||||
{
|
{
|
||||||
// TODO
|
MxVideoPresenter::Enable(p_enable);
|
||||||
|
|
||||||
|
if (MVideoManager() && (m_alpha || m_bitmap)) {
|
||||||
|
MxS32 height = GetHeight();
|
||||||
|
MxS32 width = GetWidth();
|
||||||
|
MxS32 x = m_location.m_x;
|
||||||
|
MxS32 y = m_location.m_y;
|
||||||
|
|
||||||
|
MxRect32 rect(x, y, width + x, height + y);
|
||||||
|
MVideoManager()->InvalidateRect(rect);
|
||||||
|
MVideoManager()->vtable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100ba1e0
|
// FUNCTION: LEGO1 0x100ba1e0
|
||||||
|
|||||||
@ -32,14 +32,14 @@ class MxStillPresenter : public MxVideoPresenter {
|
|||||||
virtual void CreateBitmap() override; // vtable+0x60
|
virtual void CreateBitmap() override; // vtable+0x60
|
||||||
virtual void NextFrame() override; // vtable+0x64
|
virtual void NextFrame() override; // vtable+0x64
|
||||||
virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68
|
virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68
|
||||||
virtual void VTable0x70() override; // vtable+0x70
|
virtual void RealizePalette() override; // vtable+0x70
|
||||||
virtual void VTable0x88(undefined4, undefined4); // vtable+0x88
|
virtual void VTable0x88(MxS32 p_x, MxS32 p_y); // vtable+0x88
|
||||||
virtual MxStillPresenter* Clone(); // vtable+0x8c
|
virtual MxStillPresenter* Clone(); // vtable+0x8c
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Destroy(MxBool p_fromDestructor);
|
void Destroy(MxBool p_fromDestructor);
|
||||||
|
|
||||||
undefined4 m_unk64; // 0x64
|
MxLong m_chunkTime; // 0x64
|
||||||
MxBITMAPINFO* m_bitmapInfo; // 0x68
|
MxBITMAPINFO* m_bitmapInfo; // 0x68
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,13 @@ class MxStreamChunkList : public MxList<MxStreamChunk*> {
|
|||||||
static void Destroy(MxStreamChunk* p_chunk);
|
static void Destroy(MxStreamChunk* p_chunk);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MxListCursorChild<MxStreamChunk*> MxStreamChunkListCursor;
|
// VTABLE: LEGO1 0x100dc510
|
||||||
|
class MxStreamChunkListCursor : public MxListCursor<MxStreamChunk*> {
|
||||||
|
public:
|
||||||
|
MxStreamChunkListCursor(MxStreamChunkList* p_list) : MxListCursor<MxStreamChunk*>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dc528
|
||||||
|
// class MxListCursor<MxStreamChunk *>
|
||||||
|
|
||||||
#endif // MXSTREAMCHUNKLIST_H
|
#endif // MXSTREAMCHUNKLIST_H
|
||||||
|
|||||||
@ -51,13 +51,13 @@ MxStreamController::MxStreamController()
|
|||||||
// TEMPLATE: LEGO1 0x100c0ee0
|
// TEMPLATE: LEGO1 0x100c0ee0
|
||||||
// list<MxNextActionDataStart *,allocator<MxNextActionDataStart *> >::_Buynode
|
// list<MxNextActionDataStart *,allocator<MxNextActionDataStart *> >::_Buynode
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x100c0fc0
|
// FUNCTION: LEGO1 0x100c0fc0
|
||||||
// MxStreamListMxDSSubscriber::~MxStreamListMxDSSubscriber
|
// MxStreamListMxDSSubscriber::~MxStreamListMxDSSubscriber
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x100c1010
|
// FUNCTION: LEGO1 0x100c1010
|
||||||
// MxStreamListMxDSAction::~MxStreamListMxDSAction
|
// MxStreamListMxDSAction::~MxStreamListMxDSAction
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x100c1060
|
// FUNCTION: LEGO1 0x100c1060
|
||||||
// MxStreamListMxNextActionDataStart::~MxStreamListMxNextActionDataStart
|
// MxStreamListMxNextActionDataStart::~MxStreamListMxNextActionDataStart
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x100c10b0
|
// TEMPLATE: LEGO1 0x100c10b0
|
||||||
|
|||||||
@ -9,6 +9,12 @@
|
|||||||
class MxStringList : public MxList<MxString> {};
|
class MxStringList : public MxList<MxString> {};
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dd058
|
// VTABLE: LEGO1 0x100dd058
|
||||||
typedef MxListCursorChild<MxString> MxStringListCursor;
|
class MxStringListCursor : public MxListCursor<MxString> {
|
||||||
|
public:
|
||||||
|
MxStringListCursor(MxStringList* p_list) : MxListCursor<MxString>(p_list){};
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE: LEGO1 0x100dd070
|
||||||
|
// class MxListCursor<MxString>
|
||||||
|
|
||||||
#endif // MXSTRINGLIST_H
|
#endif // MXSTRINGLIST_H
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
#ifndef MXUNKLIST_H
|
|
||||||
#define MXUNKLIST_H
|
|
||||||
|
|
||||||
#include "decomp.h"
|
|
||||||
#include "mxtypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is an as-of-yet unknown list-like data structure.
|
|
||||||
* The class hierarchy/structure isn't quite correct yet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct MxUnkListNode {
|
|
||||||
MxUnkListNode* m_unk00;
|
|
||||||
MxUnkListNode* m_unk04;
|
|
||||||
undefined4 m_unk08;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MxUnkList {
|
|
||||||
public:
|
|
||||||
inline MxUnkList()
|
|
||||||
{
|
|
||||||
undefined unk;
|
|
||||||
this->m_unk00 = unk;
|
|
||||||
|
|
||||||
MxUnkListNode* node = new MxUnkListNode();
|
|
||||||
node->m_unk00 = node;
|
|
||||||
node->m_unk04 = node;
|
|
||||||
|
|
||||||
this->m_head = node;
|
|
||||||
this->m_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
undefined m_unk00;
|
|
||||||
MxUnkListNode* m_head;
|
|
||||||
MxU32 m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MXUNKLIST_H
|
|
||||||
@ -29,8 +29,8 @@ class MxVideoManager : public MxMediaManager {
|
|||||||
virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x2c
|
virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x2c
|
||||||
|
|
||||||
__declspec(dllexport) void InvalidateRect(MxRect32&);
|
__declspec(dllexport) void InvalidateRect(MxRect32&);
|
||||||
__declspec(dllexport) virtual MxResult RealizePalette(MxPalette*); // vtable+0x30
|
__declspec(dllexport) virtual MxResult RealizePalette(MxPalette*); // vtable+0x30
|
||||||
virtual void vtable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height);
|
virtual void vtable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height); // vtable+0x34
|
||||||
|
|
||||||
MxResult Init();
|
MxResult Init();
|
||||||
void Destroy(MxBool p_fromDestructor);
|
void Destroy(MxBool p_fromDestructor);
|
||||||
@ -42,12 +42,12 @@ class MxVideoManager : public MxMediaManager {
|
|||||||
inline MxDisplaySurface* GetDisplaySurface() { return this->m_displaySurface; }
|
inline MxDisplaySurface* GetDisplaySurface() { return this->m_displaySurface; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MxVideoParam m_videoParam;
|
MxVideoParam m_videoParam; // 0x2c
|
||||||
LPDIRECTDRAW m_pDirectDraw;
|
LPDIRECTDRAW m_pDirectDraw; // 0x50
|
||||||
LPDIRECTDRAWSURFACE m_pDDSurface;
|
LPDIRECTDRAWSURFACE m_pDDSurface; // 0x54
|
||||||
MxDisplaySurface* m_displaySurface;
|
MxDisplaySurface* m_displaySurface; // 0x58
|
||||||
MxRegion* m_region;
|
MxRegion* m_region; // 0x5c
|
||||||
MxBool m_unk60;
|
MxBool m_unk60; // 0x60
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXVIDEOMANAGER_H
|
#endif // MXVIDEOMANAGER_H
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
#include "mxvideoparam.h"
|
#include "mxvideoparam.h"
|
||||||
|
|
||||||
|
#include "decomp.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(MxVideoParam, 0x24);
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100bec70
|
// FUNCTION: LEGO1 0x100bec70
|
||||||
MxVideoParam::MxVideoParam()
|
MxVideoParam::MxVideoParam()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
|
|
||||||
|
// SIZE 0x24
|
||||||
class MxVideoParam {
|
class MxVideoParam {
|
||||||
public:
|
public:
|
||||||
__declspec(dllexport) MxVideoParam();
|
__declspec(dllexport) MxVideoParam();
|
||||||
@ -31,12 +32,12 @@ class MxVideoParam {
|
|||||||
inline MxU32 GetBackBuffers() { return this->m_backBuffers; }
|
inline MxU32 GetBackBuffers() { return this->m_backBuffers; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MxRect32 m_rect;
|
MxRect32 m_rect; // 0x00
|
||||||
MxPalette* m_palette;
|
MxPalette* m_palette; // 0x10
|
||||||
MxU32 m_backBuffers;
|
MxU32 m_backBuffers; // 0x14
|
||||||
MxVideoParamFlags m_flags;
|
MxVideoParamFlags m_flags; // 0x18
|
||||||
int m_unk1c;
|
int m_unk1c; // 0x1c
|
||||||
char* m_deviceId;
|
char* m_deviceId; // 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXVIDEOPARAM_H
|
#endif // MXVIDEOPARAM_H
|
||||||
|
|||||||
@ -26,7 +26,7 @@ void MxVideoPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1000c730
|
// FUNCTION: LEGO1 0x1000c730
|
||||||
void MxVideoPresenter::VTable0x70()
|
void MxVideoPresenter::RealizePalette()
|
||||||
{
|
{
|
||||||
// Empty
|
// Empty
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class MxVideoPresenter : public MxMediaPresenter {
|
|||||||
virtual void NextFrame(); // vtable+0x64
|
virtual void NextFrame(); // vtable+0x64
|
||||||
virtual void LoadFrame(MxStreamChunk* p_chunk); // vtable+0x68
|
virtual void LoadFrame(MxStreamChunk* p_chunk); // vtable+0x68
|
||||||
virtual void VTable0x6c(); // vtable+0x6c
|
virtual void VTable0x6c(); // vtable+0x6c
|
||||||
virtual void VTable0x70(); // vtable+0x70
|
virtual void RealizePalette(); // vtable+0x70
|
||||||
virtual undefined VTable0x74(); // vtable+0x74
|
virtual undefined VTable0x74(); // vtable+0x74
|
||||||
virtual LPDIRECTDRAWSURFACE VTable0x78(); // vtable+0x78
|
virtual LPDIRECTDRAWSURFACE VTable0x78(); // vtable+0x78
|
||||||
virtual MxBool VTable0x7c(); // vtable+0x7c
|
virtual MxBool VTable0x7c(); // vtable+0x7c
|
||||||
|
|||||||
33
LEGO1/tgl/d3drm/camera.cpp
Normal file
33
LEGO1/tgl/d3drm/camera.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(Camera, 0x4);
|
||||||
|
DECOMP_SIZE_ASSERT(CameraImpl, 0x8);
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a2560
|
||||||
|
// TglImpl::CameraImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a36f0
|
||||||
|
void* CameraImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3700
|
||||||
|
Result CameraImpl::SetTransformation(const FloatMatrix4& matrix)
|
||||||
|
{
|
||||||
|
D3DRMMATRIX4D helper;
|
||||||
|
D3DRMMATRIX4D* pTransformation = Translate(matrix, helper);
|
||||||
|
|
||||||
|
D3DVECTOR position;
|
||||||
|
Result result;
|
||||||
|
Result result2;
|
||||||
|
|
||||||
|
result2 = ResultVal(m_data->GetPosition(0, &position));
|
||||||
|
result = ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *pTransformation));
|
||||||
|
// The did this second call just to assert on the return value
|
||||||
|
result2 = ResultVal(m_data->GetPosition(0, &position));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
85
LEGO1/tgl/d3drm/device.cpp
Normal file
85
LEGO1/tgl/d3drm/device.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
#include <d3drmwin.h>
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a22c0
|
||||||
|
// TglImpl::DeviceImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2bf0
|
||||||
|
void* DeviceImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2c00
|
||||||
|
unsigned long DeviceImpl::GetWidth()
|
||||||
|
{
|
||||||
|
return m_data->GetWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2c10
|
||||||
|
unsigned long DeviceImpl::GetHeight()
|
||||||
|
{
|
||||||
|
return m_data->GetHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2c20
|
||||||
|
Result DeviceImpl::SetColorModel(ColorModel)
|
||||||
|
{
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2c30
|
||||||
|
Result DeviceImpl::SetShadingModel(ShadingModel model)
|
||||||
|
{
|
||||||
|
// Doesn't match well even though we know this is exactly
|
||||||
|
// the original code thanks to the jump table.
|
||||||
|
D3DRMRENDERQUALITY renderQuality = Translate(model);
|
||||||
|
return ResultVal(m_data->SetQuality(renderQuality));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2ca0
|
||||||
|
Result DeviceImpl::SetShadeCount(unsigned long shadeCount)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->SetShades(shadeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2cc0
|
||||||
|
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*)
|
||||||
|
{
|
||||||
|
// 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->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*)
|
||||||
|
{
|
||||||
|
// Device argument is intentionally unused.
|
||||||
|
IDirect3DRMWinDevice* winDevice;
|
||||||
|
if (SUCCEEDED(m_data->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &winDevice))) {
|
||||||
|
// m_data->Init(??);
|
||||||
|
winDevice->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2d60
|
||||||
|
Result DeviceImpl::Update()
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->Update());
|
||||||
|
}
|
||||||
122
LEGO1/tgl/d3drm/group.cpp
Normal file
122
LEGO1/tgl/d3drm/group.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a2480
|
||||||
|
// TglImpl::GroupImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a31d0
|
||||||
|
void* GroupImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a31e0
|
||||||
|
Result GroupImpl::SetTransformation(const FloatMatrix4& matrix)
|
||||||
|
{
|
||||||
|
D3DRMMATRIX4D helper;
|
||||||
|
D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper);
|
||||||
|
return ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *d3dMatrix));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3240
|
||||||
|
Result GroupImpl::SetColor(float r, float g, float b, float a)
|
||||||
|
{
|
||||||
|
// The first instruction makes no sense here:
|
||||||
|
// cmp dword ptr [esp + 0x10], 0
|
||||||
|
// This compares a, which we know is a float because it immediately
|
||||||
|
// gets passed into D3DRMCreateColorRGBA, but does the comparison
|
||||||
|
// as though it's an int??
|
||||||
|
if (*reinterpret_cast<int*>(&a) > 0) {
|
||||||
|
D3DCOLOR color = D3DRMCreateColorRGBA(r, g, b, a);
|
||||||
|
return ResultVal(m_data->SetColor(color));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ResultVal(m_data->SetColorRGB(r, a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a32b0
|
||||||
|
Result GroupImpl::SetTexture(const Texture* pTexture)
|
||||||
|
{
|
||||||
|
IDirect3DRMTexture* pD3DTexture = pTexture ? static_cast<const TextureImpl*>(pTexture)->ImplementationData() : NULL;
|
||||||
|
return ResultVal(m_data->SetTexture(pD3DTexture));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a32e0
|
||||||
|
Result GroupImpl::GetTexture(Texture*& pTexture)
|
||||||
|
{
|
||||||
|
IDirect3DRMTexture* pD3DTexture;
|
||||||
|
TextureImpl* holder = new TextureImpl();
|
||||||
|
Result result = ResultVal(m_data->GetTexture(&pD3DTexture));
|
||||||
|
if (result) {
|
||||||
|
// Seems to actually call the first virtual method of holder here
|
||||||
|
// but that doesn't make any sense since it passes three arguments
|
||||||
|
// to the method (self + string constant? + an offset?).
|
||||||
|
|
||||||
|
// This line makes the start of the function match and is what I
|
||||||
|
// would expect to see there but it clearly isn't what's actually
|
||||||
|
// there.
|
||||||
|
holder->SetImplementation(pD3DTexture);
|
||||||
|
}
|
||||||
|
pTexture = holder;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a33c0
|
||||||
|
Result GroupImpl::SetMaterialMode(MaterialMode mode)
|
||||||
|
{
|
||||||
|
D3DRMMATERIALMODE d3dMode;
|
||||||
|
switch (mode) {
|
||||||
|
case FromParent:
|
||||||
|
d3dMode = D3DRMMATERIAL_FROMPARENT;
|
||||||
|
break;
|
||||||
|
case FromFrame:
|
||||||
|
d3dMode = D3DRMMATERIAL_FROMFRAME;
|
||||||
|
break;
|
||||||
|
case FromMesh:
|
||||||
|
d3dMode = D3DRMMATERIAL_FROMMESH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ResultVal(m_data->SetMaterialMode(d3dMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3410
|
||||||
|
Result GroupImpl::Add(const Mesh* pMesh)
|
||||||
|
{
|
||||||
|
const MeshImpl* pMeshImpl = static_cast<const MeshImpl*>(pMesh);
|
||||||
|
return ResultVal(m_data->AddVisual(pMeshImpl->ImplementationData()->groupMesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3430
|
||||||
|
Result GroupImpl::Add(const Group* pGroup)
|
||||||
|
{
|
||||||
|
const GroupImpl* pGroupImpl = static_cast<const GroupImpl*>(pGroup);
|
||||||
|
return ResultVal(m_data->AddVisual(pGroupImpl->m_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3450
|
||||||
|
Result GroupImpl::Remove(const Group* pGroup)
|
||||||
|
{
|
||||||
|
const GroupImpl* pGroupImpl = static_cast<const GroupImpl*>(pGroup);
|
||||||
|
return ResultVal(m_data->DeleteVisual(pGroupImpl->m_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3480
|
||||||
|
Result GroupImpl::Remove(const Mesh* pMesh)
|
||||||
|
{
|
||||||
|
const MeshImpl* pMeshImpl = static_cast<const MeshImpl*>(pMesh);
|
||||||
|
return ResultVal(m_data->DeleteVisual(pMeshImpl->ImplementationData()->groupMesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a34b0 STUB
|
||||||
|
Result GroupImpl::RemoveAll()
|
||||||
|
{
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a34c0 STUB
|
||||||
|
Result GroupImpl::Unknown()
|
||||||
|
{
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
467
LEGO1/tgl/d3drm/impl.h
Normal file
467
LEGO1/tgl/d3drm/impl.h
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
|
||||||
|
#include "../../decomp.h"
|
||||||
|
#include "../tgl.h"
|
||||||
|
|
||||||
|
#include <d3drm.h>
|
||||||
|
|
||||||
|
// Forward declare D3D types
|
||||||
|
struct IDirect3DRM;
|
||||||
|
struct IDirect3DRMDevice;
|
||||||
|
struct IDirect3DRMViewport;
|
||||||
|
struct IDirect3DRMFrame;
|
||||||
|
struct IDirect3DRMMesh;
|
||||||
|
struct IDirect3DRMMeshBuilder;
|
||||||
|
struct IDirect3DRMTexture;
|
||||||
|
|
||||||
|
namespace TglImpl
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace Tgl;
|
||||||
|
|
||||||
|
// Utility function used by implementations
|
||||||
|
inline Result ResultVal(HRESULT result)
|
||||||
|
{
|
||||||
|
return SUCCEEDED(result) ? Success : Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward declare implementations
|
||||||
|
class RendererImpl;
|
||||||
|
class DeviceImpl;
|
||||||
|
class ViewImpl;
|
||||||
|
class LightImpl;
|
||||||
|
class CameraImpl;
|
||||||
|
class GroupImpl;
|
||||||
|
class MeshImpl;
|
||||||
|
class TextureImpl;
|
||||||
|
class UnkImpl;
|
||||||
|
|
||||||
|
// VTABLE 0x100db910
|
||||||
|
class RendererImpl : public Renderer {
|
||||||
|
public:
|
||||||
|
RendererImpl() : m_data(0) {}
|
||||||
|
~RendererImpl() { Destroy(); };
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Device* CreateDevice(const DeviceDirect3DCreateData&);
|
||||||
|
virtual Device* CreateDevice(const DeviceDirectDrawCreateData&);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual View* CreateView(
|
||||||
|
const Device*,
|
||||||
|
const Camera*,
|
||||||
|
unsigned long x,
|
||||||
|
unsigned long y,
|
||||||
|
unsigned long width,
|
||||||
|
unsigned long height
|
||||||
|
);
|
||||||
|
virtual Camera* CreateCamera();
|
||||||
|
virtual Light* CreateLight(LightType, float r, float g, float b);
|
||||||
|
virtual Group* CreateGroup(const Group* pParent);
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Unk* CreateUnk();
|
||||||
|
virtual Texture* CreateTexture();
|
||||||
|
virtual Texture* CreateTexture(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int bitsPerTexel,
|
||||||
|
const void* pTexels,
|
||||||
|
int pTexelsArePersistent,
|
||||||
|
int paletteEntryCount,
|
||||||
|
const PaletteEntry* pEntries
|
||||||
|
);
|
||||||
|
virtual Result SetTextureDefaultShadeCount(unsigned long);
|
||||||
|
|
||||||
|
// vtable+0x30
|
||||||
|
virtual Result SetTextureDefaultColorCount(unsigned long);
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline Result Create();
|
||||||
|
inline void Destroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRM* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100db988
|
||||||
|
class DeviceImpl : public Device {
|
||||||
|
public:
|
||||||
|
DeviceImpl() : m_data(0) {}
|
||||||
|
~DeviceImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual unsigned long GetWidth();
|
||||||
|
virtual unsigned long GetHeight();
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Result SetColorModel(ColorModel);
|
||||||
|
virtual Result SetShadingModel(ShadingModel);
|
||||||
|
virtual Result SetShadeCount(unsigned long);
|
||||||
|
virtual Result SetDither(int);
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Result Update();
|
||||||
|
virtual void InitFromD3DDevice(Device*);
|
||||||
|
virtual void InitFromWindowsDevice(Device*);
|
||||||
|
|
||||||
|
inline IDirect3DRMDevice* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMDevice* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100db9e8
|
||||||
|
class ViewImpl : public View {
|
||||||
|
public:
|
||||||
|
ViewImpl() : m_data(0) {}
|
||||||
|
~ViewImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result Add(const Light*);
|
||||||
|
virtual Result Remove(const Light*);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Result SetCamera(const Camera*);
|
||||||
|
virtual Result SetProjection(ProjectionType);
|
||||||
|
virtual Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees);
|
||||||
|
virtual Result SetBackgroundColor(float r, float g, float b);
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Result GetBackgroundColor(float* r, float* g, float* b);
|
||||||
|
virtual Result Clear();
|
||||||
|
virtual Result Render(const Light*);
|
||||||
|
virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height);
|
||||||
|
|
||||||
|
// vtable+0x30
|
||||||
|
virtual Result TransformWorldToScreen(const float world[3], float screen[4]);
|
||||||
|
virtual Result TransformScreenToWorld(const float screen[4], float world[3]);
|
||||||
|
virtual Result Pick(
|
||||||
|
unsigned long x,
|
||||||
|
unsigned long y,
|
||||||
|
const Group** ppGroupsToPickFrom,
|
||||||
|
int groupsToPickFromCount,
|
||||||
|
const Group**& rppPickedGroups,
|
||||||
|
int& rPickedGroupCount
|
||||||
|
);
|
||||||
|
|
||||||
|
inline IDirect3DRMViewport* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
static Result ViewportCreateAppData(IDirect3DRM*, IDirect3DRMViewport*, IDirect3DRMFrame*);
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMViewport* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbad8
|
||||||
|
class CameraImpl : public Camera {
|
||||||
|
public:
|
||||||
|
CameraImpl() : m_data(0) {}
|
||||||
|
~CameraImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetTransformation(const FloatMatrix4&);
|
||||||
|
|
||||||
|
inline IDirect3DRMFrame* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMFrame* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbaf8
|
||||||
|
class LightImpl : public Light {
|
||||||
|
public:
|
||||||
|
LightImpl() : m_data(0) {}
|
||||||
|
~LightImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetTransformation(const FloatMatrix4&);
|
||||||
|
virtual Result SetColor(float r, float g, float b);
|
||||||
|
|
||||||
|
inline IDirect3DRMFrame* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMFrame* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbb88
|
||||||
|
class MeshImpl : public Mesh {
|
||||||
|
public:
|
||||||
|
MeshImpl() : m_data(0) {}
|
||||||
|
~MeshImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
delete m_data;
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetColor(float r, float g, float b, float a);
|
||||||
|
virtual Result SetTexture(const Texture*);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Result GetTexture(Texture*&);
|
||||||
|
virtual Result SetTextureMappingMode(ProjectionType);
|
||||||
|
virtual Result SetShadingModel(ShadingModel);
|
||||||
|
virtual Mesh* DeepClone(Unk*);
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Mesh* ShallowClone(Unk*);
|
||||||
|
|
||||||
|
struct MeshData {
|
||||||
|
IDirect3DRMMesh* groupMesh;
|
||||||
|
int groupIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline MeshData* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MeshData* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dba68
|
||||||
|
class GroupImpl : public Group {
|
||||||
|
public:
|
||||||
|
GroupImpl() : m_data(0) {}
|
||||||
|
~GroupImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetTransformation(const FloatMatrix4&);
|
||||||
|
virtual Result SetColor(float r, float g, float b, float a);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Result SetTexture(const Texture*);
|
||||||
|
virtual Result GetTexture(Texture*&);
|
||||||
|
virtual Result SetMaterialMode(MaterialMode);
|
||||||
|
virtual Result Add(const Group*);
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Result Add(const Mesh*);
|
||||||
|
virtual Result Remove(const Group*);
|
||||||
|
virtual Result Remove(const Mesh*);
|
||||||
|
virtual Result RemoveAll();
|
||||||
|
|
||||||
|
// vtable+0x30
|
||||||
|
virtual Result Unknown();
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMFrame* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbb18
|
||||||
|
class UnkImpl : public Unk {
|
||||||
|
public:
|
||||||
|
UnkImpl() : m_data(0) {}
|
||||||
|
~UnkImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetMeshData(
|
||||||
|
unsigned long faceCount,
|
||||||
|
unsigned long vertexCount,
|
||||||
|
const float (*pPositions)[3],
|
||||||
|
const float (*pNormals)[3],
|
||||||
|
const float (*pTextureCoordinates)[2],
|
||||||
|
unsigned long vertexPerFaceCount,
|
||||||
|
unsigned long* pFaceData
|
||||||
|
);
|
||||||
|
virtual Result GetBoundingBox(float min[3], float max[3]);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Unk* Clone();
|
||||||
|
|
||||||
|
inline IDirect3DRMMesh* ImplementationData() const { return m_data; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMMesh* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// No vtable, this is just a simple wrapper around D3DRMIMAGE
|
||||||
|
class TglD3DRMIMAGE {
|
||||||
|
public:
|
||||||
|
TglD3DRMIMAGE(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int depth,
|
||||||
|
void* pBuffer,
|
||||||
|
int useBuffer,
|
||||||
|
int paletteSize,
|
||||||
|
PaletteEntry* pEntries
|
||||||
|
);
|
||||||
|
~TglD3DRMIMAGE() { Destroy(); }
|
||||||
|
|
||||||
|
Result CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer);
|
||||||
|
void Destroy();
|
||||||
|
void FillRowsOfTexture(int y, int height, char* content);
|
||||||
|
Result InitializePalette(int paletteSize, PaletteEntry* pEntries);
|
||||||
|
|
||||||
|
D3DRMIMAGE m_image;
|
||||||
|
int m_texelsAllocatedByClient;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbb48
|
||||||
|
class TextureImpl : public Texture {
|
||||||
|
public:
|
||||||
|
TextureImpl() : m_data(0) {}
|
||||||
|
~TextureImpl()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
m_data->Release();
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* ImplementationDataPtr();
|
||||||
|
|
||||||
|
// vtable+0x08
|
||||||
|
virtual Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels);
|
||||||
|
virtual void FillRowsOfTexture(int y, int height, void* pBuffer);
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
|
virtual Result Changed(int texelsChanged, int paletteChanged);
|
||||||
|
virtual Result GetBufferAndPalette(
|
||||||
|
int* pWidth,
|
||||||
|
int* pHeight,
|
||||||
|
int* pDepth,
|
||||||
|
void** ppBuffer,
|
||||||
|
int* ppPaletteSize,
|
||||||
|
PaletteEntry** ppPalette
|
||||||
|
);
|
||||||
|
virtual Result SetPalette(int entryCount, PaletteEntry* entries);
|
||||||
|
|
||||||
|
inline IDirect3DRMTexture* ImplementationData() const { return m_data; }
|
||||||
|
inline void SetImplementation(IDirect3DRMTexture* pData) { m_data = pData; }
|
||||||
|
|
||||||
|
friend class RendererImpl;
|
||||||
|
|
||||||
|
static Result SetImage(IDirect3DRMTexture* pSelf, TglD3DRMIMAGE* pImage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDirect3DRMTexture* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Translation helpers
|
||||||
|
inline D3DRMRENDERQUALITY Translate(ShadingModel tglShadingModel)
|
||||||
|
{
|
||||||
|
D3DRMRENDERQUALITY renderQuality;
|
||||||
|
|
||||||
|
switch (tglShadingModel) {
|
||||||
|
case Wireframe:
|
||||||
|
renderQuality = D3DRMRENDER_WIREFRAME;
|
||||||
|
break;
|
||||||
|
case UnlitFlat:
|
||||||
|
renderQuality = D3DRMRENDER_UNLITFLAT;
|
||||||
|
break;
|
||||||
|
case Flat:
|
||||||
|
renderQuality = D3DRMRENDER_FLAT;
|
||||||
|
break;
|
||||||
|
case Gouraud:
|
||||||
|
renderQuality = D3DRMRENDER_GOURAUD;
|
||||||
|
break;
|
||||||
|
case Phong:
|
||||||
|
renderQuality = D3DRMRENDER_PHONG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
renderQuality = D3DRMRENDER_FLAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderQuality;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline D3DRMPROJECTIONTYPE Translate(ProjectionType tglProjectionType)
|
||||||
|
{
|
||||||
|
D3DRMPROJECTIONTYPE projectionType;
|
||||||
|
switch (tglProjectionType) {
|
||||||
|
case Perspective:
|
||||||
|
projectionType = D3DRMPROJECT_PERSPECTIVE;
|
||||||
|
break;
|
||||||
|
case Orthographic:
|
||||||
|
projectionType = D3DRMPROJECT_ORTHOGRAPHIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
projectionType = D3DRMPROJECT_PERSPECTIVE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return projectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yes this function serves no purpose, originally they intended it to
|
||||||
|
// convert from doubles to floats but ended up using floats throughout
|
||||||
|
// the software stack.
|
||||||
|
inline D3DRMMATRIX4D* Translate(const FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) {
|
||||||
|
for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) {
|
||||||
|
rD3DRMMatrix4x4[i][j] = D3DVAL(tglMatrix4x4[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &rD3DRMMatrix4x4;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace TglImpl */
|
||||||
33
LEGO1/tgl/d3drm/light.cpp
Normal file
33
LEGO1/tgl/d3drm/light.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(Light, 0x4);
|
||||||
|
DECOMP_SIZE_ASSERT(LightImpl, 0x8);
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a2640
|
||||||
|
// TglImpl::LightImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3770
|
||||||
|
void* LightImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3780
|
||||||
|
Result LightImpl::SetTransformation(const FloatMatrix4& matrix)
|
||||||
|
{
|
||||||
|
D3DRMMATRIX4D helper;
|
||||||
|
D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper);
|
||||||
|
return ResultVal(m_data->AddTransform(D3DRMCOMBINE_REPLACE, *d3dMatrix));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a37e0
|
||||||
|
Result LightImpl::SetColor(float r, float g, float b)
|
||||||
|
{
|
||||||
|
IDirect3DRMLightArray* lightArray;
|
||||||
|
IDirect3DRMLight* light;
|
||||||
|
m_data->GetLights(&lightArray);
|
||||||
|
lightArray->GetElement(0, &light);
|
||||||
|
return ResultVal(light->SetColorRGB(r, g, b));
|
||||||
|
}
|
||||||
158
LEGO1/tgl/d3drm/mesh.cpp
Normal file
158
LEGO1/tgl/d3drm/mesh.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(D3DRMVERTEX, 0x24);
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(Mesh, 0x4);
|
||||||
|
DECOMP_SIZE_ASSERT(MeshImpl, 0x8);
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a3d80
|
||||||
|
// TglImpl::MeshImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3ed0
|
||||||
|
void* MeshImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3ee0
|
||||||
|
Result MeshImpl::SetColor(float r, float g, float b, float a)
|
||||||
|
{
|
||||||
|
// The first instruction makes no sense here:
|
||||||
|
// cmp dword ptr [esp + 0x10], 0
|
||||||
|
// This compares a, which we know is a float because it immediately
|
||||||
|
// gets passed into D3DRMCreateColorRGBA, but does the comparison
|
||||||
|
// as though it's an int??
|
||||||
|
if (*reinterpret_cast<int*>(&a) > 0) {
|
||||||
|
D3DCOLOR color = D3DRMCreateColorRGBA(r, g, b, a);
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupColor(m_data->groupIndex, color));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupColorRGB(m_data->groupIndex, r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3f50
|
||||||
|
Result MeshImpl::SetTexture(const Texture* pTexture)
|
||||||
|
{
|
||||||
|
IDirect3DRMTexture* texture = pTexture ? static_cast<const TextureImpl*>(pTexture)->ImplementationData() : NULL;
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupTexture(m_data->groupIndex, texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3f80
|
||||||
|
Result MeshImpl::SetTextureMappingMode(ProjectionType projType)
|
||||||
|
{
|
||||||
|
if (projType == Perspective) {
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupMapping(m_data->groupIndex, D3DRMMAP_PERSPCORRECT));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupMapping(m_data->groupIndex, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3fc0
|
||||||
|
Result MeshImpl::SetShadingModel(ShadingModel model)
|
||||||
|
{
|
||||||
|
D3DRMRENDERQUALITY mode;
|
||||||
|
switch (model) {
|
||||||
|
case Wireframe:
|
||||||
|
mode = D3DRMRENDER_WIREFRAME;
|
||||||
|
break;
|
||||||
|
case UnlitFlat:
|
||||||
|
mode = D3DRMRENDER_UNLITFLAT;
|
||||||
|
break;
|
||||||
|
case Flat:
|
||||||
|
mode = D3DRMRENDER_FLAT;
|
||||||
|
break;
|
||||||
|
case Gouraud:
|
||||||
|
mode = D3DRMRENDER_GOURAUD;
|
||||||
|
break;
|
||||||
|
case Phong:
|
||||||
|
mode = D3DRMRENDER_PHONG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ResultVal(m_data->groupMesh->SetGroupQuality(m_data->groupIndex, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a4030
|
||||||
|
Mesh* MeshImpl::DeepClone(Unk* pUnk)
|
||||||
|
{
|
||||||
|
// Create group
|
||||||
|
MeshImpl* newMesh = new MeshImpl();
|
||||||
|
MeshData* data = new MeshData();
|
||||||
|
newMesh->m_data = data;
|
||||||
|
|
||||||
|
// Query information from old group
|
||||||
|
DWORD dataSize;
|
||||||
|
unsigned int vcount, fcount, vperface;
|
||||||
|
m_data->groupMesh->GetGroup(m_data->groupIndex, &vcount, &fcount, &vperface, &dataSize, NULL);
|
||||||
|
unsigned int* faceBuffer = new unsigned int[dataSize];
|
||||||
|
m_data->groupMesh->GetGroup(m_data->groupIndex, &vcount, &fcount, &vperface, &dataSize, faceBuffer);
|
||||||
|
// We expect vertex to be sized 0x24, checked at start of file.
|
||||||
|
D3DRMVERTEX* vertexBuffer = new D3DRMVERTEX[vcount];
|
||||||
|
m_data->groupMesh->GetVertices(m_data->groupIndex, 0, vcount, vertexBuffer);
|
||||||
|
LPDIRECT3DRMTEXTURE textureRef;
|
||||||
|
m_data->groupMesh->GetGroupTexture(m_data->groupIndex, &textureRef);
|
||||||
|
D3DRMMAPPING mapping = m_data->groupMesh->GetGroupMapping(m_data->groupIndex);
|
||||||
|
D3DRMRENDERQUALITY quality = m_data->groupMesh->GetGroupQuality(m_data->groupIndex);
|
||||||
|
D3DCOLOR color = m_data->groupMesh->GetGroupColor(m_data->groupIndex);
|
||||||
|
|
||||||
|
// Push information to new group
|
||||||
|
UnkImpl* target = static_cast<UnkImpl*>(pUnk);
|
||||||
|
D3DRMGROUPINDEX index;
|
||||||
|
target->ImplementationData()->AddGroup(vcount, fcount, vperface, faceBuffer, &index);
|
||||||
|
newMesh->m_data->groupIndex = index;
|
||||||
|
target->ImplementationData()->SetVertices(index, 0, vcount, vertexBuffer);
|
||||||
|
target->ImplementationData()->SetGroupTexture(index, textureRef);
|
||||||
|
target->ImplementationData()->SetGroupMapping(index, mapping);
|
||||||
|
target->ImplementationData()->SetGroupQuality(index, quality);
|
||||||
|
Result result = ResultVal(target->ImplementationData()->SetGroupColor(index, color));
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
delete[] faceBuffer;
|
||||||
|
delete[] vertexBuffer;
|
||||||
|
if (result == Error) {
|
||||||
|
delete newMesh;
|
||||||
|
newMesh = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a4240
|
||||||
|
Mesh* MeshImpl::ShallowClone(Unk* pUnk)
|
||||||
|
{
|
||||||
|
MeshImpl* newGroup = new MeshImpl();
|
||||||
|
MeshData* newData = new MeshData();
|
||||||
|
newGroup->m_data = newData;
|
||||||
|
if (newData) {
|
||||||
|
newData->groupIndex = m_data->groupIndex;
|
||||||
|
newData->groupMesh = static_cast<UnkImpl*>(pUnk)->ImplementationData();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete newGroup;
|
||||||
|
newGroup = NULL;
|
||||||
|
}
|
||||||
|
return newGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a4330
|
||||||
|
Result MeshImpl::GetTexture(Texture*& rpTexture)
|
||||||
|
{
|
||||||
|
IDirect3DRMTexture* texture;
|
||||||
|
TextureImpl* holder = new TextureImpl();
|
||||||
|
Result result = ResultVal(m_data->groupMesh->GetGroupTexture(m_data->groupIndex, &texture));
|
||||||
|
if (result) {
|
||||||
|
// Seems to actually call the first virtual method of holder here
|
||||||
|
// but that doesn't make any sense since it passes three arguments
|
||||||
|
// to the method (self + string constant? + an offset?).
|
||||||
|
|
||||||
|
// This line makes the start of the function match and is what I
|
||||||
|
// would expect to see there but it clearly isn't what's actually
|
||||||
|
// there.
|
||||||
|
holder->SetImplementation(texture);
|
||||||
|
}
|
||||||
|
rpTexture = holder;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
332
LEGO1/tgl/d3drm/renderer.cpp
Normal file
332
LEGO1/tgl/d3drm/renderer.cpp
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a15e0
|
||||||
|
Renderer* Tgl::CreateRenderer()
|
||||||
|
{
|
||||||
|
RendererImpl* renderer = new RendererImpl();
|
||||||
|
if (!renderer->Create()) {
|
||||||
|
delete renderer;
|
||||||
|
renderer = NULL;
|
||||||
|
}
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a16d0
|
||||||
|
// TglImpl::RendererImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// GLOBAL: LEGO1 0x1010103c
|
||||||
|
IDirect3DRM* g_pD3DRM = NULL;
|
||||||
|
|
||||||
|
// Inlined only
|
||||||
|
Result RendererImpl::Create()
|
||||||
|
{
|
||||||
|
if (g_pD3DRM) {
|
||||||
|
g_pD3DRM->AddRef();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LPDIRECT3DRM handle;
|
||||||
|
Direct3DRMCreate(&handle);
|
||||||
|
handle->QueryInterface(IID_IDirect3DRM2, (LPVOID*) &g_pD3DRM);
|
||||||
|
}
|
||||||
|
m_data = g_pD3DRM;
|
||||||
|
return (m_data != NULL) ? Success : Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void RendererDestroy(IDirect3DRM* pRenderer)
|
||||||
|
{
|
||||||
|
int refCount = pRenderer->Release();
|
||||||
|
if (refCount <= 0) {
|
||||||
|
g_pD3DRM = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inlined only
|
||||||
|
void RendererImpl::Destroy()
|
||||||
|
{
|
||||||
|
if (m_data) {
|
||||||
|
RendererDestroy(m_data);
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1894
|
||||||
|
Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data)
|
||||||
|
{
|
||||||
|
DeviceImpl* device = new DeviceImpl();
|
||||||
|
HRESULT result = m_data->CreateDeviceFromD3D(data.m_pDirect3D, data.m_pDirect3DDevice, &device->m_data);
|
||||||
|
if (!SUCCEEDED(result)) {
|
||||||
|
delete device;
|
||||||
|
device = NULL;
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLOBAL: LEGO1 0x10101040
|
||||||
|
static int gSetBufferCount = 1;
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1900
|
||||||
|
Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data)
|
||||||
|
{
|
||||||
|
DeviceImpl* device = new DeviceImpl();
|
||||||
|
HRESULT result = m_data->CreateDeviceFromSurface(
|
||||||
|
const_cast<LPGUID>(data.m_driverGUID),
|
||||||
|
data.m_pDirectDraw,
|
||||||
|
data.m_pBackBuffer,
|
||||||
|
&device->m_data
|
||||||
|
);
|
||||||
|
if (SUCCEEDED(result) && data.m_pBackBuffer && gSetBufferCount) {
|
||||||
|
device->m_data->SetBufferCount(2);
|
||||||
|
}
|
||||||
|
if (!SUCCEEDED(result)) {
|
||||||
|
delete device;
|
||||||
|
device = NULL;
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result RendererCreateView(
|
||||||
|
IDirect3DRM* pRenderer,
|
||||||
|
IDirect3DRMDevice* pDevice,
|
||||||
|
IDirect3DRMFrame* pCamera,
|
||||||
|
IDirect3DRMViewport*& rpView,
|
||||||
|
unsigned long x,
|
||||||
|
unsigned long y,
|
||||||
|
unsigned long width,
|
||||||
|
unsigned long height
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Result result = ResultVal(pRenderer->CreateViewport(pDevice, pCamera, x, y, width, height, &rpView));
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = ViewImpl::ViewportCreateAppData(pRenderer, rpView, pCamera);
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
rpView->Release();
|
||||||
|
rpView = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1a00
|
||||||
|
View* RendererImpl::CreateView(
|
||||||
|
const Device* pDevice,
|
||||||
|
const Camera* pCamera,
|
||||||
|
unsigned long x,
|
||||||
|
unsigned long y,
|
||||||
|
unsigned long width,
|
||||||
|
unsigned long height
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ViewImpl* view = new ViewImpl();
|
||||||
|
Result result = RendererCreateView(
|
||||||
|
m_data,
|
||||||
|
static_cast<const DeviceImpl*>(pDevice)->m_data,
|
||||||
|
static_cast<const CameraImpl*>(pCamera)->m_data,
|
||||||
|
view->m_data,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
if (!result) {
|
||||||
|
delete view;
|
||||||
|
view = NULL;
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result RendererCreateGroup(IDirect3DRM* pRenderer, IDirect3DRMFrame* pParent, IDirect3DRMFrame*& rpGroup)
|
||||||
|
{
|
||||||
|
Result result = ResultVal(pRenderer->CreateFrame(NULL, &rpGroup));
|
||||||
|
if (Succeeded(result) && pParent) {
|
||||||
|
result = ResultVal(pParent->AddVisual(rpGroup));
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
rpGroup->Release();
|
||||||
|
rpGroup = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1b20
|
||||||
|
Group* RendererImpl::CreateGroup(const Group* pParent)
|
||||||
|
{
|
||||||
|
GroupImpl* group = new GroupImpl();
|
||||||
|
Result result =
|
||||||
|
RendererCreateGroup(m_data, pParent ? static_cast<const GroupImpl*>(pParent)->m_data : NULL, group->m_data);
|
||||||
|
if (!result) {
|
||||||
|
delete group;
|
||||||
|
group = NULL;
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1c30
|
||||||
|
Camera* RendererImpl::CreateCamera()
|
||||||
|
{
|
||||||
|
CameraImpl* camera = new CameraImpl();
|
||||||
|
if (FAILED(m_data->CreateFrame(NULL, &camera->m_data))) {
|
||||||
|
delete camera;
|
||||||
|
camera = NULL;
|
||||||
|
}
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1cf0
|
||||||
|
Light* RendererImpl::CreateLight(LightType type, float r, float g, float b)
|
||||||
|
{
|
||||||
|
LightImpl* newLight = new LightImpl();
|
||||||
|
D3DRMLIGHTTYPE translatedType;
|
||||||
|
switch (type) {
|
||||||
|
case Ambient:
|
||||||
|
translatedType = D3DRMLIGHT_AMBIENT;
|
||||||
|
break;
|
||||||
|
case Point:
|
||||||
|
translatedType = D3DRMLIGHT_POINT;
|
||||||
|
break;
|
||||||
|
case Spot:
|
||||||
|
translatedType = D3DRMLIGHT_SPOT;
|
||||||
|
break;
|
||||||
|
case Directional:
|
||||||
|
translatedType = D3DRMLIGHT_DIRECTIONAL;
|
||||||
|
break;
|
||||||
|
case ParallelPoint:
|
||||||
|
translatedType = D3DRMLIGHT_PARALLELPOINT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
translatedType = D3DRMLIGHT_AMBIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPDIRECT3DRMFRAME frame;
|
||||||
|
Result result = ResultVal(m_data->CreateFrame(NULL, &frame));
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
LPDIRECT3DRMLIGHT d3dLight;
|
||||||
|
result = ResultVal(m_data->CreateLightRGB(translatedType, r, g, b, &d3dLight));
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
frame->Release();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = ResultVal(frame->AddLight(d3dLight));
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
d3dLight->Release();
|
||||||
|
frame->Release();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d3dLight->Release();
|
||||||
|
newLight->m_data = frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
delete newLight;
|
||||||
|
newLight = NULL;
|
||||||
|
}
|
||||||
|
return newLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1e90
|
||||||
|
Unk* RendererImpl::CreateUnk()
|
||||||
|
{
|
||||||
|
// Note: I'm fairly certain that Unknown is not what Tgl calls a
|
||||||
|
// "Mesh", because the methods on Mesh in the Tgl leak line up much
|
||||||
|
// more closely with a different vtable than the one assigned in
|
||||||
|
// this method (meaning this method is not creating a Mesh).
|
||||||
|
// Maybe this method is something like CreateMeshBuilder where the
|
||||||
|
// Mesh data type in the Tgl leak was split into builder/result?
|
||||||
|
UnkImpl* unknown = new UnkImpl();
|
||||||
|
if (FAILED(m_data->CreateMesh(&unknown->m_data))) {
|
||||||
|
delete unknown;
|
||||||
|
unknown = NULL;
|
||||||
|
}
|
||||||
|
return unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result RendererCreateTexture(
|
||||||
|
IDirect3DRM* renderer,
|
||||||
|
IDirect3DRMTexture*& texture,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int bytesPerPixel,
|
||||||
|
void* pBuffer,
|
||||||
|
int useBuffer,
|
||||||
|
int paletteSize,
|
||||||
|
PaletteEntry* pEntries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TglD3DRMIMAGE* image;
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
image = new TglD3DRMIMAGE(width, height, bytesPerPixel, pBuffer, useBuffer, paletteSize, pEntries);
|
||||||
|
result = ResultVal(renderer->CreateTexture(&image->m_image, &texture));
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = TextureImpl::SetImage(texture, image);
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
texture->Release();
|
||||||
|
texture = NULL;
|
||||||
|
delete image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete image;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1f50
|
||||||
|
Texture* RendererImpl::CreateTexture(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int bitsPerTexel,
|
||||||
|
const void* pTexels,
|
||||||
|
int texelsArePersistent,
|
||||||
|
int paletteEntryCount,
|
||||||
|
const PaletteEntry* pEntries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TextureImpl* texture = new TextureImpl();
|
||||||
|
if (!Succeeded(RendererCreateTexture(
|
||||||
|
m_data,
|
||||||
|
texture->m_data,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
bitsPerTexel,
|
||||||
|
const_cast<void*>(pTexels),
|
||||||
|
texelsArePersistent,
|
||||||
|
paletteEntryCount,
|
||||||
|
const_cast<PaletteEntry*>(pEntries)
|
||||||
|
))) {
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a20d0
|
||||||
|
Texture* RendererImpl::CreateTexture()
|
||||||
|
{
|
||||||
|
TextureImpl* texture = new TextureImpl();
|
||||||
|
if (!Succeeded(RendererCreateTexture(m_data, texture->m_data, 0, 0, 0, NULL, FALSE, 0, NULL))) {
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2270
|
||||||
|
Result RendererImpl::SetTextureDefaultShadeCount(unsigned long shadeCount)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->SetDefaultTextureShades(shadeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2290
|
||||||
|
Result RendererImpl::SetTextureDefaultColorCount(unsigned long colorCount)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->SetDefaultTextureColors(colorCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a22b0
|
||||||
|
void* RendererImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
196
LEGO1/tgl/d3drm/texture.cpp
Normal file
196
LEGO1/tgl/d3drm/texture.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(TglD3DRMIMAGE, 0x40);
|
||||||
|
|
||||||
|
inline TglD3DRMIMAGE* TextureGetImage(IDirect3DRMTexture* pTexture)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TglD3DRMIMAGE*>(pTexture->GetAppData());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward declare to satisfy order check
|
||||||
|
void TextureDestroyCallback(IDirect3DRMObject* pObject, void* pArg);
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a12a0
|
||||||
|
Result TextureImpl::SetImage(IDirect3DRMTexture* pSelf, TglD3DRMIMAGE* pImage)
|
||||||
|
{
|
||||||
|
unsigned long appData;
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
appData = reinterpret_cast<unsigned long>(pImage);
|
||||||
|
|
||||||
|
// This is here because in the original code they asserted
|
||||||
|
// on the return value being NULL.
|
||||||
|
TextureGetImage(pSelf);
|
||||||
|
|
||||||
|
result = ResultVal(pSelf->SetAppData(appData));
|
||||||
|
if (Succeeded(result) && pImage) {
|
||||||
|
result = ResultVal(pSelf->AddDestroyCallback(TextureDestroyCallback, NULL));
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
pSelf->SetAppData(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1300
|
||||||
|
void TextureDestroyCallback(IDirect3DRMObject* pObject, void* pArg)
|
||||||
|
{
|
||||||
|
TglD3DRMIMAGE* pImage = reinterpret_cast<TglD3DRMIMAGE*>(pObject->GetAppData());
|
||||||
|
delete pImage;
|
||||||
|
pObject->SetAppData(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1330
|
||||||
|
TglD3DRMIMAGE::TglD3DRMIMAGE(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int depth,
|
||||||
|
void* pBuffer,
|
||||||
|
int useBuffer,
|
||||||
|
int paletteSize,
|
||||||
|
PaletteEntry* pEntries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_image.aspectx = 1;
|
||||||
|
m_image.aspecty = 1;
|
||||||
|
m_image.width = 0;
|
||||||
|
m_image.height = 0;
|
||||||
|
m_image.depth = 0;
|
||||||
|
m_image.rgb = 0;
|
||||||
|
m_image.bytes_per_line = 0;
|
||||||
|
m_image.buffer1 = NULL;
|
||||||
|
m_image.buffer2 = NULL;
|
||||||
|
m_image.red_mask = 0xFF;
|
||||||
|
m_image.green_mask = 0xFF;
|
||||||
|
m_image.blue_mask = 0xFF;
|
||||||
|
m_image.alpha_mask = 0xFF;
|
||||||
|
m_image.palette_size = 0;
|
||||||
|
m_image.palette = NULL;
|
||||||
|
m_texelsAllocatedByClient = 0;
|
||||||
|
if (pBuffer != NULL) {
|
||||||
|
CreateBuffer(width, height, depth, pBuffer, useBuffer);
|
||||||
|
}
|
||||||
|
if (pEntries != NULL) {
|
||||||
|
InitializePalette(paletteSize, pEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a13b0
|
||||||
|
void TglD3DRMIMAGE::Destroy()
|
||||||
|
{
|
||||||
|
if (m_texelsAllocatedByClient == 0) {
|
||||||
|
delete m_image.buffer1;
|
||||||
|
}
|
||||||
|
delete m_image.palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a13e0 STUB
|
||||||
|
Result TglD3DRMIMAGE::CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer)
|
||||||
|
{
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1510
|
||||||
|
void TglD3DRMIMAGE::FillRowsOfTexture(int y, int height, char* pContent)
|
||||||
|
{
|
||||||
|
// The purpose is clearly this but I can't get the assembly to line up.
|
||||||
|
memcpy((char*) m_image.buffer1 + (y * m_image.bytes_per_line), pContent, height * m_image.bytes_per_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1550
|
||||||
|
Result TglD3DRMIMAGE::InitializePalette(int paletteSize, PaletteEntry* pEntries)
|
||||||
|
{
|
||||||
|
// This function is a 100% match if the PaletteEntry class is copied
|
||||||
|
// into into the TglD3DRMIMAGE class instead of being a global struct.
|
||||||
|
if (m_image.palette_size != paletteSize) {
|
||||||
|
if (m_image.palette != NULL) {
|
||||||
|
delete m_image.palette;
|
||||||
|
m_image.palette = NULL;
|
||||||
|
m_image.palette_size = 0;
|
||||||
|
}
|
||||||
|
if (paletteSize > 0) {
|
||||||
|
m_image.palette = new D3DRMPALETTEENTRY[paletteSize];
|
||||||
|
m_image.palette_size = paletteSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paletteSize > 0) {
|
||||||
|
for (int i = 0; i < paletteSize; i++) {
|
||||||
|
m_image.palette[i].red = pEntries[i].m_red;
|
||||||
|
m_image.palette[i].green = pEntries[i].m_green;
|
||||||
|
m_image.palette[i].blue = pEntries[i].m_blue;
|
||||||
|
m_image.palette[i].flags = D3DRMPALETTE_READONLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a2800
|
||||||
|
// TglImpl::TextureImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3c10
|
||||||
|
Result TextureImpl::SetTexels(int width, int height, int bitsPerTexel, void* pTexels)
|
||||||
|
{
|
||||||
|
TglD3DRMIMAGE* image = TextureGetImage(m_data);
|
||||||
|
Result result = image->CreateBuffer(width, height, bitsPerTexel, pTexels, TRUE);
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = ResultVal(m_data->Changed(TRUE, FALSE));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3c60
|
||||||
|
void TextureImpl::FillRowsOfTexture(int y, int height, void* pBuffer)
|
||||||
|
{
|
||||||
|
TglD3DRMIMAGE* image = TextureGetImage(m_data);
|
||||||
|
image->FillRowsOfTexture(y, height, (char*) pBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3c90
|
||||||
|
Result TextureImpl::Changed(int texelsChanged, int paletteChanged)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->Changed(texelsChanged, paletteChanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3d00
|
||||||
|
Result TextureImpl::GetBufferAndPalette(
|
||||||
|
int* width,
|
||||||
|
int* height,
|
||||||
|
int* depth,
|
||||||
|
void** pBuffer,
|
||||||
|
int* paletteSize,
|
||||||
|
PaletteEntry** pEntries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Something really doesn't match here, not sure what's up.
|
||||||
|
TglD3DRMIMAGE* image = TextureGetImage(m_data);
|
||||||
|
*width = image->m_image.width;
|
||||||
|
*height = image->m_image.height;
|
||||||
|
*depth = image->m_image.depth;
|
||||||
|
*pBuffer = image->m_image.buffer1;
|
||||||
|
*paletteSize = image->m_image.palette_size;
|
||||||
|
for (int i = 0; i < image->m_image.palette_size; i++) {
|
||||||
|
pEntries[i]->m_red = image->m_image.palette[i].red;
|
||||||
|
pEntries[i]->m_green = image->m_image.palette[i].green;
|
||||||
|
pEntries[i]->m_blue = image->m_image.palette[i].blue;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3d40
|
||||||
|
Result TextureImpl::SetPalette(int entryCount, PaletteEntry* pEntries)
|
||||||
|
{
|
||||||
|
// Not 100% confident this is supposed to directly be forwarding arguments,
|
||||||
|
// but it probably is given FillRowsOfTexture matches doing that.
|
||||||
|
TglD3DRMIMAGE* image = TextureGetImage(m_data);
|
||||||
|
image->InitializePalette(entryCount, pEntries);
|
||||||
|
m_data->Changed(FALSE, TRUE);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3d70
|
||||||
|
void* TextureImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
57
LEGO1/tgl/d3drm/unk.cpp
Normal file
57
LEGO1/tgl/d3drm/unk.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(Unk, 0x4);
|
||||||
|
DECOMP_SIZE_ASSERT(UnkImpl, 0x8);
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a2720
|
||||||
|
// TglImpl::UnkImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3830
|
||||||
|
void* UnkImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3840 STUB
|
||||||
|
Result UnkImpl::SetMeshData(
|
||||||
|
unsigned long faceCount,
|
||||||
|
unsigned long vertexCount,
|
||||||
|
const float (*pPositions)[3],
|
||||||
|
const float (*pNormals)[3],
|
||||||
|
const float (*pTextureCoordinates)[2],
|
||||||
|
unsigned long vertexPerFaceCount,
|
||||||
|
unsigned long* pFaceData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3ae0
|
||||||
|
Result UnkImpl::GetBoundingBox(float min[3], float max[3])
|
||||||
|
{
|
||||||
|
D3DRMBOX box;
|
||||||
|
Result result = ResultVal(m_data->GetBox(&box));
|
||||||
|
if (result == Success) {
|
||||||
|
min[0] = box.min.x;
|
||||||
|
min[1] = box.min.y;
|
||||||
|
min[2] = box.min.z;
|
||||||
|
max[0] = box.max.x;
|
||||||
|
max[1] = box.max.y;
|
||||||
|
max[2] = box.max.z;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3b40
|
||||||
|
Unk* UnkImpl::Clone()
|
||||||
|
{
|
||||||
|
UnkImpl* mesh = new UnkImpl();
|
||||||
|
int ret = m_data->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_data);
|
||||||
|
if (ret < 0) {
|
||||||
|
delete mesh;
|
||||||
|
mesh = NULL;
|
||||||
|
}
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
349
LEGO1/tgl/d3drm/view.cpp
Normal file
349
LEGO1/tgl/d3drm/view.cpp
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
#include "impl.h"
|
||||||
|
|
||||||
|
using namespace TglImpl;
|
||||||
|
|
||||||
|
struct ViewportAppData {
|
||||||
|
ViewportAppData(IDirect3DRM* pRenderer);
|
||||||
|
~ViewportAppData();
|
||||||
|
|
||||||
|
IDirect3DRMFrame* m_pLightFrame;
|
||||||
|
IDirect3DRMFrame* m_pCamera;
|
||||||
|
IDirect3DRMFrame* m_pLastRenderedFrame;
|
||||||
|
float m_backgroundColorRed;
|
||||||
|
float m_backgroundColorGreen;
|
||||||
|
float m_backgroundColorBlue;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(ViewportAppData, 0x18);
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a10b0
|
||||||
|
ViewportAppData::ViewportAppData(IDirect3DRM* pRenderer)
|
||||||
|
{
|
||||||
|
pRenderer->CreateFrame(NULL, &m_pLightFrame);
|
||||||
|
m_pCamera = NULL;
|
||||||
|
m_pLastRenderedFrame = NULL;
|
||||||
|
m_backgroundColorRed = 0.0f;
|
||||||
|
m_backgroundColorGreen = 0.0f;
|
||||||
|
m_backgroundColorBlue = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a10e0
|
||||||
|
ViewportAppData::~ViewportAppData()
|
||||||
|
{
|
||||||
|
IDirect3DRMFrameArray* pChildFrames;
|
||||||
|
IDirect3DRMFrame* pChildFrame = NULL;
|
||||||
|
m_pLightFrame->GetChildren(&pChildFrames);
|
||||||
|
for (int i = 0; i < (int) pChildFrames->GetSize(); i++) {
|
||||||
|
pChildFrames->GetElement(i, &pChildFrame);
|
||||||
|
m_pLightFrame->DeleteChild(pChildFrame);
|
||||||
|
pChildFrame->Release(); // GetElement() does AddRef()
|
||||||
|
}
|
||||||
|
pChildFrames->Release();
|
||||||
|
m_pLightFrame->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward declare to satisfy order check
|
||||||
|
void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg);
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1160
|
||||||
|
Result ViewImpl::ViewportCreateAppData(IDirect3DRM* pDevice, IDirect3DRMViewport* pView, IDirect3DRMFrame* pCamera)
|
||||||
|
{
|
||||||
|
ViewportAppData* data = new ViewportAppData(pDevice);
|
||||||
|
data->m_pCamera = pCamera;
|
||||||
|
Result result = ResultVal(pView->SetAppData(reinterpret_cast<unsigned long>(data)));
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = ResultVal(pView->AddDestroyCallback(ViewportDestroyCallback, data));
|
||||||
|
}
|
||||||
|
if (!Succeeded(result)) {
|
||||||
|
delete data;
|
||||||
|
pView->SetAppData(0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result ViewRestoreFrameAfterRender(
|
||||||
|
IDirect3DRMFrame* pFrame,
|
||||||
|
IDirect3DRMFrame* pCamera,
|
||||||
|
IDirect3DRMFrame* pLightFrame
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Result result = Success;
|
||||||
|
if (pFrame) {
|
||||||
|
// remove camera and light frame from frame that was rendered
|
||||||
|
// this doesn't destroy the camera as it is still the camera of the viewport...
|
||||||
|
result = ResultVal(pFrame->DeleteChild(pCamera));
|
||||||
|
result = ResultVal(pFrame->DeleteChild(pLightFrame));
|
||||||
|
|
||||||
|
// decrease frame's ref count (it was increased in ViewPrepareFrameForRender())
|
||||||
|
pFrame->Release();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1240
|
||||||
|
void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg)
|
||||||
|
{
|
||||||
|
ViewportAppData* pViewportAppData = reinterpret_cast<ViewportAppData*>(pArg);
|
||||||
|
|
||||||
|
ViewRestoreFrameAfterRender(
|
||||||
|
pViewportAppData->m_pLastRenderedFrame,
|
||||||
|
pViewportAppData->m_pCamera,
|
||||||
|
pViewportAppData->m_pLightFrame
|
||||||
|
);
|
||||||
|
|
||||||
|
delete pViewportAppData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a1290
|
||||||
|
Result ViewportPickImpl(
|
||||||
|
IDirect3DRMViewport* pViewport,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
const Group** ppGroupsToPickFrom,
|
||||||
|
int groupsToPickFromCount,
|
||||||
|
const Group**& rppPickedGroups,
|
||||||
|
int& rPickedGroupCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Left unimplemented in shipped game.
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ViewportAppData* ViewportGetData(IDirect3DRMViewport* pViewport)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ViewportAppData*>(pViewport->GetAppData());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline IDirect3DRMFrame* ViewportGetLightFrame(IDirect3DRMViewport* pViewport)
|
||||||
|
{
|
||||||
|
return ViewportGetData(pViewport)->m_pLightFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100a23a0
|
||||||
|
// TglImpl::ViewImpl::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2d80
|
||||||
|
void* ViewImpl::ImplementationDataPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(&m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2d90
|
||||||
|
Result ViewImpl::Add(const Light* pLight)
|
||||||
|
{
|
||||||
|
const LightImpl* light = static_cast<const LightImpl*>(pLight);
|
||||||
|
IDirect3DRMFrame* frame = light->ImplementationData();
|
||||||
|
return ResultVal(ViewportGetLightFrame(m_data)->AddChild(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2dc0
|
||||||
|
Result ViewImpl::Remove(const Light* pLight)
|
||||||
|
{
|
||||||
|
const LightImpl* light = static_cast<const LightImpl*>(pLight);
|
||||||
|
IDirect3DRMFrame* frame = light->ImplementationData();
|
||||||
|
return ResultVal(ViewportGetLightFrame(m_data)->DeleteChild(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2df0
|
||||||
|
Result ViewImpl::SetCamera(const Camera* pCamera)
|
||||||
|
{
|
||||||
|
const CameraImpl* camera = static_cast<const CameraImpl*>(pCamera);
|
||||||
|
IDirect3DRMFrame* frame = camera->ImplementationData();
|
||||||
|
|
||||||
|
ViewportAppData* pViewportAppData;
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
pViewportAppData = reinterpret_cast<ViewportAppData*>(m_data->GetAppData());
|
||||||
|
result = ViewRestoreFrameAfterRender(
|
||||||
|
pViewportAppData->m_pLastRenderedFrame,
|
||||||
|
pViewportAppData->m_pCamera,
|
||||||
|
pViewportAppData->m_pLightFrame
|
||||||
|
);
|
||||||
|
pViewportAppData->m_pCamera = frame;
|
||||||
|
pViewportAppData->m_pLastRenderedFrame = 0;
|
||||||
|
|
||||||
|
return ResultVal(m_data->SetCamera(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2e70
|
||||||
|
Result ViewImpl::SetProjection(ProjectionType type)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->SetProjection(Translate(type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2eb0
|
||||||
|
Result ViewImpl::SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees)
|
||||||
|
{
|
||||||
|
float field = frontClippingDistance * tan(DegreesToRadians(degrees / 2));
|
||||||
|
Result result;
|
||||||
|
result = ResultVal(m_data->SetFront(frontClippingDistance));
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = ResultVal(m_data->SetBack(backClippingDistance));
|
||||||
|
}
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
result = ResultVal(m_data->SetField(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2f30
|
||||||
|
Result ViewImpl::SetBackgroundColor(float r, float g, float b)
|
||||||
|
{
|
||||||
|
Result ret = Success;
|
||||||
|
// Note, this method in the shipped game is very diverged from
|
||||||
|
// the Tgl leak code.
|
||||||
|
ViewportAppData* data = ViewportGetData(m_data);
|
||||||
|
data->m_backgroundColorRed = r;
|
||||||
|
data->m_backgroundColorGreen = g;
|
||||||
|
data->m_backgroundColorBlue = b;
|
||||||
|
if (data->m_pLastRenderedFrame) {
|
||||||
|
ret = ResultVal(data->m_pLastRenderedFrame->SetSceneBackgroundRGB(r, g, b));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2f80
|
||||||
|
Result ViewImpl::GetBackgroundColor(float* r, float* g, float* b)
|
||||||
|
{
|
||||||
|
ViewportAppData* data = ViewportGetData(m_data);
|
||||||
|
*r = data->m_backgroundColorRed;
|
||||||
|
*g = data->m_backgroundColorGreen;
|
||||||
|
*b = data->m_backgroundColorBlue;
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2fb0
|
||||||
|
Result ViewImpl::Clear()
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->Clear());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Result ViewPrepareFrameForRender(
|
||||||
|
IDirect3DRMFrame* pFrame,
|
||||||
|
IDirect3DRMFrame* pCamera,
|
||||||
|
IDirect3DRMFrame* pLightFrame,
|
||||||
|
float backgroundRed,
|
||||||
|
float backgroundGreen,
|
||||||
|
float backgroundBlue
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Result result = Success;
|
||||||
|
|
||||||
|
if (pFrame) {
|
||||||
|
// set background color
|
||||||
|
result = ResultVal(pFrame->SetSceneBackgroundRGB(backgroundRed, backgroundGreen, backgroundBlue));
|
||||||
|
|
||||||
|
// add camera to frame to be rendered
|
||||||
|
result = ResultVal(pFrame->AddChild(pCamera));
|
||||||
|
|
||||||
|
// add light frame to frame to be rendered
|
||||||
|
result = ResultVal(pFrame->AddChild(pLightFrame));
|
||||||
|
|
||||||
|
// increase ref count of frame to ensure it does not get deleted underneath us
|
||||||
|
pFrame->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a2fd0
|
||||||
|
Result ViewImpl::Render(const Light* pCamera)
|
||||||
|
{
|
||||||
|
ViewportAppData* appdata = ViewportGetData(m_data);
|
||||||
|
|
||||||
|
IDirect3DRMFrame* light = static_cast<const LightImpl*>(pCamera)->ImplementationData();
|
||||||
|
|
||||||
|
IDirect3DRMFrame* lastRendered = appdata->m_pLastRenderedFrame;
|
||||||
|
if (light != lastRendered) {
|
||||||
|
if (lastRendered) {
|
||||||
|
lastRendered->DeleteChild(appdata->m_pCamera);
|
||||||
|
// Some other call goes here, not sure what.
|
||||||
|
lastRendered->Release();
|
||||||
|
}
|
||||||
|
appdata->m_pLastRenderedFrame = light;
|
||||||
|
if (light) {
|
||||||
|
light->SetSceneBackgroundRGB(
|
||||||
|
appdata->m_backgroundColorRed,
|
||||||
|
appdata->m_backgroundColorGreen,
|
||||||
|
appdata->m_backgroundColorBlue
|
||||||
|
);
|
||||||
|
light->AddChild(appdata->m_pCamera);
|
||||||
|
// Some other call goes here, not sure what.
|
||||||
|
light->AddRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResultVal(m_data->Render(light));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3080
|
||||||
|
Result ViewImpl::ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height)
|
||||||
|
{
|
||||||
|
return ResultVal(m_data->ForceUpdate(x, y, x + width - 1, y + height - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a30c0
|
||||||
|
Result ViewImpl::Pick(
|
||||||
|
unsigned long x,
|
||||||
|
unsigned long y,
|
||||||
|
const Group** ppGroupsToPickFrom,
|
||||||
|
int groupsToPickFromCount,
|
||||||
|
const Group**& rppPickedGroups,
|
||||||
|
int& rPickedGroupCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ViewportPickImpl(
|
||||||
|
m_data,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
ppGroupsToPickFrom,
|
||||||
|
groupsToPickFromCount,
|
||||||
|
rppPickedGroups,
|
||||||
|
rPickedGroupCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a30f0
|
||||||
|
Result ViewImpl::TransformWorldToScreen(const float world[3], float screen[4])
|
||||||
|
{
|
||||||
|
D3DRMVECTOR4D d3dRMScreen;
|
||||||
|
D3DVECTOR d3dRMWorld;
|
||||||
|
d3dRMWorld.x = world[0];
|
||||||
|
d3dRMWorld.y = world[1];
|
||||||
|
d3dRMWorld.z = world[2];
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
result = ResultVal(m_data->Transform(&d3dRMScreen, &d3dRMWorld));
|
||||||
|
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
screen[0] = d3dRMScreen.x;
|
||||||
|
screen[1] = d3dRMScreen.y;
|
||||||
|
screen[2] = d3dRMScreen.z;
|
||||||
|
screen[3] = d3dRMScreen.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100a3160
|
||||||
|
Result ViewImpl::TransformScreenToWorld(const float screen[4], float world[3])
|
||||||
|
{
|
||||||
|
// 100% match minus instruction reordering.
|
||||||
|
D3DVECTOR d3dRMWorld;
|
||||||
|
D3DRMVECTOR4D d3dScreen;
|
||||||
|
d3dScreen.x = screen[0];
|
||||||
|
d3dScreen.y = screen[1];
|
||||||
|
d3dScreen.z = screen[2];
|
||||||
|
d3dScreen.w = screen[3];
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
result = ResultVal(m_data->InverseTransform(&d3dRMWorld, &d3dScreen));
|
||||||
|
|
||||||
|
if (Succeeded(result)) {
|
||||||
|
world[0] = d3dRMWorld.x;
|
||||||
|
world[1] = d3dRMWorld.y;
|
||||||
|
world[2] = d3dRMWorld.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
303
LEGO1/tgl/tgl.h
303
LEGO1/tgl/tgl.h
@ -1,27 +1,22 @@
|
|||||||
#ifndef TGL_H
|
|
||||||
#define TGL_H
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifndef _tgl_h
|
||||||
|
#define _tgl_h
|
||||||
|
|
||||||
|
#include "tglvector.h"
|
||||||
|
|
||||||
#define NOMINMAX // to avoid conflict with STL
|
|
||||||
#include <d3d.h>
|
#include <d3d.h>
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
#include <windows.h> // HWND
|
#include <windows.h>
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
#include "tglVector.h"
|
|
||||||
|
|
||||||
namespace Tgl
|
namespace Tgl
|
||||||
{
|
{
|
||||||
|
|
||||||
// ???
|
|
||||||
enum ColorModel {
|
enum ColorModel {
|
||||||
|
// Note: Not used in shipped game, no way to verify contents.
|
||||||
Ramp,
|
Ramp,
|
||||||
RGB
|
RGB
|
||||||
};
|
};
|
||||||
|
|
||||||
// ???
|
|
||||||
enum ShadingModel {
|
enum ShadingModel {
|
||||||
Wireframe,
|
Wireframe,
|
||||||
UnlitFlat,
|
UnlitFlat,
|
||||||
@ -30,7 +25,6 @@ enum ShadingModel {
|
|||||||
Phong
|
Phong
|
||||||
};
|
};
|
||||||
|
|
||||||
// ?????
|
|
||||||
enum LightType {
|
enum LightType {
|
||||||
Ambient,
|
Ambient,
|
||||||
Point,
|
Point,
|
||||||
@ -39,7 +33,6 @@ enum LightType {
|
|||||||
ParallelPoint
|
ParallelPoint
|
||||||
};
|
};
|
||||||
|
|
||||||
// ???
|
|
||||||
enum ProjectionType {
|
enum ProjectionType {
|
||||||
Perspective,
|
Perspective,
|
||||||
Orthographic
|
Orthographic
|
||||||
@ -50,39 +43,39 @@ enum TextureMappingMode {
|
|||||||
PerspectiveCorrect
|
PerspectiveCorrect
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Not in the Tgl leak, inferred from the assembly
|
||||||
|
enum MaterialMode {
|
||||||
|
FromParent,
|
||||||
|
FromFrame,
|
||||||
|
FromMesh,
|
||||||
|
};
|
||||||
|
|
||||||
struct PaletteEntry {
|
struct PaletteEntry {
|
||||||
unsigned char m_red;
|
unsigned char m_red;
|
||||||
unsigned char m_green;
|
unsigned char m_green;
|
||||||
unsigned char m_blue;
|
unsigned char m_blue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
struct DeviceDirectDrawCreateData {
|
|
||||||
const GUID* m_driverGUID;
|
|
||||||
HWND m_hWnd; // ??? derive from m_pDirectDraw
|
|
||||||
IDirectDraw* m_pDirectDraw;
|
|
||||||
IDirectDrawSurface* m_pFrontBuffer; // ??? derive from m_pDirectDraw
|
|
||||||
IDirectDrawSurface* m_pBackBuffer;
|
|
||||||
IDirectDrawPalette* m_pPalette; // ??? derive from m_pDirectDraw
|
|
||||||
int m_isFullScreen; // ??? derive from m_pDirectDraw
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DeviceDirect3DCreateData {
|
struct DeviceDirect3DCreateData {
|
||||||
IDirect3D* m_pDirect3D;
|
IDirect3D* m_pDirect3D;
|
||||||
IDirect3DDevice* m_pDirect3DDevice;
|
IDirect3DDevice* m_pDirect3DDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
struct DeviceDirectDrawCreateData {
|
||||||
|
const GUID* m_driverGUID;
|
||||||
|
HWND m_hWnd;
|
||||||
|
IDirectDraw* m_pDirectDraw;
|
||||||
|
IDirectDrawSurface* m_pFrontBuffer;
|
||||||
|
IDirectDrawSurface* m_pBackBuffer;
|
||||||
|
|
||||||
struct DeviceDirectDrawCreateData {};
|
// These have possibly been removed in the shipped game
|
||||||
|
// (Put them back if we can verify when we find a callsite
|
||||||
#endif
|
// which constructs this type)
|
||||||
|
// IDirectDrawPalette* m_pPalette;
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// int m_isFullScreen;
|
||||||
//
|
};
|
||||||
// Result (return value type)
|
|
||||||
|
|
||||||
|
// Result type used for all methods in the Tgl API
|
||||||
enum Result {
|
enum Result {
|
||||||
Error = 0,
|
Error = 0,
|
||||||
Success = 1
|
Success = 1
|
||||||
@ -93,10 +86,7 @@ inline int Succeeded(Result result)
|
|||||||
return (result == Success);
|
return (result == Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class Object;
|
class Object;
|
||||||
class Device;
|
class Device;
|
||||||
@ -106,30 +96,24 @@ class Camera;
|
|||||||
class Group;
|
class Group;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
class Unk;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100db980
|
||||||
//
|
|
||||||
// Object
|
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
virtual ~Object() {}
|
virtual ~Object() {}
|
||||||
|
|
||||||
// returns pointer to implementation data
|
|
||||||
virtual void* ImplementationDataPtr() = 0;
|
virtual void* ImplementationDataPtr() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100db948
|
||||||
//
|
|
||||||
// Renderer
|
|
||||||
|
|
||||||
// ??? for now until we figured out how an app should pass the Renderer around
|
|
||||||
Renderer* CreateRenderer();
|
|
||||||
|
|
||||||
class Renderer : public Object {
|
class Renderer : public Object {
|
||||||
public:
|
public:
|
||||||
virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0;
|
// vtable+0x08
|
||||||
virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0;
|
virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0;
|
||||||
|
virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0;
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
virtual View* CreateView(
|
virtual View* CreateView(
|
||||||
const Device*,
|
const Device*,
|
||||||
const Camera*,
|
const Camera*,
|
||||||
@ -139,34 +123,12 @@ class Renderer : public Object {
|
|||||||
unsigned long height
|
unsigned long height
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual Camera* CreateCamera() = 0;
|
virtual Camera* CreateCamera() = 0;
|
||||||
virtual Light* CreateLight(LightType, double r, double g, double b) = 0;
|
virtual Light* CreateLight(LightType, float r, float g, float b) = 0;
|
||||||
virtual Group* CreateGroup(const Group* pParent = 0) = 0;
|
virtual Group* CreateGroup(const Group* pParent = 0) = 0;
|
||||||
|
|
||||||
// pTextureCoordinates is pointer to array of vertexCount elements
|
// vtable+0x20
|
||||||
// (each element being two floats), or NULL
|
virtual Unk* CreateUnk() = 0;
|
||||||
// pFaceData is faceCount tuples, each of format
|
virtual Texture* CreateTexture() = 0;
|
||||||
// [vertex1index, ... vertexNindex], where N = vertexPerFaceCount
|
|
||||||
virtual Mesh* CreateMesh(
|
|
||||||
unsigned long vertexCount,
|
|
||||||
const float (*pVertices)[3],
|
|
||||||
const float (*pTextureCoordinates)[2],
|
|
||||||
unsigned long faceCount,
|
|
||||||
unsigned long vertexPerFaceCount,
|
|
||||||
unsigned long* pFaceData
|
|
||||||
) = 0;
|
|
||||||
// pTextureCoordinates is pointer to array of vertexCount elements
|
|
||||||
// (each element being two floats), or NULL
|
|
||||||
// pFaceData is:
|
|
||||||
// [face1VertexCount face1Vertex1index, ... face1VertexMindex
|
|
||||||
// face2VertexCount face2Vertex1index, ... face2VertexNindex
|
|
||||||
// ...
|
|
||||||
// 0]
|
|
||||||
virtual Mesh* CreateMesh(
|
|
||||||
unsigned long vertexCount,
|
|
||||||
const float (*pVertices)[3],
|
|
||||||
const float (*pTextureCoordinates)[2],
|
|
||||||
unsigned long* pFaceData
|
|
||||||
) = 0;
|
|
||||||
virtual Texture* CreateTexture(
|
virtual Texture* CreateTexture(
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
@ -176,61 +138,54 @@ class Renderer : public Object {
|
|||||||
int paletteEntryCount,
|
int paletteEntryCount,
|
||||||
const PaletteEntry* pEntries
|
const PaletteEntry* pEntries
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual Texture* CreateTexture() = 0;
|
|
||||||
|
|
||||||
virtual Result SetTextureDefaultShadeCount(unsigned long) = 0;
|
virtual Result SetTextureDefaultShadeCount(unsigned long) = 0;
|
||||||
|
|
||||||
|
// vtable+0x30
|
||||||
virtual Result SetTextureDefaultColorCount(unsigned long) = 0;
|
virtual Result SetTextureDefaultColorCount(unsigned long) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
Renderer* CreateRenderer();
|
||||||
//
|
|
||||||
// Device
|
|
||||||
|
|
||||||
|
// VTABLE 0x100db9b8
|
||||||
class Device : public Object {
|
class Device : public Object {
|
||||||
public:
|
public:
|
||||||
|
// vtable+0x08
|
||||||
virtual unsigned long GetWidth() = 0;
|
virtual unsigned long GetWidth() = 0;
|
||||||
virtual unsigned long GetHeight() = 0;
|
virtual unsigned long GetHeight() = 0;
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
virtual Result SetColorModel(ColorModel) = 0;
|
virtual Result SetColorModel(ColorModel) = 0;
|
||||||
virtual Result SetShadingModel(ShadingModel) = 0;
|
virtual Result SetShadingModel(ShadingModel) = 0;
|
||||||
virtual Result SetShadeCount(unsigned long) = 0;
|
virtual Result SetShadeCount(unsigned long) = 0;
|
||||||
virtual Result SetDither(int) = 0;
|
virtual Result SetDither(int) = 0;
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
virtual Result Update() = 0;
|
virtual Result Update() = 0;
|
||||||
|
virtual void InitFromD3DDevice(Device*) = 0;
|
||||||
// ??? should this be handled by app ???
|
virtual void InitFromWindowsDevice(Device*) = 0;
|
||||||
// ??? this needs to be called when the window on which the device is ...
|
|
||||||
// is being activated
|
|
||||||
virtual void HandleActivate(int bActivate) = 0;
|
|
||||||
|
|
||||||
// ??? this needs to be called when the window on which this device is based
|
|
||||||
// needs to be repainted
|
|
||||||
virtual void HandlePaint(void*) = 0;
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
virtual unsigned long GetDrawnTriangleCount() = 0;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100dba28
|
||||||
//
|
|
||||||
// View
|
|
||||||
|
|
||||||
class View : public Object {
|
class View : public Object {
|
||||||
public:
|
public:
|
||||||
virtual Result Add(const Light*) = 0;
|
virtual Result Add(const Light*) = 0;
|
||||||
virtual Result Remove(const Light*) = 0;
|
virtual Result Remove(const Light*) = 0;
|
||||||
|
|
||||||
|
// vtable+0x10
|
||||||
virtual Result SetCamera(const Camera*) = 0;
|
virtual Result SetCamera(const Camera*) = 0;
|
||||||
virtual Result SetProjection(ProjectionType) = 0;
|
virtual Result SetProjection(ProjectionType) = 0;
|
||||||
virtual Result SetFrustrum(double frontClippingDistance, double backClippingDistance, double degrees) = 0;
|
virtual Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) = 0;
|
||||||
virtual Result SetBackgroundColor(double r, double g, double b) = 0;
|
virtual Result SetBackgroundColor(float r, float g, float b) = 0;
|
||||||
|
|
||||||
|
// vtable+0x20
|
||||||
|
virtual Result GetBackgroundColor(float* r, float* g, float* b) = 0;
|
||||||
virtual Result Clear() = 0;
|
virtual Result Clear() = 0;
|
||||||
virtual Result Render(const Group*) = 0;
|
virtual Result Render(const Light*) = 0;
|
||||||
// ??? needed for fine grain control when using DirectDraw/D3D ???
|
|
||||||
virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) = 0;
|
virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) = 0;
|
||||||
|
|
||||||
// ??? for now: used by Mesh Cost calculation
|
// vtable+0x30
|
||||||
virtual Result TransformWorldToScreen(const double world[3], double screen[4]) = 0;
|
virtual Result TransformWorldToScreen(const float world[3], float screen[4]) = 0;
|
||||||
|
virtual Result TransformScreenToWorld(const float screen[4], float world[3]) = 0;
|
||||||
|
|
||||||
// Pick():
|
// Pick():
|
||||||
// x, y:
|
// x, y:
|
||||||
@ -264,102 +219,94 @@ class View : public Object {
|
|||||||
) = 0;
|
) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100dbae8
|
||||||
//
|
|
||||||
// Camera
|
|
||||||
|
|
||||||
class Camera : public Object {
|
class Camera : public Object {
|
||||||
public:
|
public:
|
||||||
#if 0
|
|
||||||
virtual Result SetPosition(const double[3]) = 0;
|
|
||||||
virtual Result SetOrientation(const double direction[3],
|
|
||||||
const double up[3]) = 0;
|
|
||||||
#endif
|
|
||||||
virtual Result SetTransformation(const FloatMatrix4&) = 0;
|
virtual Result SetTransformation(const FloatMatrix4&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100dbb08
|
||||||
//
|
|
||||||
// Light
|
|
||||||
|
|
||||||
class Light : public Object {
|
class Light : public Object {
|
||||||
public:
|
public:
|
||||||
#if 0
|
|
||||||
virtual Result SetPosition(const double[3]) = 0;
|
|
||||||
virtual Result SetOrientation(const double direction[3],
|
|
||||||
const double up[3]) = 0;
|
|
||||||
#endif
|
|
||||||
virtual Result SetTransformation(const FloatMatrix4&) = 0;
|
virtual Result SetTransformation(const FloatMatrix4&) = 0;
|
||||||
|
virtual Result SetColor(float r, float g, float b) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100dbbb0
|
||||||
//
|
|
||||||
// Group
|
|
||||||
|
|
||||||
class Group : public Object {
|
|
||||||
public:
|
|
||||||
#if 0
|
|
||||||
virtual Result SetPosition(const double[3]) = 0;
|
|
||||||
virtual Result SetOrientation(const double direction[3],
|
|
||||||
const double up[3]) = 0;
|
|
||||||
#endif
|
|
||||||
// TODO: The type was changed from `FloatMatrix` to `Matrix` to make code in UpdateWorldData match.
|
|
||||||
// However, this is unlikely to be correct and will have to be figured out at some point.
|
|
||||||
virtual Result SetTransformation(const Matrix4&) = 0;
|
|
||||||
|
|
||||||
// ??? not yet fully implemented
|
|
||||||
virtual Result SetColor(double r, double g, double b) = 0;
|
|
||||||
virtual Result SetTexture(const Texture*) = 0;
|
|
||||||
|
|
||||||
virtual Result Add(const Group*) = 0;
|
|
||||||
virtual Result Add(const Mesh*) = 0;
|
|
||||||
|
|
||||||
virtual Result Remove(const Group*) = 0;
|
|
||||||
virtual Result Remove(const Mesh*) = 0;
|
|
||||||
|
|
||||||
virtual Result RemoveAll() = 0;
|
|
||||||
|
|
||||||
// ??? for now: used by Mesh Cost calculation
|
|
||||||
virtual Result TransformLocalToWorld(const double local[3], double world[3]) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Mesh
|
|
||||||
|
|
||||||
class Mesh : public Object {
|
class Mesh : public Object {
|
||||||
public:
|
public:
|
||||||
// ??? also on Group
|
virtual Result SetColor(float r, float g, float b, float a) = 0;
|
||||||
virtual Result SetColor(double r, double g, double b) = 0;
|
|
||||||
virtual Result SetTexture(const Texture*) = 0;
|
virtual Result SetTexture(const Texture*) = 0;
|
||||||
virtual Result SetTextureMappingMode(TextureMappingMode) = 0;
|
virtual Result GetTexture(Texture*&) = 0;
|
||||||
|
|
||||||
|
virtual Result SetTextureMappingMode(ProjectionType) = 0;
|
||||||
virtual Result SetShadingModel(ShadingModel) = 0;
|
virtual Result SetShadingModel(ShadingModel) = 0;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
// Clone data in underlying group
|
||||||
virtual Result GetBoundingBox(float min[3], float max[3]) = 0;
|
virtual Mesh* DeepClone(Unk*) = 0;
|
||||||
virtual unsigned long GetFaceCount() = 0;
|
|
||||||
virtual unsigned long GetVertexCount() = 0;
|
// Just get another Group pointing to the same underlying data
|
||||||
#endif
|
virtual Mesh* ShallowClone(Unk*) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// VTABLE 0x100dbaa0
|
||||||
//
|
class Group : public Object {
|
||||||
// Texture
|
public:
|
||||||
|
virtual Result SetTransformation(const FloatMatrix4&) = 0;
|
||||||
|
virtual Result SetColor(float r, float g, float b, float a) = 0;
|
||||||
|
virtual Result SetTexture(const Texture*) = 0;
|
||||||
|
virtual Result GetTexture(Texture*&) = 0;
|
||||||
|
virtual Result SetMaterialMode(MaterialMode) = 0;
|
||||||
|
virtual Result Add(const Group*) = 0;
|
||||||
|
virtual Result Add(const Mesh*) = 0;
|
||||||
|
virtual Result Remove(const Group*) = 0;
|
||||||
|
virtual Result Remove(const Mesh*) = 0;
|
||||||
|
virtual Result RemoveAll() = 0;
|
||||||
|
|
||||||
|
// This is TransformLocalToWorld in the leak, however it seems
|
||||||
|
// to have been replaced by something else in the shipped code.
|
||||||
|
virtual Result Unknown() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't know what this is. Seems like another Tgl object which
|
||||||
|
// was not in the leaked Tgl code. My suspicion is that it's
|
||||||
|
// some kind of builder class for creating meshes.
|
||||||
|
// VTABLE 0x100dbb30
|
||||||
|
class Unk : public Object {
|
||||||
|
public:
|
||||||
|
virtual Result SetMeshData(
|
||||||
|
unsigned long faceCount,
|
||||||
|
unsigned long vertexCount,
|
||||||
|
const float (*pPositions)[3],
|
||||||
|
const float (*pNormals)[3],
|
||||||
|
const float (*pTextureCoordinates)[2],
|
||||||
|
unsigned long vertexPerFaceCount,
|
||||||
|
unsigned long* pFaceData
|
||||||
|
) = 0;
|
||||||
|
virtual Result GetBoundingBox(float min[3], float max[3]) = 0;
|
||||||
|
virtual Unk* Clone() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTABLE 0x100dbb68
|
||||||
class Texture : public Object {
|
class Texture : public Object {
|
||||||
public:
|
public:
|
||||||
virtual Result SetTexels(
|
// vtable+0x08
|
||||||
int width,
|
virtual Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels) = 0;
|
||||||
int height,
|
virtual void FillRowsOfTexture(int y, int height, void* pBuffer) = 0;
|
||||||
int bitsPerTexel,
|
|
||||||
const void* pTexels,
|
|
||||||
int pTexelsArePersistent
|
|
||||||
) = 0;
|
|
||||||
virtual Result SetPalette(int entryCount, const PaletteEntry* pEntries) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
// vtable+0x10
|
||||||
|
virtual Result Changed(int texelsChanged, int paletteChanged) = 0;
|
||||||
|
virtual Result GetBufferAndPalette(
|
||||||
|
int* pWidth,
|
||||||
|
int* pHeight,
|
||||||
|
int* pDepth,
|
||||||
|
void** ppBuffer,
|
||||||
|
int* pPaletteSize,
|
||||||
|
PaletteEntry** ppPalette
|
||||||
|
) = 0;
|
||||||
|
virtual Result SetPalette(int entryCount, PaletteEntry* pEntries) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Tgl
|
} // namespace Tgl
|
||||||
|
|
||||||
#endif // TGL_H
|
#endif /* _tgl_h */
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
#ifndef TGLVECTOR_H
|
#ifndef _tglVector_h
|
||||||
#define TGLVECTOR_H
|
#define _tglVector_h
|
||||||
|
// Note: This file is almost an exact copy of the one from
|
||||||
|
// the leak but using floats instead of doubles, hence the
|
||||||
|
// strange formatting in some places.
|
||||||
|
|
||||||
#include "math.h" // ??? sin() in RotateAroundY()
|
#include "math.h" // sin() in RotateAroundY()
|
||||||
|
|
||||||
#include <stddef.h> // offsetof()
|
#include <stddef.h> // offsetof()
|
||||||
|
|
||||||
@ -142,7 +145,6 @@ class RotationY : public FloatMatrix4 {
|
|||||||
public:
|
public:
|
||||||
RotationY(float radians);
|
RotationY(float radians);
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Transformation matrices implementation
|
// Transformation matrices implementation
|
||||||
@ -274,4 +276,4 @@ inline RotationY::RotationY(float radians)
|
|||||||
|
|
||||||
} // namespace Tgl
|
} // namespace Tgl
|
||||||
|
|
||||||
#endif // TLGVECTOR_H
|
#endif /* _tglVector_h */
|
||||||
|
|||||||
@ -27,8 +27,7 @@ void ViewROI::UpdateWorldData(const Matrix4Data& parent2world)
|
|||||||
{
|
{
|
||||||
OrientableROI::UpdateWorldData(parent2world);
|
OrientableROI::UpdateWorldData(parent2world);
|
||||||
if (geometry) {
|
if (geometry) {
|
||||||
// Tgl::FloatMatrix4 tgl_mat;
|
Tgl::FloatMatrix4 mat;
|
||||||
Matrix4 mat;
|
|
||||||
SETMAT4(mat, m_local2world.GetMatrix());
|
SETMAT4(mat, m_local2world.GetMatrix());
|
||||||
Tgl::Result result = geometry->SetTransformation(mat);
|
Tgl::Result result = geometry->SetTransformation(mat);
|
||||||
// assert(Tgl::Succeeded(result));
|
// assert(Tgl::Succeeded(result));
|
||||||
|
|||||||
@ -49,7 +49,7 @@ def check_file(filename: str, verbose: bool = False) -> bool:
|
|||||||
f"{fun.end_line - fun.line_number:4} lines",
|
f"{fun.end_line - fun.line_number:4} lines",
|
||||||
f"{order_lookup[fun.offset]:3}",
|
f"{order_lookup[fun.offset]:3}",
|
||||||
" ",
|
" ",
|
||||||
sig_truncate(fun.signature),
|
sig_truncate(fun.name),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
print(msg)
|
print(msg)
|
||||||
|
|||||||
67
tools/patch_c2.py
Normal file
67
tools/patch_c2.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import pathlib
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
ORIGINAL_C2_MD5 = "dcd69f1dd28b02dd03dd7ed02984299a" # original C2.EXE
|
||||||
|
|
||||||
|
C2_MD5 = (
|
||||||
|
ORIGINAL_C2_MD5,
|
||||||
|
"e70acde41802ddec06c4263bb357ac30", # patched C2.EXE
|
||||||
|
)
|
||||||
|
|
||||||
|
C2_SIZE = 549888
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
allow_abbrev=False,
|
||||||
|
description="Path to C2.EXE of Microsoft Visual Studio 4.2.0 to disable C4786 warning",
|
||||||
|
)
|
||||||
|
parser.add_argument("path", type=pathlib.Path, help="Path of C2.EXE")
|
||||||
|
parser.add_argument(
|
||||||
|
"-f", dest="force", default=False, action="store_true", help="force"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not args.path.is_file():
|
||||||
|
parser.error("Input is not a file")
|
||||||
|
|
||||||
|
binary = bytearray(args.path.open("rb").read())
|
||||||
|
md5 = hashlib.md5(binary).hexdigest()
|
||||||
|
print(md5, C2_MD5)
|
||||||
|
|
||||||
|
msg_cb = parser.error if not args.force else print
|
||||||
|
if len(binary) != C2_SIZE:
|
||||||
|
msg_cb("file size is not correct")
|
||||||
|
if md5 not in C2_MD5:
|
||||||
|
msg_cb("md5 checksum does not match")
|
||||||
|
|
||||||
|
if md5 == ORIGINAL_C2_MD5:
|
||||||
|
backup = f"{args.path}.BAK"
|
||||||
|
print(f'Creating backup "{backup}"')
|
||||||
|
shutil.copyfile(args.path, backup)
|
||||||
|
|
||||||
|
def nop_patch(start, count, expected=None):
|
||||||
|
replacement = [0x90] * count
|
||||||
|
if expected:
|
||||||
|
current = list(binary[start : start + count])
|
||||||
|
assert len(expected) == count
|
||||||
|
assert current in (expected, replacement)
|
||||||
|
print(f"Nopping {count} bytes at 0x{start:08x}")
|
||||||
|
binary[start : start + count] = replacement
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Disable C4786 warning: '%Fs' : identifier was truncated to '%d' characters in the debug information"
|
||||||
|
)
|
||||||
|
nop_patch(0x52F07, 5, [0xE8, 0x4F, 0xB3, 0xFE, 0xFF]) # 0x00453b07
|
||||||
|
nop_patch(0x74832, 5, [0xE8, 0x24, 0x9A, 0xFC, 0xFF]) # 0x00475432
|
||||||
|
|
||||||
|
args.path.open("wb").write(binary)
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@ -23,6 +23,7 @@
|
|||||||
import colorama
|
import colorama
|
||||||
from pystache import Renderer
|
from pystache import Renderer
|
||||||
|
|
||||||
|
|
||||||
REGISTER_LIST = set(
|
REGISTER_LIST = set(
|
||||||
[
|
[
|
||||||
"ax",
|
"ax",
|
||||||
@ -200,7 +201,8 @@ def gen_svg(svg_file, name_svg, icon, svg_implemented_funcs, total_funcs, raw_ac
|
|||||||
|
|
||||||
|
|
||||||
# Do the actual work
|
# Do the actual work
|
||||||
if __name__ == "__main__":
|
def main():
|
||||||
|
# pylint: disable=too-many-locals, too-many-nested-blocks, too-many-branches, too-many-statements
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
allow_abbrev=False,
|
allow_abbrev=False,
|
||||||
description="Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.",
|
description="Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.",
|
||||||
@ -483,3 +485,7 @@ def gen_svg(svg_file, name_svg, icon, svg_implemented_funcs, total_funcs, raw_ac
|
|||||||
function_count,
|
function_count,
|
||||||
total_effective_accuracy,
|
total_effective_accuracy,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|||||||
@ -8,61 +8,71 @@
|
|||||||
|
|
||||||
from isledecomp.utils import print_diff
|
from isledecomp.utils import print_diff
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
allow_abbrev=False, description="Verify Exports: Compare the exports of two DLLs."
|
|
||||||
)
|
|
||||||
parser.add_argument("original", metavar="original-binary", help="The original binary")
|
|
||||||
parser.add_argument(
|
|
||||||
"recompiled", metavar="recompiled-binary", help="The recompiled binary"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--no-color", "-n", action="store_true", help="Do not color the output"
|
|
||||||
)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
allow_abbrev=False,
|
||||||
|
description="Verify Exports: Compare the exports of two DLLs.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"original", metavar="original-binary", help="The original binary"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"recompiled", metavar="recompiled-binary", help="The recompiled binary"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-color", "-n", action="store_true", help="Do not color the output"
|
||||||
|
)
|
||||||
|
|
||||||
if not os.path.isfile(args.original):
|
args = parser.parse_args()
|
||||||
parser.error(f"Original binary file {args.original} does not exist")
|
|
||||||
|
|
||||||
if not os.path.isfile(args.recompiled):
|
if not os.path.isfile(args.original):
|
||||||
parser.error(f"Recompiled binary {args.recompiled} does not exist")
|
parser.error(f"Original binary file {args.original} does not exist")
|
||||||
|
|
||||||
|
if not os.path.isfile(args.recompiled):
|
||||||
|
parser.error(f"Recompiled binary {args.recompiled} does not exist")
|
||||||
|
|
||||||
|
def get_file_in_script_dir(fn):
|
||||||
|
return os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), fn)
|
||||||
|
|
||||||
|
def get_exports(file):
|
||||||
|
call = [get_file_in_script_dir("DUMPBIN.EXE"), "/EXPORTS"]
|
||||||
|
|
||||||
|
if os.name != "nt":
|
||||||
|
call.insert(0, "wine")
|
||||||
|
file = (
|
||||||
|
subprocess.check_output(["winepath", "-w", file])
|
||||||
|
.decode("utf-8")
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
call.append(file)
|
||||||
|
|
||||||
|
raw = subprocess.check_output(call).decode("utf-8").split("\r\n")
|
||||||
|
exports = []
|
||||||
|
|
||||||
|
start = False
|
||||||
|
|
||||||
|
for line in raw:
|
||||||
|
if not start:
|
||||||
|
if line == " ordinal hint name":
|
||||||
|
start = True
|
||||||
|
else:
|
||||||
|
if line:
|
||||||
|
exports.append(line[27 : line.rindex(" (")])
|
||||||
|
elif exports:
|
||||||
|
break
|
||||||
|
|
||||||
|
return exports
|
||||||
|
|
||||||
|
og_exp = get_exports(args.original)
|
||||||
|
re_exp = get_exports(args.recompiled)
|
||||||
|
|
||||||
|
udiff = difflib.unified_diff(og_exp, re_exp)
|
||||||
|
has_diff = print_diff(udiff, args.no_color)
|
||||||
|
|
||||||
|
return 1 if has_diff else 0
|
||||||
|
|
||||||
|
|
||||||
def get_file_in_script_dir(fn):
|
if __name__ == "__main__":
|
||||||
return os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), fn)
|
raise SystemExit(main())
|
||||||
|
|
||||||
|
|
||||||
def get_exports(file):
|
|
||||||
call = [get_file_in_script_dir("DUMPBIN.EXE"), "/EXPORTS"]
|
|
||||||
|
|
||||||
if os.name != "nt":
|
|
||||||
call.insert(0, "wine")
|
|
||||||
file = subprocess.check_output(["winepath", "-w", file]).decode("utf-8").strip()
|
|
||||||
|
|
||||||
call.append(file)
|
|
||||||
|
|
||||||
raw = subprocess.check_output(call).decode("utf-8").split("\r\n")
|
|
||||||
exports = []
|
|
||||||
|
|
||||||
start = False
|
|
||||||
|
|
||||||
for line in raw:
|
|
||||||
if not start:
|
|
||||||
if line == " ordinal hint name":
|
|
||||||
start = True
|
|
||||||
else:
|
|
||||||
if line:
|
|
||||||
exports.append(line[27 : line.rindex(" (")])
|
|
||||||
elif exports:
|
|
||||||
break
|
|
||||||
|
|
||||||
return exports
|
|
||||||
|
|
||||||
|
|
||||||
og_exp = get_exports(args.original)
|
|
||||||
re_exp = get_exports(args.recompiled)
|
|
||||||
|
|
||||||
udiff = difflib.unified_diff(og_exp, re_exp)
|
|
||||||
has_diff = print_diff(udiff, args.no_color)
|
|
||||||
|
|
||||||
sys.exit(1 if has_diff else 0)
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user