diff options
author | lunarsoap5 <justindakotacarter@gmail.com> | 2021-12-12 16:20:53 -0600 |
---|---|---|
committer | lunarsoap5 <justindakotacarter@gmail.com> | 2021-12-12 16:20:53 -0600 |
commit | 2ac2919b68a8b54d1520c1ae40cdccd165e99883 (patch) | |
tree | f536fa8dc41e4f703335498787ca7bdd028eb9cc | |
parent | ae665953215b412a55c6ed8dc317a674b93d1b25 (diff) |
Added function definitions and usage cases for replacing checks stored in ARC files.feature-arcReplacementFunctions
Also ran the clang-format to clean code up.
-rw-r--r-- | GameCube/assets/eu.lst | 11 | ||||
-rw-r--r-- | GameCube/assets/jp.lst | 8 | ||||
-rw-r--r-- | GameCube/assets/us.lst | 8 | ||||
m--------- | GameCube/externals/libtp_rel | 0 | ||||
-rw-r--r-- | GameCube/include/events.h | 9 | ||||
-rw-r--r-- | GameCube/include/rando/data.h | 17 | ||||
-rw-r--r-- | GameCube/include/rando/randomizer.h | 1 | ||||
-rw-r--r-- | GameCube/include/rando/seed.h | 5 | ||||
-rw-r--r-- | GameCube/source/events.cpp | 8 | ||||
-rw-r--r-- | GameCube/source/main.cpp | 55 | ||||
-rw-r--r-- | GameCube/source/rando/randomizer.cpp | 14 | ||||
-rw-r--r-- | GameCube/source/rando/seed.cpp | 70 |
12 files changed, 188 insertions, 18 deletions
diff --git a/GameCube/assets/eu.lst b/GameCube/assets/eu.lst index 2bcb12eb..81783b22 100644 --- a/GameCube/assets/eu.lst +++ b/GameCube/assets/eu.lst @@ -189,4 +189,13 @@ 802BA968:sceneChange // Z2SeqMgr -802B5CB0:startBattleBgm
\ No newline at end of file +802B5CB0:startBattleBgm + +//JKRDvdRipper.o +802daa54:loadToMainRAM2 + +//dvdfs.o +80349394:DVDConvertPathToEntrynum + +//d_s_logo.o +802591F8:getPalLanguage2
\ No newline at end of file diff --git a/GameCube/assets/jp.lst b/GameCube/assets/jp.lst index d97fb82c..2ce80394 100644 --- a/GameCube/assets/jp.lst +++ b/GameCube/assets/jp.lst @@ -189,4 +189,10 @@ 802BBFA8:sceneChange // Z2SeqMgr.o -802B72F0:startBattleBgm
\ No newline at end of file +802B72F0:startBattleBgm + +//JKRDvdRipper.o +802dc0f0:loadToMainRAM2 + +//dvdfs.o +8034a9c4:DVDConvertPathToEntrynum
\ No newline at end of file diff --git a/GameCube/assets/us.lst b/GameCube/assets/us.lst index 0067bb50..bc39b3a5 100644 --- a/GameCube/assets/us.lst +++ b/GameCube/assets/us.lst @@ -189,4 +189,10 @@ 802B9B68:sceneChange // Z2SeqMgr.o -802B4EB0:startBattleBgm
\ No newline at end of file +802B4EB0:startBattleBgm + +//JKRDvdRipper.o +802d9c54:loadToMainRAM2 + +//dvdfs.o +80348528:DVDConvertPathToEntrynum diff --git a/GameCube/externals/libtp_rel b/GameCube/externals/libtp_rel -Subproject 639d694442c572f5c7f085d75bcb3bb995c6187 +Subproject cf08e7b0a367dc6eaa2f52b7b5012ae2bdd3c19 diff --git a/GameCube/include/events.h b/GameCube/include/events.h index 828b2888..0a7ae10d 100644 --- a/GameCube/include/events.h +++ b/GameCube/include/events.h @@ -55,5 +55,14 @@ namespace mod::events * their respective Area
*/
int32_t onPoe( rando::Randomizer* randomizer, uint8_t flag );
+
+ /**
+ * @brief Runs when the game loads the ARC files from the game disc.
+ *
+ * @param randomizer Pointer to mod::randomizer.
+ * @param filePtr Pointer to the file being read.
+ * @param fileIndex Index of the file being read.
+ */
+ void onARC( rando::Randomizer* randomizer, void* filePtr, int32_t fileIndex );
} // namespace mod::events
#endif
\ No newline at end of file diff --git a/GameCube/include/rando/data.h b/GameCube/include/rando/data.h index f8929001..2c5df1ea 100644 --- a/GameCube/include/rando/data.h +++ b/GameCube/include/rando/data.h @@ -36,6 +36,7 @@ namespace mod::rando entryInfo dzxCheckInfo; entryInfo relCheckInfo; entryInfo poeCheckInfo; + entryInfo arcCheckInfo; } __attribute__( ( __packed__ ) ); // Seed with index @@ -57,6 +58,13 @@ namespace mod::rando uint8_t flag; } __attribute__( ( __packed__ ) ); + enum class FileDirectory : uint8_t + { + Stage = 0x0, + Message = 0x1, + Object = 0x2 + }; + struct dzxCheck { uint16_t hash; @@ -88,5 +96,14 @@ namespace mod::rando uint8_t flag; // Flag used for identification uint16_t item; // New item id } __attribute__( ( __packed__ ) ); + + struct ArcCheck + { + int32_t offset; // The offset of the byte where the item is stored from the start of the file. + int32_t arcFileIndex; // The index of the file that contains the check. + uint8_t item; // The item being placed. + FileDirectory directory; // The type of directory where the check is stored. + const char fileName[18]; // The name of the file where the check is stored + } __attribute__( ( __packed__ ) ); } // namespace mod::rando #endif
\ No newline at end of file diff --git a/GameCube/include/rando/randomizer.h b/GameCube/include/rando/randomizer.h index 3129d12a..ffed9d13 100644 --- a/GameCube/include/rando/randomizer.h +++ b/GameCube/include/rando/randomizer.h @@ -30,6 +30,7 @@ namespace mod::rando void overrideREL( libtp::tp::dynamic_link::DynamicModuleControl* dmc ); void overrideDZX( libtp::tp::dzx::ChunkTypeInfo* chunkTypeInfo ); + void overrideARC( void* filePtr, int32_t fileIndex ); int32_t getPoeItem( uint8_t flag ); diff --git a/GameCube/include/rando/seed.h b/GameCube/include/rando/seed.h index ff47257c..b6972708 100644 --- a/GameCube/include/rando/seed.h +++ b/GameCube/include/rando/seed.h @@ -36,6 +36,9 @@ namespace mod::rando POECheck* m_POEChecks = nullptr; // POE Checks for current stage uint32_t m_numLoadedPOEChecks = 0; // Number of currently loaded POEChecks + ArcCheck* m_ArcChecks = nullptr; // Checks for the currently loaded .arc file + uint32_t m_numLoadedARCChecks = 0; // Number of currently loaded ARCChecks in the seed + // Member functions public: /** @@ -82,6 +85,8 @@ namespace mod::rando void LoadDZX( uint8_t stageIDX ); void LoadREL( uint8_t stageIDX ); void LoadPOE( uint8_t stageIDX ); + + void setArcFileIndexes(); }; } // namespace mod::rando #endif
\ No newline at end of file diff --git a/GameCube/source/events.cpp b/GameCube/source/events.cpp index 388ec879..a17676f3 100644 --- a/GameCube/source/events.cpp +++ b/GameCube/source/events.cpp @@ -87,4 +87,12 @@ namespace mod::events return static_cast<int32_t>( libtp::data::items::Poe_Soul );
}
}
+
+ void onARC( rando::Randomizer* randomizer, void* filePtr, int32_t fileIndex )
+ {
+ if ( randomizer )
+ {
+ randomizer->overrideARC( filePtr, fileIndex );
+ }
+ }
} // namespace mod::events
\ No newline at end of file diff --git a/GameCube/source/main.cpp b/GameCube/source/main.cpp index 03494429..21aa3f37 100644 --- a/GameCube/source/main.cpp +++ b/GameCube/source/main.cpp @@ -12,6 +12,7 @@ #include "rando/randomizer.h" #include "rando/seedlist.h" #include "tools.h" +#include "tp/JKRDvdRipper.h" #include "tp/d_com_inf_game.h" #include "tp/d_stage.h" #include "tp/dzx.h" @@ -53,6 +54,16 @@ namespace mod int32_t unk3, void* unk4 ) = nullptr; + void* ( *return_loadToMainRAM2 )( int32_t fileIndex, + uint8_t* unk2, + uint32_t jkrExpandSwitch, + uint32_t unk4, + void* jkrHeap, + uint32_t eAllocDirection, + uint32_t unk7, + int32_t* unk8, + uint32_t* unk9 ) = nullptr; + void main() { // Run game patches @@ -82,42 +93,56 @@ namespace mod return_fapGm_Execute = patch::hookFunction( libtp::tp::f_ap_game::fapGm_Execute, mod::handle_fapGm_Execute ); // DMC - return_do_Link = patch::hookFunction( libtp::tp::dynamic_link::do_link, - []( libtp::tp::dynamic_link::DynamicModuleControl* dmc ) - { - // Call the original function immediately, as the REL file needs to be linked - // before applying patches - const bool result = return_do_Link( dmc ); + return_do_Link = + patch::hookFunction( libtp::tp::dynamic_link::do_link, []( libtp::tp::dynamic_link::DynamicModuleControl* dmc ) { + // Call the original function immediately, as the REL file needs to be linked + // before applying patches + const bool result = return_do_Link( dmc ); - events::onRELLink( randomizer, dmc ); + events::onRELLink( randomizer, dmc ); - return result; - } ); + return result; + } ); // DZX return_actorInit = patch::hookFunction( actorInit, - []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) - { + []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) { events::onDZX( mod::randomizer, chunkTypeInfo ); return return_actorInit( mStatus_roomControl, chunkTypeInfo, unk3, unk4 ); } ); return_actorInit_always = patch::hookFunction( actorInit_always, - []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) - { + []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) { events::onDZX( mod::randomizer, chunkTypeInfo ); return return_actorInit_always( mStatus_roomControl, chunkTypeInfo, unk3, unk4 ); } ); return_actorCommonLayerInit = patch::hookFunction( actorCommonLayerInit, - []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) - { + []( void* mStatus_roomControl, ChunkTypeInfo* chunkTypeInfo, int32_t unk3, void* unk4 ) { events::onDZX( mod::randomizer, chunkTypeInfo ); return return_actorCommonLayerInit( mStatus_roomControl, chunkTypeInfo, unk3, unk4 ); } ); + + return_loadToMainRAM2 = patch::hookFunction( + tp::JKRDvdRipper::loadToMainRAM2, + []( int32_t fileIndex, + uint8_t* unk2, + uint32_t jkrExpandSwitch, + uint32_t unk4, + void* jkrHeap, + uint32_t eAllocDirection, + uint32_t unk7, + int32_t* unk8, + uint32_t* unk9 ) { + // Call the original function immediately, as we need the pointer it returns + void* filePtr = + return_loadToMainRAM2( fileIndex, unk2, jkrExpandSwitch, unk4, jkrHeap, eAllocDirection, unk7, unk8, unk9 ); + events::onARC( mod::randomizer, filePtr, fileIndex ); + return filePtr; + } ); } void setScreen( bool state ) diff --git a/GameCube/source/rando/randomizer.cpp b/GameCube/source/rando/randomizer.cpp index d6472c1f..cbe478d0 100644 --- a/GameCube/source/rando/randomizer.cpp +++ b/GameCube/source/rando/randomizer.cpp @@ -152,4 +152,18 @@ namespace mod::rando // Default return libtp::data::items::Poe_Soul; } + + void Randomizer::overrideARC( void* filePtr, int32_t fileIndex ) + { + uint32_t numReplacements = m_Seed->m_numLoadedARCChecks; + // Loop through all ArcChecks and replace the item at an offset given the fileIndex. + for ( uint32_t i = 0; i < numReplacements; i++ ) + { + if ( fileIndex == m_Seed->m_ArcChecks[i].arcFileIndex ) + { + *reinterpret_cast<uint8_t*>( ( reinterpret_cast<uint32_t>( filePtr ) + m_Seed->m_ArcChecks[i].offset ) ) = + m_Seed->m_ArcChecks[i].item; + } + } + } } // namespace mod::rando
\ No newline at end of file diff --git a/GameCube/source/rando/seed.cpp b/GameCube/source/rando/seed.cpp index 7c2dc936..9a86fd25 100644 --- a/GameCube/source/rando/seed.cpp +++ b/GameCube/source/rando/seed.cpp @@ -14,12 +14,14 @@ #include "data/stages.h" #include "gc_wii/card.h" +#include "gc_wii/dvdfs.h" #include "main.h" #include "rando/data.h" #include "tools.h" #include "tp/d_com_inf_game.h" #include "tp/d_save.h" #include "user_patch/user_patch.h" +#include "tp/d_s_logo.h" namespace mod::rando { @@ -78,6 +80,9 @@ namespace mod::rando mod::console << "Setting Region Flags... \n"; this->applyRegionFlags(); + + mod::console << "Setting Arc File Indexes... \n"; + this->setArcFileIndexes(); return true; } else @@ -356,4 +361,69 @@ namespace mod::rando } } + void Seed::setArcFileIndexes() + { + using namespace libtp; + // Local vars + uint32_t numReplacements = m_Header->arcCheckInfo.numEntries; + char filePath[32]; + int32_t len = 0; + + // Loop through all ArcChecks and set their corresponding file index + for ( uint32_t i = 0; i < numReplacements; i++ ) + { + switch ( m_ArcChecks[i].directory ) + { + case rando::FileDirectory::Stage: + { + len = snprintf( filePath, sizeof( filePath ), "res/Stage/%s", m_ArcChecks[i].fileName ); + break; + } + case rando::FileDirectory::Message: + { +#ifdef TP_US + len = snprintf( filePath, sizeof( filePath ), "res/Msgus/%s", m_ArcChecks[i].fileName ); +#elif defined TP_JP + len = snprintf( filePath, sizeof( filePath ), "res/Msgjp/%s", m_ArcChecks[i].fileName ); +#elif defined TP_EU + // PAL uses a different file for each language + tp::d_s_logo::Languages lang = tp::d_s_logo::getPalLanguage2( nullptr ); + if ( ( lang < tp::d_s_logo::Languages::uk ) || ( lang > tp::d_s_logo::Languages::it ) ) + { + // The language is invalid/unsupported, so the game defaults to English + lang = libtp::tp::d_s_logo::Languages::uk; + } + + static const char* langStrings[] = { "uk", "de", "fr", "sp", "it" }; + len = snprintf( filePath, + sizeof( filePath ), + "res/Msg%s/%s", + langStrings[static_cast<int32_t>( lang )], + m_ArcChecks[i].fileName ); +#endif + break; + } + case rando::FileDirectory::Object: + { + len = snprintf( filePath, sizeof( filePath ), "res/Object/%s", m_ArcChecks[i].fileName ); + break; + } + default: + { + len = snprintf( filePath, sizeof( filePath ), "%s", m_ArcChecks[i].fileName ); + } + } + + if ( ( len >= 0 ) && ( len < static_cast<int32_t>( sizeof( filePath ) ) ) ) + { + m_ArcChecks[i].arcFileIndex = libtp::gc_wii::dvdfs::DVDConvertPathToEntrynum( filePath ); + } + else // Failsafe in case we did not get a valid result. + { + m_ArcChecks[i].arcFileIndex = -1; + } + } + m_numLoadedARCChecks = m_Header->arcCheckInfo.numEntries; + } + } // namespace mod::rando
\ No newline at end of file |