mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-04-25 07:57:04 -05:00
Fix extending containers. Update and implement SVI files.
This commit is contained in:
parent
e355b99918
commit
69f728b29b
|
|
@ -35,7 +35,7 @@ namespace data
|
|||
/// @brief Pushes data to m_userData
|
||||
/// @param saveInfo SaveDataInfo.
|
||||
/// @param playStats Play statistics.
|
||||
void add_data(const FsSaveDataInfo &saveInfo, const PdmPlayStatistics &playStats);
|
||||
void add_data(const FsSaveDataInfo *saveInfo, const PdmPlayStatistics *playStats);
|
||||
|
||||
/// @brief Clears the user save info vector.
|
||||
void clear_save_info(void);
|
||||
|
|
|
|||
|
|
@ -13,5 +13,12 @@ namespace fs
|
|||
/// @brief Deletes the save data of the FsSaveDataInfo passed.
|
||||
/// @param saveInfo Save data to delete.
|
||||
/// @return True on success. False on failure.
|
||||
bool delete_save_data(const FsSaveDataInfo &saveInfo);
|
||||
bool delete_save_data(const FsSaveDataInfo *saveInfo);
|
||||
|
||||
/// @brief Extends the save data of the FsSaveDataInfo struct passed.
|
||||
/// @param saveInfo Pointer to the FsSaveDataInfo struct of the save to extend.
|
||||
/// @param size Size (in MB) to extend the save data to.
|
||||
/// @param journalSize Size of the journaling space.
|
||||
/// @return True on success. False on failure.
|
||||
bool extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize);
|
||||
} // namespace fs
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"Enable writing to system saves and NAND: %s",
|
||||
"Export saves to ZIP: %s",
|
||||
"Zip compression level: %u",
|
||||
"Enable CPU Boost: %s",
|
||||
"Title sort type: %s",
|
||||
"Text menu (JKSM) mode: %s",
|
||||
"Force English: %s",
|
||||
|
|
@ -53,6 +54,7 @@
|
|||
"Enables restoring system saves and writing to NAND partitions.",
|
||||
"Exports save data to ZIP archives instead of unpacked folders.",
|
||||
"Compression or deflate level used when writing to ZIP. The default value is 6. Lower values are faster, but offer less compression and space savings. Zero is store, or no compression.",
|
||||
"Enables CPU boost when exporting save data.",
|
||||
"Controls the way titles are sorted and displayed.",
|
||||
"Displays titles as text menus like the original JKSM on 3DS instead of icon grids.",
|
||||
"Forces English to be used as the language instead of the detected system language.",
|
||||
|
|
@ -138,13 +140,16 @@
|
|||
"TitleOptionStatus": [
|
||||
"Deleting all backups for #%s#.",
|
||||
"Resetting save data for #%s#.",
|
||||
"Deleting #%s#'s save data for #%s#..."
|
||||
"Deleting #%s#'s save data for #%s#...",
|
||||
"Extending #%s#'s save data for #%s#..."
|
||||
],
|
||||
"TitleOptionPops": [
|
||||
"All backups deleted for `%s`!",
|
||||
"Failed to delete all backups!",
|
||||
"Error resetting save data!",
|
||||
"Save data successfully reset!"
|
||||
"Save data successfully reset!",
|
||||
"SVI file exported successfully!",
|
||||
"Error exporting SVI file!"
|
||||
],
|
||||
"TitleOptionConfirmations": [
|
||||
"Are you sure you want to add #%s# to you blacklist? Once you do this, it will no longer appear on any title list or selection.",
|
||||
|
|
|
|||
|
|
@ -71,12 +71,6 @@ JKSV::JKSV(void)
|
|||
ABORT_ON_FAILURE(initialize_service(setsysInitialize, "SetSys"));
|
||||
ABORT_ON_FAILURE(initialize_service(socketInitializeDefault, "Socket"));
|
||||
|
||||
// JKSV doesn't really need the full GPU going so.
|
||||
if (R_FAILED(appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad)))
|
||||
{
|
||||
logger::log("Error setting CPU boost mode!");
|
||||
}
|
||||
|
||||
// Input doesn't have anything to return.
|
||||
input::initialize();
|
||||
|
||||
|
|
@ -91,6 +85,14 @@ JKSV::JKSV(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// I'd rather this be here than checked every time one is exported.
|
||||
fslib::Path sviDir = config::get_working_directory() / "svi";
|
||||
if (!fslib::directory_exists(sviDir) && !fslib::create_directories_recursively(sviDir))
|
||||
{
|
||||
// This one isn't fatal, but it can be super fatal later if this fails.
|
||||
logger::log("Error creating svi directory: %s", fslib::get_error_string());
|
||||
}
|
||||
|
||||
// JKSV also has no internal strings anymore. This is FATAL now.
|
||||
ABORT_ON_FAILURE(strings::initialize());
|
||||
|
||||
|
|
@ -125,8 +127,6 @@ JKSV::~JKSV()
|
|||
// Try to save config first.
|
||||
config::save();
|
||||
|
||||
// Not sure if this one is really needed, but just in case.
|
||||
appletSetCpuBoostMode(ApmCpuBoostMode_Normal);
|
||||
socketExit();
|
||||
setsysExit();
|
||||
setExit();
|
||||
|
|
|
|||
|
|
@ -356,7 +356,10 @@ static void create_new_backup(sys::ProgressTask *task,
|
|||
}
|
||||
fs::copy_directory(fs::DEFAULT_SAVE_ROOT, targetPath, 0, {}, task);
|
||||
}
|
||||
|
||||
// Refresh.
|
||||
spawningState->refresh();
|
||||
|
||||
task->finished();
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +458,6 @@ static void restore_backup(sys::ProgressTask *task, std::shared_ptr<TargetStruct
|
|||
else if (std::strstr(dataStruct->m_targetPath.c_string(), ".zip") != NULL)
|
||||
{
|
||||
unzFile targetZip = unzOpen64(dataStruct->m_targetPath.c_string());
|
||||
logger::log("targetZip");
|
||||
if (!targetZip)
|
||||
{
|
||||
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ static void change_output_path(data::TitleInfo *targetTitle);
|
|||
static void delete_all_backups_for_title(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
|
||||
static void reset_save_data(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
|
||||
static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
|
||||
static void extend_container(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
|
||||
static void extend_save_data(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct);
|
||||
static void export_svi_file(data::TitleInfo *titleInfo);
|
||||
|
||||
TitleOptionState::TitleOptionState(data::User *user, data::TitleInfo *titleInfo)
|
||||
: m_targetUser(user), m_titleInfo(titleInfo)
|
||||
|
|
@ -189,11 +190,19 @@ void TitleOptionState::update(void)
|
|||
|
||||
case EXTEND_CONTAINER:
|
||||
{
|
||||
// Data
|
||||
std::shared_ptr<TargetStruct> data = std::make_shared<TargetStruct>();
|
||||
data->m_targetUser = m_targetUser;
|
||||
data->m_targetTitle = m_titleInfo;
|
||||
|
||||
// State.
|
||||
JKSV::push_state(std::make_shared<TaskState>(extend_save_data, data));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPORT_SVI:
|
||||
{
|
||||
export_svi_file(m_titleInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -354,7 +363,7 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<Target
|
|||
return;
|
||||
}
|
||||
|
||||
if (!fs::delete_save_data(*saveInfo))
|
||||
if (!fs::delete_save_data(saveInfo))
|
||||
{
|
||||
// Just cleanup, I guess?
|
||||
task->finished();
|
||||
|
|
@ -368,6 +377,85 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr<Target
|
|||
task->finished();
|
||||
}
|
||||
|
||||
static void extend_container(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct)
|
||||
static void extend_save_data(sys::Task *task, std::shared_ptr<TargetStruct> dataStruct)
|
||||
{
|
||||
// This is just to make stuff easier to read.
|
||||
data::TitleInfo *titleInfo = dataStruct->m_targetTitle;
|
||||
FsSaveDataInfo *saveInfo = dataStruct->m_targetUser->get_save_info_by_id(titleInfo->get_application_id());
|
||||
if (!saveInfo)
|
||||
{
|
||||
logger::log("Error retrieving save data info to extend!");
|
||||
task->finished();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Set the status.
|
||||
task->set_status(strings::get_by_name(strings::names::TITLE_OPTION_STATUS, 3),
|
||||
dataStruct->m_targetUser->get_nickname(),
|
||||
dataStruct->m_targetTitle->get_title());
|
||||
|
||||
// This is the header string.
|
||||
std::string_view keyboardString = strings::get_by_name(strings::names::KEYBOARD_STRINGS, 8);
|
||||
|
||||
// Get how much to extend.
|
||||
char buffer[5] = {0};
|
||||
// No default. Maybe change this later?
|
||||
if (!keyboard::get_input(SwkbdType_NumPad, {}, keyboardString, buffer, 4))
|
||||
{
|
||||
task->finished();
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert input to number and multiply it by 1MB. To do: Check if this is valid before continuing?
|
||||
int64_t size = std::strtoll(buffer, NULL, 10) * 0x100000;
|
||||
|
||||
// Grab the journal size. Going max is probably a good idea here in case games increase it.
|
||||
int64_t journalSize = titleInfo->get_journal_size_max(saveInfo->save_data_type);
|
||||
|
||||
// To do: Check this and toast message.
|
||||
fs::extend_save_data(saveInfo, size, journalSize);
|
||||
|
||||
task->finished();
|
||||
}
|
||||
|
||||
static void export_svi_file(data::TitleInfo *titleInfo)
|
||||
{
|
||||
// This is to allow the files to be create with a starting size. This cuts down on FS calls with fslib.
|
||||
constexpr size_t SIZE_SVI_FILE = sizeof(uint64_t) + sizeof(NsApplicationControlData);
|
||||
|
||||
// Export path.
|
||||
fslib::Path sviPath = config::get_working_directory() / "svi" /
|
||||
stringutil::get_formatted_string("%016llX.svi", titleInfo->get_application_id());
|
||||
|
||||
// Check if it already exists.
|
||||
if (fslib::file_exists(sviPath))
|
||||
{
|
||||
logger::log("SVI for %016llX already exists!", titleInfo->get_application_id());
|
||||
// Just show this and bail.
|
||||
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
|
||||
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 5));
|
||||
return;
|
||||
}
|
||||
|
||||
// File
|
||||
fslib::File sviFile(sviPath, FsOpenMode_Create | FsOpenMode_Write, SIZE_SVI_FILE);
|
||||
if (!sviFile)
|
||||
{
|
||||
logger::log("Error exporting SVI file: %s", fslib::get_error_string());
|
||||
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
|
||||
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 5));
|
||||
}
|
||||
|
||||
// Ok. Letsa go~
|
||||
// This is needed like this.
|
||||
uint64_t applicationID = titleInfo->get_application_id();
|
||||
|
||||
// Write the stuff we need.
|
||||
sviFile.write(&applicationID, sizeof(uint64_t));
|
||||
sviFile.write(titleInfo->get_control_data(), sizeof(NsApplicationControlData));
|
||||
|
||||
// Show this so we know things happened.jpg
|
||||
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
|
||||
strings::get_by_name(strings::names::TITLE_OPTION_POPS, 4));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ static void delete_all_save_data_for_user(sys::Task *task, std::shared_ptr<UserS
|
|||
// Update thread task.
|
||||
task->set_status(strings::get_by_name(strings::names::USER_OPTION_STATUS, 1), target_title);
|
||||
|
||||
if (!fs::delete_save_data(*targetUser->get_save_info_at(i)))
|
||||
if (!fs::delete_save_data(targetUser->get_save_info_at(i)))
|
||||
{
|
||||
ui::PopMessageManager::push_message(ui::PopMessageManager::DEFAULT_MESSAGE_TICKS,
|
||||
strings::get_by_name(strings::names::POP_MESSAGES_SAVE_CREATE, 2));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ namespace
|
|||
// Makes stuff slightly easier to read.
|
||||
using ConfigPair = std::pair<std::string, uint8_t>;
|
||||
|
||||
/// @brief This is the default working directory path.
|
||||
constexpr std::string_view PATH_DEFAULT_WORK_DIR = "sdmc:/JKSV";
|
||||
// Folder path.
|
||||
constexpr std::string_view PATH_CONFIG_FOLDER = "sdmc:/config/JKSV";
|
||||
// Actual config path.
|
||||
|
|
@ -132,7 +134,7 @@ void config::initialize(void)
|
|||
|
||||
void config::reset_to_default(void)
|
||||
{
|
||||
s_workingDirectory = "sdmc:/JKSV";
|
||||
s_workingDirectory = PATH_DEFAULT_WORK_DIR;
|
||||
s_configVector.push_back(std::make_pair(config::keys::INCLUDE_DEVICE_SAVES.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::AUTO_BACKUP_ON_RESTORE.data(), 1));
|
||||
s_configVector.push_back(std::make_pair(config::keys::AUTO_NAME_BACKUPS.data(), 1));
|
||||
|
|
@ -144,7 +146,6 @@ void config::reset_to_default(void)
|
|||
s_configVector.push_back(std::make_pair(config::keys::LIST_ACCOUNT_SYS_SAVES.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::ALLOW_WRITING_TO_SYSTEM.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::EXPORT_TO_ZIP.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::ZIP_COMPRESSION_LEVEL.data(), 6));
|
||||
s_configVector.push_back(std::make_pair(config::keys::TITLE_SORT_TYPE.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::JKSM_TEXT_MODE.data(), 0));
|
||||
s_configVector.push_back(std::make_pair(config::keys::FORCE_ENGLISH.data(), 0));
|
||||
|
|
@ -231,13 +232,18 @@ void config::save(void)
|
|||
|
||||
uint8_t config::get_by_key(std::string_view key)
|
||||
{
|
||||
// See if the key can be found.
|
||||
auto findKey = std::find_if(s_configVector.begin(), s_configVector.end(), [key](const auto &configPair) {
|
||||
return key == configPair.first;
|
||||
});
|
||||
|
||||
// Bail.
|
||||
if (findKey == s_configVector.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return the value.
|
||||
return findKey->second;
|
||||
}
|
||||
|
||||
|
|
@ -247,10 +253,12 @@ void config::toggle_by_key(std::string_view key)
|
|||
auto findKey = std::find_if(s_configVector.begin(), s_configVector.end(), [key](const auto &configPair) {
|
||||
return key == configPair.first;
|
||||
});
|
||||
|
||||
if (findKey == s_configVector.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
findKey->second = findKey->second ? 0 : 1;
|
||||
}
|
||||
|
||||
|
|
@ -273,6 +281,7 @@ uint8_t config::get_by_index(int index)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return s_configVector.at(index).second;
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +291,7 @@ void config::toggle_by_index(int index)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_configVector[index].second = s_configVector[index].second ? 0 : 1;
|
||||
}
|
||||
|
||||
|
|
@ -291,6 +301,7 @@ void config::set_by_index(int index, uint8_t value)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_configVector[index].second = value;
|
||||
}
|
||||
|
||||
|
|
@ -328,6 +339,7 @@ bool config::is_favorite(uint64_t applicationID)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +362,7 @@ bool config::is_blacklisted(uint64_t applicationID)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +377,7 @@ bool config::has_custom_path(uint64_t applicationID)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -373,5 +387,6 @@ void config::get_custom_path(uint64_t applicationID, char *pathOut, size_t pathO
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(pathOut, s_pathMap[applicationID].c_str(), s_pathMap[applicationID].length());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ data::User::User(AccountUid accountID,
|
|||
std::memcpy(m_pathSafeNickname, pathSafeNickname.data(), pathSafeNickname.length());
|
||||
}
|
||||
|
||||
void data::User::add_data(const FsSaveDataInfo &saveInfo, const PdmPlayStatistics &playStats)
|
||||
void data::User::add_data(const FsSaveDataInfo *saveInfo, const PdmPlayStatistics *playStats)
|
||||
{
|
||||
uint64_t applicationID = saveInfo.application_id == 0 ? saveInfo.system_save_data_id : saveInfo.application_id;
|
||||
uint64_t applicationID = saveInfo->application_id == 0 ? saveInfo->system_save_data_id : saveInfo->application_id;
|
||||
|
||||
m_userData.push_back(std::make_pair(applicationID, std::make_pair(saveInfo, playStats)));
|
||||
m_userData.push_back(std::make_pair(applicationID, std::make_pair(*saveInfo, *playStats)));
|
||||
}
|
||||
|
||||
void data::User::clear_save_info(void)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ static bool load_create_user_accounts(void);
|
|||
/// @brief Loads the application records from NS.
|
||||
static void load_application_records(void);
|
||||
|
||||
/// @brief Imports external SVI(Control Data) files.
|
||||
static void import_svi_files(void);
|
||||
|
||||
/// @brief Loads the save data info available from the system.
|
||||
static void load_save_data_info(void);
|
||||
|
||||
|
|
@ -97,6 +100,9 @@ bool data::initialize(bool clearCache)
|
|||
load_application_records();
|
||||
}
|
||||
|
||||
// Load these now if needed.
|
||||
import_svi_files();
|
||||
|
||||
// I'm just going to assume this is implied since we're reloading everything.
|
||||
// Loop through the users and clear their save data info.
|
||||
for (auto &[accountID, user] : s_userVector)
|
||||
|
|
@ -223,6 +229,54 @@ static void load_application_records(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void import_svi_files(void)
|
||||
{
|
||||
// Path.
|
||||
fslib::Path sviPath = config::get_working_directory() / "svi";
|
||||
|
||||
// Try opening it.
|
||||
fslib::Directory sviDir(sviPath);
|
||||
if (!sviDir)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through the directory and load these things.
|
||||
for (int64_t i = 0; i < sviDir.get_count(); i++)
|
||||
{
|
||||
// Full path.
|
||||
fslib::Path fullPath = sviPath / sviDir[i];
|
||||
|
||||
// Try opening it.
|
||||
fslib::File sviFile(fullPath, FsOpenMode_Read);
|
||||
if (!sviFile || sviFile.get_size() != sizeof(uint64_t) + sizeof(NsApplicationControlData))
|
||||
{
|
||||
logger::log("Error importing \"%s\": File couldn't be opened or is invalid!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// First read the ID so we can check if it's even worth bothering with the rest.
|
||||
// To do. This could be accomplished with just the file name when I have time.
|
||||
uint64_t applicationID = 0;
|
||||
if (sviFile.read(&applicationID, sizeof(uint64_t)) != sizeof(uint64_t) ||
|
||||
s_titleInfoMap.find(applicationID) != s_titleInfoMap.end())
|
||||
{
|
||||
// Not worth continuing with this because it was already loaded somewhere else.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Good to go and read this now.
|
||||
NsApplicationControlData controlData = {0};
|
||||
if (sviFile.read(&controlData, sizeof(NsApplicationControlData)) != sizeof(NsApplicationControlData))
|
||||
{
|
||||
logger::log("Error reading SVI file!");
|
||||
continue;
|
||||
}
|
||||
|
||||
s_titleInfoMap.emplace(applicationID, std::move(data::TitleInfo(applicationID, controlData)));
|
||||
}
|
||||
}
|
||||
|
||||
static void load_save_data_info(void)
|
||||
{
|
||||
// Grab these here so I don't call the config functions every loop. Config uses a vector instead of map so the calls
|
||||
|
|
@ -248,10 +302,16 @@ static void load_save_data_info(void)
|
|||
// Grab a reference to the current SaveDataInfo struct.
|
||||
FsSaveDataInfo &saveInfo = saveReader.get();
|
||||
|
||||
// System saves have no application ID.
|
||||
uint64_t applicationID = (saveInfo.save_data_type == FsSaveDataType_System ||
|
||||
saveInfo.save_data_type == FsSaveDataType_SystemBcat)
|
||||
? saveInfo.system_save_data_id
|
||||
: saveInfo.application_id;
|
||||
|
||||
// This will filter out account system saves if desired and unmountable titles.
|
||||
if ((!showAccountSystemSaves && saveInfo.save_data_type == FsSaveDataType_System && saveInfo.uid != 0) ||
|
||||
(onlyListMountable && !fslib::open_save_data_with_save_info(fs::DEFAULT_SAVE_MOUNT, saveInfo)) ||
|
||||
config::is_blacklisted(saveInfo.application_id))
|
||||
config::is_blacklisted(applicationID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -311,12 +371,6 @@ static void load_save_data_info(void)
|
|||
}
|
||||
}
|
||||
|
||||
// System saves have no application ID.
|
||||
uint64_t applicationID = (saveInfo.save_data_type == FsSaveDataType_System ||
|
||||
saveInfo.save_data_type == FsSaveDataType_SystemBcat)
|
||||
? saveInfo.system_save_data_id
|
||||
: saveInfo.application_id;
|
||||
|
||||
// Search the map just to be sure it was loaded previously. This can happen.
|
||||
if (s_titleInfoMap.find(applicationID) == s_titleInfoMap.end())
|
||||
{
|
||||
|
|
@ -328,7 +382,6 @@ static void load_save_data_info(void)
|
|||
|
||||
// I feel weird allcating space for this even if it's not used, but whatever.
|
||||
PdmPlayStatistics stats = {0};
|
||||
|
||||
// This should be an OKish way to filter out system titles...
|
||||
if (titleInfo.has_control_data() &&
|
||||
R_FAILED(
|
||||
|
|
@ -339,7 +392,7 @@ static void load_save_data_info(void)
|
|||
}
|
||||
|
||||
// Finally push it over to the user.
|
||||
user->second.add_data(saveInfo, stats);
|
||||
user->second.add_data(&saveInfo, &stats);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +418,7 @@ static void load_save_data_info(void)
|
|||
// To do: Final decision on this. It's easier to read than second.first...
|
||||
auto &[saveInfo, playStats] = entry.second;
|
||||
|
||||
user.add_data(saveInfo, playStats);
|
||||
user.add_data(&saveInfo, &playStats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -400,7 +453,8 @@ static bool read_cache_file(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (cache.read(entryBuffer.get(), sizeof(CacheEntry) * titleCount) != sizeof(CacheEntry) * titleCount)
|
||||
if (cache.read(entryBuffer.get(), sizeof(CacheEntry) * titleCount) !=
|
||||
static_cast<ssize_t>(sizeof(CacheEntry) * titleCount))
|
||||
{
|
||||
logger::log("Error reading cache file! Size mismatch!");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -34,25 +34,25 @@ bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo
|
|||
return true;
|
||||
}
|
||||
|
||||
bool fs::delete_save_data(const FsSaveDataInfo &saveInfo)
|
||||
bool fs::delete_save_data(const FsSaveDataInfo *saveInfo)
|
||||
{
|
||||
// I'm not allowing this at all.
|
||||
if (saveInfo.save_data_type == FsSaveDataType_System || saveInfo.save_data_type == FsSaveDataType_SystemBcat)
|
||||
if (saveInfo->save_data_type == FsSaveDataType_System || saveInfo->save_data_type == FsSaveDataType_SystemBcat)
|
||||
{
|
||||
logger::log("Error deleting save data: Deleting system save data is not allowed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save attributes.
|
||||
FsSaveDataAttribute saveAttributes = {.application_id = saveInfo.application_id,
|
||||
.uid = saveInfo.uid,
|
||||
.system_save_data_id = saveInfo.system_save_data_id,
|
||||
.save_data_type = saveInfo.save_data_type,
|
||||
.save_data_rank = saveInfo.save_data_rank,
|
||||
.save_data_index = saveInfo.save_data_index};
|
||||
FsSaveDataAttribute saveAttributes = {.application_id = saveInfo->application_id,
|
||||
.uid = saveInfo->uid,
|
||||
.system_save_data_id = saveInfo->system_save_data_id,
|
||||
.save_data_type = saveInfo->save_data_type,
|
||||
.save_data_rank = saveInfo->save_data_rank,
|
||||
.save_data_index = saveInfo->save_data_index};
|
||||
|
||||
Result fsError =
|
||||
fsDeleteSaveDataFileSystemBySaveDataAttribute(static_cast<FsSaveDataSpaceId>(saveInfo.save_data_space_id),
|
||||
fsDeleteSaveDataFileSystemBySaveDataAttribute(static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id),
|
||||
&saveAttributes);
|
||||
if (R_FAILED(fsError))
|
||||
{
|
||||
|
|
@ -61,3 +61,17 @@ bool fs::delete_save_data(const FsSaveDataInfo &saveInfo)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize)
|
||||
{
|
||||
Result fsError = fsExtendSaveDataFileSystem(static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id),
|
||||
saveInfo->save_data_id,
|
||||
size,
|
||||
journalSize);
|
||||
if (R_FAILED(fsError))
|
||||
{
|
||||
logger::log("Error extending save data: 0x%0X.", fsError);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,12 +168,14 @@ void fs::copy_directory_to_zip(const fslib::Path &source, zipFile destination, s
|
|||
sharedData->m_bufferIsFull = false;
|
||||
sharedData->m_bufferCondition.notify_one();
|
||||
}
|
||||
|
||||
// Write
|
||||
zipError = zipWriteInFileInZip(destination, localBuffer.get(), readCount);
|
||||
if (zipError != ZIP_OK)
|
||||
{
|
||||
logger::log("Error writing data to zip: %i.", zipError);
|
||||
}
|
||||
|
||||
// Update count and status
|
||||
writeCount += readCount;
|
||||
if (task)
|
||||
|
|
@ -317,6 +319,7 @@ void fs::copy_zip_to_directory(unzFile source,
|
|||
|
||||
// Close file and commit again just for good measure.
|
||||
destinationFile.close();
|
||||
|
||||
if (!fslib::commit_data_to_file_system(commitDevice))
|
||||
{
|
||||
logger::log("Error performing final file commit: %s", fslib::get_error_string());
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ bool keyboard::get_input(SwkbdType keyboardType,
|
|||
{
|
||||
// Setup keyboard.
|
||||
SwkbdConfig keyboard;
|
||||
swkbdCreate(&keyboard,
|
||||
0); // Old JKSV actually used dictionary words, but I don't feel like implementing them again.
|
||||
swkbdCreate(&keyboard, 0);
|
||||
swkbdConfigSetBlurBackground(&keyboard, true);
|
||||
swkbdConfigSetInitialText(&keyboard, defaultText.data());
|
||||
swkbdConfigSetHeaderText(&keyboard, header.data());
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user