Merge remote-tracking branch 'upstream/master' into legobackgroundcolor

This commit is contained in:
Misha 2023-06-30 07:57:15 +03:00
commit 519253bff4
23 changed files with 542 additions and 4432 deletions

View file

@ -26,7 +26,7 @@ jobs:
key: dx5sdk
- name: Download DX5 SDK
if: steps.cache-dx5.outputs.cache-hit != 'true'
if: ${{ !steps.cache-dx5.outputs.cache-hit }}
run: |
cd dx5sdk
curl -fLOSs https://archive.org/download/idx5sdk/idx5sdk.exe
@ -34,8 +34,7 @@ jobs:
7z x .\DX5SDK.EXE
- name: Cache DX5 SDK
if: steps.cache-dx5.outputs.cache-hit != 'true'
id: save-dx5
if: ${{ !steps.cache-dx5.outputs.cache-hit }}
uses: actions/cache/save@v3
with:
path: dx5sdk
@ -47,22 +46,47 @@ jobs:
cd cdrom
.\SETUP.EXE /s
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.13
with:
# Use 2.8 for maximum backwards compatibility
cmake-version: '2.8.x'
- name: Build
shell: cmd
run: |
call .\msvc420\bin\VCVARS32.BAT x86
mkdir Release
.\msvc420\bin\NMAKE.EXE /f isle.mak CFG="ISLE - Win32 Release"
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles"
cmake --build .
- name: Restore cached original binaries
id: cache-original-binaries
uses: actions/cache/restore@v3
with:
path: legobin
key: legobin
- name: Download original island binares
if: ${{ !steps.cache-original-binaries.outputs.cache-hit }}
run: |
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin
- name: Cache original binaries
if: ${{ !steps.cache-original-binaries.outputs.cache-hit }}
uses: actions/cache/save@v3
with:
path: legobin
key: legobin
- name: Summarize Accuracy
shell: bash
run: |
curl -fLOSs https://legoisland.org/download/ISLE.EXE
curl -fLOSs https://legoisland.org/download/LEGO1.DLL
pip install capstone
pip install colorama
python3 tools/reccmp/reccmp.py -S ISLEPROGRESS.SVG --svg-icon tools/reccmp/isle.png -H ISLEPROGRESS.HTML ISLE.EXE Release/ISLE.EXE Release/ISLE.PDB . | tee ISLEPROGRESS.TXT
python3 tools/reccmp/reccmp.py -S LEGO1PROGRESS.SVG -T 1929 --svg-icon tools/reccmp/lego1.png -H LEGO1PROGRESS.HTML LEGO1.DLL Release/LEGO1.DLL Release/LEGO1.PDB . | tee LEGO1PROGRESS.TXT
pip install -r tools/reccmp/requirements.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
- name: Compare Accuracy With Current Master
shell: bash
@ -79,14 +103,20 @@ jobs:
with:
name: Win32
path: |
Release
ISLEPROGRESS.HTML
LEGO1PROGRESS.HTML
ISLEPROGRESS.SVG
LEGO1PROGRESS.SVG
build/ISLE.EXE
build/LEGO1.DLL
- name: Upload Artifact
uses: actions/upload-artifact@master
with:
name: Accuracy Report
path: |
ISLEPROGRESS.*
LEGO1PROGRESS.*
- name: Upload Continuous Release
shell: bash
if: github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
@ -99,13 +129,7 @@ jobs:
curl -fLOSs https://raw.githubusercontent.com/probonopd/uploadtool/master/upload.sh
./upload.sh \
Release/ISLE.EXE \
Release/LEGO1.DLL \
ISLEPROGRESS.HTML \
ISLEPROGRESS.TXT \
ISLEPROGRESS.SVG \
ISLEPROGRESS.PNG \
LEGO1PROGRESS.HTML \
LEGO1PROGRESS.TXT \
LEGO1PROGRESS.PNG \
LEGO1PROGRESS.SVG
build/ISLE.EXE \
build/LEGO1.DLL \
ISLEPROGRESS.* \
LEGO1PROGRESS.*

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ Release/
*.ncb
ISLE.EXE
LEGO1.DLL
build/

212
CMakeLists.txt Normal file
View file

