Drop the direct WAD launch hack

This removes the hack that enables directly booting from WADs
without installing them first for the following reasons:

1. It makes the NAND content handling much more complicated than what
   it should be and makes future changes like permissions or booting
   NAND titles without a WAD more annoying to implement.

   Because of this hack, we needed an extra level of abstraction
   (NANDContent*) which has to read tons of things from the NAND, even
   most of the time it's useless. This in turn forces us to have
   caching, which is known to break titles and requires manual cache
   invalidations. Annoying and error prone.

2. It prevents the WAD boot code from being easily accurate. With this
   change, we can simply reuse the existing launch code, and ask IOS
   to launch the title from the NAND.

3. The hack did not work that well since it did not cover a lot of ES
   commands. And it works even less since the ES accuracy fixes.
   This results in Dolphin returning inconsistent results: a
   lot of the ES "DI" commands will just fail because the active title
   is not installed on the NAND. uid.sys is not changed, etc.

   And I'm not even talking about FS stuff -- where this would still
   totally fail, unless we add even more unnecessary hacks.

   This is not just theoretical -- the system menu and the Wii Shop are
   known to behave strangely because the hack damages the NAND
   structure, and we've already had several users report issues.

This commit makes it so WADs are always installed prior to launching.
A future commit will remove any code that was there only for the hack.
This commit is contained in:
Léo Lam 2017-10-01 15:14:53 +02:00
parent 60ba382799
commit 9000a042e4
5 changed files with 28 additions and 55 deletions

View File

@ -100,8 +100,8 @@ std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(const std::stri
if (extension == ".dff") if (extension == ".dff")
return std::make_unique<BootParameters>(DFF{path}); return std::make_unique<BootParameters>(DFF{path});
if (DiscIO::NANDContentManager::Access().GetNANDLoader(path).IsValid()) if (extension == ".wad")
return std::make_unique<BootParameters>(NAND{path}); return std::make_unique<BootParameters>(DiscIO::WiiWAD{path});
PanicAlertT("Could not recognize file %s", path.c_str()); PanicAlertT("Could not recognize file %s", path.c_str());
return {}; return {};
@ -357,11 +357,10 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
return true; return true;
} }
bool operator()(const BootParameters::NAND& nand) const bool operator()(const DiscIO::WiiWAD& wad) const
{ {
NOTICE_LOG(BOOT, "Booting from NAND: %s", nand.content_path.c_str());
SetDefaultDisc(); SetDefaultDisc();
return Boot_WiiWAD(nand.content_path); return Boot_WiiWAD(wad);
} }
bool operator()(const BootParameters::NANDTitle& nand_title) const bool operator()(const BootParameters::NANDTitle& nand_title) const

View File

