early-access version 3874

This commit is contained in:
pineappleEA
2023-09-16 19:31:09 +02:00
parent 6aeb2166eb
commit 873a74b74f
33 changed files with 1063 additions and 126 deletions

View File

@@ -349,6 +349,8 @@ struct Values {
Category::RendererDebug};
Setting<bool> disable_shader_loop_safety_checks{
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
Category::RendererDebug};
// TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control
bool renderer_amdvlk_depth_bias_workaround{};

View File

@@ -864,6 +864,8 @@ add_library(core STATIC
telemetry_session.h
tools/freezer.cpp
tools/freezer.h
tools/renderdoc.cpp
tools/renderdoc.h
)
if (MSVC)
@@ -879,6 +881,7 @@ else()
-Werror=conversion
-Wno-sign-conversion
-Wno-cast-function-type
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
)
@@ -887,7 +890,7 @@ endif()
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core nx_tzdb)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls renderdoc)
if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})
endif()

View File

@@ -51,6 +51,7 @@
#include "core/reporter.h"
#include "core/telemetry_session.h"
#include "core/tools/freezer.h"
#include "core/tools/renderdoc.h"
#include "network/network.h"
#include "video_core/host1x/host1x.h"
#include "video_core/renderer_base.h"
@@ -281,6 +282,10 @@ struct System::Impl {
microprofile_cpu[2] = MICROPROFILE_TOKEN(ARM_CPU2);
microprofile_cpu[3] = MICROPROFILE_TOKEN(ARM_CPU3);
if (Settings::values.enable_renderdoc_hotkey) {
renderdoc_api = std::make_unique<Tools::RenderdocAPI>();
}
LOG_DEBUG(Core, "Initialized OK");
return SystemResultStatus::Success;
@@ -528,6 +533,8 @@ struct System::Impl {
std::unique_ptr<Tools::Freezer> memory_freezer;
std::array<u8, 0x20> build_id{};
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
/// Frontend applets
Service::AM::Applets::AppletManager applet_manager;
@@ -1031,6 +1038,10 @@ const Network::RoomNetwork& System::GetRoomNetwork() const {
return impl->room_network;
}
Tools::RenderdocAPI& System::GetRenderdocAPI() {
return *impl->renderdoc_api;
}
void System::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
return impl->kernel.RunServer(std::move(server_manager));
}

View File

@@ -102,6 +102,10 @@ namespace Network {
class RoomNetwork;
}
namespace Tools {
class RenderdocAPI;
}
namespace Core {
class ARM_Interface;
@@ -413,6 +417,8 @@ public:
/// Gets an immutable reference to the Room Network.
[[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const;
[[nodiscard]] Tools::RenderdocAPI& GetRenderdocAPI();
void SetExitLocked(bool locked);
bool GetExitLocked() const;

View File

@@ -294,11 +294,11 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
return out;
}
bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name) const {
const auto build_id_raw = Common::HexToString(build_id_);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id);
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name);
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
if (load_dir == nullptr) {

View File

@@ -52,7 +52,7 @@ public:
// Checks to see if PatchNSO() will have any effect given the NSO's build ID.
// Used to prevent expensive copies in NSO loader.
[[nodiscard]] bool HasNSOPatch(const BuildID& build_id) const;
[[nodiscard]] bool HasNSOPatch(const BuildID& build_id, std::string_view name) const;
// Creates a CheatList object with all
[[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(

View File

@@ -154,6 +154,14 @@ NpadIdType HIDCore::GetFirstDisconnectedNpadId() const {
return NpadIdType::Player1;
}
void HIDCore::SetLastActiveController(NpadIdType npad_id) {
last_active_controller = npad_id;
}
NpadIdType HIDCore::GetLastActiveController() const {
return last_active_controller;
}
void HIDCore::EnableAllControllerConfiguration() {
player_1->EnableConfiguration();
player_2->EnableConfiguration();

View File

@@ -48,6 +48,12 @@ public:
/// Returns the first disconnected npad id
NpadIdType GetFirstDisconnectedNpadId() const;
/// Sets the npad id of the last active controller
void SetLastActiveController(NpadIdType npad_id);
/// Returns the npad id of the last controller that pushed a button
NpadIdType GetLastActiveController() const;
/// Sets all emulated controllers into configuring mode.
void EnableAllControllerConfiguration();
@@ -77,6 +83,7 @@ private:
std::unique_ptr<EmulatedConsole> console;
std::unique_ptr<EmulatedDevices> devices;
NpadStyleTag supported_style_tag{NpadStyleSet::All};
NpadIdType last_active_controller{NpadIdType::Handheld};
};
} // namespace Core::HID

View File

@@ -96,6 +96,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string
process->m_is_suspended = false;
process->m_schedule_count = 0;
process->m_is_handle_table_initialized = false;
process->m_is_hbl = false;
// Open a reference to the resource limit.
process->m_resource_limit->Open();
@@ -351,12 +352,14 @@ Result KProcess::SetActivity(ProcessActivity activity) {
R_SUCCEED();
}
Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size) {
Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
bool is_hbl) {
m_program_id = metadata.GetTitleID();
m_ideal_core = metadata.GetMainThreadCore();
m_is_64bit_process = metadata.Is64BitProgram();
m_system_resource_size = metadata.GetSystemResourceSize();
m_image_size = code_size;
m_is_hbl = is_hbl;
if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) {
// For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.

View File

@@ -338,7 +338,8 @@ public:
* @returns ResultSuccess if all relevant metadata was able to be
* loaded and parsed. Otherwise, an error code is returned.
*/
Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size);
Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
bool is_hbl);
/**
* Starts the main application thread for this process.
@@ -368,6 +369,10 @@ public:
return GetProcessId();
}
bool IsHbl() const {
return m_is_hbl;
}
bool IsSignaled() const override;
void DoWorkerTaskImpl();
@@ -525,6 +530,7 @@ private:
bool m_is_immortal{};
bool m_is_handle_table_initialized{};
bool m_is_initialized{};
bool m_is_hbl{};
std::atomic<u16> m_num_running_threads{};

View File

@@ -14,7 +14,7 @@ Result OutputDebugString(Core::System& system, u64 address, u64 len) {
std::string str(len, '\0');
GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size());
LOG_DEBUG(Debug_Emulated, "{}", str);
LOG_INFO(Debug_Emulated, "{}", str);
R_SUCCEED();
}

View File

@@ -3,6 +3,7 @@
#include "core/core.h"
#include "core/debugger/debugger.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_types.h"
@@ -107,7 +108,10 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
}
if (system.DebuggerEnabled()) {
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
const bool should_break = is_hbl || !notification_only;
if (system.DebuggerEnabled() && should_break) {
auto* thread = system.Kernel().GetCurrentEmuThread();
system.GetDebugger().NotifyThreadStopped(thread);
thread->RequestSuspend(Kernel::SuspendType::Debug);

View File

@@ -193,7 +193,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->system_properties.use_minus.Assign(1);
shared_memory->system_properties.is_charging_joy_dual.Assign(
battery_level.dual.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController;
shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::Handheld:
@@ -216,8 +216,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->system_properties.is_charging_joy_right.Assign(
battery_level.right.is_charging);
shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
shared_memory->applet_nfc_xcd.applet_footer.type =
AppletFooterUiType::HandheldJoyConLeftJoyConRight;
shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::JoyconDual:
@@ -247,19 +246,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;
shared_memory->applet_footer_type = AppletFooterUiType::JoyDual;
shared_memory->fullkey_color.fullkey = body_colors.left;
shared_memory->battery_level_dual = battery_level.left.battery_level;
shared_memory->system_properties.is_charging_joy_dual.Assign(
battery_level.left.is_charging);
} else if (controller.is_dual_left_connected) {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly;
shared_memory->fullkey_color.fullkey = body_colors.left;
shared_memory->battery_level_dual = battery_level.left.battery_level;
shared_memory->system_properties.is_charging_joy_dual.Assign(
battery_level.left.is_charging);
} else {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly;
shared_memory->fullkey_color.fullkey = body_colors.right;
shared_memory->battery_level_dual = battery_level.right.battery_level;
shared_memory->system_properties.is_charging_joy_dual.Assign(
@@ -278,7 +277,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->system_properties.use_minus.Assign(1);
shared_memory->system_properties.is_charging_joy_left.Assign(
battery_level.left.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal;
shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
@@ -293,7 +292,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->system_properties.use_plus.Assign(1);
shared_memory->system_properties.is_charging_joy_right.Assign(
battery_level.right.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal;
shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::GameCube:
@@ -314,12 +313,12 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
case Core::HID::NpadStyleIndex::SNES:
shared_memory->style_tag.lucia.Assign(1);
shared_memory->device_type.fullkey.Assign(1);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia;
shared_memory->applet_footer_type = AppletFooterUiType::Lucia;
break;
case Core::HID::NpadStyleIndex::N64:
shared_memory->style_tag.lagoon.Assign(1);
shared_memory->device_type.fullkey.Assign(1);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon;
shared_memory->applet_footer_type = AppletFooterUiType::Lagon;
break;
case Core::HID::NpadStyleIndex::SegaGenesis:
shared_memory->style_tag.lager.Assign(1);
@@ -419,9 +418,17 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
std::scoped_lock lock{mutex};
auto& controller = GetControllerFromNpadIdType(npad_id);
const auto controller_type = controller.device->GetNpadStyleIndex();
if (!controller.device->IsConnected() && controller.is_connected) {
DisconnectNpad(npad_id);
return;
}
if (!controller.device->IsConnected()) {
return;
}
if (controller.device->IsConnected() && !controller.is_connected) {
InitNewlyAddedController(npad_id);
}
// This function is unique to yuzu for the turbo buttons and motion to work properly
controller.device->StatusUpdate();
@@ -468,6 +475,10 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
pad_entry.npad_buttons.l.Assign(button_state.zl);
pad_entry.npad_buttons.r.Assign(button_state.zr);
}
if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) {
hid_core.SetLastActiveController(npad_id);
}
}
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
@@ -736,14 +747,6 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
// Once SetSupportedStyleSet is called controllers are fully initialized
is_controller_initialized = true;
// Connect all active controllers
for (auto& controller : controller_data) {
const auto& device = controller.device;
if (device->IsConnected()) {
AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
}
}
}
Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
@@ -1116,7 +1119,7 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
.left = {},
.right = {},
};
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None;
shared_memory->applet_footer_type = AppletFooterUiType::None;
controller.is_dual_left_connected = true;
controller.is_dual_right_connected = true;
@@ -1508,6 +1511,31 @@ Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
}
void Controller_NPad::ApplyNpadSystemCommonPolicy() {
Core::HID::NpadStyleTag styletag{};
styletag.fullkey.Assign(1);
styletag.handheld.Assign(1);
styletag.joycon_dual.Assign(1);
styletag.system_ext.Assign(1);
styletag.system.Assign(1);
SetSupportedStyleSet(styletag);
SetNpadHandheldActivationMode(NpadHandheldActivationMode::Dual);
supported_npad_id_types.clear();
supported_npad_id_types.resize(10);
supported_npad_id_types[0] = Core::HID::NpadIdType::Player1;
supported_npad_id_types[1] = Core::HID::NpadIdType::Player2;
supported_npad_id_types[2] = Core::HID::NpadIdType::Player3;
supported_npad_id_types[3] = Core::HID::NpadIdType::Player4;
supported_npad_id_types[4] = Core::HID::NpadIdType::Player5;
supported_npad_id_types[5] = Core::HID::NpadIdType::Player6;
supported_npad_id_types[6] = Core::HID::NpadIdType::Player7;
supported_npad_id_types[7] = Core::HID::NpadIdType::Player8;
supported_npad_id_types[8] = Core::HID::NpadIdType::Other;
supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld;
}
bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
if (controller == Core::HID::NpadStyleIndex::Handheld) {
const bool support_handheld =

View File

@@ -190,6 +190,8 @@ public:
// Specifically for cheat engine and other features.
Core::HID::NpadButton GetAndResetPressState();
void ApplyNpadSystemCommonPolicy();
static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
static Result VerifyValidSixAxisSensorHandle(
@@ -360,7 +362,7 @@ private:
enum class AppletFooterUiType : u8 {
None = 0,
HandheldNone = 1,
HandheldJoyConLeftOnly = 1,
HandheldJoyConLeftOnly = 2,
HandheldJoyConRightOnly = 3,
HandheldJoyConLeftJoyConRight = 4,
JoyDual = 5,
@@ -382,13 +384,6 @@ private:
Lagon = 21,
};
struct AppletFooterUi {
AppletFooterUiAttributes attributes{};
AppletFooterUiType type{AppletFooterUiType::None};
INSERT_PADDING_BYTES(0x5B); // Reserved
};
static_assert(sizeof(AppletFooterUi) == 0x60, "AppletFooterUi is an invalid size");
// This is nn::hid::NpadLarkType
enum class NpadLarkType : u32 {
Invalid,
@@ -419,13 +414,6 @@ private:
U,
};
struct AppletNfcXcd {
union {
AppletFooterUi applet_footer{};
Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo;
};
};
// This is nn::hid::detail::NpadInternalState
struct NpadInternalState {
Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
@@ -452,7 +440,9 @@ private:
Core::HID::NpadBatteryLevel battery_level_dual{};
Core::HID::NpadBatteryLevel battery_level_left{};
Core::HID::NpadBatteryLevel battery_level_right{};
AppletNfcXcd applet_nfc_xcd{};
AppletFooterUiAttributes applet_footer_attributes{};
AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
INSERT_PADDING_BYTES(0x5B); // Reserved
INSERT_PADDING_BYTES(0x20); // Unknown
Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
NpadLarkType lark_type_l_and_main{};

View File

@@ -231,8 +231,10 @@ std::shared_ptr<IAppletResource> Hid::GetAppletResource() {
return applet_resource;
}
Hid::Hid(Core::System& system_)
: ServiceFramework{system_, "hid"}, service_context{system_, service_name} {
Hid::Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
: ServiceFramework{system_, "hid"}, applet_resource{applet_resource_}, service_context{
system_,
service_name} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &Hid::CreateAppletResource, "CreateAppletResource"},
@@ -2543,8 +2545,9 @@ public:
class HidSys final : public ServiceFramework<HidSys> {
public:
explicit HidSys(Core::System& system_)
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} {
explicit HidSys(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"},
applet_resource{applet_resource_} {
// clang-format off
static const FunctionInfo functions[] = {
{31, nullptr, "SendKeyboardLockKeyEvent"},
@@ -2756,9 +2759,12 @@ public:
private:
void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
// We already do this for homebrew so we can just stub it out
LOG_WARNING(Service_HID, "called");
GetAppletResource()
->GetController<Controller_NPad>(HidController::NPad)
.ApplyNpadSystemCommonPolicy();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
@@ -2768,7 +2774,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(Core::HID::NpadIdType::Handheld);
rb.PushEnum(system.HIDCore().GetLastActiveController());
}
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
@@ -2821,17 +2827,28 @@ private:
rb.PushRaw(touchscreen_config);
}
std::shared_ptr<IAppletResource> GetAppletResource() {
if (applet_resource == nullptr) {
applet_resource = std::make_shared<IAppletResource>(system, service_context);
}
return applet_resource;
}
Kernel::KEvent* joy_detach_event;
KernelHelpers::ServiceContext service_context;
std::shared_ptr<IAppletResource> applet_resource;
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
std::shared_ptr<IAppletResource> applet_resource;
server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system));
server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system, applet_resource));
server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));
server_manager->RegisterNamedService("hid:dbg", std::make_shared<HidDbg>(system));
server_manager->RegisterNamedService("hid:sys", std::make_shared<HidSys>(system));
server_manager->RegisterNamedService("hid:sys",
std::make_shared<HidSys>(system, applet_resource));
server_manager->RegisterNamedService("irs", std::make_shared<Service::IRS::IRS>(system));
server_manager->RegisterNamedService("irs:sys",

View File

@@ -95,7 +95,7 @@ private:
class Hid final : public ServiceFramework<Hid> {
public:
explicit Hid(Core::System& system_);
explicit Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_);
~Hid() override;
std::shared_ptr<IAppletResource> GetAppletResource();

View File

@@ -874,17 +874,19 @@ Result NfcDevice::RestoreAmiibo() {
}
Result NfcDevice::Format() {
auto result1 = DeleteApplicationArea();
auto result2 = DeleteRegisterInfo();
Result result = ResultSuccess;
if (result1.IsError()) {
return result1;
if (device_state == DeviceState::TagFound) {
result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All);
}
if (result2.IsError()) {
return result2;
if (result.IsError()) {
return result;
}
DeleteApplicationArea();
DeleteRegisterInfo();
return Flush();
}

View File

@@ -18,7 +18,7 @@ namespace Loader {
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
bool override_update_)
: AppLoader(std::move(file_)), override_update(override_update_) {
: AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) {
const auto file_dir = file->GetContainingDirectory();
// Title ID
@@ -69,9 +69,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys
}
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
FileSys::VirtualDir directory, bool override_update_)
FileSys::VirtualDir directory, bool override_update_, bool is_hbl_)
: AppLoader(directory->GetFile("main")), dir(std::move(directory)),
override_update(override_update_) {}
override_update(override_update_), is_hbl(is_hbl_) {}
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) {
if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) {
@@ -147,7 +147,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
}
// Setup the process code layout
if (process.LoadFromMetadata(metadata, code_size).IsError()) {
if (process.LoadFromMetadata(metadata, code_size, is_hbl).IsError()) {
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
}

View File

@@ -27,7 +27,8 @@ public:
// Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory,
bool override_update_ = false);
bool override_update_ = false,
bool is_hbl_ = false);
/**
* Identifies whether or not the given file is a deconstructed ROM directory.
@@ -62,6 +63,7 @@ private:
std::string name;
u64 title_id{};
bool override_update;
bool is_hbl;
Modules modules;
};

View File

@@ -90,7 +90,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
codeset.DataSegment().size += kip->GetBSSSize();
// Setup the process code layout
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
if (process
.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false)
.IsError()) {
return {ResultStatus::ErrorNotInitialized, {}};
}

View File

@@ -196,7 +196,8 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
program_image.resize(static_cast<u32>(program_image.size()) + bss_size);
// Setup the process code layout
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
if (process
.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false)
.IsError()) {
return false;
}

View File

@@ -127,13 +127,14 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
}
// Apply patches if necessary
if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
const auto name = nso_file.GetName();
if (pm && (pm->HasNSOPatch(nso_header.build_id, name) || Settings::values.dump_nso)) {
std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader));
std::memcpy(pi_header.data() + sizeof(NSOHeader), program_image.data(),
program_image.size());
pi_header = pm->PatchNSO(pi_header, nso_file.GetName());
pi_header = pm->PatchNSO(pi_header, name);
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
}

View File

@@ -30,7 +30,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
}
if (nsp->IsExtractedType()) {
secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(
nsp->GetExeFS(), false, file->GetName() == "hbl.nsp");
} else {
const auto control_nca =
nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);

55
src/core/tools/renderdoc.cpp Executable file
View File

@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <renderdoc_app.h>
#include "common/assert.h"
#include "common/dynamic_library.h"
#include "core/tools/renderdoc.h"
#ifdef WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
namespace Tools {
RenderdocAPI::RenderdocAPI() {
#ifdef WIN32
if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) {
const auto RENDERDOC_GetAPI =
reinterpret_cast<pRENDERDOC_GetAPI>(GetProcAddress(mod, "RENDERDOC_GetAPI"));
const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api);
ASSERT(ret == 1);
}
#else
#ifdef ANDROID
static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so";
#else
static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so";
#endif
if (void* mod = dlopen(RENDERDOC_LIB, RTLD_NOW | RTLD_NOLOAD)) {
const auto RENDERDOC_GetAPI =
reinterpret_cast<pRENDERDOC_GetAPI>(dlsym(mod, "RENDERDOC_GetAPI"));
const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api);
ASSERT(ret == 1);
}
#endif
}
RenderdocAPI::~RenderdocAPI() = default;
void RenderdocAPI::ToggleCapture() {
if (!rdoc_api) [[unlikely]] {
return;
}
if (!is_capturing) {
rdoc_api->StartFrameCapture(NULL, NULL);
} else {
rdoc_api->EndFrameCapture(NULL, NULL);
}
is_capturing = !is_capturing;
}
} // namespace Tools

22
src/core/tools/renderdoc.h Executable file
View File

@@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
struct RENDERDOC_API_1_6_0;
namespace Tools {
class RenderdocAPI {
public:
explicit RenderdocAPI();
~RenderdocAPI();
void ToggleCapture();
private:
RENDERDOC_API_1_6_0* rdoc_api{};
bool is_capturing{false};
};
} // namespace Tools

View File

@@ -140,6 +140,8 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
return PixelFormat::D32_FLOAT;
case Hash(TextureFormat::Z16, UNORM):
return PixelFormat::D16_UNORM;
case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR):
return PixelFormat::D16_UNORM;
case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR):
return PixelFormat::S8_UINT_D24_UNORM;
case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR):

View File

@@ -59,6 +59,8 @@ void ConfigureDebug::SetConfiguration() {
ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue());
ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue());
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
ui->enable_renderdoc_hotkey->setEnabled(runtime_lock);
ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue());
ui->enable_graphics_debugging->setEnabled(runtime_lock);
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
ui->enable_shader_feedback->setEnabled(runtime_lock);
@@ -111,6 +113,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.enable_renderdoc_hotkey = ui->enable_renderdoc_hotkey->isChecked();
Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();

View File

@@ -18,8 +18,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>829</width>
<height>758</height>
<width>842</width>
<height>741</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_1">
@@ -260,7 +260,7 @@
<string>Graphics</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="disable_loop_safety_checks">
<property name="toolTip">
<string>When checked, it executes shaders without loop logic changes</string>
@@ -270,20 +270,7 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="dump_shaders">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
</property>
<property name="text">
<string>Dump Game Shaders</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QCheckBox" name="disable_macro_hle">
<property name="enabled">
<bool>true</bool>
@@ -296,33 +283,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="disable_macro_jit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string>
</property>
<property name="text">
<string>Disable Macro JIT</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="enable_graphics_debugging">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, the graphics API enters a slower debugging mode</string>
</property>
<property name="text">
<string>Enable Graphics Debugging</string>
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QCheckBox" name="dump_macros">
<property name="enabled">
<bool>true</bool>
@@ -335,17 +296,7 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enable_shader_feedback">
<property name="toolTip">
<string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
</property>
<property name="text">
<string>Enable Shader Feedback</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QCheckBox" name="enable_nsight_aftermath">
<property name="toolTip">
<string>When checked, it enables Nsight Aftermath crash dumps</string>
@@ -355,7 +306,30 @@
</property>
</widget>
</item>
<item row="8" column="0">
<item row="2" column="0">
<widget class="QCheckBox" name="enable_shader_feedback">
<property name="toolTip">
<string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
</property>
<property name="text">
<string>Enable Shader Feedback</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="disable_macro_jit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string>
</property>
<property name="text">
<string>Disable Macro JIT</string>
</property>
</widget>
</item>
<item row="9" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -371,6 +345,39 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="enable_graphics_debugging">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, the graphics API enters a slower debugging mode</string>
</property>
<property name="text">
<string>Enable Graphics Debugging</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="dump_shaders">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
</property>
<property name="text">
<string>Dump Game Shaders</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enable_renderdoc_hotkey">
<property name="text">
<string>Enable Renderdoc Hotkey</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -4,10 +4,12 @@
#pragma once
#include <map>
#include <QKeySequence>
#include <QString>
#include <QWidget>
#include "core/hid/hid_types.h"
class QDialog;
class QKeySequence;
class QSettings;
class QShortcut;
class ControllerShortcut;

View File

@@ -9,6 +9,7 @@
#include <memory>
#include <thread>
#include "core/loader/nca.h"
#include "core/tools/renderdoc.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@@ -1351,6 +1352,11 @@ void GMainWindow::InitializeHotkeys() {
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
});
connect_shortcut(QStringLiteral("Toggle Renderdoc Capture"), [this] {
if (Settings::values.enable_renderdoc_hotkey) {
system->GetRenderdocAPI().ToggleCapture();
}
});
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
if (Settings::values.mouse_enabled) {
Settings::values.mouse_panning = false;