@ -0,0 +1,212 @@
cmake_minimum_required(VERSION 2.8...3.5 FATAL_ERROR)
project(isle CXX)
option(ISLE_BUILD_APP "Build ISLE.EXE application" ON)
option(ISLE_BUILD_LIB "Build LEGO1.DLL library" ON)
if (ISLE_BUILD_APP)
add_executable(isle WIN32
ISLE/res/isle.rc
ISLE/isleapp.cpp
ISLE/define.cpp
)
# Include LEGO1 headers in ISLE
target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1")
# Link DSOUND, WINMM, and our fake LEGO1 lib (TODO: replace with real once all exports are implemented)
target_link_libraries(isle PRIVATE dsound winmm "${CMAKE_SOURCE_DIR}/ISLE/ext/lego1.lib")
# Make sure filenames are ALL CAPS
set_property(TARGET isle PROPERTY OUTPUT_NAME ISLE)
set_property(TARGET isle PROPERTY SUFFIX ".EXE")
endif()
if (ISLE_BUILD_LIB)
add_library(lego1 SHARED
LEGO1/act1state.cpp
LEGO1/act2brick.cpp
LEGO1/act2policestation.cpp
LEGO1/act3.cpp
LEGO1/act3shark.cpp
LEGO1/act3state.cpp
LEGO1/ambulance.cpp
LEGO1/ambulancemissionstate.cpp
LEGO1/animstate.cpp
LEGO1/beachhouseentity.cpp
LEGO1/bike.cpp
LEGO1/buildingentity.cpp
LEGO1/bumpbouy.cpp
LEGO1/carrace.cpp
LEGO1/dllmain.cpp
LEGO1/dunebuggy.cpp
LEGO1/elevatorbottom.cpp
LEGO1/gasstation.cpp
LEGO1/gasstationentity.cpp
LEGO1/gasstationstate.cpp
LEGO1/helicopter.cpp
LEGO1/helicopterstate.cpp
LEGO1/historybook.cpp
LEGO1/hospital.cpp
LEGO1/hospitalentity.cpp
LEGO1/hospitalstate.cpp
LEGO1/infocenter.cpp
LEGO1/infocenterdoor.cpp
LEGO1/infocenterentity.cpp
LEGO1/infocenterstate.cpp
LEGO1/isle.cpp
LEGO1/isleactor.cpp
LEGO1/islepathactor.cpp
LEGO1/jetski.cpp
LEGO1/jetskirace.cpp
LEGO1/jukebox.cpp
LEGO1/jukeboxentity.cpp
LEGO1/jukeboxstate.cpp
LEGO1/legoact2state.cpp
LEGO1/legoactioncontrolpresenter.cpp
LEGO1/legoanimactor.cpp
LEGO1/legoanimationmanager.cpp
LEGO1/legoanimmmpresenter.cpp
LEGO1/legoanimpresenter.cpp
LEGO1/legobuildingmanager.cpp
LEGO1/legocachesound.cpp
LEGO1/legocameracontroller.cpp
LEGO1/legocarbuild.cpp
LEGO1/legocarbuildanimpresenter.cpp
LEGO1/legocontrolmanager.cpp
LEGO1/legoentity.cpp
LEGO1/legoentitypresenter.cpp
LEGO1/legoflctexturepresenter.cpp
LEGO1/legohideanimpresenter.cpp
LEGO1/legoinputmanager.cpp
LEGO1/legojetski.cpp
LEGO1/legoloadcachesoundpresenter.cpp
LEGO1/legolocomotionanimpresenter.cpp
LEGO1/legonavcontroller.cpp
LEGO1/legoomni.cpp
LEGO1/legopalettepresenter.cpp
LEGO1/legopathactor.cpp
LEGO1/legopathcontroller.cpp
LEGO1/legopathpresenter.cpp
LEGO1/legophonemepresenter.cpp
LEGO1/legoplantmanager.cpp
LEGO1/legorace.cpp
LEGO1/legosoundmanager.cpp
LEGO1/legostate.cpp
LEGO1/legotexturepresenter.cpp
LEGO1/legovideomanager.cpp
LEGO1/legoworld.cpp
LEGO1/legoworldpresenter.cpp
LEGO1/motorcycle.cpp
LEGO1/mxatomid.cpp
LEGO1/mxaudiopresenter.cpp
LEGO1/mxautolocker.cpp
LEGO1/mxbackgroundaudiomanager.cpp
LEGO1/mxcompositemediapresenter.cpp
LEGO1/mxcompositepresenter.cpp
LEGO1/mxcontrolpresenter.cpp
LEGO1/mxcore.cpp
LEGO1/mxcriticalsection.cpp
LEGO1/mxdiskstreamcontroller.cpp
LEGO1/mxdiskstreamprovider.cpp
LEGO1/mxdsaction.cpp
LEGO1/mxdsanim.cpp
LEGO1/mxdschunk.cpp
LEGO1/mxdsevent.cpp
LEGO1/mxdsfile.cpp
LEGO1/mxdsmediaaction.cpp
LEGO1/mxdsmultiaction.cpp
LEGO1/mxdsobject.cpp
LEGO1/mxdsobjectaction.cpp
LEGO1/mxdsparallelaction.cpp
LEGO1/mxdsselectaction.cpp
LEGO1/mxdsserialaction.cpp
LEGO1/mxdssound.cpp
LEGO1/mxdssource.cpp
LEGO1/mxdsstill.cpp
LEGO1/mxdssubscriber.cpp
LEGO1/mxentity.cpp
LEGO1/mxeventmanager.cpp
LEGO1/mxeventpresenter.cpp
LEGO1/mxflcpresenter.cpp
LEGO1/mxioinfo.cpp
LEGO1/mxloopingflcpresenter.cpp
LEGO1/mxloopingsmkpresenter.cpp
LEGO1/mxmediapresenter.cpp
LEGO1/mxmusicpresenter.cpp
LEGO1/mxnotificationmanager.cpp
LEGO1/mxomni.cpp
LEGO1/mxomnicreateflags.cpp
LEGO1/mxomnicreateparam.cpp
LEGO1/mxomnicreateparambase.cpp
LEGO1/mxpalette.cpp
LEGO1/mxpresenter.cpp
LEGO1/mxsmkpresenter.cpp
LEGO1/mxsoundmanager.cpp
LEGO1/mxsoundpresenter.cpp
LEGO1/mxstillpresenter.cpp
LEGO1/mxstreamer.cpp
LEGO1/mxstring.cpp
LEGO1/mxtimer.cpp
LEGO1/mxtransitionmanager.cpp
LEGO1/mxunknown100dc6b0.cpp
LEGO1/mxvideomanager.cpp
LEGO1/mxvideoparam.cpp
LEGO1/mxvideoparamflags.cpp
LEGO1/mxvideopresenter.cpp
LEGO1/mxwavepresenter.cpp
LEGO1/pizza.cpp
LEGO1/pizzamissionstate.cpp
LEGO1/pizzeria.cpp
LEGO1/pizzeriastate.cpp
LEGO1/police.cpp
LEGO1/policeentity.cpp
LEGO1/policestate.cpp
LEGO1/racecar.cpp
LEGO1/racestandsentity.cpp
LEGO1/racestate.cpp
LEGO1/radio.cpp
LEGO1/radiostate.cpp
LEGO1/registrationbook.cpp
LEGO1/score.cpp
LEGO1/scorestate.cpp
LEGO1/skateboard.cpp
LEGO1/towtrack.cpp
LEGO1/towtrackmissionstate.cpp
)
# Link libraries
target_link_libraries(lego1 PRIVATE ddraw dsound winmm)
# Make sure filenames are ALL CAPS
set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1)
set_property(TARGET lego1 PROPERTY SUFFIX ".DLL")
endif()
if (MSVC)
# 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.
# They ensure a recompilation that can be byte/instruction accurate to the original binaries.
target_compile_options(isle PRIVATE "/ML$<$<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_DEBUG "/Gm /Zi /Od /D \"_DEBUG\"")
set(CMAKE_CXX_FLAGS_RELEASE "/O2 /D \"NDEBUG\"")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/Zi /O2 /D \"NDEBUG\"")
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os /D \"NDEBUG\"")
set(CMAKE_EXE_LINKER_FLAGS "/machine:I386")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/incremental:yes /debug")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/incremental:no")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "/incremental:no")
set(CMAKE_SHARED_LINKER_FLAGS "/machine:I386")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/incremental:yes /debug")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/incremental:no")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug")
set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "/incremental:no")
endif()

