merge master

This commit is contained in:
Roman Masanin 2023-06-25 21:25:43 +02:00
commit 5a90ca6422
39 changed files with 2478 additions and 2390 deletions

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
*.MD text eol=lf diff=markdown
*.cpp text eol=lf diff=cpp
*.h text eol=lf diff=cpp
*.py text eol=lf diff=python
*.html text eol=lf diff=html
*.mdp binary
*.mak text eol=crlf

View File

@ -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
View File

@ -2,3 +2,5 @@ Debug/
Release/ Release/
*.ncb *.ncb
/.vs /.vs
ISLE.EXE
LEGO1.DLL

View File

@ -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";

View File

@ -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;

View File

@ -1,17 +1,5 @@
#include "isle.h" #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"
// OFFSET: ISLE 0x401000 // OFFSET: ISLE 0x401000
Isle::Isle() Isle::Isle()
{ {
@ -38,7 +26,7 @@ Isle::Isle()
m_windowActive = 1; m_windowActive = 1;
m_videoParam = MxVideoParam(MxRect32(0, 0, 639, 479), NULL, 1, MxVideoParamFlags()); m_videoParam = MxVideoParam(MxRect32(0, 0, 639, 479), NULL, 1, MxVideoParamFlags());
m_videoParam.flags().Enable16Bit(MxDirectDraw::GetPrimaryBitDepth() == 16); m_videoParam.flags().Set16Bit(MxDirectDraw::GetPrimaryBitDepth() == 16);
m_windowHandle = NULL; m_windowHandle = NULL;
m_cursorArrow = NULL; m_cursorArrow = NULL;
@ -78,7 +66,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);
@ -230,22 +218,22 @@ void Isle::LoadConfig()
// OFFSET: ISLE 0x401560 // OFFSET: ISLE 0x401560
void Isle::SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, void Isle::SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
BOOL using8bit, BOOL m_using16bit, BOOL param_6, BOOL param_7, BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7,
BOOL wideViewAngle, char *deviceId) BOOL wideViewAngle, char *deviceId)
{ {
m_videoParam.flags().EnableFullScreen(fullScreen); m_videoParam.flags().SetFullScreen(fullScreen);
m_videoParam.flags().EnableFlipSurfaces(flipSurfaces); m_videoParam.flags().SetFlipSurfaces(flipSurfaces);
m_videoParam.flags().EnableBackBuffers(backBuffers); m_videoParam.flags().SetBackBuffers(!backBuffers);
m_videoParam.flags().EnableUnknown1(param_6); m_videoParam.flags().Set_f2bit0(!param_6);
m_videoParam.flags().SetUnknown3(param_7); m_videoParam.flags().Set_f1bit7(param_7);
m_videoParam.flags().EnableWideViewAngle(wideViewAngle); m_videoParam.flags().SetWideViewAngle(wideViewAngle);
m_videoParam.flags().EnableUnknown2(); m_videoParam.flags().Set_f2bit1(1);
m_videoParam.SetDeviceName(deviceId); m_videoParam.SetDeviceName(deviceId);
if (using8bit) { if (using8bit) {
m_videoParam.flags().Set8Bit(); m_videoParam.flags().Set16Bit(0);
} }
if (m_using16bit) { if (using16bit) {
m_videoParam.flags().Set16Bit(); m_videoParam.flags().Set16Bit(1);
} }
} }
@ -294,347 +282,3 @@ void Isle::SetupCursor(WPARAM wParam)
SetCursor(m_cursorCurrent); SetCursor(m_cursorCurrent);
} }
// OFFSET: ISLE 0x401d20
LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!g_isle) {
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_PAINT:
return DefWindowProcA(hWnd, WM_PAINT, wParam, lParam);
case WM_ACTIVATE:
return DefWindowProcA(hWnd, WM_ACTIVATE, wParam, lParam);
case WM_ACTIVATEAPP:
if (g_isle) {
if ((wParam != 0) && (g_isle->m_fullScreen)) {
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;
}
return DefWindowProcA(hWnd,WM_ACTIVATEAPP,wParam,lParam);
case WM_CLOSE:
if (!g_closed && g_isle) {
if (g_isle) {
delete g_isle;
}
g_isle = NULL;
g_closed = TRUE;
return 0;
}
return DefWindowProcA(hWnd,WM_CLOSE,wParam,lParam);
case WM_GETMINMAXINFO:
{
MINMAXINFO *mmi = (MINMAXINFO *) lParam;
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;
}
case WM_ENTERMENULOOP:
return DefWindowProcA(hWnd,WM_ENTERMENULOOP,wParam,lParam);
case WM_SYSCOMMAND:
if (wParam == SC_SCREENSAVE) {
return 0;
}
if (wParam == SC_CLOSE && g_closed == 0) {
if (g_isle) {
if (g_rmDisabled) {
ShowWindow(g_isle->m_windowHandle, SW_RESTORE);
}
PostMessageA(g_isle->m_windowHandle, WM_CLOSE, 0, 0);
return 0;
}
} else if (g_isle && g_isle->m_fullScreen && (wParam == SC_MOVE || wParam == SC_KEYMENU)) {
return 0;
}
return DefWindowProcA(hWnd,WM_SYSCOMMAND,wParam,lParam);
case WM_EXITMENULOOP:
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);
case WM_NCPAINT:
if (g_isle && g_isle->m_fullScreen) {
return 0;
}
return DefWindowProcA(hWnd, WM_NCPAINT, wParam, lParam);
case WM_DISPLAYCHANGE:
if (g_isle && VideoManager() && g_isle->m_fullScreen && VideoManager()->m_unk74 && VideoManager()->m_unk74[0x220]) {
if (!g_waitingForTargetDepth) {
unsigned char valid = FALSE;
if (LOWORD(lParam) == g_targetWidth && HIWORD(lParam) == g_targetHeight && g_targetDepth == wParam) {
valid = TRUE;
}
if (!g_rmDisabled) {
if (!valid) {
g_rmDisabled = 1;
Lego()->vtable38();
VideoManager()->DisableRMDevice();
}
} else if (valid) {
g_reqEnableRMDevice = 1;
}
} else {
g_waitingForTargetDepth = 0;
g_targetDepth = wParam;
}
}
return DefWindowProcA(hWnd, WM_DISPLAYCHANGE, wParam, lParam);
case WM_SETCURSOR:
case WM_KEYDOWN:
case WM_MOUSEMOVE:
case WM_TIMER:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case 0x5400:
{
NotificationId type = NONE;
unsigned char keyCode = 0;
switch (uMsg) {
case WM_KEYDOWN:
// 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;
break;
case WM_MOUSEMOVE:
g_mousemoved = 1;
type = MOUSEMOVE;
break;
case WM_TIMER:
type = TIMER;
break;
case WM_SETCURSOR:
if (g_isle) {
HCURSOR hCursor = g_isle->m_cursorCurrent;
if (hCursor == g_isle->m_cursorBusy || hCursor == g_isle->m_cursorNo || !hCursor) {
SetCursor(hCursor);
return 0;
}
}
break;
case WM_LBUTTONDOWN:
g_mousedown = 1;
type = MOUSEDOWN;
break;
case WM_LBUTTONUP:
g_mousedown = 0;
type = MOUSEUP;
break;
case 0x5400:
if (g_isle) {
g_isle->SetupCursor(wParam);
return 0;
}
}
if (g_isle) {
if (InputManager()) {
InputManager()->QueueEvent(type, wParam, LOWORD(lParam), HIWORD(lParam), keyCode);
}
if (g_isle && g_isle->m_drawCursor && type == MOUSEMOVE) {
unsigned short x = LOWORD(lParam);
unsigned short y = HIWORD(lParam);
if (639 < x) {
x = 639;
}
if (479 < y) {
y = 479;
}
VideoManager()->MoveCursor(x,y);
}
}
return 0;
}
}
return DefWindowProcA(hWnd,uMsg,wParam,lParam);
}
// OFFSET: ISLE 0x4023e0
MxResult Isle::SetupWindow(HINSTANCE hInstance)
{
WNDCLASSA wndclass;
ZeroMemory(&wndclass, sizeof(WNDCLASSA));
LoadConfig();
SetupVideoFlags(m_fullScreen, m_flipSurfaces, m_backBuffersInVram, m_using8bit,
m_using16bit, m_unk24, FALSE, m_wideViewAngle, m_deviceId);
MxOmni::SetSound3D(m_use3dSound);
srand(timeGetTime() / 1000);
SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, NULL, 0);
ZeroMemory(&wndclass, sizeof(WNDCLASSA));
wndclass.cbClsExtra = 0;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbWndExtra = 0;
wndclass.hIcon = LoadIconA(hInstance, MAKEINTRESOURCE(APP_ICON));
wndclass.hCursor = LoadCursorA(hInstance, MAKEINTRESOURCE(ISLE_ARROW));
m_cursorCurrent = wndclass.hCursor;
m_cursorArrow = wndclass.hCursor;
m_cursorBusy = LoadCursorA(hInstance, MAKEINTRESOURCE(ISLE_BUSY));
m_cursorNo = LoadCursorA(hInstance, MAKEINTRESOURCE(ISLE_NO));
wndclass.hInstance = hInstance;
wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wndclass.lpszClassName = WNDCLASS_NAME;
if (!RegisterClassA(&wndclass)) {
return FAILURE;
}
DWORD dwStyle;
int x, y, width, height;
if (!m_fullScreen) {
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;
y = CW_USEDEFAULT;
x = CW_USEDEFAULT;
dwStyle = WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
} else {
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 = g_windowRect.left;
y = g_windowRect.top;
}
m_windowHandle = CreateWindowExA(WS_EX_APPWINDOW, WNDCLASS_NAME, WINDOW_TITLE, dwStyle,
x, y, width + 1, height + 1, NULL, NULL, hInstance, NULL);
if (!m_windowHandle) {
return FAILURE;
}
if (m_fullScreen) {
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()) {
return FAILURE;
}
GameState()->SetSavePath(m_savePath);
GameState()->SerializePlayersInfo(1);
GameState()->SerializeScoreHistory(1);
int iVar10;
if (m_islandQuality == 0) {
iVar10 = 1;
} else if (m_islandQuality == 1) {
iVar10 = 2;
} else {
iVar10 = 100;
}
int uVar1 = (m_islandTexture == 0);
LegoModelPresenter::configureLegoModelPresenter(uVar1);
LegoPartPresenter::configureLegoPartPresenter(uVar1,iVar10);
LegoWorldPresenter::configureLegoWorldPresenter(m_islandQuality);
LegoBuildingManager::configureLegoBuildingManager(m_islandQuality);
LegoROI::configureLegoROI(iVar10);
LegoAnimationManager::configureLegoAnimationManager(m_islandQuality);
if (LegoOmni::GetInstance()) {
if (LegoOmni::GetInstance()->GetInputManager()) {
LegoOmni::GetInstance()->GetInputManager()->m_unk00[0xCD] = m_useJoystick;
LegoOmni::GetInstance()->GetInputManager()->m_unk00[0x67] = m_joystickIndex;
}
}
if (m_fullScreen) {
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);
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);
}

View File

@ -1,10 +1,21 @@
#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 "legoanimationmanager.h"
#include "legobuildingmanager.h"
#include "legomodelpresenter.h"
#include "legopartpresenter.h"
#include "legoworldpresenter.h"
#include "mxresult.h" #include "mxresult.h"
#include "mxvideoparam.h" #include "mxvideoparam.h"
#include "mxdirectdraw.h"
#include "mxdsaction.h"
#include "mxomni.h"
#include "res/resource.h"
class Isle class Isle
{ {
@ -18,14 +29,14 @@ class Isle
int ReadRegBool(LPCSTR name, BOOL *out); int ReadRegBool(LPCSTR name, BOOL *out);
int ReadRegInt(LPCSTR name, int *out); int ReadRegInt(LPCSTR name, int *out);
MxResult SetupWindow(HINSTANCE hInstance); MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine);
void Tick(BOOL sleepIfNotNextFrame); void Tick(BOOL sleepIfNotNextFrame);
BOOL SetupLegoOmni(); BOOL SetupLegoOmni();
void LoadConfig(); void LoadConfig();
void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers,
BOOL using8bit, BOOL m_using16bit, BOOL param_6, BOOL param_7, BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7,
BOOL wideViewAngle, char *deviceId); BOOL wideViewAngle, char *deviceId);
void SetupCursor(WPARAM wParam); void SetupCursor(WPARAM wParam);
@ -77,4 +88,190 @@ class Isle
}; };
extern LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// OFFSET: ISLE 0x4023e0
inline MxResult Isle::SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine)
{
WNDCLASSA wndclass;
ZeroMemory(&wndclass, sizeof(WNDCLASSA));
LoadConfig();
SetupVideoFlags(m_fullScreen, m_flipSurfaces, m_backBuffersInVram, m_using8bit,
m_using16bit, m_unk24, FALSE, m_wideViewAngle, m_deviceId);
MxOmni::SetSound3D(m_use3dSound);
srand(timeGetTime() / 1000);
SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, NULL, 0);
ZeroMemory(&wndclass, sizeof(WNDCLASSA));
wndclass.cbClsExtra = 0;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbWndExtra = 0;
wndclass.hIcon = LoadIconA(hInstance, MAKEINTRESOURCEA(APP_ICON));
wndclass.hCursor = m_cursorArrow = m_cursorCurrent = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_ARROW));
m_cursorBusy = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_BUSY));
m_cursorNo = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_NO));
wndclass.hInstance = hInstance;
wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wndclass.lpszClassName = WNDCLASS_NAME;
if (!RegisterClassA(&wndclass)) {
return FAILURE;
}
if (m_fullScreen) {
AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
m_windowHandle = CreateWindowExA(
WS_EX_APPWINDOW,
WNDCLASS_NAME,
WINDOW_TITLE,
WS_CAPTION | WS_SYSMENU,
g_windowRect.left,
g_windowRect.top,
g_windowRect.right - g_windowRect.left + 1,
g_windowRect.bottom - g_windowRect.top + 1,
NULL, NULL, hInstance, NULL
);
} else {
AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
m_windowHandle = CreateWindowExA(
WS_EX_APPWINDOW,
WNDCLASS_NAME,
WINDOW_TITLE,
WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
g_windowRect.right - g_windowRect.left + 1,
g_windowRect.bottom - g_windowRect.top + 1,
NULL, NULL, hInstance, NULL
);
}
if (!m_windowHandle) {
return FAILURE;
}
if (m_fullScreen) {
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()) {
return FAILURE;
}
GameState()->SetSavePath(m_savePath);
GameState()->SerializePlayersInfo(1);
GameState()->SerializeScoreHistory(1);
int iVar10;
switch (m_islandQuality) {
case 0:
iVar10 = 1;
break;
case 1:
iVar10 = 2;
break;
default:
iVar10 = 100;
}
int uVar1 = (m_islandTexture == 0);
LegoModelPresenter::configureLegoModelPresenter(uVar1);
LegoPartPresenter::configureLegoPartPresenter(uVar1,iVar10);
LegoWorldPresenter::configureLegoWorldPresenter(m_islandQuality);
LegoBuildingManager::configureLegoBuildingManager(m_islandQuality);
LegoROI::configureLegoROI(iVar10);
LegoAnimationManager::configureLegoAnimationManager(m_islandQuality);
if (LegoOmni::GetInstance()) {
if (LegoOmni::GetInstance()->GetInputManager()) {
LegoOmni::GetInstance()->GetInputManager()->m_useJoystick = m_useJoystick;
LegoOmni::GetInstance()->GetInputManager()->m_joystickIndex = m_joystickIndex;
}
}
if (m_fullScreen) {
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);
return SUCCESS;
}
// OFFSET: ISLE 0x402c20
inline void Isle::Tick(BOOL sleepIfNotNextFrame)
{
if (!this->m_windowActive) {
Sleep(0);
return;
}
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)
Sleep(0);
}
#endif // ISLE_H #endif // ISLE_H

