This commit is contained in:
James Rowe 2015-02-25 21:34:57 -07:00
commit 4fb08427ab
5 changed files with 75 additions and 50 deletions

View file

@ -6,9 +6,9 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/make_unique.h"
#include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/archive_systemsavedata.h"
#include "core/file_sys/disk_archive.h"
#include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/archive.h"
#include "core/settings.h" #include "core/settings.h"
@ -17,9 +17,11 @@
namespace FileSys { namespace FileSys {
static std::string GetSystemSaveDataPath(const std::string& mount_point, u64 save_id) { static std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path) {
u32 save_high = static_cast<u32>((save_id >> 32) & 0xFFFFFFFF); std::vector<u8> vec_data = path.AsBinary();
u32 save_low = static_cast<u32>(save_id & 0xFFFFFFFF); const u32* data = reinterpret_cast<const u32*>(vec_data.data());
u32 save_low = data[1];
u32 save_high = data[0];
return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high); return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high);
} }
@ -27,18 +29,25 @@ static std::string GetSystemSaveDataContainerPath(const std::string& mount_point
return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID.c_str()); return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID.c_str());
} }
Archive_SystemSaveData::Archive_SystemSaveData(const std::string& mount_point, u64 save_id) ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
: DiskArchive(GetSystemSaveDataPath(GetSystemSaveDataContainerPath(mount_point), save_id)) { : base_path(GetSystemSaveDataContainerPath(nand_path)) {
LOG_INFO(Service_FS, "Directory %s set as SystemSaveData.", this->mount_point.c_str());
} }
bool Archive_SystemSaveData::Initialize() { ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) {
if (!FileUtil::CreateFullPath(mount_point)) { std::string fullpath = GetSystemSaveDataPath(base_path, path);
LOG_ERROR(Service_FS, "Unable to create SystemSaveData path."); if (!FileUtil::Exists(fullpath)) {
return false; // TODO(Subv): Check error code, this one is probably wrong
return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
ErrorSummary::InvalidState, ErrorLevel::Status);
} }
auto archive = Common::make_unique<DiskArchive>(fullpath);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
return true; ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path) {
std::string fullpath = GetSystemSaveDataPath(base_path, path);
FileUtil::CreateFullPath(fullpath);
return RESULT_SUCCESS;
} }
} // namespace FileSys } // namespace FileSys

View file

