From 6e39e8761371498dcf79337b8575a4f2800425ab Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 27 Jun 2024 15:22:13 -0400 Subject: [PATCH 1/6] Create MxDirectXInfo module (#1047) * Some beta addrs and asserts to start * Create mxdirectxinfo * include fix * CONFIG annotations * Beta matching * Match format function better, add dead code function * LegoDeviceEnumerate --- CMakeLists.txt | 3 +- CONFIG/MainDlg.cpp | 2 +- CONFIG/config.cpp | 2 +- CONFIG/config.h | 36 +- .../legoomni/src/video/legovideomanager.cpp | 2 +- LEGO1/mxdirectx/mxdirect3d.cpp | 866 +--------------- LEGO1/mxdirectx/mxdirect3d.h | 205 +--- LEGO1/mxdirectx/mxdirectdraw.cpp | 23 +- LEGO1/mxdirectx/mxdirectdraw.h | 28 +- LEGO1/mxdirectx/mxdirectxinfo.cpp | 958 ++++++++++++++++++ LEGO1/mxdirectx/mxdirectxinfo.h | 347 +++++++ 11 files changed, 1339 insertions(+), 1133 deletions(-) create mode 100644 LEGO1/mxdirectx/mxdirectxinfo.cpp create mode 100644 LEGO1/mxdirectx/mxdirectxinfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8661dabf..a36d1131 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,7 @@ target_link_libraries(viewmanager PRIVATE Vec::Vec) add_library(mxdirectx STATIC LEGO1/mxdirectx/mxdirect3d.cpp LEGO1/mxdirectx/mxdirectdraw.cpp + LEGO1/mxdirectx/mxdirectxinfo.cpp ) register_lego1_target(mxdirectx) set_property(TARGET mxdirectx PROPERTY ARCHIVE_OUTPUT_NAME "MxDirectX$<$:d>") @@ -463,7 +464,7 @@ endif() if (ISLE_BUILD_CONFIG) add_executable(config WIN32 - LEGO1/mxdirectx/mxdirect3d.cpp + LEGO1/mxdirectx/mxdirectxinfo.cpp CONFIG/config.cpp CONFIG/ConfigCommandLineInfo.cpp CONFIG/AboutDlg.cpp diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp index 58560301..da0b5d17 100644 --- a/CONFIG/MainDlg.cpp +++ b/CONFIG/MainDlg.cpp @@ -4,7 +4,7 @@ #include "config.h" #include "res/resource.h" -#include +#include DECOMP_SIZE_ASSERT(CDialog, 0x60) DECOMP_SIZE_ASSERT(CMainDialog, 0x70) diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index 4e1a2264..59c03332 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -47,7 +47,7 @@ BOOL CConfigApp::InitInstance() if (_stricmp(afxCurrentAppName, "config") == 0) { m_run_config_dialog = TRUE; } - m_device_enumerator = new MxDeviceEnumerate; + m_device_enumerator = new LegoDeviceEnumerate; if (m_device_enumerator->DoEnumerate()) { return FALSE; } diff --git a/CONFIG/config.h b/CONFIG/config.h index 63f88eaa..9172e2d5 100644 --- a/CONFIG/config.h +++ b/CONFIG/config.h @@ -7,7 +7,7 @@ #include -class MxDeviceEnumerate; +class LegoDeviceEnumerate; struct Direct3DDeviceInfo; struct MxDriver; @@ -54,23 +54,23 @@ class CConfigApp : public CWinApp { BOOL IsLegoNotRunning(); public: - MxDeviceEnumerate* m_device_enumerator; // 0x0c4 - MxDriver* m_driver; // 0x0c8 - Direct3DDeviceInfo* 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 + LegoDeviceEnumerate* m_device_enumerator; // 0x0c4 + MxDriver* m_driver; // 0x0c8 + Direct3DDeviceInfo* 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 diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index d1767f16..0eae0878 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -75,7 +75,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM MxS32 deviceNum = -1; Direct3DDeviceInfo* device = NULL; MxDriver* driver = NULL; - MxDeviceEnumerate100d9cc8 deviceEnumerate; + LegoDeviceEnumerate deviceEnumerate; Mx3DPointFloat posVec(0.0, 1.25, -50.0); Mx3DPointFloat dirVec(0.0, 0.0, 1.0); Mx3DPointFloat upVec(0.0, 1.0, 0.0); diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index 8e4a94e8..80626a30 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -1,15 +1,6 @@ #include "mxdirect3d.h" -#include // for vsprintf - -#if !defined(MXDIRECTX_FOR_CONFIG) -DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4); -DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); -#endif -DECOMP_SIZE_ASSERT(Direct3DDeviceInfo, 0x1a4); -DECOMP_SIZE_ASSERT(MxDisplayMode, 0x0c); -DECOMP_SIZE_ASSERT(MxDriver, 0x190); -DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14); +DECOMP_SIZE_ASSERT(MxDirect3D, 0x894) #if !defined(MXDIRECTX_FOR_CONFIG) #define RELEASE(x) \ @@ -149,7 +140,7 @@ BOOL MxDirect3D::D3DSetMode() return FALSE; } - MxDirectDraw::Mode mode = m_currentMode; + DeviceModesInfo::Mode mode = m_currentMode; if (IsFullScreen()) { if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { @@ -234,6 +225,7 @@ int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice) } // FUNCTION: LEGO1 0x1009b5f0 +// FUNCTION: BETA10 0x1011bbca BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device) { if (m_assignedDevice) { @@ -249,7 +241,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri MxDriver& driver = *it; if (&driver == p_driver) { - assignedDevice->m_deviceInfo = new MxDirectDraw::DeviceModesInfo; + assignedDevice->m_deviceInfo = new DeviceModesInfo; if (driver.m_guid) { assignedDevice->m_deviceInfo->m_guid = new GUID; @@ -260,7 +252,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri if (assignedDevice->m_deviceInfo->m_count > 0) { assignedDevice->m_deviceInfo->m_modeArray = - new MxDirectDraw::Mode[assignedDevice->m_deviceInfo->m_count]; + new DeviceModesInfo::Mode[assignedDevice->m_deviceInfo->m_count]; int j = 0; for (list::iterator it2 = driver.m_displayModes.begin(); @@ -319,852 +311,4 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri return TRUE; } -// FUNCTION: LEGO1 0x1009b8b0 -MxAssignedDevice::MxAssignedDevice() -{ - memset(this, 0, sizeof(*this)); -} - -// FUNCTION: LEGO1 0x1009b8d0 -MxAssignedDevice::~MxAssignedDevice() -{ - if (m_deviceInfo) { - delete m_deviceInfo; - m_deviceInfo = NULL; - } -} #endif - -// FUNCTION: CONFIG 0x00401180 -// FUNCTION: LEGO1 0x1009ba80 -MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) -{ - m_guid = NULL; - m_driverDesc = NULL; - m_driverName = NULL; - memset(&m_ddCaps, 0, sizeof(m_ddCaps)); - - Init(p_guid, p_driverDesc, p_driverName); -} - -// FUNCTION: CONFIG 0x401280 -// FUNCTION: LEGO1 0x1009bb80 -MxDriver::~MxDriver() -{ - if (m_guid) { - delete m_guid; - } - if (m_driverDesc) { - delete[] m_driverDesc; - } - if (m_driverName) { - delete[] m_driverName; - } -} - -// FUNCTION: CONFIG 0x00401330 -// FUNCTION: LEGO1 0x1009bc30 -void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) -{ - if (m_driverDesc) { - delete[] m_driverDesc; - m_driverDesc = NULL; - } - - if (m_driverName) { - delete[] m_driverName; - m_driverName = NULL; - } - - if (p_guid) { - m_guid = new GUID; - memcpy(m_guid, p_guid, sizeof(*m_guid)); - } - - if (p_driverDesc) { - m_driverDesc = new char[strlen(p_driverDesc) + 1]; - strcpy(m_driverDesc, p_driverDesc); - } - - if (p_driverName) { - m_driverName = new char[strlen(p_driverName) + 1]; - strcpy(m_driverName, p_driverName); - } -} - -// FUNCTION: LEGO1 0x1009bd20 -Direct3DDeviceInfo::Direct3DDeviceInfo( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc -) -{ - memset(this, 0, sizeof(*this)); - - Initialize(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); -} - -// FUNCTION: CONFIG 0x401460 -// FUNCTION: LEGO1 0x1009bd60 -Direct3DDeviceInfo::~Direct3DDeviceInfo() -{ - if (m_guid) { - delete m_guid; - } - if (m_deviceDesc) { - delete[] m_deviceDesc; - } - if (m_deviceName) { - delete[] m_deviceName; - } -} - -// FUNCTION: LEGO1 0x1009bda0 -void Direct3DDeviceInfo::Initialize( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc -) -{ - if (m_deviceDesc) { - delete[] m_deviceDesc; - m_deviceDesc = NULL; - } - - if (m_deviceName) { - delete[] m_deviceName; - m_deviceName = NULL; - } - - if (p_guid) { - m_guid = new GUID; - memcpy(m_guid, p_guid, sizeof(*m_guid)); - } - - if (p_deviceDesc) { - m_deviceDesc = new char[strlen(p_deviceDesc) + 1]; - strcpy(m_deviceDesc, p_deviceDesc); - } - - if (p_deviceName) { - m_deviceName = new char[strlen(p_deviceName) + 1]; - strcpy(m_deviceName, p_deviceName); - } - - if (p_HWDesc) { - memcpy(&m_HWDesc, p_HWDesc, sizeof(m_HWDesc)); - } - - if (p_HELDesc) { - memcpy(&m_HELDesc, p_HELDesc, sizeof(m_HELDesc)); - } -} - -// 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) -{ - MxDriver driver(p_guid, p_driverDesc, p_driverName); - m_list.push_back(driver); - - // Must be zeroed because held resources are copied by pointer only - // and should not be freed at the end of this function - driver.m_guid = NULL; - driver.m_driverDesc = NULL; - driver.m_driverName = NULL; - memset(&driver.m_ddCaps, 0, sizeof(driver.m_ddCaps)); - - LPDIRECT3D2 lpDirect3d2 = NULL; - LPDIRECTDRAW lpDD = NULL; - MxDriver& newDevice = m_list.back(); - HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); - - if (result != DD_OK) { - BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); - } - else { - lpDD->EnumDisplayModes(0, NULL, this, DisplayModesEnumerateCallback); - newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); - result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); - - if (result != DD_OK) { - BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); - } - else { - result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); - - if (result != DD_OK) { - BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); - } - else { - result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); - - if (result != DD_OK) { - BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); - } - else { - if (newDevice.m_devices.empty()) { - m_list.pop_back(); - } - } - } - } - } - - if (lpDirect3d2) { - lpDirect3d2->Release(); - } - - if (lpDD) { - lpDD->Release(); - } - - return DDENUMRET_OK; -} - -// FUNCTION: CONFIG 0x00401bc0 -// FUNCTION: LEGO1 0x1009c4c0 -void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) -{ - va_list args; - char buf[512]; - - va_start(args, p_format); - vsprintf(buf, p_format, args); - va_end(args); - - OutputDebugString(buf); -} - -// FUNCTION: CONFIG 0x00401bf0 -// FUNCTION: LEGO1 0x1009c4f0 -HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context) -{ - MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; - return deviceEnumerate->EnumDisplayModesCallback(p_ddsd); -} - -// FUNCTION: CONFIG 0x00401c10 -// FUNCTION: LEGO1 0x1009c510 -HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc, - LPVOID p_context -) -{ - MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; - 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) -{ - MxDisplayMode displayMode; - displayMode.m_width = p_ddsd->dwWidth; - displayMode.m_height = p_ddsd->dwHeight; - displayMode.m_bitsPerPixel = p_ddsd->ddpfPixelFormat.dwRGBBitCount; - - m_list.back().m_displayModes.push_back(displayMode); - return DDENUMRET_OK; -} - -// FUNCTION: CONFIG 0x00401cd0 -// FUNCTION: LEGO1 0x1009c5d0 -HRESULT MxDeviceEnumerate::EnumDevicesCallback( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc -) -{ - Direct3DDeviceInfo device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); - m_list.back().m_devices.push_back(device); - memset(&device, 0, sizeof(device)); - return DDENUMRET_OK; -} - -// FUNCTION: CONFIG 0x00401dc0 -// FUNCTION: LEGO1 0x1009c6c0 -int MxDeviceEnumerate::DoEnumerate() -{ - if (m_initialized) { - return -1; - } - - HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); - if (ret != DD_OK) { - BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); - return -1; - } - - m_initialized = TRUE; - return 0; -} - -// FUNCTION: CONFIG 0x00401e10 -// FUNCTION: LEGO1 0x1009c710 -BOOL CALLBACK -MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) -{ - MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; - return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); -} - -// FUNCTION: CONFIG 0x00401e30 -// FUNCTION: LEGO1 0x1009c730 -const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) -{ - switch (p_error) { - case DD_OK: - return "No error."; - case DDERR_GENERIC: - return "Generic failure."; - case DDERR_UNSUPPORTED: - return "Action not supported."; - case DDERR_INVALIDPARAMS: - return "One or more of the parameters passed to the function are incorrect."; - case DDERR_OUTOFMEMORY: - return "DirectDraw does not have enough memory to perform the operation."; - case DDERR_CANNOTATTACHSURFACE: - return "This surface can not be attached to the requested surface."; - case DDERR_ALREADYINITIALIZED: - return "This object is already initialized."; - case DDERR_CURRENTLYNOTAVAIL: - return "Support is currently not available."; - case DDERR_CANNOTDETACHSURFACE: - return "This surface can not be detached from the requested surface."; - case DDERR_HEIGHTALIGN: - return "Height of rectangle provided is not a multiple of reqd alignment."; - case DDERR_EXCEPTION: - return "An exception was encountered while performing the requested operation."; - case DDERR_INVALIDCAPS: - return "One or more of the caps bits passed to the callback are incorrect."; - case DDERR_INCOMPATIBLEPRIMARY: - return "Unable to match primary surface creation request with existing primary surface."; - case DDERR_INVALIDMODE: - return "DirectDraw does not support the requested mode."; - case DDERR_INVALIDCLIPLIST: - return "DirectDraw does not support the provided cliplist."; - case DDERR_INVALIDPIXELFORMAT: - return "The pixel format was invalid as specified."; - case DDERR_INVALIDOBJECT: - return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; - case DDERR_LOCKEDSURFACES: - return "Operation could not be carried out because one or more surfaces are locked."; - case DDERR_INVALIDRECT: - return "Rectangle provided was invalid."; - case DDERR_NOALPHAHW: - return "Operation could not be carried out because there is no alpha accleration hardware present or " - "available."; - case DDERR_NO3D: - return "There is no 3D present."; - case DDERR_NOCOLORCONVHW: - return "Operation could not be carried out because there is no color conversion hardware present or available."; - case DDERR_NOCLIPLIST: - return "No cliplist available."; - case DDERR_NOCOLORKEY: - return "Surface doesn't currently have a color key"; - case DDERR_NOCOOPERATIVELEVELSET: - return "Create function called without DirectDraw object method SetCooperativeLevel being called."; - case DDERR_NOEXCLUSIVEMODE: - return "Operation requires the application to have exclusive mode but the application does not have exclusive " - "mode."; - case DDERR_NOCOLORKEYHW: - return "Operation could not be carried out because there is no hardware support of the destination color key."; - case DDERR_NOGDI: - return "There is no GDI present."; - case DDERR_NOFLIPHW: - return "Flipping visible surfaces is not supported."; - case DDERR_NOTFOUND: - return "Requested item was not found."; - case DDERR_NOMIRRORHW: - return "Operation could not be carried out because there is no hardware present or available."; - case DDERR_NORASTEROPHW: - return "Operation could not be carried out because there is no appropriate raster op hardware present or " - "available."; - case DDERR_NOOVERLAYHW: - return "Operation could not be carried out because there is no overlay hardware present or available."; - case DDERR_NOSTRETCHHW: - return "Operation could not be carried out because there is no hardware support for stretching."; - case DDERR_NOROTATIONHW: - return "Operation could not be carried out because there is no rotation hardware present or available."; - case DDERR_NOTEXTUREHW: - return "Operation could not be carried out because there is no texture mapping hardware present or available."; - case DDERR_NOT4BITCOLOR: - return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " - "palette."; - case DDERR_NOT4BITCOLORINDEX: - return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color " - "index palette."; - case DDERR_NOT8BITCOLOR: - return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; - case DDERR_NOZBUFFERHW: - return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; - case DDERR_NOVSYNCHW: - return "Operation could not be carried out because there is no hardware support for vertical blank " - "synchronized operations."; - case DDERR_OUTOFCAPS: - return "The hardware needed for the requested operation has already been allocated."; - 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."; - case DDERR_COLORKEYNOTSET: - return "No src color key specified for this operation."; - case DDERR_OUTOFVIDEOMEMORY: - return "DirectDraw does not have enough memory to perform the operation."; - case DDERR_OVERLAYCANTCLIP: - return "The hardware does not support clipped overlays."; - case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: - return "Can only have ony color key active at one time for overlays."; - case DDERR_PALETTEBUSY: - return "Access to this palette is being refused because the palette is already locked by another thread."; - case DDERR_SURFACEALREADYDEPENDENT: - return "This surface is already a dependency of the surface it is being made a dependency of."; - case DDERR_SURFACEALREADYATTACHED: - return "This surface is already attached to the surface it is being attached to."; - case DDERR_SURFACEISOBSCURED: - return "Access to surface refused because the surface is obscured."; - case DDERR_SURFACEBUSY: - return "Access to this surface is being refused because the surface is already locked by another thread."; - case DDERR_SURFACENOTATTACHED: - return "The requested surface is not attached."; - 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."; - case DDERR_TOOBIGSIZE: - return "Size requested by DirectDraw is too large, but the individual height and width are OK."; - case DDERR_TOOBIGHEIGHT: - return "Height requested by DirectDraw is too large."; - case DDERR_UNSUPPORTEDFORMAT: - return "FOURCC format requested is unsupported by DirectDraw."; - case DDERR_TOOBIGWIDTH: - return "Width requested by DirectDraw is too large."; - case DDERR_VERTICALBLANKINPROGRESS: - return "Vertical blank is in progress."; - case DDERR_UNSUPPORTEDMASK: - return "Bitmask in the pixel format requested is unsupported by DirectDraw."; - case DDERR_XALIGN: - return "Rectangle provided was not horizontally aligned on required boundary."; - case DDERR_WASSTILLDRAWING: - return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " - "incomplete."; - case DDERR_INVALIDDIRECTDRAWGUID: - return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; - case DDERR_DIRECTDRAWALREADYCREATED: - return "A DirectDraw object representing this driver has already been created for this process."; - case DDERR_NODIRECTDRAWHW: - return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware."; - case DDERR_PRIMARYSURFACEALREADYEXISTS: - return "This process already has created a primary surface."; - case DDERR_NOEMULATION: - return "Software emulation not available."; - case DDERR_REGIONTOOSMALL: - return "Region passed to Clipper::GetClipList is too small."; - case DDERR_CLIPPERISUSINGHWND: - return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; - case DDERR_NOCLIPPERATTACHED: - return "No clipper object attached to surface object."; - case DDERR_NOHWND: - return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND."; - case DDERR_HWNDSUBCLASSED: - return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " - "state."; - case DDERR_HWNDALREADYSET: - return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " - "palettes created."; - case DDERR_NOPALETTEATTACHED: - return "No palette object attached to this surface."; - case DDERR_NOPALETTEHW: - return "No hardware support for 16 or 256 color palettes."; - case DDERR_BLTFASTCANTCLIP: - return "Return if a clipper object is attached to the source surface passed into a BltFast call."; - case DDERR_NOBLTHW: - return "No blitter hardware present."; - case DDERR_NODDROPSHW: - return "No DirectDraw ROP hardware."; - case DDERR_OVERLAYNOTVISIBLE: - return "Returned when GetOverlayPosition is called on a hidden overlay."; - case DDERR_NOOVERLAYDEST: - return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " - "to establish a destination."; - case DDERR_INVALIDPOSITION: - return "Returned when the position of the overlay on the destination is no longer legal for that destination."; - case DDERR_NOTAOVERLAYSURFACE: - return "Returned when an overlay member is called for a non-overlay surface."; - case DDERR_EXCLUSIVEMODEALREADYSET: - return "An attempt was made to set the cooperative level when it was already set to exclusive."; - case DDERR_NOTFLIPPABLE: - return "An attempt has been made to flip a surface that is not flippable."; - case DDERR_CANTDUPLICATE: - return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; - 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."; - case DDERR_CANTCREATEDC: - return "Windows can not create any more DCs."; - case DDERR_NODC: - return "No DC was ever created for this surface."; - case DDERR_WRONGMODE: - return "This surface can not be restored because it was created in a different mode."; - case DDERR_IMPLICITLYCREATED: - return "This surface can not be restored because it is an implicitly created surface."; - case DDERR_NOTPALETTIZED: - return "The surface being used is not a palette-based surface."; - default: - return "Unrecognized error value."; - } -} - -// FUNCTION: CONFIG 0x00402560 -// FUNCTION: LEGO1 0x1009ce60 -int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) -{ - if (!m_initialized) { - return -1; - } - - int num = -1; - int hex[4]; - - if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { - return -1; - } - - if (num < 0) { - return -1; - } - - GUID guid; - memcpy(&guid, hex, sizeof(guid)); - - int result = ProcessDeviceBytes(num, guid); - - if (result < 0) { - return ProcessDeviceBytes(-1, guid); - } - return result; -} - -// FUNCTION: CONFIG 0x00402620 -// FUNCTION: LEGO1 0x1009cf20 -int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) -{ - if (!m_initialized) { - return -1; - } - - int i = 0; - int j = 0; - - struct GUID4 { - int m_data1; - int m_data2; - int m_data3; - int m_data4; - }; - - static_assert(sizeof(GUID4) == sizeof(GUID), "Equal size"); - - GUID4 deviceGuid; - memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { - if (p_deviceNum >= 0 && p_deviceNum < i) { - return -1; - } - - GUID4 compareGuid; - MxDriver& driver = *it; - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { - memcpy(&compareGuid, (*it2).m_guid, sizeof(GUID4)); - - if (compareGuid.m_data1 == deviceGuid.m_data1 && compareGuid.m_data2 == deviceGuid.m_data2 && - compareGuid.m_data3 == deviceGuid.m_data3 && compareGuid.m_data4 == deviceGuid.m_data4 && - i == p_deviceNum) { - return j; - } - - j++; - } - - i++; - } - - return -1; -} - -// FUNCTION: CONFIG 0x00402730 -// FUNCTION: LEGO1 0x1009d030 -int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device) -{ - if (p_deviceNum >= 0 && m_initialized) { - int i = 0; - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { - p_driver = &*it; - - for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); - it2++) { - if (i == p_deviceNum) { - p_device = &*it2; - return 0; - } - i++; - } - } - - return -1; - } - - return -1; -} - -#if defined(MXDIRECTX_FOR_CONFIG) -// FUNCTION: CONFIG 0x004027d0 -int MxDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const Direct3DDeviceInfo* 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() -{ - if (!m_initialized) { - return -1; - } - - if (m_list.empty()) { - return -1; - } - - int i = 0; - int j = 0; - int k = -1; - int cpu_mmx = SupportsMMX(); - - for (list::iterator it = m_list.begin();; it++) { - if (it == m_list.end()) { - return k; - } - - for (list::iterator it2 = (*it).m_devices.begin(); it2 != (*it).m_devices.end(); it2++) { - if ((*it2).m_HWDesc.dcmColorModel) { - return j; - } - - if ((cpu_mmx && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) || - ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0)) { - k = j; - } - - j++; - } - - i++; - } -} - -// FUNCTION: CONFIG 0x00402930 -// FUNCTION: LEGO1 0x1009d1a0 -int MxDeviceEnumerate::SupportsMMX() -{ - if (!SupportsCPUID()) { - return 0; - } - int supports_mmx; -#ifdef _MSC_VER - __asm { - mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID -#if _MSC_VER > 1100 - cpuid ; Run CPUID -#else - __emit 0x0f - __emit 0xa2 -#endif - mov eax, 0x1 ; EAX=1: Processor Info and Feature Bits (unused) -#if _MSC_VER > 1100 - cpuid ; Run CPUID -#else - __emit 0x0f - __emit 0xa2 -#endif - xor eax, eax ; Zero EAX register - 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 - return supports_mmx; -} - -// FUNCTION: CONFIG 0x00402970 -// FUNCTION: LEGO1 0x1009d1e0 -int MxDeviceEnumerate::SupportsCPUID() -{ - int has_cpuid; -#ifdef _MSC_VER -#if defined(_M_IX86) - __asm { - xor eax, eax ; Zero EAX register - pushfd ; Push EFLAGS register value on the stack - or dword ptr[esp], 0x200000 ; Set bit 0x200000: Able to use CPUID instruction (Pentium+) - popfd ; Write the updated value into the EFLAGS register - pushfd ; Push EFLAGS register value on the stack (again) - btr dword ptr[esp], 0x15 ; Test bit 0x15 (21) and reset (set CF) - adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF - popfd ; Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) - mov has_cpuid, eax ; Save eax into C variable - } -#elif defined(_M_X64) - has_cpuid = 1; -#else - has_cpuid = 0; -#endif -#else -#if defined(__i386__) - __asm__("xorl %%eax, %%eax\n\t" // Zero EAX register - "pushfl\n\t" // Push EFLAGS register value on the stack - "orl $0x200000, (%%esp)\n\t" // Set bit 0x200000: Able to use CPUID instruction (Pentium+) - "popfl\n\t" // Write the updated value into the EFLAGS register - "pushfl\n\t" // Push EFLAGS register value on the stack (again) - "btrl $0x15, (%%esp)\n\t" // Test bit 0x15 (21) and reset (set CF) - "adc %%eax, %%eax\n\t" // Add with carry: EAX = EAX + EAX + CF = CF - "popfl" // Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) - : "=a"(has_cpuid) // has_cpuid == EAX - ); -#elif defined(__x86_64__) || defined(__amd64__) - has_cpuid = 1; -#else - has_cpuid = 0; -#endif -#endif - return has_cpuid; -} - -// FUNCTION: CONFIG 0x004029a0 -// FUNCTION: LEGO1 0x1009d210 -int MxDeviceEnumerate::FUN_1009d210() -{ - if (!m_initialized) { - return -1; - } - - for (list::iterator it = m_list.begin(); it != m_list.end();) { - MxDriver& driver = *it; - - if (!DriverSupportsRequiredDisplayMode(driver)) { - m_list.erase(it++); - } - else { - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { - Direct3DDeviceInfo& device = *it2; - - if (!FUN_1009d3d0(device)) { - driver.m_devices.erase(it2++); - } - else { - it2++; - } - } - - if (driver.m_devices.empty()) { - m_list.erase(it++); - } - else { - it++; - } - } - } - - return m_list.empty() ? -1 : 0; -} - -// FUNCTION: CONFIG 0x00402b00 -// FUNCTION: LEGO1 0x1009d370 -unsigned char MxDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) -{ - for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); - it++) { - if ((*it).m_width == 640 && (*it).m_height == 480) { - if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { - return TRUE; - } - } - } - - return FALSE; -} - -// FUNCTION: CONFIG 0x00402b60 -// FUNCTION: LEGO1 0x1009d3d0 -unsigned char MxDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) -{ - if (m_list.size() <= 0) { - return FALSE; - } - - if (p_device.m_HWDesc.dcmColorModel) { - 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++) { - if ((&*it) == &p_device) { - return TRUE; - } - } - - return FALSE; -} diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index bbfe7e3b..7109b0c5 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -3,41 +3,11 @@ #include "decomp.h" #include "mxdirectdraw.h" +#include "mxdirectxinfo.h" #include "mxstl/stlcompat.h" #include -#if !defined(MXDIRECTX_FOR_CONFIG) -class MxDirect3D; - -// SIZE 0xe4 -class MxAssignedDevice { -public: - enum { - c_hardwareMode = 0x01, - c_primaryDevice = 0x02 - }; - - MxAssignedDevice(); - ~MxAssignedDevice(); - - inline unsigned int GetFlags() { return m_flags; } - inline BOOL GetHardwareMode() { return ((int) m_flags << 31) >> 31; } - inline D3DDEVICEDESC& GetDesc() { return m_desc; } - - friend class MxDirect3D; - -private: - GUID m_guid; // 0x00 - unsigned int m_flags; // 0x10 - D3DDEVICEDESC m_desc; // 0x14 - MxDirectDraw::DeviceModesInfo* m_deviceInfo; // 0xe0 -}; - -class MxDeviceEnumerate; -struct MxDriver; -struct Direct3DDeviceInfo; - // VTABLE: LEGO1 0x100db800 // SIZE 0x894 class MxDirect3D : public MxDirectDraw { @@ -81,178 +51,5 @@ class MxDirect3D : public MxDirectDraw { BOOL m_bTexturesDisabled; // 0x88c undefined4 m_unk0x890; // 0x890 }; -#endif - -// SIZE 0x1a4 -struct Direct3DDeviceInfo { - Direct3DDeviceInfo() {} - ~Direct3DDeviceInfo(); - Direct3DDeviceInfo( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc - ); - - void Initialize( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc - ); - - LPGUID m_guid; // 0x00 - char* m_deviceDesc; // 0x04 - char* m_deviceName; // 0x08 - D3DDEVICEDESC m_HWDesc; // 0x0c - D3DDEVICEDESC m_HELDesc; // 0xd8 - - int operator==(Direct3DDeviceInfo) const { return 0; } - int operator<(Direct3DDeviceInfo) const { return 0; } -}; - -// SIZE 0x0c -struct MxDisplayMode { - DWORD m_width; // 0x00 - DWORD m_height; // 0x04 - DWORD m_bitsPerPixel; // 0x08 - - int operator==(MxDisplayMode) const { return 0; } - int operator<(MxDisplayMode) const { return 0; } -}; - -// SIZE 0x190 -struct MxDriver { - MxDriver() {} - ~MxDriver(); - MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); - - void Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); - - LPGUID m_guid; // 0x00 - char* m_driverDesc; // 0x04 - char* m_driverName; // 0x08 - DDCAPS m_ddCaps; // 0x0c - list m_devices; // 0x178 - list m_displayModes; // 0x184 - - int operator==(MxDriver) const { return 0; } - int operator<(MxDriver) const { return 0; } -}; - -// 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 - -// SYNTHETIC: LEGO1 0x1009d450 -// MxDriver::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1009d470 -// Direct3DDeviceInfo::`scalar deleting destructor' - -// VTABLE: CONFIG 0x00406000 -// VTABLE: LEGO1 0x100db814 -// SIZE 0x14 -class MxDeviceEnumerate { -public: - MxDeviceEnumerate(); - ~MxDeviceEnumerate(); - - virtual int DoEnumerate(); // vtable+0x00 - - BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); - HRESULT EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd); - HRESULT EnumDevicesCallback( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc - ); - const char* EnumerateErrorToString(HRESULT p_error); - int ParseDeviceName(const char* p_deviceId); - int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); - int GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device); - -#if defined(MXDIRECTX_FOR_CONFIG) - int FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const Direct3DDeviceInfo* p_device) const; -#endif - - int FUN_1009d0d0(); - int FUN_1009d210(); - unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); - unsigned char FUN_1009d3d0(Direct3DDeviceInfo& p_device); - - static void BuildErrorString(const char*, ...); - static BOOL CALLBACK - DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); - static HRESULT CALLBACK DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context); - static HRESULT CALLBACK DevicesEnumerateCallback( - LPGUID p_guid, - LPSTR p_deviceDesc, - LPSTR p_deviceName, - LPD3DDEVICEDESC p_HWDesc, - LPD3DDEVICEDESC p_HELDesc, - LPVOID p_context - ); - static int SupportsMMX(); - static int SupportsCPUID(); - - friend class MxDirect3D; - - const list& GetDriverList() const { return m_list; } - -private: - list m_list; // 0x04 - unsigned char m_initialized; // 0x10 -}; - -// VTABLE: LEGO1 0x100d9cc8 -// SIZE 0x14 -class MxDeviceEnumerate100d9cc8 : public MxDeviceEnumerate {}; - -// SYNTHETIC: LEGO1 0x1007b590 -// MxDeviceEnumerate100d9cc8::~MxDeviceEnumerate100d9cc8 #endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectx/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp index cdd5f3b7..50d7158b 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -2,8 +2,7 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880); -DECOMP_SIZE_ASSERT(MxDirectDraw::DeviceModesInfo, 0x17c); +DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880) #define RELEASE(x) \ if (x != NULL) { \ @@ -271,7 +270,7 @@ BOOL MxDirectDraw::DDInit(BOOL fullscreen) // FUNCTION: LEGO1 0x1009d9d0 BOOL MxDirectDraw::IsSupportedMode(int width, int height, int bpp) { - Mode mode = {width, height, bpp}; + DeviceModesInfo::Mode mode = {width, height, bpp}; for (int i = 0; i < m_pCurrentDeviceModesList->m_count; i++) { if (m_pCurrentDeviceModesList->m_modeArray[i] == mode) { @@ -1095,21 +1094,3 @@ const char* MxDirectDraw::ErrorToString(HRESULT p_error) return "Unrecognized error value."; } } - -// FUNCTION: LEGO1 0x1009efb0 -MxDirectDraw::DeviceModesInfo::DeviceModesInfo() -{ - memset(this, 0, sizeof(*this)); -} - -// FUNCTION: LEGO1 0x1009efd0 -MxDirectDraw::DeviceModesInfo::~DeviceModesInfo() -{ - if (m_guid != NULL) { - delete m_guid; - } - - if (m_modeArray != NULL) { - delete[] m_modeArray; - } -} diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h index 61c92ae0..512c10c5 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.h +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -1,6 +1,8 @@ #ifndef MXDIRECTDRAW_H #define MXDIRECTDRAW_H +#include "mxdirectxinfo.h" + #include #include @@ -10,30 +12,6 @@ class MxDirectDraw { public: typedef void (*ErrorHandler)(const char*, HRESULT, void*); - // SIZE 0x0c - struct Mode { - int operator==(const Mode& p_mode) const - { - return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel)); - } - - int width; // 0x00 - int height; // 0x04 - int bitsPerPixel; // 0x08 - }; - - // SIZE 0x17c - struct DeviceModesInfo { - DeviceModesInfo(); - ~DeviceModesInfo(); - - GUID* m_guid; // 0x00 - Mode* m_modeArray; // 0x04 - int m_count; // 0x08 - DDCAPS m_ddcaps; // 0x0c - void* m_unk0x178; // 0x178 - }; - static int GetPrimaryBitDepth(); MxDirectDraw(); @@ -125,7 +103,7 @@ class MxDirectDraw { void* m_pFatalErrorHandlerArg; // 0x868 int m_pauseCount; // 0x86c DeviceModesInfo* m_pCurrentDeviceModesList; // 0x870 - Mode m_currentMode; // 0x874 + DeviceModesInfo::Mode m_currentMode; // 0x874 }; #endif // MXDIRECTDRAW_H diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp new file mode 100644 index 00000000..dded6e04 --- /dev/null +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -0,0 +1,958 @@ +#include "mxdirectxinfo.h" + +#include +#include // for vsprintf + +DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4) +DECOMP_SIZE_ASSERT(Direct3DDeviceInfo, 0x1a4) +DECOMP_SIZE_ASSERT(MxDisplayMode, 0x0c) +DECOMP_SIZE_ASSERT(MxDriver, 0x190) +DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14) +DECOMP_SIZE_ASSERT(DeviceModesInfo, 0x17c) +DECOMP_SIZE_ASSERT(DeviceModesInfo::Mode, 0x0c) + +// FUNCTION: LEGO1 0x1009b8b0 +// FUNCTION: BETA10 0x1011c05e +MxAssignedDevice::MxAssignedDevice() +{ + memset(this, 0, sizeof(*this)); +} + +// FUNCTION: LEGO1 0x1009b8d0 +// FUNCTION: BETA10 0x1011c08a +MxAssignedDevice::~MxAssignedDevice() +{ + if (m_deviceInfo) { + delete m_deviceInfo; + m_deviceInfo = NULL; + } +} + +// FUNCTION: BETA10 0x1011d7f0 +MxDriver::MxDriver(LPGUID p_guid) +{ + m_guid = NULL; + m_driverDesc = NULL; + m_driverName = NULL; + memset(&m_ddCaps, 0, sizeof(m_ddCaps)); + // TODO: ret vs ret 4 +} + +// FUNCTION: CONFIG 0x00401180 +// FUNCTION: LEGO1 0x1009ba80 +// FUNCTION: BETA10 0x1011d8b6 +MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + m_guid = NULL; + m_driverDesc = NULL; + m_driverName = NULL; + memset(&m_ddCaps, 0, sizeof(m_ddCaps)); + + Init(p_guid, p_driverDesc, p_driverName); +} + +// FUNCTION: CONFIG 0x401280 +// FUNCTION: LEGO1 0x1009bb80 +// FUNCTION: BETA10 0x1011d992 +MxDriver::~MxDriver() +{ + if (m_guid) { + delete m_guid; + } + if (m_driverDesc) { + delete[] m_driverDesc; + } + if (m_driverName) { + delete[] m_driverName; + } +} + +// FUNCTION: CONFIG 0x00401330 +// FUNCTION: LEGO1 0x1009bc30 +// FUNCTION: BETA10 0x1011da89 +void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + if (m_driverDesc) { + delete[] m_driverDesc; + m_driverDesc = NULL; + } + + if (m_driverName) { + delete[] m_driverName; + m_driverName = NULL; + } + + if (p_guid) { + m_guid = new GUID; + memcpy(m_guid, p_guid, sizeof(*m_guid)); + } + + if (p_driverDesc) { + m_driverDesc = new char[strlen(p_driverDesc) + 1]; + strcpy(m_driverDesc, p_driverDesc); + } + + if (p_driverName) { + m_driverName = new char[strlen(p_driverName) + 1]; + strcpy(m_driverName, p_driverName); + } +} + +// FUNCTION: CONFIG 0x401420 +// FUNCTION: LEGO1 0x1009bd20 +// FUNCTION: BETA10 0x1011dbd0 +Direct3DDeviceInfo::Direct3DDeviceInfo( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + memset(this, 0, sizeof(*this)); + + Initialize(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); +} + +// FUNCTION: CONFIG 0x401460 +// FUNCTION: LEGO1 0x1009bd60 +// FUNCTION: BETA10 0x1011dc1a +Direct3DDeviceInfo::~Direct3DDeviceInfo() +{ + if (m_guid) { + delete m_guid; + } + if (m_deviceDesc) { + delete[] m_deviceDesc; + } + if (m_deviceName) { + delete[] m_deviceName; + } +} + +// FUNCTION: CONFIG 0x4014a0 +// FUNCTION: LEGO1 0x1009bda0 +// FUNCTION: BETA10 0x1011dca6 +void Direct3DDeviceInfo::Initialize( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + if (m_deviceDesc) { + delete[] m_deviceDesc; + m_deviceDesc = NULL; + } + + if (m_deviceName) { + delete[] m_deviceName; + m_deviceName = NULL; + } + + if (p_guid) { + m_guid = new GUID; + memcpy(m_guid, p_guid, sizeof(*m_guid)); + } + + if (p_deviceDesc) { + m_deviceDesc = new char[strlen(p_deviceDesc) + 1]; + strcpy(m_deviceDesc, p_deviceDesc); + } + + if (p_deviceName) { + m_deviceName = new char[strlen(p_deviceName) + 1]; + strcpy(m_deviceName, p_deviceName); + } + + // DECOMP: Beta shows implicit memcpy for these two members + if (p_HWDesc) { + m_HWDesc = *p_HWDesc; + } + + if (p_HELDesc) { + m_HELDesc = *p_HELDesc; + } +} + +// FUNCTION: CONFIG 0x004015c0 +// FUNCTION: LEGO1 0x1009bec0 +// FUNCTION: BETA10 0x1011ddf8 +MxDeviceEnumerate::MxDeviceEnumerate() +{ + m_initialized = FALSE; +} + +// FUNCTION: CONFIG 0x401710 +// FUNCTION: LEGO1 0x1009c010 +// FUNCTION: BETA10 0x1011de74 +MxDeviceEnumerate::~MxDeviceEnumerate() +{ +} + +// FUNCTION: CONFIG 0x00401770 +// FUNCTION: LEGO1 0x1009c070 +// FUNCTION: BETA10 0x1011dedf +BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + MxDriver driver(p_guid, p_driverDesc, p_driverName); + m_list.push_back(driver); + + // Must be zeroed because held resources are copied by pointer only + // and should not be freed at the end of this function + driver.m_guid = NULL; + driver.m_driverDesc = NULL; + driver.m_driverName = NULL; + memset(&driver.m_ddCaps, 0, sizeof(driver.m_ddCaps)); + + LPDIRECT3D2 lpDirect3d2 = NULL; + LPDIRECTDRAW lpDD = NULL; + MxDriver& newDevice = m_list.back(); + HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); + + if (result != DD_OK) { + BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); + } + else { + lpDD->EnumDisplayModes(0, NULL, this, DisplayModesEnumerateCallback); + newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); + result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); + + if (result != DD_OK) { + BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + } + else { + result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); + + if (result != DD_OK) { + BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + } + else { + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + + if (result != DD_OK) { + BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + } + else { + if (!newDevice.m_devices.size()) { + m_list.pop_back(); + } + } + } + } + } + + if (lpDirect3d2) { + lpDirect3d2->Release(); + } + + if (lpDD) { + lpDD->Release(); + } + + return DDENUMRET_OK; +} + +// FUNCTION: CONFIG 0x00401bc0 +// FUNCTION: LEGO1 0x1009c4c0 +// FUNCTION: BETA10 0x1011e193 +void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) +{ + va_list args; + char buf[512]; + + va_start(args, p_format); + vsprintf(buf, p_format, args); + va_end(args); + + OutputDebugString(buf); +} + +// FUNCTION: CONFIG 0x00401bf0 +// FUNCTION: LEGO1 0x1009c4f0 +// FUNCTION: BETA10 0x1011e1dd +HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context) +{ + if (p_context == NULL) { + assert(0); + } + + return ((MxDeviceEnumerate*) p_context)->EnumDisplayModesCallback(p_ddsd); +} + +// FUNCTION: CONFIG 0x00401c10 +// FUNCTION: LEGO1 0x1009c510 +// FUNCTION: BETA10 0x1011e226 +HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc, + LPVOID p_context +) +{ + if (p_context == NULL) { + assert(0); + } + + return ((MxDeviceEnumerate*) p_context) + ->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); +} + +// FUNCTION: CONFIG 0x00401c40 +// FUNCTION: LEGO1 0x1009c540 +// FUNCTION: BETA10 0x1011e27f +HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) +{ + assert(m_list.size() > 0); + assert(p_ddsd); + + // TODO: compat_mode? + MxDisplayMode displayMode(p_ddsd->dwWidth, p_ddsd->dwHeight, p_ddsd->ddpfPixelFormat.dwRGBBitCount); + m_list.back().m_displayModes.push_back(displayMode); + return DDENUMRET_OK; +} + +// FUNCTION: CONFIG 0x00401cd0 +// FUNCTION: LEGO1 0x1009c5d0 +// FUNCTION: BETA10 0x1011e32f +HRESULT MxDeviceEnumerate::EnumDevicesCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + Direct3DDeviceInfo device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); + m_list.back().m_devices.push_back(device); + memset(&device, 0, sizeof(device)); + return DDENUMRET_OK; +} + +// FUNCTION: CONFIG 0x00401dc0 +// FUNCTION: LEGO1 0x1009c6c0 +// FUNCTION: BETA10 0x1011e3fa +int MxDeviceEnumerate::DoEnumerate() +{ + if (IsInitialized()) { + return -1; + } + + HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); + if (ret != DD_OK) { + BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); + return -1; + } + + m_initialized = TRUE; + return 0; +} + +// FUNCTION: CONFIG 0x00401e10 +// FUNCTION: LEGO1 0x1009c710 +// FUNCTION: BETA10 0x1011e476 +BOOL CALLBACK +MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) +{ + if (p_context == NULL) { + assert(0); + } + + return ((MxDeviceEnumerate*) p_context)->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); +} + +// FUNCTION: CONFIG 0x00401e30 +// FUNCTION: LEGO1 0x1009c730 +// FUNCTION: BETA10 0x1011e4c7 +const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) +{ + switch (p_error) { + case DD_OK: + return "No error."; + case DDERR_GENERIC: + return "Generic failure."; + case DDERR_UNSUPPORTED: + return "Action not supported."; + case DDERR_INVALIDPARAMS: + return "One or more of the parameters passed to the function are incorrect."; + case DDERR_OUTOFMEMORY: + return "DirectDraw does not have enough memory to perform the operation."; + case DDERR_CANNOTATTACHSURFACE: + return "This surface can not be attached to the requested surface."; + case DDERR_ALREADYINITIALIZED: + return "This object is already initialized."; + case DDERR_CURRENTLYNOTAVAIL: + return "Support is currently not available."; + case DDERR_CANNOTDETACHSURFACE: + return "This surface can not be detached from the requested surface."; + case DDERR_HEIGHTALIGN: + return "Height of rectangle provided is not a multiple of reqd alignment."; + case DDERR_EXCEPTION: + return "An exception was encountered while performing the requested operation."; + case DDERR_INVALIDCAPS: + return "One or more of the caps bits passed to the callback are incorrect."; + case DDERR_INCOMPATIBLEPRIMARY: + return "Unable to match primary surface creation request with existing primary surface."; + case DDERR_INVALIDMODE: + return "DirectDraw does not support the requested mode."; + case DDERR_INVALIDCLIPLIST: + return "DirectDraw does not support the provided cliplist."; + case DDERR_INVALIDPIXELFORMAT: + return "The pixel format was invalid as specified."; + case DDERR_INVALIDOBJECT: + return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; + case DDERR_LOCKEDSURFACES: + return "Operation could not be carried out because one or more surfaces are locked."; + case DDERR_INVALIDRECT: + return "Rectangle provided was invalid."; + case DDERR_NOALPHAHW: + return "Operation could not be carried out because there is no alpha accleration hardware present or " + "available."; + case DDERR_NO3D: + return "There is no 3D present."; + case DDERR_NOCOLORCONVHW: + return "Operation could not be carried out because there is no color conversion hardware present or available."; + case DDERR_NOCLIPLIST: + return "No cliplist available."; + case DDERR_NOCOLORKEY: + return "Surface doesn't currently have a color key"; + case DDERR_NOCOOPERATIVELEVELSET: + return "Create function called without DirectDraw object method SetCooperativeLevel being called."; + case DDERR_NOEXCLUSIVEMODE: + return "Operation requires the application to have exclusive mode but the application does not have exclusive " + "mode."; + case DDERR_NOCOLORKEYHW: + return "Operation could not be carried out because there is no hardware support of the destination color key."; + case DDERR_NOGDI: + return "There is no GDI present."; + case DDERR_NOFLIPHW: + return "Flipping visible surfaces is not supported."; + case DDERR_NOTFOUND: + return "Requested item was not found."; + case DDERR_NOMIRRORHW: + return "Operation could not be carried out because there is no hardware present or available."; + case DDERR_NORASTEROPHW: + return "Operation could not be carried out because there is no appropriate raster op hardware present or " + "available."; + case DDERR_NOOVERLAYHW: + return "Operation could not be carried out because there is no overlay hardware present or available."; + case DDERR_NOSTRETCHHW: + return "Operation could not be carried out because there is no hardware support for stretching."; + case DDERR_NOROTATIONHW: + return "Operation could not be carried out because there is no rotation hardware present or available."; + case DDERR_NOTEXTUREHW: + return "Operation could not be carried out because there is no texture mapping hardware present or available."; + case DDERR_NOT4BITCOLOR: + return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " + "palette."; + case DDERR_NOT4BITCOLORINDEX: + return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color " + "index palette."; + case DDERR_NOT8BITCOLOR: + return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; + case DDERR_NOZBUFFERHW: + return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; + case DDERR_NOVSYNCHW: + return "Operation could not be carried out because there is no hardware support for vertical blank " + "synchronized operations."; + case DDERR_OUTOFCAPS: + return "The hardware needed for the requested operation has already been allocated."; + 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."; + case DDERR_COLORKEYNOTSET: + return "No src color key specified for this operation."; + case DDERR_OUTOFVIDEOMEMORY: + return "DirectDraw does not have enough memory to perform the operation."; + case DDERR_OVERLAYCANTCLIP: + return "The hardware does not support clipped overlays."; + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + return "Can only have ony color key active at one time for overlays."; + case DDERR_PALETTEBUSY: + return "Access to this palette is being refused because the palette is already locked by another thread."; + case DDERR_SURFACEALREADYDEPENDENT: + return "This surface is already a dependency of the surface it is being made a dependency of."; + case DDERR_SURFACEALREADYATTACHED: + return "This surface is already attached to the surface it is being attached to."; + case DDERR_SURFACEISOBSCURED: + return "Access to surface refused because the surface is obscured."; + case DDERR_SURFACEBUSY: + return "Access to this surface is being refused because the surface is already locked by another thread."; + case DDERR_SURFACENOTATTACHED: + return "The requested surface is not attached."; + 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."; + case DDERR_TOOBIGSIZE: + return "Size requested by DirectDraw is too large, but the individual height and width are OK."; + case DDERR_TOOBIGHEIGHT: + return "Height requested by DirectDraw is too large."; + case DDERR_UNSUPPORTEDFORMAT: + return "FOURCC format requested is unsupported by DirectDraw."; + case DDERR_TOOBIGWIDTH: + return "Width requested by DirectDraw is too large."; + case DDERR_VERTICALBLANKINPROGRESS: + return "Vertical blank is in progress."; + case DDERR_UNSUPPORTEDMASK: + return "Bitmask in the pixel format requested is unsupported by DirectDraw."; + case DDERR_XALIGN: + return "Rectangle provided was not horizontally aligned on required boundary."; + case DDERR_WASSTILLDRAWING: + return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " + "incomplete."; + case DDERR_INVALIDDIRECTDRAWGUID: + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; + case DDERR_DIRECTDRAWALREADYCREATED: + return "A DirectDraw object representing this driver has already been created for this process."; + case DDERR_NODIRECTDRAWHW: + return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware."; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + return "This process already has created a primary surface."; + case DDERR_NOEMULATION: + return "Software emulation not available."; + case DDERR_REGIONTOOSMALL: + return "Region passed to Clipper::GetClipList is too small."; + case DDERR_CLIPPERISUSINGHWND: + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; + case DDERR_NOCLIPPERATTACHED: + return "No clipper object attached to surface object."; + case DDERR_NOHWND: + return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND."; + case DDERR_HWNDSUBCLASSED: + return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " + "state."; + case DDERR_HWNDALREADYSET: + return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " + "palettes created."; + case DDERR_NOPALETTEATTACHED: + return "No palette object attached to this surface."; + case DDERR_NOPALETTEHW: + return "No hardware support for 16 or 256 color palettes."; + case DDERR_BLTFASTCANTCLIP: + return "Return if a clipper object is attached to the source surface passed into a BltFast call."; + case DDERR_NOBLTHW: + return "No blitter hardware present."; + case DDERR_NODDROPSHW: + return "No DirectDraw ROP hardware."; + case DDERR_OVERLAYNOTVISIBLE: + return "Returned when GetOverlayPosition is called on a hidden overlay."; + case DDERR_NOOVERLAYDEST: + return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " + "to establish a destination."; + case DDERR_INVALIDPOSITION: + return "Returned when the position of the overlay on the destination is no longer legal for that destination."; + case DDERR_NOTAOVERLAYSURFACE: + return "Returned when an overlay member is called for a non-overlay surface."; + case DDERR_EXCLUSIVEMODEALREADYSET: + return "An attempt was made to set the cooperative level when it was already set to exclusive."; + case DDERR_NOTFLIPPABLE: + return "An attempt has been made to flip a surface that is not flippable."; + case DDERR_CANTDUPLICATE: + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; + 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."; + case DDERR_CANTCREATEDC: + return "Windows can not create any more DCs."; + case DDERR_NODC: + return "No DC was ever created for this surface."; + case DDERR_WRONGMODE: + return "This surface can not be restored because it was created in a different mode."; + case DDERR_IMPLICITLYCREATED: + return "This surface can not be restored because it is an implicitly created surface."; + case DDERR_NOTPALETTIZED: + return "The surface being used is not a palette-based surface."; + default: + return "Unrecognized error value."; + } +} + +// FUNCTION: CONFIG 0x00402560 +// FUNCTION: LEGO1 0x1009ce60 +// FUNCTION: BETA10 0x1011c7e0 +int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) +{ + if (!IsInitialized()) { + return -1; + } + + int unknown = -1; + int num = -1; + int hex[4]; + + if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { + return -1; + } + + if (num < 0) { + return -1; + } + + GUID guid; + memcpy(&guid, hex, sizeof(guid)); + + int result = ProcessDeviceBytes(num, guid); + + if (result < 0) { + result = ProcessDeviceBytes(-1, guid); + } + + return result; +} + +// FUNCTION: CONFIG 0x00402620 +// FUNCTION: LEGO1 0x1009cf20 +// FUNCTION: BETA10 0x1011c8b3 +int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) +{ + if (!IsInitialized()) { + return -1; + } + + int i = 0; + int j = 0; + + static_assert(sizeof(GUID4) == sizeof(GUID), "Equal size"); + + GUID4 deviceGuid; + memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + if (p_deviceNum >= 0 && p_deviceNum < i) { + return -1; + } + + GUID4 compareGuid; + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + Direct3DDeviceInfo& md3d = *it2; + assert(md3d.m_guid); + + memcpy(&compareGuid, md3d.m_guid, sizeof(GUID4)); + + if (GUID4::Compare(compareGuid, deviceGuid) && i == p_deviceNum) { + return j; + } + + j++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x00402730 +// FUNCTION: LEGO1 0x1009d030 +// FUNCTION: BETA10 0x1011ca54 +int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device) +{ + if (p_deviceNum < 0 || !IsInitialized()) { + return -1; + } + + int i = 0; + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + p_driver = &*it; + + for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); + it2++) { + if (i == p_deviceNum) { + p_device = &*it2; + return 0; + } + i++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x004027d0 +// FUNCTION: BETA10 0x1011cb70 +int MxDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) + const +{ + int number = 0; + assert(p_ddInfo && p_d3dInfo); + + for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++, number++) { + if (&(*it) == p_ddInfo) { + GUID4 guid; + memcpy(&guid, p_d3dInfo->m_guid, sizeof(GUID4)); + + sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", number, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); + return 0; + } + } + + return -1; +} + +// FUNCTION: BETA10 0x1011cc65 +int MxDeviceEnumerate::BETA_1011cc65(int p_idx, char* p_buffer) +{ + if (p_idx < 0 || !IsInitialized()) { + return -1; + } + + int i = 0; + int j = 0; + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + + if (j == p_idx) { + GUID4 guid; + memcpy(&guid, &((Direct3DDeviceInfo&) *it2).m_guid, sizeof(GUID4)); + sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", i, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); + return 0; + } + + j++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x00402860 +// FUNCTION: LEGO1 0x1009d0d0 +// FUNCTION: BETA10 0x1011cdb4 +int MxDeviceEnumerate::FUN_1009d0d0() +{ + if (!IsInitialized()) { + return -1; + } + + if (m_list.size() == 0) { + return -1; + } + + int i = 0; + int j = 0; + int k = -1; + int cpu_mmx = SupportsMMX(); + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + if ((*it2).m_HWDesc.dcmColorModel) { + return j; + } + else { + if (cpu_mmx && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) { + k = j; + } + else if ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0) { + k = j; + } + } + + j++; + } + } + + return k; +} + +// FUNCTION: CONFIG 0x00402930 +// FUNCTION: LEGO1 0x1009d1a0 +// FUNCTION: BETA10 0x1011cf54 +int MxDeviceEnumerate::SupportsMMX() +{ + if (!SupportsCPUID()) { + return 0; + } + int supports_mmx; +#ifdef _MSC_VER + __asm { + mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + mov eax, 0x1 ; EAX=1: Processor Info and Feature Bits (unused) +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + xor eax, eax ; Zero EAX register + 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 + return supports_mmx; +} + +// FUNCTION: CONFIG 0x00402970 +// FUNCTION: LEGO1 0x1009d1e0 +// FUNCTION: BETA10 0x1011cf97 +int MxDeviceEnumerate::SupportsCPUID() +{ + int has_cpuid; +#ifdef _MSC_VER +#if defined(_M_IX86) + __asm { + xor eax, eax ; Zero EAX register + pushfd ; Push EFLAGS register value on the stack + or dword ptr[esp], 0x200000 ; Set bit 0x200000: Able to use CPUID instruction (Pentium+) + popfd ; Write the updated value into the EFLAGS register + pushfd ; Push EFLAGS register value on the stack (again) + btr dword ptr[esp], 0x15 ; Test bit 0x15 (21) and reset (set CF) + adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF + popfd ; Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + mov has_cpuid, eax ; Save eax into C variable + } +#elif defined(_M_X64) + has_cpuid = 1; +#else + has_cpuid = 0; +#endif +#else +#if defined(__i386__) + __asm__("xorl %%eax, %%eax\n\t" // Zero EAX register + "pushfl\n\t" // Push EFLAGS register value on the stack + "orl $0x200000, (%%esp)\n\t" // Set bit 0x200000: Able to use CPUID instruction (Pentium+) + "popfl\n\t" // Write the updated value into the EFLAGS register + "pushfl\n\t" // Push EFLAGS register value on the stack (again) + "btrl $0x15, (%%esp)\n\t" // Test bit 0x15 (21) and reset (set CF) + "adc %%eax, %%eax\n\t" // Add with carry: EAX = EAX + EAX + CF = CF + "popfl" // Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + : "=a"(has_cpuid) // has_cpuid == EAX + ); +#elif defined(__x86_64__) || defined(__amd64__) + has_cpuid = 1; +#else + has_cpuid = 0; +#endif +#endif + return has_cpuid; +} + +// FUNCTION: CONFIG 0x004029a0 +// FUNCTION: LEGO1 0x1009d210 +// FUNCTION: BETA10 0x1011cfc4 +int MxDeviceEnumerate::FUN_1009d210() +{ + if (!IsInitialized()) { + return -1; + } + + for (list::iterator it = m_list.begin(); it != m_list.end();) { + if (!DriverSupportsRequiredDisplayMode(*it)) { + m_list.erase(it++); + continue; + } + + MxDriver& driver = *it; + + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { + if (!FUN_1009d3d0(*it2)) { + driver.m_devices.erase(it2++); + } + else { + it2++; + } + } + + if (!driver.m_devices.size()) { + m_list.erase(it++); + } + else { + it++; + } + } + + if (!m_list.size()) { + return -1; + } + + return 0; +} + +// FUNCTION: CONFIG 0x00402b00 +// FUNCTION: LEGO1 0x1009d370 +// FUNCTION: BETA10 0x1011d176 +unsigned char MxDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) +{ + for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); + it++) { + if ((*it).m_width == 640 && (*it).m_height == 480) { + if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { + return TRUE; + } + } + } + + return FALSE; +} + +// FUNCTION: CONFIG 0x00402b60 +// FUNCTION: LEGO1 0x1009d3d0 +// FUNCTION: BETA10 0x1011d235 +unsigned char MxDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) +{ + if (m_list.size() <= 0) { + return FALSE; + } + + if (p_device.m_HWDesc.dcmColorModel) { + if (p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && + p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + return TRUE; + } + else { + return FALSE; + } + } + + MxDriver& front = m_list.front(); + for (list::iterator it = front.m_devices.begin(); it != front.m_devices.end(); it++) { + if ((&*it) == &p_device) { + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x1009efb0 +// FUNCTION: BETA10 0x10122ee2 +DeviceModesInfo::DeviceModesInfo() +{ + memset(this, 0, sizeof(*this)); +} + +// FUNCTION: LEGO1 0x1009efd0 +// FUNCTION: BETA10 0x10122f0e +DeviceModesInfo::~DeviceModesInfo() +{ + if (m_guid != NULL) { + delete m_guid; + } + + if (m_modeArray != NULL) { + delete[] m_modeArray; + } +} diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h new file mode 100644 index 00000000..d9279670 --- /dev/null +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -0,0 +1,347 @@ +#ifndef MXDIRECTXINFO_H +#define MXDIRECTXINFO_H + +#include "decomp.h" +#include "mxstl/stlcompat.h" + +#include + +// SIZE 0x17c +struct DeviceModesInfo { + // SIZE 0x0c + struct Mode { + int operator==(const Mode& p_mode) const + { + return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel)); + } + + int width; // 0x00 + int height; // 0x04 + int bitsPerPixel; // 0x08 + }; + + DeviceModesInfo(); + ~DeviceModesInfo(); + + GUID* m_guid; // 0x00 + Mode* m_modeArray; // 0x04 + int m_count; // 0x08 + DDCAPS m_ddcaps; // 0x0c + void* m_unk0x178; // 0x178 + + // SYNTHETIC: BETA10 0x1011c650 + // DeviceModesInfo::`scalar deleting destructor' +}; + +// SIZE 0xe4 +class MxAssignedDevice { +public: + enum { + c_hardwareMode = 0x01, + c_primaryDevice = 0x02 + }; + + MxAssignedDevice(); + ~MxAssignedDevice(); + + inline unsigned int GetFlags() { return m_flags; } + inline BOOL GetHardwareMode() { return ((int) m_flags << 31) >> 31; } + inline D3DDEVICEDESC& GetDesc() { return m_desc; } + + friend class MxDirect3D; + + // SYNTHETIC: BETA10 0x1011c130 + // MxAssignedDevice::`scalar deleting destructor' + +private: + GUID m_guid; // 0x00 + unsigned int m_flags; // 0x10 + D3DDEVICEDESC m_desc; // 0x14 + DeviceModesInfo* m_deviceInfo; // 0xe0 +}; + +// SIZE 0x1a4 +struct Direct3DDeviceInfo { + Direct3DDeviceInfo() {} + ~Direct3DDeviceInfo(); + Direct3DDeviceInfo( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + + void Initialize( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + + LPGUID m_guid; // 0x00 + char* m_deviceDesc; // 0x04 + char* m_deviceName; // 0x08 + D3DDEVICEDESC m_HWDesc; // 0x0c + D3DDEVICEDESC m_HELDesc; // 0xd8 + + int operator==(Direct3DDeviceInfo) const { return 0; } + int operator<(Direct3DDeviceInfo) const { return 0; } +}; + +// SIZE 0x0c +struct MxDisplayMode { + MxDisplayMode() {} + // FUNCTION: BETA10 0x1011f920 + MxDisplayMode(DWORD p_width, DWORD p_height, DWORD p_bitsPerPixel) + { + m_width = p_width; + m_height = p_height; + m_bitsPerPixel = p_bitsPerPixel; + } + + int operator==(MxDisplayMode) const { return 0; } + int operator<(MxDisplayMode) const { return 0; } + + DWORD m_width; // 0x00 + DWORD m_height; // 0x04 + DWORD m_bitsPerPixel; // 0x08 +}; + +// SIZE 0x190 +struct MxDriver { + MxDriver() {} + ~MxDriver(); + MxDriver(LPGUID p_guid); + MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + + void Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + + LPGUID m_guid; // 0x00 + char* m_driverDesc; // 0x04 + char* m_driverName; // 0x08 + DDCAPS m_ddCaps; // 0x0c + list m_devices; // 0x178 + list m_displayModes; // 0x184 + + int operator==(MxDriver) const { return 0; } + int operator<(MxDriver) const { return 0; } +}; + +// TEMPLATE: CONFIG 0x401000 +// TEMPLATE: LEGO1 0x1009b900 +// TEMPLATE: BETA10 0x1011ee40 +// list >::~list > + +// TEMPLATE: CONFIG 0x401070 +// TEMPLATE: LEGO1 0x1009b970 +// TEMPLATE: BETA10 0x1011f0a0 +// list >::~list > + +// TEMPLATE: CONFIG 0x4010e0 +// TEMPLATE: LEGO1 0x1009b9e0 +// TEMPLATE: BETA10 0x1011f3d0 +// List::~List + +// TEMPLATE: CONFIG 0x401130 +// TEMPLATE: LEGO1 0x1009ba30 +// TEMPLATE: BETA10 0x1011f430 +// List::~List + +// TEMPLATE: CONFIG 0x401650 +// TEMPLATE: LEGO1 0x1009bf50 +// TEMPLATE: BETA10 0x1011f550 +// list >::~list > + +// TEMPLATE: CONFIG 0x4016c0 +// TEMPLATE: LEGO1 0x1009bfc0 +// TEMPLATE: BETA10 0x1011f6f0 +// List::~List + +// Compiler-generated copy ctor for MxDriver +// SYNTHETIC: CONFIG 0x401990 +// SYNTHETIC: LEGO1 0x1009c290 +// ??0MxDriver@@QAE@ABU0@@Z + +// TEMPLATE: CONFIG 0x401b00 +// TEMPLATE: LEGO1 0x1009c400 +// TEMPLATE: BETA10 0x1011fad0 +// list >::insert + +// TEMPLATE: CONFIG 0x401b60 +// TEMPLATE: LEGO1 0x1009c460 +// TEMPLATE: BETA10 0x1011f9a0 +// list >::insert + +// SYNTHETIC: CONFIG 0x402be0 +// SYNTHETIC: LEGO1 0x1009d450 +// MxDriver::`scalar deleting destructor' + +// SYNTHETIC: CONFIG 0x402c00 +// SYNTHETIC: LEGO1 0x1009d470 +// Direct3DDeviceInfo::`scalar deleting destructor' + +// VTABLE: CONFIG 0x00406000 +// VTABLE: LEGO1 0x100db814 +// VTABLE: BETA10 0x101c1b0c +// SIZE 0x14 +class MxDeviceEnumerate { +public: + MxDeviceEnumerate(); + ~MxDeviceEnumerate(); + + virtual int DoEnumerate(); // vtable+0x00 + + BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + HRESULT EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd); + HRESULT EnumDevicesCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + const char* EnumerateErrorToString(HRESULT p_error); + int ParseDeviceName(const char* p_deviceId); + int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); + int GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device); + int FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) const; + int BETA_1011cc65(int p_idx, char* p_buffer); + + int FUN_1009d0d0(); + int FUN_1009d210(); + unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); + unsigned char FUN_1009d3d0(Direct3DDeviceInfo& p_device); + + static void BuildErrorString(const char*, ...); + static BOOL CALLBACK + DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); + static HRESULT CALLBACK DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context); + static HRESULT CALLBACK DevicesEnumerateCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc, + LPVOID p_context + ); + static int SupportsMMX(); + static int SupportsCPUID(); + + friend class MxDirect3D; + + const list& GetDriverList() const { return m_list; } + + // SIZE 0x10 + struct GUID4 { + int m_data1; + int m_data2; + int m_data3; + int m_data4; + + // FUNCTION: BETA10 0x1011d340 + static unsigned char Compare(const GUID4& p_a, const GUID4& p_b) + { + return p_a.m_data1 == p_b.m_data1 && p_a.m_data2 == p_b.m_data2 && p_a.m_data3 == p_b.m_data3 && + p_a.m_data4 == p_b.m_data4; + } + }; + + // FUNCTION: BETA10 0x1011d320 + unsigned char IsInitialized() const { return m_initialized; } + +private: + list m_list; // 0x04 + unsigned char m_initialized; // 0x10 +}; + +// VTABLE: CONFIG 0x4060e4 +// VTABLE: LEGO1 0x100d9cc8 +// VTABLE: BETA10 0x101befb4 +// SIZE 0x14 +class LegoDeviceEnumerate : public MxDeviceEnumerate {}; + +// SYNTHETIC: BETA10 0x100d8d10 +// LegoDeviceEnumerate::LegoDeviceEnumerate + +// SYNTHETIC: LEGO1 0x1007b590 +// SYNTHETIC: BETA10 0x100d8da0 +// LegoDeviceEnumerate::~LegoDeviceEnumerate + +// TEMPLATE: BETA10 0x1011c1b0 +// list >::iterator::operator* + +// TEMPLATE: BETA10 0x1011c200 +// list >::iterator::operator++ + +// TEMPLATE: BETA10 0x1011c290 +// list >::begin + +// TEMPLATE: BETA10 0x1011c300 +// list >::end + +// TEMPLATE: BETA10 0x1011c4d0 +// list >::iterator::operator* + +// TEMPLATE: BETA10 0x1011c520 +// list >::iterator::operator++ + +// TEMPLATE: BETA10 0x1011c560 +// list >::iterator::operator++ + +// TEMPLATE: BETA10 0x1011c590 +// list >::_Acc::_Next + +// TEMPLATE: BETA10 0x1011c5b0 +// list >::begin + +// TEMPLATE: BETA10 0x1011c5f0 +// list >::iterator::iterator + +// TEMPLATE: BETA10 0x1011c620 +// list >::end + +// TEMPLATE: BETA10 0x1011c690 +// ??9@YAHABViterator@?$list@UMxDriver@@V?$allocator@UMxDriver@@@@@@0@Z + +// TEMPLATE: BETA10 0x1011c770 +// ??9@YAHABViterator@?$list@UDirect3DDeviceInfo@@V?$allocator@UDirect3DDeviceInfo@@@@@@0@Z + +// TEMPLATE: BETA10 0x1011d3a0 +// list >::size + +// TEMPLATE: BETA10 0x1011d3c0 +// list >::size + +// TEMPLATE: BETA10 0x1011d3e0 +// list >::erase + +// TEMPLATE: BETA10 0x1011d570 +// list >::erase + +// TEMPLATE: BETA10 0x1011d6a0 +// list >::_Freenode + +// TEMPLATE: BETA10 0x1011d700 +// list >::front + +// TEMPLATE: BETA10 0x1011f750 +// list >::back + +// TEMPLATE: BETA10 0x1011f780 +// list >::iterator::operator-- + +// TEMPLATE: BETA10 0x1011f7b0 +// list >::push_back + +// TEMPLATE: BETA10 0x1011f830 +// list >::insert + +// TEMPLATE: BETA10 0x1011f960 +// list >::push_back + +// TEMPLATE: BETA10 0x1011fa90 +// list >::push_back + +#endif // MXDIRECTXINFO_H From 4a87c3bc445998aa324c0581e8a0d36052e98e15 Mon Sep 17 00:00:00 2001 From: MS Date: Fri, 28 Jun 2024 17:58:35 -0400 Subject: [PATCH 2/6] Small update to datacmp and roadmap (#1048) * Match uninit variables with all nulls * Enable _pnhHeap variable for ISLE * Roadmap bugfix for ordinal import dummy addrs * Format fix --- ISLE/library_smartheap.h | 2 +- tools/datacmp.py | 34 ++++++++++++++++++++++------------ tools/roadmap/roadmap.py | 4 +++- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/ISLE/library_smartheap.h b/ISLE/library_smartheap.h index c503372e..53ef5f0d 100644 --- a/ISLE/library_smartheap.h +++ b/ISLE/library_smartheap.h @@ -297,7 +297,7 @@ // GLOBAL: ISLE 0x4105b0 // __shi_TaskRecord -// ~GLOBAL: ISLE 0x4125f8 +// GLOBAL: ISLE 0x4125f8 // ?_pnhHeap@@3P6AHI@ZA // GLOBAL: ISLE 0x412830 diff --git a/tools/datacmp.py b/tools/datacmp.py index 7073fc09..cbd18877 100644 --- a/tools/datacmp.py +++ b/tools/datacmp.py @@ -188,24 +188,33 @@ def do_the_comparison(args: argparse.Namespace) -> Iterable[ComparisonItem]: orig_raw = origfile.read(var.orig_addr, data_size) recomp_raw = recompfile.read(var.recomp_addr, data_size) - # If either read exceeded the raw data size for the section, - # assume the entire variable is uninitialized. - # TODO: This is not correct, strictly speaking. However, - # it is probably impossible for a variable to exceed - # the virtual size of the section, so all that is left is - # the uninitialized data. - # If the variable falls at the end of the section like this, - # it is highly likely to be uninitialized. + # The IMAGE_SECTION_HEADER defines the SizeOfRawData and VirtualSize for the section. + # If VirtualSize > SizeOfRawData, the section is comprised of the initialized data + # corresponding to bytes in the file, and the rest is padded with zeroes when + # Windows loads the image. + # The linker might place variables initialized to zero on the threshold between + # physical data and the virtual (uninitialized) data. + # If this happens (i.e. we get an incomplete read) we just do the same padding + # to prepare for the comparison. if orig_raw is not None and len(orig_raw) < data_size: - orig_raw = None + orig_raw = orig_raw.ljust(data_size, b"\x00") if recomp_raw is not None and len(recomp_raw) < data_size: - recomp_raw = None + recomp_raw = recomp_raw.ljust(data_size, b"\x00") - # If both variables are uninitialized, we consider them equal. - # Otherwise, this is a diff but there is nothing to compare. + # If one or both variables are entirely uninitialized if orig_raw is None or recomp_raw is None: + # If both variables are uninitialized, we consider them equal. match = orig_raw is None and recomp_raw is None + + # We can match a variable initialized to all zeroes with + # an uninitialized variable, but this may or may not actually + # be correct, so we flag it for the user. + uninit_force_match = not match and ( + (orig_raw is None and all(b == 0 for b in recomp_raw)) + or (recomp_raw is None and all(b == 0 for b in orig_raw)) + ) + orig_value = "(uninitialized)" if orig_raw is None else "(initialized)" recomp_value = ( "(uninitialized)" if recomp_raw is None else "(initialized)" @@ -220,6 +229,7 @@ def do_the_comparison(args: argparse.Namespace) -> Iterable[ComparisonItem]: values=(orig_value, recomp_value), ) ], + raw_only=uninit_force_match, ) continue diff --git a/tools/roadmap/roadmap.py b/tools/roadmap/roadmap.py index a0df3cbc..b7294a95 100644 --- a/tools/roadmap/roadmap.py +++ b/tools/roadmap/roadmap.py @@ -415,7 +415,9 @@ def to_roadmap_row(match): displacement = None module_name = None - if match.recomp_addr is not None: + if match.recomp_addr is not None and recomp_bin.is_valid_vaddr( + match.recomp_addr + ): if (module_ref := module_map.get_module(match.recomp_addr)) is not None: (_, module_name) = module_ref From fb34f86171aa70df4b84cbe67c578d873a972657 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:45:10 +0200 Subject: [PATCH 3/6] Improve several functions in `vector.h` (#1049) * Improve some functions in vector.h - Add BETA10 references - inline some functions based on BETA10 - Identify and improve `Vector4::EqualsHamiltonProduct` * Fix BETA10 offset * Fix BETA10 annotation order --------- Co-authored-by: jonschz --- LEGO1/mxgeometry/mxgeometry3d.h | 1 + LEGO1/realtime/vector.h | 46 ++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 3f52b2e2..3da2f5af 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -43,6 +43,7 @@ class Mx3DPointFloat : public Vector3 { }; // VTABLE: LEGO1 0x100d41e8 +// VTABLE: BETA10 0x101bab78 // SIZE 0x18 class Mx4DPointFloat : public Vector4 { public: diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index cfccb6f4..86251b33 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -178,7 +178,8 @@ class Vector3 : public Vector2 { // in reverse order of appearance. // FUNCTION: LEGO1 0x10002270 - virtual void EqualsCrossImpl(float* p_a, float* p_b) + // FUNCTION: BETA10 0x100064a1 + inline virtual void EqualsCrossImpl(float* p_a, float* p_b) { m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; @@ -229,7 +230,7 @@ class Vector3 : public Vector2 { } // vtable+0x08 // FUNCTION: LEGO1 0x10003b20 - void MulScalarImpl(float* p_value) override + inline void MulScalarImpl(float* p_value) override { m_data[0] *= *p_value; m_data[1] *= *p_value; @@ -274,6 +275,7 @@ class Vector3 : public Vector2 { }; // VTABLE: LEGO1 0x100d45a0 +// VTABLE: BETA10 0x101bac38 // SIZE 0x08 class Vector4 : public Vector3 { public: @@ -294,8 +296,8 @@ class Vector4 : public Vector3 { // FUNCTION: LEGO1 0x10002ae0 virtual void SetMatrixProduct(Vector4* p_a, float* p_b) { SetMatrixProduct(p_a->m_data, p_b); } // vtable+0x88 - inline virtual int NormalizeQuaternion(); // vtable+0x90 - inline virtual void UnknownQuaternionOp(Vector4* p_a, Vector4* p_b); // vtable+0x94 + inline virtual int NormalizeQuaternion(); // vtable+0x90 + inline virtual int EqualsHamiltonProduct(Vector4* p_a, Vector4* p_b); // vtable+0x94 // Vector3 overrides @@ -383,40 +385,42 @@ class Vector4 : public Vector3 { friend class Mx4DPointFloat; }; -// Note close yet, included because I'm at least confident I know what operation -// it's trying to do. -// STUB: LEGO1 0x10002b70 +// FUNCTION: LEGO1 0x10002b70 +// FUNCTION: BETA10 0x10048ad0 inline int Vector4::NormalizeQuaternion() { float* v = m_data; - float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; + float magnitude = v[0] * v[0] + v[2] * v[2] + v[1] * v[1]; if (magnitude > 0.0f) { float theta = v[3] * 0.5f; v[3] = cos(theta); - float frac = sin(theta); - magnitude = frac / sqrt(magnitude); - v[0] *= magnitude; - v[1] *= magnitude; - v[2] *= magnitude; + magnitude = sin(theta) / sqrt(magnitude); + Vector3::MulScalarImpl(&magnitude); return 0; } return -1; } -// FUNCTION: LEGO1 0x10002bf0 -inline void Vector4::UnknownQuaternionOp(Vector4* p_a, Vector4* p_b) +inline static float QuaternionProductScalarPart(float* bDat, float* aDat) { - float* bDat = p_b->m_data; - float* aDat = p_a->m_data; + // We have no indication from the beta that this function exists, + // but it helps with the stack layout of Vector4::EqualsHamiltonProduct() + return aDat[3] * bDat[3] - (aDat[0] * bDat[0] + aDat[2] * bDat[2] + aDat[1] * bDat[1]); +} - this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); - this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; - this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; - this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; +// FUNCTION: LEGO1 0x10002bf0 +// FUNCTION: BETA10 0x10048c20 +inline int Vector4::EqualsHamiltonProduct(Vector4* p_a, Vector4* p_b) +{ + m_data[3] = QuaternionProductScalarPart(p_a->m_data, p_b->m_data); + + Vector3::EqualsCrossImpl(p_a->m_data, p_b->m_data); m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; + + return 0; } #endif // VECTOR_H From a21fd5975c666dd7bd150cbd5556d32fe41070c1 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:39:31 +0200 Subject: [PATCH 4/6] Start implementing `LegoRaceCar` (#1050) * Implement several functions * Limited match on LegoRaceCar::ParseAction * WIP: progress in the right direction * Implement LegoRaceCar::ParseAction() * fix linter issues * Address review comments * fix naming * fix naming (again) * Relocate address annotations --------- Co-authored-by: jonschz --- LEGO1/define.cpp | 4 + LEGO1/define.h | 1 + LEGO1/lego/legoomni/include/legorace.h | 3 +- LEGO1/lego/legoomni/include/legoracecar.h | 25 +++-- LEGO1/lego/legoomni/src/race/legoracecar.cpp | 101 ++++++++++++++++--- 5 files changed, 112 insertions(+), 22 deletions(-) diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 0c04bb50..4460107f 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -128,6 +128,10 @@ const char* g_strWORLD = "WORLD"; // STRING: LEGO1 0x10101ed0 const char* g_strANIMMAN_ID = "ANIMMAN_ID"; +// GLOBAL: LEGO1 0x101020d8 +// STRING: LEGO1 0x10101ec8 +const char* g_strCOMP = "COMP"; + // GLOBAL: LEGO1 0x101020e0 // STRING: LEGO1 0x10101eb0 const char* g_strBMP_ISMAP = "BMP_ISMAP"; diff --git a/LEGO1/define.h b/LEGO1/define.h index a73a80f8..1704d045 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -31,6 +31,7 @@ extern const char* g_strBOTTOM_TO_TOP; extern const char* g_strTOP_TO_BOTTOM; extern const char* g_strFILLER_INDEX; extern const char* g_strVARIABLE; +extern const char* g_strCOMP; extern const char* g_strBMP_ISMAP; extern const char* g_strAUTO_CREATE; extern const char* g_strDB_CREATE; diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index 388fa26a..85954a98 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "legogamestate.h" +#include "legoracemap.h" #include "legostate.h" #include "legoworld.h" #include "mxrect32.h" @@ -124,7 +125,7 @@ class LegoRace : public LegoWorld { virtual MxLong HandleType0Notification(MxNotificationParam&) { return 0; } // vtable+0x78 // STUB: LEGO1 0x1000dac0 - virtual void VTable0x7c(undefined4, undefined4) {} // vtable+0x7c + virtual void VTable0x7c(LegoRaceMap*, undefined4) {} // vtable+0x7c // SYNTHETIC: LEGO1 0x10015cc0 // LegoRace::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoracecar.h b/LEGO1/lego/legoomni/include/legoracecar.h index 18504c72..4fa0adce 100644 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ b/LEGO1/lego/legoomni/include/legoracecar.h @@ -4,6 +4,12 @@ #include "legocarraceactor.h" #include "legoracemap.h" +// SIZE 0x08 +struct EdgeReference { + const char* m_name; // 0x00 + LegoPathBoundary* m_data; // 0x04 +}; + // VTABLE: LEGO1 0x100d58a0 LegoRaceActor // VTABLE: LEGO1 0x100d58a8 LegoAnimActor // VTABLE: LEGO1 0x100d58b8 LegoPathActor @@ -46,7 +52,7 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { override; // vtable+0x98 MxResult VTable0x9c() override; // vtable+0x9c - virtual void FUN_10012ea0(float p_worldSpeed); + virtual void SetMaxLinearVelocity(float p_maxLinearVelocity); virtual void FUN_10012ff0(float); virtual MxBool FUN_10013130(float); @@ -54,13 +60,16 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { // LegoRaceCar::`scalar deleting destructor' private: - undefined m_unk0x54; // 0x54 - undefined4 m_unk0x58; // 0x58 - Mx3DPointFloat m_unk0x5c; // 0x5c - undefined4 m_unk0x70; // 0x70 - undefined4 m_unk0x74; // 0x74 - undefined4 m_unk0x78; // 0x78 - undefined4 m_unk0x7c; // 0x7c + undefined m_unk0x54; // 0x54 + undefined4 m_unk0x58; // 0x58 + Mx3DPointFloat m_unk0x5c; // 0x5c + LegoAnimActorStruct* m_unk0x70; // 0x70 + LegoAnimActorStruct* m_unk0x74; // 0x74 + LegoPathBoundary* m_unk0x78; // 0x78 + LegoPathBoundary* m_unk0x7c; // 0x7c + + static EdgeReference g_edgeReferences[]; + static const EdgeReference* g_pEdgeReferences; }; #endif // LEGORACECAR_H diff --git a/LEGO1/lego/legoomni/src/race/legoracecar.cpp b/LEGO1/lego/legoomni/src/race/legoracecar.cpp index ead26c64..2a2b2a7e 100644 --- a/LEGO1/lego/legoomni/src/race/legoracecar.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracecar.cpp @@ -1,10 +1,46 @@ #include "legoracecar.h" +#include "define.h" +#include "legorace.h" +#include "misc.h" #include "mxmisc.h" #include "mxnotificationmanager.h" +#include "mxutilities.h" +DECOMP_SIZE_ASSERT(EdgeReference, 0x08) DECOMP_SIZE_ASSERT(LegoRaceCar, 0x200) +// GLOBAL: LEGO1 0x100f0a20 +EdgeReference LegoRaceCar::g_edgeReferences[] = { + {// STRING: LEGO1 0x100f0a10 + "EDG03_772", + NULL + }, + {// STRING: LEGO1 0x100f0a04 + "EDG03_773", + NULL + }, + {// STRING: LEGO1 0x100f09f8 + "EDG03_774", + NULL + }, + {// STRING: LEGO1 0x100f09ec + "EDG03_775", + NULL + }, + {// STRING: LEGO1 0x100f09e0 + "EDG03_776", + NULL + }, + {// STRING: LEGO1 0x100f09d4 + "EDG03_777", + NULL + } +}; + +// GLOBAL: LEGO1 0x100f0a50 +const EdgeReference* LegoRaceCar::g_pEdgeReferences = g_edgeReferences; + // FUNCTION: LEGO1 0x10012950 LegoRaceCar::LegoRaceCar() { @@ -18,42 +54,81 @@ LegoRaceCar::LegoRaceCar() NotificationManager()->Register(this); } -// STUB: LEGO1 0x10012c80 +// FUNCTION: LEGO1 0x10012c80 LegoRaceCar::~LegoRaceCar() { - // TODO + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10012d90 +// FUNCTION: LEGO1 0x10012d90 MxLong LegoRaceCar::Notify(MxParam& p_param) { - // TODO - return 0; + return LegoRaceMap::Notify(p_param); } -// STUB: LEGO1 0x10012e60 +// FUNCTION: LEGO1 0x10012e60 void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) { - // TODO + if (!m_userNavFlag) { + if (!LegoCarRaceActor::m_unk0x0c) { + m_maxLinearVel = p_worldSpeed; + } + LegoAnimActor::SetWorldSpeed(p_worldSpeed); + } + else { + m_worldSpeed = p_worldSpeed; + } } // FUNCTION: LEGO1 0x10012ea0 -void LegoRaceCar::FUN_10012ea0(float p_worldSpeed) +void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity) { - if (p_worldSpeed < 0) { + if (p_maxLinearVelocity < 0) { LegoCarRaceActor::m_unk0x0c = 2; m_maxLinearVel = 0; SetWorldSpeed(0); } else { - m_maxLinearVel = p_worldSpeed; + m_maxLinearVel = p_maxLinearVelocity; } } -// STUB: LEGO1 0x10012ef0 -void LegoRaceCar::ParseAction(char*) +// FUNCTION: LEGO1 0x10012ef0 +void LegoRaceCar::ParseAction(char* p_extra) { - // TODO + char buffer[256]; + + LegoAnimActor::ParseAction(p_extra); + LegoRaceMap::ParseAction(p_extra); + LegoRace* currentWorld = (LegoRace*) CurrentWorld(); + + if (KeyValueStringParse(buffer, g_strCOMP, p_extra) && currentWorld) { + currentWorld->VTable0x7c(this, atoi(buffer)); + } + + if (m_userNavFlag) { + for (MxU32 i = 0; i < m_animMaps.size(); i++) { + LegoAnimActorStruct* animMap = m_animMaps[i]; + + if (animMap->m_unk0x00 == -1.0f) { + m_unk0x70 = animMap; + } + else if (animMap->m_unk0x00 == -2.0f) { + m_unk0x74 = animMap; + } + } + + // STRING: LEGO1 0x100f0bc4 + const char* edge0344 = "EDG03_44"; + m_unk0x78 = currentWorld->FindPathBoundary(edge0344); + // STRING: LEGO1 0x100f0bb8 + const char* edge0354 = "EDG03_54"; + m_unk0x7c = currentWorld->FindPathBoundary(edge0354); + + for (MxS32 j = 0; j < sizeOfArray(g_edgeReferences); j++) { + g_edgeReferences[j].m_data = currentWorld->FindPathBoundary(g_edgeReferences[j].m_name); + } + } } // STUB: LEGO1 0x10012ff0 From 9ba05d021d8facf150f089afcad79e80efa4e14f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 1 Jul 2024 16:14:04 -0700 Subject: [PATCH 5/6] Implement/match LegoPlantManager::ScheduleAnimation (#1051) * Implement/match LegoPlantManager::ScheduleAnimation * Add assert --- .../legoomni/include/legobuildingmanager.h | 4 +- .../lego/legoomni/include/legoplantmanager.h | 15 ++++-- .../src/common/legobuildingmanager.cpp | 4 +- .../legoomni/src/common/legoplantmanager.cpp | 52 ++++++++++++++++--- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 8c9c8cec..25d6c1d8 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -45,7 +45,7 @@ class LegoBuildingManager : public MxCore { struct AnimEntry { LegoEntity* m_entity; // 0x00 LegoROI* m_roi; // 0x04 - LegoTime m_time; // 0x08 + MxLong m_time; // 0x08 float m_unk0x0c; // 0x0c MxBool m_muted; // 0x10 }; @@ -81,7 +81,7 @@ class LegoBuildingManager : public MxCore { MxBool FUN_10030000(LegoEntity* p_entity); MxBool FUN_10030030(MxS32 p_index); MxBool FUN_10030110(LegoBuildingInfo* p_data); - void ScheduleAnimation(LegoEntity* p_entity, MxU32 p_length, MxBool p_haveSound, MxBool p_unk0x28); + void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28); void FUN_10030590(); void AdjustHeight(MxS32 p_index); MxResult FUN_10030630(); diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 48f69521..704aa1a0 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -15,6 +15,13 @@ class LegoWorld; // SIZE 0x2c class LegoPlantManager : public MxCore { public: + // SIZE 0x0c + struct AnimEntry { + LegoEntity* m_entity; // 0x00 + LegoROI* m_roi; // 0x04 + MxLong m_time; // 0x08 + }; + LegoPlantManager(); ~LegoPlantManager() override; // vtable+0x00 @@ -40,6 +47,7 @@ class LegoPlantManager : public MxCore { MxU32 GetAnimationId(LegoEntity* p_entity); MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state); MxBool FUN_10026c50(LegoEntity* p_entity); + void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length); void FUN_10027120(); static void SetCustomizeAnimFile(const char* p_value); @@ -54,6 +62,7 @@ class LegoPlantManager : public MxCore { void FUN_10026860(MxS32 p_index); LegoPlantInfo* GetInfo(LegoEntity* p_entity); MxBool FUN_10026c80(MxS32 p_index); + void FUN_100271b0(LegoEntity* p_entity, MxS32 p_adjust); static char* g_customizeAnimFile; static MxS32 g_maxMove[4]; @@ -61,9 +70,9 @@ class LegoPlantManager : public MxCore { MxS32 m_worldId; // 0x08 undefined m_unk0x0c; // 0x0c - undefined* m_unk0x10[5]; // 0x10 - MxS8 m_unk0x24; // 0x24 - undefined4 m_unk0x28; // 0x28 + AnimEntry* m_entries[5]; // 0x10 + MxS8 m_numEntries; // 0x24 + LegoWorld* m_world; // 0x28 }; #endif // LEGOPLANTMANAGER_H diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index b69a3f52..8577f71c 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -613,7 +613,7 @@ MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data) } // FUNCTION: LEGO1 0x10030150 -void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxU32 p_length, MxBool p_haveSound, MxBool p_unk0x28) +void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28) { m_world = CurrentWorld(); @@ -633,7 +633,7 @@ void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxU32 p_length entry->m_entity = p_entity; entry->m_roi = p_entity->GetROI(); entry->m_time = Timer()->GetTime() + p_length + 1000; - entry->m_unk0x0c = entry->m_roi->GetLocal2World()[3][1]; + entry->m_unk0x0c = entry->m_roi->GetWorldPosition()[1]; entry->m_muted = p_haveSound == FALSE; FUN_100307b0(p_entity, -2); } diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 263cdd94..6b661adc 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -8,6 +8,9 @@ #include "legoworld.h" #include "misc.h" #include "misc/legostorage.h" +#include "mxmisc.h" +#include "mxticklemanager.h" +#include "mxtimer.h" #include "scripts.h" #include "sndanim_actions.h" #include "viewmanager/viewmanager.h" @@ -15,6 +18,7 @@ #include DECOMP_SIZE_ASSERT(LegoPlantManager, 0x2c) +DECOMP_SIZE_ASSERT(LegoPlantManager::AnimEntry, 0x0c) // GLOBAL: LEGO1 0x100f1660 const char* g_plantLodNames[4][5] = { @@ -73,7 +77,7 @@ void LegoPlantManager::Init() m_worldId = -1; m_unk0x0c = 0; - m_unk0x24 = 0; + m_numEntries = 0; } // FUNCTION: LEGO1 0x10026360 @@ -96,11 +100,11 @@ void LegoPlantManager::Reset(MxS32 p_worldId) MxU32 i; DeleteObjects(g_sndAnimScript, SndanimScript::c_AnimC1, SndanimScript::c_AnimBld18); - for (i = 0; i < m_unk0x24; i++) { - delete m_unk0x10[i]; + for (i = 0; i < m_numEntries; i++) { + delete m_entries[i]; } - m_unk0x24 = 0; + m_numEntries = 0; for (i = 0; i < sizeOfArray(g_plantInfo); i++) { RemovePlant(i, p_worldId); @@ -499,11 +503,28 @@ MxBool LegoPlantManager::FUN_10026c80(MxS32 p_index) return result; } +// FUNCTION: LEGO1 0x10026d70 +void LegoPlantManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length) +{ + m_world = CurrentWorld(); + + if (m_numEntries == 0) { + TickleManager()->RegisterClient(this, 50); + } + + AnimEntry* entry = m_entries[m_numEntries] = new AnimEntry; + m_numEntries++; + + entry->m_entity = p_entity; + entry->m_roi = p_entity->GetROI(); + entry->m_time = Timer()->GetTime() + p_length + 1000; + FUN_100271b0(p_entity, -1); +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { - // TODO - return 0; + return SUCCESS; } // FUNCTION: LEGO1 0x10027120 @@ -526,3 +547,22 @@ void LegoPlantManager::FUN_10027120() } } } + +// FUNCTION: LEGO1 0x100271b0 +void LegoPlantManager::FUN_100271b0(LegoEntity* p_entity, MxS32 p_adjust) +{ + LegoPlantInfo* info = GetInfo(p_entity); + + if (info != NULL) { + if (info->m_unk0x16 < 0) { + info->m_unk0x16 = g_unk0x100f16c0[info->m_variant]; + } + + if (info->m_unk0x16 > 0) { + info->m_unk0x16 += p_adjust; + if (info->m_unk0x16 <= 1 && p_adjust < 0) { + info->m_unk0x16 = 0; + } + } + } +} From 7bee5fc6a5cb0ea80369ecf4fee1c373690d50f9 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 1 Jul 2024 16:43:03 -0700 Subject: [PATCH 6/6] Implement/match GasStation::HandleButtonDown (#1052) * Implement/match GasStation::HandleButtonDown * Use enum --- LEGO1/lego/legoomni/include/gasstation.h | 8 ++-- LEGO1/lego/legoomni/src/worlds/gasstation.cpp | 48 +++++++++++++++++-- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h index af224e79..7d4a301b 100644 --- a/LEGO1/lego/legoomni/include/gasstation.h +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -38,7 +38,8 @@ class GasStationState : public LegoState { // SYNTHETIC: LEGO1 0x10006290 // GasStationState::`scalar deleting destructor' - void FUN_10006430(undefined4); + void FUN_10006430(GarageScript::Script); + void FUN_10006460(GarageScript::Script); void FUN_10006490(); // TODO: Most likely getters/setters are not used according to BETA. @@ -82,12 +83,13 @@ class GasStation : public LegoWorld { void Enable(MxBool p_enable) override; // vtable+0x68 virtual MxLong HandleControl(LegoControlManagerNotificationParam& p_param); // vtable+0x6c - inline void PlayAction(MxU32 p_objectId); - // SYNTHETIC: LEGO1 0x100048a0 // GasStation::`scalar deleting destructor' private: + inline void PlayAction(GarageScript::Script p_objectId); + inline void StopAction(GarageScript::Script p_objectId); + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); MxLong HandleKeyPress(MxS8 p_key); MxLong HandleButtonDown(LegoControlManagerNotificationParam& p_param); diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index a2bcb82c..fb809668 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -8,6 +8,7 @@ #include "legogamestate.h" #include "legoinputmanager.h" #include "legomain.h" +#include "legoutils.h" #include "misc.h" #include "mxbackgroundaudiomanager.h" #include "mxmisc.h" @@ -276,7 +277,8 @@ void GasStation::ReadyWorld() } // FUNCTION: LEGO1 0x10005590 -inline void GasStation::PlayAction(MxU32 p_objectId) +// FUNCTION: BETA10 0x10029e30 +inline void GasStation::PlayAction(GarageScript::Script p_objectId) { MxDSAction action; action.SetAtomId(*g_garageScript); @@ -287,6 +289,16 @@ inline void GasStation::PlayAction(MxU32 p_objectId) m_state->FUN_10006430(p_objectId); } +// FUNCTION: BETA10 0x10029f00 +inline void GasStation::StopAction(GarageScript::Script p_objectId) +{ + if (p_objectId != GarageScript::c_noneGarage) { + InvokeAction(Extra::e_stop, *g_garageScript, p_objectId, NULL); + BackgroundAudioManager()->RaiseVolume(); + m_state->FUN_10006460(p_objectId); + } +} + // STUB: LEGO1 0x10005660 MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) { @@ -305,10 +317,32 @@ MxLong GasStation::HandleKeyPress(MxS8 p_key) return 0; } -// STUB: LEGO1 0x10005960 +// FUNCTION: LEGO1 0x10005960 +// FUNCTION: BETA10 0x10029319 MxLong GasStation::HandleButtonDown(LegoControlManagerNotificationParam& p_param) { - // TODO + if (m_unk0x104 == 1 || m_unk0x104 == 2) { + LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY()); + + if (roi != NULL) { + if (!strnicmp(roi->GetName(), "capdb", 5) || !strnicmp(roi->GetName(), "*capdb", 6)) { + m_unk0x104 = 3; + m_unk0x114 = FALSE; + + if (m_state->m_unk0x14.m_unk0x00 == 7) { + m_state->m_unk0x14.m_unk0x00 = 8; + PlayAction(GarageScript::c_wgs029nu_RunAnim); + m_unk0x106 = 1; + } + else { + StopAction(GarageScript::c_wgs023nu_RunAnim); + } + + return 1; + } + } + } + return 0; } @@ -459,7 +493,13 @@ MxResult GasStationState::Serialize(LegoFile* p_file) } // STUB: LEGO1 0x10006430 -void GasStationState::FUN_10006430(undefined4) +void GasStationState::FUN_10006430(GarageScript::Script) +{ + // TODO +} + +// STUB: LEGO1 0x10006460 +void GasStationState::FUN_10006460(GarageScript::Script) { // TODO }