View file

@ -1,9 +1,9 @@
#include "resource.h"
ISLE_ARROW CURSOR "ISLE/res/arrow.cur"
ISLE_NO CURSOR "ISLE/res/no.cur"
ISLE_BUSY CURSOR "ISLE/res/busy.cur"
APP_ICON ICON "ISLE/res/isle.ico"
ISLE_ARROW CURSOR "arrow.cur"
ISLE_NO CURSOR "no.cur"
ISLE_BUSY CURSOR "busy.cur"
APP_ICON ICON "isle.ico"
1 VERSIONINFO
FILEVERSION 1,1,0,0

View file

@ -24,7 +24,7 @@ public:
// OFFSET: LEGO1 0x1005ec90
inline virtual MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoAnimationManager::ClassName()) || MxCore::IsA(name);
return !strcmp(name, ClassName()) || MxCore::IsA(name);
}
__declspec(dllexport) static void configureLegoAnimationManager(int param_1);

View file

@ -21,7 +21,7 @@ public:
// OFFSET: LEGO1 0x10011ed0
inline virtual MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoCameraController::ClassName()) || MxCore::IsA(name);
return !strcmp(name, ClassName()) || MxCore::IsA(name);
}
};

View file

@ -20,7 +20,7 @@ public:
// OFFSET: LEGO1 0x1006d890
inline MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoHideAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(name);
return !strcmp(name, ClassName()) || LegoAnimPresenter::IsA(name);
}
private:

View file

@ -19,7 +19,7 @@ public:
// OFFSET: LEGO1 0x1006ce60
inline MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoLocomotionAnimPresenter::ClassName()) || LegoLoopingAnimPresenter::IsA(name);
return !strcmp(name, ClassName()) || LegoLoopingAnimPresenter::IsA(name);
}
private:

View file

@ -18,7 +18,7 @@ public:
// OFFSET: LEGO1 0x1000c9b0
inline MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoLoopingAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(name);
return !strcmp(name, ClassName()) || LegoAnimPresenter::IsA(name);
}
};

View file

@ -32,7 +32,7 @@ public:
// OFFSET: LEGO1 0x10054b90
inline MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoNavController::ClassName()) || MxCore::IsA(name);
return !strcmp(name, ClassName()) || MxCore::IsA(name);
}
void SetControlMax(int p_hMax, int p_vMax);

View file

@ -15,13 +15,20 @@ LegoOmni::~LegoOmni()
// OFFSET: LEGO1 0x1005ad10
LegoOmni *LegoOmni::GetInstance()
{
return (LegoOmni *) m_instance;
return (LegoOmni *)MxOmni::GetInstance();
}
// OFFSET: LEGO1 0x1005ac90
void LegoOmni::CreateInstance()
{
MxOmni::DestroyInstance();
MxOmni::SetInstance(new LegoOmni());
}
// OFFSET: LEGO1 0x10015700
LegoOmni *Lego()
{
return (LegoOmni *) MxOmni::GetInstance();
return (LegoOmni *)MxOmni::GetInstance();
}
// OFFSET: LEGO1 0x10015710
@ -30,7 +37,6 @@ LegoSoundManager *SoundManager()
return LegoOmni::GetInstance()->GetSoundManager();
}
// OFFSET: LEGO1 0x10015720
LegoVideoManager *VideoManager()
{
@ -79,6 +85,13 @@ LegoNavController *NavController()
return LegoOmni::GetInstance()->GetNavController();
}
// OFFSET: LEGO1 0x10015900
MxTransitionManager *TransitionManager()
{
return LegoOmni::GetInstance()->GetTransitionManager();
}
// OFFSET: LEGO1 0x1005b5f0
long LegoOmni::Notify(MxParam &p)
{

View file

@ -71,6 +71,7 @@ public:
LegoPlantManager *GetLegoPlantManager() { return m_plantManager; }
LegoGameState *GetGameState() { return m_gameState; }
LegoNavController *GetNavController() { return m_navController; }
MxTransitionManager *GetTransitionManager() { return m_transitionManager; }
private:
int m_unk68;
@ -84,7 +85,7 @@ private:
char m_unk94[0x4];
LegoBuildingManager* m_buildingManager; // 0x98
LegoGameState *m_gameState; // 0x9c
char m_unka0[0x94];
MxDSAction m_action;
MxBackgroundAudioManager *m_bkgAudioManager; // 0x134
MxTransitionManager *m_transitionManager; // 0x138
int m_unk13c;
@ -93,26 +94,19 @@ private:
__declspec(dllexport) MxBackgroundAudioManager * BackgroundAudioManager();
__declspec(dllexport) MxDSObject * CreateStreamObject(MxDSFile *,short);
__declspec(dllexport) MxEventManager * EventManager();
__declspec(dllexport) LegoGameState * GameState();
__declspec(dllexport) const char * GetNoCD_SourceName();
__declspec(dllexport) LegoInputManager * InputManager();
__declspec(dllexport) LegoOmni * Lego();
__declspec(dllexport) MxSoundManager * MSoundManager();
__declspec(dllexport) void MakeSourceName(char *, const char *);
__declspec(dllexport) MxMusicManager * MusicManager();
__declspec(dllexport) MxNotificationManager * NotificationManager();
__declspec(dllexport) LegoEntity * PickEntity(long,long);
__declspec(dllexport) LegoROI * PickROI(long,long);
__declspec(dllexport) void SetOmniUserMessage(void (*)(const char *,int));
__declspec(dllexport) LegoSoundManager * SoundManager();
__declspec(dllexport) long Start(MxDSAction *);
__declspec(dllexport) MxStreamer * Streamer();
__declspec(dllexport) MxTickleManager * TickleManager();
__declspec(dllexport) MxTransitionManager * TransitionManager();
__declspec(dllexport) MxVariableTable * VariableTable();
__declspec(dllexport) LegoVideoManager * VideoManager();
__declspec(dllexport) long Start(MxDSAction *a);
LegoBuildingManager* BuildingManager();

View file

@ -21,7 +21,7 @@ public:
// OFFSET: LEGO1 0x10079f40
inline MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, LegoPalettePresenter::ClassName()) || MxVideoPresenter::IsA(name);
return !strcmp(name, ClassName()) || MxVideoPresenter::IsA(name);
}
private:

View file