View File

@ -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)
@ -60,7 +61,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_isle = new Isle(); g_isle = new Isle();
// Create window // Create window
if (g_isle->SetupWindow(hInstance) != SUCCESS) { if (g_isle->SetupWindow(hInstance, lpCmdLine) != SUCCESS) {
MessageBoxA(NULL, "\"LEGO\xAE Island\" failed to start. Please quit all other applications and try again.", "LEGO\xAE Island Error", MB_OK); MessageBoxA(NULL, "\"LEGO\xAE Island\" failed to start. Please quit all other applications and try again.", "LEGO\xAE Island Error", MB_OK);
return 0; return 0;
} }
@ -89,14 +90,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
} }
if (g_isle) { if (g_isle) {
g_isle->Tick(1); g_isle->Tick(0);
} }
if (g_closed) { while (!g_closed) {
break;
}
do {
if (!PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (!PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
break; break;
} }
@ -133,10 +130,182 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
} }
goto LAB_00401bc7; goto LAB_00401bc7;
} }
} while (!g_closed); }
} }
DestroyWindow(window); DestroyWindow(window);
return msg.wParam; return msg.wParam;
} }
// OFFSET: ISLE 0x401d20
LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!g_isle) {
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_PAINT:
return DefWindowProcA(hWnd, WM_PAINT, wParam, lParam);
case WM_ACTIVATE:
return DefWindowProcA(hWnd, WM_ACTIVATE, wParam, lParam);
case WM_ACTIVATEAPP:
if (g_isle) {
if ((wParam != 0) && (g_isle->m_fullScreen)) {
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;
}
return DefWindowProcA(hWnd,WM_ACTIVATEAPP,wParam,lParam);
case WM_CLOSE:
if (!g_closed && g_isle) {
if (g_isle) {
delete g_isle;
}
g_isle = NULL;
g_closed = TRUE;
return 0;
}
return DefWindowProcA(hWnd,WM_CLOSE,wParam,lParam);
case WM_GETMINMAXINFO:
{
MINMAXINFO *mmi = (MINMAXINFO *) lParam;
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;
}
case WM_ENTERMENULOOP:
return DefWindowProcA(hWnd,WM_ENTERMENULOOP,wParam,lParam);
case WM_SYSCOMMAND:
if (wParam == SC_SCREENSAVE) {
return 0;
}
if (wParam == SC_CLOSE && g_closed == 0) {
if (g_isle) {
if (g_rmDisabled) {
ShowWindow(g_isle->m_windowHandle, SW_RESTORE);
}
PostMessageA(g_isle->m_windowHandle, WM_CLOSE, 0, 0);
return 0;
}
} else if (g_isle && g_isle->m_fullScreen && (wParam == SC_MOVE || wParam == SC_KEYMENU)) {
return 0;
}
return DefWindowProcA(hWnd,WM_SYSCOMMAND,wParam,lParam);
case WM_EXITMENULOOP:
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);
case WM_NCPAINT:
if (g_isle && g_isle->m_fullScreen) {
return 0;
}
return DefWindowProcA(hWnd, WM_NCPAINT, wParam, lParam);
case WM_DISPLAYCHANGE:
if (g_isle && VideoManager() && g_isle->m_fullScreen && VideoManager()->m_unk74 && VideoManager()->m_unk74[0x220]) {
if (!g_waitingForTargetDepth) {
unsigned char valid = FALSE;
if (LOWORD(lParam) == g_targetWidth && HIWORD(lParam) == g_targetHeight && g_targetDepth == wParam) {
valid = TRUE;
}
if (!g_rmDisabled) {
if (!valid) {
g_rmDisabled = 1;
Lego()->vtable38();
VideoManager()->DisableRMDevice();
}
} else if (valid) {
g_reqEnableRMDevice = 1;
}
} else {
g_waitingForTargetDepth = 0;
g_targetDepth = wParam;
}
}
return DefWindowProcA(hWnd, WM_DISPLAYCHANGE, wParam, lParam);
case WM_SETCURSOR:
case WM_KEYDOWN:
case WM_MOUSEMOVE:
case WM_TIMER:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case 0x5400:
{
NotificationId type = NONE;
unsigned char keyCode = 0;
switch (uMsg) {
case WM_KEYDOWN:
// 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;
break;
case WM_MOUSEMOVE:
g_mousemoved = 1;
type = MOUSEMOVE;
break;
case WM_TIMER:
type = TIMER;
break;
case WM_SETCURSOR:
if (g_isle) {
HCURSOR hCursor = g_isle->m_cursorCurrent;
if (hCursor == g_isle->m_cursorBusy || hCursor == g_isle->m_cursorNo || !hCursor) {
SetCursor(hCursor);
return 0;
}
}
break;
case WM_LBUTTONDOWN:
g_mousedown = 1;
type = MOUSEDOWN;
break;
case WM_LBUTTONUP:
g_mousedown = 0;
type = MOUSEUP;
break;
case 0x5400:
if (g_isle) {
g_isle->SetupCursor(wParam);
return 0;
}
}
if (g_isle) {
if (InputManager()) {
InputManager()->QueueEvent(type, wParam, LOWORD(lParam), HIWORD(lParam), keyCode);
}
if (g_isle && g_isle->m_drawCursor && type == MOUSEMOVE) {
unsigned short x = LOWORD(lParam);
unsigned short y = HIWORD(lParam);
if (639 < x) {
x = 639;
}
if (479 < y) {
y = 479;
}
VideoManager()->MoveCursor(x,y);
}
}
return 0;
}
}
return DefWindowProcA(hWnd,uMsg,wParam,lParam);
}

