ABI fixes: libNet, libSaveData (rewrite the legacy Kyty implementation)

This commit is contained in:
nmzik
2026-07-29 00:30:24 +02:00
parent a6b61d7aa0
commit 4b9030bd3d
4 changed files with 127 additions and 32 deletions
+3
View File
@@ -35,6 +35,7 @@ namespace LibNet {
LIB_VERSION("Net", 1, "Net", 1, 1);
static thread_local int g_net_errno = 0;
static constexpr uint32_t g_in6addr_any[4] {};
namespace Net = Network::Net;
@@ -180,6 +181,8 @@ uint16_t KYTY_SYSV_ABI NetNtohs(uint16_t net16) {
}
LIB_DEFINE(InitNet_1_Net) {
LIB_OBJECT("ZRAJo-A-ukc", &LibNet::g_in6addr_any);
LIB_FUNC("Nlev7Lg8k3A", LibNet::NetInit);
LIB_FUNC("HQOwnfMGipQ", LibNet::GetNetErrorAddr);
LIB_FUNC("PIWqhn9oSxc", LibNet::NetAccept);
+55 -32
View File
@@ -4,9 +4,11 @@
#include "common/file.h"
#include "common/logging/log.h"
#include "common/stringUtils.h"
#include "common/threads.h"
#include "kernel/fileSystem.h"
#include "libs/errno.h"
#include "libs/libs.h"
#include "libs/saveDataMountSlots.h"
#include "loader/symbolDatabase.h"
#include "loader/systemContent.h"
@@ -23,7 +25,6 @@ namespace SaveData {
// TODO(): specify dir at launcher
static constexpr char SAVE_DATA_DIR[] = "_SaveData";
static constexpr char SAVE_DATA_POINT[] = "/savedata0";
static constexpr uint64_t SAVE_DATA_BLOCKS_MAX = 16384;
struct SceSaveDataDirName {
@@ -234,6 +235,8 @@ static constexpr uint32_t SAVE_DATA_EVENT_TYPE_COMMIT_BACKUP_END = 4u;
static std::vector<uint8_t> g_save_data_memory(0x10000);
static int32_t g_next_transaction_resource = 1;
static std::deque<SaveDataEvent> g_save_data_events;
static SaveDataMountSlots g_mount_slots;
static Common::Mutex g_mount_mutex;
static std::string get_title_id() {
std::string title_id;
@@ -291,6 +294,18 @@ static bool dir_name_match(const char* str, const char* pattern) {
return *str == '\0' && *pattern == '\0';
}
static int mount_save_data(int slot, std::string_view dir_name, const std::string& directory,
uint32_t status, SaveDataMountResult* result) {
const std::string mount_point = SaveDataMountSlots::MountPoint(static_cast<size_t>(slot));
LibKernel::FileSystem::Mount(directory, mount_point);
g_mount_slots.Mount(static_cast<size_t>(slot), dir_name);
std::snprintf(result->mount_point.data, sizeof(result->mount_point.data), "%s",
mount_point.c_str());
result->required_blocks = 0;
result->mount_status = status;
return OK;
}
int KYTY_SYSV_ABI SaveDataInitialize3(const void* /*init*/) {
PRINT_NAME();
@@ -302,6 +317,10 @@ int KYTY_SYSV_ABI SaveDataInitialize3(const void* /*init*/) {
int KYTY_SYSV_ABI SaveDataTerminate() {
PRINT_NAME();
Common::LockGuard lock(g_mount_mutex);
if (!g_mount_slots.Empty()) {
return SAVE_DATA_ERROR_BUSY;
}
g_save_data_events.clear();
return OK;
@@ -418,12 +437,20 @@ int KYTY_SYSV_ABI SaveDataMount3(const SaveDataMount3* mount, SaveDataMountResul
*mount_result = {};
std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" +
std::string(mount->dir_name->data);
std::string mount_point = SAVE_DATA_POINT;
bool create = ((mount->mount_mode & 4u) != 0);
bool create2 = ((mount->mount_mode & 32u) != 0);
bool open = (!create && !create2 && ((mount->mount_mode & 3u) != 0));
Common::LockGuard lock(g_mount_mutex);
const std::string dir_name = mount->dir_name->data;
const std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" + dir_name;
const bool create = ((mount->mount_mode & 4u) != 0);
const bool create2 = ((mount->mount_mode & 32u) != 0);
const bool open = (!create && !create2 && ((mount->mount_mode & 3u) != 0));
const int slot = g_mount_slots.FindAvailable(dir_name);
if (slot == SaveDataMountSlots::BUSY) {
return SAVE_DATA_ERROR_BUSY;
}
if (slot == SaveDataMountSlots::FULL) {
return SAVE_DATA_ERROR_MOUNT_FULL;
}
if (!create && !create2 && !open) {
EXIT("unknown mount mode: %u", mount->mount_mode);
@@ -445,16 +472,7 @@ int KYTY_SYSV_ABI SaveDataMount3(const SaveDataMount3* mount, SaveDataMountResul
EXIT_NOT_IMPLEMENTED((!Common::File::IsDirectoryExisting(mount_dir)));
}
LibKernel::FileSystem::Mount(mount_dir, mount_point);
int s = snprintf(mount_result->mount_point.data, 16, "%s", mount_point.c_str());
EXIT_NOT_IMPLEMENTED(s >= 16);
mount_result->required_blocks = 0;
mount_result->mount_status = (created ? 1 : 0);
return OK;
return mount_save_data(slot, dir_name, mount_dir, created ? 1u : 0u, mount_result);
}
int KYTY_SYSV_ABI SaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2* setup_param,
@@ -575,24 +593,22 @@ int KYTY_SYSV_ABI SaveDataTransferringMount(const SaveDataTransferringMount* mou
*mount_result = {};
std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" +
std::string(mount->dir_name->data);
std::string mount_point = SAVE_DATA_POINT;
Common::LockGuard lock(g_mount_mutex);
const std::string dir_name = mount->dir_name->data;
const std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" + dir_name;
const int slot = g_mount_slots.FindAvailable(dir_name);
if (slot == SaveDataMountSlots::BUSY) {
return SAVE_DATA_ERROR_BUSY;
}
if (slot == SaveDataMountSlots::FULL) {
return SAVE_DATA_ERROR_MOUNT_FULL;
}
if (!Common::File::IsDirectoryExisting(mount_dir)) {
Common::File::CreateDirectories(mount_dir);
}
LibKernel::FileSystem::Mount(mount_dir, mount_point);
int s = snprintf(mount_result->mount_point.data, 16, "%s", mount_point.c_str());
EXIT_NOT_IMPLEMENTED(s >= 16);
mount_result->required_blocks = 0;
mount_result->mount_status = 1;
return OK;
return mount_save_data(slot, dir_name, mount_dir, 1, mount_result);
}
int KYTY_SYSV_ABI SaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mount_point) {
@@ -606,11 +622,18 @@ int KYTY_SYSV_ABI SaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mount
"\t mount_point = %s\n",
mode, mount_point->data);
Common::LockGuard lock(g_mount_mutex);
const std::string point = mount_point->data;
const int slot = g_mount_slots.Find(point);
if (slot == SaveDataMountSlots::FULL) {
return SAVE_DATA_ERROR_NOT_FOUND;
}
if ((mode & SAVE_DATA_UMOUNT_MODE_BACKUP_ASYNC) != 0) {
queue_save_data_event(SAVE_DATA_EVENT_TYPE_UMOUNT_BACKUP_END, 0, nullptr, nullptr);
}
LibKernel::FileSystem::Umount(std::string(mount_point->data));
LibKernel::FileSystem::Umount(point);
g_mount_slots.Release(static_cast<size_t>(slot));
return OK;
}
+2
View File
@@ -22,6 +22,7 @@ namespace SystemService {
[[maybe_unused]] constexpr int PARAM_ID_SUMMERTIME = 5;
[[maybe_unused]] constexpr int PARAM_ID_SYSTEM_NAME = 6;
[[maybe_unused]] constexpr int PARAM_ID_GAME_PARENTAL_LEVEL = 7;
[[maybe_unused]] constexpr int PARAM_ID_SCREEN_READER = 208;
[[maybe_unused]] constexpr int PARAM_ID_ENTER_BUTTON_ASSIGN = 1000;
[[maybe_unused]] constexpr int PARAM_LANG_JAPANESE = 0;
@@ -126,6 +127,7 @@ static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value) {
case PARAM_ID_TIME_ZONE: v = +180; break;
case PARAM_ID_SUMMERTIME: v = 0; break;
case PARAM_ID_GAME_PARENTAL_LEVEL: v = PARAM_GAME_PARENTAL_OFF; break;
case PARAM_ID_SCREEN_READER: v = 0; break;
case PARAM_ID_ENTER_BUTTON_ASSIGN: v = PARAM_ENTER_BUTTON_ASSIGN_CROSS; break;
default: EXIT("unknown param_id: %d\n", param_id);
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_SAVEDATAMOUNTSLOTS_H_
#define EMULATOR_INCLUDE_EMULATOR_LIBS_SAVEDATAMOUNTSLOTS_H_
#include <array>
#include <optional>
#include <string>
#include <string_view>
namespace Libs::SaveData {
class SaveDataMountSlots {
public:
static constexpr int BUSY = -2;
static constexpr int FULL = -1;
static constexpr size_t COUNT = 16;
[[nodiscard]] int FindAvailable(std::string_view directory) const {
int available = FULL;
for (size_t index = 0; index < m_directories.size(); index++) {
const auto& mounted = m_directories[index];
if (mounted == directory) {
return BUSY;
}
if (!mounted.has_value() && available == FULL) {
available = static_cast<int>(index);
}
}
return available;
}
void Mount(size_t slot, std::string_view directory) { m_directories[slot] = directory; }
void Release(size_t slot) {
if (slot < m_directories.size()) {
m_directories[slot].reset();
}
}
[[nodiscard]] int Find(std::string_view mount_point) const {
for (size_t index = 0; index < m_directories.size(); index++) {
if (m_directories[index].has_value() && MountPoint(index) == mount_point) {
return static_cast<int>(index);
}
}
return FULL;
}
[[nodiscard]] static std::string MountPoint(size_t slot) {
return "/savedata" + std::to_string(slot);
}
[[nodiscard]] bool Empty() const {
for (const auto& directory: m_directories) {
if (directory.has_value()) {
return false;
}
}
return true;
}
private:
std::array<std::optional<std::string>, COUNT> m_directories;
};
} // namespace Libs::SaveData
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_SAVEDATAMOUNTSLOTS_H_ */