Merge branch 'main' into user_and_settings

This commit is contained in:
georgemoralis 2026-02-15 10:31:05 +02:00 committed by GitHub
commit a9df50cc9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 101 additions and 67 deletions

View File

@ -227,6 +227,8 @@ find_package(fmt 10.2.0 CONFIG)
find_package(glslang 15 CONFIG)
find_package(half 1.12.0 MODULE)
find_package(magic_enum 0.9.7 CONFIG)
find_package(miniz 3.1 CONFIG)
find_package(nlohmann_json 3.12 CONFIG)
find_package(PNG 1.6 MODULE)
find_package(OpenAL CONFIG)
find_package(RenderDoc 1.6.0 MODULE)
@ -1120,7 +1122,7 @@ create_target_directory_groups(shadps4)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz::miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")

View File

@ -73,6 +73,8 @@ You can configure the emulator by editing the `config.toml` file found in the `u
- Examples:
- If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages.
- If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Critical Render.Vulkan:Info`
- `isIdenticalLogGrouped`: Group same logs in one line with a counter (`true`/`false`)
- By default, the emulator will not rewrite the same line, and instead add a counter.
- `Fullscreen`: Display the game in a full screen borderless window.

View File

@ -259,16 +259,19 @@ if (WIN32)
add_subdirectory(ext-wepoll)
endif()
if (NOT TARGET fdk-aac)
add_subdirectory(aacdec)
endif()
#nlohmann json
if (NOT TARGET nlohmann_json::nlohmann_json)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(json)
endif()
# miniz
if (NOT TARGET miniz::miniz)
add_subdirectory(miniz)
add_library(miniz::miniz ALIAS miniz)
endif()
# cli11
if (NOT TARGET CLI11::CLI11)

View File

