Merge pull request #5391 from leoetlino/delete-title-content
IOS/ES: Implement DeleteTitleContent properly
This commit is contained in:
commit
ea89e8566e
|
@ -24,7 +24,6 @@
|
||||||
#include "Core/IOS/IOS.h"
|
#include "Core/IOS/IOS.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/State.h"
|
#include "Core/State.h"
|
||||||
#include "Core/WiiRoot.h"
|
|
||||||
|
|
||||||
namespace HW
|
namespace HW
|
||||||
{
|
{
|
||||||
|
@ -50,7 +49,6 @@ void Init()
|
||||||
|
|
||||||
if (SConfig::GetInstance().bWii)
|
if (SConfig::GetInstance().bWii)
|
||||||
{
|
{
|
||||||
Core::InitializeWiiRoot(Core::WantsDeterminism());
|
|
||||||
IOS::Init();
|
IOS::Init();
|
||||||
IOS::HLE::Init(); // Depends on Memory
|
IOS::HLE::Init(); // Depends on Memory
|
||||||
}
|
}
|
||||||
|
@ -61,8 +59,6 @@ void Shutdown()
|
||||||
// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
|
// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
|
||||||
IOS::HLE::Shutdown(); // Depends on Memory
|
IOS::HLE::Shutdown(); // Depends on Memory
|
||||||
IOS::Shutdown();
|
IOS::Shutdown();
|
||||||
if (SConfig::GetInstance().bWii)
|
|
||||||
Core::ShutdownWiiRoot();
|
|
||||||
|
|
||||||
SystemTimers::Shutdown();
|
SystemTimers::Shutdown();
|
||||||
CPU::Shutdown();
|
CPU::Shutdown();
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
ReturnCode Close(u32 fd) override;
|
ReturnCode Close(u32 fd) override;
|
||||||
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
|
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
|
||||||
|
|
||||||
|
ReturnCode DeleteTitleContent(u64 title_id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -376,20 +376,29 @@ IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request)
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnCode ES::DeleteTitleContent(u64 title_id) const
|
||||||
|
{
|
||||||
|
if (!CanDeleteTitle(title_id))
|
||||||
|
return ES_EINVAL;
|
||||||
|
|
||||||
|
const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT);
|
||||||
|
if (!File::IsDirectory(content_dir))
|
||||||
|
return FS_ENOENT;
|
||||||
|
|
||||||
|
for (const auto& file : File::ScanDirectoryTree(content_dir, false).children)
|
||||||
|
{
|
||||||
|
if (file.virtualName.size() == 12 && file.virtualName.compare(8, 4, ".app") == 0)
|
||||||
|
File::Delete(file.physicalName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
|
IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
if (!request.HasNumberOfValidVectors(1, 0))
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
|
||||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
|
||||||
INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
|
|
||||||
(u32)TitleID);
|
|
||||||
|
|
||||||
// Presumably return -1017 when title not installed TODO verify
|
|
||||||
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
|
|
||||||
return GetDefaultReply(ES_EINVAL);
|
|
||||||
|
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request)
|
IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request)
|
||||||
|
|
|
@ -51,13 +51,14 @@
|
||||||
#include "Core/IOS/WFS/WFSI.h"
|
#include "Core/IOS/WFS/WFSI.h"
|
||||||
#include "Core/IOS/WFS/WFSSRV.h"
|
#include "Core/IOS/WFS/WFSSRV.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/WiiRoot.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
|
||||||
namespace IOS
|
namespace IOS
|
||||||
{
|
{
|
||||||
namespace HLE
|
namespace HLE
|
||||||
{
|
{
|
||||||
static std::unique_ptr<Kernel> s_ios;
|
static std::unique_ptr<EmulationKernel> s_ios;
|
||||||
|
|
||||||
constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
|
constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
|
||||||
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
|
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
|
||||||
|
@ -172,29 +173,17 @@ constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
|
||||||
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
||||||
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
|
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
|
||||||
|
|
||||||
Kernel::Kernel(u64 title_id) : m_title_id(title_id)
|
Kernel::Kernel()
|
||||||
{
|
{
|
||||||
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);
|
// Until the Wii root and NAND path stuff is entirely managed by IOS and made non-static,
|
||||||
|
// using more than one IOS instance at a time is not supported.
|
||||||
if (!SetupMemory(title_id, MemorySetupType::IOSReload))
|
_assert_(GetIOS() == nullptr);
|
||||||
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");
|
Core::InitializeWiiRoot(false);
|
||||||
|
AddCoreDevices();
|
||||||
if (title_id == MIOS_TITLE_ID)
|
|
||||||
{
|
|
||||||
MIOS::Load();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IOS re-inits IPC and sends a dummy ack during its boot process.
|
|
||||||
EnqueueIPCAcknowledgement(0);
|
|
||||||
|
|
||||||
AddStaticDevices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::~Kernel()
|
Kernel::~Kernel()
|
||||||
{
|
{
|
||||||
CoreTiming::RemoveAllEvents(s_event_enqueue);
|
|
||||||
|
|
||||||
// Close all devices that were opened
|
// Close all devices that were opened
|
||||||
for (auto& device : m_fdmap)
|
for (auto& device : m_fdmap)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +196,36 @@ Kernel::~Kernel()
|
||||||
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
||||||
m_device_map.clear();
|
m_device_map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::ShutdownWiiRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulationKernel::EmulationKernel(u64 title_id)
|
||||||
|
{
|
||||||
|
m_title_id = title_id;
|
||||||
|
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);
|
||||||
|
|
||||||
|
if (!SetupMemory(title_id, MemorySetupType::IOSReload))
|
||||||
|
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");
|
||||||
|
|
||||||
|
Core::InitializeWiiRoot(Core::WantsDeterminism());
|
||||||
|
|
||||||
|
if (title_id == MIOS_TITLE_ID)
|
||||||
|
{
|
||||||
|
MIOS::Load();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IOS re-inits IPC and sends a dummy ack during its boot process.
|
||||||
|
EnqueueIPCAcknowledgement(0);
|
||||||
|
|
||||||
|
AddCoreDevices();
|
||||||
|
AddStaticDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulationKernel::~EmulationKernel()
|
||||||
|
{
|
||||||
|
CoreTiming::RemoveAllEvents(s_event_enqueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The title ID is a u64 where the first 32 bits are used for the title type.
|
// The title ID is a u64 where the first 32 bits are used for the title type.
|
||||||
|
@ -217,6 +236,16 @@ u32 Kernel::GetVersion() const
|
||||||
return static_cast<u32>(m_title_id);
|
return static_cast<u32>(m_title_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device::FS> Kernel::GetFS()
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<Device::FS>(m_device_map.at("/dev/fs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device::ES> Kernel::GetES()
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<Device::ES>(m_device_map.at("/dev/es"));
|
||||||
|
}
|
||||||
|
|
||||||
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
||||||
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
|
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
|
||||||
void Kernel::SetUidForPPC(u32 uid)
|
void Kernel::SetUidForPPC(u32 uid)
|
||||||
|
@ -289,7 +318,7 @@ bool Kernel::BootIOS(const u64 ios_title_id)
|
||||||
|
|
||||||
// Shut down the active IOS first before switching to the new one.
|
// Shut down the active IOS first before switching to the new one.
|
||||||
s_ios.reset();
|
s_ios.reset();
|
||||||
s_ios = std::make_unique<Kernel>(ios_title_id);
|
s_ios = std::make_unique<EmulationKernel>(ios_title_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,10 +328,16 @@ void Kernel::AddDevice(std::unique_ptr<Device::Device> device)
|
||||||
m_device_map[device->GetDeviceName()] = std::move(device);
|
m_device_map[device->GetDeviceName()] = std::move(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kernel::AddCoreDevices()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
||||||
|
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
|
||||||
|
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
|
||||||
|
}
|
||||||
|
|
||||||
void Kernel::AddStaticDevices()
|
void Kernel::AddStaticDevices()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
||||||
_assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized");
|
|
||||||
|
|
||||||
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
|
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
|
||||||
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
|
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
|
||||||
|
@ -311,8 +346,6 @@ void Kernel::AddStaticDevices()
|
||||||
|
|
||||||
AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
|
AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
|
||||||
AddDevice(std::make_unique<Device::STMEventHook>(*this, "/dev/stm/eventhook"));
|
AddDevice(std::make_unique<Device::STMEventHook>(*this, "/dev/stm/eventhook"));
|
||||||
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
|
|
||||||
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
|
|
||||||
AddDevice(std::make_unique<Device::DI>(*this, "/dev/di"));
|
AddDevice(std::make_unique<Device::DI>(*this, "/dev/di"));
|
||||||
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
|
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
|
||||||
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
|
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
|
||||||
|
@ -351,6 +384,11 @@ std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& devic
|
||||||
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device::Device> EmulationKernel::GetDeviceByName(const std::string& device_name)
|
||||||
|
{
|
||||||
|
return Kernel::GetDeviceByName(device_name);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the FD for the newly opened device (on success) or an error code.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
s32 Kernel::OpenDevice(OpenRequest& request)
|
s32 Kernel::OpenDevice(OpenRequest& request)
|
||||||
{
|
{
|
||||||
|
@ -639,7 +677,7 @@ void Init()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start with IOS80 to simulate part of the Wii boot process.
|
// Start with IOS80 to simulate part of the Wii boot process.
|
||||||
s_ios = std::make_unique<Kernel>(IOS80_TITLE_ID);
|
s_ios = std::make_unique<EmulationKernel>(IOS80_TITLE_ID);
|
||||||
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
|
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
|
||||||
// (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up.
|
// (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up.
|
||||||
// This means that the constants in the 0x3100 region are always set up by the time
|
// This means that the constants in the 0x3100 region are always set up by the time
|
||||||
|
@ -653,7 +691,7 @@ void Shutdown()
|
||||||
s_ios.reset();
|
s_ios.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel* GetIOS()
|
EmulationKernel* GetIOS()
|
||||||
{
|
{
|
||||||
return s_ios.get();
|
return s_ios.get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ namespace HLE
|
||||||
namespace Device
|
namespace Device
|
||||||
{
|
{
|
||||||
class Device;
|
class Device;
|
||||||
|
class ES;
|
||||||
|
class FS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Request;
|
struct Request;
|
||||||
|
@ -84,8 +86,8 @@ enum ProcessId : u32
|
||||||
class Kernel
|
class Kernel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Kernel(u64 ios_title_id);
|
Kernel();
|
||||||
~Kernel();
|
virtual ~Kernel();
|
||||||
|
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
void HandleIPCEvent(u64 userdata);
|
void HandleIPCEvent(u64 userdata);
|
||||||
|
@ -93,7 +95,11 @@ public:
|
||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
void UpdateWantDeterminism(bool new_want_determinism);
|
void UpdateWantDeterminism(bool new_want_determinism);
|
||||||
|
|
||||||
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
|
// These are *always* part of the IOS kernel and always available.
|
||||||
|
// They are also the only available resource managers even before loading any module.
|
||||||
|
std::shared_ptr<Device::FS> GetFS();
|
||||||
|
std::shared_ptr<Device::ES> GetES();
|
||||||
|
|
||||||
void SDIO_EventNotify();
|
void SDIO_EventNotify();
|
||||||
|
|
||||||
void EnqueueIPCRequest(u32 address);
|
void EnqueueIPCRequest(u32 address);
|
||||||
|
@ -111,13 +117,15 @@ public:
|
||||||
|
|
||||||
IOSC& GetIOSC();
|
IOSC& GetIOSC();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void ExecuteIPCCommand(u32 address);
|
void ExecuteIPCCommand(u32 address);
|
||||||
IPCCommandResult HandleIPCCommand(const Request& request);
|
IPCCommandResult HandleIPCCommand(const Request& request);
|
||||||
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
|
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
|
||||||
|
|
||||||
void AddDevice(std::unique_ptr<Device::Device> device);
|
void AddDevice(std::unique_ptr<Device::Device> device);
|
||||||
|
void AddCoreDevices();
|
||||||
void AddStaticDevices();
|
void AddStaticDevices();
|
||||||
|
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
|
||||||
s32 GetFreeDeviceID();
|
s32 GetFreeDeviceID();
|
||||||
s32 OpenDevice(OpenRequest& request);
|
s32 OpenDevice(OpenRequest& request);
|
||||||
|
|
||||||
|
@ -140,10 +148,22 @@ private:
|
||||||
IOSC m_iosc;
|
IOSC m_iosc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// HLE for an IOS tied to emulation: base kernel which may have additional modules loaded.
|
||||||
|
class EmulationKernel : public Kernel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit EmulationKernel(u64 ios_title_id);
|
||||||
|
~EmulationKernel();
|
||||||
|
|
||||||
|
// Get a resource manager by name.
|
||||||
|
// This only works for devices which are part of the device map.
|
||||||
|
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
|
||||||
|
};
|
||||||
|
|
||||||
// Used for controlling and accessing an IOS instance that is tied to emulation.
|
// Used for controlling and accessing an IOS instance that is tied to emulation.
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
Kernel* GetIOS();
|
EmulationKernel* GetIOS();
|
||||||
|
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
|
|
@ -45,7 +45,7 @@ OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, D
|
||||||
|
|
||||||
void OH0Device::DoState(PointerWrap& p)
|
void OH0Device::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
|
m_oh0 = std::static_pointer_cast<OH0>(GetIOS()->GetDeviceByName("/dev/usb/oh0"));
|
||||||
p.Do(m_name);
|
p.Do(m_name);
|
||||||
p.Do(m_vid);
|
p.Do(m_vid);
|
||||||
p.Do(m_pid);
|
p.Do(m_pid);
|
||||||
|
@ -61,7 +61,7 @@ ReturnCode OH0Device::Open(const OpenRequest& request)
|
||||||
if (m_vid == 0 && m_pid == 0)
|
if (m_vid == 0 && m_pid == 0)
|
||||||
return IPC_ENOENT;
|
return IPC_ENOENT;
|
||||||
|
|
||||||
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
|
m_oh0 = std::static_pointer_cast<OH0>(GetIOS()->GetDeviceByName("/dev/usb/oh0"));
|
||||||
|
|
||||||
ReturnCode return_code;
|
ReturnCode return_code;
|
||||||
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
|
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
|
||||||
|
|
|
@ -109,7 +109,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
||||||
m_tmd.SetBytes(std::move(tmd_bytes));
|
m_tmd.SetBytes(std::move(tmd_bytes));
|
||||||
|
|
||||||
ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId());
|
IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId());
|
||||||
if (!ticket.IsValid())
|
if (!ticket.IsValid())
|
||||||
{
|
{
|
||||||
return_error_code = -11028;
|
return_error_code = -11028;
|
||||||
|
@ -134,7 +134,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
||||||
|
|
||||||
// Initializes the IV from the index of the content in the TMD contents.
|
// Initializes the IV from the index of the content in the TMD contents.
|
||||||
u32 content_id = Memory::Read_U32(request.buffer_in + 8);
|
u32 content_id = Memory::Read_U32(request.buffer_in + 8);
|
||||||
ES::Content content_info;
|
IOS::ES::Content content_info;
|
||||||
if (!m_tmd.FindContentById(content_id, &content_info))
|
if (!m_tmd.FindContentById(content_id, &content_info))
|
||||||
{
|
{
|
||||||
WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);
|
WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);
|
||||||
|
|
|
@ -241,40 +241,11 @@ const CNANDContentLoader& CNANDContentManager::GetNANDLoader(u64 title_id,
|
||||||
return GetNANDLoader(path);
|
return GetNANDLoader(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNANDContentManager::RemoveTitle(u64 title_id, Common::FromWhichRoot from)
|
|
||||||
{
|
|
||||||
auto& loader = GetNANDLoader(title_id, from);
|
|
||||||
if (!loader.IsValid())
|
|
||||||
return false;
|
|
||||||
loader.RemoveTitle();
|
|
||||||
return GetNANDLoader(title_id, from).IsValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNANDContentManager::ClearCache()
|
void CNANDContentManager::ClearCache()
|
||||||
{
|
{
|
||||||
m_map.clear();
|
m_map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNANDContentLoader::RemoveTitle() const
|
|
||||||
{
|
|
||||||
const u64 title_id = m_tmd.GetTitleId();
|
|
||||||
INFO_LOG(DISCIO, "RemoveTitle %016" PRIx64, title_id);
|
|
||||||
if (IsValid())
|
|
||||||
{
|
|
||||||
// remove TMD?
|
|
||||||
for (const auto& content : m_Content)
|
|
||||||
{
|
|
||||||
if (!content.m_metadata.IsShared())
|
|
||||||
{
|
|
||||||
std::string path = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_metadata.id);
|
|
||||||
INFO_LOG(DISCIO, "Delete %s", path.c_str());
|
|
||||||
File::Delete(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CNANDContentManager::Access().ClearCache(); // deletes 'this'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
||||||
{
|
{
|
||||||
if (filename.find(".wad") == std::string::npos)
|
if (filename.find(".wad") == std::string::npos)
|
||||||
|
|
|
@ -79,7 +79,6 @@ public:
|
||||||
~CNANDContentLoader();
|
~CNANDContentLoader();
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
void RemoveTitle() const;
|
|
||||||
const SNANDContent* GetContentByID(u32 id) const;
|
const SNANDContent* GetContentByID(u32 id) const;
|
||||||
const SNANDContent* GetContentByIndex(int index) const;
|
const SNANDContent* GetContentByIndex(int index) const;
|
||||||
const IOS::ES::TMDReader& GetTMD() const { return m_tmd; }
|
const IOS::ES::TMDReader& GetTMD() const { return m_tmd; }
|
||||||
|
@ -111,7 +110,6 @@ public:
|
||||||
|
|
||||||
const CNANDContentLoader& GetNANDLoader(const std::string& content_path);
|
const CNANDContentLoader& GetNANDLoader(const std::string& content_path);
|
||||||
const CNANDContentLoader& GetNANDLoader(u64 title_id, Common::FromWhichRoot from);
|
const CNANDContentLoader& GetNANDLoader(u64 title_id, Common::FromWhichRoot from);
|
||||||
bool RemoveTitle(u64 title_id, Common::FromWhichRoot from);
|
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "Common/NandPaths.h"
|
#include "Common/NandPaths.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/HW/WiiSaveCrypted.h"
|
#include "Core/HW/WiiSaveCrypted.h"
|
||||||
|
#include "Core/IOS/ES/ES.h"
|
||||||
|
#include "Core/IOS/IOS.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
@ -324,9 +326,8 @@ bool GameFile::Install()
|
||||||
bool GameFile::Uninstall()
|
bool GameFile::Uninstall()
|
||||||
{
|
{
|
||||||
_assert_(m_platform == DiscIO::Platform::WII_WAD);
|
_assert_(m_platform == DiscIO::Platform::WII_WAD);
|
||||||
|
IOS::HLE::Kernel ios;
|
||||||
return DiscIO::CNANDContentManager::Access().RemoveTitle(m_title_id,
|
return ios.GetES()->DeleteTitleContent(m_title_id) == IOS::HLE::IPC_SUCCESS;
|
||||||
Common::FROM_CONFIGURED_ROOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameFile::ExportWiiSave()
|
bool GameFile::ExportWiiSave()
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Core/HW/Wiimote.h"
|
#include "Core/HW/Wiimote.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "Core/HotkeyManager.h"
|
#include "Core/HotkeyManager.h"
|
||||||
|
#include "Core/IOS/ES/ES.h"
|
||||||
#include "Core/IOS/IOS.h"
|
#include "Core/IOS/IOS.h"
|
||||||
#include "Core/IOS/STM/STM.h"
|
#include "Core/IOS/STM/STM.h"
|
||||||
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
||||||
|
@ -1228,7 +1229,8 @@ void CFrame::OnUninstallWAD(wxCommandEvent&)
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 title_id = file->GetTitleID();
|
u64 title_id = file->GetTitleID();
|
||||||
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(title_id, Common::FROM_CONFIGURED_ROOT))
|
IOS::HLE::Kernel ios;
|
||||||
|
if (ios.GetES()->DeleteTitleContent(title_id) < 0)
|
||||||
{
|
{
|
||||||
PanicAlertT("Failed to remove this title from the NAND.");
|
PanicAlertT("Failed to remove this title from the NAND.");
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue