diff --git a/LEGO1/mxdirect3d.cpp b/LEGO1/mxdirect3d.cpp index 0ee2c501..0c621503 100644 --- a/LEGO1/mxdirect3d.cpp +++ b/LEGO1/mxdirect3d.cpp @@ -4,6 +4,8 @@ DECOMP_SIZE_ASSERT(MxDeviceModeFinder, 0xe4); DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); +DECOMP_SIZE_ASSERT(MxDeviceEnumerate0x178Element, 0x1a4); +DECOMP_SIZE_ASSERT(MxDeviceEnumerate0x184Element, 0x0c); DECOMP_SIZE_ASSERT(MxDeviceEnumerateElement, 0x190); DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14); @@ -144,23 +146,118 @@ MxDeviceModeFinder::~MxDeviceModeFinder() } } +// FUNCTION: LEGO1 0x1009ba80 +MxDeviceEnumerateElement::MxDeviceEnumerateElement(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: LEGO1 0x1009bb80 +MxDeviceEnumerateElement::~MxDeviceEnumerateElement() +{ + if (m_guid) + delete m_guid; + + if (m_driverDesc) + delete[] m_driverDesc; + + if (m_driverName) + delete[] m_driverName; +} + +// FUNCTION: LEGO1 0x1009bc30 +void MxDeviceEnumerateElement::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 0x1009bec0 MxDeviceEnumerate::MxDeviceEnumerate() { m_unk0x10 = FALSE; } -// STUB: LEGO1 0x1009c070 -BOOL MxDeviceEnumerate::EnumDirectDrawCallback(GUID FAR* p_guid, LPSTR p_driverName, LPSTR p_driverDesc) +// FUNCTION: LEGO1 0x1009c070 +BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { - // TODO - // HRESULT ret = DirectDrawCreate(); - HRESULT ret = 0; - if (ret) { - BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(ret)); + MxDeviceEnumerateElement device(p_guid, p_driverDesc, p_driverName); + m_list.push_back(device); + + // Must be zeroed because held resources are copied by pointer only + // and should not be freed at the end of this function + device.m_guid = NULL; + device.m_driverDesc = NULL; + device.m_driverName = NULL; + memset(&device.m_ddCaps, 0, sizeof(device.m_ddCaps)); + + LPDIRECTDRAW lpDD = NULL; + LPDIRECT3D2 lpDirect3d2 = NULL; + MxDeviceEnumerateElement& 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_unk0x178.empty()) { + m_list.pop_back(); + } + } + } + } } - // IDirect3D2_EnumDevices - return TRUE; + + if (lpDirect3d2) + lpDirect3d2->Release(); + + if (lpDD) + lpDD->Release(); + + return DDENUMRET_OK; } // FUNCTION: LEGO1 0x1009c4c0 @@ -176,13 +273,32 @@ void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) OutputDebugString(buf); } +// STUB: LEGO1 0x1009c4f0 +HRESULT CALLBACK DisplayModesEnumerateCallback(LPDDSURFACEDESC, LPVOID) +{ + return TRUE; +} + +// STUB: LEGO1 0x1009c510 +HRESULT CALLBACK DevicesEnumerateCallback( + LPGUID p_lpGuid, + LPSTR p_lpDeviceDescription, + LPSTR p_lpDeviceName, + LPD3DDEVICEDESC p_pHWDesc, + LPD3DDEVICEDESC p_pHELDesc, + LPVOID p_context +) +{ + return TRUE; +} + // FUNCTION: LEGO1 0x1009c6c0 MxResult MxDeviceEnumerate::DoEnumerate() { if (m_unk0x10) return FAILURE; - HRESULT ret = DirectDrawEnumerate(EnumerateCallback, this); + HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); if (ret) { BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); return FAILURE; @@ -193,10 +309,10 @@ MxResult MxDeviceEnumerate::DoEnumerate() } // FUNCTION: LEGO1 0x1009c710 -BOOL CALLBACK EnumerateCallback(GUID FAR* p_guid, LPSTR p_driverName, LPSTR p_driverDesc, LPVOID p_context) +BOOL CALLBACK DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) { MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; - return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverName, p_driverDesc); + return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); } // STUB: LEGO1 0x1009c730 diff --git a/LEGO1/mxdirect3d.h b/LEGO1/mxdirect3d.h index 67cf1420..963efc8f 100644 --- a/LEGO1/mxdirect3d.h +++ b/LEGO1/mxdirect3d.h @@ -57,14 +57,61 @@ private: undefined4 m_unk0x890; // 0x890 }; +// SIZE 0x1a4 +struct MxDeviceEnumerate0x178Element { + undefined m_unk0x00[0x1a4]; // 0x00 + + MxBool operator==(MxDeviceEnumerate0x178Element) const { return TRUE; } + MxBool operator<(MxDeviceEnumerate0x178Element) const { return TRUE; } +}; + +// SIZE 0x0c +struct MxDeviceEnumerate0x184Element { + undefined m_unk0x00[0x0c]; // 0x00 + + MxBool operator==(MxDeviceEnumerate0x184Element) const { return TRUE; } + MxBool operator<(MxDeviceEnumerate0x184Element) const { return TRUE; } +}; + // SIZE 0x190 struct MxDeviceEnumerateElement { - undefined m_pad[0x190]; // 0x00 + MxDeviceEnumerateElement() {} + ~MxDeviceEnumerateElement(); + MxDeviceEnumerateElement(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_unk0x178; // 0x178 + list m_unk0x184; // 0x184 MxBool operator==(MxDeviceEnumerateElement) const { return TRUE; } MxBool operator<(MxDeviceEnumerateElement) const { return TRUE; } }; +// clang-format off +// TEMPLATE: LEGO1 0x1009b900 +// list >::~list > +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x1009b970 +// list >::~list > +// clang-format on + +// TEMPLATE: LEGO1 0x1009b9e0 +// List::~List + +// TEMPLATE: LEGO1 0x1009ba30 +// List::~List + +// Compiler-generated copy ctor +// SYNTHETIC: LEGO1 0x1009c290 +// MxDeviceEnumerateElement::MxDeviceEnumerateElement + // VTABLE: LEGO1 0x100db814 // SIZE 0x14 class MxDeviceEnumerate { @@ -73,7 +120,7 @@ public: virtual MxResult DoEnumerate(); // vtable+0x00 - BOOL EnumDirectDrawCallback(GUID FAR* p_guid, LPSTR p_driverName, LPSTR p_driverDesc); + BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); const char* EnumerateErrorToString(HRESULT p_error); MxS32 ParseDeviceName(const char* p_deviceId); MxResult FUN_1009d030(MxS32 p_und1, undefined** p_und2, undefined** p_und3); @@ -82,11 +129,21 @@ public: static void BuildErrorString(const char*, ...); +private: list m_list; // 0x04 MxBool m_unk0x10; // 0x10 }; -BOOL CALLBACK EnumerateCallback(GUID FAR*, LPSTR, LPSTR, LPVOID); +BOOL CALLBACK DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); +HRESULT CALLBACK DisplayModesEnumerateCallback(LPDDSURFACEDESC, LPVOID); +HRESULT CALLBACK DevicesEnumerateCallback( + LPGUID p_lpGuid, + LPSTR p_lpDeviceDescription, + LPSTR p_lpDeviceName, + LPD3DDEVICEDESC p_pHWDesc, + LPD3DDEVICEDESC p_pHELDesc, + LPVOID p_context +); // VTABLE: LEGO1 0x100d9cc8 // SIZE 0x14