This commit is contained in:
Christian Semmler 2023-06-19 10:58:37 +02:00
commit c17054b13a
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
49 changed files with 1139 additions and 299 deletions

View File

@ -32,8 +32,7 @@ jobs:
C:\msys64\usr\bin\wget.exe https://archive.org/download/idx5sdk/idx5sdk.exe
7z x .\idx5sdk.exe
7z x .\DX5SDK.EXE
cd cdrom
- name: Cache DX5 SDK
if: steps.cache-dx5.outputs.cache-hit != 'true'
id: save-dx5
@ -41,19 +40,28 @@ jobs:
with:
path: dx5sdk
key: dx5sdk
- name: Setup DX5 SDK
run: |
cd dx5sdk
cd cdrom
.\SETUP.EXE /s
- name: Build
shell: cmd
run: |
call .\msvc420\bin\VCVARS32.BAT x86
mkdir Release
.\msvc420\bin\NMAKE.EXE /f isle.mak CFG="ISLE - Win32 Release"
- name: Summarize Accuracy
shell: cmd
run: |
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE
C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL
pip install capstone
python3 tools/reccomp/reccomp.py ISLE.EXE Release/ISLE.EXE Release/ISLE.PDB ISLE
python3 tools/reccomp/reccomp.py LEGO1.DLL Release/LEGO1.DLL Release/LEGO1.PDB LEGO1
- name: Upload Artifact
uses: actions/upload-artifact@master