@ -15,17 +15,17 @@
namespace FileSys { namespace FileSys {
/// File system interface to the SystemSaveData archive /// File system interface to the SystemSaveData archive
class Archive_SystemSaveData final : public DiskArchive { class ArchiveFactory_SystemSaveData final : public ArchiveFactory {
public: public:
Archive_SystemSaveData(const std::string& mount_point, u64 save_id); ArchiveFactory_SystemSaveData(const std::string& mount_point);
/** ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
* Initialize the archive. ResultCode Format(const Path& path) override;
* @return true if it initialized successfully
*/
bool Initialize();
std::string GetName() const override { return "SystemSaveData"; } std::string GetName() const override { return "SystemSaveData"; }
private:
std::string base_path;
}; };
} // namespace FileSys } // namespace FileSys

View file

@ -4,8 +4,8 @@
#include <algorithm> #include <algorithm>
#include "common/make_unique.h" #include "common/make_unique.h"
#include "core/file_sys/archive_systemsavedata.h"
#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/fs/archive.h"
namespace Service { namespace Service {
namespace CFG { namespace CFG {
@ -36,7 +36,8 @@ const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
static std::unique_ptr<FileSys::Archive_SystemSaveData> cfg_system_save_data; static Service::FS::ArchiveHandle cfg_system_save_data_archive;
static const std::vector<u8> cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 };
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) {
// Read the header // Read the header
@ -97,19 +98,22 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data
ResultCode DeleteConfigNANDSaveFile() { ResultCode DeleteConfigNANDSaveFile() {
FileSys::Path path("config"); FileSys::Path path("config");
if (cfg_system_save_data->DeleteFile(path)) return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path);
return RESULT_SUCCESS;
return ResultCode(-1); // TODO(Subv): Find the right error code
} }
ResultCode UpdateConfigNANDSavegame() { ResultCode UpdateConfigNANDSavegame() {
FileSys::Mode mode = {}; FileSys::Mode mode = {};
mode.write_flag = 1; mode.write_flag = 1;
mode.create_flag = 1; mode.create_flag = 1;
FileSys::Path path("config"); FileSys::Path path("config");
auto file = cfg_system_save_data->OpenFile(path, mode);
ASSERT_MSG(file != nullptr, "could not open file"); auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode);
file->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data()); ASSERT_MSG(config_result.Succeeded(), "could not open file");
auto config = config_result.MoveFrom();
config->backend->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data());
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -158,27 +162,33 @@ ResultCode FormatConfig() {
} }
void CFGInit() { void CFGInit() {
// TODO(Subv): In the future we should use the FS service to query this archive, // Open the SystemSaveData archive 0x00010017
// currently it is not possible because you can only have one open archive of the same type at any time FileSys::Path archive_path(cfg_system_savedata_id);
std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
cfg_system_save_data = Common::make_unique<FileSys::Archive_SystemSaveData>(
nand_directory, CFG_SAVE_ID); // If the archive didn't exist, create the files inside
if (!cfg_system_save_data->Initialize()) { if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
LOG_CRITICAL(Service_CFG, "Could not initialize SystemSaveData archive for the CFG:U service"); // Format the archive to create the directories
return; Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
// Open it again to get a valid archive now that the folder exists
archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
} }
// TODO(Subv): All this code should be moved to cfg:i, ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!");
// it's only here because we do not currently emulate the lower level code that uses that service
// Try to open the file in read-only mode to check its existence
FileSys::Mode mode = {};
mode.read_flag = 1;
FileSys::Path path("config");
auto file = cfg_system_save_data->OpenFile(path, mode);
// Load the config if it already exists cfg_system_save_data_archive = *archive_result;
if (file != nullptr) {
file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); FileSys::Path config_path("config");
FileSys::Mode open_mode = {};
open_mode.read_flag = 1;
auto config_result = Service::FS::OpenFileFromArchive(*archive_result, config_path, open_mode);
// Read the file if it already exists
if (config_result.Succeeded()) {
auto config = config_result.MoveFrom();
config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data());
return; return;
} }
@ -186,10 +196,12 @@ void CFGInit() {
// TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals
CONSOLE_USERNAME_BLOCK.ng_word = 0; CONSOLE_USERNAME_BLOCK.ng_word = 0;
CONSOLE_USERNAME_BLOCK.zero = 0; CONSOLE_USERNAME_BLOCK.zero = 0;
// Copy string to buffer and pad with zeros at the end // Copy string to buffer and pad with zeros at the end
auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14); auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14);
std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size, std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size,
std::end(CONSOLE_USERNAME_BLOCK.username), 0); std::end(CONSOLE_USERNAME_BLOCK.username), 0);
FormatConfig(); FormatConfig();
} }

View file

@ -18,6 +18,7 @@
#include "core/file_sys/archive_savedata.h" #include "core/file_sys/archive_savedata.h"
#include "core/file_sys/archive_savedatacheck.h" #include "core/file_sys/archive_savedatacheck.h"
#include "core/file_sys/archive_sdmc.h" #include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/archive_systemsavedata.h"
#include "core/file_sys/directory_backend.h" #include "core/file_sys/directory_backend.h"
#include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/archive.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -449,6 +450,9 @@ void ArchiveInit() {
// Create the SaveDataCheck archive, basically a small variation of the RomFS archive // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
auto systemsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
} }
/// Shutdown archives /// Shutdown archives

View file

@ -333,9 +333,9 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
// Interleave the lower 3 bits of each coordinate to get the intra-block offsets, which are // Interleave the lower 3 bits of each coordinate to get the intra-block offsets, which are
// arranged in a Z-order curve. More details on the bit manipulation at: // arranged in a Z-order curve. More details on the bit manipulation at:
// https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ // https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
unsigned int i = (x | (y << 8)) & 0x0707; // ---- -210 unsigned int i = (x & 7) | ((y & 7) << 8); // ---- -210
i = (i ^ (i << 2)) & 0x1313; // ---2 --10 i = (i ^ (i << 2)) & 0x1313; // ---2 --10
i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0 i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0
i = (i | (i >> 7)) & 0x3F; i = (i | (i >> 7)) & 0x3F;
if (info.format != Regs::TextureFormat::ETC1 && if (info.format != Regs::TextureFormat::ETC1 &&
@ -436,9 +436,9 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
case Regs::TextureFormat::A4: case Regs::TextureFormat::A4:
{ {
const u8* source_ptr = source + offset / 2 + i / 2; const u8* source_ptr = source + (offset + i) / 2;
u8 a = (coarse_x % 2) ? ((*source_ptr)&0xF) : (((*source_ptr) & 0xF0) >> 4); u8 a = (i % 2) ? ((*source_ptr & 0xF0) >> 4) : (*source_ptr & 0xF);
a = Color::Convert4To8(a); a = Color::Convert4To8(a);
if (disable_alpha) { if (disable_alpha) {