-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial WFSI/WFSSRV implementation (+ some ES additions). #4632
Conversation
f83a923
to
b1221a9
Compare
File::CreateFullPath(tmd_path); | ||
|
||
File::IOFile fp(tmd_path, "wb"); | ||
fp.WriteBytes(tmd.data(), tmd.size()); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
#include "Core/HW/DVDInterface.h" | ||
#include "Core/HW/Memmap.h" | ||
|
||
u32 num_calls = 0; |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
} | ||
|
||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_OPEN(%s, %d) -> %d", path.c_str(), mode, fd); | ||
Memory::Write_U16(fd, buffer_out + 0x14); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
void ARCUnpacker::Extract(const WriteCallback& callback) | ||
{ | ||
u32 fourcc = Common::swap32(m_whole_file.data()); | ||
if (fourcc != 0x55AA382D) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
u64 title_id; | ||
DVDInterface::GetVolume().GetTitleID(&title_id); | ||
|
||
Memory::Write_U32(title_id >> 32, command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
|
||
IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::Open(u32 command_address, u32 mode) | ||
{ | ||
INFO_LOG(WII_IPC_HLE, "/dev/usb_wfssrv: Open"); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
return GetDefaultReply(); | ||
} | ||
|
||
IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::Close(u32 command_address, bool force) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
case IOCTL_WFS_DEVICE_INFO: | ||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_DEVICE_INFO"); | ||
Memory::Write_U64(16ull << 30, buffer_out); // 16GB storage. | ||
Memory::Write_U8(4, buffer_out + 8); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
IPCCommandResult CWII_IPC_HLE_Device_wfsi::Open(u32 command_address, u32 mode) | ||
{ | ||
INFO_LOG(WII_IPC_HLE, "/dev/wfsi: Open"); | ||
Memory::Write_U32(GetDeviceID(), command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
{ | ||
SIOCtlVBuffer command_buffer(command_address); | ||
ERROR_LOG(WII_IPC_HLE, "IOCtlV on /dev/usb/wfssrv -- unsupported"); | ||
Memory::Write_U32(FS_SUCCESS, command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
|
||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_wfsi.h" | ||
|
||
#include <mbedtls/aes.h> |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
|
||
IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtlV(u32 command_address) | ||
{ | ||
SIOCtlVBuffer command_buffer(command_address); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
#include "Core/IPC_HLE/WII_IPC_HLE.h" | ||
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h" | ||
|
||
class ARCUnpacker |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
#pragma once | ||
|
||
#include <string> | ||
|
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
Considering that it only affects Dragon Quest X, I'm of course okay with merging it in an alpha state to make cleanup easier. I'll of course be testing this later today. Congratulations! |
@JMC47 This may affect other things too. For instance, I noticed that trying to copy a channel from an SD card to the NAND using the system menu now gives the message "The data may not have been copied." instead of the system menu claiming that it succeeded. (It never actually succeeds, it just claims to succeed.) |
That's still fine, it's all fringe things. |
Yeah, the added ES function isn't exactly something that's used by emulated code that's working correctly in master. |
9e7513f
to
89e97fd
Compare
u64 title_id; | ||
DVDInterface::GetVolume().GetTitleID(&title_id); | ||
|
||
Memory::Write_U32(title_id >> 32, command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
|
||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_wfsi.h" | ||
|
||
#include <mbedtls/aes.h> |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtlV(u32 command_address) | ||
{ | ||
ERROR_LOG(WII_IPC_HLE, "IOCtlV on /dev/wfsi -- unsupported"); | ||
Memory::Write_U32(IPC_SUCCESS, command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
WFSI calls into ES to perform this operation, so expose a way for us to do the same thing.
Refactor the existing DiscIO::AddTicket to not require the caller to pass the requested title ID. We do not have the title ID in the ES case, and it needs to be extracted from the ticket. Since this is always a safe operation to do (title ID is always in the ticket), the implementation is made default.
b81d424
to
c9c48de
Compare
Just note: this Pull Request has been verified to add enough functionality for the Mario Kart Wii and Wii Fit Channels to be successfully installed. Wii Fit Channel runs as expected, I haven't been able to run the MKWii Channel yet due to unrelated issues. |
c260742
to
c3057f8
Compare
{ | ||
SIOCtlVBuffer command_buffer(command_address); | ||
ERROR_LOG(WII_IPC_HLE, "IOCtlV on /dev/usb/wfssrv -- unsupported"); | ||
Memory::Write_U32(FS_EINVAL, command_address + 4); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
std::vector<u8> ticket(Buffer.InBuffer[0].m_Size); | ||
Memory::CopyFromEmu(ticket.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size); | ||
DiscIO::AddTicket(ticket); | ||
break; |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
} | ||
else | ||
std::vector<u8> ticket = SignedTicketToTicket(signed_ticket); | ||
if (ticket.size() == 0) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
std::vector<u8> FindTicket(u64 title_id) | ||
{ | ||
std::vector<u8> signed_ticket = FindSignedTicket(title_id); | ||
if (!signed_ticket.size()) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
These two functions load either a signed ticket or a raw ticket from the emulated NAND. The ticket signature skip is refactored out of the ticket writing in order to be usable by the raw ticket reading function.
This function has more uses than just in DiscIO (e.g. WFS).
This library implements basic parsing support for some of the IOS ES formats we need to extract data from. Currently only implements TMD functions, but some ticket handling functions from DiscIO should likely be moved here in the future.
There are several things wrong with this implementation. The first being that since we still don't have a proper ticket/tmd handling library, we hardcode offsets once again to fetch TMD fields. The second being that we don't stream data to the disk and we buffer everything in memory. The third being that we don't properly fetch the content index for decryption, which is prone to breaking. But hey, it works well enough to install the DQX channel!
Defaults to $USERDIR/WFS. Used to store the contents normally stored on WFS mass storage devices.
std::string m_device_name; | ||
|
||
mbedtls_aes_context m_aes_ctx; | ||
u8 m_aes_key[0x10]; |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
The current implementations do many things wrong but work well enough to run the Dragon Quest X installer until the very end. The game itself crashes when being launched from its System Menu channel unfortunately so it is hard to verify whether the install properly worked or not. There are plenty of "TODO(wfs)" sprinkled around this codebase with things that are knowingly done wrong. The most important one right now is that content extraction is done by buffering everything into memory instead of properly streaming the data to disk (and processing asynchronously), which causes freezes. It is likely to not cause any practical issues since only the installer and the updater should use this anyway.
This implementation is enough to fully run the Dragon Quest X installer (with tons of stubbing and broken install paths). It also adds support for title installation from ES (which is required for DQX since the game installs itself as a channel, nothing is loaded from disc itself when playing).
There are too many things wrong with the WFS implementation to list here, it should be considered a pre-alpha thing and I'm just thinking of merging it to make merge conflicts less annoying :)