@ -7,9 +7,9 @@
MxDSObject::MxDSObject()
{
this->m_unk0c = 0;
this->m_unk10 = 0;
this->m_sourceName = NULL;
this->m_unk14 = 0;
this->m_name = NULL;
this->m_objectName = NULL;
this->m_unk24 = -1;
this->m_unk1c = -1;
this->m_unk28 = 0;
@ -18,25 +18,110 @@ MxDSObject::MxDSObject()
// OFFSET: LEGO1 0x100bf7e0
MxDSObject::~MxDSObject()
{
// TODO
delete[] m_objectName;
delete[] m_sourceName;
}
// OFFSET: LEGO1 0x100bf870
void MxDSObject::CopyFrom(MxDSObject &p_dsObject)
{
this->SetSourceName(p_dsObject.m_sourceName);
this->m_unk14 = p_dsObject.m_unk14;
this->SetObjectName(p_dsObject.m_objectName);
this->m_unk1c = p_dsObject.m_unk1c;
this->m_unk24 = p_dsObject.m_unk24;
this->m_atomId = p_dsObject.m_atomId;
this->m_unk28 = p_dsObject.m_unk28;
}
// OFFSET: LEGO1 0x100bf8c0
MxDSObject &MxDSObject::operator=(MxDSObject &p_dsObject)
{
if (this == &p_dsObject)
return *this;
this->CopyFrom(p_dsObject);
return *this;
}
// OFFSET: LEGO1 0x100bf8e0
void MxDSObject::SetObjectName(const char *p_name)
{
if (p_name != this->m_name)
{
free(this->m_name);
if (p_name != this->m_objectName) {
delete[] this->m_objectName;
if (p_name) {
this->m_name = (char *)malloc(strlen(p_name) + 1);
this->m_objectName = new char[strlen(p_name) + 1];
if (this->m_name) {
strcpy(this->m_name, p_name);
if (this->m_objectName) {
strcpy(this->m_objectName, p_name);
}
}
else {
this->m_name = NULL;
this->m_objectName = NULL;
}
}
}
// OFFSET: LEGO1 0x100bf950
void MxDSObject::SetSourceName(const char *p_sourceName)
{
if (p_sourceName != this->m_sourceName) {
delete[] this->m_sourceName;
if (p_sourceName) {
this->m_sourceName = new char[strlen(p_sourceName) + 1];
if (this->m_sourceName) {
strcpy(this->m_sourceName, p_sourceName);
}
}
else {
this->m_sourceName = NULL;
}
}
}
// OFFSET: LEGO1 0x100bf9c0
int MxDSObject::unk14()
{
return 10;
}
// OFFSET: LEGO1 0x100bf9d0
unsigned int MxDSObject::CalculateUnk08()
{
unsigned int unk08;
if (this->m_sourceName)
unk08 = strlen(this->m_sourceName) + 3;
else
unk08 = 3;
unk08 += 4;
if (this->m_objectName)
unk08 += strlen(this->m_objectName) + 1;
else
unk08++;
unk08 += 4;
this->m_unk08 = unk08;
return unk08;
}
// OFFSET: LEGO1 0x100bfa20
void MxDSObject::Parse(char **p_source, unsigned short p_unk24)
{
this->SetSourceName(*p_source);
*p_source += strlen(this->m_sourceName) + 1;
this->m_unk14 = *(int*) *p_source;
*p_source += 4;
this->SetObjectName(*p_source);
*p_source += strlen(this->m_objectName) + 1;
this->m_unk1c = *(int*) *p_source;
*p_source += 4;
this->m_unk24 = p_unk24;
}

View file

@ -9,23 +9,25 @@
class MxDSObject : public MxCore
{
public:
__declspec(dllexport) void SetObjectName(const char *);
__declspec(dllexport) void SetObjectName(const char *p_objectName);
MxDSObject();
virtual ~MxDSObject() override;
// OFFSET: LEGO1 0x100bf730
inline virtual const char *ClassName() const override // vtable+0x0c
{
// 0x10101400
return "MxDSObject";
}
MxDSObject &operator=(MxDSObject &p_dsObject);
void CopyFrom(MxDSObject &p_dsObject);
// OFFSET: LEGO1 0x100bf730
inline virtual const char *ClassName() const override { return "MxDSObject"; }; // vtable+0c
// OFFSET: LEGO1 0x100bf740
inline virtual MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, MxDSObject::ClassName()) || MxCore::IsA(name);
}
inline virtual MxBool IsA(const char *name) const override { return !strcmp(name, MxDSObject::ClassName()) || MxCore::IsA(name); }; // vtable+10;
virtual int unk14(); // vtable+14;
virtual unsigned int CalculateUnk08(); // vtable+18;
virtual void Parse(char **p_source, unsigned short p_unk24); // vtable+1c;
void SetSourceName(const char *p_sourceName);
inline const MxAtomId& GetAtomId() { return this->m_atomId; }
inline int GetUnknown1c() { return this->m_unk1c; }
@ -38,11 +40,11 @@ public:
inline void SetAtomId(MxAtomId p_atomId) { this->m_atomId = p_atomId; }
private:
int m_unk08;
unsigned int m_unk08;
short m_unk0c;
char* m_unk10;
char* m_sourceName;
int m_unk14;
char *m_name;
char *m_objectName;
int m_unk1c;
MxAtomId m_atomId;
short m_unk24;

View file

@ -1,7 +1,7 @@
#include "mxomni.h"
// 0x101015b0
MxOmni* MxOmni::m_instance = NULL;
MxOmni *MxOmni::g_instance = NULL;
// OFFSET: LEGO1 0x100aef10
MxOmni::MxOmni()
@ -33,10 +33,26 @@ void MxOmni::Init()
m_unk64 = NULL;
}
// OFFSET: LEGO1 0x100b0690
void MxOmni::DestroyInstance()
{
if (g_instance != NULL)
{
delete g_instance;
g_instance = NULL;
}
}
// OFFSET: LEGO1 0x100b0680
MxOmni *MxOmni::GetInstance()
{
return m_instance;
return g_instance;
}
// OFFSET: LEGO1 0x100af0b0
void MxOmni::SetInstance(MxOmni *instance)
{
g_instance = instance;
}
// OFFSET: LEGO1 0x100af0c0
@ -67,8 +83,62 @@ long MxOmni::Notify(MxParam &p)
return 0;
}
// OFFSET: LEGO1 0x100acea0
MxObjectFactory *ObjectFactory()
{
return MxOmni::GetInstance()->GetObjectFactory();
}
// OFFSET: LEGO1 0x100aceb0
MxNotificationManager *NotificationManager()
{
return MxOmni::GetInstance()->GetNotificationManager();
}
// OFFSET: LEGO1 0x100acec0
MxTickleManager *TickleManager()
{
return MxOmni::GetInstance()->GetTickleManager();
}
// OFFSET: LEGO1 0x100aced0
MxTimer *Timer()
{
return MxOmni::GetInstance()->GetTimer();
}
// OFFSET: LEGO1 0x100acef0
MxStreamer* Streamer()
{
return MxOmni::GetInstance()->GetStreamer();
}
// OFFSET: LEGO1 0x100acf00
MxSoundManager* MSoundManager()
{
return MxOmni::GetInstance()->GetSoundManager();
}
// OFFSET: LEGO1 0x100acf10
MxVideoManager* MVideoManager()
{
return MxOmni::GetInstance()->GetVideoManager();
}
// OFFSET: LEGO1 0x100acf20
MxVariableTable* VariableTable()
{
return MxOmni::GetInstance()->GetVariableTable();
}
// OFFSET: LEGO1 0x100acf30
MxMusicManager* MusicManager()
{
return MxOmni::GetInstance()->GetMusicManager();
}
// OFFSET: LEGO1 0x100acf40
MxEventManager* EventManager()
{
return MxOmni::GetInstance()->GetEventManager();
}

