mirror of
https://github.com/Vita3K/Vita3K.git
synced 2025-04-02 11:02:10 -04:00
303 lines
9 KiB
C++
303 lines
9 KiB
C++
// Vita3K emulator project
|
|
// Copyright (C) 2025 Vita3K team
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
#include "SceProcessmgr.h"
|
|
|
|
#include <io/functions.h>
|
|
#include <kernel/state.h>
|
|
#include <rtc/rtc.h>
|
|
|
|
#include <util/safe_time.h>
|
|
|
|
#include <util/tracy.h>
|
|
TRACY_MODULE_NAME(SceProcessmgr);
|
|
|
|
template <>
|
|
std::string to_debug_str<SceKernelPowerTickType>(const MemState &mem, SceKernelPowerTickType type) {
|
|
switch (type) {
|
|
case SCE_KERNEL_POWER_TICK_DEFAULT: return "SCE_KERNEL_POWER_TICK_DEFAULT";
|
|
case SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND: return "SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND";
|
|
case SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF: return "SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF";
|
|
case SCE_KERNEL_POWER_TICK_DISABLE_OLED_DIMMING: return "SCE_KERNEL_POWER_TICK_DISABLE_OLED_DIMMING";
|
|
}
|
|
return std::to_string(type);
|
|
}
|
|
|
|
struct VitaTimeval {
|
|
uint32_t tv_sec;
|
|
uint32_t tv_usec;
|
|
};
|
|
struct VitaTimezone {
|
|
int tz_minuteswest;
|
|
int tz_dsttime;
|
|
};
|
|
|
|
using VitaTime = uint32_t;
|
|
struct VitaTM {
|
|
int tm_sec;
|
|
int tm_min;
|
|
int tm_hour;
|
|
int tm_mday;
|
|
int tm_mon;
|
|
int tm_year;
|
|
int tm_wday;
|
|
int tm_yday;
|
|
int tm_isdst;
|
|
};
|
|
|
|
static_assert(sizeof(VitaTM) == 36);
|
|
static_assert(sizeof(VitaTM) <= sizeof(struct tm));
|
|
|
|
struct SceLibkernelAddresses {
|
|
uint32_t size;
|
|
Ptr<void> sceKernelExitThread;
|
|
Ptr<void> sceKernelExitDeleteThread;
|
|
Ptr<void> _sceKernelExitCallback;
|
|
Ptr<void> field_0x10;
|
|
Ptr<void> field_0x14;
|
|
Ptr<void> field_0x18;
|
|
};
|
|
|
|
EXPORT(int, _sceKernelExitProcessForUser) {
|
|
TRACY_FUNC(_sceKernelExitProcessForUser);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, _sceKernelGetTimer5Reg, Ptr<uint64_t> *timer) {
|
|
TRACY_FUNC(_sceKernelGetTimer5Reg, timer);
|
|
*timer = alloc<uint64_t>(emuenv.mem, "timer5reg");
|
|
*(*timer).get(emuenv.mem) = rtc_get_ticks(emuenv.kernel.base_tick.tick);
|
|
return SCE_KERNEL_OK;
|
|
}
|
|
|
|
EXPORT(int, _sceKernelRegisterLibkernelAddresses, SceLibkernelAddresses *addresses) {
|
|
TRACY_FUNC(_sceKernelRegisterLibkernelAddresses, addresses);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelCDialogSessionClose) {
|
|
TRACY_FUNC(sceKernelCDialogSessionClose);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelCDialogSetLeaseLimit) {
|
|
TRACY_FUNC(sceKernelCDialogSetLeaseLimit);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelCallAbortHandler, uint32_t param1, uint32_t param2) {
|
|
TRACY_FUNC(sceKernelCallAbortHandler, param1, param2);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetCurrentProcess) {
|
|
TRACY_FUNC(sceKernelGetCurrentProcess);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetExtraTty) {
|
|
TRACY_FUNC(sceKernelGetExtraTty);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetProcessName, char *process_name, uint32_t len) {
|
|
TRACY_FUNC(sceKernelGetProcessName, process_name, len);
|
|
if (!process_name || len > 32 || len == 0)
|
|
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT);
|
|
strncpy(process_name, emuenv.kernel.process_param.get(emuenv.mem)->process_name.get(emuenv.mem), len);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(Ptr<SceProcessParam>, sceKernelGetProcessParam, void *args) {
|
|
TRACY_FUNC(sceKernelGetProcessParam, args);
|
|
return emuenv.kernel.process_param;
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetProcessTimeCore) {
|
|
TRACY_FUNC(sceKernelGetProcessTimeCore);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetProcessTimeLowCore) {
|
|
TRACY_FUNC(sceKernelGetProcessTimeLowCore);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetProcessTimeWideCore) {
|
|
TRACY_FUNC(sceKernelGetProcessTimeWideCore);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetProcessTitleId, char *title_id, uint32_t len) {
|
|
TRACY_FUNC(sceKernelGetProcessTitleId, title_id, len);
|
|
if (!title_id || len > 32 || len == 0)
|
|
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT);
|
|
strncpy(title_id, emuenv.io.title_id.c_str(), len);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetRemoteProcessTime) {
|
|
TRACY_FUNC(sceKernelGetRemoteProcessTime);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetStderr) {
|
|
TRACY_FUNC(sceKernelGetStderr);
|
|
return open_file(emuenv.io, "tty0:", SCE_O_WRONLY, emuenv.pref_path, export_name);
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetStdin) {
|
|
TRACY_FUNC(sceKernelGetStdin);
|
|
return open_file(emuenv.io, "tty0:", SCE_O_RDONLY, emuenv.pref_path, export_name);
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetStdout) {
|
|
TRACY_FUNC(sceKernelGetStdout);
|
|
return open_file(emuenv.io, "tty0:", SCE_O_WRONLY, emuenv.pref_path, export_name);
|
|
}
|
|
|
|
EXPORT(int, sceKernelIsCDialogAvailable) {
|
|
TRACY_FUNC(sceKernelIsCDialogAvailable);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelIsGameBudget) {
|
|
TRACY_FUNC(sceKernelIsGameBudget);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(VitaTime, sceKernelLibcClock) {
|
|
TRACY_FUNC(sceKernelLibcClock);
|
|
return static_cast<VitaTime>(rtc_get_ticks(emuenv.kernel.base_tick.tick) - emuenv.kernel.start_tick);
|
|
}
|
|
|
|
EXPORT(int, sceKernelLibcGettimeofday, VitaTimeval *timeAddr, VitaTimezone *tzAddr) {
|
|
TRACY_FUNC(sceKernelLibcGettimeofday, timeAddr, tzAddr);
|
|
const auto ticks = rtc_get_ticks(emuenv.kernel.base_tick.tick) - RTC_OFFSET;
|
|
if (timeAddr != nullptr) {
|
|
timeAddr->tv_sec = static_cast<std::uint32_t>(ticks / VITA_CLOCKS_PER_SEC);
|
|
timeAddr->tv_usec = ticks % VITA_CLOCKS_PER_SEC;
|
|
}
|
|
if (tzAddr != nullptr) {
|
|
std::time_t t = std::time(nullptr);
|
|
|
|
tm localtime_tm = {};
|
|
|
|
SAFE_LOCALTIME(&t, &localtime_tm);
|
|
std::time_t lt = mktime(&localtime_tm);
|
|
tzAddr->tz_minuteswest = static_cast<int>((lt - t) / 60);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(Ptr<VitaTM>, sceKernelLibcGmtime_r, const VitaTime *time, Ptr<VitaTM> date) {
|
|
TRACY_FUNC(sceKernelLibcGmtime_r, time, date);
|
|
const time_t plat_time = *time;
|
|
|
|
auto dateIn = date.get(emuenv.mem);
|
|
|
|
tm host_tm = {};
|
|
SAFE_GMTIME(&plat_time, &host_tm);
|
|
memcpy(dateIn, &host_tm, sizeof(VitaTM));
|
|
|
|
return date;
|
|
}
|
|
|
|
EXPORT(Ptr<VitaTM>, sceKernelLibcLocaltime_r, const VitaTime *time, Ptr<VitaTM> date) {
|
|
TRACY_FUNC(sceKernelLibcLocaltime_r, time, date);
|
|
const time_t plat_time = *time;
|
|
auto dateIn = date.get(emuenv.mem);
|
|
|
|
tm host_tm = {};
|
|
SAFE_LOCALTIME(&plat_time, &host_tm);
|
|
memcpy(dateIn, &host_tm, sizeof(VitaTM));
|
|
|
|
return date;
|
|
}
|
|
|
|
EXPORT(int, sceKernelLibcMktime, VitaTM *date, VitaTime *time, uint64_t *param_3) {
|
|
TRACY_FUNC(sceKernelLibcMktime, date, time);
|
|
// param_3 - result, 8 bytes, unused
|
|
if (!date) {
|
|
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT);
|
|
}
|
|
bool year_1900 = false;
|
|
if (date->tm_year >= 1900) {
|
|
date->tm_year -= 1900;
|
|
year_1900 = true;
|
|
}
|
|
tm host_tm = {};
|
|
// Copy the input date to host_tm and use that on mktime instead of the input directly
|
|
// to avoid stack corruption on systems where tm size is different
|
|
memcpy(&host_tm, date, sizeof(VitaTM));
|
|
auto time_local = mktime(&host_tm);
|
|
memcpy(date, &host_tm, sizeof(VitaTM));
|
|
if (year_1900) {
|
|
date->tm_year += 1900;
|
|
}
|
|
if (time)
|
|
*time = static_cast<VitaTime>(time_local);
|
|
if (param_3)
|
|
*param_3 = time_local;
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(VitaTime, sceKernelLibcTime, VitaTime *time) {
|
|
TRACY_FUNC(sceKernelLibcTime, time);
|
|
const auto secs = (rtc_get_ticks(emuenv.kernel.base_tick.tick) - RTC_OFFSET) / VITA_CLOCKS_PER_SEC;
|
|
|
|
if (time) {
|
|
*time = static_cast<VitaTime>(secs);
|
|
}
|
|
|
|
return static_cast<VitaTime>(secs);
|
|
}
|
|
|
|
EXPORT(int, sceKernelPowerLock) {
|
|
TRACY_FUNC(sceKernelPowerLock);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelPowerTick, SceKernelPowerTickType type) {
|
|
TRACY_FUNC(sceKernelPowerTick, type);
|
|
return SCE_KERNEL_OK;
|
|
}
|
|
|
|
EXPORT(int, sceKernelPowerUnlock) {
|
|
TRACY_FUNC(sceKernelPowerUnlock);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelRegisterProcessTerminationCallback) {
|
|
TRACY_FUNC(sceKernelRegisterProcessTerminationCallback);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelUnregisterProcessTerminationCallback) {
|
|
TRACY_FUNC(sceKernelUnregisterProcessTerminationCallback);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceKernelGetMainModuleSdkVersion) {
|
|
TRACY_FUNC(sceKernelGetMainModuleSdkVersion);
|
|
SceProcessParam *process_param = emuenv.kernel.process_param.get(emuenv.mem);
|
|
if (process_param && (process_param->magic == '2PSP') && (process_param->version != 0)) {
|
|
return process_param->fw_version;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|