summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlunarsoap5 <justindakotacarter@gmail.com>2021-12-12 16:20:53 -0600
committerlunarsoap5 <justindakotacarter@gmail.com>2021-12-12 16:20:53 -0600
commit2ac2919b68a8b54d1520c1ae40cdccd165e99883 (patch)
treef536fa8dc41e4f703335498787ca7bdd028eb9cc
parentae665953215b412a55c6ed8dc317a674b93d1b25 (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.lst11
-rw-r--r--GameCube/assets/jp.lst8
-rw-r--r--GameCube/assets/us.lst8
m---------GameCube/externals/libtp_rel0
-rw-r--r--GameCube/include/events.h9
-rw-r--r--GameCube/include/rando/data.h17
-rw-r--r--GameCube/include/rando/randomizer.h1
-rw-r--r--GameCube/include/rando/seed.h5
-rw-r--r--GameCube/source/events.cpp8
-rw-r--r--GameCube/source/main.cpp55
-rw-r--r--GameCube/source/rando/randomizer.cpp14
-rw-r--r--GameCube/source/rando/seed.cpp70
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