View file

@ -35,11 +35,19 @@ public:
virtual void Init(); // vtable+14
virtual MxResult Create(MxOmniCreateParam &p); // vtable+18
virtual void Destroy(); // vtable+1c
static void SetInstance(MxOmni* instance);
MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; }
MxNotificationManager* GetNotificationManager() const { return this->m_notificationManager; }
MxTickleManager* GetTickleManager() const { return this->m_tickleManager; }
MxTimer* GetTimer() const { return this->m_timer; }
MxStreamer* GetStreamer() const { return this->m_streamer; }
MxSoundManager* GetSoundManager() const { return this->m_soundManager; }
MxVideoManager* GetVideoManager() const { return this->m_videoManager; }
MxVariableTable* GetVariableTable() const { return this->m_variableTable; }
MxMusicManager* GetMusicManager() const { return this->m_musicManager; }
MxEventManager* GetEventManager() const { return this->m_eventManager; }
protected:
static MxOmni* m_instance;
static MxOmni* g_instance;
MxString m_mediaPath; // 0x8
HWND *m_windowHandle; // 0x18;
@ -60,7 +68,12 @@ protected:
unsigned char m_unk64; // 0x64
};
__declspec(dllexport) MxTickleManager * TickleManager();
__declspec(dllexport) MxTimer * Timer();
__declspec(dllexport) MxStreamer * Streamer();
__declspec(dllexport) MxSoundManager * MSoundManager();
__declspec(dllexport) MxVariableTable * VariableTable();
__declspec(dllexport) MxMusicManager * MusicManager();
__declspec(dllexport) MxEventManager * EventManager();
#endif // MXOMNI_H

View file

