IOS/KD/VFF: Implement reading from VFF

This commit is contained in:
Sketch 2023-11-11 09:56:26 -05:00 committed by Admiral H. Curtiss
parent 0d908a83e7
commit 2c3d05423d
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
3 changed files with 158 additions and 8 deletions

View File

@ -616,8 +616,8 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index,
}
}
NWC24::ErrorCode reply = IOS::HLE::NWC24::OpenVFF(m_dl_list.GetVFFPath(entry_index), content_name,
m_ios.GetFS(), file_data);
NWC24::ErrorCode reply = IOS::HLE::NWC24::WriteToVFF(m_dl_list.GetVFFPath(entry_index),
content_name, m_ios.GetFS(), file_data);
if (reply != NWC24::WC24_OK)
{

View File

@ -237,6 +237,48 @@ static ErrorCode WriteFile(const std::string& filename, const std::vector<u8>& t
return WC24_OK;
}
static ErrorCode ReadFile(const std::string& filename, std::vector<u8>& out)
{
FIL src{};
const auto open_error_code = f_open(&src, filename.c_str(), FA_READ);
if (open_error_code != FR_OK)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to open file {} in VFF", filename);
return WC24_ERR_FILE_OPEN;
}
Common::ScopeGuard vff_close_guard{[&] { f_close(&src); }};
u32 size = static_cast<u32>(out.size());
u32 read_size{};
const auto read_error_code = f_read(&src, out.data(), size, &read_size);
if (read_error_code != FR_OK)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to read file {} in VFF: {}", filename,
static_cast<u32>(read_error_code));
return WC24_ERR_FILE_READ;
}
if (read_size != size)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to read bytes of file {} to VFF ({} != {})", filename,
read_size, size);
return WC24_ERR_FILE_READ;
}
// As prior operations did not fail, dismiss the guard and handle a potential error with f_close.
vff_close_guard.Dismiss();
const auto close_error_code = f_close(&src);
if (close_error_code != FR_OK)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to close file {} in VFF", filename);
return WC24_ERR_FILE_CLOSE;
}
return WC24_OK;
}
namespace
{
class VffFatFsCallbacks : public Common::FatFsCallbacks
@ -258,8 +300,8 @@ public:
};
} // namespace
ErrorCode OpenVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, const std::vector<u8>& data)
ErrorCode WriteToVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, const std::vector<u8>& data)
{
VffFatFsCallbacks callbacks;
ErrorCode return_value;
@ -286,6 +328,8 @@ ErrorCode OpenVFF(const std::string& path, const std::string& filename,
return;
}
Common::ScopeGuard unmount_guard{[] { f_unmount(""); }};
const FRESULT vff_mount_error_code = vff_mount(callbacks.m_vff, &fatfs);
if (vff_mount_error_code != FR_OK)
{
@ -295,8 +339,6 @@ ErrorCode OpenVFF(const std::string& path, const std::string& filename,
return;
}
Common::ScopeGuard unmount_guard{[] { f_unmount(""); }};
const auto write_error_code = WriteFile(filename, data);
if (write_error_code != WC24_OK)
{
@ -312,4 +354,108 @@ ErrorCode OpenVFF(const std::string& path, const std::string& filename,
return return_value;
}
ErrorCode ReadFromVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, std::vector<u8>& out)
{
VffFatFsCallbacks callbacks;
ErrorCode return_value;
Common::RunInFatFsContext(callbacks, [&]() {
auto temp = fs->OpenFile(PID_KD, PID_KD, path, FS::Mode::ReadWrite);
if (!temp)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to open VFF at: {}", path);
return_value = WC24_ERR_NOT_FOUND;
return;
}
callbacks.m_vff = &*temp;
FATFS fatfs{};
const FRESULT fatfs_mount_error_code = f_mount(&fatfs, "", 0);
if (fatfs_mount_error_code != FR_OK)
{
// The VFF is most likely broken.
ERROR_LOG_FMT(IOS_WC24, "Failed to mount VFF at: {}", path);
return_value = WC24_ERR_BROKEN;
return;
}
Common::ScopeGuard unmount_guard{[] { f_unmount(""); }};
const FRESULT vff_mount_error_code = vff_mount(callbacks.m_vff, &fatfs);
if (vff_mount_error_code != FR_OK)
{
// The VFF is most likely broken.
ERROR_LOG_FMT(IOS_WC24, "Failed to mount VFF at: {}", path);
return_value = WC24_ERR_BROKEN;
return;
}
const ErrorCode read_error_code = ReadFile(filename, out);
if (read_error_code != WC24_OK)
{
return_value = read_error_code;
return;
}
return_value = WC24_OK;
return;
});
return return_value;
}
ErrorCode DeleteFileFromVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs)
{
VffFatFsCallbacks callbacks;
ErrorCode return_value;
Common::RunInFatFsContext(callbacks, [&]() {
auto temp = fs->OpenFile(PID_KD, PID_KD, path, FS::Mode::ReadWrite);
if (!temp)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to open VFF at: {}", path);
return_value = WC24_ERR_NOT_FOUND;
return;
}
callbacks.m_vff = &*temp;
FATFS fatfs{};
const FRESULT fatfs_mount_error_code = f_mount(&fatfs, "", 0);
if (fatfs_mount_error_code != FR_OK)
{
// The VFF is most likely broken.
ERROR_LOG_FMT(IOS_WC24, "Failed to mount VFF at: {}", path);
return_value = WC24_ERR_BROKEN;
return;
}
Common::ScopeGuard unmount_guard{[] { f_unmount(""); }};
const FRESULT vff_mount_error_code = vff_mount(callbacks.m_vff, &fatfs);
if (vff_mount_error_code != FR_OK)
{
// The VFF is most likely broken.
ERROR_LOG_FMT(IOS_WC24, "Failed to mount VFF at: {}", path);
return_value = WC24_ERR_BROKEN;
return;
}
const FRESULT unlink_code = f_unlink(filename.c_str());
if (unlink_code != FR_OK)
{
ERROR_LOG_FMT(IOS_WC24, "Failed to delete file {} in VFF at: {} Code: {}", filename, path,
static_cast<u32>(unlink_code));
return_value = WC24_ERR_BROKEN;
return;
}
return_value = WC24_OK;
return;
});
return return_value;
}
} // namespace IOS::HLE::NWC24

View File

@ -22,8 +22,12 @@ namespace NWC24
constexpr u16 SECTOR_SIZE = 512;
constexpr u16 VF_LITTLE_ENDIAN = 0xFFFE;
constexpr u16 VF_BIG_ENDIAN = 0xFEFF;
ErrorCode OpenVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, const std::vector<u8>& data);
ErrorCode WriteToVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, const std::vector<u8>& data);
ErrorCode ReadFromVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs, std::vector<u8>& out);
ErrorCode DeleteFileFromVFF(const std::string& path, const std::string& filename,
const std::shared_ptr<FS::FileSystem>& fs);
#pragma pack(push, 1)
struct VFFHeader final