mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-15 16:16:14 +00:00
Added support for exporting Trilogy and Wii de Asobu builds
This commit is contained in:
@@ -17,12 +17,14 @@
|
||||
#define USE_ASSET_NAME_MAP 1
|
||||
#define EXPORT_COOKED 1
|
||||
|
||||
CGameExporter::CGameExporter(EGame Game, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion)
|
||||
CGameExporter::CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion)
|
||||
: mGame(Game)
|
||||
, mRegion(Region)
|
||||
, mGameName(rkGameName)
|
||||
, mGameID(rkGameID)
|
||||
, mBuildVersion(BuildVersion)
|
||||
, mDiscType(DiscType)
|
||||
, mFrontEnd(FrontEnd)
|
||||
, mpProgress(nullptr)
|
||||
{
|
||||
ASSERT(mGame != eUnknownGame);
|
||||
@@ -96,6 +98,70 @@ void CGameExporter::LoadResource(const CAssetID& rkID, std::vector<u8>& rBuffer)
|
||||
if (pInst) LoadResource(*pInst, rBuffer);
|
||||
}
|
||||
|
||||
bool CGameExporter::ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot)
|
||||
{
|
||||
if (IsInRoot && mDiscType != eDT_Normal)
|
||||
{
|
||||
// Directories - exclude the filesystem for other games
|
||||
if (pkNode->getKind() == nod::Node::Kind::Directory)
|
||||
{
|
||||
// Frontend is always included; this is for compatibility with Dolphin
|
||||
if (pkNode->getName() == "fe")
|
||||
return true;
|
||||
|
||||
else if (mFrontEnd)
|
||||
return false;
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP1JPN") ||
|
||||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP1") );
|
||||
|
||||
case eEchoes:
|
||||
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP2JPN") ||
|
||||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP2") );
|
||||
|
||||
case eCorruption:
|
||||
return (mDiscType == eDT_Trilogy && pkNode->getName() == "MP3");
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Files - exclude the DOLs for other games
|
||||
else
|
||||
{
|
||||
// Again - always include frontend. Always include opening.bnr as well.
|
||||
if (pkNode->getName() == "rs5fe_p.dol" || pkNode->getName() == "opening.bnr")
|
||||
return true;
|
||||
|
||||
else if (mFrontEnd)
|
||||
return false;
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp1jpn_p.dol") ||
|
||||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp1_p.dol") );
|
||||
|
||||
case eEchoes:
|
||||
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp2jpn_p.dol") ||
|
||||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp2_p.dol") );
|
||||
|
||||
case eCorruption:
|
||||
return (mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp3_p.dol");
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ************ PROTECTED ************
|
||||
bool CGameExporter::ExtractDiscData()
|
||||
{
|
||||
@@ -122,7 +188,7 @@ bool CGameExporter::ExtractDiscData()
|
||||
TString FilesDir = AbsDiscDir + "files/";
|
||||
FileUtil::MakeDirectory(FilesDir);
|
||||
|
||||
bool Success = ExtractDiscNodeRecursive(&pDataPartition->getFSTRoot(), FilesDir, Context);
|
||||
bool Success = ExtractDiscNodeRecursive(&pDataPartition->getFSTRoot(), FilesDir, true, Context);
|
||||
if (!Success) return false;
|
||||
|
||||
if (!mpProgress->ShouldCancel())
|
||||
@@ -150,18 +216,25 @@ bool CGameExporter::ExtractDiscData()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, const nod::ExtractionContext& rkContext)
|
||||
bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, bool RootNode, const nod::ExtractionContext& rkContext)
|
||||
{
|
||||
for (nod::Node::DirectoryIterator Iter = pkNode->begin(); Iter != pkNode->end(); ++Iter)
|
||||
{
|
||||
if (!ShouldExportDiscNode(&*Iter, RootNode))
|
||||
continue;
|
||||
|
||||
if (Iter->getKind() == nod::Node::Kind::File)
|
||||
{
|
||||
TString FilePath = rkDir + Iter->getName();
|
||||
bool Success = Iter->extractToDirectory(*rkDir.ToUTF16(), rkContext);
|
||||
if (!Success) return false;
|
||||
|
||||
if (FilePath.GetFileExtension() == "pak")
|
||||
mPaks.push_back(FilePath);
|
||||
if (FilePath.GetFileExtension().CaseInsensitiveCompare("pak"))
|
||||
{
|
||||
// For multi-game Wii discs, don't track packages for frontend unless we're exporting frontend
|
||||
if (mDiscType == eDT_Normal || mFrontEnd || pkNode->getName() != "fe")
|
||||
mPaks.push_back(FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
@@ -170,7 +243,7 @@ bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TStr
|
||||
bool Success = FileUtil::MakeDirectory(Subdir);
|
||||
if (!Success) return false;
|
||||
|
||||
Success = ExtractDiscNodeRecursive(&*Iter, Subdir, rkContext);
|
||||
Success = ExtractDiscNodeRecursive(&*Iter, Subdir, false, rkContext);
|
||||
if (!Success) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
#include <map>
|
||||
#include <nod/nod.hpp>
|
||||
|
||||
enum EDiscType
|
||||
{
|
||||
eDT_Normal,
|
||||
eDT_WiiDeAsobu,
|
||||
eDT_Trilogy
|
||||
};
|
||||
|
||||
class CGameExporter
|
||||
{
|
||||
// Project Data
|
||||
@@ -33,6 +40,8 @@ class CGameExporter
|
||||
|
||||
// Files
|
||||
nod::DiscBase *mpDisc;
|
||||
EDiscType mDiscType;
|
||||
bool mFrontEnd;
|
||||
|
||||
// Resources
|
||||
TStringList mPaks;
|
||||
@@ -65,15 +74,16 @@ class CGameExporter
|
||||
};
|
||||
|
||||
public:
|
||||
CGameExporter(EGame Game, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion);
|
||||
CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion);
|
||||
bool Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAssetNameMap *pNameMap, CGameInfo *pGameInfo, IProgressNotifier *pProgress);
|
||||
void LoadResource(const CAssetID& rkID, std::vector<u8>& rBuffer);
|
||||
bool ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot);
|
||||
|
||||
inline TString ProjectPath() const { return mProjectPath; }
|
||||
|
||||
protected:
|
||||
bool ExtractDiscData();
|
||||
bool ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, const nod::ExtractionContext& rkContext);
|
||||
bool ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, bool RootNode, const nod::ExtractionContext& rkContext);
|
||||
void LoadPaks();
|
||||
void LoadResource(const SResourceInstance& rkResource, std::vector<u8>& rBuffer);
|
||||
void ExportCookedResources();
|
||||
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
inline float BuildVersion() const { return mBuildVersion; }
|
||||
inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; }
|
||||
inline bool IsTrilogy() const { return mGame <= eCorruption && mBuildVersion >= 3.593f; }
|
||||
inline bool IsWiiDeAsobu() const { return mGame < eCorruption && mBuildVersion >= 3.f && mBuildVersion < 3.593f; }
|
||||
};
|
||||
|
||||
#endif // CGAMEPROJECT_H
|
||||
|
||||
@@ -170,9 +170,14 @@ bool CVirtualDirectory::AddChild(const TString &rkPath, CResourceEntry *pEntry)
|
||||
{
|
||||
// Create new subdirectory
|
||||
pSubdir = new CVirtualDirectory(this, DirName, mpStore);
|
||||
FileUtil::MakeDirectory(mpStore->ResourcesDir() + pSubdir->FullPath());
|
||||
mSubdirectories.push_back(pSubdir);
|
||||
|
||||
if (!pSubdir->CreateFilesystemDirectory())
|
||||
{
|
||||
delete pSubdir;
|
||||
return false;
|
||||
}
|
||||
|
||||
mSubdirectories.push_back(pSubdir);
|
||||
std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool {
|
||||
return (pLeft->Name().ToUpper() < pRight->Name().ToUpper());
|
||||
});
|
||||
@@ -184,6 +189,13 @@ bool CVirtualDirectory::AddChild(const TString &rkPath, CResourceEntry *pEntry)
|
||||
for (auto Iter = Components.begin(); Iter != Components.end(); Iter++)
|
||||
{
|
||||
pSubdir = new CVirtualDirectory(pSubdir, *Iter, mpStore);
|
||||
|
||||
if (!pSubdir->CreateFilesystemDirectory())
|
||||
{
|
||||
delete pSubdir;
|
||||
return false;
|
||||
}
|
||||
|
||||
pSubdir->Parent()->mSubdirectories.push_back(pSubdir);
|
||||
}
|
||||
|
||||
@@ -307,6 +319,23 @@ void CVirtualDirectory::DeleteEmptySubdirectories()
|
||||
}
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::CreateFilesystemDirectory()
|
||||
{
|
||||
TString AbsPath = AbsolutePath();
|
||||
|
||||
if (!FileUtil::Exists(AbsPath))
|
||||
{
|
||||
bool CreateSuccess = FileUtil::MakeDirectory(AbsPath);
|
||||
|
||||
if (!CreateSuccess)
|
||||
Log::Error("FAILED to create filesystem directory: " + AbsPath);
|
||||
|
||||
return CreateSuccess;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVirtualDirectory::SetParent(CVirtualDirectory *pParent)
|
||||
{
|
||||
ASSERT(!pParent->IsDescendantOf(this));
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool Rename(const TString& rkNewName);
|
||||
bool Delete();
|
||||
void DeleteEmptySubdirectories();
|
||||
bool CreateFilesystemDirectory();
|
||||
bool SetParent(CVirtualDirectory *pParent);
|
||||
|
||||
static bool IsValidDirectoryName(const TString& rkName);
|
||||
|
||||
Reference in New Issue
Block a user