@ -8,7 +8,6 @@
class MxStreamController : public MxCore
{
public:
// OFFSET: LEGO1 0x100c0f10
inline virtual const char *ClassName() const override // vtable+0xc
{
@ -22,8 +21,6 @@ public:
return !strcmp(name, MxStreamController::ClassName()) || MxCore::IsA(name);
}
int m_unk00;
int m_unk04;
int m_unk08;
int m_unk0c;
int m_unk10;

View file

@ -6,7 +6,18 @@
// VTABLE 0x100dd100
class MxStreamProvider : public MxCore
{
public:
// OFFSET: LEGO1 0x100d07e0
inline virtual const char *ClassName() const override // vtable+0x0c
{
return "MxStreamProvider";
}
// OFFSET: LEGO1 0x100d07f0
inline virtual MxBool IsA(const char *name) const override // vtable+0x10
{
return !strcmp(name, MxStreamProvider::ClassName()) || MxCore::IsA(name);
}
};
#endif // MXSTREAMPROVIDER_H

View file

@ -2,47 +2,53 @@
[Development Vlog](https://www.youtube.com/playlist?list=PLbpl-gZkNl2COf_bB6cfgTapD5WduAfPz) | [Contributing](https://github.com/isledecomp/isle/blob/master/CONTRIBUTING.md) | [Matrix](https://matrix.to/#/#isledecomp:matrix.org) | [Forums](https://forum.mattkc.com/viewforum.php?f=1) | [Patreon](https://www.patreon.com/mattkc)
This is a **work-in-progress** decompilation of LEGO Island version 1.1. It aims to be relatively faithful, but not byte accurate. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms later on.
This is a **work-in-progress** decompilation of LEGO Island version 1.1. It aims to be as accurate as possible, matching the recompiled instructions to the original machine code as much as possible. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms later on.
## Status
<img src="https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.PNG" width="50%"><img src="https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.PNG" width="50%">
Currently `ISLE.EXE` is completely decompiled, however there are some known inaccuracies. It should work if you pair it with the original game's `LEGO1.DLL` (and other files), however small things may not work correctly yet. Work on decompiling `LEGO1.DLL` has only just started and currently it is too incomplete to be usable.
Currently `ISLE.EXE` is completely decompiled and behaves identically to the original. A handful of stubborn instructions are not yet matching, however we anticipate they will as more of the overall codebase is implemented.
`LEGO1.DLL` is still very much incomplete and cannot be used at this time. Instead, if you want to test this, it is recommended to pair the recompiled `ISLE.EXE` with the `LEGO1.DLL` from the original game.
## Building
LEGO Island was compiled with Microsoft Visual C++ 4.20, so that's what this decompilation targets. However it should compile with NMAKE on newer versions of Visual Studio too.
This projects uses the [CMake](https://cmake.org/) build system, which allows for a high degree of versatility regarding compilers and development environments. For the most accurate results, it is recommended to use Microsoft Visual C++ 4.20 (the same compiler used to build the original game). Since we're trying to match this to the original executable as closely as possible, all contributions will be graded with the output of this compiler.
### Recommended Instructions
These instructions use the development IDE from Visual C++ 4.20. By modern standards, it can be a little clunky to use, especially on newer versions of Windows, however it's still relatively straightforward. If you prefer a command line process that can fit into a modern workflow/IDE, see the instructions below.
These instructions will outline how to compile this repository into an accurate instruction-matching binary with Visual C++ 4.2. If you wish, you can try using other compilers, but this is at your own risk and won't be covered in this guide.
1. Install Microsoft Visual C++ 4.20. This can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, I made a [portable version](https://github.com/itsmattkc/msvc420) that can be downloaded and used quickly instead.
2. Download and install the DirectX 5 SDK. Similarly, this can be found on many abandonware sites.
3. Open "Microsoft Developer Studio" (`BIN/MSDEV.EXE` for those using the portable).
4. `File` > `Open Workspace`
5. Select `ISLE.MDP` from this repository.
6. Select a build configuration. `ISLE - Win32 Release` is recommended because, at this point in time, you'll almost certainly be pairing it with the retail `LEGO1.DLL`, which is also a release build.
7. `Build` > `Build ISLE.EXE`. This will build `ISLE.EXE` in a folder called `Release`. It will also build `LEGO1.DLL` since it's listed as a dependency, however the `LEGO1.DLL` produced is too incomplete to be usable at this time.
#### Prerequisites
### Command Line Instructions
You will need the following software installed:
For some users, this may be preferable to using an obsolete graphical IDE. Any modern IDE should support custom command line build steps, making this potentially easier to fit into a familiar contemporary workflow. This guide assumes a general familiarity with the Windows command prompt.
- Microsoft Visual C++ 4.2. This can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, I made a [portable version](https://github.com/itsmattkc/msvc420) that can be downloaded and used quickly instead.
- DirectX 5 SDK. Similarly, this can be found on many abandonware sites.
- [CMake](https://cmake.org/). A copy is often included with the "Desktop development with C++" workload in newer versions of Visual Studio, however it can also be installed as a standalone app.
1. Acquire Visual Studio/Visual C++. Any version after 4.20 should work here, but 4.20 is the only one guaranteed to work. If you wish to use 4.20, it can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, I made a [portable version](https://github.com/itsmattkc/msvc420) that can be downloaded and used quickly instead.
2. Download and install the DirectX 5 SDK. Similarly, this can be found on many abandonware sites, but later versions of Visual Studio include the DirectX SDK by default, so this step may be skippable (you definitely need it for MSVC 4.20).
3. Open an x86/32-bit developer command prompt. Depending on the version of VS you're using, you may have a start menu item for it already (e.g. `x86 Native Tools Command Prompt`). Alternatively, you can start a normal command prompt (`cmd`) and run `vcvars32.bat` from the Visual Studio folder (run `BIN/VCVARS32.BAT x86` if you're using the portable 4.20).
4. `cd` to the folder you cloned this repository to.
5. `mkdir Release` if the folder doesn't already exist. Some versions of NMAKE may make this folder by itself, but some don't.
6. Run `nmake /f isle.mak CFG="ISLE - Win32 Release"`. This will build `ISLE.EXE` in the `Release` folder you just made. It will also build `LEGO1.DLL` since it's listed as a dependency, however the `LEGO1.DLL` produced is too incomplete to be usable at this time.
#### Compiling From Command Line
1. Open a Command Prompt (`cmd`).
1. From Visual C++ 4.2, run `BIN/VCVARS32.BAT x86` to populate the path and other environment variables for compiling with MSVC.
1. Make a folder for compiled objects to go, such as a `build` folder inside the source repository (the folder you cloned/downloaded to).
1. In your Command Prompt, `cd` to the build folder.
1. Configure the project with CMake by running:
```
cmake <path-to-source> -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
- Replace `<path-to-source>` with the source repository. Can be `..` if your build folder is inside the source repository.
- `RelWithDebInfo` is recommended because it will produce debug symbols useful for further decompilation work. However, you can change this to `Release` if you don't need them. `Debug` builds are not recommended because they are unlikely to be compatible with the retail `LEGO1.DLL`, which is currently the only way to really use this decomp.
- `NMake Makefiles` is most recommended because it will be immediately compatible with Visual C++ 4.2. For faster builds, you can use `Ninja` (if you have it installed), however due to limitations in Visual C++ 4.2, you can only build `Release` builds this way (debug symbols cannot be generated with `Ninja`).
1. Build the project by running `nmake` or `cmake --build <build-folder>`
1. When this is done, there should a recompiled `ISLE.EXE` and `LEGO1.DLL` in the build folder.
If you have a CMake-compatible IDE, it should be pretty straightforward to use this repository, as long as you can use `VCVARS32.BAT` and set the generator to `NMake Makefiles`.
## Usage
Simply place the compiled `ISLE.EXE` into LEGO Island's install folder (usually `C:\Program Files\LEGO Island` or `C:\Program Files (x86)\LEGO Island`). Unless you're a developer, disregard the compiled `LEGO1.DLL` for now as it is too incomplete to be usable. Alternatively, LEGO Island can run from any directory as long as `ISLE.EXE` and `LEGO1.DLL` are in the same directory, and the registry keys point to the correct location for the asset files.
Ideally, this decompilation should be paired with version 1.1. It may work on 1.0 too, however this is not guaranteed.
## Contributing
If you're interested in helping/contributing to this project, check out the [CONTRIBUTING](https://github.com/isledecomp/isle/blob/master/CONTRIBUTING.md) page.

4323
isle.mak

File diff suppressed because it is too large Load diff

BIN
isle.mdp

Binary file not shown.

View file

@ -16,12 +16,13 @@ parser.add_argument('original', metavar='original-binary', help='The original bi
parser.add_argument('recompiled', metavar='recompiled-binary', help='The recompiled binary')
parser.add_argument('pdb', metavar='recompiled-pdb', help='The PDB of the recompiled binary')
parser.add_argument('decomp_dir', metavar='decomp-dir', help='The decompiled source tree')
parser.add_argument('--total', '-T', metavar='total-func-count', help='Total number of expected functions (improves total accuracy statistic)')
parser.add_argument('--verbose', '-v', metavar='offset', help='Print assembly diff for specific function (original file\'s offset)')
parser.add_argument('--html', '-H', metavar='output-file', help='Generate searchable HTML summary of status and diffs')
parser.add_argument('--total', '-T', metavar='<count>', help='Total number of expected functions (improves total accuracy statistic)')
parser.add_argument('--verbose', '-v', metavar='<offset>', help='Print assembly diff for specific function (original file\'s offset)')
parser.add_argument('--html', '-H', metavar='<file>', help='Generate searchable HTML summary of status and diffs')
parser.add_argument('--no-color', '-n', action='store_true', help='Do not color the output')
parser.add_argument('--svg', '-S', metavar='output-svg', help='Generate SVG graphic of progress')
parser.add_argument('--svg-icon', metavar='svg-icon', help='Icon to use in SVG (PNG)')
parser.add_argument('--svg', '-S', metavar='<file>', help='Generate SVG graphic of progress')
parser.add_argument('--svg-icon', metavar='icon', help='Icon to use in SVG (PNG)')
parser.add_argument('--print-rec-addr', action='store_true', help='Print addresses of recompiled functions too')
args = parser.parse_args()
@ -335,7 +336,11 @@ for subdir, dirs, files in os.walk(source):
percenttext = colorama.Fore.RED + percenttext + colorama.Style.RESET_ALL
if not verbose:
print(' %s (%s / %s) is %s similar to the original' % (recinfo.name, hex(addr), hex(recinfo.addr), percenttext))
if args.print_rec_addr:
addrs = '%s / %s' % (hex(addr), hex(recinfo.addr))
else:
addrs = hex(addr)
print(' %s (%s) is %s similar to the original' % (recinfo.name, addrs, percenttext))
function_count += 1
total_accuracy += ratio