Merge pull request #37 from georgemoralis/video_event_queue
Video event queue
This commit is contained in:
commit
c2453f6ae9
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
constexpr int SCE_OK = 0;
|
constexpr int SCE_OK = 0;
|
||||||
|
|
||||||
constexpr int SCE_KERNEL_ERROR_EBADF = 0x80020009;
|
constexpr int SCE_KERNEL_ERROR_EBADF = 0x80020009;
|
||||||
constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c; // Insufficient memory
|
constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c; // Insufficient memory
|
||||||
constexpr int SCE_KERNEL_ERROR_EFAULT = 0x8002000e; // Invalid address pointer
|
constexpr int SCE_KERNEL_ERROR_EFAULT = 0x8002000e; // Invalid address pointer
|
||||||
constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; // null or invalid states
|
constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; // null or invalid states
|
||||||
|
@ -11,5 +11,7 @@ constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003f; // character strings
|
||||||
// videoOut
|
// videoOut
|
||||||
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument
|
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument
|
||||||
constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened
|
constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened
|
||||||
|
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_INDEX = 0x8029000A; // invalid buffer index
|
||||||
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle
|
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle
|
||||||
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue
|
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue
|
||||||
|
constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "video_out_ctx.h"
|
#include "video_out_ctx.h"
|
||||||
|
|
||||||
|
#include <Core/PS4/HLE/LibKernel.h>
|
||||||
|
|
||||||
namespace HLE::Graphics::Objects {
|
namespace HLE::Graphics::Objects {
|
||||||
|
|
||||||
void VideoOutCtx::Init(u32 width, u32 height) {
|
void VideoOutCtx::Init(u32 width, u32 height) {
|
||||||
|
@ -29,7 +31,7 @@ int VideoOutCtx::Open() {
|
||||||
|
|
||||||
VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
|
VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
|
||||||
if (handle != 1) return nullptr;
|
if (handle != 1) return nullptr;
|
||||||
return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more
|
return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) {
|
void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) {
|
||||||
|
@ -38,5 +40,64 @@ void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* o
|
||||||
*out = cfg->m_flip_status;
|
*out = cfg->m_flip_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace HLE::Graphics::Objects
|
bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
|
||||||
|
Lib::LockMutexGuard lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_requests.size() >= 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request r{};
|
||||||
|
r.cfg = cfg;
|
||||||
|
r.index = index;
|
||||||
|
r.flip_arg = flip_arg;
|
||||||
|
r.submit_tsc = HLE::Libs::LibKernel::sceKernelReadTsc();
|
||||||
|
|
||||||
|
m_requests.push_back(r);
|
||||||
|
|
||||||
|
cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
||||||
|
cfg->m_flip_status.gcQueueNum = 0;
|
||||||
|
|
||||||
|
m_submit_cond.SignalCondVar();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlipQueue::flip(u32 micros) {
|
||||||
|
m_mutex.LockMutex();
|
||||||
|
if (m_requests.size() == 0) {
|
||||||
|
m_submit_cond.WaitCondVarFor(&m_mutex, micros);
|
||||||
|
|
||||||
|
if (m_requests.size() == 0) {
|
||||||
|
m_mutex.UnlockMutex();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto request = m_requests.at(0); // proceed first request
|
||||||
|
m_mutex.UnlockMutex();
|
||||||
|
|
||||||
|
request.cfg->m_mutex.LockMutex();
|
||||||
|
for (auto& flip_eq : request.cfg->m_flip_evtEq) {
|
||||||
|
if (flip_eq != nullptr) {
|
||||||
|
flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, HLE::Kernel::Objects::EVFILT_VIDEO_OUT, reinterpret_cast<void*>(request.flip_arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.cfg->m_mutex.UnlockMutex();
|
||||||
|
|
||||||
|
m_requests.erase(m_requests.begin());
|
||||||
|
m_done_cond.SignalCondVar();
|
||||||
|
|
||||||
|
request.cfg->m_flip_status.count++;
|
||||||
|
//TODO request.cfg->m_flip_status.processTime = LibKernel::KernelGetProcessTime();
|
||||||
|
request.cfg->m_flip_status.tsc = HLE::Libs::LibKernel::sceKernelReadTsc();
|
||||||
|
request.cfg->m_flip_status.submitTsc = request.submit_tsc;
|
||||||
|
request.cfg->m_flip_status.flipArg = request.flip_arg;
|
||||||
|
request.cfg->m_flip_status.currentBuffer = request.index;
|
||||||
|
request.cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
|
||||||
|
|
||||||
|
m_mutex.UnlockMutex();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace HLE::Graphics::Objects
|
||||||
|
|
|
@ -24,9 +24,20 @@ class FlipQueue {
|
||||||
virtual ~FlipQueue() {}
|
virtual ~FlipQueue() {}
|
||||||
|
|
||||||
void getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out);
|
void getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out);
|
||||||
|
bool submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg);
|
||||||
|
bool flip(u32 micros);
|
||||||
private:
|
private:
|
||||||
|
struct Request {
|
||||||
|
VideoConfigInternal* cfg;
|
||||||
|
int index;
|
||||||
|
int64_t flip_arg;
|
||||||
|
uint64_t submit_tsc;
|
||||||
|
};
|
||||||
|
|
||||||
Lib::Mutex m_mutex;
|
Lib::Mutex m_mutex;
|
||||||
|
Lib::ConditionVariable m_submit_cond;
|
||||||
|
Lib::ConditionVariable m_done_cond;
|
||||||
|
std::vector<Request> m_requests;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VideoOutCtx {
|
class VideoOutCtx {
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
#include <magic_enum.hpp>
|
#include <magic_enum.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Objects/video_out_ctx.h"
|
|
||||||
|
|
||||||
|
#include "Objects/video_out_ctx.h"
|
||||||
#include "Util/Singleton.h"
|
#include "Util/Singleton.h"
|
||||||
|
|
||||||
namespace HLE::Libs::Graphics::VideoOut {
|
namespace HLE::Libs::Graphics::VideoOut {
|
||||||
|
@ -21,6 +21,12 @@ void videoOutInit(u32 width, u32 height) {
|
||||||
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
||||||
videoOut->Init(width, height);
|
videoOut->Init(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool videoOutFlip(u32 micros) {
|
||||||
|
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
||||||
|
return videoOut->getFlipQueue().flip(micros);
|
||||||
|
}
|
||||||
|
|
||||||
std::string getPixelFormatString(s32 format) {
|
std::string getPixelFormatString(s32 format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case SCE_VIDEO_OUT_PIXEL_FORMAT_A8R8G8B8_SRGB: return "PIXEL_FORMAT_A8R8G8B8_SRGB";
|
case SCE_VIDEO_OUT_PIXEL_FORMAT_A8R8G8B8_SRGB: return "PIXEL_FORMAT_A8R8G8B8_SRGB";
|
||||||
|
@ -59,6 +65,20 @@ void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attr
|
||||||
attribute->option = SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_NONE;
|
attribute->option = SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void flip_reset_event_func(HLE::Kernel::Objects::EqueueEvent* event) {
|
||||||
|
event->isTriggered = false;
|
||||||
|
event->event.fflags = 0;
|
||||||
|
event->event.data = 0;
|
||||||
|
}
|
||||||
|
static void flip_trigger_event_func(HLE::Kernel::Objects::EqueueEvent* event, void* trigger_data) {
|
||||||
|
event->isTriggered = true;
|
||||||
|
event->event.fflags++;
|
||||||
|
event->event.data = reinterpret_cast<intptr_t>(trigger_data);
|
||||||
|
}
|
||||||
|
static void flip_delete_event_func(LibKernel::EventQueues::SceKernelEqueue eq, HLE::Kernel::Objects::EqueueEvent* event) {
|
||||||
|
BREAKPOINT(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue eq, s32 handle, void* udata) {
|
s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue eq, s32 handle, void* udata) {
|
||||||
PRINT_FUNCTION_NAME();
|
PRINT_FUNCTION_NAME();
|
||||||
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
||||||
|
@ -81,9 +101,9 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue
|
||||||
event.event.udata = udata;
|
event.event.udata = udata;
|
||||||
event.event.fflags = 0;
|
event.event.fflags = 0;
|
||||||
event.event.data = 0;
|
event.event.data = 0;
|
||||||
// event.filter.delete_event_func = flip_event_delete_func;//called in sceKernelDeleteEvent //TODO
|
event.filter.delete_event_func = flip_delete_event_func;
|
||||||
// event.filter.reset_event_func = flip_event_reset_func;//called in sceKernelWaitEqueue //TODO
|
event.filter.reset_event_func = flip_reset_event_func;
|
||||||
// event.filter.trigger_event_func = flip_event_trigger_func;//called in sceKernelTriggerEvent //TODO
|
event.filter.trigger_event_func = flip_trigger_event_func;
|
||||||
event.filter.data = ctx;
|
event.filter.data = ctx;
|
||||||
|
|
||||||
int result = eq->addEvent(event);
|
int result = eq->addEvent(event);
|
||||||
|
@ -111,9 +131,30 @@ s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg) {
|
s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg) {
|
||||||
// BREAKPOINT();
|
PRINT_FUNCTION_NAME();
|
||||||
PRINT_DUMMY_FUNCTION_NAME();
|
auto* videoOut = Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
|
||||||
return 0;
|
auto* ctx = videoOut->getCtx(handle);
|
||||||
|
|
||||||
|
if (flipMode != 1) {
|
||||||
|
BREAKPOINT(); // only flipmode==1 is supported
|
||||||
|
}
|
||||||
|
if (bufferIndex == -1) {
|
||||||
|
BREAKPOINT(); // blank output not supported
|
||||||
|
}
|
||||||
|
if (bufferIndex < -1 || bufferIndex > 15) {
|
||||||
|
LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip invalid bufferIndex {}\n", bufferIndex);
|
||||||
|
return SCE_VIDEO_OUT_ERROR_INVALID_INDEX;
|
||||||
|
}
|
||||||
|
LOG_INFO_IF(log_file_videoout, "bufferIndex = {}\n", bufferIndex);
|
||||||
|
LOG_INFO_IF(log_file_videoout, "flipMode = {}\n", flipMode);
|
||||||
|
LOG_INFO_IF(log_file_videoout, "flipArg = {}\n", flipArg);
|
||||||
|
|
||||||
|
if (!videoOut->getFlipQueue().submitFlip(ctx, bufferIndex, flipArg)) {
|
||||||
|
LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flip queue is full\n");
|
||||||
|
return SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, SceVideoOutFlipStatus* status) {
|
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, SceVideoOutFlipStatus* status) {
|
||||||
PRINT_FUNCTION_NAME();
|
PRINT_FUNCTION_NAME();
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct SceVideoOutVblankStatus {
|
||||||
void videoOutInit(u32 width, u32 height);
|
void videoOutInit(u32 width, u32 height);
|
||||||
std::string getPixelFormatString(s32 format);
|
std::string getPixelFormatString(s32 format);
|
||||||
void videoOutRegisterLib(SymbolsResolver* sym);
|
void videoOutRegisterLib(SymbolsResolver* sym);
|
||||||
|
bool videoOutFlip(u32 micros);
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute, u32 pixelFormat, u32 tilingMode, u32 aspectRatio, u32 width,
|
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute, u32 pixelFormat, u32 tilingMode, u32 aspectRatio, u32 width,
|
||||||
u32 height, u32 pitchInPixel);
|
u32 height, u32 pitchInPixel);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "event_queue.h"
|
#include "event_queue.h"
|
||||||
|
|
||||||
|
#include <Lib/Timer.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
namespace HLE::Kernel::Objects {
|
namespace HLE::Kernel::Objects {
|
||||||
|
@ -21,4 +23,70 @@ int EqueueInternal::addEvent(const EqueueEvent& event) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||||
|
Lib::LockMutexGuard lock(m_mutex);
|
||||||
|
|
||||||
|
u32 timeElapsed = 0;
|
||||||
|
Lib::Timer t;
|
||||||
|
t.Start();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int ret = getTriggeredEvents(ev, num);
|
||||||
|
|
||||||
|
if (ret > 0 || (timeElapsed >= micros && micros != 0)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (micros == 0) {
|
||||||
|
m_cond.WaitCondVar(&m_mutex);
|
||||||
|
} else {
|
||||||
|
m_cond.WaitCondVarFor(&m_mutex, micros - timeElapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeElapsed = static_cast<uint32_t>(t.GetTimeSec() * 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
||||||
|
Lib::LockMutexGuard lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_events.size() > 1) {
|
||||||
|
BREAKPOINT(); // we currently support one event
|
||||||
|
}
|
||||||
|
auto& event = m_events[0];
|
||||||
|
|
||||||
|
if (event.filter.trigger_event_func != nullptr) {
|
||||||
|
event.filter.trigger_event_func(&event, trigger_data);
|
||||||
|
} else {
|
||||||
|
event.isTriggered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cond.SignalCondVar();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) {
|
||||||
|
Lib::LockMutexGuard lock(m_mutex);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (m_events.size() > 1) {
|
||||||
|
BREAKPOINT(); // we currently support one event
|
||||||
|
}
|
||||||
|
auto& event = m_events[0];
|
||||||
|
|
||||||
|
if (event.isTriggered) {
|
||||||
|
ev[ret++] = event.event;
|
||||||
|
|
||||||
|
if (event.filter.reset_event_func != nullptr) {
|
||||||
|
event.filter.reset_event_func(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace HLE::Kernel::Objects
|
}; // namespace HLE::Kernel::Objects
|
|
@ -50,7 +50,7 @@ struct SceKernelEvent {
|
||||||
struct Filter {
|
struct Filter {
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
TriggerFunc trigger_event_func = nullptr;
|
TriggerFunc trigger_event_func = nullptr;
|
||||||
ResetFunc reset__event_func = nullptr;
|
ResetFunc reset_event_func = nullptr;
|
||||||
DeleteFunc delete_event_func = nullptr;
|
DeleteFunc delete_event_func = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,9 +66,13 @@ class EqueueInternal {
|
||||||
virtual ~EqueueInternal();
|
virtual ~EqueueInternal();
|
||||||
void setName(const std::string& m_name) { this->m_name = m_name; }
|
void setName(const std::string& m_name) { this->m_name = m_name; }
|
||||||
int addEvent(const EqueueEvent& event);
|
int addEvent(const EqueueEvent& event);
|
||||||
|
int waitForEvents(SceKernelEvent* ev, int num, u32 micros);
|
||||||
|
bool triggerEvent(u64 ident, s16 filter, void* trigger_data);
|
||||||
|
int getTriggeredEvents(SceKernelEvent* ev, int num);
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
Lib::Mutex m_mutex;
|
Lib::Mutex m_mutex;
|
||||||
std::vector<EqueueEvent> m_events;
|
std::vector<EqueueEvent> m_events;
|
||||||
|
Lib::ConditionVariable m_cond;
|
||||||
};
|
};
|
||||||
}; // namespace HLE::Kernel::Objects
|
}; // namespace HLE::Kernel::Objects
|
|
@ -51,7 +51,7 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, HLE::Kernel::Objects::S
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
if (timo == nullptr) { // wait until an event arrives without timing out
|
if (timo == nullptr) { // wait until an event arrives without timing out
|
||||||
// BREAKPOINT();//NOT supported yet TODO
|
*out = eq->waitForEvents(ev, num, 0);
|
||||||
}
|
}
|
||||||
if (timo != nullptr) {
|
if (timo != nullptr) {
|
||||||
if (*timo == 0) {//only events that have already arrived at the time of this function call can be received
|
if (*timo == 0) {//only events that have already arrived at the time of this function call can be received
|
||||||
|
|
|
@ -21,6 +21,11 @@ namespace HLE::Libs::LibKernel {
|
||||||
|
|
||||||
static PS4_SYSV_ABI void stack_chk_fail() { BREAKPOINT();
|
static PS4_SYSV_ABI void stack_chk_fail() { BREAKPOINT();
|
||||||
}
|
}
|
||||||
|
u64 PS4_SYSV_ABI sceKernelReadTsc() {
|
||||||
|
LARGE_INTEGER c;
|
||||||
|
QueryPerformanceCounter(&c);
|
||||||
|
return c.QuadPart;
|
||||||
|
}
|
||||||
void LibKernel_Register(SymbolsResolver* sym) {
|
void LibKernel_Register(SymbolsResolver* sym) {
|
||||||
//obj
|
//obj
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &HLE::Libs::LibKernel::g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &HLE::Libs::LibKernel::g_stack_chk_guard);
|
||||||
|
@ -35,6 +40,8 @@ namespace HLE::Libs::LibKernel {
|
||||||
//misc
|
//misc
|
||||||
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, CPUManagement::sceKernelIsNeoMode);
|
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, CPUManagement::sceKernelIsNeoMode);
|
||||||
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
||||||
|
//time
|
||||||
|
LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
|
@ -6,6 +6,6 @@ void LibKernel_Register(SymbolsResolver* sym);
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
|
|
||||||
|
u64 PS4_SYSV_ABI sceKernelReadTsc();
|
||||||
int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len);
|
int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len);
|
||||||
}; // namespace HLE::Libs::LibKernel
|
}; // namespace HLE::Libs::LibKernel
|
|
@ -1,9 +1,11 @@
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
|
#include "Core/PS4/HLE/Graphics/video_out.h"
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
void emuInit() {}
|
void emuInit() {}
|
||||||
void emuRun() {
|
void emuRun() {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
HLE::Libs::Graphics::VideoOut::videoOutFlip(100000);//flip every 0.1 sec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace emulator
|
} // namespace emulator
|
Loading…
Reference in New Issue