@ -211,41 +211,62 @@ public:
}
}
std::unique_lock entry_loc(_mutex);
if (_last_entry.message == message) {
++_last_entry.counter;
return;
}
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (EmulatorSettings::GetInstance()->GetLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::steady_clock;
this->_last_entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
if (Config::groupIdenticalLogs()) {
std::unique_lock entry_loc(_mutex);
if (_last_entry.message == message) {
++_last_entry.counter;
return;
}
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
this->_last_entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
} else {
const Entry entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(entry);
} else {
ForEachBackend([&entry](auto& backend) { backend.Write(entry); });
std::fflush(stdout);
}
}
}
private:
@ -277,21 +298,23 @@ private:
}
void StopBackendThread() {
// log last message
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (EmulatorSettings::GetInstance()->GetLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
if (Config::groupIdenticalLogs()) {
// log last message
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
}
this->_last_entry = {};
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
this->_last_entry = {};
}
backend_thread.request_stop();
if (backend_thread.joinable()) {

View File

@ -2053,7 +2053,7 @@ int PS4_SYSV_ABI sceGnmSqttWaitForEvent() {
}
static inline s32 PatchFlipRequest(u32* cmdbuf, u32 size, u32 vo_handle, u32 buf_idx, u32 flip_mode,
u32 flip_arg, void* unk) {
s64 flip_arg, void* unk) {
// check for `prepareFlip` packet
cmdbuf += size - 64;
ASSERT_MSG(cmdbuf[0] == 0xc03e1000, "Can't find `prepareFlip` packet");
@ -2139,7 +2139,7 @@ static inline s32 PatchFlipRequest(u32* cmdbuf, u32 size, u32 vo_handle, u32 buf
s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, u32* dcb_gpu_addrs[],
u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes, u32 vo_handle,
u32 buf_idx, u32 flip_mode, u32 flip_arg) {
u32 buf_idx, u32 flip_mode, s64 flip_arg) {
return sceGnmSubmitAndFlipCommandBuffersForWorkload(
count, count, dcb_gpu_addrs, dcb_sizes_in_bytes, ccb_gpu_addrs, ccb_sizes_in_bytes,
vo_handle, buf_idx, flip_mode, flip_arg);
@ -2147,7 +2147,7 @@ s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, u32* dcb_gpu_addrs
s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffersForWorkload(
u32 workload, u32 count, u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg) {
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, s64 flip_arg) {
LOG_DEBUG(Lib_GnmDriver, "called [buf = {}]", buf_idx);
auto* cmdbuf = dcb_gpu_addrs[count - 1];

View File

@ -211,10 +211,10 @@ int PS4_SYSV_ABI sceGnmSqttWaitForEvent();
s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, u32* dcb_gpu_addrs[],
u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes, u32 vo_handle,
u32 buf_idx, u32 flip_mode, u32 flip_arg);
u32 buf_idx, u32 flip_mode, s64 flip_arg);
int PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffersForWorkload(
u32 workload, u32 count, u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg);
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, s64 flip_arg);
s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[],
u32* dcb_sizes_in_bytes, const u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes);

View File

@ -32,6 +32,14 @@ bool EqueueInternal::AddEvent(EqueueEvent& event) {
event.timer_interval = std::chrono::microseconds(event.event.data - offset);
}
// Remove add flag from event
event.event.flags &= ~SceKernelEvent::Flags::Add;
// Clear flag is appended to most event types internally.
if (event.event.filter != SceKernelEvent::Filter::User) {
event.event.flags |= SceKernelEvent::Flags::Clear;
}
const auto& it = std::ranges::find(m_events, event);
if (it != m_events.cend()) {
*it = std::move(event);
@ -165,10 +173,6 @@ int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
for (auto it = m_events.begin(); it != m_events.end();) {
if (it->IsTriggered()) {
ev[count++] = it->event;
// Event should not trigger again
it->ResetTriggerState();
if (it->event.flags & SceKernelEvent::Flags::Clear) {
it->Clear();
}

View File

@ -84,11 +84,8 @@ struct EqueueEvent {
std::chrono::microseconds timer_interval;
std::unique_ptr<boost::asio::steady_timer> timer;
void ResetTriggerState() {
is_triggered = false;
}
void Clear() {
is_triggered = false;
event.fflags = 0;
event.data = 0;
}
@ -101,14 +98,13 @@ struct EqueueEvent {
void TriggerUser(void* data) {
is_triggered = true;
event.fflags++;
event.udata = data;
}
void TriggerDisplay(void* data) {
is_triggered = true;
if (data != nullptr) {
auto event_data = static_cast<OrbisVideoOutEventData>(event.data);
auto event_data = std::bit_cast<OrbisVideoOutEventData>(event.data);
auto event_hint_raw = reinterpret_cast<u64>(data);
auto event_hint = static_cast<OrbisVideoOutEventHint>(event_hint_raw);
if (event_hint.event_id == event.ident && event.ident != 0xfe) {

View File

@ -218,7 +218,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, s64*
}
auto event_data = ev->data >> 0x10;
if (ev->ident != static_cast<s32>(OrbisVideoOutInternalEventId::Flip) || ev->data == 0) {
if (ev->ident != static_cast<s32>(OrbisVideoOutInternalEventId::Flip) || ev->data >= 0) {
*data = event_data;
} else {
*data = event_data | 0xffff000000000000;
@ -339,7 +339,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_a
return 16;
}
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk) {
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, s64 flip_arg, void** unk) {
auto* port = driver->GetPort(handle);
if (!port) {
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
@ -349,7 +349,7 @@ s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** u
Platform::InterruptId::GfxFlip, [=](Platform::InterruptId irq) {
ASSERT_MSG(irq == Platform::InterruptId::GfxFlip, "An unexpected IRQ occured");
ASSERT_MSG(port->buffer_labels[buf_id] == 1, "Out of order flip IRQ");
const auto result = driver->SubmitFlip(port, buf_id, arg, true);
const auto result = driver->SubmitFlip(port, buf_id, flip_arg, true);
ASSERT_MSG(result, "EOP flip submission failed");
});

View File

@ -139,7 +139,7 @@ s32 PS4_SYSV_ABI sceVideoOutColorSettingsSetGamma(SceVideoOutColorSettings* sett
s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings);
// Internal system functions
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk);
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, s64 flip_arg, void** unk);
void RegisterLib(Core::Loader::SymbolsResolver* sym);

View File

@ -61,7 +61,10 @@ template <class ReturnType, class... FuncArgs, class... CallArgs>
ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) {
EnsureThreadInitialized();
// clear stack to avoid trash from EnsureThreadInitialized
ClearStack<12_KB>();
auto* tcb = GetTcbBase();
if (tcb != nullptr && tcb->tcb_fiber == nullptr) {
ClearStack<12_KB>();
}
return func(std::forward<CallArgs>(args)...);
}

View File

@ -240,6 +240,7 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
LOG_INFO(Config, "Game-specific config exists: {}", has_game_config);
LOG_INFO(Config, "General LogType: {}", EmulatorSettings::GetInstance()->GetLogType());
LOG_INFO(Config, "General isIdenticalLogGrouped: {}", Config::groupIdenticalLogs());
LOG_INFO(Config, "General isNeo: {}", EmulatorSettings::GetInstance()->IsNeo());
LOG_INFO(Config, "General isDevKit: {}", EmulatorSettings::GetInstance()->IsDevKit());
LOG_INFO(Config, "General isConnectedToNetwork: {}",