From 24ec7023bdfd3b455e58655570ab859f1e7e6b2e Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 27 Jun 2023 22:07:29 +0200 Subject: [PATCH] isle: match WndProc and re-arrange functions in `ISLE.EXE` (#45) * match WinProc * minor accuracy improvement * WndProc at 50% * fix WM_DISPLAYCHANGE branching * fix type * fix x/y comparison * WndProc 82% * 84% * 97% * rearrange functions to get close to the original * remove newline * inline no longer necessary * merge --- ISLE/define.cpp | 2 +- ISLE/define.h | 2 +- ISLE/isle.cpp | 563 +++++++++++++++++++++++++++++++++--- ISLE/isle.h | 217 +------------- ISLE/main.cpp | 311 -------------------- LEGO1/mxpalette.cpp | 0 LEGO1/mxunknown100dc6b0.cpp | 0 LEGO1/mxunknown100dc6b0.h | 0 LEGO1/mxvideomanager.cpp | 0 isle.mak | 122 ++------ isle.mdp | Bin 52224 -> 51200 bytes 11 files changed, 568 insertions(+), 649 deletions(-) delete mode 100644 ISLE/main.cpp mode change 100755 => 100644 LEGO1/mxpalette.cpp mode change 100755 => 100644 LEGO1/mxunknown100dc6b0.cpp mode change 100755 => 100644 LEGO1/mxunknown100dc6b0.h mode change 100755 => 100644 LEGO1/mxvideomanager.cpp diff --git a/ISLE/define.cpp b/ISLE/define.cpp index b5501b08..0a77efd9 100644 --- a/ISLE/define.cpp +++ b/ISLE/define.cpp @@ -28,7 +28,7 @@ int g_targetWidth = 640; int g_targetHeight = 480; // 0x410060 -unsigned int g_targetDepth = 16; +int g_targetDepth = 16; // 0x410064 int g_reqEnableRMDevice = 0; diff --git a/ISLE/define.h b/ISLE/define.h index 27a347b7..41f7de27 100644 --- a/ISLE/define.h +++ b/ISLE/define.h @@ -18,7 +18,7 @@ extern int g_rmDisabled; extern int g_waitingForTargetDepth; extern int g_targetWidth; extern int g_targetHeight; -extern unsigned int g_targetDepth; +extern int g_targetDepth; extern int g_reqEnableRMDevice; extern int g_startupDelay; extern long g_lastFrameTime; diff --git a/ISLE/isle.cpp b/ISLE/isle.cpp index 051572ef..efaa2564 100644 --- a/ISLE/isle.cpp +++ b/ISLE/isle.cpp @@ -1,4 +1,18 @@ #include "isle.h" +#include "define.h" + +#include + +#include "legoomni.h" +#include "legoanimationmanager.h" +#include "legobuildingmanager.h" +#include "legomodelpresenter.h" +#include "legopartpresenter.h" +#include "legoworldpresenter.h" +#include "mxdirectdraw.h" +#include "mxdsaction.h" + +#include "res/resource.h" // OFFSET: ISLE 0x401000 Isle::Isle() @@ -97,6 +111,459 @@ void Isle::Close() } } +// OFFSET: ISLE 0x4013b0 +BOOL Isle::SetupLegoOmni() +{ + BOOL result = FALSE; + char mediaPath[256]; + GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, sizeof(mediaPath)); + + BOOL failure = Lego()->Create(MxOmniCreateParam(mediaPath, (struct HWND__ *) m_windowHandle, m_videoParam, MxOmniCreateFlags())) == FAILURE; + if (!failure) { + VariableTable()->SetVariable("ACTOR_01", ""); + TickleManager()->vtable1c(VideoManager(), 10); + result = TRUE; + } + + return result; +} + +// OFFSET: ISLE 0x401560 +void Isle::SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, + BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7, + BOOL wideViewAngle, char *deviceId) +{ + m_videoParam.flags().SetFullScreen(fullScreen); + m_videoParam.flags().SetFlipSurfaces(flipSurfaces); + m_videoParam.flags().SetBackBuffers(!backBuffers); + m_videoParam.flags().Set_f2bit0(!param_6); + m_videoParam.flags().Set_f1bit7(param_7); + m_videoParam.flags().SetWideViewAngle(wideViewAngle); + m_videoParam.flags().Set_f2bit1(1); + m_videoParam.SetDeviceName(deviceId); + if (using8bit) { + m_videoParam.flags().Set16Bit(0); + } + if (using16bit) { + m_videoParam.flags().Set16Bit(1); + } +} + +BOOL FindExistingInstance(void); +BOOL StartDirectSound(void); + +// 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()) { + return 0; + } + + // Attempt to create DirectSound instance + BOOL soundReady = FALSE; + for (int i = 0; i < 20; i++) { + if (StartDirectSound()) { + soundReady = TRUE; + break; + } + Sleep(500); + } + + // 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", MB_OK); + return 0; + } + + // Create global app instance + g_isle = new Isle(); + + // Create window + 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); + return 0; + } + + // Get reference to window + HWND window; + if (g_isle->m_windowHandle) { + window = g_isle->m_windowHandle; + } + + // 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; + + while (!g_closed) { + while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if (g_isle) { + g_isle->Tick(1); + } + } + + if (g_isle) { + g_isle->Tick(0); + } + + while (!g_closed) { + if (!PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { + break; + } + + MSG nextMsg; + if (!g_isle + || !g_isle->m_windowHandle + || msg.message != WM_MOUSEMOVE + || !PeekMessageA(&nextMsg, NULL, 0, 0, PM_NOREMOVE) + || nextMsg.message != WM_MOUSEMOVE) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + + if (g_reqEnableRMDevice) { + g_reqEnableRMDevice = 0; + VideoManager()->EnableRMDevice(); + g_rmDisabled = 0; + Lego()->vtable3c(); + } + + if (g_closed) { + break; + } + + if (g_mousedown == 0) { +LAB_00401bc7: + if (g_mousemoved) { + g_mousemoved = FALSE; + } + } else if (g_mousemoved) { + if (g_isle) { + g_isle->Tick(0); + } + goto LAB_00401bc7; + } + } + } + + DestroyWindow(window); + + return msg.wParam; +} + +// OFFSET: ISLE 0x401ca0 +BOOL FindExistingInstance(void) +{ + HWND hWnd = FindWindowA(WNDCLASS_NAME, WINDOW_TITLE); + if (hWnd) { + if (SetForegroundWindow(hWnd)) { + ShowWindow(hWnd, SW_RESTORE); + } + return 0; + } + return 1; +} + +// OFFSET: ISLE 0x401ce0 +BOOL StartDirectSound(void) +{ + LPDIRECTSOUND lpDS = NULL; + HRESULT ret = DirectSoundCreate(NULL, &lpDS, NULL); + if (ret == DS_OK && lpDS != NULL) { + lpDS->Release(); + return TRUE; + } + + return FALSE; +} + +// OFFSET: ISLE 0x401d20 +LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + NotificationId type; + unsigned char keyCode = 0; + + if (!g_isle) { + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + } + + switch (uMsg) { + case WM_PAINT: + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + case WM_ACTIVATE: + return DefWindowProcA(hWnd, uMsg, 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,uMsg,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,uMsg,wParam,lParam); + case WM_GETMINMAXINFO: + ((MINMAXINFO*) lParam)->ptMaxTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1; + ((MINMAXINFO*) lParam)->ptMaxTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1; + ((MINMAXINFO*) lParam)->ptMinTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1; + ((MINMAXINFO*) lParam)->ptMinTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1; + return 0; + case WM_ENTERMENULOOP: + return DefWindowProcA(hWnd,uMsg,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,uMsg,wParam,lParam); + case WM_EXITMENULOOP: + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + case WM_MOVING: + if (g_isle && g_isle->m_fullScreen) { + GetWindowRect(hWnd, (LPRECT) lParam); + return 0; + } + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + case WM_NCPAINT: + if (g_isle && g_isle->m_fullScreen) { + return 0; + } + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + case WM_DISPLAYCHANGE: + if (g_isle && VideoManager() && g_isle->m_fullScreen && VideoManager()->m_unk74 && VideoManager()->m_unk74[0x220]) { + int targetWidth = LOWORD(lParam); + int targetHeight = HIWORD(lParam); + int targetDepth = wParam; + + if (g_waitingForTargetDepth) { + g_waitingForTargetDepth = 0; + g_targetDepth = targetDepth; + } + else { + BOOL valid = FALSE; + if (targetWidth == g_targetWidth && targetHeight == g_targetHeight && g_targetDepth == targetDepth) { + valid = TRUE; + } + + if (g_rmDisabled) { + if (valid) { + g_reqEnableRMDevice = 1; + } + } + else if (!valid) { + g_rmDisabled = 1; + Lego()->vtable38(); + VideoManager()->DisableRMDevice(); + } + } + } + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + 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_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, uMsg, wParam, lParam); + } + keyCode = wParam; + type = KEYDOWN; + break; + case WM_MOUSEMOVE: + g_mousemoved = 1; + type = MOUSEMOVE; + break; + case WM_TIMER: + type = TIMER; + 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; + } + break; + default: + return DefWindowProcA(hWnd,uMsg,wParam,lParam); + } + + if (g_isle) { + if (InputManager()) { + InputManager()->QueueEvent(type, wParam, LOWORD(lParam), HIWORD(lParam), keyCode); + } + if (g_isle && g_isle->m_drawCursor && type == MOUSEMOVE) { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + if (x >= 640) { + x = 639; + } + if (y >= 480) { + y = 479; + } + VideoManager()->MoveCursor(x,y); + } + } + + return 0; +} + +// OFFSET: ISLE 0x4023e0 +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 0x402740 BOOL Isle::ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize) { @@ -216,42 +683,72 @@ void Isle::LoadConfig() } } -// OFFSET: ISLE 0x401560 -void Isle::SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, - BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7, - BOOL wideViewAngle, char *deviceId) +// OFFSET: ISLE 0x402c20 +inline void Isle::Tick(BOOL sleepIfNotNextFrame) { - m_videoParam.flags().SetFullScreen(fullScreen); - m_videoParam.flags().SetFlipSurfaces(flipSurfaces); - m_videoParam.flags().SetBackBuffers(!backBuffers); - m_videoParam.flags().Set_f2bit0(!param_6); - m_videoParam.flags().Set_f1bit7(param_7); - m_videoParam.flags().SetWideViewAngle(wideViewAngle); - m_videoParam.flags().Set_f2bit1(1); - m_videoParam.SetDeviceName(deviceId); - if (using8bit) { - m_videoParam.flags().Set16Bit(0); - } - if (using16bit) { - m_videoParam.flags().Set16Bit(1); - } -} - -// OFFSET: ISLE 0x4013b0 -BOOL Isle::SetupLegoOmni() -{ - BOOL result = FALSE; - char mediaPath[256]; - GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, sizeof(mediaPath)); - - BOOL failure = Lego()->Create(MxOmniCreateParam(mediaPath, (struct HWND__ *) m_windowHandle, m_videoParam, MxOmniCreateFlags())) == FAILURE; - if (!failure) { - VariableTable()->SetVariable("ACTOR_01", ""); - TickleManager()->vtable1c(VideoManager(), 10); - result = TRUE; + if (!this->m_windowActive) { + Sleep(0); + return; } - return result; + 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); } // OFFSET: ISLE 0x402e80 diff --git a/ISLE/isle.h b/ISLE/isle.h index d899d037..d45d33a3 100644 --- a/ISLE/isle.h +++ b/ISLE/isle.h @@ -2,20 +2,9 @@ #define ISLE_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 "mxvideoparam.h" -#include "mxdirectdraw.h" -#include "mxdsaction.h" -#include "mxomni.h" -#include "res/resource.h" class Isle { @@ -25,24 +14,21 @@ public: void Close(); + BOOL SetupLegoOmni(); + void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, + BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7, + BOOL wideViewAngle, char *deviceId); + MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine); + BOOL ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize); int ReadRegBool(LPCSTR name, BOOL *out); int ReadRegInt(LPCSTR name, int *out); - MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine); - - void Tick(BOOL sleepIfNotNextFrame); - - BOOL SetupLegoOmni(); void LoadConfig(); - void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, - BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7, - BOOL wideViewAngle, char *deviceId); - + void Tick(BOOL sleepIfNotNextFrame); void SetupCursor(WPARAM wParam); -// private: - + // private: // 0 LPSTR m_hdPath; LPSTR m_cdPath; @@ -85,193 +71,6 @@ public: HCURSOR m_cursorBusy; HCURSOR m_cursorNo; HCURSOR m_cursorCurrent; - }; -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 diff --git a/ISLE/main.cpp b/ISLE/main.cpp deleted file mode 100644 index f45e9529..00000000 --- a/ISLE/main.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include - -#include "legoinc.h" -#include "define.h" - -#include "legoomni.h" -#include "isle.h" - -// OFFSET: ISLE 0x401ca0 -BOOL FindExistingInstance(void) -{ - HWND hWnd = FindWindowA(WNDCLASS_NAME, WINDOW_TITLE); - if (hWnd) { - if (SetForegroundWindow(hWnd)) { - ShowWindow(hWnd, SW_RESTORE); - } - return 0; - } - return 1; -} - -// OFFSET: ISLE 0x401ce0 -BOOL StartDirectSound(void) -{ - LPDIRECTSOUND lpDS = NULL; - HRESULT ret = DirectSoundCreate(NULL, &lpDS, NULL); - if (ret == DS_OK && lpDS != NULL) { - lpDS->Release(); - return TRUE; - } - - 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()) { - return 0; - } - - // Attempt to create DirectSound instance - BOOL soundReady = FALSE; - for (int i = 0; i < 20; i++) { - if (StartDirectSound()) { - soundReady = TRUE; - break; - } - Sleep(500); - } - - // 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", MB_OK); - return 0; - } - - // Create global app instance - g_isle = new Isle(); - - // Create window - 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); - return 0; - } - - // Get reference to window - HWND window; - if (g_isle->m_windowHandle) { - window = g_isle->m_windowHandle; - } - - // 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; - - while (!g_closed) { - while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (g_isle) { - g_isle->Tick(1); - } - } - - if (g_isle) { - g_isle->Tick(0); - } - - while (!g_closed) { - if (!PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { - break; - } - - MSG nextMsg; - if (!g_isle - || !g_isle->m_windowHandle - || msg.message != WM_MOUSEMOVE - || !PeekMessageA(&nextMsg, NULL, 0, 0, PM_NOREMOVE) - || nextMsg.message != WM_MOUSEMOVE) { - TranslateMessage(&msg); - DispatchMessageA(&msg); - } - - if (g_reqEnableRMDevice) { - g_reqEnableRMDevice = 0; - VideoManager()->EnableRMDevice(); - g_rmDisabled = 0; - Lego()->vtable3c(); - } - - if (g_closed) { - break; - } - - if (g_mousedown == 0) { -LAB_00401bc7: - if (g_mousemoved) { - g_mousemoved = FALSE; - } - } else if (g_mousemoved) { - if (g_isle) { - g_isle->Tick(0); - } - goto LAB_00401bc7; - } - } - } - - DestroyWindow(window); - - 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); -} \ No newline at end of file diff --git a/LEGO1/mxpalette.cpp b/LEGO1/mxpalette.cpp old mode 100755 new mode 100644 diff --git a/LEGO1/mxunknown100dc6b0.cpp b/LEGO1/mxunknown100dc6b0.cpp old mode 100755 new mode 100644 diff --git a/LEGO1/mxunknown100dc6b0.h b/LEGO1/mxunknown100dc6b0.h old mode 100755 new mode 100644 diff --git a/LEGO1/mxvideomanager.cpp b/LEGO1/mxvideomanager.cpp old mode 100755 new mode 100644 diff --git a/isle.mak b/isle.mak index 7eaf3d48..23583c29 100644 --- a/isle.mak +++ b/isle.mak @@ -311,7 +311,6 @@ CLEAN : -@erase "$(INTDIR)\define.obj" -@erase "$(INTDIR)\isle.obj" -@erase "$(INTDIR)\isle.res" - -@erase "$(INTDIR)\main.obj" -@erase "$(INTDIR)\vc40.pdb" -@erase ".\Release\ISLE.EXE" -@erase ".\Release\ISLE.PDB" @@ -372,7 +371,6 @@ LINK32_OBJS= \ "$(INTDIR)\define.obj" \ "$(INTDIR)\isle.obj" \ "$(INTDIR)\isle.res" \ - "$(INTDIR)\main.obj" \ ".\Release\LEGO1.LIB" ".\Release\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -401,7 +399,6 @@ CLEAN : -@erase "$(INTDIR)\define.obj" -@erase "$(INTDIR)\isle.obj" -@erase "$(INTDIR)\isle.res" - -@erase "$(INTDIR)\main.obj" -@erase "$(INTDIR)\vc40.idb" -@erase "$(INTDIR)\vc40.pdb" -@erase ".\Debug\ISLE.EXE" @@ -464,7 +461,6 @@ LINK32_OBJS= \ "$(INTDIR)\define.obj" \ "$(INTDIR)\isle.obj" \ "$(INTDIR)\isle.res" \ - "$(INTDIR)\main.obj" \ ".\LEGO1\Debug\LEGO1.lib" ".\Debug\ISLE.EXE" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -917,6 +913,7 @@ DEP_CPP_MXPAL=\ SOURCE=.\LEGO1\mxioinfo.cpp DEP_CPP_MXIOI=\ + ".\LEGO1\legoinc.h"\ ".\LEGO1\mxioinfo.h"\ @@ -930,6 +927,7 @@ DEP_CPP_MXIOI=\ SOURCE=.\LEGO1\mxdsfile.cpp DEP_CPP_MXDSF=\ + ".\LEGO1\legoinc.h"\ ".\LEGO1\mxbool.h"\ ".\LEGO1\mxcore.h"\ ".\LEGO1\mxdsfile.h"\ @@ -974,19 +972,6 @@ DEP_CPP_MXDSS=\ ################################################################################ # Begin Source File -SOURCE=.\ISLE\define.cpp -DEP_CPP_DEFIN=\ - ".\ISLE\define.h"\ - - -"$(INTDIR)\define.obj" : $(SOURCE) $(DEP_CPP_DEFIN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -# End Source File -################################################################################ -# Begin Source File - SOURCE=.\ISLE\isle.cpp DEP_CPP_ISLE_=\ ".\ISLE\define.h"\ @@ -1048,71 +1033,6 @@ DEP_CPP_ISLE_=\ $(CPP) $(CPP_PROJ) $(SOURCE) -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ISLE\main.cpp -DEP_CPP_MAIN_=\ - ".\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\mxdssource.h"\ - ".\LEGO1\mxeventmanager.h"\ - ".\LEGO1\mxioinfo.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\mxunknown100dc6b0.h"\ - ".\LEGO1\mxvariabletable.h"\ - ".\LEGO1\mxvideomanager.h"\ - ".\LEGO1\mxvideoparam.h"\ - ".\LEGO1\mxvideoparamflags.h"\ - ".\LEGO1\viewmanager.h"\ - - -"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - # End Source File ################################################################################ # Begin Source File @@ -1262,18 +1182,6 @@ SOURCE=.\LEGO1\legoworldpresenter.h ################################################################################ # Begin Source File -SOURCE=.\LEGO1\mxatomid.h - -!IF "$(CFG)" == "ISLE - Win32 Release" - -!ELSEIF "$(CFG)" == "ISLE - Win32 Debug" - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - SOURCE=.\LEGO1\mxbackgroundaudiomanager.h !IF "$(CFG)" == "ISLE - Win32 Release" @@ -1553,6 +1461,32 @@ SOURCE=.\LEGO1\mxvideoparamflags.h !ENDIF # End Project Dependency +################################################################################ +# Begin Source File + +SOURCE=.\LEGO1\mxatomid.h + +!IF "$(CFG)" == "ISLE - Win32 Release" + +!ELSEIF "$(CFG)" == "ISLE - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\ISLE\define.cpp +DEP_CPP_DEFIN=\ + ".\ISLE\define.h"\ + ".\LEGO1\legoinc.h"\ + + +"$(INTDIR)\define.obj" : $(SOURCE) $(DEP_CPP_DEFIN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File # End Target # End Project ################################################################################ diff --git a/isle.mdp b/isle.mdp index 9449bd89ad80f94b71cded5a7863892a0bbb9186..d9512305a07494826c1af13a85dc6a272fbd5283 100644 GIT binary patch literal 51200 zcmeHQTX!7A5w69OBgqC|B-vnY!nqLwi!R21xg=OJjvW!ef;b5x$?VKXJ7_LCv$OL0 zJr6qk4*mfTye4_gpWvA%{sF1(x%EtU&rS=+ilx#ymiEYBbyt5=eW|LR((R3#izi?L z9Dv7wzK$IOKhW2)X5ianJ$f4apW$V&;W9i4jEg7ucVgxEFd%Mt-yff0(?~N0Cg3Nc z3D9R^fEXYKhyh}N7$63S0b+m{AO?s5Vt^Pp!VG*f0bl?7iwXEA`~$wdxIcM$=JM*b z%})nzJlI_A$KD|EtZ;KJx)=J9BR)ft$E6VS6X?cv zr}OT3p|t9N?`}s{=ml2dMPXihp#P4EcyH+Wju&nh(yyCHZ(D&oNbtS>ZvUEzoEPp6 zlcLMFO+r7Pspz2 zy9t}*ttVSBV$82B8;T5ue$s7k_Q7b7U|EsCj>064e4nic2G2PaHd;h@kGNcR`){_V zFY)Xh-z}EA)=Nk*N?*5VzoMf=Y=r}_vL6^|x@X0n)x(F)z8Ot5zHnuh)p~u+s^)O9 z%%Tk}EUSFeZ^0+ul^u7>3*B^IhFQKT6r25;+Z%3+TfKoEd|BeVed{SDl(gw|T3amJ z?)jR*J8Qko2O~R1i?A(!fOC?qYh3<~_6A(7q|@oN9%pXBZO=k^F{N^p23iUxXi88i znwp`he7P{EQ-I6A*Ph^-d=Jl^=|gI58^ywOaMceobY_yFwI?jVynmBDdJy%#K)W;^ zZ&~=N(=nI}!*D0W3SLW#i;jJ@x0rU@`iv&m`Ra6DYyX_{jg*sQ@NCO!T?WfVaV9Z; zB!g%e+xb#?zTy^1DHZ-jujJaXmBPN<=GN_i^W>_&QB*fir|Lnxtt@stuFGt8G{DXVBX0)Po1jw~)&yZnS!w*W=6$pJ9DfZx~qxon`#=s^Z|vwmF(_ zNDb|u3P$--+JM4`kY||nopVr{Q`Up<$)kCMZPueXzE9Q?&iaj(i;0Te3n$Hn2KgdCOgy~aq96C<)ZE(byRc$Mjj<$-5$|>@V9(_t1m+pax4BhO zha#-OM5G(sDv66?Clw!9j_nm85Y~G2rnai-XT+xKx3g6OMT|{!g=ICK7TZP7LA-^n zYWAFn&zxtu)ym-N=S~@38C?B_wMvW2xfV^%wA@d@NqLi6)%sbX^(6ZFeHQyEk|ebIj`cEFbS!aJ4mLO@vXHf5YJrqbUW z1Is;58CIB6?imUf=kWX|3kckcuA~eU^eml88TM3ZK$1Htql+meIFvG~SdBC;r7R(6 zA-Rb%S}@hpsbj}w87f#!32m^NNuKcTVD0xjQBwv;<%CEXLX&$&s_OZ4g???kz3iHD zgFA4NXP6oQGq~lXH~1Pr4?GNeLAQbF;>q)x?MsJ$;BnqI(Q2bu@EjYFya(zA^gjq4 z^CqR;Qm4QJ4>WTEiF$oqXT=?wI!>UZZGW)#MU#5a!g2Wtw0=UFHr zyF_7d`@TR2g~5wdrN9b>!7*HV$YJpIfonR-==L-^%8bu~(@`e9sYOQ_ysjeb0sQnd z-oK%YzGvgh(Udo6%B)dFUwjv`!M8b@8U6GqBYtN$Wa*0-AO?s5Vt^PR28aP-;Ak`O zYhyh}N7$6211Ft|AUWG+if@N5NEASdzh1cN? zcoVL{Tktl#1Mk9b;J5G|T!&RygB$QZ+=So3Ew~N8hjsV>{s14sNANM+ferWsK7~KR zUHB7``$#bGGGN`uM?zClk{BQchyh}N7$63S0b+m{AO?s5Vt^PR27WvP{O>juxr0D9&HtGuVXB;ji#F_&Zq8`|+kkEj%&|Ov8Tx4SnN| literal 52224 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 l%ncu}wfH6?d