mirror of
https://github.com/isledecomp/isle.git
synced 2026-02-28 15:07:38 +00:00
Merge branch 'master' into pr/36
This commit is contained in:
commit
c3d3f36bf0
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -60,8 +60,8 @@ jobs:
|
|||||||
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE
|
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE
|
||||||
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL
|
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL
|
||||||
pip install capstone
|
pip install capstone
|
||||||
python3 tools/reccomp/reccomp.py -h ISLEPROGRESS.HTML ISLE.EXE Release/ISLE.EXE Release/ISLE.PDB ISLE
|
python3 tools/reccmp/reccmp.py -H ISLEPROGRESS.HTML ISLE.EXE Release/ISLE.EXE Release/ISLE.PDB .
|
||||||
python3 tools/reccomp/reccomp.py -h LEGO1PROGRESS.HTML LEGO1.DLL Release/LEGO1.DLL Release/LEGO1.PDB LEGO1
|
python3 tools/reccmp/reccmp.py -H LEGO1PROGRESS.HTML LEGO1.DLL Release/LEGO1.DLL Release/LEGO1.PDB .
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@master
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
Debug/
|
Debug/
|
||||||
Release/
|
Release/
|
||||||
*.ncb
|
*.ncb
|
||||||
|
ISLE.EXE
|
||||||
|
LEGO1.DLL
|
||||||
|
|||||||
@ -38,6 +38,3 @@ int g_startupDelay = 200;
|
|||||||
|
|
||||||
// 0x4101c0
|
// 0x4101c0
|
||||||
long g_lastFrameTime = 0;
|
long g_lastFrameTime = 0;
|
||||||
|
|
||||||
// 0x4101dc
|
|
||||||
const char *WINDOW_TITLE = "LEGO\xAE";
|
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
#ifndef DEFINE_H
|
#ifndef DEFINE_H
|
||||||
#define DEFINE_H
|
#define DEFINE_H
|
||||||
|
|
||||||
#include <Windows.h>
|
#include "legoinc.h"
|
||||||
|
|
||||||
class Isle;
|
class Isle;
|
||||||
|
|
||||||
extern Isle *g_isle;
|
extern Isle *g_isle;
|
||||||
extern int g_closed;
|
extern int g_closed;
|
||||||
|
// 0x4101c4
|
||||||
#define WNDCLASS_NAME "Lego Island MainNoM App"
|
#define WNDCLASS_NAME "Lego Island MainNoM App"
|
||||||
extern const char *WINDOW_TITLE;
|
// 0x4101dc
|
||||||
|
#define WINDOW_TITLE "LEGO\xAE"
|
||||||
extern unsigned char g_mousedown;
|
extern unsigned char g_mousedown;
|
||||||
extern unsigned char g_mousemoved;
|
extern unsigned char g_mousemoved;
|
||||||
extern RECT g_windowRect;
|
extern RECT g_windowRect;
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
#include "isle.h"
|
#include "isle.h"
|
||||||
|
|
||||||
#include "define.h"
|
|
||||||
#include "legoanimationmanager.h"
|
#include "legoanimationmanager.h"
|
||||||
#include "legobuildingmanager.h"
|
#include "legobuildingmanager.h"
|
||||||
#include "legomodelpresenter.h"
|
#include "legomodelpresenter.h"
|
||||||
#include "legoomni.h"
|
|
||||||
#include "legopartpresenter.h"
|
#include "legopartpresenter.h"
|
||||||
#include "legoworldpresenter.h"
|
#include "legoworldpresenter.h"
|
||||||
#include "mxdirectdraw.h"
|
#include "mxdirectdraw.h"
|
||||||
@ -78,7 +76,7 @@ Isle::~Isle()
|
|||||||
void Isle::Close()
|
void Isle::Close()
|
||||||
{
|
{
|
||||||
MxDSAction ds;
|
MxDSAction ds;
|
||||||
ds.SetUnknown24(0xFFFE);
|
ds.SetUnknown24(-2);
|
||||||
|
|
||||||
if (Lego()) {
|
if (Lego()) {
|
||||||
GameState()->Save(0);
|
GameState()->Save(0);
|
||||||
@ -574,67 +572,3 @@ MxResult Isle::SetupWindow(HINSTANCE hInstance)
|
|||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: ISLE 0x402c20
|
|
||||||
void Isle::Tick(BOOL sleepIfNotNextFrame)
|
|
||||||
{
|
|
||||||
if (this->m_windowActive) {
|
|
||||||
if (!Lego()) return;
|
|
||||||
if (!TickleManager()) return;
|
|
||||||
if (!Timer()) return;
|
|
||||||
|
|
||||||
long currentTime = Timer()->GetRealTime();
|
|
||||||
if (currentTime < g_lastFrameTime) {
|
|
||||||
g_lastFrameTime = -this->m_frameDelta;
|
|
||||||
}
|
|
||||||
if (this->m_frameDelta + g_lastFrameTime < currentTime) {
|
|
||||||
if (!Lego()->vtable40()) {
|
|
||||||
TickleManager()->Tickle();
|
|
||||||
}
|
|
||||||
g_lastFrameTime = currentTime;
|
|
||||||
|
|
||||||
if (g_startupDelay == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_startupDelay--;
|
|
||||||
if (g_startupDelay != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LegoOmni::GetInstance()->CreateBackgroundAudio();
|
|
||||||
BackgroundAudioManager()->Enable(this->m_useMusic);
|
|
||||||
|
|
||||||
MxStreamController *stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", 0);
|
|
||||||
MxDSAction ds;
|
|
||||||
|
|
||||||
if (!stream) {
|
|
||||||
stream = Streamer()->Open("\\lego\\scripts\\nocd", 0);
|
|
||||||
if (!stream) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ds.SetAtomId(stream->atom);
|
|
||||||
ds.SetUnknown24(0xFFFF);
|
|
||||||
ds.SetUnknown1c(0);
|
|
||||||
VideoManager()->EnableFullScreenMovie(TRUE, TRUE);
|
|
||||||
|
|
||||||
if (Start(&ds) != SUCCESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ds.SetAtomId(stream->atom);
|
|
||||||
ds.SetUnknown24(0xFFFF);
|
|
||||||
ds.SetUnknown1c(0);
|
|
||||||
if (Start(&ds) != SUCCESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->m_gameStarted = 1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sleepIfNotNextFrame == 0) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sleep(0);
|
|
||||||
}
|
|
||||||
|
|||||||
68
ISLE/isle.h
68
ISLE/isle.h
@ -1,8 +1,10 @@
|
|||||||
#ifndef ISLE_H
|
#ifndef ISLE_H
|
||||||
#define ISLE_H
|
#define ISLE_H
|
||||||
|
|
||||||
#include <windows.h>
|
#include "legoinc.h"
|
||||||
|
#include "define.h"
|
||||||
|
|
||||||
|
#include "legoomni.h"
|
||||||
#include "mxresult.h"
|
#include "mxresult.h"
|
||||||
#include "mxvideoparam.h"
|
#include "mxvideoparam.h"
|
||||||
|
|
||||||
@ -77,4 +79,68 @@ class Isle
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// OFFSET: ISLE 0x402c20
|
||||||
|
inline void Isle::Tick(BOOL sleepIfNotNextFrame)
|
||||||
|
{
|
||||||
|
if (this->m_windowActive) {
|
||||||
|
if (!Lego()) return;
|
||||||
|
if (!TickleManager()) return;
|
||||||
|
if (!Timer()) return;
|
||||||
|
|
||||||
|
long currentTime = Timer()->GetRealTime();
|
||||||
|
if (currentTime < g_lastFrameTime) {
|
||||||
|
g_lastFrameTime = -this->m_frameDelta;
|
||||||
|
}
|
||||||
|
if (this->m_frameDelta + g_lastFrameTime < currentTime) {
|
||||||
|
if (!Lego()->vtable40()) {
|
||||||
|
TickleManager()->Tickle();
|
||||||
|
}
|
||||||
|
g_lastFrameTime = currentTime;
|
||||||
|
|
||||||
|
if (g_startupDelay == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_startupDelay--;
|
||||||
|
if (g_startupDelay != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LegoOmni::GetInstance()->CreateBackgroundAudio();
|
||||||
|
BackgroundAudioManager()->Enable(this->m_useMusic);
|
||||||
|
|
||||||
|
MxStreamController *stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", 0);
|
||||||
|
MxDSAction ds;
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
stream = Streamer()->Open("\\lego\\scripts\\nocd", 0);
|
||||||
|
if (!stream) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.SetAtomId(stream->atom);
|
||||||
|
ds.SetUnknown24(-1);
|
||||||
|
ds.SetUnknown1c(0);
|
||||||
|
VideoManager()->EnableFullScreenMovie(TRUE, TRUE);
|
||||||
|
|
||||||
|
if (Start(&ds) != SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ds.SetAtomId(stream->atom);
|
||||||
|
ds.SetUnknown24(-1);
|
||||||
|
ds.SetUnknown1c(0);
|
||||||
|
if (Start(&ds) != SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->m_gameStarted = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sleepIfNotNextFrame == 0) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ISLE_H
|
#endif // ISLE_H
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
#include <dsound.h>
|
#include <dsound.h>
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
|
#include "legoinc.h"
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
#include "isle.h"
|
|
||||||
#include "legoomni.h"
|
#include "legoomni.h"
|
||||||
|
#include "isle.h"
|
||||||
|
|
||||||
// OFFSET: ISLE 0x401ca0
|
// OFFSET: ISLE 0x401ca0
|
||||||
BOOL FindExistingInstance(void)
|
BOOL FindExistingInstance(void)
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
#include "mxdsobject.h"
|
|
||||||
|
|
||||||
// OFFSET: ISLE 0x00401c40
|
|
||||||
void MxDSObject::SetAtomId(MxAtomId p_atomId)
|
|
||||||
{
|
|
||||||
this->m_atomId = p_atomId;
|
|
||||||
}
|
|
||||||
@ -6,14 +6,11 @@
|
|||||||
// OFFSET: LEGO1 0x100bf6a0
|
// OFFSET: LEGO1 0x100bf6a0
|
||||||
MxDSObject::MxDSObject()
|
MxDSObject::MxDSObject()
|
||||||
{
|
{
|
||||||
// The following code yields 100% matching assembly if m_unk24 is declared as (signed) short.
|
|
||||||
// However, in other areas m_unk24 (notably, ISLE.EXE) is treated as unsigned short.
|
|
||||||
// Since we don't have a proper solution yet, we are using a union to work around this discrepancy.
|
|
||||||
this->m_unk0c = 0;
|
this->m_unk0c = 0;
|
||||||
this->m_unk10 = 0;
|
this->m_unk10 = 0;
|
||||||
this->m_unk14 = 0;
|
this->m_unk14 = 0;
|
||||||
this->m_name = NULL;
|
this->m_name = NULL;
|
||||||
this->m_unk24signed = -1;
|
this->m_unk24 = -1;
|
||||||
this->m_unk1c = -1;
|
this->m_unk1c = -1;
|
||||||
this->m_unk28 = 0;
|
this->m_unk28 = 0;
|
||||||
}
|
}
|
||||||
@ -37,9 +34,3 @@ void MxDSObject::SetObjectName(const char *p_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10005530
|
|
||||||
void MxDSObject::SetAtomId(MxAtomId p_atomId)
|
|
||||||
{
|
|
||||||
this->m_atomId = p_atomId;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -15,9 +15,11 @@ class MxDSObject : public MxCore
|
|||||||
inline int GetUnknown1c() { return this->m_unk1c; }
|
inline int GetUnknown1c() { return this->m_unk1c; }
|
||||||
|
|
||||||
inline void SetUnknown1c(int p_unk1c) { this->m_unk1c = p_unk1c; }
|
inline void SetUnknown1c(int p_unk1c) { this->m_unk1c = p_unk1c; }
|
||||||
inline void SetUnknown24(unsigned short p_unk24) { this->m_unk24 = p_unk24; }
|
inline void SetUnknown24(short p_unk24) { this->m_unk24 = p_unk24; }
|
||||||
|
|
||||||
void SetAtomId(MxAtomId p_atomId);
|
// OFFSET: ISLE 0x401c40
|
||||||
|
// OFFSET: LEGO1 0x10005530
|
||||||
|
inline void SetAtomId(MxAtomId p_atomId) { this->m_atomId = p_atomId; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_unk08;
|
int m_unk08;
|
||||||
@ -27,13 +29,7 @@ class MxDSObject : public MxCore
|
|||||||
char *m_name;
|
char *m_name;
|
||||||
int m_unk1c;
|
int m_unk1c;
|
||||||
MxAtomId m_atomId;
|
MxAtomId m_atomId;
|
||||||
// So far, implementing MxDSObject::MxDSObject correctly required that m_unk24 is declared a (signed) short.
|
short m_unk24;
|
||||||
// Most of the other game's code appears to treat it as unsigned short, however.
|
|
||||||
// This union is a workaround until we have figured this out.
|
|
||||||
union {
|
|
||||||
unsigned short m_unk24;
|
|
||||||
short m_unk24signed;
|
|
||||||
};
|
|
||||||
unsigned short m_unk26;
|
unsigned short m_unk26;
|
||||||
int m_unk28;
|
int m_unk28;
|
||||||
};
|
};
|
||||||
|
|||||||
137
isle.mak
137
isle.mak
@ -288,7 +288,6 @@ CLEAN :
|
|||||||
-@erase "$(INTDIR)\isle.obj"
|
-@erase "$(INTDIR)\isle.obj"
|
||||||
-@erase "$(INTDIR)\isle.res"
|
-@erase "$(INTDIR)\isle.res"
|
||||||
-@erase "$(INTDIR)\main.obj"
|
-@erase "$(INTDIR)\main.obj"
|
||||||
-@erase "$(INTDIR)\mx.obj"
|
|
||||||
-@erase "$(INTDIR)\vc40.pdb"
|
-@erase "$(INTDIR)\vc40.pdb"
|
||||||
-@erase ".\Release\ISLE.EXE"
|
-@erase ".\Release\ISLE.EXE"
|
||||||
-@erase ".\Release\ISLE.PDB"
|
-@erase ".\Release\ISLE.PDB"
|
||||||
@ -350,7 +349,6 @@ LINK32_OBJS= \
|
|||||||
"$(INTDIR)\isle.obj" \
|
"$(INTDIR)\isle.obj" \
|
||||||
"$(INTDIR)\isle.res" \
|
"$(INTDIR)\isle.res" \
|
||||||
"$(INTDIR)\main.obj" \
|
"$(INTDIR)\main.obj" \
|
||||||
"$(INTDIR)\mx.obj" \
|
|
||||||
".\Release\LEGO1.LIB"
|
".\Release\LEGO1.LIB"
|
||||||
|
|
||||||
".\Release\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
|
".\Release\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
|
||||||
@ -380,7 +378,6 @@ CLEAN :
|
|||||||
-@erase "$(INTDIR)\isle.obj"
|
-@erase "$(INTDIR)\isle.obj"
|
||||||
-@erase "$(INTDIR)\isle.res"
|
-@erase "$(INTDIR)\isle.res"
|
||||||
-@erase "$(INTDIR)\main.obj"
|
-@erase "$(INTDIR)\main.obj"
|
||||||
-@erase "$(INTDIR)\mx.obj"
|
|
||||||
-@erase "$(INTDIR)\vc40.idb"
|
-@erase "$(INTDIR)\vc40.idb"
|
||||||
-@erase "$(INTDIR)\vc40.pdb"
|
-@erase "$(INTDIR)\vc40.pdb"
|
||||||
-@erase ".\Debug\ISLE.EXE"
|
-@erase ".\Debug\ISLE.EXE"
|
||||||
@ -444,7 +441,6 @@ LINK32_OBJS= \
|
|||||||
"$(INTDIR)\isle.obj" \
|
"$(INTDIR)\isle.obj" \
|
||||||
"$(INTDIR)\isle.res" \
|
"$(INTDIR)\isle.res" \
|
||||||
"$(INTDIR)\main.obj" \
|
"$(INTDIR)\main.obj" \
|
||||||
"$(INTDIR)\mx.obj" \
|
|
||||||
".\LEGO1\Debug\LEGO1.lib"
|
".\LEGO1\Debug\LEGO1.lib"
|
||||||
|
|
||||||
".\Debug\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
|
".\Debug\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
|
||||||
@ -551,6 +547,7 @@ DEP_CPP_LEGOO=\
|
|||||||
|
|
||||||
SOURCE=.\LEGO1\mxcriticalsection.cpp
|
SOURCE=.\LEGO1\mxcriticalsection.cpp
|
||||||
DEP_CPP_MXCRI=\
|
DEP_CPP_MXCRI=\
|
||||||
|
".\LEGO1\legoinc.h"\
|
||||||
".\LEGO1\mxcriticalsection.h"\
|
".\LEGO1\mxcriticalsection.h"\
|
||||||
|
|
||||||
|
|
||||||
@ -564,6 +561,7 @@ DEP_CPP_MXCRI=\
|
|||||||
|
|
||||||
SOURCE=.\LEGO1\mxautolocker.cpp
|
SOURCE=.\LEGO1\mxautolocker.cpp
|
||||||
DEP_CPP_MXAUT=\
|
DEP_CPP_MXAUT=\
|
||||||
|
".\LEGO1\legoinc.h"\
|
||||||
".\LEGO1\mxautolocker.h"\
|
".\LEGO1\mxautolocker.h"\
|
||||||
".\LEGO1\mxcriticalsection.h"\
|
".\LEGO1\mxcriticalsection.h"\
|
||||||
|
|
||||||
@ -850,9 +848,6 @@ DEP_CPP_DEFIN=\
|
|||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\ISLE\isle.cpp
|
SOURCE=.\ISLE\isle.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "ISLE - Win32 Release"
|
|
||||||
|
|
||||||
DEP_CPP_ISLE_=\
|
DEP_CPP_ISLE_=\
|
||||||
".\ISLE\define.h"\
|
".\ISLE\define.h"\
|
||||||
".\ISLE\isle.h"\
|
".\ISLE\isle.h"\
|
||||||
@ -910,72 +905,11 @@ DEP_CPP_ISLE_=\
|
|||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||||
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "ISLE - Win32 Debug"
|
|
||||||
|
|
||||||
DEP_CPP_ISLE_=\
|
|
||||||
".\ISLE\define.h"\
|
|
||||||
".\ISLE\isle.h"\
|
|
||||||
".\ISLE\res\resource.h"\
|
|
||||||
".\LEGO1\lego3dmanager.h"\
|
|
||||||
".\LEGO1\lego3dview.h"\
|
|
||||||
".\LEGO1\legoanimationmanager.h"\
|
|
||||||
".\LEGO1\legobuildingmanager.h"\
|
|
||||||
".\LEGO1\legoentity.h"\
|
|
||||||
".\LEGO1\legogamestate.h"\
|
|
||||||
".\LEGO1\legoinc.h"\
|
|
||||||
".\LEGO1\legoinputmanager.h"\
|
|
||||||
".\LEGO1\legomodelpresenter.h"\
|
|
||||||
".\LEGO1\legonavcontroller.h"\
|
|
||||||
".\LEGO1\legoomni.h"\
|
|
||||||
".\LEGO1\legopartpresenter.h"\
|
|
||||||
".\LEGO1\legoroi.h"\
|
|
||||||
".\LEGO1\legovideomanager.h"\
|
|
||||||
".\LEGO1\legoworldpresenter.h"\
|
|
||||||
".\LEGO1\mxatomid.h"\
|
|
||||||
".\LEGO1\mxbackgroundaudiomanager.h"\
|
|
||||||
".\LEGO1\mxbool.h"\
|
|
||||||
".\LEGO1\mxcore.h"\
|
|
||||||
".\LEGO1\mxcriticalsection.h"\
|
|
||||||
".\LEGO1\mxdirectdraw.h"\
|
|
||||||
".\LEGO1\mxdsaction.h"\
|
|
||||||
".\LEGO1\mxdsfile.h"\
|
|
||||||
".\LEGO1\mxdsobject.h"\
|
|
||||||
".\LEGO1\mxeventmanager.h"\
|
|
||||||
".\LEGO1\mxmusicmanager.h"\
|
|
||||||
".\LEGO1\mxnotificationmanager.h"\
|
|
||||||
".\LEGO1\mxobjectfactory.h"\
|
|
||||||
".\LEGO1\mxomni.h"\
|
|
||||||
".\LEGO1\mxomnicreateflags.h"\
|
|
||||||
".\LEGO1\mxomnicreateparam.h"\
|
|
||||||
".\LEGO1\mxomnicreateparambase.h"\
|
|
||||||
".\LEGO1\mxresult.h"\
|
|
||||||
".\LEGO1\mxsoundmanager.h"\
|
|
||||||
".\LEGO1\mxstreamcontroller.h"\
|
|
||||||
".\LEGO1\mxstreamer.h"\
|
|
||||||
".\LEGO1\mxstring.h"\
|
|
||||||
".\LEGO1\mxticklemanager.h"\
|
|
||||||
".\LEGO1\mxtimer.h"\
|
|
||||||
".\LEGO1\mxtransitionmanager.h"\
|
|
||||||
".\LEGO1\mxvariabletable.h"\
|
|
||||||
".\LEGO1\mxvideomanager.h"\
|
|
||||||
".\LEGO1\mxvideoparam.h"\
|
|
||||||
".\LEGO1\viewmanager.h"\
|
|
||||||
|
|
||||||
|
|
||||||
"$(INTDIR)\isle.obj" : $(SOURCE) $(DEP_CPP_ISLE_) "$(INTDIR)"
|
|
||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
|
||||||
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# End Source File
|
# End Source File
|
||||||
################################################################################
|
################################################################################
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\ISLE\main.cpp
|
SOURCE=.\ISLE\main.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "ISLE - Win32 Release"
|
|
||||||
|
|
||||||
DEP_CPP_MAIN_=\
|
DEP_CPP_MAIN_=\
|
||||||
".\ISLE\define.h"\
|
".\ISLE\define.h"\
|
||||||
".\ISLE\isle.h"\
|
".\ISLE\isle.h"\
|
||||||
@ -1026,57 +960,6 @@ DEP_CPP_MAIN_=\
|
|||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||||
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "ISLE - Win32 Debug"
|
|
||||||
|
|
||||||
DEP_CPP_MAIN_=\
|
|
||||||
".\ISLE\define.h"\
|
|
||||||
".\ISLE\isle.h"\
|
|
||||||
".\LEGO1\lego3dmanager.h"\
|
|
||||||
".\LEGO1\lego3dview.h"\
|
|
||||||
".\LEGO1\legoentity.h"\
|
|
||||||
".\LEGO1\legogamestate.h"\
|
|
||||||
".\LEGO1\legoinc.h"\
|
|
||||||
".\LEGO1\legoinputmanager.h"\
|
|
||||||
".\LEGO1\legonavcontroller.h"\
|
|
||||||
".\LEGO1\legoomni.h"\
|
|
||||||
".\LEGO1\legoroi.h"\
|
|
||||||
".\LEGO1\legovideomanager.h"\
|
|
||||||
".\LEGO1\mxatomid.h"\
|
|
||||||
".\LEGO1\mxbackgroundaudiomanager.h"\
|
|
||||||
".\LEGO1\mxbool.h"\
|
|
||||||
".\LEGO1\mxcore.h"\
|
|
||||||
".\LEGO1\mxcriticalsection.h"\
|
|
||||||
".\LEGO1\mxdsaction.h"\
|
|
||||||
".\LEGO1\mxdsfile.h"\
|
|
||||||
".\LEGO1\mxdsobject.h"\
|
|
||||||
".\LEGO1\mxeventmanager.h"\
|
|
||||||
".\LEGO1\mxmusicmanager.h"\
|
|
||||||
".\LEGO1\mxnotificationmanager.h"\
|
|
||||||
".\LEGO1\mxobjectfactory.h"\
|
|
||||||
".\LEGO1\mxomni.h"\
|
|
||||||
".\LEGO1\mxomnicreateflags.h"\
|
|
||||||
".\LEGO1\mxomnicreateparam.h"\
|
|
||||||
".\LEGO1\mxomnicreateparambase.h"\
|
|
||||||
".\LEGO1\mxresult.h"\
|
|
||||||
".\LEGO1\mxsoundmanager.h"\
|
|
||||||
".\LEGO1\mxstreamcontroller.h"\
|
|
||||||
".\LEGO1\mxstreamer.h"\
|
|
||||||
".\LEGO1\mxstring.h"\
|
|
||||||
".\LEGO1\mxticklemanager.h"\
|
|
||||||
".\LEGO1\mxtimer.h"\
|
|
||||||
".\LEGO1\mxtransitionmanager.h"\
|
|
||||||
".\LEGO1\mxvariabletable.h"\
|
|
||||||
".\LEGO1\mxvideomanager.h"\
|
|
||||||
".\LEGO1\mxvideoparam.h"\
|
|
||||||
".\LEGO1\viewmanager.h"\
|
|
||||||
|
|
||||||
|
|
||||||
"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)"
|
|
||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
|
||||||
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# End Source File
|
# End Source File
|
||||||
################################################################################
|
################################################################################
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@ -1517,22 +1400,6 @@ SOURCE=.\LEGO1\mxvideoparamflags.h
|
|||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# End Project Dependency
|
# End Project Dependency
|
||||||
################################################################################
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ISLE\mx.cpp
|
|
||||||
DEP_CPP_MX_CP=\
|
|
||||||
".\LEGO1\mxatomid.h"\
|
|
||||||
".\LEGO1\mxbool.h"\
|
|
||||||
".\LEGO1\mxcore.h"\
|
|
||||||
".\LEGO1\mxdsobject.h"\
|
|
||||||
|
|
||||||
|
|
||||||
"$(INTDIR)\mx.obj" : $(SOURCE) $(DEP_CPP_MX_CP) "$(INTDIR)"
|
|
||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
|
||||||
|
|
||||||
|
|
||||||
# End Source File
|
|
||||||
# End Target
|
# End Target
|
||||||
# End Project
|
# End Project
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
from capstone import *
|
from capstone import *
|
||||||
import difflib
|
import difflib
|
||||||
import struct
|
import struct
|
||||||
@ -7,60 +8,40 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
def print_usage():
|
parser = argparse.ArgumentParser(allow_abbrev=False,
|
||||||
print('Usage: %s [options] <original-binary> <recompiled-binary> <recompiled-pdb> <decomp-dir>\n' % sys.argv[0])
|
description='Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.')
|
||||||
print('\t-v, --verbose <offset>\t\t\tPrint assembly diff for specific function (original file\'s offset)')
|
parser.add_argument('original', metavar='original-binary', help='The original binary')
|
||||||
print('\t-h, --html <output-file>\t\t\tGenerate searchable HTML summary of status and diffs')
|
parser.add_argument('recompiled', metavar='recompiled-binary', help='The recompiled binary')
|
||||||
sys.exit(1)
|
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('--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')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
positional_args = []
|
|
||||||
verbose = None
|
verbose = None
|
||||||
skip = False
|
if args.verbose:
|
||||||
html = None
|
try:
|
||||||
|
verbose = int(args.verbose, 16)
|
||||||
|
except ValueError:
|
||||||
|
parser.error('invalid verbose argument')
|
||||||
|
html = args.html
|
||||||
|
|
||||||
for i, arg in enumerate(sys.argv):
|
original = args.original
|
||||||
if skip:
|
|
||||||
skip = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
if arg.startswith('-'):
|
|
||||||
# A flag rather than a positional arg
|
|
||||||
flag = arg[1:]
|
|
||||||
|
|
||||||
if flag == 'v' or flag == '-verbose':
|
|
||||||
verbose = int(sys.argv[i + 1], 16)
|
|
||||||
skip = True
|
|
||||||
elif flag == 'h' or flag == '-html':
|
|
||||||
html = sys.argv[i + 1]
|
|
||||||
skip = True
|
|
||||||
else:
|
|
||||||
print('Unknown flag: %s' % arg)
|
|
||||||
print_usage()
|
|
||||||
else:
|
|
||||||
positional_args.append(arg)
|
|
||||||
|
|
||||||
if len(positional_args) != 5:
|
|
||||||
print_usage()
|
|
||||||
|
|
||||||
original = positional_args[1]
|
|
||||||
if not os.path.isfile(original):
|
if not os.path.isfile(original):
|
||||||
print('Invalid input: Original binary does not exist')
|
parser.error('Original binary does not exist')
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
recomp = positional_args[2]
|
recomp = args.recompiled
|
||||||
if not os.path.isfile(recomp):
|
if not os.path.isfile(recomp):
|
||||||
print('Invalid input: Recompiled binary does not exist')
|
parser.error('Recompiled binary does not exist')
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
syms = positional_args[3]
|
syms = args.pdb
|
||||||
if not os.path.isfile(syms):
|
if not os.path.isfile(syms):
|
||||||
print('Invalid input: Symbols PDB does not exist')
|
parser.error('Symbols PDB does not exist')
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
source = positional_args[4]
|
source = args.decomp_dir
|
||||||
if not os.path.isdir(source):
|
if not os.path.isdir(source):
|
||||||
print('Invalid input: Source directory does not exist')
|
parser.error('Source directory does not exist')
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Declare a class that can automatically convert virtual executable addresses
|
# Declare a class that can automatically convert virtual executable addresses
|
||||||
# to file addresses
|
# to file addresses
|
||||||
@ -137,14 +118,23 @@ def __init__(self, pdb, file):
|
|||||||
if current_section == 'SYMBOLS' and 'S_GPROC32' in line:
|
if current_section == 'SYMBOLS' and 'S_GPROC32' in line:
|
||||||
addr = int(line[26:34], 16)
|
addr = int(line[26:34], 16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
info = RecompiledInfo()
|
||||||
|
info.addr = addr + recompfile.imagebase + recompfile.textvirt
|
||||||
|
|
||||||
|
use_dbg_offs = False
|
||||||
|
if use_dbg_offs:
|
||||||
debug_offs = line_dump[i + 2]
|
debug_offs = line_dump[i + 2]
|
||||||
debug_start = int(debug_offs[22:30], 16)
|
debug_start = int(debug_offs[22:30], 16)
|
||||||
debug_end = int(debug_offs[43:], 16)
|
debug_end = int(debug_offs[43:], 16)
|
||||||
|
|
||||||
info = RecompiledInfo()
|
|
||||||
info.addr = addr + recompfile.imagebase + recompfile.textvirt
|
|
||||||
info.start = debug_start
|
info.start = debug_start
|
||||||
info.size = debug_end - debug_start
|
info.size = debug_end - debug_start
|
||||||
|
else:
|
||||||
|
info.start = 0
|
||||||
|
info.size = int(line[41:49], 16)
|
||||||
|
|
||||||
info.name = line[77:]
|
info.name = line[77:]
|
||||||
|
|
||||||
self.funcs[addr] = info
|
self.funcs[addr] = info
|
||||||
@ -208,7 +198,14 @@ def get_recompiled_address(self, filename, line):
|
|||||||
def sanitize(file, mnemonic, op_str):
|
def sanitize(file, mnemonic, op_str):
|
||||||
offsetplaceholder = '<OFFSET>'
|
offsetplaceholder = '<OFFSET>'
|
||||||
|
|
||||||
if mnemonic == 'call' or mnemonic == 'jmp':
|
op_str_is_number = False
|
||||||
|
try:
|
||||||
|
int(op_str, 16)
|
||||||
|
op_str_is_number = True
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if (mnemonic == 'call' or mnemonic == 'jmp') and op_str_is_number:
|
||||||
# Filter out "calls" because the offsets we're not currently trying to
|
# Filter out "calls" because the offsets we're not currently trying to
|
||||||
# match offsets. As long as there's a call in the right place, it's
|
# match offsets. As long as there's a call in the right place, it's
|
||||||
# probably accurate.
|
# probably accurate.
|
||||||
@ -262,6 +259,10 @@ def parse_asm(file, addr, size):
|
|||||||
total_accuracy = 0
|
total_accuracy = 0
|
||||||
htmlinsert = []
|
htmlinsert = []
|
||||||
|
|
||||||
|
# Generate basename of original file, used in locating OFFSET lines
|
||||||
|
basename = os.path.basename(os.path.splitext(original)[0])
|
||||||
|
pattern = '// OFFSET:'
|
||||||
|
|
||||||
for subdir, dirs, files in os.walk(source):
|
for subdir, dirs, files in os.walk(source):
|
||||||
for file in files:
|
for file in files:
|
||||||
srcfilename = os.path.join(os.path.abspath(subdir), file)
|
srcfilename = os.path.join(os.path.abspath(subdir), file)
|
||||||
@ -276,9 +277,14 @@ def parse_asm(file, addr, size):
|
|||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
|
|
||||||
if line.startswith('// OFFSET:'):
|
line = line.strip()
|
||||||
par = line[10:].strip().split()
|
|
||||||
|
if line.startswith(pattern):
|
||||||
|
par = line[len(pattern):].strip().split()
|
||||||
module = par[0]
|
module = par[0]
|
||||||
|
if module != basename:
|
||||||
|
continue
|
||||||
|
|
||||||
addr = int(par[1], 16)
|
addr = int(par[1], 16)
|
||||||
|
|
||||||
find_open_bracket = line
|
find_open_bracket = line
|
||||||
@ -67,6 +67,12 @@
|
|||||||
#sortind {
|
#sortind {
|
||||||
margin: 0 0.5em;
|
margin: 0 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filters {
|
||||||
|
font-size: 10pt;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0.5em 0 1em 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
var data = [/* INSERT DATA HERE */];
|
var data = [/* INSERT DATA HERE */];
|
||||||
@ -115,18 +121,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filter(text) {
|
const filterOptions = { text: '', hidePerfect: false };
|
||||||
|
|
||||||
|
function filter() {
|
||||||
closeAllDiffs();
|
closeAllDiffs();
|
||||||
|
|
||||||
var ltext = text.toLowerCase();
|
var ltext = filterOptions.text.toLowerCase();
|
||||||
|
|
||||||
const collection = document.getElementsByClassName("funcrow");
|
const collection = document.getElementsByClassName("funcrow");
|
||||||
var searchCount = 0;
|
var searchCount = 0;
|
||||||
for (var ele of collection) {
|
for (var ele of collection) {
|
||||||
var eledata = data[ele.dataset.index];
|
var eledata = data[ele.dataset.index];
|
||||||
if (text == ''
|
|
||||||
|
const textOk = (ltext == ''
|
||||||
|| eledata.address.toLowerCase().includes(ltext)
|
|| eledata.address.toLowerCase().includes(ltext)
|
||||||
|| eledata.name.toLowerCase().includes(ltext)) {
|
|| eledata.name.toLowerCase().includes(ltext));
|
||||||
|
|
||||||
|
const perfOk = (!filterOptions.hidePerfect || (eledata.matching < 1));
|
||||||
|
|
||||||
|
if (textOk && perfOk) {
|
||||||
ele.style.display = '';
|
ele.style.display = '';
|
||||||
searchCount++;
|
searchCount++;
|
||||||
} else {
|
} else {
|
||||||
@ -219,9 +232,16 @@
|
|||||||
|
|
||||||
var search = document.getElementById('search');
|
var search = document.getElementById('search');
|
||||||
search.addEventListener('input', function (evt) {
|
search.addEventListener('input', function (evt) {
|
||||||
filter(search.value);
|
filterOptions.text = search.value;
|
||||||
|
filter();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cbHidePerfect = document.getElementById('cbHidePerfect');
|
||||||
|
cbHidePerfect.addEventListener('change', evt => {
|
||||||
|
filterOptions.hidePerfect = evt.target.checked;
|
||||||
|
filter();
|
||||||
|
})
|
||||||
|
|
||||||
sortByColumn(0);
|
sortByColumn(0);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -230,8 +250,10 @@
|
|||||||
<div class="main">
|
<div class="main">
|
||||||
<h1>Decompilation Status</h1>
|
<h1>Decompilation Status</h1>
|
||||||
<input id="search" type="search" placeholder="Search for offset or function name...">
|
<input id="search" type="search" placeholder="Search for offset or function name...">
|
||||||
<br>
|
<div class="filters">
|
||||||
<br>
|
<label for="cbHidePerfect">Hide 100% match</label>
|
||||||
|
<input type="checkbox" id="cbHidePerfect" />
|
||||||
|
</div>
|
||||||
<table id="listing">
|
<table id="listing">
|
||||||
<tr id='listingheader'><th style='width: 20%'>Address</th><th style="width:60%">Name</th><th style='width: 20%'>Matching</th></tr>
|
<tr id='listingheader'><th style='width: 20%'>Address</th><th style="width:60%">Name</th><th style='width: 20%'>Matching</th></tr>
|
||||||
</table>
|
</table>
|
||||||
Loading…
Reference in New Issue
Block a user