Isle
Loading...
Searching...
No Matches
isleapp.cpp
Go to the documentation of this file.
1#include "isleapp.h"
2
4#include "decomp.h"
7#include "legogamestate.h"
8#include "legoinputmanager.h"
9#include "legomain.h"
10#include "legomodelpresenter.h"
11#include "legopartpresenter.h"
12#include "legoutils.h"
13#include "legovideomanager.h"
14#include "legoworldpresenter.h"
15#include "misc.h"
18#include "mxdsaction.h"
19#include "mxmisc.h"
20#include "mxomnicreateflags.h"
21#include "mxomnicreateparam.h"
22#include "mxstreamer.h"
23#include "mxticklemanager.h"
24#include "mxtimer.h"
25#include "mxtransitionmanager.h"
26#include "mxvariabletable.h"
27#include "res/resource.h"
28#include "roi/legoroi.h"
30
31#include <dsound.h>
32
34
35// GLOBAL: ISLE 0x410030
37
38// GLOBAL: ISLE 0x410034
39unsigned char g_mousedown = 0;
40
41// GLOBAL: ISLE 0x410038
42unsigned char g_mousemoved = 0;
43
44// GLOBAL: ISLE 0x41003c
46
47// GLOBAL: ISLE 0x410040
48RECT g_windowRect = {0, 0, 640, 480};
49
50// GLOBAL: ISLE 0x410050
52
53// GLOBAL: ISLE 0x410054
55
56// GLOBAL: ISLE 0x410058
57int g_targetWidth = 640;
58
59// GLOBAL: ISLE 0x41005c
61
62// GLOBAL: ISLE 0x410060
64
65// GLOBAL: ISLE 0x410064
67
68// STRING: ISLE 0x4101c4
69#define WNDCLASS_NAME "Lego Island MainNoM App"
70
71// STRING: ISLE 0x4101dc
72#define WINDOW_TITLE "LEGO\xAE"
73
74// Might be static functions of IsleApp
77
78// FUNCTION: ISLE 0x401000
80{
81 m_hdPath = NULL;
82 m_cdPath = NULL;
83 m_deviceId = NULL;
84 m_savePath = NULL;
85 m_fullScreen = TRUE;
86 m_flipSurfaces = FALSE;
87 m_backBuffersInVram = TRUE;
88 m_using8bit = FALSE;
89 m_using16bit = TRUE;
90 m_unk0x24 = 0;
91 m_drawCursor = FALSE;
92 m_use3dSound = TRUE;
93 m_useMusic = TRUE;
94 m_useJoystick = FALSE;
95 m_joystickIndex = 0;
96 m_wideViewAngle = TRUE;
97 m_islandQuality = 1;
98 m_islandTexture = 1;
99 m_gameStarted = FALSE;
100 m_frameDelta = 10;
101 m_windowActive = TRUE;
102
103#ifdef COMPAT_MODE
104 {
105 MxRect32 r(0, 0, 639, 479);
106 MxVideoParamFlags flags;
107 m_videoParam = MxVideoParam(r, NULL, 1, flags);
108 }
109#else
110 m_videoParam = MxVideoParam(MxRect32(0, 0, 639, 479), NULL, 1, MxVideoParamFlags());
111#endif
112 m_videoParam.Flags().Set16Bit(MxDirectDraw::GetPrimaryBitDepth() == 16);
113
114 m_windowHandle = NULL;
115 m_cursorArrow = NULL;
116 m_cursorBusy = NULL;
117 m_cursorNo = NULL;
118 m_cursorCurrent = NULL;
119
121}
122
123// FUNCTION: ISLE 0x4011a0
125{
126 if (LegoOmni::GetInstance()) {
127 Close();
129 }
130
131 if (m_hdPath) {
132 delete[] m_hdPath;
133 }
134
135 if (m_cdPath) {
136 delete[] m_cdPath;
137 }
138
139 if (m_deviceId) {
140 delete[] m_deviceId;
141 }
142
143 if (m_savePath) {
144 delete[] m_savePath;
145 }
146}
147
148// FUNCTION: ISLE 0x401260
150{
151 MxDSAction ds;
152 ds.SetUnknown24(-2);
153
154 if (Lego()) {
155 GameState()->Save(0);
156 if (InputManager()) {
157 InputManager()->QueueEvent(c_notificationKeyPress, 0, 0, 0, VK_SPACE);
158 }
159
161
162 Lego()->RemoveWorld(ds.GetAtomId(), ds.GetObjectId());
163 Lego()->DeleteObject(ds);
165 Lego()->Resume();
166
167 while (Streamer()->Close(NULL) == SUCCESS) {
168 }
169
170 while (Lego() && !Lego()->DoesEntityExist(ds)) {
171 Timer()->GetRealTime();
173 }
174 }
175}
176
177// FUNCTION: ISLE 0x4013b0
179{
180 BOOL result = FALSE;
181 char mediaPath[256];
182 GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, sizeof(mediaPath));
183
184#ifdef COMPAT_MODE
185 BOOL failure;
186 {
187 MxOmniCreateParam param(mediaPath, (struct HWND__*) m_windowHandle, m_videoParam, MxOmniCreateFlags());
188 failure = Lego()->Create(param) == FAILURE;
189 }
190#else
191 BOOL failure =
192 Lego()->Create(MxOmniCreateParam(mediaPath, (struct HWND__*) m_windowHandle, m_videoParam, MxOmniCreateFlags())
193 ) == FAILURE;
194#endif
195
196 if (!failure) {
197 VariableTable()->SetVariable("ACTOR_01", "");
199 result = TRUE;
200 }
201
202 return result;
203}
204
205// FUNCTION: ISLE 0x401560
207 BOOL fullScreen,
208 BOOL flipSurfaces,
209 BOOL backBuffers,
210 BOOL using8bit,
211 BOOL using16bit,
212 BOOL param_6,
213 BOOL param_7,
214 BOOL wideViewAngle,
215 char* deviceId
216)
217{
218 m_videoParam.Flags().SetFullScreen(fullScreen);
219 m_videoParam.Flags().SetFlipSurfaces(flipSurfaces);
220 m_videoParam.Flags().SetBackBuffers(!backBuffers);
221 m_videoParam.Flags().SetF2bit0(!param_6);
222 m_videoParam.Flags().SetF1bit7(param_7);
223 m_videoParam.Flags().SetWideViewAngle(wideViewAngle);
224 m_videoParam.Flags().SetF2bit1(1);
225 m_videoParam.SetDeviceName(deviceId);
226 if (using8bit) {
227 m_videoParam.Flags().Set16Bit(0);
228 }
229 if (using16bit) {
230 m_videoParam.Flags().Set16Bit(1);
231 }
232}
233
234// FUNCTION: ISLE 0x401610
235int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
236{
237 // Look for another instance, if we find one, bring it to the foreground instead
238 if (!FindExistingInstance()) {
239 return 0;
240 }
241
242 // Attempt to create DirectSound instance
243 BOOL soundReady = FALSE;
244 for (int i = 0; i < 20; i++) {
245 if (StartDirectSound()) {
246 soundReady = TRUE;
247 break;
248 }
249 Sleep(500);
250 }
251
252 // Throw error if sound unavailable
253 if (!soundReady) {
254 MessageBoxA(
255 NULL,
256 "\"LEGO\xAE Island\" is not detecting a DirectSound compatible sound card. Please quit all other "
257 "applications and try again.",
258 "Lego Island Error",
259 MB_OK
260 );
261 return 0;
262 }
263
264 // Create global app instance
265 g_isle = new IsleApp();
266
267 // Create window
268 if (g_isle->SetupWindow(hInstance, lpCmdLine) != SUCCESS) {
269 MessageBoxA(
270 NULL,
271 "\"LEGO\xAE Island\" failed to start. Please quit all other applications and try again.",
272 "LEGO\xAE Island Error",
273 MB_OK
274 );
275 return 0;
276 }
277
278 // Get reference to window
279 HWND window;
280 if (g_isle->GetWindowHandle()) {
281 window = g_isle->GetWindowHandle();
282 }
283
284 // Load accelerators (this call actually achieves nothing - there is no "AppAccel" resource in the original - but
285 // we'll keep this for authenticity) This line may actually be here because it's in DFVIEW, an example project that
286 // ships with MSVC420, and was such a clean example of a Win32 app, that it was later adapted into an "ExeSkeleton"
287 // sample for MSVC600. It's quite possible Mindscape derived this app from that example since they no longer had the
288 // luxury of the MFC AppWizard which we know they used for the frontend used during development (ISLEMFC.EXE,
289 // MAIN.EXE, et al.)
290 LoadAcceleratorsA(hInstance, "AppAccel");
291
292 MSG msg;
293
294 while (!g_closed) {
295 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)) {
296 if (g_isle) {
297 g_isle->Tick(1);
298 }
299 }
300
301 if (g_isle) {
302 g_isle->Tick(0);
303 }
304
305 while (!g_closed) {
306 if (!PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
307 break;
308 }
309
310 MSG nextMsg;
311 if (!g_isle || !g_isle->GetWindowHandle() || msg.message != WM_MOUSEMOVE ||
312 !PeekMessageA(&nextMsg, NULL, 0, 0, PM_NOREMOVE) || nextMsg.message != WM_MOUSEMOVE) {
313 TranslateMessage(&msg);
314 DispatchMessageA(&msg);
315 }
316
321 Lego()->Resume();
322 }
323
324 if (g_closed) {
325 break;
326 }
327
328 if (g_mousedown && g_mousemoved && g_isle) {
329 g_isle->Tick(0);
330 }
331
332 if (g_mousemoved) {
334 }
335 }
336 }
337
338 DestroyWindow(window);
339
340 return msg.wParam;
341}
342
343// FUNCTION: ISLE 0x401ca0
345{
346 HWND hWnd = FindWindowA(WNDCLASS_NAME, WINDOW_TITLE);
347 if (hWnd) {
348 if (SetForegroundWindow(hWnd)) {
349 ShowWindow(hWnd, SW_RESTORE);
350 }
351 return 0;
352 }
353 return 1;
354}
355
356// FUNCTION: ISLE 0x401ce0
358{
359 LPDIRECTSOUND lpDS = NULL;
360 HRESULT ret = DirectSoundCreate(NULL, &lpDS, NULL);
361 if (ret == DS_OK && lpDS != NULL) {
362 lpDS->Release();
363 return TRUE;
364 }
365
366 return FALSE;
367}
368
369// FUNCTION: ISLE 0x401d20
370LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
371{
372 NotificationId type;
373 unsigned char keyCode = 0;
374
375 if (!g_isle) {
376 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
377 }
378
379 switch (uMsg) {
380 case WM_PAINT:
381 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
382 case WM_ACTIVATE:
383 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
384 case WM_ACTIVATEAPP:
385 if (g_isle) {
386 if ((wParam != 0) && (g_isle->GetFullScreen())) {
387 MoveWindow(
388 hWnd,
389 g_windowRect.left,
390 g_windowRect.top,
391 (g_windowRect.right - g_windowRect.left) + 1,
392 (g_windowRect.bottom - g_windowRect.top) + 1,
393 TRUE
394 );
395 }
396 g_isle->SetWindowActive(wParam);
397 }
398 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
399 case WM_CLOSE:
400 if (!g_closed && g_isle) {
401 delete g_isle;
402 g_isle = NULL;
403 g_closed = TRUE;
404 return 0;
405 }
406 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
407 case WM_GETMINMAXINFO:
408 ((MINMAXINFO*) lParam)->ptMaxTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1;
409 ((MINMAXINFO*) lParam)->ptMaxTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1;
410 ((MINMAXINFO*) lParam)->ptMinTrackSize.x = (g_windowRect.right - g_windowRect.left) + 1;
411 ((MINMAXINFO*) lParam)->ptMinTrackSize.y = (g_windowRect.bottom - g_windowRect.top) + 1;
412 return 0;
413 case WM_ENTERMENULOOP:
414 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
415 case WM_SYSCOMMAND:
416 if (wParam == SC_SCREENSAVE) {
417 return 0;
418 }
419 if (wParam == SC_CLOSE && g_closed == FALSE) {
420 if (g_isle) {
421 if (g_rmDisabled) {
422 ShowWindow(g_isle->GetWindowHandle(), SW_RESTORE);
423 }
424 PostMessageA(g_isle->GetWindowHandle(), WM_CLOSE, 0, 0);
425 return 0;
426 }
427 }
428 else if (g_isle && g_isle->GetFullScreen() && (wParam == SC_MOVE || wParam == SC_KEYMENU)) {
429 return 0;
430 }
431 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
432 case WM_EXITMENULOOP:
433 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
434 case WM_MOVING:
435 if (g_isle && g_isle->GetFullScreen()) {
436 GetWindowRect(hWnd, (LPRECT) lParam);
437 return 0;
438 }
439 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
440 case WM_NCPAINT:
441 if (g_isle && g_isle->GetFullScreen()) {
442 return 0;
443 }
444 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
445 case WM_DISPLAYCHANGE:
446 if (g_isle && VideoManager() && g_isle->GetFullScreen() && VideoManager()->GetDirect3D()) {
447 if (VideoManager()->GetDirect3D()->AssignedDevice()) {
448 int targetDepth = wParam;
449 int targetWidth = LOWORD(lParam);
450 int targetHeight = HIWORD(lParam);
451
454 g_targetDepth = targetDepth;
455 }
456 else {
457 BOOL valid = FALSE;
458
459 if (g_targetWidth == targetWidth && g_targetHeight == targetHeight &&
460 g_targetDepth == targetDepth) {
461 valid = TRUE;
462 }
463
464 if (g_rmDisabled) {
465 if (valid) {
467 }
468 }
469 else if (!valid) {
471 Lego()->Pause();
473 }
474 }
475 }
476 }
477 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
478 case WM_KEYDOWN:
479 // While this probably should be (HIWORD(lParam) & KF_REPEAT), this seems
480 // to be what the assembly is actually doing
481 if (lParam & (KF_REPEAT << 16)) {
482 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
483 }
485 keyCode = wParam;
486 break;
487 case WM_MOUSEMOVE:
488 g_mousemoved = 1;
490 break;
491 case WM_TIMER:
492 type = c_notificationTimer;
493 break;
494 case WM_LBUTTONDOWN:
495 g_mousedown = 1;
497 break;
498 case WM_LBUTTONUP:
499 g_mousedown = 0;
501 break;
503 if (g_isle) {
504 g_isle->SetupCursor(wParam);
505 return 0;
506 }
507 break;
508 case WM_SETCURSOR:
511 SetCursor(g_isle->GetCursorCurrent());
512 return 0;
513 }
514 break;
515 default:
516 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
517 }
518
519 if (g_isle) {
520 if (InputManager()) {
521 InputManager()->QueueEvent(type, wParam, LOWORD(lParam), HIWORD(lParam), keyCode);
522 }
523 if (g_isle && g_isle->GetDrawCursor() && type == c_notificationMouseMove) {
524 int x = LOWORD(lParam);
525 int y = HIWORD(lParam);
526 if (x >= 640) {
527 x = 639;
528 }
529 if (y >= 480) {
530 y = 479;
531 }
532 VideoManager()->MoveCursor(x, y);
533 }
534 }
535
536 return 0;
537}
538
539// FUNCTION: ISLE 0x4023e0
540MxResult IsleApp::SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine)
541{
542 WNDCLASSA wndclass;
543 ZeroMemory(&wndclass, sizeof(WNDCLASSA));
544
545 LoadConfig();
546
548 m_fullScreen,
549 m_flipSurfaces,
550 m_backBuffersInVram,
551 m_using8bit,
552 m_using16bit,
553 m_unk0x24,
554 FALSE,
555 m_wideViewAngle,
556 m_deviceId
557 );
558
559 MxOmni::SetSound3D(m_use3dSound);
560
561 srand(timeGetTime() / 1000);
562 SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, NULL, 0);
563
564 ZeroMemory(&wndclass, sizeof(WNDCLASSA));
565
566 wndclass.cbClsExtra = 0;
567 wndclass.style = CS_HREDRAW | CS_VREDRAW;
568 wndclass.lpfnWndProc = WndProc;
569 wndclass.cbWndExtra = 0;
570 wndclass.hIcon = LoadIconA(hInstance, MAKEINTRESOURCEA(APP_ICON));
571 wndclass.hCursor = m_cursorArrow = m_cursorCurrent = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_ARROW));
572 m_cursorBusy = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_BUSY));
573 m_cursorNo = LoadCursorA(hInstance, MAKEINTRESOURCEA(ISLE_NO));
574 wndclass.hInstance = hInstance;
575 wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
576 wndclass.lpszClassName = WNDCLASS_NAME;
577
578 if (!RegisterClassA(&wndclass)) {
579 return FAILURE;
580 }
581
582 if (m_fullScreen) {
583 AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
584
585 m_windowHandle = CreateWindowExA(
586 WS_EX_APPWINDOW,
589 WS_CAPTION | WS_SYSMENU,
590 g_windowRect.left,
591 g_windowRect.top,
592 g_windowRect.right - g_windowRect.left + 1,
593 g_windowRect.bottom - g_windowRect.top + 1,
594 NULL,
595 NULL,
596 hInstance,
597 NULL
598 );
599 }
600 else {
601 AdjustWindowRectEx(&g_windowRect, WS_CAPTION | WS_SYSMENU, 0, WS_EX_APPWINDOW);
602
603 m_windowHandle = CreateWindowExA(
604 WS_EX_APPWINDOW,
607 WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
608 CW_USEDEFAULT,
609 CW_USEDEFAULT,
610 g_windowRect.right - g_windowRect.left + 1,
611 g_windowRect.bottom - g_windowRect.top + 1,
612 NULL,
613 NULL,
614 hInstance,
615 NULL
616 );
617 }
618
619 if (!m_windowHandle) {
620 return FAILURE;
621 }
622
623 if (m_fullScreen) {
624 MoveWindow(
625 m_windowHandle,
626 g_windowRect.left,
627 g_windowRect.top,
628 (g_windowRect.right - g_windowRect.left) + 1,
629 (g_windowRect.bottom - g_windowRect.top) + 1,
630 TRUE
631 );
632 }
633
634 ShowWindow(m_windowHandle, SW_SHOWNORMAL);
635 UpdateWindow(m_windowHandle);
636 if (!SetupLegoOmni()) {
637 return FAILURE;
638 }
639
640 GameState()->SetSavePath(m_savePath);
643
644 int iVar10;
645 switch (m_islandQuality) {
646 case 0:
647 iVar10 = 1;
648 break;
649 case 1:
650 iVar10 = 2;
651 break;
652 default:
653 iVar10 = 100;
654 }
655
656 int uVar1 = (m_islandTexture == 0);
663 if (LegoOmni::GetInstance()) {
664 if (LegoOmni::GetInstance()->GetInputManager()) {
667 }
668 }
669 if (m_fullScreen) {
670 MoveWindow(
671 m_windowHandle,
672 g_windowRect.left,
673 g_windowRect.top,
674 (g_windowRect.right - g_windowRect.left) + 1,
675 (g_windowRect.bottom - g_windowRect.top) + 1,
676 TRUE
677 );
678 }
679 ShowWindow(m_windowHandle, SW_SHOWNORMAL);
680 UpdateWindow(m_windowHandle);
681
682 return SUCCESS;
683}
684
685// FUNCTION: ISLE 0x402740
686BOOL IsleApp::ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize)
687{
688 HKEY hKey;
689 DWORD valueType;
690
691 BOOL out = FALSE;
692 DWORD size = outSize;
693 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Mindscape\\LEGO Island", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
694 if (RegQueryValueExA(hKey, name, NULL, &valueType, (LPBYTE) outValue, &size) == ERROR_SUCCESS) {
695 if (RegCloseKey(hKey) == ERROR_SUCCESS) {
696 out = TRUE;
697 }
698 }
699 }
700
701 return out;
702}
703
704// FUNCTION: ISLE 0x4027b0
706{
707 char buffer[256];
708
709 BOOL read = ReadReg(name, buffer, sizeof(buffer));
710 if (read) {
711 if (strcmp("YES", buffer) == 0) {
712 *out = TRUE;
713 return read;
714 }
715
716 if (strcmp("NO", buffer) == 0) {
717 *out = FALSE;
718 return read;
719 }
720
721 read = FALSE;
722 }
723 return read;
724}
725
726// FUNCTION: ISLE 0x402880
727BOOL IsleApp::ReadRegInt(LPCSTR name, int* out)
728{
729 char buffer[256];
730
731 BOOL read = ReadReg(name, buffer, sizeof(buffer));
732 if (read) {
733 *out = atoi(buffer);
734 }
735
736 return read;
737}
738
739// FUNCTION: ISLE 0x4028d0
741{
742 char buffer[1024];
743
744 if (!ReadReg("diskpath", buffer, sizeof(buffer))) {
745 strcpy(buffer, MxOmni::GetHD());
746 }
747
748 m_hdPath = new char[strlen(buffer) + 1];
749 strcpy(m_hdPath, buffer);
750 MxOmni::SetHD(m_hdPath);
751
752 if (!ReadReg("cdpath", buffer, sizeof(buffer))) {
753 strcpy(buffer, MxOmni::GetCD());
754 }
755
756 m_cdPath = new char[strlen(buffer) + 1];
757 strcpy(m_cdPath, buffer);
758 MxOmni::SetCD(m_cdPath);
759
760 ReadRegBool("Flip Surfaces", &m_flipSurfaces);
761 ReadRegBool("Full Screen", &m_fullScreen);
762 ReadRegBool("Wide View Angle", &m_wideViewAngle);
763 ReadRegBool("3DSound", &m_use3dSound);
764 ReadRegBool("Music", &m_useMusic);
765 ReadRegBool("UseJoystick", &m_useJoystick);
766 ReadRegInt("JoystickIndex", &m_joystickIndex);
767 ReadRegBool("Draw Cursor", &m_drawCursor);
768
769 int backBuffersInVRAM;
770 if (ReadRegBool("Back Buffers in Video RAM", &backBuffersInVRAM)) {
771 m_backBuffersInVram = !backBuffersInVRAM;
772 }
773
774 int bitDepth;
775 if (ReadRegInt("Display Bit Depth", &bitDepth)) {
776 if (bitDepth == 8) {
777 m_using8bit = TRUE;
778 }
779 else if (bitDepth == 16) {
780 m_using16bit = TRUE;
781 }
782 }
783
784 if (!ReadReg("Island Quality", buffer, sizeof(buffer))) {
785 strcpy(buffer, "1");
786 }
787 m_islandQuality = atoi(buffer);
788
789 if (!ReadReg("Island Texture", buffer, sizeof(buffer))) {
790 strcpy(buffer, "1");
791 }
792 m_islandTexture = atoi(buffer);
793
794 if (ReadReg("3D Device ID", buffer, sizeof(buffer))) {
795 m_deviceId = new char[strlen(buffer) + 1];
796 strcpy(m_deviceId, buffer);
797 }
798
799 if (ReadReg("savepath", buffer, sizeof(buffer))) {
800 m_savePath = new char[strlen(buffer) + 1];
801 strcpy(m_savePath, buffer);
802 }
803}
804
805// FUNCTION: ISLE 0x402c20
806inline void IsleApp::Tick(BOOL sleepIfNotNextFrame)
807{
808 // GLOBAL: ISLE 0x4101c0
809 static MxLong g_lastFrameTime = 0;
810
811 // GLOBAL: ISLE 0x4101bc
812 static int g_startupDelay = 200;
813
814 if (!m_windowActive) {
815 Sleep(0);
816 return;
817 }
818
819 if (!Lego()) {
820 return;
821 }
822 if (!TickleManager()) {
823 return;
824 }
825 if (!Timer()) {
826 return;
827 }
828
829 MxLong currentTime = Timer()->GetRealTime();
830 if (currentTime < g_lastFrameTime) {
831 g_lastFrameTime = -m_frameDelta;
832 }
833
834 if (m_frameDelta + g_lastFrameTime < currentTime) {
835 if (!Lego()->IsPaused()) {
837 }
838 g_lastFrameTime = currentTime;
839
840 if (g_startupDelay == 0) {
841 return;
842 }
843
844 g_startupDelay--;
845 if (g_startupDelay != 0) {
846 return;
847 }
848
850 BackgroundAudioManager()->Enable(this->m_useMusic);
851
852 MxStreamController* stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", MxStreamer::e_diskStream);
853 MxDSAction ds;
854
855 if (!stream) {
856 stream = Streamer()->Open("\\lego\\scripts\\nocd", MxStreamer::e_diskStream);
857 if (!stream) {
858 return;
859 }
860
861 ds.SetAtomId(stream->GetAtom());
862 ds.SetUnknown24(-1);
863 ds.SetObjectId(0);
865
866 if (Start(&ds) != SUCCESS) {
867 return;
868 }
869 }
870 else {
871 ds.SetAtomId(stream->GetAtom());
872 ds.SetUnknown24(-1);
873 ds.SetObjectId(0);
874 if (Start(&ds) != SUCCESS) {
875 return;
876 }
877 m_gameStarted = TRUE;
878 }
879 }
880 else if (sleepIfNotNextFrame != 0) {
881 Sleep(0);
882 }
883}
884
885// FUNCTION: ISLE 0x402e80
886void IsleApp::SetupCursor(WPARAM wParam)
887{
888 switch (wParam) {
889 case e_cursorArrow:
890 m_cursorCurrent = m_cursorArrow;
891 break;
892 case e_cursorBusy:
893 m_cursorCurrent = m_cursorBusy;
894 break;
895 case e_cursorNo:
896 m_cursorCurrent = m_cursorNo;
897 break;
898 case e_cursorNone:
899 m_cursorCurrent = NULL;
900 case e_cursorUnused3:
901 case e_cursorUnused4:
902 case e_cursorUnused5:
903 case e_cursorUnused6:
904 case e_cursorUnused7:
905 case e_cursorUnused8:
906 case e_cursorUnused9:
907 case e_cursorUnused10:
908 break;
909 }
910
911 SetCursor(m_cursorCurrent);
912}
#define ISLE_NO
[AI] Resource ID for the custom "no" cursor, typically indicates an invalid action or forbidden area.
#define APP_ICON
[AI] Resource ID for the main application icon (e.g., window/taskbar icon for LEGO Island).
#define ISLE_ARROW
[AI] Resource ID definitions for cursor icons and application icon.
#define ISLE_BUSY
[AI] Resource ID for the custom "busy" cursor, used to indicate processes such as loading or waiting.
[AI] Main application class for LEGO Island.
Definition: isleapp.h:14
void Tick(BOOL sleepIfNotNextFrame)
[AI] Executes a single frame tick/update for the game, managing timing, engine state,...
Definition: isleapp.cpp:806
MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine)
[AI] Creates the application window, registers the window class, loads icons/cursors,...
Definition: isleapp.cpp:540
HCURSOR GetCursorCurrent()
[AI] Gets the HCURSOR currently active for the application.
Definition: isleapp.h:133
void SetupCursor(WPARAM wParam)
[AI] Sets the current mouse cursor based on application or game state.
Definition: isleapp.cpp:886
void LoadConfig()
[AI] Loads all configuration from the registry (disk path, CD path, sound, joystick,...
Definition: isleapp.cpp:740
BOOL GetDrawCursor()
[AI] Returns TRUE if the application is drawing the custom cursor.
Definition: isleapp.h:148
void SetWindowActive(BOOL p_windowActive)
[AI] Sets application window active status (focus/active state).
Definition: isleapp.h:155
BOOL ReadRegBool(LPCSTR name, BOOL *out)
[AI] Reads a boolean (YES/NO string) value from registry.
Definition: isleapp.cpp:705
BOOL SetupLegoOmni()
[AI] Initializes the core LEGO Island engine with the current settings and media path.
Definition: isleapp.cpp:178
void SetupVideoFlags(BOOL fullScreen, BOOL flipSurfaces, BOOL backBuffers, BOOL using8bit, BOOL using16bit, BOOL param_6, BOOL param_7, BOOL wideViewAngle, char *deviceId)
[AI] Configures video mode and 3D device flags for rendering (fullscreen, backbuffers,...
Definition: isleapp.cpp:206
HCURSOR GetCursorNo()
[AI] Gets the HCURSOR representing the "not allowed" cursor.
Definition: isleapp.h:143
~IsleApp()
[AI] Destructor.
Definition: isleapp.cpp:124
BOOL GetFullScreen()
[AI] Returns TRUE if the game is in fullscreen mode.
Definition: isleapp.h:128
void Close()
[AI] Gracefully closes down the LEGO Island game, including engine teardown and saving player progres...
Definition: isleapp.cpp:149
IsleApp()
[AI] Constructor.
Definition: isleapp.cpp:79
HCURSOR GetCursorBusy()
[AI] Gets the HCURSOR representing the "busy" cursor.
Definition: isleapp.h:138
HWND GetWindowHandle()
[AI] Returns the handle to the main application window.
Definition: isleapp.h:118
BOOL ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize)
[AI] Reads a string value from the LEGO Island registry key under HKLM.
Definition: isleapp.cpp:686
BOOL ReadRegInt(LPCSTR name, int *out)
[AI] Reads an integer value from registry.
Definition: isleapp.cpp:727
Lego3DView * GetLego3DView()
[AI] Returns the encapsulated Lego3DView instance.
ViewManager * GetViewManager()
[AI] Returns the ViewManager responsible for managing scene objects and transformations.
Definition: lego3dview.h:154
static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig)
[AI] Updates the configuration values (global) for animation manager's allowed number of extras,...
static void configureLegoBuildingManager(MxS32 p_buildingManagerConfig)
[AI] Configure static settings for the LegoBuildingManager globally.
void SerializeScoreHistory(MxS16 p_flags)
Serializes the score history table to score file.
void SetSavePath(char *p_savePath)
Sets the path for current save slot directory; creates a copy of input string.
void SerializePlayersInfo(MxS16 p_flags)
Serializes all player info (usernames, player count) to the appropriate storage.
MxResult Save(MxULong p_slot)
Saves persistent game state (world variables, actor, etc.) to a file slot.
void QueueEvent(NotificationId p_id, MxU8 p_modifier, MxLong p_x, MxLong p_y, MxU8 p_key)
[AI] Add an input event (for mouse, keyboard, or joystick) to the processing queue,...
void SetJoystickIndex(MxS32 p_joystickIndex)
[AI] Set user-preferred joystick device index (overrides auto-detection).
void SetUseJoystick(MxBool p_useJoystick)
[AI] Enable or disable joystick support in input processing.
static void configureLegoModelPresenter(MxS32 p_modelPresenterConfig)
[AI] Configures the LegoModelPresenter's handling of textures/model data.
void Resume() override
[AI] Resumes engine/game state and sets default cursor.
Definition: legomain.cpp:593
static LegoOmni * GetInstance()
[AI] Returns the current LegoOmni singleton pointer, cast from MxOmni.
Definition: legomain.cpp:305
void RemoveWorld(const MxAtomId &p_atom, MxLong p_objectId)
[AI] Removes worlds by Atom and/or id, deleting matching entries from the world list and freeing reso...
Definition: legomain.cpp:335
LegoInputManager * GetInputManager()
[AI] Returns the input manager.
Definition: legomain.h:353
static void CreateInstance()
[AI] Allocates and sets up a new LegoOmni singleton instance, replacing the previous one if any.
Definition: legomain.cpp:298
void CreateBackgroundAudio()
[AI] Initializes background audio manager and starts music using global script.
Definition: legomain.cpp:540
void Pause() override
[AI] Pauses the engine/game state and sets busy cursor.
Definition: legomain.cpp:586
MxResult Create(MxOmniCreateParam &p_param) override
[AI] Creates and initializes all subsystems for the game, wiring up all managers and attaching Lego-s...
Definition: legomain.cpp:156
void DeleteObject(MxDSAction &p_dsAction) override
[AI] Deletes an entity or world referenced by the given DSAction (by object and Atom),...
Definition: legomain.cpp:378
static void configureLegoPartPresenter(MxS32 p_partPresenterConfig1, MxS32 p_partPresenterConfig2)
[AI] Configure global settings for texture loading order and maximum number of LODs.
static void configureLegoROI(int p_roi)
[AI] [Static] Configures the global ROI loading limit, controlling max LODs at load time.
Definition: legoroi.cpp:66
@ c_read
Open for read operations. [AI].
Definition: legostorage.h:23
int EnableRMDevice()
[AI] Enables the Direct3D Retained Mode (RM) rendering device, and re-creates the device/viewport if ...
void EnableFullScreenMovie(MxBool p_enable)
[AI] Convenience method to enable or disable fullscreen movie playback with default scaling.
int DisableRMDevice()
[AI] Disables the Direct3D Retained Mode (RM) rendering device and saves/restores 3D state as needed.
Lego3DManager * Get3DManager()
[AI] Returns the Lego3DManager for this manager, which owns all 3D scene representations and view con...
void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY)
[AI] Updates the position of the custom software cursor overlay, and ensures it renders on the next f...
static void configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality)
[AI] Configure the global 'quality' level for presenting the LEGO world.
void Enable(MxBool p_enable)
[AI] Enables or disables the background audio manager.
[AI] Represents an action deserialized from SI chunks, holding key animation or script parameters suc...
Definition: mxdsaction.h:17
const MxAtomId & GetAtomId()
[AI] Returns a const-reference to the object's atom identifier.
Definition: mxdsobject.h:133
virtual void SetAtomId(MxAtomId p_atomId)
[AI] Sets the atom id for this object instance, used for indexing or lookup.
Definition: mxdsobject.h:118
void SetUnknown24(MxS16 p_unk0x24)
[AI] Sets the unknown field at 0x24 (possibly version/state).
Definition: mxdsobject.h:151
void SetObjectId(MxU32 p_objectId)
[AI] Sets the object id (for serialization or lookup).
Definition: mxdsobject.h:147
MxU32 GetObjectId()
[AI] Returns the object id numeric value.
Definition: mxdsobject.h:130
static int GetPrimaryBitDepth()
Returns the bit depth (color depth) of the primary display device.
[AI] Stores creation flags for initializing core LEGO Island engine subsystems.
[AI] Encapsulates parameters required to initialize the core Omni engine.
static const char * GetCD()
[AI] Retrieves the configured CD-ROM media path string used for resource location.
Definition: mxomni.cpp:375
static void SetCD(const char *p_cd)
[AI] Sets the global CD media path used for source file lookup.
Definition: mxomni.cpp:381
static void DestroyInstance()
[AI] Destroys the singleton MxOmni instance and performs memory cleanup.
Definition: mxomni.cpp:295
static const char * GetHD()
[AI] Retrieves the configured hard disk media path string used for resource location.
Definition: mxomni.cpp:363
static void SetSound3D(MxBool p_use3dSound)
[AI] Enables or disables use of 3D sound processing.
Definition: mxomni.cpp:393
static void SetHD(const char *p_hd)
[AI] Sets the global hard disk media path used for resource lookup.
Definition: mxomni.cpp:369
[AI] Rectangle using 32-bit signed integer coordinates.
Definition: mxgeometry.h:706
[AI] Controller for streaming and managing multimedia resources and actions during gameplay.
MxAtomId & GetAtom()
[AI] Retrieves the atom ID (unique logical identifier) for this stream controller.
MxStreamController * Open(const char *p_name, MxU16 p_openMode)
Open a stream, returning a controller for further access [AI].
Definition: mxstreamer.cpp:62
@ e_diskStream
Load streaming resource from disk [AI].
Definition: mxstreamer.h:71
virtual void SetClientTickleInterval(MxCore *p_client, MxTime p_interval)
[AI] Changes the tickle interval of an already registered client.
MxResult Tickle() override
[AI] Iterates over registered clients and invokes their Tickle() methods as needed.
MxLong GetRealTime()
Retrieves the elapsed real time (in ms) since timer construction or last reset.
Definition: mxtimer.cpp:23
void SetWaitIndicator(MxVideoPresenter *p_waitIndicator)
[AI] Sets or resets the visual wait indicator presented during blocking transitions.
void SetVariable(const char *p_key, const char *p_value)
Sets a variable by key and value, replacing or updating if it exists.
[AI] Manages video parameter flags, providing an abstraction for various video settings such as fulls...
void SetF1bit7(MxBool p_e)
[AI] Set an additional flag (purpose unknown; originally used by the engine for extension).
void SetF2bit1(MxBool p_e)
[AI] Set secondary flag 1 (often used for internal video logic).
void SetWideViewAngle(MxBool p_e)
[AI] Enable or disable a wider field of view for 3D rendering.
void SetBackBuffers(MxBool p_e)
[AI] Toggle the use of a back buffer (double-buffered rendering).
void SetF2bit0(MxBool p_e)
[AI] Set secondary flag 0 (often used for internal video logic).
void Set16Bit(MxBool p_e)
[AI] Specify whether 16-bit color depth should be used for rendering.
void SetFlipSurfaces(MxBool p_e)
[AI] Toggle the use of flip (page flipping) for surfaces.
void SetFullScreen(MxBool p_e)
[AI] Enable or disable fullscreen mode.
[AI] Video parameter configuration for display and rendering, encapsulates resolution,...
Definition: mxvideoparam.h:14
void SetDeviceName(char *p_deviceId)
[AI] Set the device name/id for this video parameter (e.g., a specific display adapter),...
MxVideoParamFlags & Flags()
[AI] Access the video parameter flags (windowed/fullscreen, rendering mode, etc).
Definition: mxvideoparam.h:45
void RemoveAll(ViewROI *p_roi)
[AI] Recursively removes all ViewROI objects.
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
typedef DWORD(FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper
HWND hWnd
Definition: ddraw.h:425
long HRESULT
Definition: ddraw.h:115
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
typedef BOOL(FAR PASCAL *LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA
HRESULT WINAPI DirectSoundCreate(LPGUID, LPDIRECTSOUND *, LPUNKNOWN)
struct IDirectSound * LPDIRECTSOUND
Definition: dsound.h:46
#define DS_OK
Definition: dsound.h:690
unsigned char g_mousemoved
Definition: isleapp.cpp:42
IsleApp * g_isle
Definition: isleapp.cpp:36
BOOL g_reqEnableRMDevice
Definition: isleapp.cpp:66
#define WINDOW_TITLE
Definition: isleapp.cpp:72
unsigned char g_mousedown
Definition: isleapp.cpp:39
BOOL g_waitingForTargetDepth
Definition: isleapp.cpp:54
BOOL FindExistingInstance()
Definition: isleapp.cpp:344
#define WNDCLASS_NAME
Definition: isleapp.cpp:69
BOOL StartDirectSound()
Definition: isleapp.cpp:357
BOOL g_rmDisabled
Definition: isleapp.cpp:51
LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: isleapp.cpp:370
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
Definition: isleapp.cpp:235
int g_targetDepth
Definition: isleapp.cpp:63
int g_targetWidth
Definition: isleapp.cpp:57
BOOL g_closed
Definition: isleapp.cpp:45
int g_targetHeight
Definition: isleapp.cpp:60
RECT g_windowRect
Definition: isleapp.cpp:48
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
#define WM_ISLE_SETCURSOR
[AI] Custom Windows message for setting the cursor in LEGO Island. Used with PostMessage....
Definition: legoutils.h:11
@ e_cursorUnused3
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:26
@ e_cursorUnused5
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:28
@ e_cursorUnused7
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:30
@ e_cursorBusy
[AI] Busy or loading cursor (e.g., hourglass). [AI]
Definition: legoutils.h:24
@ e_cursorNone
[AI] No cursor (invisible or hidden). [AI]
Definition: legoutils.h:34
@ e_cursorUnused10
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:33
@ e_cursorUnused8
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:31
@ e_cursorArrow
[AI] Standard arrow cursor. [AI]
Definition: legoutils.h:23
@ e_cursorUnused9
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:32
@ e_cursorUnused4
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:27
@ e_cursorUnused6
[AI] Reserved slot. Not used. [AI]
Definition: legoutils.h:29
@ e_cursorNo
[AI] 'Not allowed' cursor. [AI]
Definition: legoutils.h:25
LegoGameState * GameState()
[AI] Accessor for the game's central game state controller. [AI]
Definition: misc.cpp:61
LegoVideoManager * VideoManager()
[AI] Accessor for the game's LegoVideoManager subsystem. Used for managing 3D/video hardware....
Definition: misc.cpp:29
MxTransitionManager * TransitionManager()
[AI] Accessor for the MxTransitionManager, handling level transitions, fades, and world changes....
Definition: misc.cpp:208
MxBackgroundAudioManager * BackgroundAudioManager()
[AI] Accessor for the background audio manager. Used for background music and ambient sounds....
Definition: misc.cpp:37
LegoOmni * Lego()
[AI] Retrieves the global LegoOmni singleton instance, providing access to core subsystems.
Definition: misc.cpp:16
LegoInputManager * InputManager()
[AI] Accessor for the input manager, which handles keyboard, mouse, and controller input....
Definition: misc.cpp:45
MxTimer * Timer()
[AI] Returns the global simulation timer.
Definition: mxmisc.cpp:33
MxResult Start(MxDSAction *p_dsAction)
[AI] Schedules and initiates execution of a script action.
Definition: mxmisc.cpp:97
MxVariableTable * VariableTable()
[AI] Returns the variable table used for script variables and global key/value state.
Definition: mxmisc.cpp:73
MxStreamer * Streamer()
[AI] Returns the global streamer used for all chunked media streaming (SI file, audio,...
Definition: mxmisc.cpp:49
MxTickleManager * TickleManager()
[AI] Provides access to the global tickle manager.
Definition: mxmisc.cpp:25
NotificationId
Several of those should be defined in LegoOmni.
@ c_notificationTimer
[AI] Timer-related event [AI]
@ c_notificationButtonUp
[AI] Mouse/gamepad button release [AI]
@ c_notificationButtonDown
[AI] Mouse/gamepad button press [AI]
@ c_notificationMouseMove
[AI] Mouse movement event [AI]
@ c_notificationKeyPress
[AI] Keyboard key press detected [AI]
MxLong MxResult
[AI]
Definition: mxtypes.h:106
int MxLong
[AI]
Definition: mxtypes.h:83