31
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,31 @@
# Contributing
## Learning Decompilation
Generally, decompilation is a fairly advanced skill. If you aren't already familiar with it, it will likely take you months, or even years, to learn the skills necessary to do it (depending on your current proficiency with C/C++ and x86 assembly). If you're still interested, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from.
## Ghidra Server
For documenting the original binaries and generating pseudocode that we decompile with, we primarily use [Ghidra](https://ghidra-sre.org/) (it's free and open source). To help with collaboration, we have a shared Ghidra repository with all of our current work. It is available to the public but read-only; to contribute to it yourself, you'll need approval from a current maintainer.
To access the Ghidra repository, use the following details:
- Address: `server.mattkc.com`
- Port: `13100`
## Code Style
In general, we're not exhaustively strict about coding style, but there are some preferable guidelines to follow that have been adopted from what we know about the original codebase:
- Indent: 2 spaces
- `PascalCase` for classes and function names.
- `m_camelCase` for member variables.
- `g_camelCase` for global variables.
## Kinds of Contributions
This repository has only one goal: accuracy to the original executables. As such, we are not likely to accept pull requests that attempt to modernize the code, or improve compatibility in a newer compiler that ends up reducing compatibility in MSVC 4.20. Essentially, accuracy is king, everything else is secondary. For modernizations and enhancements, it's recommended to create a fork downstream from this one instead.
## Questions?
For any further questions, feel free to ask in either the [Matrix chatroom](https://matrix.to/#/#isledecomp:matrix.org) or on the [forum](https://forum.mattkc.com/viewforum.php?f=1).

View File

@ -1,17 +1,43 @@
#include "define.h"
// 0x410030
Isle *g_isle = 0;
// 0x410034
unsigned char g_mousedown = 0;
// 0x410038
unsigned char g_mousemoved = 0;
// 0x41003c
int g_closed = 0;
const char *WINDOW_TITLE = "LEGO\xAE";
// 0x410040
RECT g_windowRect = {0, 0, 640, 480};
unsigned char g_mousedown = 0;
unsigned char g_mousemoved = 0;
// 0x410050
int g_rmDisabled = 0;
// 0x410054
int g_waitingForTargetDepth = 1;
// 0x410058
int g_targetWidth = 640;
// 0x41005c
int g_targetHeight = 480;
// 0x410060
unsigned int g_targetDepth = 16;
// 0x410064
int g_reqEnableRMDevice = 0;
// 0x4101bc
int g_startupDelay = 200;
// 0x4101c0
long g_lastFrameTime = 0;
// 0x4101dc
const char *WINDOW_TITLE = "LEGO\xAE";

View File

@ -1,6 +1,8 @@
#ifndef DEFINE_H
#define DEFINE_H
#include <Windows.h>
class Isle;
extern Isle *g_isle;
@ -9,6 +11,7 @@ extern int g_closed;
extern const char *WINDOW_TITLE;
extern unsigned char g_mousedown;
extern unsigned char g_mousemoved;
extern RECT g_windowRect;
extern int g_rmDisabled;
extern int g_waitingForTargetDepth;
extern int g_targetWidth;

View File

@ -1,14 +1,18 @@
#include "isle.h"
#include "define.h"
#include "legoanimationmanager.h"
#include "legobuildingmanager.h"
#include "legomodelpresenter.h"
#include "legoomni.h"
#include "legopartpresenter.h"
#include "legoworldpresenter.h"
#include "mxdirectdraw.h"
#include "mxdsaction.h"
#include "mxomni.h"
#include "res/resource.h"
RECT windowRect = {0, 0, 640, 480};
// OFFSET: ISLE 0x401000
Isle::Isle()
{
m_hdPath = NULL;
@ -51,10 +55,11 @@ Isle::Isle()
LegoOmni::CreateInstance();
}
// OFFSET: ISLE 0x4011a0
Isle::~Isle()
{
if (LegoOmni::GetInstance()) {
close();
Close();
MxOmni::DestroyInstance();
}
@ -75,7 +80,8 @@ Isle::~Isle()
}
}
void Isle::close()
// OFFSET: ISLE 0x401260
void Isle::Close()
{
MxDSAction ds;
@ -108,7 +114,8 @@ void Isle::close()
}
}
BOOL readReg(LPCSTR name, LPSTR outValue, DWORD outSize)
// OFFSET: ISLE 0x402740
BOOL ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize)
{
HKEY hKey;
DWORD valueType;
@ -126,11 +133,12 @@ BOOL readReg(LPCSTR name, LPSTR outValue, DWORD outSize)
return out;
}
int readRegBool(LPCSTR name, BOOL *out)
// OFFSET: ISLE 0x4027b0
int ReadRegBool(LPCSTR name, BOOL *out)
{
char buffer[256];
BOOL read = readReg(name, buffer, 0x100);
BOOL read = ReadReg(name, buffer, sizeof(buffer));
if (read) {
if (strcmp("YES", buffer) == 0) {
*out = TRUE;
@ -145,11 +153,12 @@ int readRegBool(LPCSTR name, BOOL *out)
return FALSE;
}
int readRegInt(LPCSTR name, int *out)
// OFFSET: ISLE 0x402880
int ReadRegInt(LPCSTR name, int *out)
{
char buffer[256];
if (readReg(name, buffer, 0x100)) {
if (ReadReg(name, buffer, sizeof(buffer))) {
*out = atoi(buffer);
return TRUE;
}
@ -157,13 +166,12 @@ int readRegInt(LPCSTR name, int *out)
return FALSE;
}
void Isle::loadConfig()
// OFFSET: ISLE 0x4028d0
void Isle::LoadConfig()
{
#define BUFFER_SIZE 1024
char buffer[1024];
char buffer[BUFFER_SIZE];
if (!readReg("diskpath", buffer, BUFFER_SIZE)) {
if (!ReadReg("diskpath", buffer, sizeof(buffer))) {
strcpy(buffer, MxOmni::GetHD());
}
@ -171,7 +179,7 @@ void Isle::loadConfig()
strcpy(m_hdPath, buffer);
MxOmni::SetHD(m_hdPath);
if (!readReg("cdpath", buffer, BUFFER_SIZE)) {
if (!ReadReg("cdpath", buffer, sizeof(buffer))) {
strcpy(buffer, MxOmni::GetCD());
}
@ -179,22 +187,22 @@ void Isle::loadConfig()
strcpy(m_cdPath, buffer);
MxOmni::SetCD(m_cdPath);
readRegBool("Flip Surfaces", &m_flipSurfaces);
readRegBool("Full Screen", &m_fullScreen);
readRegBool("Wide View Angle", &m_wideViewAngle);
readRegBool("3DSound", &m_use3dSound);
readRegBool("Music", &m_useMusic);
readRegBool("UseJoystick", &m_useJoystick);
readRegInt("JoystickIndex", &m_joystickIndex);
readRegBool("Draw Cursor", &m_drawCursor);
ReadRegBool("Flip Surfaces", &m_flipSurfaces);
ReadRegBool("Full Screen", &m_fullScreen);
ReadRegBool("Wide View Angle", &m_wideViewAngle);
ReadRegBool("3DSound", &m_use3dSound);
ReadRegBool("Music", &m_useMusic);
ReadRegBool("UseJoystick", &m_useJoystick);
ReadRegInt("JoystickIndex", &m_joystickIndex);
ReadRegBool("Draw Cursor", &m_drawCursor);
int backBuffersInVRAM;
if (readRegBool("Back Buffers in Video RAM",&backBuffersInVRAM)) {
if (ReadRegBool("Back Buffers in Video RAM",&backBuffersInVRAM)) {
m_backBuffersInVram = !backBuffersInVRAM;
}
int bitDepth;
if (readRegInt("Display Bit Depth", &bitDepth)) {
if (ReadRegInt("Display Bit Depth", &bitDepth)) {
if (bitDepth == 8) {
m_using8bit = TRUE;
} else if (bitDepth == 16) {
@ -202,28 +210,29 @@ void Isle::loadConfig()
}
}
if (!readReg("Island Quality", buffer, BUFFER_SIZE)) {
if (!ReadReg("Island Quality", buffer, sizeof(buffer))) {
strcpy(buffer, "1");
}
m_islandQuality = atoi(buffer);
if (!readReg("Island Texture", buffer, BUFFER_SIZE)) {
if (!ReadReg("Island Texture", buffer, sizeof(buffer))) {
strcpy(buffer, "1");
}
m_islandTexture = atoi(buffer);
if (readReg("3D Device ID", buffer, BUFFER_SIZE)) {
if (ReadReg("3D Device ID", buffer, sizeof(buffer))) {
m_deviceId = new char[strlen(buffer) + 1];
strcpy(m_deviceId, buffer);
}
if (readReg("savepath", buffer, BUFFER_SIZE)) {
if (ReadReg("savepath", buffer, sizeof(buffer))) {
m_savePath = new char[strlen(buffer) + 1];
strcpy(m_savePath, buffer);
}
}
void Isle::setupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
// OFFSET: ISLE 0x401560
void Isle::SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
BOOL using8bit, BOOL m_using16bit, BOOL param_6, BOOL param_7,
BOOL wideViewAngle, char *deviceId)
{
@ -243,10 +252,11 @@ void Isle::setupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
}
}
BOOL Isle::setupLegoOmni()
// OFFSET: ISLE 0x4013b0
BOOL Isle::SetupLegoOmni()
{
char mediaPath[256];
GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, 256);
GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, sizeof(mediaPath));
if (Lego()->Create(MxOmniCreateParam(mediaPath, (struct HWND__ *) m_windowHandle, m_videoParam, MxOmniCreateFlags())) != FAILURE) {
VariableTable()->SetVariable("ACTOR_01", "");
@ -257,7 +267,8 @@ BOOL Isle::setupLegoOmni()
return FALSE;
}
void Isle::setupCursor(WPARAM wParam)
// OFFSET: ISLE 0x402e80
void Isle::SetupCursor(WPARAM wParam)
{
switch (wParam) {
case 0:
@ -277,6 +288,7 @@ void Isle::setupCursor(WPARAM wParam)
SetCursor(m_cursorCurrent);
}
// OFFSET: ISLE 0x401d20
LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!g_isle) {
@ -291,9 +303,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_ACTIVATEAPP:
if (g_isle) {
if ((wParam != 0) && (g_isle->m_fullScreen)) {
MoveWindow(hWnd, windowRect.left, windowRect.top,
(windowRect.right - windowRect.left) + 1,
(windowRect.bottom - windowRect.top) + 1, TRUE);
MoveWindow(hWnd, g_windowRect.left, g_windowRect.top,
(g_windowRect.right - g_windowRect.left) + 1,
(g_windowRect.bottom - g_windowRect.top) + 1, TRUE);
}
g_isle->m_windowActive = wParam;
}
@ -312,10 +324,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MINMAXINFO *mmi = (MINMAXINFO *) lParam;
mmi->ptMaxTrackSize.x = (windowRect.right - windowRect.left) + 1;
mmi->ptMaxTrackSize.y = (windowRect.bottom - windowRect.top) + 1;
mmi->ptMinTrackSize.x = (windowRect.right - windowRect.left) + 1;
mmi->ptMinTrackSize.y = (windowRect.bottom - windowRect.top) + 1;
mmi->ptMaxTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1;
mmi->ptMaxTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1;
mmi->ptMinTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1;
mmi->ptMinTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1;
return 0;
}
@ -338,13 +350,13 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
return DefWindowProcA(hWnd,WM_SYSCOMMAND,wParam,lParam);
case WM_EXITMENULOOP:
return DefWindowProcA(hWnd,WM_EXITMENULOOP,wParam,lParam);
return DefWindowProcA(hWnd, WM_EXITMENULOOP, wParam, lParam);
case WM_MOVING:
if (g_isle && g_isle->m_fullScreen) {
GetWindowRect(hWnd, (LPRECT) lParam);
return 0;
}
return DefWindowProcA(hWnd,WM_MOVING,wParam,lParam);
return DefWindowProcA(hWnd, WM_MOVING, wParam, lParam);
case WM_NCPAINT:
if (g_isle && g_isle->m_fullScreen) {
return 0;
@ -386,8 +398,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg) {
case WM_KEYDOWN:
if (lParam & 0x40000000) {
return DefWindowProcA(hWnd,WM_KEYDOWN,wParam,lParam);
// While this probably should be (HIWORD(lParam) & KF_REPEAT), this seems
// to be what the assembly is actually doing
if (lParam & (KF_REPEAT << 16)) {
return DefWindowProcA(hWnd, WM_KEYDOWN, wParam, lParam);
}
keyCode = wParam;
type = KEYDOWN;
@ -418,7 +432,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
case 0x5400:
if (g_isle) {
g_isle->setupCursor(wParam);
g_isle->SetupCursor(wParam);
return 0;
}
}
@ -446,14 +460,15 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return DefWindowProcA(hWnd,uMsg,wParam,lParam);
}
MxResult Isle::setupWindow(HINSTANCE hInstance)
// OFFSET: ISLE 0x4023e0
MxResult Isle::SetupWindow(HINSTANCE hInstance)
{
WNDCLASSA wndclass;
ZeroMemory(&wndclass, sizeof(WNDCLASSA));
loadConfig();
LoadConfig();
setupVideoFlags(m_fullScreen, m_flipSurfaces, m_backBuffersInVram, m_using8bit,
SetupVideoFlags(m_fullScreen, m_flipSurfaces, m_backBuffersInVram, m_using8bit,
m_using16bit, m_unk24, FALSE, m_wideViewAngle, m_deviceId);
MxOmni::SetSound3D(m_use3dSound);
@ -485,21 +500,21 @@ MxResult Isle::setupWindow(HINSTANCE hInstance)
int x, y, width, height;
if (!m_fullScreen) {
AdjustWindowRectEx(&windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
height = windowRect.bottom - windowRect.top;
width = windowRect.right - windowRect.left;
height = g_windowRect.bottom - g_windowRect.top;
width = g_windowRect.right - g_windowRect.left;
y = CW_USEDEFAULT;
x = CW_USEDEFAULT;
dwStyle = WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
} else {
AdjustWindowRectEx(&windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
height = windowRect.bottom - windowRect.top;
width = windowRect.right - windowRect.left;
AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
height = g_windowRect.bottom - g_windowRect.top;
width = g_windowRect.right - g_windowRect.left;
dwStyle = WS_CAPTION | WS_SYSMENU;
x = windowRect.left;
y = windowRect.top;
x = g_windowRect.left;
y = g_windowRect.top;
}
m_windowHandle = CreateWindowExA(WS_EX_APPWINDOW, WNDCLASS_NAME, WINDOW_TITLE, dwStyle,
@ -509,12 +524,12 @@ MxResult Isle::setupWindow(HINSTANCE hInstance)
}
if (m_fullScreen) {
MoveWindow(m_windowHandle, windowRect.left, windowRect.top, (windowRect.right - windowRect.left) + 1, (windowRect.bottom - windowRect.top) + 1, TRUE);
MoveWindow(m_windowHandle, g_windowRect.left, g_windowRect.top, (g_windowRect.right - g_windowRect.left) + 1, (g_windowRect.bottom - g_windowRect.top) + 1, TRUE);
}
ShowWindow(m_windowHandle, SW_SHOWNORMAL);
UpdateWindow(m_windowHandle);
if (!setupLegoOmni()) {
if (!SetupLegoOmni()) {
return FAILURE;
}
@ -545,7 +560,7 @@ MxResult Isle::setupWindow(HINSTANCE hInstance)
}
}
if (m_fullScreen) {
MoveWindow(m_windowHandle, windowRect.left, windowRect.top, (windowRect.right - windowRect.left) + 1, (windowRect.bottom - windowRect.top) + 1, TRUE);
MoveWindow(m_windowHandle, g_windowRect.left, g_windowRect.top, (g_windowRect.right - g_windowRect.left) + 1, (g_windowRect.bottom - g_windowRect.top) + 1, TRUE);
}
ShowWindow(m_windowHandle, SW_SHOWNORMAL);
UpdateWindow(m_windowHandle);
@ -553,7 +568,8 @@ MxResult Isle::setupWindow(HINSTANCE hInstance)
return SUCCESS;
}
void Isle::tick(BOOL sleepIfNotNextFrame)
// OFFSET: ISLE 0x402c20
void Isle::Tick(BOOL sleepIfNotNextFrame)
{
if (this->m_windowActive) {
if (!Lego()) return;

View File

@ -1,7 +1,7 @@
#ifndef ISLE_H
#define ISLE_H
#include <Windows.h>
#include <windows.h>
#include "mxresult.h"
#include "mxvideoparam.h"
@ -12,21 +12,21 @@ class Isle
Isle();
~Isle();
static void close();
static void Close();
MxResult setupWindow(HINSTANCE hInstance);
MxResult SetupWindow(HINSTANCE hInstance);
void tick(BOOL sleepIfNotNextFrame);
void Tick(BOOL sleepIfNotNextFrame);
BOOL setupLegoOmni();
void loadConfig();
void setupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
BOOL SetupLegoOmni();
void LoadConfig();
void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
BOOL using8bit, BOOL m_using16bit, BOOL param_6, BOOL param_7,
BOOL wideViewAngle, char *deviceId);
void setupCursor(WPARAM wParam);
void SetupCursor(WPARAM wParam);
//private:
// private:
// 0
LPSTR m_hdPath;

View File

@ -1,11 +1,12 @@
#include <DSOUND.H>
#include <Windows.h>
#include <dsound.h>
#include <windows.h>
#include "define.h"
#include "isle.h"
#include "legoomni.h"
BOOL findExistingInstance(void)
// OFFSET: ISLE 0x401ca0
BOOL FindExistingInstance(void)
{
HWND hWnd = FindWindowA(WNDCLASS_NAME, WINDOW_TITLE);
if (hWnd) {
@ -17,9 +18,10 @@ BOOL findExistingInstance(void)
return 1;
}
BOOL startDirectSound(void)
// OFFSET: ISLE 0x401ce0
BOOL StartDirectSound(void)
{
LPDIRECTSOUND lpDS = 0;
LPDIRECTSOUND lpDS = NULL;
HRESULT ret = DirectSoundCreate(NULL, &lpDS, NULL);
if (ret == DS_OK && lpDS != NULL) {
lpDS->Release();
@ -29,17 +31,18 @@ BOOL startDirectSound(void)
return FALSE;
}
// OFFSET: ISLE 0x401610
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// Look for another instance, if we find one, bring it to the foreground instead
if (!findExistingInstance()) {
if (!FindExistingInstance()) {
return 0;
}
// Attempt to create DirectSound instance
BOOL soundReady = FALSE;
for (int i = 0; i < 20; i++) {
if (startDirectSound()) {
if (StartDirectSound()) {
soundReady = TRUE;
break;
}
@ -49,7 +52,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// Throw error if sound unavailable
if (!soundReady) {
MessageBoxA(NULL, "\"LEGO\xAE Island\" is not detecting a DirectSound compatible sound card. Please quit all other applications and try again.",
"Lego Island Error",0);
"Lego Island Error", MB_OK);
return 0;
}
@ -57,8 +60,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_isle = new Isle();
// Create window
if (g_isle->setupWindow(hInstance) != SUCCESS) {
MessageBoxA(NULL, "\"LEGO\xAE Island\" failed to start. Please quit all other applications and try again.", "LEGO\xAE Island Error",0);
if (g_isle->SetupWindow(hInstance) != SUCCESS) {
MessageBoxA(NULL, "\"LEGO\xAE Island\" failed to start. Please quit all other applications and try again.", "LEGO\xAE Island Error", MB_OK);
return 0;
}
@ -68,7 +71,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
window = g_isle->m_windowHandle;
}
// Load accelerator (this call actually achieves nothing - there is no "AppAccel" resource in the original - but we'll keep this for authenticity)
// Load accelerators (this call actually achieves nothing - there is no "AppAccel" resource in the original - but we'll keep this for authenticity)
// This line may actually be here because it's in DFVIEW, an example project that ships with
// MSVC420, and was such a clean example of a Win32 app, that it was later adapted
// into an "ExeSkeleton" sample for MSVC600. It's quite possible Mindscape derived
// this app from that example since they no longer had the luxury of the
// MFC AppWizard which we know they used for the frontend used during development (ISLEMFC.EXE, MAIN.EXE, et al.)
LoadAcceleratorsA(hInstance, "AppAccel");
MSG msg;
@ -76,12 +84,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
while (!g_closed) {
while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (g_isle) {
g_isle->tick(1);
g_isle->Tick(1);
}
}
if (g_isle) {
g_isle->tick(1);
g_isle->Tick(1);
}
if (g_closed) {
@ -121,7 +129,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
} else if (g_mousemoved) {
if (g_isle) {
g_isle->tick(0);
g_isle->Tick(0);
}
goto LAB_00401bc7;
}

Binary file not shown.

View File

@ -1,5 +1,6 @@
#include <Windows.h>
#include "legoinc.h"
// OFFSET: LEGO1 0x10091ee0
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return TRUE;

10
LEGO1/legoinc.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LEGOINC_H
#define LEGOINC_H
// It is recommended to include this over <windows.h> directly because this way
// we can undef stuff that might cause issues with our code.
#include <windows.h>
#undef GetClassName
#endif // LEGOINC_H

View File

@ -1,14 +1,16 @@
#ifndef LEGOINPUTMANAGER_H
#define LEGOINPUTMANAGER_H
#include "mxcore.h"
__declspec(dllexport) enum NotificationId
{
NONE = 0x0,
KEYDOWN = 0x7,
MOUSEUP = 0x8,
MOUSEDOWN = 0x9,
MOUSEMOVE = 0x10,
TIMER = 0xF
NONE = 0,
KEYDOWN = 7,
MOUSEUP = 8,
MOUSEDOWN = 9,
MOUSEMOVE = 10,
TIMER = 15
};
class LegoInputManager

View File

@ -1,22 +1,38 @@
#include "legonavcontroller.h"
int g_mouseDeadzone = 40;
float g_zeroThreshold = 0.001f;
float g_movementMaxSpeed = 40.0f;
float g_turnMaxSpeed = 20.0f;
float g_movementMaxAccel = 15.0f;
float g_turnMaxAccel = 30.0f;
float g_movementMinAccel = 4.0f;
float g_turnMinAccel = 15.0f;
float g_movementDecel = 50.0f;
float g_turnDecel = 50.0f;
float g_rotationSensitivity = 0.4f;
MxBool g_turnUseVelocity = 0;
#include "legoomni.h"
#include "legoutil.h"
// 0x100f4c28
int g_mouseDeadzone = 40;
// 0x100f4c2c
float g_zeroThreshold = 0.001f;
// 0x100f4c30
float g_movementMaxSpeed = 40.0f;
// 0x100f4c34
float g_turnMaxSpeed = 20.0f;
// 0x100f4c38
float g_movementMaxAccel = 15.0f;
// 0x100f4c3c
float g_turnMaxAccel = 30.0f;
// 0x100f4c40
float g_movementMinAccel = 4.0f;
// 0x100f4c44
float g_turnMinAccel = 15.0f;
// 0x100f4c48
float g_movementDecel = 50.0f;
// 0x100f4c4c
float g_turnDecel = 50.0f;
// 0x100f4c50
float g_turnSensitivity = 0.4f;
// 0x100f4c54
MxBool g_turnUseVelocity = MX_FALSE;
// OFFSET: LEGO1 0x10054d40
void LegoNavController::GetDefaults(int *p_mouseDeadzone, float *p_movementMaxSpeed, float *p_turnMaxSpeed,
float *p_movementMaxAccel, float *p_turnMaxAccel, float *p_movementDecel,
float *p_turnDecel, float *p_movementMinAccel, float *p_turnMinAccel,
float *p_rotationSensitivity, MxBool *p_turnUseVelocity)
float *p_turnSensitivity, MxBool *p_turnUseVelocity)
{
*p_mouseDeadzone = g_mouseDeadzone;
*p_movementMaxSpeed = g_movementMaxSpeed;
@ -27,14 +43,15 @@ void LegoNavController::GetDefaults(int *p_mouseDeadzone, float *p_movementMaxSp
*p_turnDecel = g_turnDecel;
*p_movementMinAccel = g_movementMinAccel;
*p_turnMinAccel = g_turnMinAccel;
*p_rotationSensitivity = g_rotationSensitivity;
*p_turnSensitivity = g_turnSensitivity;
*p_turnUseVelocity = g_turnUseVelocity;
}
// OFFSET: LEGO1 0x10054dd0
void LegoNavController::SetDefaults(int p_mouseDeadzone, float p_movementMaxSpeed, float p_turnMaxSpeed,
float p_movementMaxAccel, float p_turnMaxAccel, float p_movementDecel,
float p_turnDecel, float p_movementMinAccel, float p_turnMinAccel,
float p_rotationSensitivity, MxBool p_turnUseVelocity)
float p_turnSensitivity, MxBool p_turnUseVelocity)
{
g_mouseDeadzone = p_mouseDeadzone;
g_movementMaxSpeed = p_movementMaxSpeed;
@ -45,10 +62,62 @@ void LegoNavController::SetDefaults(int p_mouseDeadzone, float p_movementMaxSpee
g_turnDecel = p_turnDecel;
g_movementMinAccel = p_movementMinAccel;
g_turnMinAccel = p_turnMinAccel;
g_rotationSensitivity = p_rotationSensitivity;
g_turnSensitivity = p_turnSensitivity;
g_turnUseVelocity = p_turnUseVelocity;
}
// OFFSET: LEGO1 0x10054ac0
LegoNavController::LegoNavController()
{
ResetToDefault();
this->unk_18 = 0.0f;
this->unk_1C = 0.0f;
this->m_targetMovementSpeed = 0.0f;
this->m_targetTurnSpeed = 0.0f;
this->m_movementAccel = 0.0f;
this->m_turnAccel = 0.0f;
this->m_trackDefault = MX_FALSE;
this->m_unk5D = MX_FALSE;
this->m_unk6C = MX_FALSE;
this->m_unk64 = 0;
this->m_unk68 = 0;
this->m_unk60 = 0;
MxTimer *timer = Timer();
this->m_time = timer->GetTime();
// TODO: InputManager()
// LegoInputManager* inputManager = InputManager();
// inputManager->Register(this);
}
// TODO: InputManager()
// OFFSET: LEGO1 0x10054c30
// LegoNavController::~LegoNavController()
// {
// LegoInputManager* inputManager = InputManager();
// inputManager->UnRegister(this);
// }
// TODO: VideoManager()
// OFFSET: LEGO1 0x10054ca0
// void LegoNavController::SetControlMax(int p_hMax, int p_vMax)
// {
// LegoVideoManager* videoManager = VideoManager();
// this->m_hMax = p_hMax;
// this->m_vMax = p_vMax;
// Probably checks for MxVideoParamFlags: FULL_SCREEN
// if ((videoManager->m_unk44 & 0x01) != 0)
// {
// this->m_hMax = 640;
// this->m_vMax = 480;
// }
// }
// OFFSET: LEGO1 0x10054cd0
void LegoNavController::ResetToDefault()
{
this->m_mouseDeadzone = g_mouseDeadzone;
@ -62,5 +131,61 @@ void LegoNavController::ResetToDefault()
this->m_turnMaxSpeed = g_turnMaxSpeed;
this->m_movementMaxSpeed = g_movementMaxSpeed;
this->m_turnUseVelocity = g_turnUseVelocity;
this->m_rotationSensitivity = g_rotationSensitivity;
this->m_turnSensitivity = g_turnSensitivity;
}
// OFFSET: LEGO1 0x10054e40
void LegoNavController::SetTargets(int p_hPos, int p_vPos, MxBool p_accel)
{
if (this->m_trackDefault != MX_FALSE)
{
ResetToDefault();
}
if (p_accel != MX_FALSE)
{
this->m_targetTurnSpeed = CalculateNewTargetSpeed(p_hPos, this->m_hMax / 2, this->m_turnMaxSpeed);
this->m_targetMovementSpeed = CalculateNewTargetSpeed(this->m_vMax - p_vPos, this->m_vMax / 2, this->m_movementMaxSpeed);
this->m_turnAccel = CalculateNewAccel(p_hPos, this->m_hMax / 2, this->m_turnMaxAccel, (int)this->m_turnMinAccel);
this->m_movementAccel = CalculateNewAccel(this->m_vMax - p_vPos, this->m_vMax / 2, this->m_movementMaxAccel, (int)this->m_movementMinAccel);
}
else
{
this->m_targetTurnSpeed = 0.0f;
this->m_targetMovementSpeed = 0.0f;
this->m_movementAccel = this->m_movementDecel;
this->m_turnAccel = this->m_turnDecel;
}
}
// OFFSET: LEGO1 0x10054f10
float LegoNavController::CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed)
{
float result;
int diff = p_pos - p_center;
if (diff > this->m_mouseDeadzone)
result = (diff - m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone);
else if (diff < -m_mouseDeadzone)
result = (diff + m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone);
else
result = 0.0f;
return result;
}
// OFFSET: LEGO1 0x10054f90
float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel)
{
float result;
int diff = p_pos - p_center;
result = Abs(diff) * p_maxAccel / p_center;
if (result < p_minAccel)
{
result = (float)p_minAccel;
}
return result;
}

View File

@ -3,6 +3,7 @@
#include "mxcore.h"
#include "mxbool.h"
#include "mxtimer.h"
class LegoNavController : public MxCore
{
@ -15,25 +16,45 @@ class LegoNavController : public MxCore
float p_movementMaxAccel, float p_turnMaxAccel, float p_movementDecel,
float p_turnDecel, float p_movementMinAccel, float p_turnMinAccel,
float p_rotationSensitivity, MxBool p_turnUseVelocity);
LegoNavController();
// virtual ~LegoNavController();
// void SetControlMax(int p_hMax, int p_vMax);
void ResetToDefault();
void SetTargets(int p_hPos, int p_vPos, MxBool p_accel);
float CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed);
float CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel);
private:
int unk_08; // known to be set to window width: 640 (default)
int unk_0C; // known to be set to window height: 480 (default)
int m_hMax;
int m_vMax;
int m_mouseDeadzone;
float m_zeroThreshold;
int unk_18[4];
float unk_18;
float unk_1C;
float m_targetMovementSpeed;
float m_targetTurnSpeed;
float m_movementMaxSpeed;
float m_turnMaxSpeed;
int unk_30[2];
float m_movementAccel;
float m_turnAccel;
float m_movementMaxAccel;
float m_turnMaxAccel;
float m_movementMinAccel;
float m_turnMinAccel;
float m_movementDecel;
float m_turnDecel;
float m_rotationSensitivity;
float m_turnSensitivity;
MxBool m_turnUseVelocity;
int m_time;
MxBool m_trackDefault;
MxBool m_unk5D;
char m_unk5E[2];
int m_unk60;
int m_unk64;
int m_unk68;
MxBool m_unk6C;
};
#endif // LEGONAVCONTROLLER_H

View File

@ -1,18 +1,115 @@
#include "legoomni.h"
LegoOmni *LegoOmni::m_instance = NULL;
// OFFSET: LEGO1 0x10058a00
LegoOmni::LegoOmni()
{
Init();
}
// OFFSET: LEGO1 0x10058b50
LegoOmni::~LegoOmni()
{
Destroy();
}
// OFFSET: LEGO1 0x1005ad10
LegoOmni *LegoOmni::GetInstance()
{
return m_instance;
return (LegoOmni *) m_instance;
}
// OFFSET: LEGO1 0x10015700
LegoOmni *Lego()
{
return LegoOmni::GetInstance();
return (LegoOmni *) MxOmni::GetInstance();
}
// OFFSET: LEGO1 0x10015720
LegoVideoManager *VideoManager()
{
return LegoOmni::GetInstance()->GetVideoManager();
}
}
// OFFSET: LEGO1 0x1005b5f0
long LegoOmni::Notify(MxParam &p)
{
// FIXME: Stub
return 0;
}
// OFFSET: LEGO1 0x10058aa0
const char *LegoOmni::GetClassName() const
{
return "LegoOmni";
}
// OFFSET: LEGO1 0x10058ab0
MxBool LegoOmni::IsClass(const char *name) const
{
return strcmp("LegoOmni", name) == 0;
}
// OFFSET: LEGO1 0x10058bd0
void LegoOmni::Init()
{
// FIXME: Stub
}
// OFFSET: LEGO1 0x10058e70
MxResult LegoOmni::Create(MxOmniCreateParam &p)
{
// FIXME: Stub
return SUCCESS;
}
void LegoOmni::Destroy()
{
// FIXME: Stub
}
void LegoOmni::vtable20()
{
// FIXME: Stub
}
void LegoOmni::vtable24(MxDSAction &ds)
{
// FIXME: Stub
}
MxBool LegoOmni::vtable28(MxDSAction &ds)
{
// FIXME: Stub
return MX_TRUE;
}
void LegoOmni::vtable2c()
{
// FIXME: Stub
}
void LegoOmni::vtable30()
{
// FIXME: Stub
}
void LegoOmni::vtable34()
{
// FIXME: Stub
}
void LegoOmni::vtable38()
{
// FIXME: Stub
}
void LegoOmni::vtable3c()
{
// FIXME: Stub
}
unsigned char LegoOmni::vtable40()
{
// FIXME: Stub
return 0;
}

View File

@ -1,35 +1,23 @@
#ifndef LEGOOMNI_H
#define LEGOOMNI_H
#include "legoentity.h"
#include "legoinputmanager.h"
#include "legogamestate.h"
#include "legonavcontroller.h"
#include "legoroi.h"
#include "legovideomanager.h"
#include "mxatomid.h"
#include "mxbackgroundaudiomanager.h"
#include "mxdsaction.h"
#include "mxdsfile.h"
#include "mxdsobject.h"
#include "mxomnicreateparam.h"
#include "mxresult.h"
#include "mxstreamer.h"
#include "mxticklemanager.h"
#include "mxtimer.h"
#include "mxomni.h"
#include "mxtransitionmanager.h"
#include "legoanimationmanager.h"
#include "legobuildingmanager.h"
#include "legoentity.h"
#include "legogamestate.h"
#include "legoinputmanager.h"
#include "legomodelpresenter.h"
#include "legopartpresenter.h"
#include "legoroi.h"
#include "legoworldpresenter.h"
#include "legovideomanager.h"
class LegoSoundManager;
class MxEventManager;
class MxMusicManager;
class MxNotificationManager;
class MxSoundManager;
// class LegoOmni : public MxOmni
class LegoOmni
class LegoOmni : public MxOmni
{
public:
__declspec(dllexport) void CreateBackgroundAudio();
@ -38,15 +26,15 @@ class LegoOmni
__declspec(dllexport) static void CreateInstance();
__declspec(dllexport) static LegoOmni *GetInstance();
virtual ~LegoOmni();
LegoOmni();
virtual ~LegoOmni(); // vtable+00
virtual void vtable04();
virtual void vtable08();
virtual void vtable0c();
virtual void vtable10();
virtual void vtable14();
virtual MxResult Create(const MxOmniCreateParam &p);
virtual void vtable1c();
virtual long Notify(MxParam &p); // vtable+04
virtual const char *GetClassName() const; // vtable+0c
virtual MxBool IsClass(const char *name) const; // vtable+10;
virtual void Init(); // vtable+14
virtual MxResult Create(MxOmniCreateParam &p); // vtable+18
virtual void Destroy(); // vtable+1c
virtual void vtable20();
virtual void vtable24(MxDSAction &ds);
virtual MxBool vtable28(MxDSAction &ds);
@ -57,40 +45,20 @@ class LegoOmni
virtual void vtable3c();
virtual unsigned char vtable40();
LegoVideoManager *GetVideoManager() { return m_videoMgr; }
LegoVideoManager *GetVideoManager() { return (LegoVideoManager *) m_videoManager; }
LegoInputManager *GetInputManager() { return m_inputMgr; }
private:
int m_unk04;
int m_unk08;
int m_unk0c;
int m_unk10;
int m_unk14;
int m_unk18;
int m_unk1c;
int m_unk20;
int m_unk24;
int m_unk28;
LegoVideoManager *m_videoMgr;
int m_unk30;
int m_unk34;
int m_unk38;
int m_unk3c;
int m_unk40;
int m_unk44;
int m_unk48;
int m_unk4c;
int m_unk50;
int m_unk54;
int m_unk58;
int m_unk5c;
int m_unk60;
int m_unk64;
int m_unk68;
int m_unk6c;
LegoInputManager *m_inputMgr;
static LegoOmni *m_instance;
LegoInputManager *m_inputMgr; // 0x70
char m_unk74[0x10];
LegoNavController *m_navController; // 0x84
char m_unk88[0x14];
LegoGameState *m_gameState; // 0x9c
char m_unka0[0x94];
MxBackgroundAudioManager *m_bkgAudioManager; // 0x134
MxTransitionManager *m_transitionManager; // 0x138
};
@ -112,7 +80,6 @@ __declspec(dllexport) LegoSoundManager * SoundManager();
__declspec(dllexport) long Start(MxDSAction *);
__declspec(dllexport) MxStreamer * Streamer();
__declspec(dllexport) MxTickleManager * TickleManager();
__declspec(dllexport) MxTimer * Timer();
__declspec(dllexport) MxTransitionManager * TransitionManager();
__declspec(dllexport) MxVariableTable * VariableTable();
__declspec(dllexport) LegoVideoManager * VideoManager();

10
LEGO1/legoutil.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LEGOUTIL_H
#define LEGOUTIL_H
template <class T>
inline T Abs(T p_t)
{
return p_t < 0 ? -p_t : p_t;
}
#endif // LEGOUTIL_H

View File

@ -1,7 +1,9 @@
#ifndef MXATOMID_H
#define MXATOMID_H
enum LookupMode;
enum LookupMode
{
};
class MxAtomId
{

View File

@ -1,5 +1,6 @@
#include "mxautolocker.h"
// OFFSET: LEGO1 0x100b8ed0
MxAutoLocker::MxAutoLocker(MxCriticalSection *critsect)
{
this->m_criticalSection = critsect;
@ -7,6 +8,7 @@ MxAutoLocker::MxAutoLocker(MxCriticalSection *critsect)
this->m_criticalSection->Enter();
}
// OFFSET: LEGO1 0x100b8ef0
MxAutoLocker::~MxAutoLocker()
{
if (this->m_criticalSection != 0)

View File

@ -2,33 +2,40 @@
#include <string.h>
// 0x1010141c
unsigned int g_mxcoreCount = 0;
// OFFSET: LEGO1 0x100ae1a0
MxCore::MxCore()
{
m_id = g_mxcoreCount;
g_mxcoreCount++;
}
// OFFSET: LEGO1 0x100ae1e0
MxCore::~MxCore()
{
}
// OFFSET: LEGO1 0x100ae1f0
long MxCore::Notify(MxParam &p)
{
return 0;
}
// OFFSET: LEGO1 0x10001f70
long MxCore::Tickle()
{
return 0;
}
// OFFSET: LEGO1 0x100144c0
const char *MxCore::GetClassName() const
{
return "MxCore";
}
// OFFSET: LEGO1 0x100140d0
MxBool MxCore::IsClass(const char *name) const
{
return strcmp(name, "MxCore") == 0;

View File

@ -9,11 +9,11 @@ class MxCore
{
public:
__declspec(dllexport) MxCore();
__declspec(dllexport) virtual ~MxCore();
__declspec(dllexport) virtual long Notify(MxParam &p);
virtual long Tickle();
virtual const char *GetClassName() const;
virtual MxBool IsClass(const char *name) const;
__declspec(dllexport) virtual ~MxCore(); // vtable+00
__declspec(dllexport) virtual long Notify(MxParam &p); // vtable+04
virtual long Tickle(); // vtable+08
virtual const char *GetClassName() const; // vtable+0c
virtual MxBool IsClass(const char *name) const; // vtable+10
private:
unsigned int m_id;

View File

@ -2,8 +2,10 @@
#include <stdio.h>
// 0x10101e78
int g_useMutex = 0;
// OFFSET: LEGO1 0x100b6d20
MxCriticalSection::MxCriticalSection()
{
HANDLE mutex;
@ -19,6 +21,7 @@ MxCriticalSection::MxCriticalSection()
this->m_mutex = NULL;
}
// OFFSET: LEGO1 0x100b6d60
MxCriticalSection::~MxCriticalSection()
{
if (this->m_mutex != NULL)
@ -30,11 +33,13 @@ MxCriticalSection::~MxCriticalSection()
DeleteCriticalSection(&this->m_criticalSection);
}
// OFFSET: LEGO1 0x100b6e00
void MxCriticalSection::SetDoMutex()
{
g_useMutex = 1;
}
// OFFSET: LEGO1 0x100b6d80
void MxCriticalSection::Enter()
{
DWORD result;
@ -61,6 +66,7 @@ void MxCriticalSection::Enter()
}
}
// OFFSET: LEGO1 0x100b6de0
void MxCriticalSection::Leave()
{
if (this->m_mutex != NULL)
@ -70,4 +76,4 @@ void MxCriticalSection::Leave()
}
LeaveCriticalSection(&this->m_criticalSection);
}
}

View File

@ -1,7 +1,7 @@
#ifndef MXCRITICALSECTION_H
#define MXCRITICALSECTION_H
#include <Windows.h>
#include "legoinc.h"
class MxCriticalSection
{

View File

@ -36,6 +36,11 @@ class MxDSAction : public MxDSObject
int m_unk8c;
int m_unk90;
void setAtomId(MxAtomId &atomId)
{
this->m_atomId = atomId;
}
};
#endif // MXDSACTION_H

6
LEGO1/mxdsfile.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "mxdsfile.h"
unsigned long MxDSFile::GetBufferSize()
{
return this->m_buffersize;
}

View File

@ -12,6 +12,9 @@ class MxDSFile
__declspec(dllexport) virtual long Open(unsigned long);
__declspec(dllexport) virtual long Read(unsigned char *,unsigned long);
__declspec(dllexport) virtual long Seek(long,int);
private:
char m_unknown[0x70];
unsigned long m_buffersize;
};
#endif // MXDSFILE_H

9
LEGO1/mxeventmanager.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef MXEVENTMANAGER_H
#define MXEVENTMANAGER_H
class MxEventManager
{
};
#endif // MXEVENTMANAGER_H

9
LEGO1/mxmusicmanager.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef MXMUSICMANAGER_H
#define MXMUSICMANAGER_H
class MxMusicManager
{
};
#endif // MXMUSICMANAGER_H

View File

@ -0,0 +1,9 @@
#ifndef MXNOTIFICATIONMANAGER_H
#define MXNOTIFICATIONMANAGER_H
class MxNotificationManager
{
};
#endif // MXNOTIFICATIONMANAGER_H

9
LEGO1/mxobjectfactory.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef MXOBJECTFACTORY_H
#define MXOBJECTFACTORY_H
class MxObjectFactory
{
};
#endif MXOBJECTFACTORY_H

View File

@ -1,15 +1,73 @@
#include "mxomni.h"
MxResult MxOmni::Create(const MxOmniCreateParam &p)
{
if (p.CreateFlags().CreateTimer())
{
MxTimer *timer = new MxTimer();
this->m_Timer = timer;
if (timer == NULL)
return FAILURE;
}
return SUCCESS;
}
#include "mxomni.h"
// 0x101015b0
MxOmni* MxOmni::m_instance = NULL;
// OFFSET: LEGO1 0x100aef10
MxOmni::MxOmni()
{
Init();
}
// OFFSET: LEGO1 0x100aeff0
MxOmni::~MxOmni()
{
Destroy();
}
void MxOmni::Init()
{
m_windowHandle = NULL;
m_objectFactory = NULL;
m_variableTable = NULL;
m_tickleManager = NULL;
m_notificationManager = NULL;
m_videoManager = NULL;
m_soundManager = NULL;
m_musicManager = NULL;
m_eventManager = NULL;
m_timer = NULL;
m_streamer = NULL;
m_unk44 = NULL;
m_unk64 = NULL;
}
// OFFSET: LEGO1 0x100b0680
MxOmni *MxOmni::GetInstance()
{
return m_instance;
}
// OFFSET: LEGO1 0x100af0c0
MxResult MxOmni::Create(MxOmniCreateParam &p)
{
if (p.CreateFlags().CreateTimer())
{
MxTimer *timer = new MxTimer();
this->m_timer = timer;
if (timer == NULL)
return FAILURE;
}
return SUCCESS;
}
// OFFSET: LEGO1 0x100afe90
void MxOmni::Destroy()
{
// FIXME: Stub
}
// OFFSET: LEGO1 0x100b07f0
long MxOmni::Notify(MxParam &p)
{
// FIXME: Stub
return 0;
}
// OFFSET: LEGO1 0x100aced0
MxTimer *Timer()
{
return MxOmni::GetInstance()->GetTimer();
}

View File

@ -1,12 +1,22 @@
#ifndef MXOMNI_H
#define MXOMNI_H
#include "mxresult.h"
#include "mxomnicreateparam.h"
#include "mxcriticalsection.h"
#include "mxeventmanager.h"
#include "mxmusicmanager.h"
#include "mxnotificationmanager.h"
#include "mxobjectfactory.h"
#include "mxomnicreateflags.h"
#include "mxomnicreateparam.h"
#include "mxresult.h"
#include "mxsoundmanager.h"
#include "mxstreamer.h"
#include "mxticklemanager.h"
#include "mxtimer.h"
#include "mxvariabletable.h"
#include "mxvideomanager.h"
class MxOmni
class MxOmni : public MxCore
{
public:
__declspec(dllexport) static void DestroyInstance();
@ -18,13 +28,38 @@ class MxOmni
__declspec(dllexport) static void SetHD(const char *s);
__declspec(dllexport) static void SetSound3D(unsigned char);
MxResult MxOmni::Create(const MxOmniCreateParam &p);
virtual ~MxOmni();
MxTimer* GetTimer() const { return this->m_Timer; }
virtual long Notify(MxParam &p); // vtable+04
virtual void Init(); // vtable+14
virtual MxResult Create(MxOmniCreateParam &p); // vtable+18
virtual void Destroy(); // vtable+1c
private:
char padding[0x3c];
MxTimer* m_Timer;
MxTimer* GetTimer() const { return this->m_timer; }
protected:
static MxOmni* m_instance;
MxString m_mediaPath; // 0x8
HWND *m_windowHandle; // 0x18;
MxObjectFactory *m_objectFactory; // 0x1C
MxVariableTable* m_variableTable; //0x20
MxTickleManager* m_tickleManager; //0x24
MxNotificationManager* m_notificationManager; //0x28
MxVideoManager *m_videoManager; //0x2C
MxSoundManager* m_soundManager; //0x30
MxMusicManager* m_musicManager; //0x34
MxEventManager* m_eventManager; //0x38
MxTimer* m_timer; //0x3C
MxStreamer* m_streamer; //0x40
int m_unk44; // 0x44
MxCriticalSection m_criticalsection; // 0x48
int m_unk64; // 0x64
};
__declspec(dllexport) MxTimer * Timer();
#endif // MXOMNI_H

View File

@ -1,5 +1,6 @@
#include "mxomnicreateflags.h"
// OFFSET: LEGO1 0x100b0a30
MxOmniCreateFlags::MxOmniCreateFlags()
{
this->CreateObjectFactory(MX_TRUE);

View File

@ -1,5 +1,6 @@
#include "mxomnicreateparam.h"
// OFFSET: LEGO1 0x100b0b00
MxOmniCreateParam::MxOmniCreateParam(const char *mediaPath, struct HWND__ *windowHandle, MxVideoParam &vparam, MxOmniCreateFlags flags)
{
this->m_mediaPath = mediaPath;

View File

@ -1,8 +1,7 @@
#ifndef MXOMNICREATEPARAM_H
#define MXOMNICREATEPARAM_H
#include <Windows.h>
#include "legoinc.h"
#include "mxomnicreateflags.h"
#include "mxomnicreateparambase.h"
#include "mxstring.h"
@ -12,7 +11,6 @@ class MxOmniCreateParam : public MxOmniCreateParamBase
{
public:
__declspec(dllexport) MxOmniCreateParam(const char *mediaPath, struct HWND__ *windowHandle, MxVideoParam &vparam, MxOmniCreateFlags flags);
// virtual void vtable00(); seems to be a destructor
const MxOmniCreateFlags& CreateFlags() const { return this->m_createFlags; }

View File

@ -1,6 +1 @@
#include "mxomnicreateparam.h"
MxOmniCreateParamBase::~MxOmniCreateParamBase()
{
}

View File

@ -5,8 +5,7 @@
class MxOmniCreateParamBase
{
public:
~MxOmniCreateParamBase();
virtual void vtable00(){}
virtual ~MxOmniCreateParamBase(){}
};

9
LEGO1/mxsoundmanager.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef MXSOUNDMANAGER_H
#define MXSOUNDMANAGER_H
class MxSoundManager
{
};
#endif // MXSOUNDMANAGER_H

View File

@ -1,6 +1,8 @@
#ifndef MXSTREAMCONTROLLER_H
#define MXSTREAMCONTROLLER_H
#include "mxatomid.h"
class MxStreamController
{
public:

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
// OFFSET: LEGO1 0x100ae200
MxString::MxString()
{
// Set string to one char in length and set that char to null terminator
@ -11,6 +12,7 @@ MxString::MxString()
}
// TODO: this *mostly* matches, again weird with the comparison
// OFFSET: LEGO1 0x100ae510
const MxString &MxString::operator=(const char *param)
{
if (this->m_data != param)
@ -24,6 +26,7 @@ const MxString &MxString::operator=(const char *param)
return *this;
}
// OFFSET: LEGO1 0x100ae420
MxString::~MxString()
{
free(this->m_data);

View File

@ -1,6 +1,8 @@
#ifndef MXTICKLEMANAGER_H
#define MXTICKLEMANAGER_H
#include "mxcore.h"
class MxTickleManager : public MxCore
{
public:

View File

@ -1,10 +1,14 @@
#include "mxtimer.h"
#include <windows.h>
#include "legoinc.h"
// 0x10101414
long MxTimer::s_LastTimeCalculated = 0;
// 0x10101418
long MxTimer::s_LastTimeTimerStarted = 0;
// OFFSET: LEGO1 0x100ae060
MxTimer::MxTimer()
{
this->m_isRunning = MX_FALSE;
@ -12,12 +16,14 @@ MxTimer::MxTimer()
this->m_startTime = MxTimer::s_LastTimeCalculated;
}
// OFFSET: LEGO1 0x100ae160
void MxTimer::Start()
{
this->m_isRunning = MX_TRUE;
MxTimer::s_LastTimeTimerStarted = timeGetTime();
}
// OFFSET: LEGO1 0x100ae180
void MxTimer::Stop()
{
long elapsed = this->GetRealTime();
@ -27,6 +33,7 @@ void MxTimer::Stop()
this->m_startTime = this->m_startTime + startTime - 5;
}
// OFFSET: LEGO1 0x100ae140
long MxTimer::GetRealTime()
{
MxTimer::s_LastTimeCalculated = timeGetTime();

View File

@ -1,5 +1,9 @@
#include "mxvideoparam.h"
#include <stdlib.h>
#include <string.h>
// OFFSET: LEGO1 0x100bec70
MxVideoParam::MxVideoParam()
{
this->m_flags = MxVideoParamFlags();
@ -13,6 +17,7 @@ MxVideoParam::MxVideoParam()
this->m_deviceId = 0;
}
// OFFSET: LEGO1 0x100becf0
MxVideoParam &MxVideoParam::operator=(const MxVideoParam &other)
{
m_flags = MxVideoParamFlags();
@ -30,6 +35,7 @@ MxVideoParam &MxVideoParam::operator=(const MxVideoParam &other)
return *this;
}
// OFFSET: LEGO1 0x100bed70
void MxVideoParam::SetDeviceName(char *id)
{
if (this->m_deviceId != 0)
@ -48,6 +54,7 @@ void MxVideoParam::SetDeviceName(char *id)
}
}
// OFFSET: LEGO1 0x100bed50
MxVideoParam::~MxVideoParam()
{
if (this->m_deviceId != 0)

View File

@ -25,7 +25,7 @@ class MxVideoParam
int m_right;
int m_bottom;
MxPalette *m_palette;
BOOL m_backBuffers;
int m_backBuffers;
MxVideoParamFlags m_flags;
int m_unk1c;
char *m_deviceId;

View File

@ -1,5 +1,6 @@
#include "mxvideoparamflags.h"
// OFFSET: LEGO1 0x100bec40
MxVideoParamFlags::MxVideoParamFlags()
{
// TODO: convert to EnableXXX function calls

View File

@ -1,7 +1,7 @@
#ifndef MXVIDEOPARAMFLAGS_H
#define MXVIDEOPARAMFLAGS_H
#include <windows.h>
#include "mxbool.h"
class MxVideoParamFlags
{
@ -24,22 +24,22 @@ class MxVideoParamFlags
__declspec(dllexport) MxVideoParamFlags();
inline void EnableFullScreen(BOOL e)
inline void EnableFullScreen(MxBool e)
{
m_flags1 = (m_flags1 ^ (e << 0)) & FULL_SCREEN ^ m_flags1;
}
inline void EnableFlipSurfaces(BOOL e)
inline void EnableFlipSurfaces(MxBool e)
{
m_flags1 = (m_flags1 ^ (e << 1)) & FLIP_SURFACES ^ m_flags1;
}
inline void EnableBackBuffers(BOOL e)
inline void EnableBackBuffers(MxBool e)
{
m_flags1 = (m_flags1 ^ ((!e) << 2)) & BACK_BUFFERS ^ m_flags1;
}
inline void SetUnknown3(BOOL e)
inline void SetUnknown3(MxBool e)
{
m_flags1 = (m_flags1 ^ (e << 7)) & UNKNOWN3 ^ m_flags1;
}
@ -59,17 +59,17 @@ class MxVideoParamFlags
m_flags1 = ((e << 5) ^ m_flags1) & ENABLE_16BIT ^ m_flags1;
}
inline void EnableWideViewAngle(BOOL e)
inline void EnableWideViewAngle(MxBool e)
{
m_flags1 = (m_flags1 ^ (e << 6)) & WIDE_VIEW_ANGLE ^ m_flags1;
}
inline void EnableUnknown1(BOOL e)
inline void EnableUnknown1(MxBool e)
{
m_flags2 = (m_flags2 ^ ((!e) << 0)) & UNKNOWN1 ^ m_flags2;
}
inline void EnableUnknown2(BOOL e)
inline void EnableUnknown2(MxBool e)
{
m_flags2 = (m_flags2 ^ (e << 1)) & UNKNOWN2 ^ m_flags2;
}

View File

@ -1,6 +1,6 @@
# LEGO Island Decompilation
[Development Vlog](https://www.youtube.com/playlist?list=PLbpl-gZkNl2COf_bB6cfgTapD5WduAfPz) | [Matrix](https://matrix.to/#/#isledecomp:matrix.org) | [Forums](https://forum.mattkc.com/viewforum.php?f=1) | [Patreon](https://www.patreon.com/mattkc)
[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.
@ -14,7 +14,7 @@ Currently `ISLE.EXE` is completely decompiled, however there are some known inac
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.
### Recommended Instructions:
### 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.
@ -43,6 +43,10 @@ Simply place the compiled `ISLE.EXE` into LEGO Island's install folder (usually
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.
## Additional Information
### Which version of LEGO Island do I have?

228
isle.mak
View File

@ -70,19 +70,20 @@ CLEAN :
-@erase "$(INTDIR)\mxtimer.obj"
-@erase "$(INTDIR)\mxvideoparam.obj"
-@erase "$(INTDIR)\mxvideoparamflags.obj"
-@erase "$(INTDIR)\vc40.pdb"
-@erase ".\Release\LEGO1.DLL"
-@erase ".\Release\LEGO1.EXP"
-@erase ".\Release\LEGO1.LIB"
-@erase ".\Release\LEGO1.MAP"
-@erase ".\Release\LEGO1.PDB"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
/Fp"$(INTDIR)/LEGO1.pch" /YX /Fo"$(INTDIR)/" /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
CPP_PROJ=/nologo /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
/Fp"$(INTDIR)/LEGO1.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
CPP_OBJS=.\LEGO1\Release/
CPP_SBRS=.\.
@ -119,13 +120,13 @@ BSC32_SBRS= \
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:"Release/LEGO1.PDB" /map:"Release/LEGO1.MAP" /machine:I386 /out:"Release/LEGO1.DLL" /implib:"Release/LEGO1.LIB"
# SUBTRACT LINK32 /pdb:none
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /pdb:"Release/LEGO1.PDB" /debug /machine:I386 /out:"Release/LEGO1.DLL" /implib:"Release/LEGO1.LIB"
# SUBTRACT LINK32 /pdb:none /map
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no\
/pdb:"Release/LEGO1.PDB" /map:"Release/LEGO1.MAP" /machine:I386\
/out:"Release/LEGO1.DLL" /implib:"Release/LEGO1.LIB"
/pdb:"Release/LEGO1.PDB" /debug /machine:I386 /out:"Release/LEGO1.DLL"\
/implib:"Release/LEGO1.LIB"
LINK32_OBJS= \
"$(INTDIR)\dllmain.obj" \
"$(INTDIR)\legonavcontroller.obj" \
@ -187,7 +188,6 @@ CLEAN :
-@erase "$(INTDIR)\vc40.pdb"
-@erase "$(OUTDIR)\LEGO1.exp"
-@erase "$(OUTDIR)\LEGO1.lib"
-@erase "$(OUTDIR)\LEGO1.map"
-@erase "$(OUTDIR)\LEGO1.pdb"
-@erase ".\Debug\LEGO1.DLL"
-@erase ".\Debug\LEGO1.ILK"
@ -236,13 +236,13 @@ BSC32_SBRS= \
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /out:"Debug/LEGO1.DLL"
# SUBTRACT LINK32 /pdb:none
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Debug/LEGO1.DLL"
# SUBTRACT LINK32 /pdb:none /map
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:yes\
/pdb:"$(OUTDIR)/LEGO1.pdb" /map:"$(INTDIR)/LEGO1.map" /debug /machine:I386\
/out:"Debug/LEGO1.DLL" /implib:"$(OUTDIR)/LEGO1.lib"
/pdb:"$(OUTDIR)/LEGO1.pdb" /debug /machine:I386 /out:"Debug/LEGO1.DLL"\
/implib:"$(OUTDIR)/LEGO1.lib"
LINK32_OBJS= \
"$(INTDIR)\dllmain.obj" \
"$(INTDIR)\legonavcontroller.obj" \
@ -288,18 +288,23 @@ CLEAN :
-@erase "$(INTDIR)\isle.obj"
-@erase "$(INTDIR)\isle.res"
-@erase "$(INTDIR)\main.obj"
<<<<<<< HEAD
-@erase "$(INTDIR)\mxatomid.obj"
-@erase "$(INTDIR)\mxomnicreateparambase.obj"
=======
-@erase "$(INTDIR)\vc40.pdb"
>>>>>>> master
-@erase ".\Release\ISLE.EXE"
-@erase ".\Release\ISLE.PDB"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /W3 /GX /O2 /I "LEGO1" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "LEGO1" /D "WIN32" /D "NDEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)/ISLE.pch" /YX /Fo"$(INTDIR)/" /c
# ADD CPP /nologo /W3 /GX /Zi /O2 /I "LEGO1" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
CPP_PROJ=/nologo /ML /W3 /GX /Zi /O2 /I "LEGO1" /D "WIN32" /D "NDEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)/ISLE.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
CPP_OBJS=.\ISLE\Release/
CPP_SBRS=.\.
@ -337,20 +342,23 @@ BSC32_SBRS= \
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib lego1.lib dsound.lib /nologo /subsystem:windows /pdb:"Release/ISLE.PDB" /machine:I386 /out:"Release/ISLE.EXE" /LIBPATH:"ISLE/ext"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib lego1.lib dsound.lib /nologo /subsystem:windows /pdb:"Release/ISLE.PDB" /debug /machine:I386 /out:"Release/ISLE.EXE" /LIBPATH:"ISLE/ext"
# SUBTRACT LINK32 /pdb:none
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
odbccp32.lib winmm.lib lego1.lib dsound.lib /nologo /subsystem:windows\
/incremental:no /pdb:"Release/ISLE.PDB" /machine:I386 /out:"Release/ISLE.EXE"\
/LIBPATH:"ISLE/ext"
/incremental:no /pdb:"Release/ISLE.PDB" /debug /machine:I386\
/out:"Release/ISLE.EXE" /LIBPATH:"ISLE/ext"
LINK32_OBJS= \
"$(INTDIR)\define.obj" \
"$(INTDIR)\isle.obj" \
"$(INTDIR)\isle.res" \
"$(INTDIR)\main.obj" \
<<<<<<< HEAD
"$(INTDIR)\mxatomid.obj" \
"$(INTDIR)\mxomnicreateparambase.obj" \
=======
>>>>>>> master
".\Release\LEGO1.LIB"
".\Release\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@ -380,8 +388,11 @@ CLEAN :
-@erase "$(INTDIR)\isle.obj"
-@erase "$(INTDIR)\isle.res"
-@erase "$(INTDIR)\main.obj"
<<<<<<< HEAD
-@erase "$(INTDIR)\mxatomid.obj"
-@erase "$(INTDIR)\mxomnicreateparambase.obj"
=======
>>>>>>> master
-@erase "$(INTDIR)\vc40.idb"
-@erase "$(INTDIR)\vc40.pdb"
-@erase ".\Debug\ISLE.EXE"
@ -445,8 +456,11 @@ LINK32_OBJS= \
"$(INTDIR)\isle.obj" \
"$(INTDIR)\isle.res" \
"$(INTDIR)\main.obj" \
<<<<<<< HEAD
"$(INTDIR)\mxatomid.obj" \
"$(INTDIR)\mxomnicreateparambase.obj" \
=======
>>>>>>> master
".\LEGO1\Debug\LEGO1.lib"
".\Debug\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@ -486,8 +500,11 @@ DEP_CPP_MXCOR=\
# Begin Source File
SOURCE=.\LEGO1\dllmain.cpp
DEP_CPP_DLLMA=\
".\LEGO1\legoinc.h"\
"$(INTDIR)\dllmain.obj" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\dllmain.obj" : $(SOURCE) $(DEP_CPP_DLLMA) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
@ -499,30 +516,34 @@ SOURCE=.\LEGO1\legoomni.cpp
DEP_CPP_LEGOO=\
".\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\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\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxresult.h"\
".\LEGO1\mxsoundmanager.h"\
".\LEGO1\mxstreamcontroller.h"\
".\LEGO1\mxstreamer.h"\
".\LEGO1\mxstring.h"\
@ -530,6 +551,7 @@ DEP_CPP_LEGOO=\
".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
".\LEGO1\viewmanager.h"\
@ -545,6 +567,7 @@ DEP_CPP_LEGOO=\
SOURCE=.\LEGO1\mxcriticalsection.cpp
DEP_CPP_MXCRI=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxcriticalsection.h"\
@ -558,6 +581,7 @@ DEP_CPP_MXCRI=\
SOURCE=.\LEGO1\mxautolocker.cpp
DEP_CPP_MXAUT=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxautolocker.h"\
".\LEGO1\mxcriticalsection.h"\
@ -572,6 +596,7 @@ DEP_CPP_MXAUT=\
SOURCE=.\LEGO1\mxtimer.cpp
DEP_CPP_MXTIM=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxtimer.h"\
@ -587,8 +612,15 @@ DEP_CPP_MXTIM=\
SOURCE=.\LEGO1\mxomni.cpp
DEP_CPP_MXOMN=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxatomid.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxcriticalsection.h"\
".\LEGO1\mxeventmanager.h"\
".\LEGO1\mxmusicmanager.h"\
".\LEGO1\mxnotificationmanager.h"\
".\LEGO1\mxobjectfactory.h"\
".\LEGO1\mxomni.h"\
".\LEGO1\mxomnicreateflags.h"\
".\LEGO1\mxomnicreateparam.h"\
@ -596,9 +628,14 @@ DEP_CPP_MXOMN=\
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxresult.h"\
".\LEGO1\mxsoundmanager.h"\
".\LEGO1\mxstreamcontroller.h"\
".\LEGO1\mxstreamer.h"\
".\LEGO1\mxstring.h"\
".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
@ -613,6 +650,10 @@ DEP_CPP_MXOMN=\
SOURCE=.\LEGO1\mxvideoparam.cpp
DEP_CPP_MXVID=\
<<<<<<< HEAD
=======
".\LEGO1\mxbool.h"\
>>>>>>> master
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxvariabletable.h"\
@ -630,6 +671,7 @@ DEP_CPP_MXVID=\
SOURCE=.\LEGO1\mxvideoparamflags.cpp
DEP_CPP_MXVIDE=\
".\LEGO1\mxbool.h"\
".\LEGO1\mxvideoparamflags.h"\
@ -643,6 +685,7 @@ DEP_CPP_MXVIDE=\
SOURCE=.\LEGO1\mxomnicreateparam.cpp
DEP_CPP_MXOMNI=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxomnicreateflags.h"\
@ -666,6 +709,7 @@ DEP_CPP_MXOMNI=\
SOURCE=.\LEGO1\mxomnicreateparambase.cpp
DEP_CPP_MXOMNIC=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxomnicreateflags.h"\
@ -719,9 +763,48 @@ DEP_CPP_MXOMNICR=\
SOURCE=.\LEGO1\legonavcontroller.cpp
DEP_CPP_LEGON=\
".\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\legoutil.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\mxpalette.h"\
".\LEGO1\mxrect32.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\mxvideoparamflags.h"\
".\LEGO1\viewmanager.h"\
"$(INTDIR)\legonavcontroller.obj" : $(SOURCE) $(DEP_CPP_LEGON) "$(INTDIR)"
@ -801,8 +884,10 @@ DEP_CPP_ISLE_=\
".\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"\
@ -812,10 +897,15 @@ DEP_CPP_ISLE_=\
".\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"\
@ -823,6 +913,7 @@ DEP_CPP_ISLE_=\
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxresult.h"\
".\LEGO1\mxsoundmanager.h"\
".\LEGO1\mxstreamcontroller.h"\
".\LEGO1\mxstreamer.h"\
".\LEGO1\mxstring.h"\
@ -830,6 +921,7 @@ DEP_CPP_ISLE_=\
".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
".\LEGO1\viewmanager.h"\
@ -902,30 +994,39 @@ DEP_CPP_MAIN_=\
".\ISLE\isle.h"\
".\LEGO1\lego3dmanager.h"\
".\LEGO1\lego3dview.h"\
<<<<<<< HEAD
".\LEGO1\legoanimationmanager.h"\
".\LEGO1\legobuildingmanager.h"\
=======
>>>>>>> master
".\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\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\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxresult.h"\
".\LEGO1\mxsoundmanager.h"\
".\LEGO1\mxstreamcontroller.h"\
".\LEGO1\mxstreamer.h"\
".\LEGO1\mxstring.h"\
@ -933,6 +1034,7 @@ DEP_CPP_MAIN_=\
".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
".\LEGO1\viewmanager.h"\
@ -949,6 +1051,7 @@ DEP_CPP_MAIN_=\
".\ISLE\isle.h"\
".\LEGO1\lego3dmanager.h"\
".\LEGO1\lego3dview.h"\
<<<<<<< HEAD
".\LEGO1\legoanimationmanager.h"\
".\LEGO1\legobuildingmanager.h"\
".\LEGO1\legoentity.h"\
@ -960,26 +1063,59 @@ DEP_CPP_MAIN_=\
".\LEGO1\legoroi.h"\
".\LEGO1\legovideomanager.h"\
".\LEGO1\legoworldpresenter.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"\
>>>>>>> master
".\LEGO1\mxatomid.h"\
".\LEGO1\mxbackgroundaudiomanager.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
<<<<<<< HEAD
".\LEGO1\mxdsaction.h"\
".\LEGO1\mxdsfile.h"\
".\LEGO1\mxdsobject.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"\
>>>>>>> master
".\LEGO1\mxomnicreateflags.h"\
".\LEGO1\mxomnicreateparam.h"\
".\LEGO1\mxomnicreateparambase.h"\
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxresult.h"\
<<<<<<< HEAD
=======
".\LEGO1\mxsoundmanager.h"\
>>>>>>> master
".\LEGO1\mxstreamcontroller.h"\
".\LEGO1\mxstreamer.h"\
".\LEGO1\mxstring.h"\
".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\
<<<<<<< HEAD
".\LEGO1\mxvideoparam.h"\
=======
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
>>>>>>> master
".\LEGO1\viewmanager.h"\
@ -1011,30 +1147,6 @@ SOURCE=.\ISLE\res\isle.rc
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxomnicreateparambase.cpp
DEP_CPP_MXOMNIC=\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxomnicreateflags.h"\
".\LEGO1\mxomnicreateparam.h"\
".\LEGO1\mxomnicreateparambase.h"\
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxstring.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
"$(INTDIR)\mxomnicreateparambase.obj" : $(SOURCE) $(DEP_CPP_MXOMNIC)\
"$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
@ -1291,18 +1403,6 @@ SOURCE=.\LEGO1\mxomnicreateparam.h
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxomnicreateparambase.h
!IF "$(CFG)" == "ISLE - Win32 Release"
!ELSEIF "$(CFG)" == "ISLE - Win32 Debug"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxpalette.h
!IF "$(CFG)" == "ISLE - Win32 Release"

BIN
tools/reccomp/cvdump.exe Normal file

Binary file not shown.

226
tools/reccomp/reccomp.py Executable file
View File

@ -0,0 +1,226 @@
#!/usr/bin/env python3
from capstone import *
import difflib
import struct
import subprocess
import os
import sys
def print_usage():
print('Usage: %s [options] <original-binary> <recompiled-binary> <recompiled-pdb> <decomp-dir>\n' % sys.argv[0])
print('\t-v, --verbose <offset>\t\t\tPrint assembly diff for specific function (original file\'s offset)')
sys.exit(1)
positional_args = []
verbose = None
skip = False
for i, arg in enumerate(sys.argv):
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
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):
print('Invalid input: Original binary does not exist')
sys.exit(1)
recomp = positional_args[2]
if not os.path.isfile(recomp):
print('Invalid input: Recompiled binary does not exist')
sys.exit(1)
syms = positional_args[3]
if not os.path.isfile(syms):
print('Invalid input: Symbols PDB does not exist')
sys.exit(1)
source = positional_args[4]
if not os.path.isdir(source):
print('Invalid input: Source directory does not exist')
sys.exit(1)
# Declare a class that can automatically convert virtual executable addresses
# to file addresses
class Bin:
def __init__(self, filename):
self.file = open(filename, 'rb')
#HACK: Strictly, we should be parsing the header, but we know where
# everything is in these two files so we just jump straight there
# Read ImageBase
self.file.seek(0xB4)
self.imagebase = struct.unpack('i', self.file.read(4))[0]
# Read .text VirtualAddress
self.file.seek(0x184)
self.textvirt = struct.unpack('i', self.file.read(4))[0]
# Read .text PointerToRawData
self.file.seek(0x18C)
self.textraw = struct.unpack('i', self.file.read(4))[0]
def __del__(self):
if self.file:
self.file.close()
def get_addr(self, virt):
return virt - self.imagebase - self.textvirt + self.textraw
def read(self, offset, size):
self.file.seek(self.get_addr(offset))
return self.file.read(size)
line_dump = None
origfile = Bin(original)
recompfile = Bin(recomp)
class RecompiledInfo:
addr = None
size = None
name = None
print()
def get_recompiled_address(filename, line):
global line_dump, sym_dump
def get_wine_path(fn):
return subprocess.check_output(['winepath', '-w', fn]).decode('utf-8').strip()
# Load source lines from PDB
if not line_dump:
call = [os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'cvdump.exe'), '-l', '-s']
if os.name != 'nt':
# Run cvdump through wine and convert path to Windows-friendly wine path
call.insert(0, 'wine')
call.append(get_wine_path(syms))
else:
call.append(syms)
line_dump = subprocess.check_output(call).decode('utf-8').split('\r\n')
# Find requested filename/line in PDB
if os.name != 'nt':
# Convert filename to Wine path
filename = get_wine_path(filename)
#print('Looking for ' + filename + ' line ' + str(line))
addr = None
found = False
for i, s in enumerate(line_dump):
try:
sourcepath = s.split()[0]
if os.path.isfile(sourcepath) and os.path.samefile(sourcepath, filename):
lines = line_dump[i + 2].split()
if line == int(lines[0]):
# Found address
addr = int(lines[1], 16)
found = True
break
except IndexError:
pass
if found:
# Find size of function
for i, s in enumerate(line_dump):
if 'S_GPROC32' in s:
if int(s[26:34], 16) == addr:
obj = RecompiledInfo()
obj.addr = addr + recompfile.imagebase + recompfile.textvirt
obj.size = int(s[41:49], 16)
obj.name = s[77:]
return obj
md = Cs(CS_ARCH_X86, CS_MODE_32)
def parse_asm(file, addr, size):
asm = []
data = file.read(addr, size)
for i in md.disasm(data, 0):
if i.mnemonic == 'call':
# 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
# probably accurate.
asm.append(i.mnemonic)
else:
asm.append("%s %s" % (i.mnemonic, i.op_str))
return asm
function_count = 0
total_accuracy = 0
for subdir, dirs, files in os.walk(source):
for file in files:
srcfilename = os.path.join(os.path.abspath(subdir), file)
srcfile = open(srcfilename, 'r')
line_no = 0
while True:
try:
line = srcfile.readline()
line_no += 1
if not line:
break
if line.startswith('// OFFSET:'):
par = line[10:].strip().split()
module = par[0]
addr = int(par[1], 16)
find_open_bracket = line
while '{' not in find_open_bracket:
find_open_bracket = srcfile.readline()
line_no += 1
recinfo = get_recompiled_address(srcfilename, line_no)
if not recinfo:
print('Failed to find recompiled address of ' + hex(addr))
continue
origasm = parse_asm(origfile, addr, recinfo.size)
recompasm = parse_asm(recompfile, recinfo.addr, recinfo.size)
diff = difflib.SequenceMatcher(None, origasm, recompasm)
ratio = diff.ratio()
print('%s (%s / %s) is %.2f%% similar to the original' % (recinfo.name, hex(addr), hex(recinfo.addr), ratio * 100))
function_count += 1
total_accuracy += ratio
if verbose == addr:
udiff = difflib.unified_diff(origasm, recompasm)
for line in udiff:
print(line)
print()
print()
except UnicodeDecodeError:
break
if function_count > 0:
print('\nTotal accuracy %.2f%% across %i functions' % (total_accuracy / function_count * 100, function_count))