* Implement RomFS cache and async reads. * Suggestions and fix compilation. * Apply suggestions
103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <shared_mutex>
|
|
#include <boost/serialization/array.hpp>
|
|
#include <boost/serialization/base_object.hpp>
|
|
#include <boost/serialization/export.hpp>
|
|
#include "common/alignment.h"
|
|
#include "common/common_types.h"
|
|
#include "common/file_util.h"
|
|
#include "common/static_lru_cache.h"
|
|
|
|
namespace FileSys {
|
|
|
|
/**
|
|
* Interface for reading RomFS data.
|
|
*/
|
|
class RomFSReader {
|
|
public:
|
|
virtual ~RomFSReader() = default;
|
|
|
|
virtual std::size_t GetSize() const = 0;
|
|
virtual std::size_t ReadFile(std::size_t offset, std::size_t length, u8* buffer) = 0;
|
|
virtual bool AllowsCachedReads() const = 0;
|
|
virtual bool CacheReady(std::size_t file_offset, std::size_t length) = 0;
|
|
|
|
private:
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int file_version) {}
|
|
friend class boost::serialization::access;
|
|
};
|
|
|
|
/**
|
|
* A RomFS reader that directly reads the RomFS file.
|
|
*/
|
|
class DirectRomFSReader : public RomFSReader {
|
|
public:
|
|
DirectRomFSReader(FileUtil::IOFile&& file, std::size_t file_offset, std::size_t data_size)
|
|
: is_encrypted(false), file(std::move(file)), file_offset(file_offset),
|
|
data_size(data_size) {}
|
|
|
|
DirectRomFSReader(FileUtil::IOFile&& file, std::size_t file_offset, std::size_t data_size,
|
|
const std::array<u8, 16>& key, const std::array<u8, 16>& ctr,
|
|
std::size_t crypto_offset)
|
|
: is_encrypted(true), file(std::move(file)), key(key), ctr(ctr), file_offset(file_offset),
|
|
crypto_offset(crypto_offset), data_size(data_size) {}
|
|
|
|
~DirectRomFSReader() override = default;
|
|
|
|
std::size_t GetSize() const override {
|
|
return data_size;
|
|
}
|
|
|
|
std::size_t ReadFile(std::size_t offset, std::size_t length, u8* buffer) override;
|
|
|
|
bool AllowsCachedReads() const override;
|
|
|
|
bool CacheReady(std::size_t file_offset, std::size_t length) override;
|
|
|
|
private:
|
|
bool is_encrypted;
|
|
FileUtil::IOFile file;
|
|
std::array<u8, 16> key;
|
|
std::array<u8, 16> ctr;
|
|
u64 file_offset;
|
|
u64 crypto_offset;
|
|
u64 data_size;
|
|
|
|
// Total cache size: 128KB
|
|
static constexpr size_t cache_line_size = (1 << 13); // About 8KB
|
|
static constexpr size_t cache_line_count = 16;
|
|
|
|
Common::StaticLRUCache<std::size_t, std::array<u8, cache_line_size>, cache_line_count> cache;
|
|
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
|
|
// std::shared_mutex cache_mutex;
|
|
|
|
DirectRomFSReader() = default;
|
|
|
|
std::size_t OffsetToPage(std::size_t offset) {
|
|
return Common::AlignDown<std::size_t>(offset, cache_line_size);
|
|
}
|
|
|
|
std::vector<std::pair<std::size_t, std::size_t>> BreakupRead(std::size_t offset,
|
|
std::size_t length);
|
|
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int) {
|
|
ar& boost::serialization::base_object<RomFSReader>(*this);
|
|
ar& is_encrypted;
|
|
ar& file;
|
|
ar& key;
|
|
ar& ctr;
|
|
ar& file_offset;
|
|
ar& crypto_offset;
|
|
ar& data_size;
|
|
}
|
|
friend class boost::serialization::access;
|
|
};
|
|
|
|
} // namespace FileSys
|
|
|
|
BOOST_CLASS_EXPORT_KEY(FileSys::DirectRomFSReader)
|