@ -13,8 +13,10 @@
#include <vector> #include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h" #include "DiscIO/Enums.h"
#include "DiscIO/Volume.h" #include "DiscIO/Volume.h"
#include "DiscIO/WiiWad.h"
namespace File namespace File
{ {
@ -45,11 +47,6 @@ struct BootParameters
std::unique_ptr<BootExecutableReader> reader; std::unique_ptr<BootExecutableReader> reader;
}; };
struct NAND
{
std::string content_path;
};
struct NANDTitle struct NANDTitle
{ {
u64 id; u64 id;
@ -72,7 +69,7 @@ struct BootParameters
static std::unique_ptr<BootParameters> GenerateFromFile(const std::string& path); static std::unique_ptr<BootParameters> GenerateFromFile(const std::string& path);
using Parameters = std::variant<Disc, Executable, NAND, NANDTitle, IPL, DFF>; using Parameters = std::variant<Disc, Executable, DiscIO::WiiWAD, NANDTitle, IPL, DFF>;
BootParameters(Parameters&& parameters_); BootParameters(Parameters&& parameters_);
Parameters parameters; Parameters parameters;
@ -103,7 +100,7 @@ private:
static void UpdateDebugger_MapLoaded(); static void UpdateDebugger_MapLoaded();
static bool Boot_WiiWAD(const std::string& filename); static bool Boot_WiiWAD(const DiscIO::WiiWAD& wad);
static bool BootNANDTitle(u64 title_id); static bool BootNANDTitle(u64 title_id);
static void SetupMSR(); static void SetupMSR();

View File

@ -18,8 +18,10 @@
#include "Core/IOS/ES/Formats.h" #include "Core/IOS/ES/Formats.h"
#include "Core/IOS/FS/FileIO.h" #include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IOS.h" #include "Core/IOS/IOS.h"
#include "Core/WiiUtils.h"
#include "DiscIO/NANDContentLoader.h" #include "DiscIO/NANDContentLoader.h"
#include "DiscIO/WiiWad.h"
bool CBoot::BootNANDTitle(const u64 title_id) bool CBoot::BootNANDTitle(const u64 title_id)
{ {
@ -35,46 +37,12 @@ bool CBoot::BootNANDTitle(const u64 title_id)
return ios->GetES()->LaunchTitle(title_id); return ios->GetES()->LaunchTitle(title_id);
} }
bool CBoot::Boot_WiiWAD(const std::string& _pFilename) bool CBoot::Boot_WiiWAD(const DiscIO::WiiWAD& wad)
{ {
UpdateStateFlags([](StateFlags* state) { if (!WiiUtils::InstallWAD(*IOS::HLE::GetIOS(), wad))
state->type = 0x03; // TYPE_RETURN
});
const DiscIO::NANDContentLoader& ContentLoader =
DiscIO::NANDContentManager::Access().GetNANDLoader(_pFilename);
if (!ContentLoader.IsValid())
return false;
u64 titleID = ContentLoader.GetTMD().GetTitleId();
if (!IOS::ES::IsChannel(titleID))
{ {
PanicAlertT("This WAD is not bootable."); PanicAlertT("Cannot boot this WAD because it could not be installed to the NAND.");
return false; return false;
} }
return BootNANDTitle(wad.GetTMD().GetTitleId());
// create data directory
File::CreateFullPath(Common::GetTitleDataPath(titleID, Common::FROM_SESSION_ROOT));
if (titleID == Titles::SYSTEM_MENU)
IOS::HLE::CreateVirtualFATFilesystem();
// setup Wii memory
if (!SetupWiiMemory(ContentLoader.GetTMD().GetIOSId()))
return false;
IOS::HLE::Device::ES::LoadWAD(_pFilename);
// TODO: kill these manual calls and just use ES_Launch here, as soon as the direct WAD
// launch hack is dropped.
auto* ios = IOS::HLE::GetIOS();
IOS::ES::UIDSys uid_map{Common::FROM_SESSION_ROOT};
ios->SetUidForPPC(uid_map.GetOrInsertUIDForTitle(titleID));
ios->SetGidForPPC(ContentLoader.GetTMD().GetGroupId());
if (!ios->BootstrapPPC(ContentLoader))
return false;
return true;
} }

View File

@ -45,6 +45,7 @@
#include "DiscIO/Enums.h" #include "DiscIO/Enums.h"
#include "DiscIO/NANDContentLoader.h" #include "DiscIO/NANDContentLoader.h"
#include "DiscIO/Volume.h" #include "DiscIO/Volume.h"
#include "DiscIO/WiiWad.h"
SConfig* SConfig::m_Instance; SConfig* SConfig::m_Instance;
@ -888,14 +889,20 @@ struct SetGameMetadata
return true; return true;
} }
bool operator()(const BootParameters::NAND& nand) const bool operator()(const DiscIO::WiiWAD& wad) const
{ {
const auto& loader = DiscIO::NANDContentManager::Access().GetNANDLoader(nand.content_path); if (!wad.IsValid() || !wad.GetTMD().IsValid())
if (!loader.IsValid()) {
PanicAlertT("This WAD is not valid.");
return false; return false;
}
if (!IOS::ES::IsChannel(wad.GetTMD().GetTitleId()))
{
PanicAlertT("This WAD is not bootable.");
return false;
}
const IOS::ES::TMDReader& tmd = loader.GetTMD(); const IOS::ES::TMDReader& tmd = wad.GetTMD();
config->SetRunningGameMetadata(tmd); config->SetRunningGameMetadata(tmd);
config->bWii = true; config->bWii = true;
*region = tmd.GetRegion(); *region = tmd.GetRegion();

View File

@ -20,6 +20,8 @@ class WiiWAD
public: public:
explicit WiiWAD(const std::string& name); explicit WiiWAD(const std::string& name);
explicit WiiWAD(std::unique_ptr<BlobReader> blob_reader); explicit WiiWAD(std::unique_ptr<BlobReader> blob_reader);
WiiWAD(WiiWAD&&) = default;
WiiWAD& operator=(WiiWAD&&) = default;
~WiiWAD(); ~WiiWAD();
bool IsValid() const { return m_valid; } bool IsValid() const { return m_valid; }