Files
KytyPS5/src/libs/dialog.cpp
T
05f92b6422 libCes CP932 fix for Windows/macOS, fix SaveDataDialog lockups (#878)
* libs: fix CP932 iconv conversion on Windows and macOS

SDL3's SDL_SYSTEM_ICONV build option defaults off on Windows and macOS,
so SDL falls back to its own bundled iconv there, which only implements
ASCII/Latin-1/UTF/UCS. SDL_iconv_open("UTF-8", "CP932") always failed as
a result, crashing games that convert Shift-JIS strings via
sceCesMbcsStrToUtf8Str (e.g. save-data dialogs).

Add a small CesIconv shim selected at compile time: Windows converts one
character at a time via the Win32 codepage-932 APIs, replicating
SDL_iconv's chunked semantics and error codes; macOS calls real POSIX
iconv directly, since libiconv is always present there and does support
CP932, unlike SDL's fallback. Linux is untouched, since SDL already
links real system iconv by default there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* libs: fix SaveDataDialog infinite loop on save

SaveDataDialogOpen() jumped straight from SAVE_STATUS_INITIALIZED (1) to
SAVE_STATUS_FINISHED (3), skipping SAVE_STATUS_RUNNING (2) entirely. At
least one title's save-write dialog stage only accepts a FINISHED status
after observing a RUNNING poll first; without it, the title assumed the
Open() request never took effect and re-issued it forever, hanging the
save flow (this only became visible once the CP932 crash above stopped
masking it).

Open() now starts the dialog as RUNNING. UpdateStatus() advances the
state machine, reporting RUNNING once before flipping to FINISHED for
subsequent polls; GetStatus() is untouched, staying a pure peek with no
side effects, matching the real SDK's pump-vs-peek split between the two
calls.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Add iconv linking to macOS

* Fix missing macOS iconv link for tests

* Fix CP932 edge cases and save dialog status consistency

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: nmzik <Nmzik@mail.ru>
2026-09-28 18:42:22 +04:00

797 lines
18 KiB
C++

#include "libs/dialog.h"
#include "common/emulatorConfig.h"
#include "common/logging/log.h"
#include "common/stringUtils.h"
#include "libs/errno.h"
#include "libs/libs.h"
#include <atomic>
#include <cstdio>
#include <cstring>
#include <mutex>
// NOLINTNEXTLINE(modernize-concat-nested-namespaces)
namespace Libs::Dialog {
namespace CommonDialog {
LIB_NAME("CommonDialog", "CommonDialog");
int KYTY_SYSV_ABI CommonDialogInitialize() {
PRINT_NAME();
return OK;
}
bool KYTY_SYSV_ABI CommonDialogIsUsed() {
PRINT_NAME();
return false;
}
} // namespace CommonDialog
namespace LoginDialog {
LIB_NAME("LoginDialog", "LoginDialog");
constexpr int LOGIN_STATUS_NONE = 0;
constexpr int LOGIN_STATUS_INITIALIZED = 1;
constexpr int LOGIN_STATUS_RUNNING = 2;
constexpr int LOGIN_STATUS_FINISHED = 3;
constexpr int LOGIN_RESULT_OK = 0;
constexpr int LOGIN_MODE_ALL_USERS = 0;
constexpr int LOGIN_MODE_NOT_LOGGED_IN = 1;
constexpr int LOGIN_USER_INVALID = -1;
constexpr int LOGIN_ERROR_NOT_INITIALIZED = static_cast<int>(0x81340001u);
constexpr int LOGIN_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x81340002u);
constexpr int LOGIN_ERROR_PARAM_INVALID = static_cast<int>(0x81340003u);
constexpr int LOGIN_ERROR_INVALID_STATE = static_cast<int>(0x81340005u);
struct LoginDialogResult {
int32_t result;
int32_t selected_user;
int32_t reserved[2];
};
struct LoginDialogParam {
int32_t size;
int32_t mode;
int32_t exclude_users_from_login_list[4];
int32_t exclude_users_from_logout_list[4];
int32_t initial_focus;
int32_t reserved[5];
};
static_assert(sizeof(LoginDialogResult) == 16);
static_assert(sizeof(LoginDialogParam) == 64);
static int g_login_status = LOGIN_STATUS_NONE;
static int g_login_selected_user = LOGIN_USER_INVALID;
int KYTY_SYSV_ABI LoginDialogInitialize() {
PRINT_NAME();
if (g_login_status != LOGIN_STATUS_NONE) {
return LOGIN_ERROR_ALREADY_INITIALIZED;
}
g_login_status = LOGIN_STATUS_INITIALIZED;
g_login_selected_user = Config::GetUserId();
return OK;
}
int KYTY_SYSV_ABI LoginDialogTerminate() {
PRINT_NAME();
if (g_login_status == LOGIN_STATUS_NONE) {
return LOGIN_ERROR_NOT_INITIALIZED;
}
g_login_status = LOGIN_STATUS_NONE;
g_login_selected_user = LOGIN_USER_INVALID;
return OK;
}
int KYTY_SYSV_ABI LoginDialogOpen(const void* param) {
PRINT_NAME();
if (g_login_status != LOGIN_STATUS_INITIALIZED && g_login_status != LOGIN_STATUS_FINISHED) {
return LOGIN_ERROR_INVALID_STATE;
}
if (param == nullptr) {
return LOGIN_ERROR_PARAM_INVALID;
}
const auto* p = static_cast<const LoginDialogParam*>(param);
if (p->size != sizeof(LoginDialogParam) ||
(p->mode != LOGIN_MODE_ALL_USERS && p->mode != LOGIN_MODE_NOT_LOGGED_IN)) {
return LOGIN_ERROR_PARAM_INVALID;
}
g_login_selected_user =
p->initial_focus != LOGIN_USER_INVALID ? p->initial_focus : Config::GetUserId();
LOGF("\t size = %d\n"
"\t mode = %d\n"
"\t initial_focus = %d\n"
"\t selected_user = %d\n",
p->size, p->mode, p->initial_focus, g_login_selected_user);
g_login_status = LOGIN_STATUS_RUNNING;
return OK;
}
int KYTY_SYSV_ABI LoginDialogClose() {
PRINT_NAME();
if (g_login_status == LOGIN_STATUS_NONE) {
return LOGIN_ERROR_NOT_INITIALIZED;
}
g_login_status = LOGIN_STATUS_FINISHED;
return OK;
}
int KYTY_SYSV_ABI LoginDialogUpdateStatus() {
PRINT_NAME();
if (g_login_status == LOGIN_STATUS_RUNNING) {
g_login_status = LOGIN_STATUS_FINISHED;
}
return g_login_status;
}
int KYTY_SYSV_ABI LoginDialogGetStatus() {
PRINT_NAME();
return g_login_status;
}
int KYTY_SYSV_ABI LoginDialogGetResult(void* result) {
PRINT_NAME();
if (g_login_status == LOGIN_STATUS_NONE) {
return LOGIN_ERROR_NOT_INITIALIZED;
}
if (result == nullptr) {
return LOGIN_ERROR_PARAM_INVALID;
}
auto* r = static_cast<LoginDialogResult*>(result);
r->result = LOGIN_RESULT_OK;
r->selected_user = g_login_selected_user;
r->reserved[0] = 0;
r->reserved[1] = 0;
return OK;
}
void KYTY_SYSV_ABI LoginDialogParamInitialize(void* param) {
PRINT_NAME();
if (param == nullptr) {
return;
}
auto* p = static_cast<LoginDialogParam*>(param);
std::memset(p, 0, sizeof(LoginDialogParam));
p->size = sizeof(LoginDialogParam);
for (int i = 0; i < 4; i++) {
p->exclude_users_from_login_list[i] = LOGIN_USER_INVALID;
p->exclude_users_from_logout_list[i] = LOGIN_USER_INVALID;
}
p->initial_focus = LOGIN_USER_INVALID;
}
} // namespace LoginDialog
namespace SigninDialog {
LIB_NAME("SigninDialog", "SigninDialog");
constexpr int SIGNIN_STATUS_NONE = 0;
constexpr int SIGNIN_STATUS_INITIALIZED = 1;
constexpr int SIGNIN_STATUS_RUNNING = 2;
constexpr int SIGNIN_STATUS_FINISHED = 3;
constexpr int SIGNIN_RESULT_USER_CANCELED = 1;
constexpr int SIGNIN_ERROR_NOT_INITIALIZED = static_cast<int>(0x81350001u);
constexpr int SIGNIN_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x81350002u);
constexpr int SIGNIN_ERROR_PARAM_INVALID = static_cast<int>(0x81350003u);
constexpr int SIGNIN_ERROR_INVALID_STATE = static_cast<int>(0x81350005u);
struct SigninDialogResult {
int32_t result;
int32_t reserved[3];
};
struct SigninDialogParam {
int32_t size;
int32_t user_id;
int32_t reserved[2];
};
static_assert(sizeof(SigninDialogResult) == 16);
static_assert(sizeof(SigninDialogParam) == 16);
static int g_signin_status = SIGNIN_STATUS_NONE;
int KYTY_SYSV_ABI SigninDialogInitialize() {
PRINT_NAME();
if (g_signin_status != SIGNIN_STATUS_NONE) {
return SIGNIN_ERROR_ALREADY_INITIALIZED;
}
g_signin_status = SIGNIN_STATUS_INITIALIZED;
return OK;
}
int KYTY_SYSV_ABI SigninDialogTerminate() {
PRINT_NAME();
if (g_signin_status == SIGNIN_STATUS_NONE) {
return SIGNIN_ERROR_NOT_INITIALIZED;
}
g_signin_status = SIGNIN_STATUS_NONE;
return OK;
}
int KYTY_SYSV_ABI SigninDialogOpen(const void* param) {
PRINT_NAME();
if (g_signin_status != SIGNIN_STATUS_INITIALIZED && g_signin_status != SIGNIN_STATUS_FINISHED) {
return SIGNIN_ERROR_INVALID_STATE;
}
if (param == nullptr ||
static_cast<const SigninDialogParam*>(param)->size != sizeof(SigninDialogParam)) {
return SIGNIN_ERROR_PARAM_INVALID;
}
g_signin_status = SIGNIN_STATUS_RUNNING;
return OK;
}
int KYTY_SYSV_ABI SigninDialogClose() {
PRINT_NAME();
if (g_signin_status == SIGNIN_STATUS_NONE) {
return SIGNIN_ERROR_NOT_INITIALIZED;
}
if (g_signin_status != SIGNIN_STATUS_RUNNING && g_signin_status != SIGNIN_STATUS_FINISHED) {
return SIGNIN_ERROR_INVALID_STATE;
}
g_signin_status = SIGNIN_STATUS_FINISHED;
return OK;
}
int KYTY_SYSV_ABI SigninDialogUpdateStatus() {
PRINT_NAME();
if (g_signin_status == SIGNIN_STATUS_RUNNING) {
g_signin_status = SIGNIN_STATUS_FINISHED;
}
return g_signin_status;
}
int KYTY_SYSV_ABI SigninDialogGetStatus() {
PRINT_NAME();
return g_signin_status;
}
int KYTY_SYSV_ABI SigninDialogGetResult(void* result) {
PRINT_NAME();
if (g_signin_status == SIGNIN_STATUS_NONE) {
return SIGNIN_ERROR_NOT_INITIALIZED;
}
if (g_signin_status != SIGNIN_STATUS_FINISHED) {
return SIGNIN_ERROR_INVALID_STATE;
}
if (result == nullptr) {
return SIGNIN_ERROR_PARAM_INVALID;
}
auto* r = static_cast<SigninDialogResult*>(result);
r->result = SIGNIN_RESULT_USER_CANCELED;
r->reserved[0] = 0;
r->reserved[1] = 0;
r->reserved[2] = 0;
return OK;
}
} // namespace SigninDialog
namespace SaveDataDialog {
LIB_NAME("SaveDataDialog", "SaveDataDialog");
constexpr int SAVE_STATUS_NONE = 0;
constexpr int SAVE_STATUS_INITIALIZED = 1;
constexpr int SAVE_STATUS_RUNNING = 2;
constexpr int SAVE_STATUS_FINISHED = 3;
constexpr int SAVE_RESULT_OK = 0;
constexpr int SAVE_BUTTON_ID_OK = 1;
struct SaveDataDialogParam {
uint8_t base_param[48];
int32_t size;
int32_t mode;
int32_t disp_type;
uint32_t pad0;
void* anim_param;
void* items;
void* user_msg_param;
void* sys_msg_param;
void* error_code_param;
void* prog_bar_param;
void* user_data;
void* option_param;
void* wizard_param;
uint8_t reserved[16];
};
struct SaveDataDirName {
char data[32];
};
struct SaveDataDialogItems {
int32_t user_id;
int32_t pad0;
const void* title_id;
const SaveDataDirName* dir_names;
uint32_t dir_names_num;
};
struct SaveDataDialogResult {
int32_t mode;
int32_t result;
int32_t button_id;
uint32_t pad0;
void* dir_name;
void* param;
void* user_data;
uint8_t reserved[32];
};
static std::atomic<int> g_save_status = SAVE_STATUS_NONE;
static bool g_save_running_polled = false;
static int g_save_mode = 0;
static void* g_save_user_data = nullptr;
static char g_save_dir_name[sizeof(SaveDataDirName::data)] {};
int KYTY_SYSV_ABI SaveDataDialogInitialize() {
PRINT_NAME();
g_save_status = SAVE_STATUS_INITIALIZED;
g_save_running_polled = false;
g_save_mode = 0;
g_save_user_data = nullptr;
g_save_dir_name[0] = '\0';
return OK;
}
int KYTY_SYSV_ABI SaveDataDialogGetStatus() {
PRINT_NAME();
return g_save_status;
}
int KYTY_SYSV_ABI SaveDataDialogUpdateStatus() {
PRINT_NAME();
// Some games require a RUNNING update before FINISHED.
if (g_save_status == SAVE_STATUS_RUNNING) {
if (g_save_running_polled) {
g_save_status = SAVE_STATUS_FINISHED;
}
g_save_running_polled = true;
}
return g_save_status;
}
int KYTY_SYSV_ABI SaveDataDialogGetResult(void* result) {
PRINT_NAME();
if (result != nullptr) {
auto* r = static_cast<SaveDataDialogResult*>(result);
r->mode = g_save_mode;
r->result = SAVE_RESULT_OK;
r->button_id = SAVE_BUTTON_ID_OK;
r->user_data = g_save_user_data;
if (r->dir_name != nullptr && g_save_dir_name[0] != '\0') {
std::snprintf(static_cast<SaveDataDirName*>(r->dir_name)->data,
sizeof(SaveDataDirName::data), "%s", g_save_dir_name);
}
}
return OK;
}
int KYTY_SYSV_ABI SaveDataDialogOpen(const void* param) {
PRINT_NAME();
const auto* p = static_cast<const SaveDataDialogParam*>(param);
if (p != nullptr) {
g_save_mode = p->mode;
g_save_user_data = p->user_data;
g_save_dir_name[0] = '\0';
LOGF("\t size = %d\n"
"\t mode = %d\n"
"\t disp_type = %d\n"
"\t items = 0x%016" PRIx64 "\n"
"\t user_msg_param = 0x%016" PRIx64 "\n"
"\t sys_msg_param = 0x%016" PRIx64 "\n"
"\t prog_bar_param = 0x%016" PRIx64 "\n"
"\t user_data = 0x%016" PRIx64 "\n",
p->size, p->mode, p->disp_type, reinterpret_cast<uint64_t>(p->items),
reinterpret_cast<uint64_t>(p->user_msg_param),
reinterpret_cast<uint64_t>(p->sys_msg_param),
reinterpret_cast<uint64_t>(p->prog_bar_param),
reinterpret_cast<uint64_t>(p->user_data));
const auto* items = static_cast<const SaveDataDialogItems*>(p->items);
if (items != nullptr && items->dir_names != nullptr) {
for (uint32_t i = 0; i < items->dir_names_num; i++) {
const auto* name = items->dir_names[i].data;
if (name[0] != '\0') {
std::snprintf(g_save_dir_name, sizeof(g_save_dir_name), "%s", name);
break;
}
}
}
}
g_save_status = SAVE_STATUS_RUNNING;
g_save_running_polled = false;
return OK;
}
int KYTY_SYSV_ABI SaveDataDialogClose(const void* close_param) {
PRINT_NAME();
LOGF("\t close_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(close_param));
g_save_status = SAVE_STATUS_FINISHED;
g_save_running_polled = false;
return OK;
}
int KYTY_SYSV_ABI SaveDataDialogIsReadyToDisplay() {
PRINT_NAME();
return 1;
}
int KYTY_SYSV_ABI SaveDataDialogTerminate() {
PRINT_NAME();
g_save_status = SAVE_STATUS_NONE;
g_save_running_polled = false;
g_save_mode = 0;
g_save_user_data = nullptr;
g_save_dir_name[0] = '\0';
return 0;
}
int KYTY_SYSV_ABI SaveDataDialogProgressBarInc(int target, uint32_t delta) {
PRINT_NAME();
LOGF("\t target = %d\n"
"\t delta = %u\n",
target, delta);
return OK;
}
int KYTY_SYSV_ABI SaveDataDialogProgressBarSetValue(int target, uint32_t rate) {
PRINT_NAME();
LOGF("\t target = %d\n"
"\t rate = %u\n",
target, rate);
return OK;
}
} // namespace SaveDataDialog
namespace MsgDialog {
LIB_NAME("MsgDialog.native", "MsgDialog");
constexpr int STATUS_NONE = 0;
constexpr int STATUS_INITIALIZED = 1;
constexpr int STATUS_FINISHED = 3;
constexpr int RESULT_OK = 0;
constexpr int BUTTON_ID_OK = 1;
struct MsgDialogParam {
uint8_t base_param[48];
uint64_t size;
int32_t mode;
uint32_t pad0;
void* user_msg_param;
void* prog_bar_param;
void* sys_msg_param;
int32_t user_id;
uint8_t reserved[40];
uint32_t pad1;
};
struct MsgDialogResult {
int32_t mode;
int32_t result;
int32_t button_id;
uint8_t reserved[32];
};
static int g_status = STATUS_NONE;
static int g_mode = 0;
int KYTY_SYSV_ABI MsgDialogInitialize() {
PRINT_NAME();
g_status = STATUS_INITIALIZED;
g_mode = 0;
return OK;
}
int KYTY_SYSV_ABI MsgDialogOpen(const void* param) {
PRINT_NAME();
const auto* p = static_cast<const MsgDialogParam*>(param);
if (p != nullptr) {
g_mode = p->mode;
LOGF("\t size = 0x%016" PRIx64 "\n"
"\t mode = %d\n"
"\t user_msg_param = 0x%016" PRIx64 "\n"
"\t prog_bar_param = 0x%016" PRIx64 "\n"
"\t sys_msg_param = 0x%016" PRIx64 "\n"
"\t user_id = %d\n",
p->size, p->mode, reinterpret_cast<uint64_t>(p->user_msg_param),
reinterpret_cast<uint64_t>(p->prog_bar_param),
reinterpret_cast<uint64_t>(p->sys_msg_param), p->user_id);
}
g_status = STATUS_FINISHED;
return OK;
}
int KYTY_SYSV_ABI MsgDialogUpdateStatus() {
PRINT_NAME();
return g_status;
}
int KYTY_SYSV_ABI MsgDialogGetStatus() {
PRINT_NAME();
return g_status;
}
int KYTY_SYSV_ABI MsgDialogGetResult(void* result) {
PRINT_NAME();
if (result != nullptr) {
auto* r = static_cast<MsgDialogResult*>(result);
r->mode = g_mode;
r->result = RESULT_OK;
r->button_id = BUTTON_ID_OK;
}
return OK;
}
int KYTY_SYSV_ABI MsgDialogTerminate() {
PRINT_NAME();
g_status = STATUS_NONE;
g_mode = 0;
return OK;
}
int KYTY_SYSV_ABI MsgDialogClose() {
PRINT_NAME();
g_status = STATUS_FINISHED;
return OK;
}
int KYTY_SYSV_ABI MsgDialogProgressBarInc(int target, uint32_t delta) {
PRINT_NAME();
LOGF("\t target = %d\n"
"\t delta = %u\n",
target, delta);
return OK;
}
int KYTY_SYSV_ABI MsgDialogProgressBarSetValue(int target, uint32_t rate) {
PRINT_NAME();
LOGF("\t target = %d\n"
"\t rate = %u\n",
target, rate);
return OK;
}
int KYTY_SYSV_ABI MsgDialogProgressBarSetMsg(int target, const char* msg) {
PRINT_NAME();
LOGF("\t target = %d\n"
"\t msg = 0x%016" PRIx64 "\n",
target, reinterpret_cast<uint64_t>(msg));
return OK;
}
} // namespace MsgDialog
namespace ErrorDialog {
LIB_NAME("ErrorDialog", "ErrorDialog");
constexpr int STATUS_NONE = 0;
constexpr int STATUS_INITIALIZED = 1;
constexpr int STATUS_RUNNING = 2;
constexpr int STATUS_FINISHED = 3;
constexpr int ERROR_NOT_INITIALIZED = static_cast<int>(0x80ed0001);
constexpr int ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80ed0002);
constexpr int ERROR_PARAM_INVALID = static_cast<int>(0x80ed0003);
constexpr int ERROR_INVALID_STATE = static_cast<int>(0x80ed0005);
struct ErrorDialogParam {
int32_t size;
int32_t error_code;
int32_t user_id;
int32_t reserved;
};
static_assert(sizeof(ErrorDialogParam) == 16);
static std::mutex g_error_mutex;
static int g_error_status = STATUS_NONE;
static uint64_t g_error_generation = 0;
static uint64_t g_error_revision = 0;
static int32_t g_error_code = 0;
static void (*g_error_visibility_callback)() = nullptr;
static void SetStatus(int status, std::unique_lock<std::mutex>& lock) {
const bool visibility_changed =
(g_error_status == STATUS_RUNNING) != (status == STATUS_RUNNING);
g_error_status = status;
if (visibility_changed) {
g_error_revision++;
}
const auto callback = visibility_changed ? g_error_visibility_callback : nullptr;
lock.unlock();
if (callback != nullptr) {
callback();
}
}
bool GetHostSnapshot(HostSnapshot* snapshot) {
std::scoped_lock lock(g_error_mutex);
if (g_error_status != STATUS_RUNNING) {
return false;
}
*snapshot = {g_error_generation, g_error_code};
return true;
}
VisualState GetVisualState() noexcept {
std::scoped_lock lock(g_error_mutex);
return {g_error_status == STATUS_RUNNING, g_error_revision};
}
void SetVisibilityCallback(void (*callback)()) {
std::scoped_lock lock(g_error_mutex);
g_error_visibility_callback = callback;
}
bool HostAccept(uint64_t generation) {
std::unique_lock lock(g_error_mutex);
if (g_error_status != STATUS_RUNNING || generation != g_error_generation) {
return false;
}
SetStatus(STATUS_FINISHED, lock);
return true;
}
int KYTY_SYSV_ABI ErrorDialogInitialize() {
PRINT_NAME();
std::scoped_lock lock(g_error_mutex);
if (g_error_status != STATUS_NONE) {
return ERROR_ALREADY_INITIALIZED;
}
g_error_status = STATUS_INITIALIZED;
return OK;
}
int KYTY_SYSV_ABI ErrorDialogOpen(const void* param) {
PRINT_NAME();
std::unique_lock lock(g_error_mutex);
if (g_error_status != STATUS_INITIALIZED && g_error_status != STATUS_FINISHED) {
return ERROR_INVALID_STATE;
}
if (param == nullptr) {
return ERROR_PARAM_INVALID;
}
const auto* p = static_cast<const ErrorDialogParam*>(param);
if (p->size != sizeof(ErrorDialogParam)) {
return ERROR_PARAM_INVALID;
}
LOGF("\t size = %d\n"
"\t error_code = 0x%08" PRIx32 "\n"
"\t user_id = %d\n",
p->size, static_cast<uint32_t>(p->error_code), p->user_id);
g_error_code = p->error_code;
g_error_generation++;
SetStatus(STATUS_RUNNING, lock);
return OK;
}
int KYTY_SYSV_ABI ErrorDialogClose() {
PRINT_NAME();
std::unique_lock lock(g_error_mutex);
if (g_error_status != STATUS_RUNNING) {
return ERROR_INVALID_STATE;
}
SetStatus(STATUS_FINISHED, lock);
return OK;
}
int KYTY_SYSV_ABI ErrorDialogTerminate() {
PRINT_NAME();
std::unique_lock lock(g_error_mutex);
if (g_error_status == STATUS_NONE) {
return ERROR_NOT_INITIALIZED;
}
SetStatus(STATUS_NONE, lock);
return OK;
}
int KYTY_SYSV_ABI ErrorDialogUpdateStatus() {
PRINT_NAME();
std::scoped_lock lock(g_error_mutex);
return g_error_status;
}
int KYTY_SYSV_ABI ErrorDialogGetStatus() {
PRINT_NAME();
std::scoped_lock lock(g_error_mutex);
return g_error_status;
}
} // namespace ErrorDialog
} // namespace Libs::Dialog