From ccb6223d7023bda014d141cd3ddc7bf14779a330 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 7 Feb 2024 12:11:45 +0100 Subject: [PATCH] Decompiled CONFIG.EXE executable (#533) * mxdirectdraw: no need to explicitly add a terminating '\0' in C * mxstopwatch must include LIMITS.H for ULONG_MAX * Add Config app * 88.78% * style fixes * Test more CONFIG things * Add a few assertions on MFC classes * reformat * actionSSSSSSSSSSSSSSS * actions again * decomplint needed a shebang * Fix annotations of Message Map entries * ci: We're building CONFIG.EXE, not CONFIG.DLL * remove ninja.exe * Fix CAboutDialog::GetMessageMap annotation * format reloaded * Fix global CConfigApp object annotation * trigger worflows * ci: request at least python 3 * oops :) * curl CONFIGPROGRESS-OLD.TXT will fail * Forget about actions/setup-python (for now) * Annotation fixes * Config tweaks and MxDirect3d annotations * It's important to compare against the correct file * Introduce common CDialog parent for CAboutDialog and CMainDialog * format * Remove CSerializer --------- Co-authored-by: disinvite --- .github/workflows/analyze.yml | 28 +- .github/workflows/build.yml | 21 +- .github/workflows/format.yml | 2 +- CMakeLists.txt | 52 +++- CONFIG/AboutDlg.cpp | 19 ++ CONFIG/AboutDlg.h | 49 ++++ CONFIG/ConfigCommandLineInfo.cpp | 22 ++ CONFIG/ConfigCommandLineInfo.h | 22 ++ CONFIG/MainDlg.cpp | 344 ++++++++++++++++++++++++ CONFIG/MainDlg.h | 76 ++++++ CONFIG/common.cpp | 13 + CONFIG/common.h | 16 ++ CONFIG/config.cpp | 434 +++++++++++++++++++++++++++++++ CONFIG/config.h | 88 +++++++ CONFIG/detectdx5.cpp | 142 ++++++++++ CONFIG/detectdx5.h | 10 + CONFIG/library_mfc.h | 12 + CONFIG/res/config.rc | 82 ++++++ CONFIG/res/lego.ico | Bin 0 -> 1078 bytes CONFIG/res/resource.h | 25 ++ CONFIG/res/shark.bmp | Bin 0 -> 56230 bytes LEGO1/mxdirectx/mxdirect3d.cpp | 97 +++++-- LEGO1/mxdirectx/mxdirect3d.h | 24 +- LEGO1/mxdirectx/mxdirectdraw.cpp | 184 ++++++------- LEGO1/mxdirectx/mxstopwatch.h | 1 + tools/decomplint/decomplint.py | 7 +- tools/patch_c2.py | 0 tools/reccmp/config.png | Bin 0 -> 1432 bytes tools/vtable/vtable.py | 2 + 29 files changed, 1621 insertions(+), 151 deletions(-) create mode 100644 CONFIG/AboutDlg.cpp create mode 100644 CONFIG/AboutDlg.h create mode 100644 CONFIG/ConfigCommandLineInfo.cpp create mode 100644 CONFIG/ConfigCommandLineInfo.h create mode 100644 CONFIG/MainDlg.cpp create mode 100644 CONFIG/MainDlg.h create mode 100644 CONFIG/common.cpp create mode 100644 CONFIG/common.h create mode 100644 CONFIG/config.cpp create mode 100644 CONFIG/config.h create mode 100644 CONFIG/detectdx5.cpp create mode 100644 CONFIG/detectdx5.h create mode 100644 CONFIG/library_mfc.h create mode 100644 CONFIG/res/config.rc create mode 100644 CONFIG/res/lego.ico create mode 100644 CONFIG/res/resource.h create mode 100644 CONFIG/res/shark.bmp mode change 100644 => 100755 tools/decomplint/decomplint.py mode change 100644 => 100755 tools/patch_c2.py create mode 100644 tools/reccmp/config.png mode change 100644 => 100755 tools/vtable/vtable.py diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index dec8b191..8e903cc1 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -4,31 +4,23 @@ on: [push, pull_request] jobs: decomplint-isle: - name: 'ISLE annotations' + name: '${{ matrix.who }} annotations' runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + who: + - CONFIG + - ISLE + - LEGO1 steps: - uses: actions/checkout@v4 - name: Install python libraries run: | - pip install -r tools/requirements.txt + python -m pip install -r tools/requirements.txt - name: Run decomplint.py run: | - python3 tools/decomplint/decomplint.py ISLE --module ISLE --warnfail - - decomplint-lego1: - name: 'LEGO1 annotations' - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install python libraries - run: | - pip install -r tools/requirements.txt - - - name: Run decomplint.py - run: | - python3 tools/decomplint/decomplint.py LEGO1 --module LEGO1 --warnfail + tools/decomplint/decomplint.py ${{ matrix.who }} --module ${{ matrix.who }} --warnfail diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 70b80c85..c7d7363f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,11 +71,11 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 with: # Use minimum supported version - cmake-version: '3.13.x' + cmake-version: '3.15.x' - name: Patch MSVC 4.2 run: | - python tools/patch_c2.py msvc420/bin/C2.EXE + tools/patch_c2.py msvc420/bin/C2.EXE - name: Build shell: cmd @@ -89,6 +89,8 @@ jobs: with: name: Win32 path: | + build/CONFIG.EXE + build/CONFIG.PDB build/ISLE.EXE build/ISLE.PDB build/LEGO1.DLL @@ -117,6 +119,7 @@ jobs: - name: Download original island binares if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} run: | + C:\msys64\usr\bin\wget.exe https://legoisland.org/download/CONFIG.EXE --directory-prefix=legobin C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin @@ -136,6 +139,7 @@ jobs: - name: Summarize Accuracy shell: bash run: | + python3 tools/reccmp/reccmp.py -S CONFIGPROGRESS.SVG --svg-icon tools/reccmp/config.png -H CONFIGPROGRESS.HTML legobin/CONFIG.EXE build/CONFIG.EXE build/CONFIG.PDB . | tee CONFIGPROGRESS.TXT python3 tools/reccmp/reccmp.py -S ISLEPROGRESS.SVG --svg-icon tools/reccmp/isle.png -H ISLEPROGRESS.HTML legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . | tee ISLEPROGRESS.TXT python3 tools/reccmp/reccmp.py -S LEGO1PROGRESS.SVG -T 4252 --svg-icon tools/reccmp/lego1.png -H LEGO1PROGRESS.HTML legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . | tee LEGO1PROGRESS.TXT @@ -143,20 +147,23 @@ jobs: shell: bash run: | # Compare with current master - curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT - curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT + curl -fLSs -o CONFIGPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/CONFIGPROGRESS.TXT || echo "" >CONFIGPROGRESS-OLD.TXT + curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT || echo "" >ISLEPROGRESS-OLD.TXT + curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT || echo "" >LEGO1PROGRESS-OLD.TXT + diff -u0 CONFIGPROGRESS-OLD.TXT CONFIGPROGRESS.TXT || true diff -u0 ISLEPROGRESS-OLD.TXT ISLEPROGRESS.TXT || true diff -u0 LEGO1PROGRESS-OLD.TXT LEGO1PROGRESS.TXT || true - name: Test Exports shell: bash run: | - python3 tools/verexp/verexp.py legobin/LEGO1.DLL build/LEGO1.DLL + tools/verexp/verexp.py legobin/LEGO1.DLL build/LEGO1.DLL - name: Check Vtables shell: bash run: | + python3 tools/vtable/vtable.py legobin/CONFIG.EXE build/CONFIG.EXE build/CONFIG.PDB . python3 tools/vtable/vtable.py legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . python3 tools/vtable/vtable.py legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . @@ -165,6 +172,7 @@ jobs: with: name: Accuracy Report path: | + CONFIGPROGRESS.* ISLEPROGRESS.* LEGO1PROGRESS.* @@ -193,10 +201,13 @@ jobs: UPLOAD_KEY: ${{ secrets.UPLOAD_KEY }} run: | ./upload.sh \ + build/CONFIG.EXE \ build/ISLE.EXE \ build/LEGO1.DLL \ + CONFIGPROGRESS.* \ ISLEPROGRESS.* \ LEGO1PROGRESS.* + curl -X POST -F key=$UPLOAD_KEY -F 'file=@CONFIGPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@ISLEPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@LEGO1PROGRESS.SVG' https://legoisland.org/progress/ diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 4cfb5d9e..9432beb0 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -12,7 +12,7 @@ jobs: - name: Run clang-format run: | - find LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ + find CONFIG LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ pipx run "clang-format>=17,<18" \ --style=file \ -i diff --git a/CMakeLists.txt b/CMakeLists.txt index 765cc68a..8ccd0188 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ -cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +# MSVC runtime library flags are selected by an abstraction +cmake_policy(SET CMP0091 NEW) project(isle CXX) @@ -60,6 +63,7 @@ message(STATUS "MSVC for decompilation: ${MSVC_FOR_DECOMP}") option(ISLE_WERROR "Treat warnings as errors" OFF) option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) +cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "NOT MINGW" OFF) option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC_FOR_DECOMP}) option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) cmake_dependent_option(ISLE_USE_DX5_LIBS "Build with internal DirectX 5 SDK Libraries" ON ISLE_USE_DX5 OFF) @@ -435,14 +439,38 @@ if (ISLE_BUILD_APP) set_property(TARGET isle PROPERTY SUFFIX ".EXE") endif() +if (ISLE_BUILD_CONFIG) + add_executable(config WIN32 + LEGO1/mxdirectx/mxdirect3d.cpp + CONFIG/config.cpp + CONFIG/ConfigCommandLineInfo.cpp + CONFIG/common.cpp + CONFIG/AboutDlg.cpp + CONFIG/MainDlg.cpp + CONFIG/detectdx5.cpp + CONFIG/res/config.rc + ) + target_compile_definitions(config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG) + target_include_directories(config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/util" "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) + target_link_libraries(config PRIVATE DirectX5::DirectX5) + endif() + target_compile_definitions(config PRIVATE DIRECT3D_VERSION=0x500) + target_link_libraries(config PRIVATE ddraw dxguid) + set_property(TARGET config PROPERTY OUTPUT_NAME "CONFIG") + set_property(TARGET config PROPERTY SUFFIX ".EXE") + set_property(TARGET config PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>DLL) +endif() + if (MSVC) if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "15") - foreach(tgt IN LISTS lego1_targets) - target_compile_definitions(${tgt} PRIVATE _CRT_SECURE_NO_WARNINGS) - endforeach() + set_property(TARGET ${lego1_targets} APPEND PROPERTY COMPILE_DEFINITIONS "_CRT_SECURE_NO_WARNINGS") if (TARGET isle) target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS") endif() + if (TARGET config) + target_compile_definitions(config PRIVATE "_CRT_SECURE_NO_WARNINGS") + endif() endif() # Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.14.26428") @@ -452,13 +480,19 @@ if (MSVC) if (TARGET isle) target_compile_options(isle PRIVATE "-Zc:__cplusplus") endif() + if (TARGET config) + target_compile_options(config PRIVATE "-Zc:__cplusplus") + endif() endif() endif() if (MSVC_FOR_DECOMP) target_compile_definitions(lego1 PRIVATE "ENABLE_DECOMP_ASSERTS") - if (ISLE_BUILD_APP) - target_compile_definitions(isle PRIVATE "ENABLE_DECOMP_ASSERTS") + if (TARGET isle) + target_compile_definitions(isle PRIVATE "ENABLE_DECOMP_ASSERTS") + endif() + if (TARGET config) + target_compile_definitions(config PRIVATE "ENABLE_DECOMP_ASSERTS") endif() endif() @@ -471,10 +505,8 @@ if (MSVC_FOR_DECOMP) target_link_options(isle PRIVATE "/OPT:REF") endif() - target_compile_options(lego1 PRIVATE "/MT$<$:d>") - foreach(tgt IN LISTS lego1_targets) - target_compile_options(${tgt} PRIVATE "/MT$<$:d>") - endforeach() + # Equivalent to target_compile_options(... PRIVATE "/MT$<$:d>") + set_property(TARGET lego1 ${lego1_targets} PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"") set(CMAKE_CXX_FLAGS_DEBUG "/Gm /Zi /Od /D \"_DEBUG\"") diff --git a/CONFIG/AboutDlg.cpp b/CONFIG/AboutDlg.cpp new file mode 100644 index 00000000..b14704f1 --- /dev/null +++ b/CONFIG/AboutDlg.cpp @@ -0,0 +1,19 @@ +#include "AboutDlg.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(CDialog, 0x60) +DECOMP_SIZE_ASSERT(CAboutDialog, 0x60) + +// FUNCTION: CONFIG 0x00403c20 +CAboutDialog::CAboutDialog() : CCommonDialog(IDD) +{ +} + +// FUNCTION: CONFIG 0x00403d20 +void CAboutDialog::DoDataExchange(CDataExchange* pDX) +{ +} + +BEGIN_MESSAGE_MAP(CAboutDialog, CDialog) +END_MESSAGE_MAP() diff --git a/CONFIG/AboutDlg.h b/CONFIG/AboutDlg.h new file mode 100644 index 00000000..725ac9e9 --- /dev/null +++ b/CONFIG/AboutDlg.h @@ -0,0 +1,49 @@ +#if !defined(AFX_ABOUTDLG_H) +#define AFX_ABOUTDLG_H + +#include "afxwin.h" +#include "common.h" +#include "compat.h" +#include "res/resource.h" + +// VTABLE: CONFIG 0x00406308 +// SIZE 0x60 +class CAboutDialog : public CCommonDialog { +public: + CAboutDialog(); + // Dialog Data + //{{AFX_DATA(CMainDialog) + enum { + IDD = IDD_ABOUT + }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainDialog) + +protected: + void DoDataExchange(CDataExchange* pDX) override; + //}}AFX_VIRTUAL + // void UpdateInterface(); + // void SwitchToAdvanced(BOOL p_advanced); + // Implementation + +protected: + //{{AFX_MSG(CMainDialog) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +// SYNTHETIC: CONFIG 0x00403cb0 +// CAboutDialog::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x00403d40 +// CAboutDialog::GetMessageMap + +// GLOBAL: CONFIG 0x00406100 +// CAboutDialog::messageMap + +// GLOBAL: CONFIG 0x00406108 +// CAboutDialog::_messageEntries + +#endif // !defined(AFX_ABOUTDLG_H) diff --git a/CONFIG/ConfigCommandLineInfo.cpp b/CONFIG/ConfigCommandLineInfo.cpp new file mode 100644 index 00000000..0e376e6d --- /dev/null +++ b/CONFIG/ConfigCommandLineInfo.cpp @@ -0,0 +1,22 @@ +#include "ConfigCommandLineInfo.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(CCommandLineInfo, 0x24) +DECOMP_SIZE_ASSERT(CConfigCommandLineInfo, 0x24) + +// FUNCTION: CONFIG 0x00403b10 +CConfigCommandLineInfo::CConfigCommandLineInfo() +{ + currentConfigApp->m_run_config_dialog = FALSE; +} + +// FUNCTION: CONFIG 0x00403bf0 +void CConfigCommandLineInfo::ParseParam(LPCSTR pszParam, BOOL bFlag, BOOL bLast) +{ + if (bFlag) { + if (lstrcmpiA(pszParam, "config") == 0) { + currentConfigApp->m_run_config_dialog = TRUE; + } + } +} diff --git a/CONFIG/ConfigCommandLineInfo.h b/CONFIG/ConfigCommandLineInfo.h new file mode 100644 index 00000000..d7b88ac9 --- /dev/null +++ b/CONFIG/ConfigCommandLineInfo.h @@ -0,0 +1,22 @@ +#if !defined(AFX_CONFIGCOMMANDLINEINFO_H) +#define AFX_CONFIGCOMMANDLINEINFO_H + +#include "compat.h" +#include "config.h" +#include "decomp.h" + +#include + +// VTABLE: CONFIG 0x004060e8 +// SIZE 0x24 +class CConfigCommandLineInfo : public CCommandLineInfo { +public: + CConfigCommandLineInfo(); + + void ParseParam(LPCSTR pszParam, BOOL bFlag, BOOL bLast) override; +}; + +// SYNTHETIC: CONFIG 0x00403b80 +// CConfigCommandLineInfo::`scalar deleting destructor' + +#endif // !defined(AFX_CONFIGCOMMANDLINEINFO_H) diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp new file mode 100644 index 00000000..52f55e58 --- /dev/null +++ b/CONFIG/MainDlg.cpp @@ -0,0 +1,344 @@ +#include "MainDlg.h" + +#include "AboutDlg.h" +#include "config.h" +#include "res/resource.h" + +#include + +DECOMP_SIZE_ASSERT(CDialog, 0x60) +DECOMP_SIZE_ASSERT(CMainDialog, 0x70) + +// FUNCTION: CONFIG 0x00403d50 +CMainDialog::CMainDialog(CWnd* pParent) : CCommonDialog(IDD, pParent) +{ + afxCurrentWinApp; + m_icon = LoadIconA(AfxFindResourceHandle(MAKEINTRESOURCE(IDI_CONFIG), RT_GROUP_ICON), MAKEINTRESOURCE(IDI_CONFIG)); +} + +// FUNCTION: CONFIG 0x00403e50 +void CMainDialog::DoDataExchange(CDataExchange* pDX) +{ +} + +BEGIN_MESSAGE_MAP(CMainDialog, CDialog) +ON_WM_SYSCOMMAND() +ON_WM_PAINT() +ON_WM_QUERYDRAGICON() +ON_COMMAND(IDC_CHK_FLIP_VIDEO_MEM_PAGES, OnCheckboxFlipVideoMemPages) +ON_LBN_SELCHANGE(IDC_LIST_3DDEVICES, OnList3DevicesSelectionChanged) +ON_COMMAND(IDC_RAD_PALETTE_16BIT, OnRadiobuttonPalette16bit) +ON_COMMAND(IDC_RAD_PALETTE_256, OnRadiobuttonPalette256) +ON_COMMAND(IDC_CHK_3D_VIDEO_MEMORY, OnCheckbox3DVideoMemory) +ON_WM_DESTROY() // FIXME: CONFIG.EXE calls Default +ON_COMMAND(IDABORT, OnButtonCancel) +ON_COMMAND(IDC_CHK_3DSOUND, OnCheckbox3DSound) +ON_COMMAND(IDC_RAD_MODEL_QUALITY_LOW, OnRadiobuttonModelLowQuality) +ON_COMMAND(IDC_RAD_MODEL_QUALITY_HIGH, OnRadiobuttonModelHighQuality) +ON_COMMAND(IDC_RAD_TEXTURE_QUALITY_LOW, OnRadiobuttonTextureLowQuality) +ON_COMMAND(IDC_RAD_TEXTURE_QUALITY_HIGH, OnRadiobuttonTextureHighQuality) +ON_COMMAND(IDC_CHK_JOYSTICK, OnCheckboxJoystick) +ON_COMMAND(IDC_BTN_ADVANCED, OnButtonAdvanced) +ON_COMMAND(IDC_CHK_DRAW_CURSOR, OnCheckboxDrawCursor) +ON_COMMAND(IDC_CHK_MUSIC, OnCheckboxMusic) +END_MESSAGE_MAP() + +// FUNCTION: CONFIG 0x00403e80 +BOOL CMainDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + SwitchToAdvanced(FALSE); + CMenu* system_menu = CMenu::FromHandle(::GetSystemMenu(m_hWnd, FALSE)); + CString about_text; + about_text.LoadString(IDS_ABOUT); + if (system_menu) { + AppendMenuA(system_menu->m_hMenu, MF_SEPARATOR, 0, NULL); + AppendMenuA(system_menu->m_hMenu, MF_STRING, 16, (LPCTSTR) about_text); + } + SendMessage(WM_SETICON, ICON_BIG, (LPARAM) m_icon); + SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) m_icon); + MxDeviceEnumerate* enumerator = currentConfigApp->m_device_enumerator; + enumerator->FUN_1009d210(); + m_modified = currentConfigApp->ReadRegisterSettings(); + CWnd* list_3d_devices = GetDlgItem(IDC_LIST_3DDEVICES); + int driver_i = 0; + int device_i = 0; + int selected = 0; + char device_name[256]; + const list& driver_list = enumerator->GetDriverList(); + for (list::const_iterator it_driver = driver_list.begin(); it_driver != driver_list.end(); it_driver++) { + const MxDriver& driver = *it_driver; + for (list::const_iterator it_device = driver.m_devices.begin(); it_device != driver.m_devices.end(); + it_device++) { + const MxDevice& device = *it_device; + if (&device == currentConfigApp->m_device) { + selected = device_i; + } + device_i += 1; + sprintf( + device_name, + driver_i == 0 ? "%s ( Primary Device )" : "%s ( Secondary Device )", + device.m_deviceName + ); + ::SendMessage(list_3d_devices->m_hWnd, LB_ADDSTRING, 0, (LPARAM) device_name); + } + driver_i += 1; + } + ::SendMessage(list_3d_devices->m_hWnd, LB_SETCURSEL, selected, 0); + UpdateInterface(); + return TRUE; +} + +// FUNCTION: CONFIG 0x00404080 +void CMainDialog::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xfff0) == 0x10) { + CAboutDialog about_dialog; + about_dialog.DoModal(); + } + else { + Default(); + } +} + +// FUNCTION: CONFIG 0x00404150 +void CMainDialog::OnPaint() +{ + if (IsIconic()) { + CPaintDC painter(this); + ::SendMessage(m_hWnd, WM_ICONERASEBKGND, (WPARAM) painter.m_hDC, 0); + RECT dim; + GetClientRect(&dim); + DrawIcon( + painter.m_hDC, + (dim.right - dim.left - GetSystemMetrics(SM_CXICON) + 1) / 2, + (dim.bottom - dim.top - GetSystemMetrics(SM_CYICON) + 1) / 2, + m_icon + ); + } + else { + Default(); + } +} + +// FUNCTION: CONFIG 0x00404230 +HCURSOR CMainDialog::OnQueryDragIcon() +{ + return m_icon; +} + +// FUNCTION: CONFIG 0x00404240 +void CMainDialog::OnList3DevicesSelectionChanged() +{ + MxDeviceEnumerate* device_enumerator = currentConfigApp->m_device_enumerator; + int selected = ::SendMessage(GetDlgItem(IDC_LIST_3DDEVICES)->m_hWnd, LB_GETCURSEL, 0, 0); + device_enumerator->GetDevice(selected, currentConfigApp->m_driver, currentConfigApp->m_device); + if (currentConfigApp->GetHardwareDeviceColorModel()) { + GetDlgItem(IDC_CHK_DRAW_CURSOR)->EnableWindow(TRUE); + } + else { + currentConfigApp->m_3d_video_ram = FALSE; + currentConfigApp->m_flip_surfaces = FALSE; + CheckDlgButton(IDC_CHK_3D_VIDEO_MEMORY, currentConfigApp->m_3d_video_ram); + CheckDlgButton(IDC_CHK_FLIP_VIDEO_MEM_PAGES, currentConfigApp->m_flip_surfaces); + } + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404320 +void CMainDialog::OnCancel() +{ + CDialog::OnCancel(); +} + +// FUNCTION: CONFIG 0x00404330 +void CMainDialog::OnDestroy() +{ + CDialog::Default(); +} + +// FUNCTION: CONFIG 0x00404340 +void CMainDialog::OnButtonCancel() +{ + if (m_modified) { + currentConfigApp->WriteRegisterSettings(); + } + OnCancel(); +} + +// FUNCTION: CONFIG 0x00404360 +void CMainDialog::UpdateInterface() +{ + currentConfigApp->ValidateSettings(); + GetDlgItem(IDC_CHK_3D_VIDEO_MEMORY) + ->EnableWindow(!currentConfigApp->m_flip_surfaces && !currentConfigApp->GetHardwareDeviceColorModel()); + CheckDlgButton(IDC_CHK_FLIP_VIDEO_MEM_PAGES, currentConfigApp->m_flip_surfaces); + CheckDlgButton(IDC_CHK_3D_VIDEO_MEMORY, currentConfigApp->m_3d_video_ram); + BOOL full_screen = currentConfigApp->m_full_screen; + currentConfigApp->FUN_00403810(); + if (currentConfigApp->GetHardwareDeviceColorModel()) { + CheckDlgButton(IDC_CHK_DRAW_CURSOR, TRUE); + } + else { + CheckDlgButton(IDC_CHK_DRAW_CURSOR, FALSE); + currentConfigApp->m_draw_cursor = FALSE; + GetDlgItem(IDC_CHK_DRAW_CURSOR)->EnableWindow(FALSE); + } + if (full_screen) { + CheckRadioButton( + IDC_RAD_PALETTE_256, + IDC_RAD_PALETTE_16BIT, + currentConfigApp->m_display_bit_depth == 8 ? IDC_RAD_PALETTE_256 : IDC_RAD_PALETTE_16BIT + ); + } + else { + CheckDlgButton(IDC_RAD_PALETTE_256, 0); + CheckDlgButton(IDC_RAD_PALETTE_16BIT, 0); + currentConfigApp->m_display_bit_depth = 0; + } + GetDlgItem(IDC_RAD_PALETTE_256)->EnableWindow(full_screen && currentConfigApp->FUN_004037a0()); + GetDlgItem(IDC_RAD_PALETTE_16BIT)->EnableWindow(full_screen && currentConfigApp->FUN_004037e0()); + CheckDlgButton(IDC_CHK_3DSOUND, currentConfigApp->m_3d_sound); + CheckDlgButton(IDC_CHK_DRAW_CURSOR, currentConfigApp->m_draw_cursor); + switch (currentConfigApp->m_model_quality) { + case 1: + CheckRadioButton(IDC_RAD_MODEL_QUALITY_LOW, IDC_RAD_MODEL_QUALITY_HIGH, IDC_RAD_MODEL_QUALITY_LOW); + break; + case 2: + CheckRadioButton(IDC_RAD_MODEL_QUALITY_LOW, IDC_RAD_MODEL_QUALITY_HIGH, IDC_RAD_MODEL_QUALITY_HIGH); + break; + } + CheckRadioButton( + IDC_RAD_TEXTURE_QUALITY_LOW, + IDC_RAD_TEXTURE_QUALITY_HIGH, + currentConfigApp->m_texture_quality == 0 ? IDC_RAD_TEXTURE_QUALITY_LOW : IDC_RAD_TEXTURE_QUALITY_HIGH + ); + CheckDlgButton(IDC_CHK_JOYSTICK, currentConfigApp->m_use_joystick); + CheckDlgButton(IDC_CHK_MUSIC, currentConfigApp->m_music); +} + +// FUNCTION: CONFIG 0x004045e0 +void CMainDialog::OnCheckbox3DSound() +{ + currentConfigApp->m_3d_sound = IsDlgButtonChecked(IDC_CHK_3DSOUND); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404610 +void CMainDialog::OnCheckbox3DVideoMemory() +{ + currentConfigApp->m_3d_video_ram = IsDlgButtonChecked(IDC_CHK_3D_VIDEO_MEMORY); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404640 +void CMainDialog::OnRadiobuttonPalette16bit() +{ + currentConfigApp->m_display_bit_depth = 16; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404670 +void CMainDialog::OnRadiobuttonPalette256() +{ + currentConfigApp->m_display_bit_depth = 8; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004046a0 +void CMainDialog::OnCheckboxFlipVideoMemPages() +{ + currentConfigApp->m_flip_surfaces = IsDlgButtonChecked(IDC_CHK_FLIP_VIDEO_MEM_PAGES); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004046d0 +void CMainDialog::OnRadiobuttonModelLowQuality() +{ + currentConfigApp->m_model_quality = 1; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404700 +void CMainDialog::OnRadiobuttonModelHighQuality() +{ + currentConfigApp->m_model_quality = 2; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404730 +void CMainDialog::OnRadiobuttonTextureLowQuality() +{ + currentConfigApp->m_texture_quality = 0; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404760 +void CMainDialog::OnRadiobuttonTextureHighQuality() +{ + currentConfigApp->m_texture_quality = 1; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404790 +void CMainDialog::OnCheckboxJoystick() +{ + currentConfigApp->m_use_joystick = IsDlgButtonChecked(IDC_CHK_JOYSTICK); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004047c0 +void CMainDialog::OnButtonAdvanced() +{ + SwitchToAdvanced(!m_advanced); +} + +// FUNCTION: CONFIG 0x004047d0 +void CMainDialog::SwitchToAdvanced(BOOL p_advanced) +{ + RECT dialog_rect; + RECT grp_advanced_rect; + ::GetWindowRect(m_hWnd, &dialog_rect); + ::GetWindowRect(GetDlgItem(IDC_GRP_ADVANCED)->m_hWnd, &grp_advanced_rect); + CWnd* button_advanced = GetDlgItem(IDC_BTN_ADVANCED); + m_advanced = p_advanced; + int height; + if (p_advanced) { + height = grp_advanced_rect.bottom - dialog_rect.top + 10; + GetDlgItem(IDC_BMP_SHARK)->EnableWindow(TRUE); + button_advanced->SetWindowText("Basic"); + } + else { + height = grp_advanced_rect.top - dialog_rect.top; + GetDlgItem(IDC_BMP_SHARK)->EnableWindow(FALSE); + button_advanced->SetWindowText("Advanced"); + } + SetWindowPos(&wndTop, 0, 0, dialog_rect.right - dialog_rect.left, height, SWP_NOMOVE); +} + +// FUNCTION: CONFIG 0x00404890 +void CMainDialog::OnCheckboxDrawCursor() +{ + currentConfigApp->m_draw_cursor = IsDlgButtonChecked(IDC_CHK_DRAW_CURSOR); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004048c0 +void CMainDialog::OnCheckboxMusic() +{ + currentConfigApp->m_music = IsDlgButtonChecked(IDC_CHK_MUSIC); + m_modified = TRUE; + UpdateInterface(); +} diff --git a/CONFIG/MainDlg.h b/CONFIG/MainDlg.h new file mode 100644 index 00000000..3f8da55a --- /dev/null +++ b/CONFIG/MainDlg.h @@ -0,0 +1,76 @@ +#if !defined(AFX_MAINDLG_H) +#define AFX_MAINDLG_H + +#include "afxwin.h" +#include "common.h" +#include "compat.h" +#include "decomp.h" +#include "res/resource.h" + +// VTABLE: CONFIG 0x004063e0 +// SIZE 0x70 +class CMainDialog : public CCommonDialog { +public: + CMainDialog(CWnd* pParent); + // Dialog Data + //{{AFX_DATA(CMainDialog) + enum { + IDD = IDD_MAIN + }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainDialog) + +protected: + void DoDataExchange(CDataExchange* pDX) override; + //}}AFX_VIRTUAL + void UpdateInterface(); + void SwitchToAdvanced(BOOL p_advanced); + + undefined m_unk0x60[4]; // 0x60 + HCURSOR m_icon; // 0x64 + BOOL m_modified; // 0x68 + BOOL m_advanced; // 0x6c + // Implementation + +protected: + //{{AFX_MSG(CMainDialog) + BOOL OnInitDialog() override; + void OnSysCommand(UINT nID, LPARAM lParam); + void OnPaint(); + HCURSOR OnQueryDragIcon(); + void OnList3DevicesSelectionChanged(); + void OnCancel(); + void OnDestroy(); + void OnButtonCancel(); + void OnCheckbox3DSound(); + void OnCheckbox3DVideoMemory(); + void OnRadiobuttonPalette16bit(); + void OnRadiobuttonPalette256(); + void OnCheckboxFlipVideoMemPages(); + void OnRadiobuttonModelLowQuality(); + void OnRadiobuttonModelHighQuality(); + void OnRadiobuttonTextureLowQuality(); + void OnRadiobuttonTextureHighQuality(); + void OnCheckboxJoystick(); + void OnButtonAdvanced(); + void OnCheckboxDrawCursor(); + void OnCheckboxMusic(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +// SYNTHETIC: CONFIG 0x00403de0 +// CMainDialog::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x00403e70 +// CMainDialog::GetMessageMap + +// GLOBAL: CONFIG 0x00406120 +// CMainDialog::messageMap + +// GLOBAL: CONFIG 0x00406128 +// CMainDialog::_messageEntries + +#endif // !defined(AFX_MAINDLG_H) diff --git a/CONFIG/common.cpp b/CONFIG/common.cpp new file mode 100644 index 00000000..207d583d --- /dev/null +++ b/CONFIG/common.cpp @@ -0,0 +1,13 @@ +#include "common.h" + +// FUNCTION: CONFIG 0x00403c90 +void CCommonDialog::BeginModalState() +{ + ::EnableWindow(m_hWnd, FALSE); +} + +// FUNCTION: CONFIG 0x00403ca0 +void CCommonDialog::EndModalState() +{ + ::EnableWindow(m_hWnd, TRUE); +} diff --git a/CONFIG/common.h b/CONFIG/common.h new file mode 100644 index 00000000..f8c6299e --- /dev/null +++ b/CONFIG/common.h @@ -0,0 +1,16 @@ +#ifndef AFX_COMMON_H +#define AFX_COMMON_H + +#include "compat.h" + +#include + +class CCommonDialog : public CDialog { +public: + CCommonDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL) : CDialog(nIDTemplate, pParentWnd) {} + + void BeginModalState() override; + void EndModalState() override; +}; + +#endif diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp new file mode 100644 index 00000000..78c6b6c2 --- /dev/null +++ b/CONFIG/config.cpp @@ -0,0 +1,434 @@ +#include "config.h" + +#include "ConfigCommandLineInfo.h" +#include "MainDlg.h" +#include "detectdx5.h" + +#include // _chdir +#include +#include // _spawnl + +DECOMP_SIZE_ASSERT(CWinApp, 0xc4) +DECOMP_SIZE_ASSERT(CConfigApp, 0x108) + +DECOMP_STATIC_ASSERT(offsetof(CConfigApp, m_display_bit_depth) == 0xd0) + +BEGIN_MESSAGE_MAP(CConfigApp, CWinApp) +ON_COMMAND(ID_HELP, OnHelp) +END_MESSAGE_MAP() + +// FUNCTION: CONFIG 0x00402c40 +CConfigApp::CConfigApp() +{ +} + +#define MiB (1024 * 1024) + +// FUNCTION: CONFIG 0x00402dc0 +BOOL CConfigApp::InitInstance() +{ + if (!IsLegoNotRunning()) { + return FALSE; + } + if (!DetectDirectX5()) { + AfxMessageBox( + "\"LEGO\xae Island\" is not detecting DirectX 5 or later. Please quit all other applications and try " + "again." + ); + return FALSE; + } +#ifdef _AFXDLL + Enable3dControls(); +#else + Enable3dControlsStatic(); +#endif + CConfigCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + if (_stricmp(afxCurrentAppName, "config") == 0) { + m_run_config_dialog = TRUE; + } + m_device_enumerator = new MxDeviceEnumerate; + if (m_device_enumerator->DoEnumerate()) { + return FALSE; + } + m_driver = NULL; + m_device = NULL; + m_full_screen = TRUE; + m_wide_view_angle = TRUE; + m_use_joystick = FALSE; + m_music = TRUE; + m_flip_surfaces = FALSE; + m_3d_video_ram = FALSE; + m_joystick_index = -1; + m_display_bit_depth = 16; + MEMORYSTATUS memory_status; + memory_status.dwLength = sizeof(memory_status); + GlobalMemoryStatus(&memory_status); + if (memory_status.dwTotalPhys < 12 * MiB) { + m_3d_sound = FALSE; + m_model_quality = 0; + m_texture_quality = 1; + } + else if (memory_status.dwTotalPhys < 20 * MiB) { + m_3d_sound = FALSE; + m_model_quality = 1; + m_texture_quality = 1; + } + else { + m_model_quality = 2; + m_3d_sound = TRUE; + m_texture_quality = 1; + } + if (!m_run_config_dialog) { + ReadRegisterSettings(); + ValidateSettings(); + WriteRegisterSettings(); + delete m_device_enumerator; + m_device_enumerator = NULL; + m_driver = NULL; + m_device = NULL; + char password[256]; + ReadReg("password", password, sizeof(password)); + const char* exe = _stricmp("ogel", password) == 0 ? "isled.exe" : "isle.exe"; + char diskpath[1024]; + if (ReadReg("diskpath", diskpath, sizeof(diskpath))) { + _chdir(diskpath); + } + _spawnl(_P_NOWAIT, exe, exe, "/diskstream", "/script", "\\lego\\scripts\\isle\\isle.si", NULL); + return FALSE; + } + CMainDialog main_dialog(NULL); + main_dialog.DoModal(); + return FALSE; +} + +// FUNCTION: CONFIG 0x00403100 +BOOL CConfigApp::IsLegoNotRunning() +{ + HWND hWnd = FindWindowA("Lego Island MainNoM App", "LEGO\xae"); + if (_stricmp(afxCurrentAppName, "config") == 0 || !hWnd) { + return TRUE; + } + if (SetForegroundWindow(hWnd)) { + ShowWindow(hWnd, SW_RESTORE); + } + return FALSE; +} + +// FUNCTION: CONFIG 0x004031b0 +BOOL CConfigApp::WriteReg(const char* p_key, const char* p_value) const +{ + HKEY hKey; + DWORD pos; + + if (RegCreateKeyExA( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Mindscape\\LEGO Island", + 0, + "string", + 0, + KEY_READ | KEY_WRITE, + NULL, + &hKey, + &pos + ) == ERROR_SUCCESS) { + if (RegSetValueExA(hKey, p_key, 0, REG_SZ, (LPBYTE) p_value, strlen(p_value)) == ERROR_SUCCESS) { + if (RegCloseKey(hKey) == ERROR_SUCCESS) { + return TRUE; + } + } + else { + RegCloseKey(hKey); + } + } + return FALSE; +} + +// FUNCTION: CONFIG 0x00403240 +BOOL CConfigApp::ReadReg(LPCSTR p_key, LPCSTR p_value, DWORD p_size) const +{ + HKEY hKey; + DWORD valueType; + + BOOL out = FALSE; + DWORD size = p_size; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Mindscape\\LEGO Island", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, p_key, NULL, &valueType, (LPBYTE) p_value, &size) == ERROR_SUCCESS) { + if (RegCloseKey(hKey) == ERROR_SUCCESS) { + out = TRUE; + } + } + } + return out; +} + +// FUNCTION: CONFIG 0x004032b0 +BOOL CConfigApp::ReadRegBool(LPCSTR p_key, BOOL* p_bool) const +{ + char buffer[256]; + + BOOL read = ReadReg(p_key, buffer, sizeof(buffer)); + if (read) { + if (strcmp("YES", buffer) == 0) { + *p_bool = TRUE; + return read; + } + + if (strcmp("NO", buffer) == 0) { + *p_bool = FALSE; + return read; + } + + read = FALSE; + } + return read; +} + +// FUNCTION: CONFIG 0x00403380 +BOOL CConfigApp::ReadRegInt(LPCSTR p_key, int* p_value) const +{ + char buffer[256]; + + BOOL read = ReadReg(p_key, buffer, sizeof(buffer)); + if (read) { + *p_value = atoi(buffer); + } + + return read; +} + +// FUNCTION: CONFIG 0x004033d0 +BOOL CConfigApp::FUN_004033d0() const +{ + /* + * BUG: should be: + * return !GetHardwareDeviceColorModel() && (m_device->m_HELDesc.dcmColorModel & D3DCOLOR_RGB); + */ + return !GetHardwareDeviceColorModel() && m_device->m_HELDesc.dcmColorModel == D3DCOLOR_RGB; +} + +// FUNCTION: CONFIG 0x00403400 +D3DCOLORMODEL CConfigApp::GetHardwareDeviceColorModel() const +{ + return m_device->m_HWDesc.dcmColorModel; +} + +// FUNCTION: CONFIG 0x00403410 +BOOL CConfigApp::IsPrimaryDriver() const +{ + return m_driver == &m_device_enumerator->GetDriverList().front(); +} + +// FUNCTION: CONFIG 0x00403430 +BOOL CConfigApp::ReadRegisterSettings() +{ + char buffer[256]; + BOOL is_modified = FALSE; + int tmp = -1; + + if (ReadReg("3D Device ID", buffer, sizeof(buffer))) { + tmp = m_device_enumerator->ParseDeviceName(buffer); + if (tmp >= 0) { + tmp = m_device_enumerator->GetDevice(tmp, m_driver, m_device); + } + } + if (tmp != 0) { + is_modified = TRUE; + m_device_enumerator->FUN_1009d210(); + tmp = m_device_enumerator->FUN_1009d0d0(); + m_device_enumerator->GetDevice(tmp, m_driver, m_device); + } + if (!ReadRegInt("Display Bit Depth", &m_display_bit_depth)) { + is_modified = TRUE; + } + if (!ReadRegBool("Flip Surfaces", &m_flip_surfaces)) { + is_modified = TRUE; + } + if (!ReadRegBool("Full Screen", &m_full_screen)) { + is_modified = TRUE; + } + if (!ReadRegBool("Back Buffers in Video RAM", &m_3d_video_ram)) { + is_modified = TRUE; + } + if (!ReadRegBool("Wide View Angle", &m_wide_view_angle)) { + is_modified = TRUE; + } + if (!ReadRegBool("3DSound", &m_3d_sound)) { + is_modified = TRUE; + } + if (!ReadRegBool("Draw Cursor", &m_draw_cursor)) { + is_modified = TRUE; + } + if (!ReadRegInt("Island Quality", &m_model_quality)) { + is_modified = TRUE; + } + if (!ReadRegInt("Island Texture", &m_texture_quality)) { + is_modified = TRUE; + } + if (!ReadRegBool("UseJoystick", &m_use_joystick)) { + is_modified = TRUE; + } + if (!ReadRegBool("Music", &m_music)) { + is_modified = TRUE; + } + if (!ReadRegInt("JoystickIndex", &m_joystick_index)) { + is_modified = TRUE; + } + return is_modified; +} + +// FUNCTION: CONFIG 0x00403630 +BOOL CConfigApp::ValidateSettings() +{ + BOOL is_modified = FALSE; + + if (!IsPrimaryDriver() && !m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + if (FUN_004033d0()) { + if (m_3d_video_ram) { + m_3d_video_ram = FALSE; + is_modified = TRUE; + } + if (m_flip_surfaces) { + m_flip_surfaces = FALSE; + is_modified = TRUE; + } + if (m_display_bit_depth != 16) { + m_display_bit_depth = 16; + is_modified = TRUE; + } + } + if (!GetHardwareDeviceColorModel()) { + m_draw_cursor = FALSE; + is_modified = TRUE; + } + else { + if (!m_3d_video_ram) { + m_3d_video_ram = TRUE; + is_modified = TRUE; + } + if (m_full_screen && !m_flip_surfaces) { + m_flip_surfaces = TRUE; + is_modified = TRUE; + } + } + if (m_flip_surfaces) { + if (!m_3d_video_ram) { + m_3d_video_ram = TRUE; + is_modified = TRUE; + } + if (!m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + } + if ((m_display_bit_depth != 8 && m_display_bit_depth != 16) && (m_display_bit_depth != 0 || m_full_screen)) { + m_display_bit_depth = 8; + is_modified = TRUE; + } + if (m_model_quality < 0 || m_model_quality > 2) { + m_model_quality = 1; + is_modified = TRUE; + } + if (m_texture_quality < 0 || m_texture_quality > 1) { + m_texture_quality = 0; + is_modified = TRUE; + } + return is_modified; +} + +// FUNCTION: CONFIG 0x004037a0 +DWORD CConfigApp::FUN_004037a0() const +{ + if (FUN_004033d0()) { + return 0; + } + if (GetHardwareDeviceColorModel()) { + return 0; + } + return m_device->m_HELDesc.dwDeviceRenderBitDepth & 0x800; +} + +// FUNCTION: CONFIG 0x004037e0 +DWORD CConfigApp::FUN_004037e0() const +{ + if (GetHardwareDeviceColorModel()) { + return m_device->m_HWDesc.dwDeviceRenderBitDepth & 0x400; + } + else { + return m_device->m_HELDesc.dwDeviceRenderBitDepth & 0x400; + } +} + +// FUNCTION: CONFIG 0x00403810 +BOOL CConfigApp::FUN_00403810() +{ + if (m_display_bit_depth == 8) { + if (FUN_004037a0()) { + return FALSE; + } + } + if (m_display_bit_depth == 16) { + if (FUN_004037e0()) { + return FALSE; + } + } + if (FUN_004037a0()) { + m_display_bit_depth = 8; + return TRUE; + } + if (FUN_004037e0()) { + m_display_bit_depth = 16; + return TRUE; + } + m_display_bit_depth = 8; + return TRUE; +} + +// FUNCTION: CONFIG 00403890 +void CConfigApp::WriteRegisterSettings() const + +{ + char buffer[128]; + +#define WriteRegBool(NAME, VALUE) WriteReg(NAME, VALUE ? "YES" : "NO") +#define WriteRegInt(NAME, VALUE) \ + do { \ + sprintf(buffer, "%d", VALUE); \ + WriteReg(NAME, buffer); \ + } while (0) + + m_device_enumerator->FormatDeviceName(buffer, m_driver, m_device); + WriteReg("3D Device ID", buffer); + WriteReg("3D Device Name", m_device->m_deviceName); + WriteRegInt("Display Bit Depth", m_display_bit_depth); + WriteRegBool("Flip Surfaces", m_flip_surfaces); + WriteRegBool("Full Screen", m_full_screen); + WriteRegBool("Back Buffers in Video RAM", m_3d_video_ram); + WriteRegBool("Wide View Angle", m_wide_view_angle); + WriteRegBool("3DSound", m_3d_sound); + WriteRegBool("Draw Cursor", m_draw_cursor); + WriteRegInt("Island Quality", m_model_quality); + WriteRegInt("Island Texture", m_texture_quality); + WriteRegBool("UseJoystick", m_use_joystick); + WriteRegBool("Music", m_music); + WriteRegInt("JoystickIndex", m_joystick_index); + +#undef WriteRegBool +#undef WriteRegInt +} + +// FUNCTION: CONFIG 0x00403a90 +int CConfigApp::ExitInstance() +{ + if (m_device_enumerator) { + delete m_device_enumerator; + m_device_enumerator = NULL; + } + return CWinApp::ExitInstance(); +} + +// GLOBAL: CONFIG 0x00408e50 +CConfigApp g_theApp; diff --git a/CONFIG/config.h b/CONFIG/config.h new file mode 100644 index 00000000..7112f8e4 --- /dev/null +++ b/CONFIG/config.h @@ -0,0 +1,88 @@ +#if !defined(AFX_CONFIG_H) +#define AFX_CONFIG_H + +#include "compat.h" +#include "decomp.h" + +#include +#include + +class MxDeviceEnumerate; +struct MxDevice; +struct MxDriver; + +#define currentConfigApp ((CConfigApp*) afxCurrentWinApp) + +// VTABLE: CONFIG 0x00406040 +// SIZE 0x108 +class CConfigApp : public CWinApp { +public: + CConfigApp(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CConfigApp) + +public: + BOOL InitInstance() override; + int ExitInstance() override; + //}}AFX_VIRTUAL + + // Implementation + + BOOL WriteReg(const char* p_key, const char* p_value) const; + BOOL ReadReg(LPCSTR p_key, LPCSTR p_value, DWORD p_size) const; + BOOL ReadRegBool(LPCSTR p_key, BOOL* p_bool) const; + BOOL ReadRegInt(LPCSTR p_key, int* p_value) const; + BOOL FUN_004033d0() const; + D3DCOLORMODEL GetHardwareDeviceColorModel() const; + BOOL IsPrimaryDriver() const; + BOOL ReadRegisterSettings(); + BOOL ValidateSettings(); + DWORD FUN_004037a0() const; + DWORD FUN_004037e0() const; + BOOL FUN_00403810(); + void CConfigApp::WriteRegisterSettings() const; + + //{{AFX_MSG(CConfigApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + BOOL IsLegoNotRunning(); + +public: + MxDeviceEnumerate* m_device_enumerator; // 0x0c4 + MxDriver* m_driver; // 0x0c8 + MxDevice* m_device; // 0x0cc + int m_display_bit_depth; // 0x0d0 + BOOL m_flip_surfaces; // 0x0d4 + BOOL m_full_screen; // 0x0d8 + BOOL m_3d_video_ram; // 0x0dc + BOOL m_wide_view_angle; // 0x0e0 + BOOL m_3d_sound; // 0x0e4 + BOOL m_draw_cursor; // 0x0e8 + BOOL m_use_joystick; // 0x0ec + int m_joystick_index; // 0x0f0 + BOOL m_run_config_dialog; // 0x0f4 + int m_model_quality; // 0x0f8 + int m_texture_quality; // 0x0fc + undefined m_unk0x100[4]; // 0x100 + BOOL m_music; // 0x104 +}; + +// SYNTHETIC: CONFIG 0x00402cd0 +// CConfigApp::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x402c30 +// CConfigApp::GetMessageMap + +// GLOBAL: CONFIG 0x406008 +// CConfigApp::messageMap + +// GLOBAL: CONFIG 0x406010 +// CConfigApp::_messageEntries + +#endif // !defined(AFX_CONFIG_H) diff --git a/CONFIG/detectdx5.cpp b/CONFIG/detectdx5.cpp new file mode 100644 index 00000000..546f0dbd --- /dev/null +++ b/CONFIG/detectdx5.cpp @@ -0,0 +1,142 @@ +#include "detectdx5.h" + +#include +#include + +typedef HRESULT WINAPI DirectDrawCreate_fn(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter); +typedef HRESULT WINAPI +DirectInputCreateA_fn(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* ppDI, LPUNKNOWN punkOuter); + +// FUNCTION: CONFIG 0x004048f0 +BOOL DetectDirectX5() +{ + unsigned int version; + BOOL found; + DetectDirectX(&version, &found); + return version >= 0x500; +} + +// FUNCTION: CONFIG 0x00404920 +void DetectDirectX(unsigned int* p_version, BOOL* p_found) +{ + OSVERSIONINFOA os_version; + + os_version.dwOSVersionInfoSize = sizeof(os_version); + if (!GetVersionExA(&os_version)) { + *p_version = 0; + *p_found = 0; + return; + } + if (os_version.dwPlatformId == 2) { + *p_found = 2; + if (os_version.dwMajorVersion < 4) { + *p_found = 0; + return; + } + if (os_version.dwMajorVersion != 4) { + *p_version = 0x501; + return; + } + *p_version = 0x200; + HMODULE dinput_module = LoadLibraryA("DINPUT.DLL"); + if (!dinput_module) { + OutputDebugStringA("Couldn't LoadLibrary DInput\r\n"); + return; + } + DirectInputCreateA_fn* func_DirectInputCreateA = + (DirectInputCreateA_fn*) GetProcAddress(dinput_module, "DirectInputCreateA"); + FreeLibrary(dinput_module); + if (!func_DirectInputCreateA) { + OutputDebugStringA("Couldn't GetProcAddress DInputCreate\r\n"); + return; + } + *p_version = 0x300; + return; + } + *p_found = 1; + if (LOWORD(os_version.dwBuildNumber) >= 0x550) { + *p_version = 0x501; + return; + } + HMODULE ddraw_module = LoadLibraryA("DDRAW.DLL"); + if (!ddraw_module) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + return; + } + DirectDrawCreate_fn* func_DirectDrawCreate = + (DirectDrawCreate_fn*) GetProcAddress(ddraw_module, "DirectDrawCreate"); + if (!func_DirectDrawCreate) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't LoadLibrary DDraw\r\n"); + return; + } + LPDIRECTDRAW ddraw; + if (FAILED(func_DirectDrawCreate(NULL, &ddraw, NULL))) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't create DDraw\r\n"); + return; + } + *p_version = 0x100; + LPDIRECTDRAW2 ddraw2; + if (FAILED(ddraw->QueryInterface(IID_IDirectDraw2, (LPVOID*) &ddraw2))) { + ddraw->Release(); + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't QI DDraw2\r\n"); + return; + } + ddraw->Release(); + *p_version = 0x200; + HMODULE dinput_module = LoadLibraryA("DINPUT.DLL"); + if (!dinput_module) { + OutputDebugStringA("Couldn't LoadLibrary DInput\r\n"); + ddraw2->Release(); + FreeLibrary(ddraw_module); + return; + } + DirectInputCreateA_fn* func_DirectInputCreateA = + (DirectInputCreateA_fn*) GetProcAddress(dinput_module, "DirectInputCreateA"); + FreeLibrary(dinput_module); + if (!func_DirectInputCreateA) { + FreeLibrary(ddraw_module); + ddraw2->Release(); + OutputDebugStringA("Couldn't GetProcAddress DInputCreate\r\n"); + return; + } + *p_version = 0x300; + DDSURFACEDESC surface_desc; + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDCAPS2_NONLOCALVIDMEM; + if (FAILED(ddraw2->SetCooperativeLevel(NULL, DISCL_BACKGROUND))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + *p_version = 0; + OutputDebugStringA("Couldn't Set coop level\r\n"); + return; + } + LPDIRECTDRAWSURFACE surface; + if (FAILED(ddraw2->CreateSurface(&surface_desc, &surface, NULL))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + *p_version = 0; + OutputDebugStringA("Couldn't CreateSurface\r\n"); + return; + } + LPDIRECTDRAWSURFACE3 surface3; + if (FAILED(surface->QueryInterface(IID_IDirectDrawSurface3, (LPVOID*) &surface3))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + return; + } + *p_version = 0x500; + surface3->Release(); + ddraw2->Release(); + FreeLibrary(ddraw_module); +} diff --git a/CONFIG/detectdx5.h b/CONFIG/detectdx5.h new file mode 100644 index 00000000..6f45837c --- /dev/null +++ b/CONFIG/detectdx5.h @@ -0,0 +1,10 @@ +#if !defined(AFX_DETECTDX5_H) +#define AFX_DETECTDX5_H + +#include + +extern BOOL DetectDirectX5(); + +extern void DetectDirectX(unsigned int* p_version, BOOL* p_found); + +#endif // !defined(AFX_DETECTDX5_H) diff --git a/CONFIG/library_mfc.h b/CONFIG/library_mfc.h new file mode 100644 index 00000000..c6e1aa47 --- /dev/null +++ b/CONFIG/library_mfc.h @@ -0,0 +1,12 @@ +#ifdef 0 + +// FUNCTION: CONFIG 0x402ca0 +// CObject::Serialize + +// FUNCTION: CONFIG 0x402cb0 +// CObject::AssertValid + +// FUNCTION: CONFIG 0x402cc0 +// CObject::Dump + +#endif diff --git a/CONFIG/res/config.rc b/CONFIG/res/config.rc new file mode 100644 index 00000000..a6164bfa --- /dev/null +++ b/CONFIG/res/config.rc @@ -0,0 +1,82 @@ +#include "resource.h" +#include "afxres.h" + +IDI_CONFIG ICON "lego.ico" + +IDB_SHARK BITMAP "shark.bmp" + +IDD_ABOUT DIALOG 0, 0, 217, 55 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Configure LEGO\xAE Island" +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +FONT 8, "MS Sans Serif" +BEGIN + CONTROL IDI_CONFIG, -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 11, 17, 18, 20 + CONTROL "Configure LEGO Island Version 1.0", -1, "STATIC", SS_LEFT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 10, 119, 8 + CONTROL "Copyright \xA9 1997 mindscape", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 25, 119, 8 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 178, 7, 32, 14 +END + +STRINGTABLE +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +BEGIN + IDS_ABOUT, "&About Config..." +END + +IDD_MAIN DIALOGEX 0, 0, 289, 247 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Configure LEGO Island" +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "OK", IDABORT, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 172, 125, 44, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 238, 125, 44, 14 + CONTROL "Fast", IDC_RAD_MODEL_QUALITY_LOW, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 18, 42, 10 + CONTROL "High", IDC_RAD_MODEL_QUALITY_HIGH, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 18, 69, 10 + CONTROL "Fast", IDC_RAD_TEXTURE_QUALITY_LOW, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 49, 43, 10 + CONTROL "High", IDC_RAD_TEXTURE_QUALITY_HIGH, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 49, 69, 10 + CONTROL "256 Color", IDC_RAD_PALETTE_256, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 80, 50, 10 + CONTROL "High Color(16 bit)", IDC_RAD_PALETTE_16BIT, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 80, 76, 10 + CONTROL "Use Joystick", IDC_CHK_JOYSTICK, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 192, 104, 60, 10 + CONTROL "", IDC_LIST_3DDEVICES, "LISTBOX", LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL, 115, 168, 161, 36 , WS_EX_TRANSPARENT + CONTROL "Flip Video Memory Pages", IDC_CHK_FLIP_VIDEO_MEM_PAGES, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 116, 224, 96, 15 + CONTROL "Draw 3D to Video Memory", IDC_CHK_3D_VIDEO_MEMORY, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 116, 210, 99, 10 + CONTROL "Color Palette", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 69, 175, 26 + CONTROL "Direct 3D Devices", -1, "STATIC", SS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP, 123, 158, 143, 10 + CONTROL "3D Sound", IDC_CHK_3DSOUND, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 220, 210, 45, 10 + CONTROL "Island Model Quality", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 7, 175, 26 + CONTROL "Island Texture Quality", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 38, 175, 26 + CONTROL "Advanced Settings", IDC_GRP_ADVANCED, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 147, 175, 93 + CONTROL "Advanced", IDC_BTN_ADVANCED, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 109, 124, 44, 14 + CONTROL IDB_SHARK, IDC_BMP_SHARK, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 7, 7, 83, 249 + CONTROL "Draw Cursor", IDC_CHK_DRAW_CURSOR, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 219, 227, 54, 10 + CONTROL "Music", IDC_CHK_MUSIC, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 104, 35, 10 +END + +1 VERSIONINFO +FILEVERSION 1,1,0,0 +PRODUCTVERSION 1,1,0,0 +FILEOS 0x4 +FILETYPE 0x1 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Mindscape, Inc." + VALUE "FileDescription", "LEGOIsland & Configuration application" + VALUE "FileVersion", "1, 1, 0, 0" + VALUE "InternalName", "LEGOISLE.EXE" + VALUE "LegalCopyright", "Copyright \xA9 1997" + VALUE "OriginalFilename", "CONFIG.EXE" + VALUE "ProductName", "LEGO Island" + VALUE "ProductVersion", "1, 1, 0, 0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 // U.S. English, Unicode + END +END diff --git a/CONFIG/res/lego.ico b/CONFIG/res/lego.ico new file mode 100644 index 0000000000000000000000000000000000000000..7db1421d89d8d871d800144088d66defbec57fbd GIT binary patch literal 1078 zcmbtT!A`xuWt(b|?i^^eq z)4H$+4iH{D`{vEeZg;a&po1t`-+Cogm*A*w>H`R^c(70L?b&8>oHjg^>jj5@zE99wL_b zKh$o9<=b<%A)6nAJ+Q+!Fh0jBp#K3}K69N%VD@x#y?9t`^{EMMYhS;# zH{R${U)1`1M4Qk;pQrQ>BV~^>!=7%4Bi*C=Tms(i3?hMRUfLiNsWaz{-%IC)rLnb^ r$i_RDcw=6Umvwuax9hrbWNqs@A=9fW@f&J(m$w8&_^;5RdnWz>IR057 literal 0 HcmV?d00001 diff --git a/CONFIG/res/resource.h b/CONFIG/res/resource.h new file mode 100644 index 00000000..4c72eaa1 --- /dev/null +++ b/CONFIG/res/resource.h @@ -0,0 +1,25 @@ +#define IDI_CONFIG 128 + +#define IDD_ABOUT 100 +#define IDS_ABOUT 101 + +#define IDD_MAIN 102 + +#define IDC_LIST_3DDEVICES 1000 +#define IDC_CHK_FLIP_VIDEO_MEM_PAGES 1001 +#define IDC_CHK_3D_VIDEO_MEMORY 1003 +#define IDC_RAD_PALETTE_256 1004 +#define IDC_RAD_PALETTE_16BIT 1005 +#define IDC_CHK_3DSOUND 1006 +#define IDC_CHK_DRAW_CURSOR 1008 +#define IDC_RAD_MODEL_QUALITY_LOW 1010 +#define IDC_RAD_MODEL_QUALITY_HIGH 1011 +#define IDC_RAD_TEXTURE_QUALITY_LOW 1013 +#define IDC_RAD_TEXTURE_QUALITY_HIGH 1014 +#define IDC_CHK_JOYSTICK 1015 +#define IDC_GRP_ADVANCED 1017 +#define IDC_BTN_ADVANCED 1020 +#define IDC_BMP_SHARK 1023 +#define IDC_CHK_MUSIC 1024 + +#define IDB_SHARK 135 diff --git a/CONFIG/res/shark.bmp b/CONFIG/res/shark.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0829a1d1da6bd18c3729c84bf0e16d16a7bb2c43 GIT binary patch literal 56230 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 literal 0 HcmV?d00001 diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index be3f6bba..0fd02023 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -2,13 +2,16 @@ #include // for vsprintf +#if !defined(MXDIRECTX_FOR_CONFIG) DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4); DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); +#endif DECOMP_SIZE_ASSERT(MxDevice, 0x1a4); DECOMP_SIZE_ASSERT(MxDisplayMode, 0x0c); DECOMP_SIZE_ASSERT(MxDriver, 0x190); DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14); +#if !defined(MXDIRECTX_FOR_CONFIG) // FUNCTION: LEGO1 0x1009b0a0 MxDirect3D::MxDirect3D() { @@ -332,7 +335,9 @@ MxAssignedDevice::~MxAssignedDevice() m_deviceInfo = NULL; } } +#endif +// FUNCTION: CONFIG 0x00401180 // FUNCTION: LEGO1 0x1009ba80 MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -344,6 +349,7 @@ MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) Init(p_guid, p_driverDesc, p_driverName); } +// FUNCTION: CONFIG 0x401280 // FUNCTION: LEGO1 0x1009bb80 MxDriver::~MxDriver() { @@ -358,6 +364,7 @@ MxDriver::~MxDriver() } } +// FUNCTION: CONFIG 0x00401330 // FUNCTION: LEGO1 0x1009bc30 void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -401,6 +408,7 @@ MxDevice::MxDevice( Init(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); } +// FUNCTION: CONFIG 0x401460 // FUNCTION: LEGO1 0x1009bd60 MxDevice::~MxDevice() { @@ -458,12 +466,20 @@ void MxDevice::Init( } } +// FUNCTION: CONFIG 0x004015c0 // FUNCTION: LEGO1 0x1009bec0 MxDeviceEnumerate::MxDeviceEnumerate() { m_initialized = FALSE; } +// FUNCTION: CONFIG 0x401710 +// FUNCTION: LEGO1 0x1009c010 +MxDeviceEnumerate::~MxDeviceEnumerate() +{ +} + +// FUNCTION: CONFIG 0x00401770 // FUNCTION: LEGO1 0x1009c070 BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -525,6 +541,7 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401bc0 // FUNCTION: LEGO1 0x1009c4c0 void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) { @@ -538,6 +555,7 @@ void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) OutputDebugString(buf); } +// FUNCTION: CONFIG 0x00401bf0 // FUNCTION: LEGO1 0x1009c4f0 HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context) { @@ -545,6 +563,7 @@ HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDES return deviceEnumerate->EnumDisplayModesCallback(p_ddsd); } +// FUNCTION: CONFIG 0x00401c10 // FUNCTION: LEGO1 0x1009c510 HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( LPGUID p_guid, @@ -559,6 +578,7 @@ HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( return deviceEnumerate->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); } +// FUNCTION: CONFIG 0x00401c40 // FUNCTION: LEGO1 0x1009c540 HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) { @@ -571,6 +591,7 @@ HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401cd0 // FUNCTION: LEGO1 0x1009c5d0 HRESULT MxDeviceEnumerate::EnumDevicesCallback( LPGUID p_guid, @@ -586,6 +607,7 @@ HRESULT MxDeviceEnumerate::EnumDevicesCallback( return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401dc0 // FUNCTION: LEGO1 0x1009c6c0 int MxDeviceEnumerate::DoEnumerate() { @@ -603,6 +625,7 @@ int MxDeviceEnumerate::DoEnumerate() return 0; } +// FUNCTION: CONFIG 0x00401e10 // FUNCTION: LEGO1 0x1009c710 BOOL CALLBACK MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) @@ -611,6 +634,7 @@ MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); } +// FUNCTION: CONFIG 0x00401e30 // FUNCTION: LEGO1 0x1009c730 const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) { @@ -815,6 +839,7 @@ const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) } } +// FUNCTION: CONFIG 0x00402560 // FUNCTION: LEGO1 0x1009ce60 int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) { @@ -844,6 +869,7 @@ int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) return result; } +// FUNCTION: CONFIG 0x00402620 // FUNCTION: LEGO1 0x1009cf20 int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) { @@ -891,6 +917,7 @@ int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) return -1; } +// FUNCTION: CONFIG 0x00402730 // FUNCTION: LEGO1 0x1009d030 int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device) { @@ -915,6 +942,31 @@ int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice* return -1; } +#if defined(MXDIRECTX_FOR_CONFIG) +// FUNCTION: CONFIG 0x004027d0 +int MxDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const MxDevice* p_device) const +{ + int number = 0; + for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++) { + if (&(*it) == p_driver) { + sprintf( + p_buffer, + "%d 0x%x 0x%x 0x%x 0x%x", + number, + ((DWORD*) (p_device->m_guid))[0], + ((DWORD*) (p_device->m_guid))[1], + ((DWORD*) (p_device->m_guid))[2], + ((DWORD*) (p_device->m_guid))[3] + ); + return 0; + } + number++; + } + return -1; +} +#endif + +// FUNCTION: CONFIG 0x00402860 // FUNCTION: LEGO1 0x1009d0d0 int MxDeviceEnumerate::FUN_1009d0d0() { @@ -951,17 +1003,18 @@ int MxDeviceEnumerate::FUN_1009d0d0() i++; } - - return -1; } +// FUNCTION: CONFIG 0x00402930 // FUNCTION: LEGO1 0x1009d1a0 int MxDeviceEnumerate::SupportsMMX() { - int supports_mmx = SupportsCPUID(); - if (supports_mmx) { + if (!SupportsCPUID()) { + return 0; + } + int supports_mmx; #ifdef _MSC_VER - __asm { + __asm { mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID #if _MSC_VER > 1100 cpuid ; Run CPUID @@ -980,22 +1033,22 @@ int MxDeviceEnumerate::SupportsMMX() bt edx, 0x17 ; Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF mov supports_mmx, eax ; Save eax into C variable - } -#else - __asm__("movl $0x0, %%eax\n\t" // EAX=0: Highest Function Parameter and Manufacturer ID - "cpuid\n\t" // Run CPUID\n" - "mov $0x1, %%eax\n\t" // EAX=1: Processor Info and Feature Bits (unused) - "cpuid\n\t" // Run CPUID - "xorl %%eax, %%eax\n\t" // Zero EAX register - "btl $0x15, %%edx\n\t" // Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) - "adc %%eax, %%eax" // Add with carry: EAX = EAX + EAX + CF = CF - : "=a"(supports_mmx) // supports_mmx == EAX - ); -#endif } +#else + __asm__("movl $0x0, %%eax\n\t" // EAX=0: Highest Function Parameter and Manufacturer ID + "cpuid\n\t" // Run CPUID\n" + "mov $0x1, %%eax\n\t" // EAX=1: Processor Info and Feature Bits (unused) + "cpuid\n\t" // Run CPUID + "xorl %%eax, %%eax\n\t" // Zero EAX register + "btl $0x15, %%edx\n\t" // Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) + "adc %%eax, %%eax" // Add with carry: EAX = EAX + EAX + CF = CF + : "=a"(supports_mmx) // supports_mmx == EAX + ); +#endif return supports_mmx; } +// FUNCTION: CONFIG 0x00402970 // FUNCTION: LEGO1 0x1009d1e0 int MxDeviceEnumerate::SupportsCPUID() { @@ -1027,6 +1080,7 @@ int MxDeviceEnumerate::SupportsCPUID() return has_cpuid; } +// FUNCTION: CONFIG 0x004029a0 // FUNCTION: LEGO1 0x1009d210 int MxDeviceEnumerate::FUN_1009d210() { @@ -1037,7 +1091,7 @@ int MxDeviceEnumerate::FUN_1009d210() for (list::iterator it = m_list.begin(); it != m_list.end();) { MxDriver& driver = *it; - if (!FUN_1009d370(driver)) { + if (!DriverSupportsRequiredDisplayMode(driver)) { m_list.erase(it++); } else { @@ -1064,8 +1118,9 @@ int MxDeviceEnumerate::FUN_1009d210() return m_list.empty() ? -1 : 0; } +// FUNCTION: CONFIG 0x00402b00 // FUNCTION: LEGO1 0x1009d370 -unsigned char MxDeviceEnumerate::FUN_1009d370(MxDriver& p_driver) +unsigned char MxDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) { for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); it++) { @@ -1079,6 +1134,7 @@ unsigned char MxDeviceEnumerate::FUN_1009d370(MxDriver& p_driver) return FALSE; } +// FUNCTION: CONFIG 0x00402b60 // FUNCTION: LEGO1 0x1009d3d0 unsigned char MxDeviceEnumerate::FUN_1009d3d0(MxDevice& p_device) { @@ -1087,7 +1143,8 @@ unsigned char MxDeviceEnumerate::FUN_1009d3d0(MxDevice& p_device) } if (p_device.m_HWDesc.dcmColorModel) { - return p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & 1; + return p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && + p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE; } for (list::iterator it = m_list.front().m_devices.begin(); it != m_list.front().m_devices.end(); it++) { diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index e884c741..77d769b8 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -7,6 +7,7 @@ #include +#if !defined(MXDIRECTX_FOR_CONFIG) class MxDirect3D; // SIZE 0xe4 @@ -76,6 +77,7 @@ private: BOOL m_unk0x88c; // 0x88c undefined4 m_unk0x890; // 0x890 }; +#endif // SIZE 0x1a4 struct MxDevice { @@ -137,36 +139,45 @@ struct MxDriver { }; // clang-format off +// TEMPLATE: CONFIG 0x401000 // TEMPLATE: LEGO1 0x1009b900 // list >::~list > // clang-format on // clang-format off +// TEMPLATE: CONFIG 0x401070 // TEMPLATE: LEGO1 0x1009b970 // list >::~list > // clang-format on +// TEMPLATE: CONFIG 0x4010e0 // TEMPLATE: LEGO1 0x1009b9e0 // List::~List +// TEMPLATE: CONFIG 0x401130 // TEMPLATE: LEGO1 0x1009ba30 // List::~List // clang-format off +// TEMPLATE: CONFIG 0x401650 // TEMPLATE: LEGO1 0x1009bf50 // list >::~list > // clang-format on +// TEMPLATE: CONFIG 0x4016c0 // TEMPLATE: LEGO1 0x1009bfc0 // List::~List // Compiler-generated copy ctor +// SYNTHETIC: CONFIG 0x401990 // SYNTHETIC: LEGO1 0x1009c290 // MxDriver::MxDriver +// SYNTHETIC: CONFIG 0x401b00 // SYNTHETIC: LEGO1 0x1009c400 // list >::insert +// SYNTHETIC: CONFIG 0x401b60 // SYNTHETIC: LEGO1 0x1009c460 // list >::insert @@ -176,13 +187,13 @@ struct MxDriver { // SYNTHETIC: LEGO1 0x1009d470 // MxDevice::`scalar deleting destructor' +// VTABLE: CONFIG 0x00406000 // VTABLE: LEGO1 0x100db814 // SIZE 0x14 class MxDeviceEnumerate { public: MxDeviceEnumerate(); - // FUNCTION: LEGO1 0x1009c010 - ~MxDeviceEnumerate() {} + ~MxDeviceEnumerate(); virtual int DoEnumerate(); // vtable+0x00 @@ -199,9 +210,14 @@ public: int ParseDeviceName(const char* p_deviceId); int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); int GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device); + +#if defined(MXDIRECTX_FOR_CONFIG) + int FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const MxDevice* p_device) const; +#endif + int FUN_1009d0d0(); int FUN_1009d210(); - unsigned char FUN_1009d370(MxDriver& p_driver); + unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); unsigned char FUN_1009d3d0(MxDevice& p_device); static void BuildErrorString(const char*, ...); @@ -221,6 +237,8 @@ public: friend class MxDirect3D; + const list& GetDriverList() const { return m_list; } + private: list m_list; // 0x04 unsigned char m_initialized; // 0x10 diff --git a/LEGO1/mxdirectx/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp index 7b64afe3..0e31e8d1 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -911,208 +911,208 @@ const char* MxDirectDraw::ErrorToString(HRESULT p_error) { switch (p_error) { case DD_OK: - return "No error.\0"; + return "No error."; case DDERR_ALREADYINITIALIZED: - return "This object is already initialized.\0"; + return "This object is already initialized."; case DDERR_BLTFASTCANTCLIP: - return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0"; + return "Return if a clipper object is attached to the source surface passed into a BltFast call."; case DDERR_CANNOTATTACHSURFACE: - return "This surface can not be attached to the requested surface.\0"; + return "This surface can not be attached to the requested surface."; case DDERR_CANNOTDETACHSURFACE: - return "This surface can not be detached from the requested surface.\0"; + return "This surface can not be detached from the requested surface."; case DDERR_CANTCREATEDC: - return "Windows can not create any more DCs.\0"; + return "Windows can not create any more DCs."; case DDERR_CANTDUPLICATE: - return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0"; + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; case DDERR_CLIPPERISUSINGHWND: - return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0"; + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; case DDERR_COLORKEYNOTSET: - return "No src color key specified for this operation.\0"; + return "No src color key specified for this operation."; case DDERR_CURRENTLYNOTAVAIL: - return "Support is currently not available.\0"; + return "Support is currently not available."; case DDERR_DIRECTDRAWALREADYCREATED: - return "A DirectDraw object representing this driver has already been created for this process.\0"; + return "A DirectDraw object representing this driver has already been created for this process."; case DDERR_EXCEPTION: - return "An exception was encountered while performing the requested operation.\0"; + return "An exception was encountered while performing the requested operation."; case DDERR_EXCLUSIVEMODEALREADYSET: - return "An attempt was made to set the cooperative level when it was already set to exclusive.\0"; + return "An attempt was made to set the cooperative level when it was already set to exclusive."; case DDERR_GENERIC: - return "Generic failure.\0"; + return "Generic failure."; case DDERR_HEIGHTALIGN: - return "Height of rectangle provided is not a multiple of reqd alignment.\0"; + return "Height of rectangle provided is not a multiple of reqd alignment."; case DDERR_HWNDALREADYSET: return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " - "palettes created.\0"; + "palettes created."; case DDERR_HWNDSUBCLASSED: return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " - "state.\0"; + "state."; case DDERR_IMPLICITLYCREATED: - return "This surface can not be restored because it is an implicitly created surface.\0"; + return "This surface can not be restored because it is an implicitly created surface."; case DDERR_INCOMPATIBLEPRIMARY: - return "Unable to match primary surface creation request with existing primary surface.\0"; + return "Unable to match primary surface creation request with existing primary surface."; case DDERR_INVALIDCAPS: - return "One or more of the caps bits passed to the callback are incorrect.\0"; + return "One or more of the caps bits passed to the callback are incorrect."; case DDERR_INVALIDCLIPLIST: - return "DirectDraw does not support the provided cliplist.\0"; + return "DirectDraw does not support the provided cliplist."; case DDERR_INVALIDDIRECTDRAWGUID: - return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0"; + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; case DDERR_INVALIDMODE: - return "DirectDraw does not support the requested mode.\0"; + return "DirectDraw does not support the requested mode."; case DDERR_INVALIDOBJECT: - return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0"; + return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; case DDERR_INVALIDPARAMS: - return "One or more of the parameters passed to the function are incorrect.\0"; + return "One or more of the parameters passed to the function are incorrect."; case DDERR_INVALIDPIXELFORMAT: - return "The pixel format was invalid as specified.\0"; + return "The pixel format was invalid as specified."; case DDERR_INVALIDPOSITION: return "Returned when the position of the overlay on the destination is no longer legal for that " - "destination.\0"; + "destination."; case DDERR_INVALIDRECT: - return "Rectangle provided was invalid.\0"; + return "Rectangle provided was invalid."; case DDERR_LOCKEDSURFACES: - return "Operation could not be carried out because one or more surfaces are locked.\0"; + return "Operation could not be carried out because one or more surfaces are locked."; case DDERR_NO3D: - return "There is no 3D present.\0"; + return "There is no 3D present."; case DDERR_NOALPHAHW: return "Operation could not be carried out because there is no alpha accleration hardware present or " - "available.\0"; + "available."; case DDERR_NOBLTHW: - return "No blitter hardware present.\0"; + return "No blitter hardware present."; case DDERR_NOCLIPLIST: - return "No cliplist available.\0"; + return "No cliplist available."; case DDERR_NOCLIPPERATTACHED: - return "No clipper object attached to surface object.\0"; + return "No clipper object attached to surface object."; case DDERR_NOCOLORCONVHW: return "Operation could not be carried out because there is no color conversion hardware present or " - "available.\0"; + "available."; case DDERR_NOCOLORKEY: - return "Surface doesn't currently have a color key\0"; + return "Surface doesn't currently have a color key"; case DDERR_NOCOLORKEYHW: return "Operation could not be carried out because there is no hardware support of the destination color " - "key.\0"; + "key."; case DDERR_NOCOOPERATIVELEVELSET: - return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0"; + return "Create function called without DirectDraw object method SetCooperativeLevel being called."; case DDERR_NODC: - return "No DC was ever created for this surface.\0"; + return "No DC was ever created for this surface."; case DDERR_NODDROPSHW: - return "No DirectDraw ROP hardware.\0"; + return "No DirectDraw ROP hardware."; case DDERR_NODIRECTDRAWHW: return "A hardware-only DirectDraw object creation was attempted but the driver did not support any " - "hardware.\0"; + "hardware."; case DDERR_NOEMULATION: - return "Software emulation not available.\0"; + return "Software emulation not available."; case DDERR_NOEXCLUSIVEMODE: return "Operation requires the application to have exclusive mode but the application does not have exclusive " - "mode.\0"; + "mode."; case DDERR_NOFLIPHW: - return "Flipping visible surfaces is not supported.\0"; + return "Flipping visible surfaces is not supported."; case DDERR_NOGDI: - return "There is no GDI present.\0"; + return "There is no GDI present."; case DDERR_NOHWND: return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel " - "HWND.\0"; + "HWND."; case DDERR_NOMIRRORHW: - return "Operation could not be carried out because there is no hardware present or available.\0"; + return "Operation could not be carried out because there is no hardware present or available."; case DDERR_NOOVERLAYDEST: return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " - "to establish a destination.\0"; + "to establish a destination."; case DDERR_NOOVERLAYHW: - return "Operation could not be carried out because there is no overlay hardware present or available.\0"; + return "Operation could not be carried out because there is no overlay hardware present or available."; case DDERR_NOPALETTEATTACHED: - return "No palette object attached to this surface.\0"; + return "No palette object attached to this surface."; case DDERR_NOPALETTEHW: - return "No hardware support for 16 or 256 color palettes.\0"; + return "No hardware support for 16 or 256 color palettes."; case DDERR_NORASTEROPHW: return "Operation could not be carried out because there is no appropriate raster op hardware present or " - "available.\0"; + "available."; case DDERR_NOROTATIONHW: - return "Operation could not be carried out because there is no rotation hardware present or available.\0"; + return "Operation could not be carried out because there is no rotation hardware present or available."; case DDERR_NOSTRETCHHW: - return "Operation could not be carried out because there is no hardware support for stretching.\0"; + return "Operation could not be carried out because there is no hardware support for stretching."; case DDERR_NOT4BITCOLOR: return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " - "palette.\0"; + "palette."; case DDERR_NOT4BITCOLORINDEX: return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color " - "index palette.\0"; + "index palette."; case DDERR_NOT8BITCOLOR: - return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0"; + return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; case DDERR_NOTAOVERLAYSURFACE: - return "Returned when an overlay member is called for a non-overlay surface.\0"; + return "Returned when an overlay member is called for a non-overlay surface."; case DDERR_NOTEXTUREHW: return "Operation could not be carried out because there is no texture mapping hardware present or " - "available.\0"; + "available."; case DDERR_NOTFLIPPABLE: - return "An attempt has been made to flip a surface that is not flippable.\0"; + return "An attempt has been made to flip a surface that is not flippable."; case DDERR_NOTFOUND: - return "Requested item was not found.\0"; + return "Requested item was not found."; case DDERR_NOTLOCKED: return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this " - "process, has been attempted.\0"; + "process, has been attempted."; case DDERR_NOTPALETTIZED: - return "The surface being used is not a palette-based surface.\0"; + return "The surface being used is not a palette-based surface."; case DDERR_NOVSYNCHW: return "Operation could not be carried out because there is no hardware support for vertical blank " - "synchronized operations.\0"; + "synchronized operations."; case DDERR_NOZBUFFERHW: - return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0"; + return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; case DDERR_NOZOVERLAYHW: return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support " - "z layering of overlays.\0"; + "z layering of overlays."; case DDERR_OUTOFCAPS: - return "The hardware needed for the requested operation has already been allocated.\0"; + return "The hardware needed for the requested operation has already been allocated."; case DDERR_OUTOFMEMORY: - return "DirectDraw does not have enough memory to perform the operation.\0"; + return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OUTOFVIDEOMEMORY: - return "DirectDraw does not have enough memory to perform the operation.\0"; + return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OVERLAYCANTCLIP: - return "The hardware does not support clipped overlays.\0"; + return "The hardware does not support clipped overlays."; case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: - return "Can only have ony color key active at one time for overlays.\0"; + return "Can only have ony color key active at one time for overlays."; case DDERR_OVERLAYNOTVISIBLE: - return "Returned when GetOverlayPosition is called on a hidden overlay.\0"; + return "Returned when GetOverlayPosition is called on a hidden overlay."; case DDERR_PALETTEBUSY: - return "Access to this palette is being refused because the palette is already locked by another thread.\0"; + return "Access to this palette is being refused because the palette is already locked by another thread."; case DDERR_PRIMARYSURFACEALREADYEXISTS: - return "This process already has created a primary surface.\0"; + return "This process already has created a primary surface."; case DDERR_REGIONTOOSMALL: - return "Region passed to Clipper::GetClipList is too small.\0"; + return "Region passed to Clipper::GetClipList is too small."; case DDERR_SURFACEALREADYATTACHED: - return "This surface is already attached to the surface it is being attached to.\0"; + return "This surface is already attached to the surface it is being attached to."; case DDERR_SURFACEALREADYDEPENDENT: - return "This surface is already a dependency of the surface it is being made a dependency of.\0"; + return "This surface is already a dependency of the surface it is being made a dependency of."; case DDERR_SURFACEBUSY: - return "Access to this surface is being refused because the surface is already locked by another thread.\0"; + return "Access to this surface is being refused because the surface is already locked by another thread."; case DDERR_SURFACEISOBSCURED: - return "Access to surface refused because the surface is obscured.\0"; + return "Access to surface refused because the surface is obscured."; case DDERR_SURFACELOST: return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface " - "object representing this surface should have Restore called on it.\0"; + "object representing this surface should have Restore called on it."; case DDERR_SURFACENOTATTACHED: - return "The requested surface is not attached.\0"; + return "The requested surface is not attached."; case DDERR_TOOBIGHEIGHT: - return "Height requested by DirectDraw is too large.\0"; + return "Height requested by DirectDraw is too large."; case DDERR_TOOBIGSIZE: - return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0"; + return "Size requested by DirectDraw is too large, but the individual height and width are OK."; case DDERR_TOOBIGWIDTH: - return "Width requested by DirectDraw is too large.\0"; + return "Width requested by DirectDraw is too large."; case DDERR_UNSUPPORTED: - return "Action not supported.\0"; + return "Action not supported."; case DDERR_UNSUPPORTEDFORMAT: - return "FOURCC format requested is unsupported by DirectDraw.\0"; + return "FOURCC format requested is unsupported by DirectDraw."; case DDERR_UNSUPPORTEDMASK: - return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0"; + return "Bitmask in the pixel format requested is unsupported by DirectDraw."; case DDERR_VERTICALBLANKINPROGRESS: - return "Vertical blank is in progress.\0"; + return "Vertical blank is in progress."; case DDERR_WASSTILLDRAWING: return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " - "incomplete.\0"; + "incomplete."; case DDERR_WRONGMODE: - return "This surface can not be restored because it was created in a different mode.\0"; + return "This surface can not be restored because it was created in a different mode."; case DDERR_XALIGN: - return "Rectangle provided was not horizontally aligned on required boundary.\0"; + return "Rectangle provided was not horizontally aligned on required boundary."; default: - return "Unrecognized error value.\0"; + return "Unrecognized error value."; } } diff --git a/LEGO1/mxdirectx/mxstopwatch.h b/LEGO1/mxdirectx/mxstopwatch.h index 0630d2f6..5a86b283 100644 --- a/LEGO1/mxdirectx/mxstopwatch.h +++ b/LEGO1/mxdirectx/mxstopwatch.h @@ -3,6 +3,7 @@ #include "assert.h" +#include // ULONG_MAX #include #include diff --git a/tools/decomplint/decomplint.py b/tools/decomplint/decomplint.py old mode 100644 new mode 100755 index 2ceb42c2..cfe9155b --- a/tools/decomplint/decomplint.py +++ b/tools/decomplint/decomplint.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import sys import argparse @@ -92,8 +94,9 @@ def main(): would_fail = error_count > 0 or (warning_count > 0 and args.warnfail) if would_fail: - sys.exit(1) + return 1 + return 0 if __name__ == "__main__": - main() + raise SystemExit(main()) diff --git a/tools/patch_c2.py b/tools/patch_c2.py old mode 100644 new mode 100755 diff --git a/tools/reccmp/config.png b/tools/reccmp/config.png new file mode 100644 index 0000000000000000000000000000000000000000..1f2050ad37fcf5401d5bca86171b5da2efab4fd5 GIT binary patch literal 1432 zcmeAS@N?(olHy`uVBq!ia0y~yU}^wi7G|KxzsFYufRsYAN02WALzNl>LqiJ#!!Mvv z!wUw6QUeBtR|yOZRx=nF#0%!^3bX-Ahz9tCxc>jozyQJwAPgjc@c;kkKdyBHd5lTk z?k;SJX*+6x9QG1VUsv`QOl+dE#>SSxNem1uF`h1tAr-gYUO3n*Z7AUCxO9W22J6xX zB6I4s_UUb~;`zoo>u1s4;>kJJ-j)T$%U_DDV_;-rsc2-iFRs0ei! z?d&XY1{o3Is?Too+c}(ricaE5c%%6s{Ds)A{R=nUPh=)5tQ;EbtG>C-M2l+l5XBYP z6>IDl{+8DI4NOlcNrg!Le{3IYHa{hU%XIu^9!R!zde5Lkf!(Xg_Vs>wkfTY;R79i@ zV5kw1J;fPV4cHCXs0P3B|DS8)tZ{Yb8eq|*TH+c}l9E`GYL#4+3Zxi}42(>44UBXR z%tDL|t&B{qjEuDn46FW(*QA`1`W6kC7HRY#U+Wk1?YM# ZtxOFemZ-aRmIL)Lc)I$ztaD0e0sz^hIHLdn literal 0 HcmV?d00001 diff --git a/tools/vtable/vtable.py b/tools/vtable/vtable.py old mode 100644 new mode 100755 index bdee080b..2c47d1d5 --- a/tools/vtable/vtable.py +++ b/tools/vtable/vtable.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import argparse import logging