mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-26 03:55:37 +00:00
Merge branch 'main' into qt_save
This commit is contained in:
commit
fa99a3d1f1
@ -603,6 +603,8 @@ set(CAMERA_LIBS src/core/libraries/camera/camera.cpp
|
||||
|
||||
set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
||||
src/core/libraries/companion/companion_httpd.h
|
||||
src/core/libraries/companion/companion_util.cpp
|
||||
src/core/libraries/companion/companion_util.h
|
||||
src/core/libraries/companion/companion_error.h
|
||||
)
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
@ -622,6 +624,8 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
src/core/devtools/widget/imgui_memory_editor.h
|
||||
src/core/devtools/widget/memory_map.cpp
|
||||
src/core/devtools/widget/memory_map.h
|
||||
src/core/devtools/widget/module_list.cpp
|
||||
src/core/devtools/widget/module_list.h
|
||||
src/core/devtools/widget/reg_popup.cpp
|
||||
src/core/devtools/widget/reg_popup.h
|
||||
src/core/devtools/widget/reg_view.cpp
|
||||
|
@ -71,6 +71,7 @@ class ElfInfo {
|
||||
PSFAttributes psf_attributes{};
|
||||
|
||||
std::filesystem::path splash_path{};
|
||||
std::filesystem::path game_folder{};
|
||||
|
||||
public:
|
||||
static constexpr u32 FW_15 = 0x1500000;
|
||||
@ -123,6 +124,10 @@ public:
|
||||
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||
return splash_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::filesystem::path& GetGameFolder() const {
|
||||
return game_folder;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
@ -140,6 +140,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Lib, SigninDialog) \
|
||||
SUB(Lib, Camera) \
|
||||
SUB(Lib, CompanionHttpd) \
|
||||
SUB(Lib, CompanionUtil) \
|
||||
CLS(Frontend) \
|
||||
CLS(Render) \
|
||||
SUB(Render, Vulkan) \
|
||||
|
@ -107,6 +107,7 @@ enum class Class : u8 {
|
||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||
Lib_Camera, ///< The LibCamera implementation.
|
||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "widget/frame_dump.h"
|
||||
#include "widget/frame_graph.h"
|
||||
#include "widget/memory_map.h"
|
||||
#include "widget/module_list.h"
|
||||
#include "widget/shader_list.h"
|
||||
|
||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||
@ -40,6 +41,7 @@ static bool just_opened_options = false;
|
||||
|
||||
static Widget::MemoryMapViewer memory_map;
|
||||
static Widget::ShaderList shader_list;
|
||||
static Widget::ModuleList module_list;
|
||||
|
||||
// clang-format off
|
||||
static std::string help_text =
|
||||
@ -108,6 +110,9 @@ void L::DrawMenuBar() {
|
||||
if (MenuItem("Memory map")) {
|
||||
memory_map.open = true;
|
||||
}
|
||||
if (MenuItem("Module list")) {
|
||||
module_list.open = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -256,6 +261,9 @@ void L::DrawAdvanced() {
|
||||
if (shader_list.open) {
|
||||
shader_list.Draw();
|
||||
}
|
||||
if (module_list.open) {
|
||||
module_list.Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void L::DrawSimple() {
|
||||
|
55
src/core/devtools/widget/module_list.cpp
Normal file
55
src/core/devtools/widget/module_list.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "module_list.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "core/debug_state.h"
|
||||
#include "imgui/imgui_std.h"
|
||||
|
||||
using namespace ImGui;
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
void ModuleList::Draw() {
|
||||
SetNextWindowSize({550.0f, 600.0f}, ImGuiCond_FirstUseEver);
|
||||
if (!Begin("Module List", &open)) {
|
||||
End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (BeginTable("ModuleTable", 3,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||
ImGuiTableFlags_RowBg)) {
|
||||
TableSetupColumn("Modulname", ImGuiTableColumnFlags_WidthStretch);
|
||||
TableHeadersRow();
|
||||
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
for (const auto& module : modules) {
|
||||
TableNextRow();
|
||||
|
||||
TableSetColumnIndex(0);
|
||||
TextUnformatted(module.name.c_str());
|
||||
|
||||
TableSetColumnIndex(1);
|
||||
if (module.is_sys_module) {
|
||||
TextColored({0.2f, 0.6f, 0.8f, 1.0f}, "System Module");
|
||||
} else {
|
||||
TextColored({0.8f, 0.4f, 0.2f, 1.0f}, "Game Module");
|
||||
}
|
||||
|
||||
TableSetColumnIndex(2);
|
||||
if (module.is_lle) {
|
||||
TextColored({0.4f, 0.7f, 0.4f, 1.0f}, "LLE");
|
||||
} else {
|
||||
TextColored({0.7f, 0.4f, 0.5f, 1.0f}, "HLE");
|
||||
}
|
||||
}
|
||||
EndTable();
|
||||
}
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
82
src/core/devtools/widget/module_list.h
Normal file
82
src/core/devtools/widget/module_list.h
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/elf_info.h"
|
||||
#include "common/path_util.h"
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
class ModuleList {
|
||||
public:
|
||||
ModuleList() = default;
|
||||
~ModuleList() = default;
|
||||
|
||||
void Draw();
|
||||
bool open = false;
|
||||
|
||||
static bool IsSystemModule(const std::filesystem::path& path) {
|
||||
const auto sys_modules_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
|
||||
const auto abs_path = std::filesystem::absolute(path).lexically_normal();
|
||||
const auto abs_sys_path = std::filesystem::absolute(sys_modules_path).lexically_normal();
|
||||
|
||||
const auto path_str = abs_path.string();
|
||||
const auto sys_path_str = abs_sys_path.string();
|
||||
|
||||
return path_str.starts_with(sys_path_str);
|
||||
}
|
||||
|
||||
static bool IsSystemModule(const std::string& name) {
|
||||
const auto game_modules_path = Common::ElfInfo::Instance().GetGameFolder() / "sce_module";
|
||||
const auto prx_path = game_modules_path / name;
|
||||
|
||||
if (!std::filesystem::exists(prx_path)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AddModule(const std::string& name, std::filesystem::path path) {
|
||||
if (name == "eboot.bin") {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
modules.push_back({name, IsSystemModule(path), true});
|
||||
}
|
||||
|
||||
static void AddModule(std::string name) {
|
||||
name = name + ".prx";
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
|
||||
bool is_sys_module = IsSystemModule(name);
|
||||
bool is_lle = false;
|
||||
auto it = std::find_if(modules.begin(), modules.end(),
|
||||
[&name, is_sys_module, is_lle](const ModuleInfo& entry) {
|
||||
return entry.name == name && !entry.is_lle;
|
||||
});
|
||||
|
||||
if (it == modules.end()) {
|
||||
modules.push_back({name, is_sys_module, is_lle});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ModuleInfo {
|
||||
std::string name;
|
||||
bool is_sys_module;
|
||||
bool is_lle;
|
||||
};
|
||||
|
||||
static inline std::mutex modules_mutex;
|
||||
|
||||
static inline std::vector<ModuleInfo> modules;
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
// companion_httpd error codes
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_UNKNOWN = 0x80E40001;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_FATAL = 0x80E40002;
|
||||
@ -18,3 +20,8 @@ constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_STARTED = 0x80E4000B;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_ALREADY_REGISTERED = 0x80E4000;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_CONNECTED = 0x80E4000D;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_USER_NOT_FOUND = 0x80E4000E;
|
||||
|
||||
// companion_util error codes
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_INVALID_ARGUMENT = 0x80AD0004;
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_INVALID_POINTER = 0x80AD0006;
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_NO_EVENT = 0x80AD0008;
|
72
src/core/libraries/companion/companion_util.cpp
Normal file
72
src/core/libraries/companion/companion_util.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "companion_error.h"
|
||||
#include "core/libraries/companion/companion_util.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::CompanionUtil {
|
||||
|
||||
u32 PS4_SYSV_ABI getEvent(sceCompanionUtilContext* ctx, sceCompanionUtilEvent* outEvent,
|
||||
s32 param_3) {
|
||||
if (outEvent == 0) {
|
||||
return ORBIS_COMPANION_UTIL_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ctx == nullptr) {
|
||||
return ORBIS_COMPANION_UTIL_INVALID_POINTER;
|
||||
}
|
||||
|
||||
uint8_t* base = ctx->blob;
|
||||
int flag = *reinterpret_cast<int*>(base + 0x178);
|
||||
if (flag == 0) {
|
||||
return ORBIS_COMPANION_UTIL_NO_EVENT;
|
||||
}
|
||||
|
||||
return ORBIS_COMPANION_UTIL_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetEvent(sceCompanionUtilEvent* outEvent) {
|
||||
sceCompanionUtilContext* ctx = nullptr;
|
||||
u32 ret = getEvent(ctx, outEvent, 1);
|
||||
|
||||
LOG_DEBUG(Lib_CompanionUtil, "(STUBBED) called ret: {}", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetRemoteOskEvent() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilInitialize() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilOptParamInitialize() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilTerminate() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceCompanionUtil(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("cE5Msy11WhU", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilGetEvent);
|
||||
LIB_FUNCTION("MaVrz79mT5o", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilGetRemoteOskEvent);
|
||||
LIB_FUNCTION("xb1xlIhf0QY", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilInitialize);
|
||||
LIB_FUNCTION("IPN-FRSrafk", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilOptParamInitialize);
|
||||
LIB_FUNCTION("H1fYQd5lFAI", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilTerminate);
|
||||
};
|
||||
|
||||
} // namespace Libraries::CompanionUtil
|
33
src/core/libraries/companion/companion_util.h
Normal file
33
src/core/libraries/companion/companion_util.h
Normal file
@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::CompanionUtil {
|
||||
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_OK = 0;
|
||||
|
||||
struct sceCompanionUtilEvent {
|
||||
std::uint8_t blob[0x104]{}; /// 0x104 bytes of data, dont know what it is exactly
|
||||
};
|
||||
|
||||
struct sceCompanionUtilContext {
|
||||
std::uint8_t blob[0x27B]{}; /// 0x27B bytes of data, dont know what it is exactly
|
||||
};
|
||||
|
||||
u32 PS4_SYSV_ABI getEvent(sceCompanionUtilContext* ctx, sceCompanionUtilEvent* outEvent,
|
||||
s32 param_3);
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetEvent(sceCompanionUtilEvent* outEvent);
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetRemoteOskEvent();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilOptParamInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilTerminate();
|
||||
|
||||
void RegisterlibSceCompanionUtil(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::CompanionUtil
|
@ -98,6 +98,11 @@ bool EqueueInternal::RemoveEvent(u64 id, s16 filter) {
|
||||
}
|
||||
|
||||
int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||
if (HasSmallTimer()) {
|
||||
// If a small timer is set, just wait for it to expire.
|
||||
return WaitForSmallTimer(ev, num, micros);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
const auto predicate = [&] {
|
||||
@ -187,7 +192,8 @@ int EqueueInternal::WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros) {
|
||||
ASSERT(num == 1);
|
||||
|
||||
auto curr_clock = std::chrono::steady_clock::now();
|
||||
const auto wait_end_us = curr_clock + std::chrono::microseconds{micros};
|
||||
const auto wait_end_us = (micros == 0) ? std::chrono::steady_clock::time_point::max()
|
||||
: curr_clock + std::chrono::microseconds{micros};
|
||||
|
||||
do {
|
||||
curr_clock = std::chrono::steady_clock::now();
|
||||
@ -266,24 +272,15 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
if (eq->HasSmallTimer()) {
|
||||
ASSERT(timo && *timo);
|
||||
*out = eq->WaitForSmallTimer(ev, num, *timo);
|
||||
if (timo == nullptr) {
|
||||
// When the timeout is nullptr, we wait indefinitely
|
||||
*out = eq->WaitForEvents(ev, num, 0);
|
||||
} else if (*timo == 0) {
|
||||
// Only events that have already arrived at the time of this function call can be received
|
||||
*out = eq->GetTriggeredEvents(ev, num);
|
||||
} else {
|
||||
if (timo == nullptr) { // wait until an event arrives without timing out
|
||||
*out = eq->WaitForEvents(ev, num, 0);
|
||||
}
|
||||
|
||||
if (timo != nullptr) {
|
||||
// Only events that have already arrived at the time of this function call can be
|
||||
// received
|
||||
if (*timo == 0) {
|
||||
*out = eq->GetTriggeredEvents(ev, num);
|
||||
} else {
|
||||
// Wait until an event arrives with timing out
|
||||
*out = eq->WaitForEvents(ev, num, *timo);
|
||||
}
|
||||
}
|
||||
// Wait for up to the specified timeout value
|
||||
*out = eq->WaitForEvents(ev, num, *timo);
|
||||
}
|
||||
|
||||
if (*out == 0) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "core/libraries/avplayer/avplayer.h"
|
||||
#include "core/libraries/camera/camera.h"
|
||||
#include "core/libraries/companion/companion_httpd.h"
|
||||
#include "core/libraries/companion/companion_util.h"
|
||||
#include "core/libraries/disc_map/disc_map.h"
|
||||
#include "core/libraries/game_live_streaming/gamelivestreaming.h"
|
||||
#include "core/libraries/gnmdriver/gnmdriver.h"
|
||||
@ -126,6 +127,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
||||
Libraries::SigninDialog::RegisterlibSceSigninDialog(sym);
|
||||
Libraries::Camera::RegisterlibSceCamera(sym);
|
||||
Libraries::CompanionHttpd::RegisterlibSceCompanionHttpd(sym);
|
||||
Libraries::CompanionUtil::RegisterlibSceCompanionUtil(sym);
|
||||
}
|
||||
|
||||
} // namespace Libraries
|
||||
|
@ -955,16 +955,148 @@ u16 PS4_SYSV_ABI sceNetHtons(u16 host16) {
|
||||
return htons(host16);
|
||||
}
|
||||
|
||||
const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 size) {
|
||||
#ifdef WIN32
|
||||
const char* res = InetNtopA(af, src, dst, size);
|
||||
#else
|
||||
const char* res = inet_ntop(af, src, dst, size);
|
||||
#endif
|
||||
if (res == nullptr) {
|
||||
UNREACHABLE();
|
||||
// there isn't a strlcpy function in windows so implement one
|
||||
u64 strlcpy(char* dst, const char* src, u64 size) {
|
||||
u64 src_len = strlen(src);
|
||||
|
||||
if (size > 0) {
|
||||
u64 copy_len = (src_len >= size) ? (size - 1) : src_len;
|
||||
memcpy(dst, src, copy_len);
|
||||
dst[copy_len] = '\0';
|
||||
}
|
||||
return dst;
|
||||
|
||||
return src_len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* freebsd_inet_ntop4(const char* src, char* dst, u64 size) {
|
||||
static const char fmt[] = "%u.%u.%u.%u";
|
||||
char tmp[sizeof "255.255.255.255"];
|
||||
int l;
|
||||
|
||||
l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
|
||||
if (l <= 0 || (socklen_t)l >= size) {
|
||||
return nullptr;
|
||||
}
|
||||
strlcpy(dst, tmp, size);
|
||||
return (dst);
|
||||
}
|
||||
|
||||
const char* freebsd_inet_ntop6(const char* src, char* dst, u64 size) {
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
|
||||
struct {
|
||||
int base, len;
|
||||
} best, cur;
|
||||
#define NS_IN6ADDRSZ 16
|
||||
#define NS_INT16SZ 2
|
||||
u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < NS_IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
best.len = 0;
|
||||
cur.base = -1;
|
||||
cur.len = 0;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 &&
|
||||
(best.len == 6 || (best.len == 7 && words[7] != 0x0001) ||
|
||||
(best.len == 5 && words[5] == 0xffff))) {
|
||||
if (!freebsd_inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
|
||||
return nullptr;
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((u64)(tp - tmp) > size) {
|
||||
return nullptr;
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 size) {
|
||||
if (!(src && dst)) {
|
||||
*sceNetErrnoLoc() = ORBIS_NET_ENOSPC;
|
||||
LOG_ERROR(Lib_Net, "returned ORBIS_NET_ENOSPC");
|
||||
return nullptr;
|
||||
}
|
||||
const char* returnvalue = nullptr;
|
||||
switch (af) {
|
||||
case ORBIS_NET_AF_INET:
|
||||
returnvalue = freebsd_inet_ntop4((const char*)src, dst, size);
|
||||
break;
|
||||
case ORBIS_NET_AF_INET6:
|
||||
returnvalue = freebsd_inet_ntop6((const char*)src, dst, size);
|
||||
break;
|
||||
default:
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EAFNOSUPPORT;
|
||||
LOG_ERROR(Lib_Net, "returned ORBIS_NET_EAFNOSUPPORT");
|
||||
return nullptr;
|
||||
}
|
||||
if (returnvalue == nullptr) {
|
||||
*sceNetErrnoLoc() = ORBIS_NET_ENOSPC;
|
||||
LOG_ERROR(Lib_Net, "returned ORBIS_NET_ENOSPC");
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNetInetNtopWithScopeId() {
|
||||
|
@ -20,6 +20,10 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::Net {
|
||||
|
||||
enum OrbisNetFamily : u32 {
|
||||
ORBIS_NET_AF_INET = 2,
|
||||
ORBIS_NET_AF_INET6 = 28,
|
||||
};
|
||||
enum OrbisNetSocketType : u32 {
|
||||
ORBIS_NET_SOCK_STREAM = 1,
|
||||
ORBIS_NET_SOCK_DGRAM = 2,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "common/thread.h"
|
||||
#include "core/aerolib/aerolib.h"
|
||||
#include "core/aerolib/stubs.h"
|
||||
#include "core/devtools/widget/module_list.h"
|
||||
#include "core/libraries/kernel/memory.h"
|
||||
#include "core/libraries/kernel/threads.h"
|
||||
#include "core/linker.h"
|
||||
@ -147,6 +148,9 @@ s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) {
|
||||
|
||||
num_static_modules += !is_dynamic;
|
||||
m_modules.emplace_back(std::move(module));
|
||||
|
||||
Core::Devtools::Widget::ModuleList::AddModule(elf_name.filename().string(), elf_name);
|
||||
|
||||
return m_modules.size() - 1;
|
||||
}
|
||||
|
||||
@ -325,6 +329,9 @@ bool Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Modul
|
||||
}
|
||||
if (record) {
|
||||
*return_info = *record;
|
||||
|
||||
Core::Devtools::Widget::ModuleList::AddModule(sr.library);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/devtools/widget/module_list.h"
|
||||
#include "core/file_format/psf.h"
|
||||
#include "core/file_format/trp.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
@ -188,6 +189,8 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
||||
game_info.splash_path = pic1_path;
|
||||
}
|
||||
|
||||
game_info.game_folder = game_folder;
|
||||
|
||||
std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version);
|
||||
std::string window_title = "";
|
||||
std::string remote_url(Common::g_scm_remote_url);
|
||||
|
@ -26,7 +26,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n</source>
|
||||
<translation>Los cheats/patches son experimentales.\nÚselos con precaución.\n\nDescargue los cheats individualmente seleccionando el repositorio y haciendo clic en el botón de descarga.\nEn la pestaña Patches, puede descargar todos los patches a la vez, elegir cuáles desea usar y guardar la selección.\n\nComo no desarrollamos los Cheats/Patches,\npor favor informe los problemas al autor del cheat.\n\n¿Creaste un nuevo cheat? Visita:\n</translation>
|
||||
<translation>Los trucos/parches son experimentales.\nÚselos con precaución.\n\nPuede descargar cada truco seleccionando el repositorio y haciendo clic en el botón de descarga.\nEn la pestaña Parches podrá descargar todos los parches a la vez, elegir cuáles desea usar y guardar la selección.\n\nComo no desarrollamos los trucos/parches,\ndebe informar de cualquier problema a sus autores correspondientes.\n\n¿Creaste un truco nuevo? Visita:\n</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No Image Available</source>
|
||||
@ -2048,7 +2048,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source> * Unsupported Vulkan Version</source>
|
||||
<translation type="unfinished"> * Unsupported Vulkan Version</translation>
|
||||
<translation> * Versión de Vulkan no soportada</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -2048,7 +2048,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source> * Unsupported Vulkan Version</source>
|
||||
<translation type="unfinished"> * Unsupported Vulkan Version</translation>
|
||||
<translation> * Desteklenmeyen Vulkan Sürümü</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -154,7 +154,7 @@ Id EmitFPRecip32(EmitContext& ctx, Id value) {
|
||||
}
|
||||
|
||||
Id EmitFPRecip64(EmitContext& ctx, Id value) {
|
||||
return ctx.OpFDiv(ctx.F64[1], ctx.Constant(ctx.F64[1], 1.0f), value);
|
||||
return ctx.OpFDiv(ctx.F64[1], ctx.Constant(ctx.F64[1], f64{1.0}), value);
|
||||
}
|
||||
|
||||
Id EmitFPRecipSqrt32(EmitContext& ctx, Id value) {
|
||||
|
@ -752,6 +752,10 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
||||
strmout->buffer_select.Value());
|
||||
break;
|
||||
}
|
||||
case PM4ItOpcode::GetLodStats: {
|
||||
LOG_WARNING(Render_Vulkan, "Unimplemented IT_GET_LOD_STATS");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}",
|
||||
static_cast<u32>(opcode), count);
|
||||
|
@ -71,6 +71,7 @@ enum class PM4ItOpcode : u32 {
|
||||
IncrementDeCounter = 0x85,
|
||||
WaitOnCeCounter = 0x86,
|
||||
WaitOnDeCounterDiff = 0x88,
|
||||
GetLodStats = 0x8E,
|
||||
DrawIndexIndirectCountMulti = 0x9d,
|
||||
};
|
||||
|
||||
|
@ -668,7 +668,7 @@ void BufferCache::ProcessFaultBuffer() {
|
||||
const VAddr fault_end = fault + CACHING_PAGESIZE; // This can be adjusted
|
||||
fault_ranges +=
|
||||
boost::icl::interval_set<VAddr>::interval_type::right_open(fault, fault_end);
|
||||
LOG_INFO(Render_Vulkan, "Accessed non-GPU mapped memory at {:#x}", fault);
|
||||
LOG_INFO(Render_Vulkan, "Accessed non-GPU cached memory at {:#x}", fault);
|
||||
}
|
||||
for (const auto& range : fault_ranges) {
|
||||
const VAddr start = range.lower();
|
||||
|
@ -213,6 +213,12 @@ struct PageManager::Impl {
|
||||
|
||||
// Iterate requested pages
|
||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||
const u64 aligned_addr = page << PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PAGE_BITS;
|
||||
ASSERT_MSG(rasterizer->IsMapped(aligned_addr, aligned_end - aligned_addr),
|
||||
"Attempted to track non-GPU memory at address {:#x}, size {:#x}.",
|
||||
aligned_addr, aligned_end - aligned_addr);
|
||||
|
||||
for (; page != page_end; ++page) {
|
||||
PageState& state = cached_pages[page];
|
||||
|
||||
|
@ -222,14 +222,23 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
|
||||
-1, -1};
|
||||
}
|
||||
|
||||
ImageId new_image_id{};
|
||||
if (image_info.type == tex_cache_image.info.type) {
|
||||
ASSERT(image_info.resources > tex_cache_image.info.resources);
|
||||
new_image_id = ExpandImage(image_info, cache_image_id);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
if (image_info.type == tex_cache_image.info.type &&
|
||||
image_info.resources > tex_cache_image.info.resources) {
|
||||
// Size and resources are greater, expand the image.
|
||||
return {ExpandImage(image_info, cache_image_id), -1, -1};
|
||||
}
|
||||
return {new_image_id, -1, -1};
|
||||
|
||||
if (image_info.tiling_mode != tex_cache_image.info.tiling_mode) {
|
||||
// Size is greater but resources are not, because the tiling mode is different.
|
||||
// Likely this memory address is being reused for a different image with a different
|
||||
// tiling mode.
|
||||
if (safe_to_delete) {
|
||||
FreeImage(cache_image_id);
|
||||
}
|
||||
return {merged_image_id, -1, -1};
|
||||
}
|
||||
|
||||
UNREACHABLE_MSG("Encountered unresolvable image overlap with equal memory address.");
|
||||
}
|
||||
|
||||
// Right overlap, the image requested is a possible subresource of the image from cache.
|
||||
|
Loading…
Reference in New Issue
Block a user