View File

@ -1,7 +0,0 @@
#include "mxdsobject.h"
// OFFSET: ISLE 0x00401c40
void MxDSObject::SetAtomId(MxAtomId p_atomId)
{
this->m_atomId = p_atomId;
}

View File

@ -20,7 +20,10 @@ class LegoInputManager
__declspec(dllexport) void Register(MxCore *); __declspec(dllexport) void Register(MxCore *);
__declspec(dllexport) void UnRegister(MxCore *); __declspec(dllexport) void UnRegister(MxCore *);
int m_unk00[0x400]; char m_pad00[0x19C];
int m_joystickIndex;
char m_pad200[0x194];
MxBool m_useJoystick;
}; };
#endif // LEGOINPUTMANAGER_H #endif // LEGOINPUTMANAGER_H

View File

@ -100,22 +100,18 @@ LegoNavController::LegoNavController()
// inputManager->UnRegister(this); // inputManager->UnRegister(this);
// } // }
// TODO: VideoManager()
// OFFSET: LEGO1 0x10054ca0 // OFFSET: LEGO1 0x10054ca0
// void LegoNavController::SetControlMax(int p_hMax, int p_vMax) void LegoNavController::SetControlMax(int p_hMax, int p_vMax)
// { {
// LegoVideoManager* videoManager = VideoManager(); this->m_hMax = p_hMax;
this->m_vMax = p_vMax;
// this->m_hMax = p_hMax; if (VideoManager()->GetVideoParam().flags().GetFullScreen())
// this->m_vMax = p_vMax; {
this->m_hMax = 640;
// Probably checks for MxVideoParamFlags: FULL_SCREEN this->m_vMax = 480;
// if ((videoManager->m_unk44 & 0x01) != 0) }
// { }
// this->m_hMax = 640;
// this->m_vMax = 480;
// }
// }
// OFFSET: LEGO1 0x10054cd0 // OFFSET: LEGO1 0x10054cd0
void LegoNavController::ResetToDefault() void LegoNavController::ResetToDefault()

View File

@ -20,7 +20,7 @@ class LegoNavController : public MxCore
LegoNavController(); LegoNavController();
// virtual ~LegoNavController(); // virtual ~LegoNavController();
// void SetControlMax(int p_hMax, int p_vMax); void SetControlMax(int p_hMax, int p_vMax);
void ResetToDefault(); void ResetToDefault();
void SetTargets(int p_hPos, int p_vPos, MxBool p_accel); void SetTargets(int p_hPos, int p_vPos, MxBool p_accel);
float CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed); float CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed);

View File

@ -24,12 +24,43 @@ LegoOmni *Lego()
return (LegoOmni *) MxOmni::GetInstance(); return (LegoOmni *) MxOmni::GetInstance();
} }
// OFFSET: LEGO1 0x10015710
LegoSoundManager *SoundManager()
{
return LegoOmni::GetInstance()->GetSoundManager();
}
// OFFSET: LEGO1 0x10015720 // OFFSET: LEGO1 0x10015720
LegoVideoManager *VideoManager() LegoVideoManager *VideoManager()
{ {
return LegoOmni::GetInstance()->GetVideoManager(); return LegoOmni::GetInstance()->GetVideoManager();
} }
// OFFSET: LEGO1 0x10015730
MxBackgroundAudioManager *BackgroundAudioManager()
{
return LegoOmni::GetInstance()->GetBackgroundAudioManager();
}
// OFFSET: LEGO1 0x10015740
LegoInputManager *InputManager()
{
return LegoOmni::GetInstance()->GetInputManager();
}
// OFFSET: LEGO1 0x10015760
LegoGameState *GameState()
{
return LegoOmni::GetInstance()->GetGameState();
}
// OFFSET: LEGO1 0x10015780
LegoNavController *NavController()
{
return LegoOmni::GetInstance()->GetNavController();
}
// OFFSET: LEGO1 0x1005b5f0 // OFFSET: LEGO1 0x1005b5f0
long LegoOmni::Notify(MxParam &p) long LegoOmni::Notify(MxParam &p)
{ {

View File

@ -46,7 +46,11 @@ class LegoOmni : public MxOmni
virtual unsigned char vtable40(); virtual unsigned char vtable40();
LegoVideoManager *GetVideoManager() { return (LegoVideoManager *) m_videoManager; } LegoVideoManager *GetVideoManager() { return (LegoVideoManager *) m_videoManager; }
LegoSoundManager *GetSoundManager() { return (LegoSoundManager *)m_soundManager;}
MxBackgroundAudioManager *GetBackgroundAudioManager() { return m_bkgAudioManager; }
LegoInputManager *GetInputManager() { return m_inputMgr; } LegoInputManager *GetInputManager() { return m_inputMgr; }
LegoGameState *GetGameState() { return m_gameState; }
LegoNavController *GetNavController() { return m_navController; }
private: private:
int m_unk68; int m_unk68;

View File

@ -1,10 +1,10 @@
#ifndef LEGOVIDEOMANAGER_H #ifndef LEGOVIDEOMANAGER_H
#define LEGOVIDEOMANAGER_H #define LEGOVIDEOMANAGER_H
#include "mxvideomanager.h"
#include "lego3dmanager.h" #include "lego3dmanager.h"
// class LegoVideoManager : public MxVideoManager class LegoVideoManager : public MxVideoManager
class LegoVideoManager
{ {
public: public:
__declspec(dllexport) int EnableRMDevice(); __declspec(dllexport) int EnableRMDevice();
@ -14,31 +14,6 @@ class LegoVideoManager
inline Lego3DManager *Get3DManager() { return this->m_3dManager; } inline Lego3DManager *Get3DManager() { return this->m_3dManager; }
int m_unk00;
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;
int m_unk2c;
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_unk64;
Lego3DManager *m_3dManager; Lego3DManager *m_3dManager;
int m_unk6c; int m_unk6c;

View File

@ -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;
}

View File

@ -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;
}; };

8
LEGO1/mxpalette.cpp Executable file
View File

@ -0,0 +1,8 @@
#include "mxpalette.h"
// OFFSET: LEGO1 0x100bf150
MxResult MxPalette::GetEntries(LPPALETTEENTRY p_entries)
{
memcpy(p_entries, this->m_entries, sizeof(this->m_entries));
return SUCCESS;
}

View File

@ -1,11 +1,23 @@
#ifndef MXPALETTE_H #ifndef MXPALETTE_H
#define MXPALETTE_H #define MXPALETTE_H
class MxPalette #include <ddraw.h>
#include "mxcore.h"
#include "mxresult.h"
class MxPalette : public MxCore
{ {
public: public:
__declspec(dllexport) unsigned char operator==(MxPalette &); __declspec(dllexport) unsigned char operator==(MxPalette &);
__declspec(dllexport) void Detach(); __declspec(dllexport) void Detach();
MxResult GetEntries(LPPALETTEENTRY p_entries);
private:
LPDIRECTDRAWPALETTE m_pDirectDrawPalette;
PALETTEENTRY m_entries[256];
// there's a bit more here
}; };
#endif // MXPALETTE_H #endif // MXPALETTE_H

View File

@ -4,6 +4,7 @@
class MxRect32 class MxRect32
{ {
public: public:
MxRect32() { }
MxRect32(int p_left, int p_top, int p_right, int p_bottom) MxRect32(int p_left, int p_top, int p_right, int p_bottom)
{ {
this->m_left = p_left; this->m_left = p_left;

15
LEGO1/mxunknown100dc6b0.cpp Executable file
View File

@ -0,0 +1,15 @@
#include "mxunknown100dc6b0.h"
// OFFSET: LEGO1 0x100b84c0
MxUnknown100dc6b0::MxUnknown100dc6b0()
{
Init();
}
// OFFSET: LEGO1 0x100b85d0
MxResult MxUnknown100dc6b0::Init()
{
this->m_unk08 = 0;
this->m_unk0c = 0;
return SUCCESS;
}

23
LEGO1/mxunknown100dc6b0.h Executable file
View File

@ -0,0 +1,23 @@
#ifndef MXUNKNOWN100DC6B0_H
#define MXUNKNOWN100DC6B0_H
#include "mxcore.h"
#include "mxresult.h"
#include "mxcriticalsection.h"
class MxUnknown100dc6b0 : public MxCore
{
public:
MxUnknown100dc6b0();
MxResult Init();
private:
int m_unk08;
int m_unk0c;
protected:
MxCriticalSection m_criticalSection;
};
#endif // MXUNKNOWN100DC6B0_H

36
LEGO1/mxvideomanager.cpp Executable file
View File

@ -0,0 +1,36 @@
#include "mxvideomanager.h"
// OFFSET: LEGO1 0x100be1f0
MxVideoManager::MxVideoManager()
{
Init();
}
// OFFSET: LEGO1 0x100be320
int MxVideoManager::Init()
{
this->m_unk50 = 0;
this->m_unk54 = NULL;
this->m_unk58 = NULL;
this->m_unk5c = 0;
this->m_videoParam.SetPalette(NULL);
this->m_unk60 = MX_FALSE;
return 0;
}
// OFFSET: LEGO1 0x100bebe0
long MxVideoManager::RealizePalette(MxPalette *p_palette)
{
PALETTEENTRY paletteEntries[256];
this->m_criticalSection.Enter();
if (p_palette && this->m_videoParam.GetPalette())
{
p_palette->GetEntries(paletteEntries);
// TODO
}
this->m_criticalSection.Leave();
return 0;
}

View File

@ -1,11 +1,28 @@
#ifndef MXVIDEOMANAGER_H #ifndef MXVIDEOMANAGER_H
#define MXVIDEOMANAGER_H #define MXVIDEOMANAGER_H
class MxVideoManager #include "mxunknown100dc6b0.h"
#include "mxvideoparam.h"
class MxVideoManager : public MxUnknown100dc6b0
{ {
public: public:
__declspec(dllexport) void InvalidateRect(MxRect32 &); __declspec(dllexport) void InvalidateRect(MxRect32 &);
__declspec(dllexport) virtual long RealizePalette(MxPalette *); __declspec(dllexport) virtual long RealizePalette(MxPalette *);
MxVideoManager();
int Init();
inline MxVideoParam& GetVideoParam() { return this->m_videoParam; }
private:
MxVideoParam m_videoParam;
int m_unk50;
LPDIRECTDRAWSURFACE m_unk54;
void* m_unk58;
int m_unk5c;
MxBool m_unk60;
}; };
#endif // MXVIDEOMANAGER_H #endif // MXVIDEOMANAGER_H

View File

@ -6,31 +6,57 @@
// OFFSET: LEGO1 0x100bec70 // OFFSET: LEGO1 0x100bec70
MxVideoParam::MxVideoParam() MxVideoParam::MxVideoParam()
{ {
this->m_flags = MxVideoParamFlags(); this->m_rect.m_right = 640;
this->m_right = 640; this->m_rect.m_bottom = 480;
this->m_bottom = 480; this->m_rect.m_left = 0;
this->m_left = 0; this->m_rect.m_top = 0;
this->m_top = 0;
this->m_palette = 0; this->m_palette = 0;
this->m_backBuffers = 0; this->m_backBuffers = 0;
this->m_unk1c = 0; this->m_unk1c = 0;
this->m_deviceId = 0; this->m_deviceId = 0;
} }
// OFFSET: LEGO1 0x100becf0 // OFFSET: LEGO1 0x100beca0
MxVideoParam &MxVideoParam::operator=(const MxVideoParam &other) MxVideoParam::MxVideoParam(MxRect32 &p_rect, MxPalette *p_pal, unsigned long p_backBuffers, MxVideoParamFlags &p_flags)
{ {
m_flags = MxVideoParamFlags(); this->m_rect.m_left = p_rect.m_left;
m_left = other.m_left; this->m_rect.m_top = p_rect.m_top;
m_top = other.m_top; this->m_rect.m_right = p_rect.m_right;
m_right = other.m_right; this->m_rect.m_bottom = p_rect.m_bottom;
m_bottom = other.m_bottom; this->m_palette = p_pal;
m_palette = other.m_palette; this->m_backBuffers = p_backBuffers;
m_backBuffers = other.m_backBuffers; this->m_flags = p_flags;
m_flags = other.m_flags; this->m_unk1c = 0;
m_unk1c = other.m_unk1c; this->m_deviceId = NULL;
m_deviceId = other.m_deviceId; }
SetDeviceName(other.m_deviceId);
// OFFSET: LEGO1 0x100becf0
MxVideoParam::MxVideoParam(MxVideoParam &p_videoParam)
{
this->m_rect.m_left = p_videoParam.m_rect.m_left;
this->m_rect.m_top = p_videoParam.m_rect.m_top;
this->m_rect.m_right = p_videoParam.m_rect.m_right;
this->m_rect.m_bottom = p_videoParam.m_rect.m_bottom;
this->m_palette = p_videoParam.m_palette;
this->m_backBuffers = p_videoParam.m_backBuffers;
this->m_flags = p_videoParam.m_flags;
this->m_unk1c = p_videoParam.m_unk1c;
this->m_deviceId = NULL;
SetDeviceName(p_videoParam.m_deviceId);
}
// OFFSET: LEGO1 0x100bede0
MxVideoParam &MxVideoParam::operator=(const MxVideoParam &p_videoParam)
{
this->m_rect.m_left = p_videoParam.m_rect.m_left;
this->m_rect.m_top = p_videoParam.m_rect.m_top;
this->m_rect.m_right = p_videoParam.m_rect.m_right;
this->m_rect.m_bottom = p_videoParam.m_rect.m_bottom;
this->m_palette = p_videoParam.m_palette;
this->m_backBuffers = p_videoParam.m_backBuffers;
this->m_flags = p_videoParam.m_flags;
this->m_unk1c = p_videoParam.m_unk1c;
SetDeviceName(p_videoParam.m_deviceId);
return *this; return *this;
} }

View File

@ -1,7 +1,10 @@
#ifndef MXVIDEOPARAM_H #ifndef MXVIDEOPARAM_H
#define MXVIDEOPARAM_H #define MXVIDEOPARAM_H
#include <ddraw.h>
#include "mxpalette.h" #include "mxpalette.h"
#include "mxbool.h"
#include "mxrect32.h" #include "mxrect32.h"
#include "mxvariabletable.h" #include "mxvariabletable.h"
#include "mxvideoparamflags.h" #include "mxvideoparamflags.h"
@ -19,17 +22,16 @@ class MxVideoParam
inline MxVideoParamFlags &flags() { return m_flags; } inline MxVideoParamFlags &flags() { return m_flags; }
inline void SetPalette(MxPalette *p_palette) { this->m_palette = p_palette; }
inline MxPalette *GetPalette() { return this->m_palette; }
private: private:
int m_left; MxRect32 m_rect;
int m_top;
int m_right;
int m_bottom;
MxPalette *m_palette; MxPalette *m_palette;
int m_backBuffers; unsigned int m_backBuffers;
MxVideoParamFlags m_flags; MxVideoParamFlags m_flags;
int m_unk1c; int m_unk1c;
char *m_deviceId; char *m_deviceId;
}; };
#endif // MXVIDEOPARAM_H #endif // MXVIDEOPARAM_H

View File

@ -3,15 +3,13 @@
// OFFSET: LEGO1 0x100bec40 // OFFSET: LEGO1 0x100bec40
MxVideoParamFlags::MxVideoParamFlags() MxVideoParamFlags::MxVideoParamFlags()
{ {
// TODO: convert to EnableXXX function calls this->SetFullScreen(0);
unsigned char bVar1 = this->m_flags1; this->SetFlipSurfaces(0);
this->m_flags1 = bVar1 & 0xfe; this->SetBackBuffers(0);
this->m_flags1 = bVar1 & 0xfc; this->Set_f1bit3(0);
this->m_flags1 = bVar1 & 0xf8; this->Set_f1bit4(0);
this->m_flags1 = bVar1 & 0xf0; this->Set16Bit(0);
this->m_flags1 = bVar1 & 0xe0; this->SetWideViewAngle(1);
this->m_flags2 = this->m_flags2 | 2; this->Set_f1bit7(1);
this->m_flags1 = bVar1 & 0xc0; this->Set_f2bit1(1);
this->m_flags1 = bVar1 & 0xc0 | 0x40;
this->m_flags1 = 0xc0;
} }

View File

@ -3,85 +3,63 @@
#include "legoinc.h" #include "legoinc.h"
// Must be union with struct for match.
typedef union {
struct {
BYTE bit0: 1;
BYTE bit1: 1;
BYTE bit2: 1;
BYTE bit3: 1;
BYTE bit4: 1;
BYTE bit5: 1;
BYTE bit6: 1;
BYTE bit7: 1;
};
// BYTE all; // ?
} flag_bitfield;
class MxVideoParamFlags class MxVideoParamFlags
{ {
public: public:
enum LowFlags
{
FULL_SCREEN = 0x1,
FLIP_SURFACES = 0x2,
BACK_BUFFERS = 0x4,
ENABLE_16BIT = 0x20,
WIDE_VIEW_ANGLE = 0x40,
UNKNOWN3 = 0x80
};
enum HighFlags
{
UNKNOWN1 = 0x1,
UNKNOWN2 = 0x2
};
__declspec(dllexport) MxVideoParamFlags(); __declspec(dllexport) MxVideoParamFlags();
inline void EnableFullScreen(BOOL e) inline void SetFullScreen(BOOL e) { m_flags1.bit0 = e; }
{ inline void SetFlipSurfaces(BOOL e) { m_flags1.bit1 = e; }
m_flags1 = (m_flags1 ^ (e << 0)) & FULL_SCREEN ^ m_flags1; inline void SetBackBuffers(BOOL e) { m_flags1.bit2 = e; }
} inline void Set_f1bit3(BOOL e) { m_flags1.bit3 = e; }
inline void Set_f1bit4(BOOL e) { m_flags1.bit4 = e; }
inline void Set16Bit(BYTE e) { m_flags1.bit5 = e; }
inline void SetWideViewAngle(BOOL e) { m_flags1.bit6 = e; }
inline void Set_f1bit7(BOOL e) { m_flags1.bit7 = e; }
inline void Set_f2bit0(BOOL e) { m_flags2.bit0 = e; }
inline void Set_f2bit1(BOOL e) { m_flags2.bit1 = e; }
inline void Set_f2bit2(BOOL e) { m_flags2.bit2 = e; }
inline void Set_f2bit3(BOOL e) { m_flags2.bit3 = e; }
inline void Set_f2bit4(BOOL e) { m_flags2.bit4 = e; }
inline void Set_f2bit5(BOOL e) { m_flags2.bit5 = e; }
inline void Set_f2bit6(BOOL e) { m_flags2.bit6 = e; }
inline void Set_f2bit7(BOOL e) { m_flags2.bit7 = e; }
inline void EnableFlipSurfaces(BOOL e) inline BYTE GetFullScreen() { return m_flags1.bit0; }
{ inline BYTE GetFlipSurfaces() { return m_flags1.bit1; }
m_flags1 = (m_flags1 ^ (e << 1)) & FLIP_SURFACES ^ m_flags1; inline BYTE GetBackBuffers() { return m_flags1.bit2; }
} inline BYTE Get_f1bit3() { return m_flags1.bit3; }
inline BYTE Get_f1bit4() { return m_flags1.bit4; }
inline void EnableBackBuffers(BOOL e) inline BYTE Get16Bit() { return m_flags1.bit5; }
{ inline BYTE GetWideViewAngle() { return m_flags1.bit6; }
m_flags1 = (m_flags1 ^ ((!e) << 2)) & BACK_BUFFERS ^ m_flags1; inline BYTE Get_f1bit7() { return m_flags1.bit7; }
} inline BYTE Get_f2bit0() { return m_flags2.bit0; }
inline BYTE Get_f2bit1() { return m_flags2.bit1; }
inline void SetUnknown3(BOOL e) inline BYTE Get_f2bit2() { return m_flags2.bit2; }
{ inline BYTE Get_f2bit3() { return m_flags2.bit3; }
m_flags1 = (m_flags1 ^ (e << 7)) & UNKNOWN3 ^ m_flags1; inline BYTE Get_f2bit4() { return m_flags2.bit4; }
} inline BYTE Get_f2bit5() { return m_flags2.bit5; }
inline BYTE Get_f2bit6() { return m_flags2.bit6; }
inline void Set8Bit() inline BYTE Get_f2bit7() { return m_flags2.bit7; }
{
m_flags1 &= ~ENABLE_16BIT;
}
inline void Set16Bit()
{
m_flags1 |= ENABLE_16BIT;
}
inline void Enable16Bit(unsigned char e)
{
m_flags1 = ((e << 5) ^ m_flags1) & ENABLE_16BIT ^ m_flags1;
}
inline void EnableWideViewAngle(BOOL e)
{
m_flags1 = (m_flags1 ^ (e << 6)) & WIDE_VIEW_ANGLE ^ m_flags1;
}
inline void EnableUnknown1(BOOL e)
{
m_flags2 = (m_flags2 ^ ((!e) << 0)) & UNKNOWN1 ^ m_flags2;
}
inline void EnableUnknown2(BOOL e)
{
m_flags2 = (m_flags2 ^ (e << 1)) & UNKNOWN2 ^ m_flags2;
}
inline void EnableUnknown2()
{
m_flags2 |= UNKNOWN2;
}
private: private:
unsigned char m_flags1; flag_bitfield m_flags1;
unsigned char m_flags2; flag_bitfield m_flags2;
}; };

207
isle.mak
View File

@ -66,8 +66,11 @@ CLEAN :
-@erase "$(INTDIR)\mxomnicreateflags.obj" -@erase "$(INTDIR)\mxomnicreateflags.obj"
-@erase "$(INTDIR)\mxomnicreateparam.obj" -@erase "$(INTDIR)\mxomnicreateparam.obj"
-@erase "$(INTDIR)\mxomnicreateparambase.obj" -@erase "$(INTDIR)\mxomnicreateparambase.obj"
-@erase "$(INTDIR)\mxpalette.obj"
-@erase "$(INTDIR)\mxstring.obj" -@erase "$(INTDIR)\mxstring.obj"
-@erase "$(INTDIR)\mxtimer.obj" -@erase "$(INTDIR)\mxtimer.obj"
-@erase "$(INTDIR)\mxunknown100dc6b0.obj"
-@erase "$(INTDIR)\mxvideomanager.obj"
-@erase "$(INTDIR)\mxvideoparam.obj" -@erase "$(INTDIR)\mxvideoparam.obj"
-@erase "$(INTDIR)\mxvideoparamflags.obj" -@erase "$(INTDIR)\mxvideoparamflags.obj"
-@erase "$(INTDIR)\vc40.pdb" -@erase "$(INTDIR)\vc40.pdb"
@ -140,8 +143,11 @@ LINK32_OBJS= \
"$(INTDIR)\mxomnicreateflags.obj" \ "$(INTDIR)\mxomnicreateflags.obj" \
"$(INTDIR)\mxomnicreateparam.obj" \ "$(INTDIR)\mxomnicreateparam.obj" \
"$(INTDIR)\mxomnicreateparambase.obj" \ "$(INTDIR)\mxomnicreateparambase.obj" \
"$(INTDIR)\mxpalette.obj" \
"$(INTDIR)\mxstring.obj" \ "$(INTDIR)\mxstring.obj" \
"$(INTDIR)\mxtimer.obj" \ "$(INTDIR)\mxtimer.obj" \
"$(INTDIR)\mxunknown100dc6b0.obj" \
"$(INTDIR)\mxvideomanager.obj" \
"$(INTDIR)\mxvideoparam.obj" \ "$(INTDIR)\mxvideoparam.obj" \
"$(INTDIR)\mxvideoparamflags.obj" "$(INTDIR)\mxvideoparamflags.obj"
@ -180,8 +186,11 @@ CLEAN :
-@erase "$(INTDIR)\mxomnicreateflags.obj" -@erase "$(INTDIR)\mxomnicreateflags.obj"
-@erase "$(INTDIR)\mxomnicreateparam.obj" -@erase "$(INTDIR)\mxomnicreateparam.obj"
-@erase "$(INTDIR)\mxomnicreateparambase.obj" -@erase "$(INTDIR)\mxomnicreateparambase.obj"
-@erase "$(INTDIR)\mxpalette.obj"
-@erase "$(INTDIR)\mxstring.obj" -@erase "$(INTDIR)\mxstring.obj"
-@erase "$(INTDIR)\mxtimer.obj" -@erase "$(INTDIR)\mxtimer.obj"
-@erase "$(INTDIR)\mxunknown100dc6b0.obj"
-@erase "$(INTDIR)\mxvideomanager.obj"
-@erase "$(INTDIR)\mxvideoparam.obj" -@erase "$(INTDIR)\mxvideoparam.obj"
-@erase "$(INTDIR)\mxvideoparamflags.obj" -@erase "$(INTDIR)\mxvideoparamflags.obj"
-@erase "$(INTDIR)\vc40.idb" -@erase "$(INTDIR)\vc40.idb"
@ -256,8 +265,11 @@ LINK32_OBJS= \
"$(INTDIR)\mxomnicreateflags.obj" \ "$(INTDIR)\mxomnicreateflags.obj" \
"$(INTDIR)\mxomnicreateparam.obj" \ "$(INTDIR)\mxomnicreateparam.obj" \
"$(INTDIR)\mxomnicreateparambase.obj" \ "$(INTDIR)\mxomnicreateparambase.obj" \
"$(INTDIR)\mxpalette.obj" \
"$(INTDIR)\mxstring.obj" \ "$(INTDIR)\mxstring.obj" \
"$(INTDIR)\mxtimer.obj" \ "$(INTDIR)\mxtimer.obj" \
"$(INTDIR)\mxunknown100dc6b0.obj" \
"$(INTDIR)\mxvideomanager.obj" \
"$(INTDIR)\mxvideoparam.obj" \ "$(INTDIR)\mxvideoparam.obj" \
"$(INTDIR)\mxvideoparamflags.obj" "$(INTDIR)\mxvideoparamflags.obj"
@ -288,7 +300,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 +361,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 +390,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 +453,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)
@ -534,6 +542,7 @@ DEP_CPP_LEGOO=\
".\LEGO1\mxticklemanager.h"\ ".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\ ".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\ ".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\ ".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\ ".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\ ".\LEGO1\mxvideoparam.h"\
@ -551,6 +560,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 +574,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"\
@ -616,6 +627,7 @@ DEP_CPP_MXOMN=\
".\LEGO1\mxstring.h"\ ".\LEGO1\mxstring.h"\
".\LEGO1\mxticklemanager.h"\ ".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\ ".\LEGO1\mxtimer.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\ ".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\ ".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\ ".\LEGO1\mxvideoparam.h"\
@ -779,6 +791,7 @@ DEP_CPP_LEGON=\
".\LEGO1\mxticklemanager.h"\ ".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\ ".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\ ".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\ ".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\ ".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\ ".\LEGO1\mxvideoparam.h"\
@ -819,6 +832,59 @@ DEP_CPP_MXATO=\
$(CPP) $(CPP_PROJ) $(SOURCE) $(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxunknown100dc6b0.cpp
DEP_CPP_MXUNK=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxcriticalsection.h"\
".\LEGO1\mxunknown100dc6b0.h"\
"$(INTDIR)\mxunknown100dc6b0.obj" : $(SOURCE) $(DEP_CPP_MXUNK) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxvideomanager.cpp
DEP_CPP_MXVIDEO=\
".\LEGO1\legoinc.h"\
".\LEGO1\mxbool.h"\
".\LEGO1\mxcore.h"\
".\LEGO1\mxcriticalsection.h"\
".\LEGO1\mxpalette.h"\
".\LEGO1\mxrect32.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\
".\LEGO1\mxvideoparamflags.h"\
"$(INTDIR)\mxvideomanager.obj" : $(SOURCE) $(DEP_CPP_MXVIDEO) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\LEGO1\mxpalette.cpp
DEP_CPP_MXPAL=\
".\LEGO1\mxpalette.h"\
"$(INTDIR)\mxpalette.obj" : $(SOURCE) $(DEP_CPP_MXPAL) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File # End Source File
# End Target # End Target
################################################################################ ################################################################################
@ -850,9 +916,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"\
@ -899,6 +962,7 @@ DEP_CPP_ISLE_=\
".\LEGO1\mxticklemanager.h"\ ".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\ ".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\ ".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\ ".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\ ".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\ ".\LEGO1\mxvideoparam.h"\
@ -910,72 +974,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"\
@ -1015,6 +1018,7 @@ DEP_CPP_MAIN_=\
".\LEGO1\mxticklemanager.h"\ ".\LEGO1\mxticklemanager.h"\
".\LEGO1\mxtimer.h"\ ".\LEGO1\mxtimer.h"\
".\LEGO1\mxtransitionmanager.h"\ ".\LEGO1\mxtransitionmanager.h"\
".\LEGO1\mxunknown100dc6b0.h"\
".\LEGO1\mxvariabletable.h"\ ".\LEGO1\mxvariabletable.h"\
".\LEGO1\mxvideomanager.h"\ ".\LEGO1\mxvideomanager.h"\
".\LEGO1\mxvideoparam.h"\ ".\LEGO1\mxvideoparam.h"\
@ -1026,57 +1030,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 +1470,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
################################################################################ ################################################################################

BIN
isle.mdp

Binary file not shown.

View File

@ -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)
debug_offs = line_dump[i + 2]
debug_start = int(debug_offs[22:30], 16)
debug_end = int(debug_offs[43:], 16)
info = RecompiledInfo() info = RecompiledInfo()
info.addr = addr + recompfile.imagebase + recompfile.textvirt info.addr = addr + recompfile.imagebase + recompfile.textvirt
info.start = debug_start
info.size = debug_end - debug_start use_dbg_offs = False
if use_dbg_offs:
debug_offs = line_dump[i + 2]
debug_start = int(debug_offs[22:30], 16)
debug_end = int(debug_offs[43:], 16)
info.start = 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

View File

@ -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>