IOS/KD/VFF: Implement reading from VFF
This commit is contained in:
parent
0d908a83e7
commit
2c3d05423d
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue