Browse Source
Merge pull request #381 from Subv/savedatacheck
Merge pull request #381 from Subv/savedatacheck
Implemented the SaveDataCheck archivepull/15/merge
17 changed files with 279 additions and 319 deletions
-
1src/common/common_paths.h
-
2src/common/file_util.cpp
-
1src/common/file_util.h
-
8src/core/CMakeLists.txt
-
3src/core/file_sys/archive_backend.h
-
47src/core/file_sys/archive_romfs.cpp
-
76src/core/file_sys/archive_romfs.h
-
41src/core/file_sys/archive_savedatacheck.cpp
-
31src/core/file_sys/archive_savedatacheck.h
-
32src/core/file_sys/directory_romfs.cpp
-
43src/core/file_sys/directory_romfs.h
-
43src/core/file_sys/file_romfs.cpp
-
73src/core/file_sys/file_romfs.h
-
88src/core/file_sys/ivfc_archive.cpp
-
66src/core/file_sys/ivfc_archive.h
-
40src/core/hle/service/fs/archive.cpp
-
3src/core/hle/service/fs/archive.h
@ -0,0 +1,41 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/file_util.h"
|
|||
|
|||
#include "core/file_sys/archive_savedatacheck.h"
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// FileSys namespace
|
|||
|
|||
namespace FileSys { |
|||
|
|||
Archive_SaveDataCheck::Archive_SaveDataCheck(const std::string& mount_loc) : mount_point(mount_loc) { |
|||
} |
|||
|
|||
ResultCode Archive_SaveDataCheck::Open(const Path& path) { |
|||
// TODO(Subv): We should not be overwriting raw_data everytime this function is called,
|
|||
// but until we use factory classes to create the archives at runtime instead of creating them beforehand
|
|||
// and allow multiple archives of the same type to be open at the same time without clobbering each other,
|
|||
// we won't be able to maintain the state of each archive, hence we overwrite it every time it's needed.
|
|||
// There are a number of problems with this, for example opening a file in this archive, then opening
|
|||
// this archive again with a different path, will corrupt the previously open file.
|
|||
auto vec = path.AsBinary(); |
|||
const u32* data = reinterpret_cast<u32*>(vec.data()); |
|||
std::string file_path = Common::StringFromFormat("%s%08x%08x.bin", mount_point.c_str(), data[1], data[0]); |
|||
FileUtil::IOFile file(file_path, "rb"); |
|||
|
|||
std::fill(raw_data.begin(), raw_data.end(), 0); |
|||
|
|||
if (!file.IsOpen()) { |
|||
return ResultCode(-1); // TODO(Subv): Find the right error code
|
|||
} |
|||
auto size = file.GetSize(); |
|||
raw_data.resize(size); |
|||
file.ReadBytes(raw_data.data(), size); |
|||
file.Close(); |
|||
return RESULT_SUCCESS; |
|||
} |
|||
|
|||
} // namespace FileSys
|
|||
@ -0,0 +1,31 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/file_sys/ivfc_archive.h" |
|||
#include "core/loader/loader.h" |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// FileSys namespace |
|||
|
|||
namespace FileSys { |
|||
|
|||
/// File system interface to the SaveDataCheck archive |
|||
class Archive_SaveDataCheck final : public IVFCArchive { |
|||
public: |
|||
Archive_SaveDataCheck(const std::string& mount_point); |
|||
|
|||
std::string GetName() const override { return "SaveDataCheck"; } |
|||
ResultCode Open(const Path& path) override; |
|||
|
|||
private: |
|||
std::string mount_point; |
|||
}; |
|||
|
|||
} // namespace FileSys |
|||
@ -1,32 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/common_types.h"
|
|||
|
|||
#include "core/file_sys/directory_romfs.h"
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// FileSys namespace
|
|||
|
|||
namespace FileSys { |
|||
|
|||
Directory_RomFS::Directory_RomFS() { |
|||
} |
|||
|
|||
Directory_RomFS::~Directory_RomFS() { |
|||
} |
|||
|
|||
bool Directory_RomFS::Open() { |
|||
return false; |
|||
} |
|||
|
|||
u32 Directory_RomFS::Read(const u32 count, Entry* entries) { |
|||
return 0; |
|||
} |
|||
|
|||
bool Directory_RomFS::Close() const { |
|||
return false; |
|||
} |
|||
|
|||
} // namespace FileSys
|
|||
@ -1,43 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/file_sys/directory_backend.h" |
|||
#include "core/loader/loader.h" |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// FileSys namespace |
|||
|
|||
namespace FileSys { |
|||
|
|||
class Directory_RomFS final : public DirectoryBackend { |
|||
public: |
|||
Directory_RomFS(); |
|||
~Directory_RomFS() override; |
|||
|
|||
/** |
|||
* Open the directory |
|||
* @return true if the directory opened correctly |
|||
*/ |
|||
bool Open() override; |
|||
|
|||
/** |
|||
* List files contained in the directory |
|||
* @param count Number of entries to return at once in entries |
|||
* @param entries Buffer to read data into |
|||
* @return Number of entries listed |
|||
*/ |
|||
u32 Read(const u32 count, Entry* entries) override; |
|||
|
|||
/** |
|||
* Close the directory |
|||
* @return true if the directory closed correctly |
|||
*/ |
|||
bool Close() const override; |
|||
}; |
|||
|
|||
} // namespace FileSys |
|||
@ -1,43 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/common_types.h"
|
|||
|
|||
#include "core/file_sys/file_romfs.h"
|
|||
#include "core/file_sys/archive_romfs.h"
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// FileSys namespace
|
|||
|
|||
namespace FileSys { |
|||
|
|||
bool File_RomFS::Open() { |
|||
return true; |
|||
} |
|||
|
|||
size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { |
|||
LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |
|||
memcpy(buffer, &archive->raw_data[(u32)offset], length); |
|||
return length; |
|||
} |
|||
|
|||
size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
|||
LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); |
|||
return 0; |
|||
} |
|||
|
|||
size_t File_RomFS::GetSize() const { |
|||
return sizeof(u8) * archive->raw_data.size(); |
|||
} |
|||
|
|||
bool File_RomFS::SetSize(const u64 size) const { |
|||
LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); |
|||
return false; |
|||
} |
|||
|
|||
bool File_RomFS::Close() const { |
|||
return false; |
|||
} |
|||
|
|||
} // namespace FileSys
|
|||
@ -1,73 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/file_sys/file_backend.h" |
|||
#include "core/loader/loader.h" |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// FileSys namespace |
|||
|
|||
namespace FileSys { |
|||
|
|||
class Archive_RomFS; |
|||
|
|||
class File_RomFS final : public FileBackend { |
|||
public: |
|||
File_RomFS(const Archive_RomFS* archive) : archive(archive) {} |
|||
|
|||
/** |
|||
* Open the file |
|||
* @return true if the file opened correctly |
|||
*/ |
|||
bool Open() override; |
|||
|
|||
/** |
|||
* Read data from the file |
|||
* @param offset Offset in bytes to start reading data from |
|||
* @param length Length in bytes of data to read from file |
|||
* @param buffer Buffer to read data into |
|||
* @return Number of bytes read |
|||
*/ |
|||
size_t Read(const u64 offset, const u32 length, u8* buffer) const override; |
|||
|
|||
/** |
|||
* Write data to the file |
|||
* @param offset Offset in bytes to start writing data to |
|||
* @param length Length in bytes of data to write to file |
|||
* @param flush The flush parameters (0 == do not flush) |
|||
* @param buffer Buffer to read data from |
|||
* @return Number of bytes written |
|||
*/ |
|||
size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; |
|||
|
|||
/** |
|||
* Get the size of the file in bytes |
|||
* @return Size of the file in bytes |
|||
*/ |
|||
size_t GetSize() const override; |
|||
|
|||
/** |
|||
* Set the size of the file in bytes |
|||
* @param size New size of the file |
|||
* @return true if successful |
|||
*/ |
|||
bool SetSize(const u64 size) const override; |
|||
|
|||
/** |
|||
* Close the file |
|||
* @return true if the file closed correctly |
|||
*/ |
|||
bool Close() const override; |
|||
|
|||
void Flush() const override { } |
|||
|
|||
private: |
|||
const Archive_RomFS* archive; |
|||
}; |
|||
|
|||
} // namespace FileSys |
|||
@ -0,0 +1,88 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <memory>
|
|||
|
|||
#include "common/common_types.h"
|
|||
#include "common/file_util.h"
|
|||
#include "common/make_unique.h"
|
|||
|
|||
#include "core/file_sys/ivfc_archive.h"
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// FileSys namespace
|
|||
|
|||
namespace FileSys { |
|||
|
|||
IVFCArchive::IVFCArchive() { |
|||
} |
|||
|
|||
std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { |
|||
return Common::make_unique<IVFCFile>(this); |
|||
} |
|||
|
|||
bool IVFCArchive::DeleteFile(const Path& path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
bool IVFCArchive::DeleteDirectory(const Path& path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
ResultCode IVFCArchive::CreateFile(const Path& path, u32 size) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str()); |
|||
// TODO: Verify error code
|
|||
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); |
|||
} |
|||
|
|||
bool IVFCArchive::CreateDirectory(const Path& path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) const { |
|||
return Common::make_unique<IVFCDirectory>(); |
|||
} |
|||
|
|||
ResultCode IVFCArchive::Format(const Path& path) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to format an IVFC archive (%s).", GetName().c_str()); |
|||
// TODO: Verify error code
|
|||
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); |
|||
} |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { |
|||
LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |
|||
memcpy(buffer, &archive->raw_data[(u32)offset], length); |
|||
return length; |
|||
} |
|||
|
|||
size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to write to IVFC file in archive %s.", archive->GetName().c_str()); |
|||
return 0; |
|||
} |
|||
|
|||
size_t IVFCFile::GetSize() const { |
|||
return sizeof(u8) * archive->raw_data.size(); |
|||
} |
|||
|
|||
bool IVFCFile::SetSize(const u64 size) const { |
|||
LOG_CRITICAL(Service_FS, "Attempted to set the size of an IVFC file in archive %s", archive->GetName().c_str()); |
|||
return false; |
|||
} |
|||
|
|||
} // namespace FileSys
|
|||
@ -0,0 +1,66 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/file_sys/archive_backend.h" |
|||
#include "core/loader/loader.h" |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// FileSys namespace |
|||
|
|||
namespace FileSys { |
|||
|
|||
/** |
|||
* Helper which implements an interface to deal with IVFC images used in some archives |
|||
* This should be subclassed by concrete archive types, which will provide the |
|||
* input data (load the raw IVFC archive) and override any required methods |
|||
*/ |
|||
class IVFCArchive : public ArchiveBackend { |
|||
public: |
|||
IVFCArchive(); |
|||
|
|||
std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
|||
bool DeleteFile(const Path& path) const override; |
|||
bool RenameFile(const Path& src_path, const Path& dest_path) const override; |
|||
bool DeleteDirectory(const Path& path) const override; |
|||
ResultCode CreateFile(const Path& path, u32 size) const override; |
|||
bool CreateDirectory(const Path& path) const override; |
|||
bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; |
|||
std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
|||
ResultCode Format(const Path& path) const override; |
|||
|
|||
protected: |
|||
friend class IVFCFile; |
|||
std::vector<u8> raw_data; |
|||
}; |
|||
|
|||
class IVFCFile : public FileBackend { |
|||
public: |
|||
IVFCFile(const IVFCArchive* archive) : archive(archive) {} |
|||
|
|||
bool Open() override { return true; } |
|||
size_t Read(const u64 offset, const u32 length, u8* buffer) const override; |
|||
size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; |
|||
size_t GetSize() const override; |
|||
bool SetSize(const u64 size) const override; |
|||
bool Close() const override { return false; } |
|||
void Flush() const override { } |
|||
|
|||
private: |
|||
const IVFCArchive* archive; |
|||
}; |
|||
|
|||
class IVFCDirectory : public DirectoryBackend { |
|||
public: |
|||
bool Open() override { return false; } |
|||
u32 Read(const u32 count, Entry* entries) override { return 0; } |
|||
bool Close() const override { return false; } |
|||
}; |
|||
|
|||
} // namespace FileSys |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue