Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
.vscode
__pycache__
Debug
!Spore ModAPI/Spore/Debug/
!Spore ModAPI/SourceCode/Debug/
Release
Projects/*
!Projects/Example Projects/
Expand Down
25 changes: 25 additions & 0 deletions Spore ModAPI/SourceCode/DLL/AddressesDebug.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifdef MODAPI_DLL_EXPORT
#include "stdafx.h"
#include <Spore\Debug\ReportWriter.h>

namespace Debug
{
namespace Addresses(ReportWriter)
{
DefineAddress(GetFileNameExtension, SelectAddress(0x0091eee0, 0x0091ec20));
DefineAddress(OpenReport, SelectAddress(0x0091ef10, 0x0091ec50));
DefineAddress(CloseReport, SelectAddress(0x0091ef70, 0x0091ecb0));
DefineAddress(BeginSection, SelectAddress(0x0091efa0, 0x0091ece0));
DefineAddress(EndSection, SelectAddress(0x0091efd0, 0x0091ed10));
DefineAddress(WriteText, SelectAddress(0x0091efe0, 0x0091ed20));
DefineAddress(WriteFormatted, SelectAddress(0x0091f020, 0x0091ed60));
DefineAddress(WriteKeyValue, SelectAddress(0x0091f070, 0x0091edb0));
DefineAddress(WriteKeyValueFormatted, SelectAddress(0x0091f0f0, 0x0091ee30));
DefineAddress(WriteBlankLine, SelectAddress(0x0091f140, 0x0091ee80));
DefineAddress(Write, SelectAddress(0x0091f150, 0x0091ee90));
DefineAddress(GetPosition, SelectAddress(0x0091f1b0, 0x0091eef0));
DefineAddress(SetPosition, SelectAddress(0x0091f1d0, 0x0091ef10));
};
}

#endif
184 changes: 184 additions & 0 deletions Spore ModAPI/SourceCode/DLL/DebugReportWriterOverride.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#ifdef MODAPI_DLL_EXPORT
#include "stdafx.h"
#include "DebugReportWriterOverride.h"

#include <Spore\Debug\ReportWriter.h>
#include <Spore\ModAPI.h>

typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);

member_detour(WriteSystemInfoDetour, Debug::ReportWriter, bool(void))
{
bool detoured(void)
{
char buffer[256] = { 0 };
DWORD bufferSize = sizeof(buffer);

if (GetComputerNameExA(COMPUTER_NAME_FORMAT::ComputerNameDnsFullyQualified, buffer, &bufferSize))
{
WriteKeyValue("Computer name", buffer);
}

bufferSize = sizeof(buffer);
if (GetUserNameA(buffer, &bufferSize))
{
WriteKeyValue("User name", buffer);
}

WriteKeyValue("EA_PLATFORM", "Windows on X86");

// GetVersionExA() is deprecated and only reports upto Windows 8
// unless a higher Windows version is specified in the executable
// manifest, so use RtlGetVersion() from ntdll.dll instead
HMODULE ntdllHandle = GetModuleHandleW(L"ntdll.dll");
if (ntdllHandle != nullptr)
{
RtlGetVersionPtr rtlGetVersion = (RtlGetVersionPtr)GetProcAddress(ntdllHandle, "RtlGetVersion");
if (rtlGetVersion != nullptr)
{
RTL_OSVERSIONINFOW versionInfo = { 0 };
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);

if (rtlGetVersion(&versionInfo) == 0)
{
if (versionInfo.dwMajorVersion == 5 &&
versionInfo.dwMinorVersion == 1)
{
sprintf_s(buffer, sizeof(buffer), "Windows XP");
}
else if (versionInfo.dwMajorVersion == 6 &&
versionInfo.dwMinorVersion == 0)
{
sprintf_s(buffer, sizeof(buffer), "Windows Vista");
}
else if (versionInfo.dwMajorVersion == 6 &&
versionInfo.dwMinorVersion == 1)
{
sprintf_s(buffer, sizeof(buffer), "Windows 7");
}
else if (versionInfo.dwMajorVersion == 6 &&
versionInfo.dwMinorVersion == 2)
{
sprintf_s(buffer, sizeof(buffer), "Windows 8");
}
else if (versionInfo.dwMajorVersion == 6 &&
versionInfo.dwMinorVersion == 3)
{
sprintf_s(buffer, sizeof(buffer), "Windows 8.1");
}
else if (versionInfo.dwMajorVersion == 10 &&
versionInfo.dwMinorVersion == 0 &&
versionInfo.dwBuildNumber < 22000)
{
sprintf_s(buffer, sizeof(buffer), "Windows 10");
}
else if (versionInfo.dwMajorVersion >= 10 &&
versionInfo.dwMinorVersion == 0 &&
versionInfo.dwBuildNumber >= 22000)
{
sprintf_s(buffer, sizeof(buffer), "Windows 11");
}
else
{
sprintf_s(buffer, sizeof(buffer), "Unknown");
}
WriteKeyValue("OS name", buffer);

sprintf_s(buffer, sizeof(buffer), "%u.%u.%u", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber);
WriteKeyValue("OS version number", buffer);

if (versionInfo.szCSDVersion[0] != L'\0')
{
sprintf_s(buffer, sizeof(buffer), "%ls", versionInfo.szCSDVersion);
WriteKeyValue("OS service pack", buffer);
}

}
}
}

WriteKeyValue("Debugger present", (IsDebuggerPresent() ? "yes" : "no"));

// GetSystemInfo() does not return correct information
// when we're running on a x86_64 CPU while in a x86 process,
// so use GetNativeSystemInfo() instead.
SYSTEM_INFO systemInfo = { 0 };
GetNativeSystemInfo(&systemInfo);

sprintf_s(buffer, sizeof(buffer), "%u", systemInfo.dwNumberOfProcessors);
WriteKeyValue("CPU count", buffer);

if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
sprintf_s(buffer, sizeof(buffer), "x86-64");
}
else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
{
sprintf_s(buffer, sizeof(buffer), "x86 on x86-64");
}
else
{
sprintf_s(buffer, sizeof(buffer), "x86");
}
WriteKeyValue("Processor type", buffer);

sprintf_s(buffer, sizeof(buffer), "%u", systemInfo.wProcessorLevel);
WriteKeyValue("Processor level", buffer);

sprintf_s(buffer, sizeof(buffer), "%u", systemInfo.wProcessorRevision);
WriteKeyValue("Processor revision", buffer);


MEMORYSTATUSEX memoryStatus = { 0 };
memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
if (GlobalMemoryStatusEx(&memoryStatus))
{
sprintf_s(buffer, sizeof(buffer), "%d%%", memoryStatus.dwMemoryLoad);
WriteKeyValue("Memory load", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullTotalPhys / 1024 / 1024);
WriteKeyValue("Total physical memory", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullAvailPhys / 1024 / 1024);
WriteKeyValue("Available physical memory", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullTotalPageFile / 1024 / 1024);
WriteKeyValue("Total page file memory", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullAvailPageFile / 1024 / 1024);
WriteKeyValue("Available page file memory", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullTotalVirtual / 1024 / 1024);
WriteKeyValue("Total virtual memory", buffer);

sprintf_s(buffer, sizeof(buffer), "%I64d Mb", memoryStatus.ullAvailVirtual / 1024 / 1024);
WriteKeyValue("Free virtual memory", buffer);
}

return true;
}
};

member_detour(WriteApplicationInfoDetour, Debug::ReportWriter, bool(void))
{
bool detoured(void)
{
bool ret = original_function(this);

char buffer[256] = { 0 };
sprintf_s(buffer, sizeof(buffer), "%i.%i.%i", ModAPI::GetMajorVersion(), ModAPI::GetMinorVersion(), ModAPI::GetBuildVersion());
WriteKeyValue("ModAPI Version", buffer);

return ret;
}
};


long DebugReportWriterOverride::AttachDetour()
{
long result = 0;
result |= WriteSystemInfoDetour::attach(Address(ModAPI::ChooseAddress(0x0091f480, 0x0091f1c0)));
result |= WriteApplicationInfoDetour::attach(Address(ModAPI::ChooseAddress(0x0091f850, 0x0091f590)));
return result;
}
#endif
6 changes: 6 additions & 0 deletions Spore ModAPI/SourceCode/DLL/DebugReportWriterOverride.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

namespace DebugReportWriterOverride
{
long AttachDetour();
}
2 changes: 2 additions & 0 deletions Spore ModAPI/SourceCode/DLL/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Application.h"
#include "TextureOverride.h"
#include "SpaceToolIconOverride.h"
#include "DebugReportWriterOverride.h"

uintptr_t baseAddress;
ArgScript::PrintF_ptr ArgScript::PrintF;
Expand All @@ -27,6 +28,7 @@ BOOL APIENTRY DllMain(HMODULE hModule,
ModAPI::AttachDetour();
TextureOverride::AttachDetour();
SpaceToolIconOverride::AttachDetour();
DebugReportWriterOverride::AttachDetour();
CommitDetours();
break;

Expand Down
40 changes: 40 additions & 0 deletions Spore ModAPI/SourceCode/Debug/ReportWriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//#ifndef MODAPI_DLL_EXPORT
/****************************************************************************
* Copyright (C) 2026 Rosalie Wanders
*
* This file is part of Spore ModAPI.
*
* Spore ModAPI is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/

#include <Spore\Debug\ReportWriter.h>

namespace Debug
{
auto_METHOD(ReportWriter, void, GetFileNameExtension, Args(char* buffer, size_t size), Args(buffer, size));
auto_METHOD(ReportWriter, bool, OpenReport, Args(char* param_1), Args(param_1));
auto_METHOD_(ReportWriter, bool, CloseReport);
auto_METHOD(ReportWriter, bool, BeginSection, Args(const char* name), Args(name));
auto_METHOD_(ReportWriter, void, EndSection);
auto_METHOD(ReportWriter, bool, WriteText, Args(const char* text), Args(text));
auto_METHOD(ReportWriter, bool, WriteFormatted, Args(const char* text), Args(text));
auto_METHOD(ReportWriter, bool, WriteKeyValue, Args(const char* key, const char* value), Args(key, value));
auto_METHOD(ReportWriter, bool, WriteKeyValueFormatted, Args(const char* key, const char* value), Args(key, value));
auto_METHOD_(ReportWriter, void, WriteBlankLine);
auto_METHOD(ReportWriter, bool, Write, Args(const char* text, size_t size), Args(text, size));
auto_METHOD_(ReportWriter, long, GetPosition);
auto_METHOD(ReportWriter, void, SetPosition, Args(long position), Args(position));
};

//#endif
5 changes: 5 additions & 0 deletions Spore ModAPI/Spore ModAPI.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
<ClInclude Include="EASTL\version.h" />
<ClInclude Include="EASTL\weak_ptr.h" />
<ClInclude Include="SourceCode\DLL\Application.h" />
<ClInclude Include="SourceCode\DLL\DebugReportWriterOverride.h" />
<ClInclude Include="SourceCode\DLL\resource.h" />
<ClInclude Include="SourceCode\DLL\SpaceToolIconOverride.h" />
<ClInclude Include="SourceCode\DLL\stdafx.h" />
Expand Down Expand Up @@ -327,6 +328,7 @@
<ClInclude Include="Spore\App\IDGenerator.h" />
<ClInclude Include="Spore\App\JobManager.h" />
<ClInclude Include="Spore\App\Thumbnail_cImportExport.h" />
<ClInclude Include="Spore\Debug\ReportWriter.h" />
<ClInclude Include="Spore\Editors\cSPEditorVerbTrayCollection.h" />
<ClInclude Include="Spore\Editors\cSPEditorVerbIcon.h" />
<ClInclude Include="Spore\Editors\cSPEditorVerbIconTray.h" />
Expand Down Expand Up @@ -958,6 +960,8 @@
<ClInclude Include="Spore\UTFWin\WinTreeView.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="SourceCode\Debug\ReportWriter.cpp" />
<ClCompile Include="SourceCode\DLL\AddressesDebug.cpp" />
<ClCompile Include="SourceCode\DLL\AddressesMovie.cpp" />
<ClCompile Include="SourceCode\DLL\AddressesOpenSSL.cpp" />
<ClCompile Include="SourceCode\Allocator.cpp" />
Expand Down Expand Up @@ -996,6 +1000,7 @@
<ClCompile Include="SourceCode\DLL\AddressesUI.cpp" />
<ClCompile Include="SourceCode\DLL\AddressesUTFWin.cpp" />
<ClCompile Include="SourceCode\DLL\Application.cpp" />
<ClCompile Include="SourceCode\DLL\DebugReportWriterOverride.cpp" />
<ClCompile Include="SourceCode\DLL\dllmain.cpp" />
<ClCompile Include="SourceCode\DLL\DllModAPI.cpp" />
<ClCompile Include="SourceCode\DLL\SpaceToolIconOverride.cpp" />
Expand Down
15 changes: 15 additions & 0 deletions Spore ModAPI/Spore ModAPI.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,12 @@
<ClInclude Include="Spore\Movie\MovieSystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SourceCode\DLL\DebugReportWriterOverride.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Spore\Debug\ReportWriter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SourceCode\Allocator.cpp">
Expand Down Expand Up @@ -2825,6 +2831,15 @@
<ClCompile Include="SourceCode\Movie\MovieSystem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SourceCode\DLL\DebugReportWriterOverride.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SourceCode\Debug\ReportWriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SourceCode\DLL\AddressesDebug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="EASTL.natvis" />
Expand Down
44 changes: 44 additions & 0 deletions Spore ModAPI/Spore/Debug/ReportWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <Spore\Internal.h>

namespace Debug
{
class ReportWriter
{
public:
/* 00h */ // TODO ~ReportWriter();
/* 04h */ void GetFileNameExtension(char* buffer, size_t size);
/* 08h */ bool OpenReport(char* param_1); // TODO
/* 0Ch */ bool CloseReport(void);
/* 10h */ // TODO
/* 14h */ // TODO
/* 18h */ bool BeginSection(const char* name);
/* 1Ch */ void EndSection(void);
/* 20h */ bool WriteText(const char* text);
/* 24h */ bool WriteFormatted(const char* text);
/* 28h */ bool WriteKeyValue(const char* key, const char* value);
/* 2Ch */ bool WriteKeyValueFormatted(const char* key, const char* value);
/* 30h */ void WriteBlankLine(void);
/* 34h */ bool Write(const char* text, size_t size);
/* 38h */ long GetPosition(void);
/* 3Ch */ void SetPosition(long position);
};

namespace Addresses(ReportWriter)
{
DeclareAddress(GetFileNameExtension);
DeclareAddress(OpenReport);
DeclareAddress(CloseReport);
DeclareAddress(BeginSection);
DeclareAddress(EndSection);
DeclareAddress(WriteText);
DeclareAddress(WriteFormatted);
DeclareAddress(WriteKeyValue);
DeclareAddress(WriteKeyValueFormatted);
DeclareAddress(WriteBlankLine);
DeclareAddress(Write);
DeclareAddress(GetPosition);
DeclareAddress(SetPosition);
}
}
Loading