diff --git a/3rdParty/BuildSporeModAPI.bat b/3rdParty/BuildSporeModAPI.bat index 5da9726..0f318b3 100644 --- a/3rdParty/BuildSporeModAPI.bat +++ b/3rdParty/BuildSporeModAPI.bat @@ -4,7 +4,7 @@ set SPOREMODAPI_CUR_DIR=%~dp0 msbuild "%SPOREMODAPI_CUR_DIR%\Spore-ModAPI\Spore ModAPI" ^ /p:Configuration="Release DLL" ^ - /p:SDK_BUILD_VER=306 ^ + /p:SDK_BUILD_VER=309 ^ /p:EXECUTABLE_TYPE=10 ^ /p:Platform=Win32 ^ /m diff --git a/3rdParty/Spore-ModAPI/.gitrepo b/3rdParty/Spore-ModAPI/.gitrepo index 61dab5c..42de8c2 100644 --- a/3rdParty/Spore-ModAPI/.gitrepo +++ b/3rdParty/Spore-ModAPI/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:emd4600/Spore-ModAPI.git branch = master - commit = 2acd9498cc262f2c1860381d999802da01a44ee3 - parent = b403863775c22022a64a405c7a295962b5c7eb99 + commit = 5a79029bf07cb031e68f8936b5e31ac5b2b1c52b + parent = 8f960ee9ce3d3977f112f90b603613c27f471059 method = merge cmdver = 0.4.6 diff --git a/3rdParty/Spore-ModAPI/EASTL-3.02.01/include/EASTL/fixed_map.h b/3rdParty/Spore-ModAPI/EASTL-3.02.01/include/EASTL/fixed_map.h index c97df62..6a4eb65 100644 --- a/3rdParty/Spore-ModAPI/EASTL-3.02.01/include/EASTL/fixed_map.h +++ b/3rdParty/Spore-ModAPI/EASTL-3.02.01/include/EASTL/fixed_map.h @@ -608,6 +608,24 @@ namespace eastl } + + /// Spore equivalent of fixed_map; only reading is supported, adding elements might crash. + template + class sp_fixed_map : public map + { + public: + typedef map base_type; + typedef typename base_type::node_type node_type; + typedef typename base_type::size_type size_type; + + public: + /* 1Ch */ int mPoolAllocator[4]; // actually part of mAllocator + char mPoolBuffer[(nodeCount + 1) * sizeof(node_type)]; + }; + + } // namespace eastl diff --git a/3rdParty/Spore-ModAPI/SDKtoGhidra/GhidraScript/ImportSporeSDK.java b/3rdParty/Spore-ModAPI/SDKtoGhidra/GhidraScript/ImportSporeSDK.java index 23fd559..20f8d2a 100644 --- a/3rdParty/Spore-ModAPI/SDKtoGhidra/GhidraScript/ImportSporeSDK.java +++ b/3rdParty/Spore-ModAPI/SDKtoGhidra/GhidraScript/ImportSporeSDK.java @@ -332,6 +332,9 @@ else if (returnTypeSize == 8) { } else if ("void".equals(signature.getReturnType().getName())) { returnStorage = VariableStorage.VOID_STORAGE; + } + else if ("float".equals(signature.getReturnType().getName())) { + returnStorage = new VariableStorage(currentProgram, currentProgram.getRegister("st0")); } else { returnStorage = new VariableStorage(currentProgram, currentProgram.getRegister("eax")); diff --git a/3rdParty/Spore-ModAPI/SDKtoGhidra/eastl_include.h b/3rdParty/Spore-ModAPI/SDKtoGhidra/eastl_include.h index 8883be5..267de71 100644 --- a/3rdParty/Spore-ModAPI/SDKtoGhidra/eastl_include.h +++ b/3rdParty/Spore-ModAPI/SDKtoGhidra/eastl_include.h @@ -228,7 +228,7 @@ namespace eastl float mfMaxLoadFactor; float mfGrowthFactor; int mnNextResize; - /* 1Ch */ int mPoolAllocator[5]; + /* 1Ch */ int mPoolAllocator[6]; /* 34h */ void* mBucketBuffer[bucketCount + 1]; //WARNING this does not work if T has alignment 8, because the struct will also get the alignment (but it shouldn't) int mPoolBuffer0[bucketCount + 1]; diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesMisc.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesMisc.cpp index 25a3db1..ee7800b 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesMisc.cpp +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesMisc.cpp @@ -64,6 +64,7 @@ namespace Addresses(LocalizedString) DefineAddress(ctor_0, SelectAddress(0x6B5330, 0x6B4FF0)); DefineAddress(ctor_1, SelectAddress(0x6B5A40, 0x6B5700)); + DefineAddress(op_equal, SelectAddress(0x6B59C0, 0x6B5680)); DefineAddress(dtor, SelectAddress(0x6B5510, 0x6B51D0)); } diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp index 304e548..3b79613 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp @@ -132,6 +132,8 @@ namespace Addresses(Simulator) DefineAddress(IsNotStarOrBinaryStar, SelectAddress(0xC8A840, 0xC8B6B0)); DefineAddress(LaunchDefaultToolProjectile, SelectAddress(0x1054F40, 0x1054390)); + + DefineAddress(sCreatureGameUnlockCategoriesCount, SelectAddress(0x1587278, 0x1583298)); #ifndef SDK_TO_GHIDRA DefineAddress(LightingWorld_ptr, SelectAddress(0x1682CD4, 0x167EA54)); @@ -1029,6 +1031,13 @@ namespace Simulator DefineAddress(LoadConfig, SelectAddress(0x599100, 0x599440)); DefineAddress(AddUnlockableItem, SelectAddress(0x598A70, 0x598DB0)); DefineAddress(AddUnlockableItemFromProp, SelectAddress(0x598B50, 0x598E90)); + DefineAddress(sub_597BC0, SelectAddress(0x597BC0, 0x597F00)); + DefineAddress(sub_597390, SelectAddress(0x597390, 0x5976D0)); + } + + namespace Addresses(CreatureGamePartUnlocking) + { + DefineAddress(sub_D3B460, SelectAddress(0xD3B460, 0xD3BF50)); } } diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.cpp index 0478977..f692657 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.cpp +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.cpp @@ -1,8 +1,9 @@ -#include "Spore/App/CommandLine.h" #ifdef MODAPI_DLL_EXPORT #include "stdafx.h" #include "Application.h" #include +#include +#include #include #include #include @@ -98,6 +99,7 @@ namespace ModAPI long result = 0; result |= ShaderFragments_detour::attach(GetAddress(Graphics::cMaterialManager, ReadShaderFragments)); + result |= PreInit_detour::attach(GetAddress(App::cAppSystem, PreInit)); result |= sub_7E6C60_detour::attach(Address(SelectAddress(0x7E6C60, 0x7E6850))); result |= AppInit_detour::attach(Address(SelectAddress(0xF48230, 0xF47E90))); result |= AppShutdown_detour::attach(Address(SelectAddress(0xF47950, 0xF475A0))); @@ -206,14 +208,21 @@ void CloseLogFile() { } } -int ModAPI::sub_7E6C60_detour::DETOUR(int arg_0) +int ModAPI::PreInit_detour::DETOUR(int arg_0, int arg_1) { - int result = original_function(this, arg_0); + int result = original_function(this, arg_0, arg_1); CreateLogFile(); ModAPI::Log("Spore ModAPI %d.%d.%d loaded.", ModAPI::GetMajorVersion(), ModAPI::GetMinorVersion(), ModAPI::GetBuildVersion()); ModAPI::Log("Platform: %s", ModAPI::GetGameType() == ModAPI::GameType::Disk ? "Disk" : "March2017"); + return result; +} + +int ModAPI::sub_7E6C60_detour::DETOUR(int arg_0) +{ + int result = original_function(this, arg_0); + for (ModAPI::InitFunction& func : ModAPI::initFunctions) func(); return result; diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.h b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.h index 63bc1f6..f7584c6 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.h +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/Application.h @@ -33,6 +33,7 @@ namespace ModAPI void DetachDetour(); class UnkClass {}; + member_detour(PreInit_detour, UnkClass, int(int, int)) {}; member_detour(sub_7E6C60_detour, UnkClass, int(int)) {}; member_detour(AppInit_detour, UnkClass, int(int)) {}; member_detour(AppShutdown_detour, UnkClass, int()) {}; diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/LocalizedString.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/LocalizedString.cpp index 28f12c6..a0c8751 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/LocalizedString.cpp +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/LocalizedString.cpp @@ -33,6 +33,19 @@ LocalizedString::LocalizedString(uint32_t tableID, uint32_t instanceID, const ch Args(LocalizedString*, uint32_t tableID, uint32_t instanceID, const char16_t* text), Args(this, tableID, instanceID, text)); } + +LocalizedString::LocalizedString(const LocalizedString& other) +{ + *this = other; +} + +LocalizedString& LocalizedString::operator=(const LocalizedString& other) +{ + return CALL(GetAddress(LocalizedString, op_equal), LocalizedString&, + Args(LocalizedString*, const LocalizedString&), + Args(this, other)); +} + LocalizedString::~LocalizedString() { CALL(GetAddress(LocalizedString, dtor), void, diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/SimulatorMisc.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/SimulatorMisc.cpp index 351d66a..f705cce 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/SimulatorMisc.cpp +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/SimulatorMisc.cpp @@ -137,5 +137,14 @@ namespace Simulator auto_METHOD(cCollectableItems, bool, AddUnlockableItemFromProp, Args(struct ResourceKey key, uint32_t categoryID, int row, int column, int pageIndex), Args(key, categoryID, row, column, pageIndex)); + + auto_METHOD_VOID(cCollectableItems, sub_597390, + Args(eastl::vector& dst, struct cCollectableItemID itemID, int unk), + Args(dst, itemID, unk)); + + + eastl::fixed_vector, 16>& GetCreatureGameUnlockCategoriesCount() { + return *(eastl::fixed_vector, 16>*)(GetAddress(Simulator, sCreatureGameUnlockCategoriesCount)); + } } #endif \ No newline at end of file diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/LocalizedString.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/LocalizedString.h index 9bf636c..75c6fb0 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/LocalizedString.h +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/LocalizedString.h @@ -34,7 +34,9 @@ class LocalizedString public: LocalizedString(); LocalizedString(uint32_t tableID, uint32_t instanceID, const char16_t* pText = nullptr); + LocalizedString(const LocalizedString& other); ~LocalizedString(); + LocalizedString& operator=(const LocalizedString& other); /// /// Gets the text that corresponds to this object according to the current locale. @@ -66,5 +68,6 @@ namespace Addresses(LocalizedString) DeclareAddress(ctor_0); DeclareAddress(ctor_1); + DeclareAddress(op_equal); DeclareAddress(dtor); } \ No newline at end of file diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/SubSystem/GameNounManager.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/SubSystem/GameNounManager.h index 73700fb..84fc78e 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/SubSystem/GameNounManager.h +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/SubSystem/GameNounManager.h @@ -230,3 +230,10 @@ inline T* simulator_new() { return object_cast(GameNounManager.CreateInstance(T::NOUN_ID)); } + +namespace Simulator +{ + inline cPlayer* GetPlayer() { + return GameNounManager.GetPlayer(); + } +} \ No newline at end of file diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cCollectableItems.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cCollectableItems.h index 771baed..ea898ce 100644 --- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cCollectableItems.h +++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cCollectableItems.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -24,6 +26,8 @@ namespace Simulator uint32_t instanceID; uint32_t groupID; }; + + constexpr cCollectableItemID COLLECTABLE_ITEM_NULL_ID = { -1, -1 }; } #ifndef SDK_TO_GHIDRA @@ -39,11 +43,40 @@ namespace eastl namespace Simulator { + typedef eastl::fixed_vector cCollectableItemsRowVector; + ASSERT_SIZE(cCollectableItemsRowVector, 56); + + typedef uint64_t cCollectableItemsRowID; + + typedef eastl::map::node_type NodeType; + static_assert(sizeof(NodeType) == 0x50, ""); + + inline cCollectableItemsRowID GetCollectableItemsRowID(uint32_t categoryID, int pageIndex, int row) { + return ((uint64_t)categoryID) << 32 | (pageIndex << 16) | row; + } + + struct UnkHashtableItem { + int field_0; + int field_4; + }; + ASSERT_SIZE(UnkHashtableItem, 8); + typedef eastl::sp_fixed_hash_map UnkHastable; + ASSERT_SIZE(UnkHastable, 0xDC); + + typedef eastl::sp_fixed_hash_map UnkHashMap; + ASSERT_SIZE(UnkHashMap, 0x888); + class cCollectableItems : public ISimulatorSerializable , public DefaultRefCounted { public: + static const uint32_t TYPE = 0x3A3AA3A; + + using Object::AddRef; + using Object::Release; + using Object::Cast; + void LoadConfig(uint32_t configGroupID, uint32_t configInstanceID, uint32_t itemsGroupID); void AddUnlockableItem(uint32_t instanceID, uint32_t groupID, int itemUnlockLevel, uint32_t categoryID, int row, int column, int pageIndex, float itemUnlockFindPercentage, uint32_t itemUnlockEffect); @@ -57,14 +90,19 @@ namespace Simulator /// @param pageIndex bool AddUnlockableItemFromProp(struct ResourceKey key, uint32_t categoryID, int row, int column, int pageIndex); + + void sub_597BC0(UnkHashMap& dst, int, const ResourceKey& speciesKey); + + void sub_597390(eastl::vector& dst, struct cCollectableItemID itemID, int); + public: struct UnlockableItem { /* 00h */ int itemUnlockLevel; /* 04h */ float itemUnlockFindPercentage; /* 08h */ uint32_t categoryID; - /* 0Ch */ int row; - /* 10h */ int column; + /* 0Ch */ int column; + /* 10h */ int row; /* 14h */ int pageIndex; /* 18h */ uint32_t itemUnlockEffect; }; @@ -72,7 +110,8 @@ namespace Simulator #ifndef SDK_TO_GHIDRA /* 0Ch */ bool field_C; // true - /* 10h */ char field_10[0x147C]; // some fixed_ structure of vector>? + /// Stores a progression of unlockable items (for instance, all the mouths in the same row) + /* 10h */ eastl::sp_fixed_map mUnlockableRows; /* 148Ch */ eastl::sp_fixed_hash_map mUnlockableItems; /// Some flags /* 4D00h */ eastl::sp_fixed_hash_map mItemStatusInfos; @@ -107,9 +146,28 @@ namespace Simulator DeclareAddress(LoadConfig); // 0x599100 0x599440 DeclareAddress(AddUnlockableItem); // 0x598A70 0x598DB0 DeclareAddress(AddUnlockableItemFromProp); // 0x598B50 0x598E90 + + DeclareAddress(sub_597BC0); // 0x597BC0 0x597F00 + DeclareAddress(sub_597390); // 0x597390 0x5976D0 } + class CreatureGamePartUnlocking + { + public: + struct cCollectableItemID sub_D3B460(UnkHashMap&, bool, int, int); + }; - // eastl::fixed_vector + namespace Addresses(CreatureGamePartUnlocking) + { + DeclareAddress(sub_D3B460); // 0xD3B460 0xD3BF50 + } + + + eastl::fixed_vector, 16>& GetCreatureGameUnlockCategoriesCount(); +} + +namespace Addresses(Simulator) +{ + DeclareAddress(sCreatureGameUnlockCategoriesCount); // 0x1587278 0x1583298 }