Compare commits
36 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c883666045 | ||
|
|
05781ce8c4 | ||
|
|
312c3788df | ||
|
|
a7af349dae | ||
|
|
6b35317ff3 | ||
|
|
f97c2cdd0b | ||
|
|
d51afc4efb | ||
|
|
1ffff4dab2 | ||
|
|
99d191d80d | ||
|
|
d840ed90e1 | ||
|
|
f490b4545d | ||
|
|
08f02836d8 | ||
|
|
4524e1bd54 | ||
|
|
45cf48bd0a | ||
|
|
b69f902b18 | ||
|
|
dd92bd644d | ||
|
|
35b96a28d7 | ||
|
|
7b070bbf62 | ||
|
|
5dab23e017 | ||
|
|
a2e1810287 | ||
|
|
e3503de588 | ||
|
|
5f075bb490 | ||
|
|
80eedff9e1 | ||
|
|
1a7cf26884 | ||
|
|
ac7e4e2cab | ||
|
|
04699c366b | ||
|
|
e19972dfc4 | ||
|
|
ca6ff01333 | ||
|
|
d046e9b458 | ||
|
|
e96cf13ebc | ||
|
|
dc2d31b1b2 | ||
|
|
4b369126c4 | ||
|
|
92d879e5f6 | ||
|
|
8248d76964 | ||
|
|
d7d2c27b48 | ||
|
|
0319cc1c37 |
BIN
dist/qt_themes/qdarkstyle/rc/checkbox_checked.png
vendored
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 492 B |
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 252 B |
8
dist/qt_themes/qdarkstyle/style.qss
vendored
@@ -654,7 +654,11 @@ QAbstractSpinBox::down-arrow:hover {
|
||||
image: url(:/qss_icons/rc/down_arrow.png);
|
||||
}
|
||||
|
||||
QLabel,
|
||||
QLabel {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QTabWidget {
|
||||
border: 0;
|
||||
}
|
||||
@@ -1269,4 +1273,4 @@ QPushButton#RendererStatusBarButton:checked {
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked{
|
||||
color: #00ccdd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,7 +875,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QLabel {
|
||||
background-color: #19232D;
|
||||
background: transparent;
|
||||
border: 0px solid #32414B;
|
||||
padding: 2px;
|
||||
margin: 0px;
|
||||
@@ -883,7 +883,6 @@ QLabel {
|
||||
}
|
||||
|
||||
QLabel:disabled {
|
||||
background-color: #19232D;
|
||||
border: 0px solid #32414B;
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,10 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
|
||||
ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_)
|
||||
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
|
||||
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
|
||||
|
||||
release_event = Core::Timing::CreateEvent(
|
||||
name, [this](u64, std::chrono::nanoseconds ns_late) { ReleaseActiveBuffer(ns_late); });
|
||||
release_event =
|
||||
Core::Timing::CreateEvent(name, [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
|
||||
ReleaseActiveBuffer(ns_late);
|
||||
});
|
||||
}
|
||||
|
||||
void Stream::Play() {
|
||||
|
||||
@@ -74,16 +74,4 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t
|
||||
std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
|
||||
std::size_t max_len);
|
||||
|
||||
/**
|
||||
* Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's
|
||||
* intended to be used to strip a system-specific build directory from the `__FILE__` macro,
|
||||
* leaving only the path relative to the sources root.
|
||||
*
|
||||
* @param path The input file path as a null-terminated string
|
||||
* @param root The name of the root source directory as a null-terminated string. Path up to and
|
||||
* including the last occurrence of this name will be stripped
|
||||
* @return A pointer to the same string passed as `path`, but starting at the trimmed portion
|
||||
*/
|
||||
const char* TrimSourcePath(const char* path, const char* root = "src");
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -38,7 +38,7 @@ void* AllocateMemoryPages(std::size_t size) {
|
||||
return base;
|
||||
}
|
||||
|
||||
void FreeMemoryPages(void* base, std::size_t size) {
|
||||
void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) {
|
||||
if (!base) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac
|
||||
struct CoreTiming::Event {
|
||||
u64 time;
|
||||
u64 fifo_order;
|
||||
u64 userdata;
|
||||
std::uintptr_t user_data;
|
||||
std::weak_ptr<EventType> type;
|
||||
|
||||
// Sort by time, unless the times are the same, in which case sort by
|
||||
@@ -58,7 +58,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
event_fifo_id = 0;
|
||||
shutting_down = false;
|
||||
ticks = 0;
|
||||
const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {};
|
||||
const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {};
|
||||
ev_lost = CreateEvent("_lost_event", empty_timed_callback);
|
||||
if (is_multicore) {
|
||||
timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
|
||||
@@ -107,22 +107,24 @@ bool CoreTiming::HasPendingEvents() const {
|
||||
}
|
||||
|
||||
void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
const std::shared_ptr<EventType>& event_type, u64 userdata) {
|
||||
const std::shared_ptr<EventType>& event_type,
|
||||
std::uintptr_t user_data) {
|
||||
{
|
||||
std::scoped_lock scope{basic_lock};
|
||||
const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
|
||||
|
||||
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
|
||||
event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type});
|
||||
|
||||
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
|
||||
}
|
||||
event.Set();
|
||||
}
|
||||
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
std::uintptr_t user_data) {
|
||||
std::scoped_lock scope{basic_lock};
|
||||
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
|
||||
return e.type.lock().get() == event_type.get() && e.userdata == userdata;
|
||||
return e.type.lock().get() == event_type.get() && e.user_data == user_data;
|
||||
});
|
||||
|
||||
// Removing random items breaks the invariant so we have to re-establish it.
|
||||
@@ -197,7 +199,7 @@ std::optional<s64> CoreTiming::Advance() {
|
||||
|
||||
if (const auto event_type{evt.type.lock()}) {
|
||||
event_type->callback(
|
||||
evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)});
|
||||
evt.user_data, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)});
|
||||
}
|
||||
|
||||
basic_lock.lock();
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
namespace Core::Timing {
|
||||
|
||||
/// A callback that may be scheduled for a particular core timing event.
|
||||
using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>;
|
||||
using TimedCallback =
|
||||
std::function<void(std::uintptr_t user_data, std::chrono::nanoseconds ns_late)>;
|
||||
|
||||
/// Contains the characteristics of a particular event.
|
||||
struct EventType {
|
||||
@@ -94,9 +95,9 @@ public:
|
||||
|
||||
/// Schedules an event in core timing
|
||||
void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
const std::shared_ptr<EventType>& event_type, u64 userdata = 0);
|
||||
const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0);
|
||||
|
||||
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
|
||||
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data);
|
||||
|
||||
/// We only permit one event of each type in the queue at a time.
|
||||
void RemoveEvent(const std::shared_ptr<EventType>& event_type);
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
namespace Core::Hardware {
|
||||
|
||||
InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
|
||||
gpu_interrupt_event =
|
||||
Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) {
|
||||
gpu_interrupt_event = Core::Timing::CreateEvent(
|
||||
"GPUInterrupt", [this](std::uintptr_t message, std::chrono::nanoseconds) {
|
||||
auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
|
||||
const u32 syncpt = static_cast<u32>(message >> 32);
|
||||
const u32 value = static_cast<u32>(message);
|
||||
|
||||
@@ -145,7 +145,7 @@ struct KernelCore::Impl {
|
||||
|
||||
void InitializePreemption(KernelCore& kernel) {
|
||||
preemption_event = Core::Timing::CreateEvent(
|
||||
"PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) {
|
||||
"PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) {
|
||||
{
|
||||
SchedulerLock lock(kernel);
|
||||
global_scheduler.PreemptThreads();
|
||||
|
||||
@@ -33,8 +33,10 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern
|
||||
std::string name) {
|
||||
std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
|
||||
|
||||
session->request_event = Core::Timing::CreateEvent(
|
||||
name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); });
|
||||
session->request_event =
|
||||
Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) {
|
||||
session->CompleteSyncRequest();
|
||||
});
|
||||
session->name = std::move(name);
|
||||
session->parent = std::move(parent);
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Kernel {
|
||||
|
||||
TimeManager::TimeManager(Core::System& system_) : system{system_} {
|
||||
time_manager_event_type = Core::Timing::CreateEvent(
|
||||
"Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) {
|
||||
SchedulerLock lock(system.Kernel());
|
||||
Handle proper_handle = static_cast<Handle>(thread_handle);
|
||||
"Kernel::TimeManagerCallback",
|
||||
[this](std::uintptr_t thread_handle, std::chrono::nanoseconds) {
|
||||
const SchedulerLock lock(system.Kernel());
|
||||
const auto proper_handle = static_cast<Handle>(thread_handle);
|
||||
if (cancelled_events[proper_handle]) {
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<Thread> thread =
|
||||
this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
|
||||
auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
|
||||
thread->OnWakeUp();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1405,7 +1405,6 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
|
||||
// Get supported languages from NACP, if possible
|
||||
// Default to 0 (all languages supported)
|
||||
u32 supported_languages = 0;
|
||||
FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()};
|
||||
|
||||
const auto res = [this] {
|
||||
const auto title_id = system.CurrentProcess()->GetTitleID();
|
||||
|
||||
@@ -13,11 +13,23 @@
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
namespace {
|
||||
enum class Request : u32 {
|
||||
Finalize = 0x4,
|
||||
SetUserWordInfo = 0x6,
|
||||
SetCustomizeDic = 0x7,
|
||||
Calc = 0xa,
|
||||
SetCustomizedDictionaries = 0xb,
|
||||
UnsetCustomizedDictionaries = 0xc,
|
||||
UnknownD = 0xd,
|
||||
UnknownE = 0xe,
|
||||
};
|
||||
constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8;
|
||||
constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8;
|
||||
constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4;
|
||||
constexpr std::size_t DEFAULT_MAX_LENGTH = 500;
|
||||
constexpr bool INTERACTIVE_STATUS_OK = false;
|
||||
|
||||
} // Anonymous namespace
|
||||
static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
|
||||
KeyboardConfig config, std::u16string initial_text) {
|
||||
Core::Frontend::SoftwareKeyboardParameters params{};
|
||||
@@ -47,6 +59,7 @@ SoftwareKeyboard::~SoftwareKeyboard() = default;
|
||||
|
||||
void SoftwareKeyboard::Initialize() {
|
||||
complete = false;
|
||||
is_inline = false;
|
||||
initial_text.clear();
|
||||
final_data.clear();
|
||||
|
||||
@@ -56,6 +69,11 @@ void SoftwareKeyboard::Initialize() {
|
||||
ASSERT(keyboard_config_storage != nullptr);
|
||||
const auto& keyboard_config = keyboard_config_storage->GetData();
|
||||
|
||||
if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
|
||||
is_inline = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
|
||||
std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
|
||||
|
||||
@@ -87,16 +105,32 @@ void SoftwareKeyboard::ExecuteInteractive() {
|
||||
const auto storage = broker.PopInteractiveDataToApplet();
|
||||
ASSERT(storage != nullptr);
|
||||
const auto data = storage->GetData();
|
||||
const auto status = static_cast<bool>(data[0]);
|
||||
|
||||
if (status == INTERACTIVE_STATUS_OK) {
|
||||
complete = true;
|
||||
if (!is_inline) {
|
||||
const auto status = static_cast<bool>(data[0]);
|
||||
if (status == INTERACTIVE_STATUS_OK) {
|
||||
complete = true;
|
||||
} else {
|
||||
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
|
||||
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
|
||||
frontend.SendTextCheckDialog(
|
||||
Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
|
||||
[this] { broker.SignalStateChanged(); });
|
||||
}
|
||||
} else {
|
||||
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
|
||||
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
|
||||
frontend.SendTextCheckDialog(
|
||||
Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
|
||||
[this] { broker.SignalStateChanged(); });
|
||||
Request request{};
|
||||
std::memcpy(&request, data.data(), sizeof(Request));
|
||||
|
||||
switch (request) {
|
||||
case Request::Calc: {
|
||||
broker.PushNormalDataFromApplet(
|
||||
std::make_shared<IStorage>(std::move(std::vector<u8>{1})));
|
||||
broker.SignalStateChanged();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,9 +142,10 @@ void SoftwareKeyboard::Execute() {
|
||||
}
|
||||
|
||||
const auto parameters = ConvertToFrontendParameters(config, initial_text);
|
||||
|
||||
frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(std::move(text)); },
|
||||
parameters);
|
||||
if (!is_inline) {
|
||||
frontend.RequestText(
|
||||
[this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
|
||||
|
||||
@@ -78,6 +78,7 @@ private:
|
||||
KeyboardConfig config;
|
||||
std::u16string initial_text;
|
||||
bool complete = false;
|
||||
bool is_inline = false;
|
||||
std::vector<u8> final_data;
|
||||
};
|
||||
|
||||
|
||||
@@ -39,33 +39,36 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,
|
||||
|
||||
cur_entry.sampling_number = last_entry.sampling_number + 1;
|
||||
cur_entry.sampling_number2 = cur_entry.sampling_number;
|
||||
cur_entry.attribute.connected.Assign(1);
|
||||
auto& pad = cur_entry.pad_state;
|
||||
|
||||
using namespace Settings::NativeButton;
|
||||
pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
|
||||
if (Settings::values.debug_pad_enabled) {
|
||||
cur_entry.attribute.connected.Assign(1);
|
||||
auto& pad = cur_entry.pad_state;
|
||||
|
||||
const auto [stick_l_x_f, stick_l_y_f] =
|
||||
analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
|
||||
const auto [stick_r_x_f, stick_r_y_f] =
|
||||
analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
|
||||
cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
|
||||
using namespace Settings::NativeButton;
|
||||
pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
|
||||
|
||||
const auto [stick_l_x_f, stick_l_y_f] =
|
||||
analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
|
||||
const auto [stick_r_x_f, stick_r_y_f] =
|
||||
analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
|
||||
cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
|
||||
cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
|
||||
}
|
||||
|
||||
std::memcpy(data, &shared_memory, sizeof(SharedMemory));
|
||||
}
|
||||
|
||||
@@ -40,15 +40,16 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
|
||||
|
||||
cur_entry.key.fill(0);
|
||||
cur_entry.modifier = 0;
|
||||
if (Settings::values.keyboard_enabled) {
|
||||
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
|
||||
cur_entry.key[i / KEYS_PER_BYTE] |=
|
||||
(keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
|
||||
cur_entry.key[i / KEYS_PER_BYTE] |= (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE));
|
||||
for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
|
||||
cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
|
||||
cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i);
|
||||
}
|
||||
|
||||
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
|
||||
}
|
||||
|
||||
|
||||
@@ -77,8 +77,9 @@ IAppletResource::IAppletResource(Core::System& system)
|
||||
|
||||
// Register update callbacks
|
||||
pad_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) {
|
||||
UpdateControllers(userdata, ns_late);
|
||||
"HID::UpdatePadCallback",
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
UpdateControllers(user_data, ns_late);
|
||||
});
|
||||
|
||||
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
|
||||
@@ -108,7 +109,8 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
|
||||
rb.PushCopyObjects(shared_mem);
|
||||
}
|
||||
|
||||
void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) {
|
||||
void IAppletResource::UpdateControllers(std::uintptr_t user_data,
|
||||
std::chrono::nanoseconds ns_late) {
|
||||
auto& core_timing = system.CoreTiming();
|
||||
|
||||
const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
}
|
||||
|
||||
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
|
||||
void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late);
|
||||
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
|
||||
std::shared_ptr<Kernel::SharedMemory> shared_mem;
|
||||
|
||||
|
||||
@@ -67,8 +67,8 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||
|
||||
// Schedule the screen composition events
|
||||
composition_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) {
|
||||
Lock();
|
||||
"ScreenComposition", [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
|
||||
const auto guard = Lock();
|
||||
Compose();
|
||||
|
||||
const auto ticks = std::chrono::nanoseconds{GetNextTicks()};
|
||||
|
||||
@@ -54,12 +54,12 @@ public:
|
||||
/// Opens the specified display and returns the ID.
|
||||
///
|
||||
/// If an invalid display name is provided, then an empty optional is returned.
|
||||
std::optional<u64> OpenDisplay(std::string_view name);
|
||||
[[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
|
||||
|
||||
/// Creates a layer on the specified display and returns the layer ID.
|
||||
///
|
||||
/// If an invalid display ID is specified, then an empty optional is returned.
|
||||
std::optional<u64> CreateLayer(u64 display_id);
|
||||
[[nodiscard]] std::optional<u64> CreateLayer(u64 display_id);
|
||||
|
||||
/// Closes a layer on all displays for the given layer ID.
|
||||
void CloseLayer(u64 layer_id);
|
||||
@@ -67,41 +67,39 @@ public:
|
||||
/// Finds the buffer queue ID of the specified layer in the specified display.
|
||||
///
|
||||
/// If an invalid display ID or layer ID is provided, then an empty optional is returned.
|
||||
std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const;
|
||||
[[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const;
|
||||
|
||||
/// Gets the vsync event for the specified display.
|
||||
///
|
||||
/// If an invalid display ID is provided, then nullptr is returned.
|
||||
std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
|
||||
[[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
|
||||
|
||||
/// Obtains a buffer queue identified by the ID.
|
||||
BufferQueue& FindBufferQueue(u32 id);
|
||||
[[nodiscard]] BufferQueue& FindBufferQueue(u32 id);
|
||||
|
||||
/// Obtains a buffer queue identified by the ID.
|
||||
const BufferQueue& FindBufferQueue(u32 id) const;
|
||||
[[nodiscard]] const BufferQueue& FindBufferQueue(u32 id) const;
|
||||
|
||||
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
|
||||
/// finished.
|
||||
void Compose();
|
||||
|
||||
s64 GetNextTicks() const;
|
||||
[[nodiscard]] s64 GetNextTicks() const;
|
||||
|
||||
std::unique_lock<std::mutex> Lock() {
|
||||
return std::unique_lock{*guard};
|
||||
}
|
||||
[[nodiscard]] std::unique_lock<std::mutex> Lock() const { return std::unique_lock{*guard}; }
|
||||
|
||||
private:
|
||||
/// Finds the display identified by the specified ID.
|
||||
VI::Display* FindDisplay(u64 display_id);
|
||||
private :
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] VI::Display* FindDisplay(u64 display_id);
|
||||
|
||||
/// Finds the display identified by the specified ID.
|
||||
const VI::Display* FindDisplay(u64 display_id) const;
|
||||
[[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
|
||||
|
||||
/// Finds the layer identified by the specified ID in the desired display.
|
||||
VI::Layer* FindLayer(u64 display_id, u64 layer_id);
|
||||
[[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
|
||||
|
||||
/// Finds the layer identified by the specified ID in the desired display.
|
||||
const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
|
||||
[[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
|
||||
|
||||
static void VSyncThread(NVFlinger& nv_flinger);
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ private:
|
||||
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
|
||||
static_cast<u32>(transaction), flags);
|
||||
|
||||
nv_flinger->Lock();
|
||||
const auto guard = nv_flinger->Lock();
|
||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||
|
||||
switch (transaction) {
|
||||
@@ -551,7 +551,7 @@ private:
|
||||
[=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||
Kernel::ThreadWakeupReason reason) {
|
||||
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
||||
nv_flinger->Lock();
|
||||
const auto guard = nv_flinger->Lock();
|
||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||
auto result = buffer_queue.DequeueBuffer(width, height);
|
||||
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
|
||||
|
||||
@@ -188,11 +188,11 @@ CheatEngine::~CheatEngine() {
|
||||
}
|
||||
|
||||
void CheatEngine::Initialize() {
|
||||
event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" +
|
||||
Common::HexToString(metadata.main_nso_build_id),
|
||||
[this](u64 userdata, std::chrono::nanoseconds ns_late) {
|
||||
FrameCallback(userdata, ns_late);
|
||||
});
|
||||
event = Core::Timing::CreateEvent(
|
||||
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
FrameCallback(user_data, ns_late);
|
||||
});
|
||||
core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event);
|
||||
|
||||
metadata.process_id = system.CurrentProcess()->GetProcessID();
|
||||
@@ -219,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) {
|
||||
|
||||
MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70));
|
||||
|
||||
void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) {
|
||||
void CheatEngine::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
|
||||
if (is_pending_reload.exchange(false)) {
|
||||
vm.LoadProgram(cheats);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
void Reload(std::vector<CheatEntry> cheats);
|
||||
|
||||
private:
|
||||
void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late);
|
||||
void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
|
||||
DmntCheatVm vm;
|
||||
CheatProcessMetadata metadata;
|
||||
|
||||
@@ -313,30 +313,32 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
|
||||
switch (opcode_type) {
|
||||
case CheatVmOpcodeType::StoreStatic: {
|
||||
StoreStaticOpcode store_static{};
|
||||
// 0TMR00AA AAAAAAAA YYYYYYYY (YYYYYYYY)
|
||||
// Read additional words.
|
||||
const u32 second_dword = GetNextDword();
|
||||
store_static.bit_width = (first_dword >> 24) & 0xF;
|
||||
store_static.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF);
|
||||
store_static.offset_register = ((first_dword >> 16) & 0xF);
|
||||
store_static.rel_address =
|
||||
(static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword);
|
||||
store_static.value = GetNextVmInt(store_static.bit_width);
|
||||
opcode.opcode = store_static;
|
||||
const u32 bit_width = (first_dword >> 24) & 0xF;
|
||||
|
||||
opcode.opcode = StoreStaticOpcode{
|
||||
.bit_width = bit_width,
|
||||
.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF),
|
||||
.offset_register = (first_dword >> 16) & 0xF,
|
||||
.rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword,
|
||||
.value = GetNextVmInt(bit_width),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::BeginConditionalBlock: {
|
||||
BeginConditionalOpcode begin_cond{};
|
||||
// 1TMC00AA AAAAAAAA YYYYYYYY (YYYYYYYY)
|
||||
// Read additional words.
|
||||
const u32 second_dword = GetNextDword();
|
||||
begin_cond.bit_width = (first_dword >> 24) & 0xF;
|
||||
begin_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF);
|
||||
begin_cond.cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF);
|
||||
begin_cond.rel_address =
|
||||
(static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword);
|
||||
begin_cond.value = GetNextVmInt(begin_cond.bit_width);
|
||||
opcode.opcode = begin_cond;
|
||||
const u32 bit_width = (first_dword >> 24) & 0xF;
|
||||
|
||||
opcode.opcode = BeginConditionalOpcode{
|
||||
.bit_width = bit_width,
|
||||
.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF),
|
||||
.cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF),
|
||||
.rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword,
|
||||
.value = GetNextVmInt(bit_width),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::EndConditionalBlock: {
|
||||
// 20000000
|
||||
@@ -344,12 +346,14 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
opcode.opcode = EndConditionalOpcode{};
|
||||
} break;
|
||||
case CheatVmOpcodeType::ControlLoop: {
|
||||
ControlLoopOpcode ctrl_loop{};
|
||||
// 300R0000 VVVVVVVV
|
||||
// 310R0000
|
||||
// Parse register, whether loop start or loop end.
|
||||
ctrl_loop.start_loop = ((first_dword >> 24) & 0xF) == 0;
|
||||
ctrl_loop.reg_index = ((first_dword >> 20) & 0xF);
|
||||
ControlLoopOpcode ctrl_loop{
|
||||
.start_loop = ((first_dword >> 24) & 0xF) == 0,
|
||||
.reg_index = (first_dword >> 20) & 0xF,
|
||||
.num_iters = 0,
|
||||
};
|
||||
|
||||
// Read number of iters if loop start.
|
||||
if (ctrl_loop.start_loop) {
|
||||
@@ -358,66 +362,65 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
opcode.opcode = ctrl_loop;
|
||||
} break;
|
||||
case CheatVmOpcodeType::LoadRegisterStatic: {
|
||||
LoadRegisterStaticOpcode ldr_static{};
|
||||
// 400R0000 VVVVVVVV VVVVVVVV
|
||||
// Read additional words.
|
||||
ldr_static.reg_index = ((first_dword >> 16) & 0xF);
|
||||
ldr_static.value =
|
||||
(static_cast<u64>(GetNextDword()) << 32ul) | static_cast<u64>(GetNextDword());
|
||||
opcode.opcode = ldr_static;
|
||||
opcode.opcode = LoadRegisterStaticOpcode{
|
||||
.reg_index = (first_dword >> 16) & 0xF,
|
||||
.value = (static_cast<u64>(GetNextDword()) << 32) | GetNextDword(),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::LoadRegisterMemory: {
|
||||
LoadRegisterMemoryOpcode ldr_memory{};
|
||||
// 5TMRI0AA AAAAAAAA
|
||||
// Read additional words.
|
||||
const u32 second_dword = GetNextDword();
|
||||
ldr_memory.bit_width = (first_dword >> 24) & 0xF;
|
||||
ldr_memory.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF);
|
||||
ldr_memory.reg_index = ((first_dword >> 16) & 0xF);
|
||||
ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) != 0;
|
||||
ldr_memory.rel_address =
|
||||
(static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword);
|
||||
opcode.opcode = ldr_memory;
|
||||
opcode.opcode = LoadRegisterMemoryOpcode{
|
||||
.bit_width = (first_dword >> 24) & 0xF,
|
||||
.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF),
|
||||
.reg_index = ((first_dword >> 16) & 0xF),
|
||||
.load_from_reg = ((first_dword >> 12) & 0xF) != 0,
|
||||
.rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword,
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::StoreStaticToAddress: {
|
||||
StoreStaticToAddressOpcode str_static{};
|
||||
// 6T0RIor0 VVVVVVVV VVVVVVVV
|
||||
// Read additional words.
|
||||
str_static.bit_width = (first_dword >> 24) & 0xF;
|
||||
str_static.reg_index = ((first_dword >> 16) & 0xF);
|
||||
str_static.increment_reg = ((first_dword >> 12) & 0xF) != 0;
|
||||
str_static.add_offset_reg = ((first_dword >> 8) & 0xF) != 0;
|
||||
str_static.offset_reg_index = ((first_dword >> 4) & 0xF);
|
||||
str_static.value =
|
||||
(static_cast<u64>(GetNextDword()) << 32ul) | static_cast<u64>(GetNextDword());
|
||||
opcode.opcode = str_static;
|
||||
opcode.opcode = StoreStaticToAddressOpcode{
|
||||
.bit_width = (first_dword >> 24) & 0xF,
|
||||
.reg_index = (first_dword >> 16) & 0xF,
|
||||
.increment_reg = ((first_dword >> 12) & 0xF) != 0,
|
||||
.add_offset_reg = ((first_dword >> 8) & 0xF) != 0,
|
||||
.offset_reg_index = (first_dword >> 4) & 0xF,
|
||||
.value = (static_cast<u64>(GetNextDword()) << 32) | GetNextDword(),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::PerformArithmeticStatic: {
|
||||
PerformArithmeticStaticOpcode perform_math_static{};
|
||||
// 7T0RC000 VVVVVVVV
|
||||
// Read additional words.
|
||||
perform_math_static.bit_width = (first_dword >> 24) & 0xF;
|
||||
perform_math_static.reg_index = ((first_dword >> 16) & 0xF);
|
||||
perform_math_static.math_type =
|
||||
static_cast<RegisterArithmeticType>((first_dword >> 12) & 0xF);
|
||||
perform_math_static.value = GetNextDword();
|
||||
opcode.opcode = perform_math_static;
|
||||
opcode.opcode = PerformArithmeticStaticOpcode{
|
||||
.bit_width = (first_dword >> 24) & 0xF,
|
||||
.reg_index = ((first_dword >> 16) & 0xF),
|
||||
.math_type = static_cast<RegisterArithmeticType>((first_dword >> 12) & 0xF),
|
||||
.value = GetNextDword(),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::BeginKeypressConditionalBlock: {
|
||||
BeginKeypressConditionalOpcode begin_keypress_cond{};
|
||||
// 8kkkkkkk
|
||||
// Just parse the mask.
|
||||
begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF;
|
||||
opcode.opcode = begin_keypress_cond;
|
||||
opcode.opcode = BeginKeypressConditionalOpcode{
|
||||
.key_mask = first_dword & 0x0FFFFFFF,
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::PerformArithmeticRegister: {
|
||||
PerformArithmeticRegisterOpcode perform_math_reg{};
|
||||
// 9TCRSIs0 (VVVVVVVV (VVVVVVVV))
|
||||
perform_math_reg.bit_width = (first_dword >> 24) & 0xF;
|
||||
perform_math_reg.math_type = static_cast<RegisterArithmeticType>((first_dword >> 20) & 0xF);
|
||||
perform_math_reg.dst_reg_index = ((first_dword >> 16) & 0xF);
|
||||
perform_math_reg.src_reg_1_index = ((first_dword >> 12) & 0xF);
|
||||
perform_math_reg.has_immediate = ((first_dword >> 8) & 0xF) != 0;
|
||||
PerformArithmeticRegisterOpcode perform_math_reg{
|
||||
.bit_width = (first_dword >> 24) & 0xF,
|
||||
.math_type = static_cast<RegisterArithmeticType>((first_dword >> 20) & 0xF),
|
||||
.dst_reg_index = (first_dword >> 16) & 0xF,
|
||||
.src_reg_1_index = (first_dword >> 12) & 0xF,
|
||||
.src_reg_2_index = 0,
|
||||
.has_immediate = ((first_dword >> 8) & 0xF) != 0,
|
||||
.value = {},
|
||||
};
|
||||
if (perform_math_reg.has_immediate) {
|
||||
perform_math_reg.src_reg_2_index = 0;
|
||||
perform_math_reg.value = GetNextVmInt(perform_math_reg.bit_width);
|
||||
@@ -427,7 +430,6 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
opcode.opcode = perform_math_reg;
|
||||
} break;
|
||||
case CheatVmOpcodeType::StoreRegisterToAddress: {
|
||||
StoreRegisterToAddressOpcode str_register{};
|
||||
// ATSRIOxa (aaaaaaaa)
|
||||
// A = opcode 10
|
||||
// T = bit width
|
||||
@@ -439,20 +441,23 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
// Relative Address
|
||||
// x = offset register (for offset type 1), memory type (for offset type 3)
|
||||
// a = relative address (for offset type 2+3)
|
||||
str_register.bit_width = (first_dword >> 24) & 0xF;
|
||||
str_register.str_reg_index = ((first_dword >> 20) & 0xF);
|
||||
str_register.addr_reg_index = ((first_dword >> 16) & 0xF);
|
||||
str_register.increment_reg = ((first_dword >> 12) & 0xF) != 0;
|
||||
str_register.ofs_type = static_cast<StoreRegisterOffsetType>(((first_dword >> 8) & 0xF));
|
||||
str_register.ofs_reg_index = ((first_dword >> 4) & 0xF);
|
||||
StoreRegisterToAddressOpcode str_register{
|
||||
.bit_width = (first_dword >> 24) & 0xF,
|
||||
.str_reg_index = (first_dword >> 20) & 0xF,
|
||||
.addr_reg_index = (first_dword >> 16) & 0xF,
|
||||
.increment_reg = ((first_dword >> 12) & 0xF) != 0,
|
||||
.ofs_type = static_cast<StoreRegisterOffsetType>(((first_dword >> 8) & 0xF)),
|
||||
.mem_type = MemoryAccessType::MainNso,
|
||||
.ofs_reg_index = (first_dword >> 4) & 0xF,
|
||||
.rel_address = 0,
|
||||
};
|
||||
switch (str_register.ofs_type) {
|
||||
case StoreRegisterOffsetType::None:
|
||||
case StoreRegisterOffsetType::Reg:
|
||||
// Nothing more to do
|
||||
break;
|
||||
case StoreRegisterOffsetType::Imm:
|
||||
str_register.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
str_register.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
case StoreRegisterOffsetType::MemReg:
|
||||
str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
@@ -460,8 +465,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
case StoreRegisterOffsetType::MemImm:
|
||||
case StoreRegisterOffsetType::MemImmReg:
|
||||
str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
str_register.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
str_register.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
default:
|
||||
str_register.ofs_type = StoreRegisterOffsetType::None;
|
||||
@@ -470,7 +474,6 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
opcode.opcode = str_register;
|
||||
} break;
|
||||
case CheatVmOpcodeType::BeginRegisterConditionalBlock: {
|
||||
BeginRegisterConditionalOpcode begin_reg_cond{};
|
||||
// C0TcSX##
|
||||
// C0TcS0Ma aaaaaaaa
|
||||
// C0TcS1Mr
|
||||
@@ -492,11 +495,19 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
// r = offset register.
|
||||
// X = other register.
|
||||
// V = value.
|
||||
begin_reg_cond.bit_width = (first_dword >> 20) & 0xF;
|
||||
begin_reg_cond.cond_type =
|
||||
static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF);
|
||||
begin_reg_cond.val_reg_index = ((first_dword >> 12) & 0xF);
|
||||
begin_reg_cond.comp_type = static_cast<CompareRegisterValueType>((first_dword >> 8) & 0xF);
|
||||
|
||||
BeginRegisterConditionalOpcode begin_reg_cond{
|
||||
.bit_width = (first_dword >> 20) & 0xF,
|
||||
.cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF),
|
||||
.val_reg_index = (first_dword >> 12) & 0xF,
|
||||
.comp_type = static_cast<CompareRegisterValueType>((first_dword >> 8) & 0xF),
|
||||
.mem_type = MemoryAccessType::MainNso,
|
||||
.addr_reg_index = 0,
|
||||
.other_reg_index = 0,
|
||||
.ofs_reg_index = 0,
|
||||
.rel_address = 0,
|
||||
.value = {},
|
||||
};
|
||||
|
||||
switch (begin_reg_cond.comp_type) {
|
||||
case CompareRegisterValueType::StaticValue:
|
||||
@@ -508,26 +519,25 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
case CompareRegisterValueType::MemoryRelAddr:
|
||||
begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
begin_reg_cond.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
(static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
case CompareRegisterValueType::MemoryOfsReg:
|
||||
begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
begin_reg_cond.ofs_reg_index = (first_dword & 0xF);
|
||||
break;
|
||||
case CompareRegisterValueType::RegisterRelAddr:
|
||||
begin_reg_cond.addr_reg_index = ((first_dword >> 4) & 0xF);
|
||||
begin_reg_cond.addr_reg_index = (first_dword >> 4) & 0xF;
|
||||
begin_reg_cond.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
(static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
case CompareRegisterValueType::RegisterOfsReg:
|
||||
begin_reg_cond.addr_reg_index = ((first_dword >> 4) & 0xF);
|
||||
begin_reg_cond.ofs_reg_index = (first_dword & 0xF);
|
||||
begin_reg_cond.addr_reg_index = (first_dword >> 4) & 0xF;
|
||||
begin_reg_cond.ofs_reg_index = first_dword & 0xF;
|
||||
break;
|
||||
}
|
||||
opcode.opcode = begin_reg_cond;
|
||||
} break;
|
||||
case CheatVmOpcodeType::SaveRestoreRegister: {
|
||||
SaveRestoreRegisterOpcode save_restore_reg{};
|
||||
// C10D0Sx0
|
||||
// C1 = opcode 0xC1
|
||||
// D = destination index.
|
||||
@@ -535,36 +545,37 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
// x = 3 if clearing reg, 2 if clearing saved value, 1 if saving a register, 0 if restoring
|
||||
// a register.
|
||||
// NOTE: If we add more save slots later, current encoding is backwards compatible.
|
||||
save_restore_reg.dst_index = (first_dword >> 16) & 0xF;
|
||||
save_restore_reg.src_index = (first_dword >> 8) & 0xF;
|
||||
save_restore_reg.op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 4) & 0xF);
|
||||
opcode.opcode = save_restore_reg;
|
||||
opcode.opcode = SaveRestoreRegisterOpcode{
|
||||
.dst_index = (first_dword >> 16) & 0xF,
|
||||
.src_index = (first_dword >> 8) & 0xF,
|
||||
.op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 4) & 0xF),
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::SaveRestoreRegisterMask: {
|
||||
SaveRestoreRegisterMaskOpcode save_restore_regmask{};
|
||||
// C2x0XXXX
|
||||
// C2 = opcode 0xC2
|
||||
// x = 3 if clearing reg, 2 if clearing saved value, 1 if saving, 0 if restoring.
|
||||
// X = 16-bit bitmask, bit i --> save or restore register i.
|
||||
save_restore_regmask.op_type =
|
||||
static_cast<SaveRestoreRegisterOpType>((first_dword >> 20) & 0xF);
|
||||
SaveRestoreRegisterMaskOpcode save_restore_regmask{
|
||||
.op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 20) & 0xF),
|
||||
.should_operate = {},
|
||||
};
|
||||
for (std::size_t i = 0; i < NumRegisters; i++) {
|
||||
save_restore_regmask.should_operate[i] = (first_dword & (1u << i)) != 0;
|
||||
save_restore_regmask.should_operate[i] = (first_dword & (1U << i)) != 0;
|
||||
}
|
||||
opcode.opcode = save_restore_regmask;
|
||||
} break;
|
||||
case CheatVmOpcodeType::ReadWriteStaticRegister: {
|
||||
ReadWriteStaticRegisterOpcode rw_static_reg{};
|
||||
// C3000XXx
|
||||
// C3 = opcode 0xC3.
|
||||
// XX = static register index.
|
||||
// x = register index.
|
||||
rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF);
|
||||
rw_static_reg.idx = (first_dword & 0xF);
|
||||
opcode.opcode = rw_static_reg;
|
||||
opcode.opcode = ReadWriteStaticRegisterOpcode{
|
||||
.static_idx = (first_dword >> 4) & 0xFF,
|
||||
.idx = first_dword & 0xF,
|
||||
};
|
||||
} break;
|
||||
case CheatVmOpcodeType::DebugLog: {
|
||||
DebugLogOpcode debug_log{};
|
||||
// FFFTIX##
|
||||
// FFFTI0Ma aaaaaaaa
|
||||
// FFFTI1Mr
|
||||
@@ -583,31 +594,36 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
|
||||
// a = relative address.
|
||||
// r = offset register.
|
||||
// X = value register.
|
||||
debug_log.bit_width = (first_dword >> 16) & 0xF;
|
||||
debug_log.log_id = ((first_dword >> 12) & 0xF);
|
||||
debug_log.val_type = static_cast<DebugLogValueType>((first_dword >> 8) & 0xF);
|
||||
DebugLogOpcode debug_log{
|
||||
.bit_width = (first_dword >> 16) & 0xF,
|
||||
.log_id = (first_dword >> 12) & 0xF,
|
||||
.val_type = static_cast<DebugLogValueType>((first_dword >> 8) & 0xF),
|
||||
.mem_type = MemoryAccessType::MainNso,
|
||||
.addr_reg_index = 0,
|
||||
.val_reg_index = 0,
|
||||
.ofs_reg_index = 0,
|
||||
.rel_address = 0,
|
||||
};
|
||||
|
||||
switch (debug_log.val_type) {
|
||||
case DebugLogValueType::RegisterValue:
|
||||
debug_log.val_reg_index = ((first_dword >> 4) & 0xF);
|
||||
debug_log.val_reg_index = (first_dword >> 4) & 0xF;
|
||||
break;
|
||||
case DebugLogValueType::MemoryRelAddr:
|
||||
debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
debug_log.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
debug_log.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
case DebugLogValueType::MemoryOfsReg:
|
||||
debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF);
|
||||
debug_log.ofs_reg_index = (first_dword & 0xF);
|
||||
debug_log.ofs_reg_index = first_dword & 0xF;
|
||||
break;
|
||||
case DebugLogValueType::RegisterRelAddr:
|
||||
debug_log.addr_reg_index = ((first_dword >> 4) & 0xF);
|
||||
debug_log.rel_address =
|
||||
((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword()));
|
||||
debug_log.addr_reg_index = (first_dword >> 4) & 0xF;
|
||||
debug_log.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword();
|
||||
break;
|
||||
case DebugLogValueType::RegisterOfsReg:
|
||||
debug_log.addr_reg_index = ((first_dword >> 4) & 0xF);
|
||||
debug_log.ofs_reg_index = (first_dword & 0xF);
|
||||
debug_log.addr_reg_index = (first_dword >> 4) & 0xF;
|
||||
debug_log.ofs_reg_index = first_dword & 0xF;
|
||||
break;
|
||||
}
|
||||
opcode.opcode = debug_log;
|
||||
|
||||
@@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
|
||||
|
||||
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
|
||||
: core_timing{core_timing_}, memory{memory_} {
|
||||
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
|
||||
[this](u64 userdata, std::chrono::nanoseconds ns_late) {
|
||||
FrameCallback(userdata, ns_late);
|
||||
});
|
||||
event = Core::Timing::CreateEvent(
|
||||
"MemoryFreezer::FrameCallback",
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
FrameCallback(user_data, ns_late);
|
||||
});
|
||||
core_timing.ScheduleEvent(memory_freezer_ns, event);
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const {
|
||||
return entries;
|
||||
}
|
||||
|
||||
void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) {
|
||||
void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
|
||||
if (!IsActive()) {
|
||||
LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
|
||||
return;
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
std::vector<Entry> GetEntries() const;
|
||||
|
||||
private:
|
||||
void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late);
|
||||
void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
void FillEntryReads();
|
||||
|
||||
std::atomic_bool active{false};
|
||||
|
||||
@@ -254,7 +254,7 @@ void Adapter::GetGCEndpoint(libusb_device* device) {
|
||||
sizeof(clear_payload), nullptr, 16);
|
||||
|
||||
adapter_thread_running = true;
|
||||
adapter_input_thread = std::thread([=] { Read(); }); // Read input
|
||||
adapter_input_thread = std::thread(&Adapter::Read, this);
|
||||
}
|
||||
|
||||
Adapter::~Adapter() {
|
||||
@@ -265,7 +265,9 @@ void Adapter::Reset() {
|
||||
if (adapter_thread_running) {
|
||||
adapter_thread_running = false;
|
||||
}
|
||||
adapter_input_thread.join();
|
||||
if (adapter_input_thread.joinable()) {
|
||||
adapter_input_thread.join();
|
||||
}
|
||||
|
||||
adapter_controllers_status.fill(ControllerTypes::None);
|
||||
get_origin.fill(true);
|
||||
|
||||
@@ -76,8 +76,7 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
|
||||
|
||||
// button is not an axis/stick button
|
||||
if (button_id != PAD_STICK_ID) {
|
||||
auto button = std::make_unique<GCButton>(port, button_id, adapter.get());
|
||||
return std::move(button);
|
||||
return std::make_unique<GCButton>(port, button_id, adapter.get());
|
||||
}
|
||||
|
||||
// For Axis buttons, used by the binary sticks.
|
||||
@@ -264,7 +263,8 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
|
||||
if (analog_x_axis == -1) {
|
||||
analog_x_axis = axis;
|
||||
controller_number = static_cast<int>(port);
|
||||
} else if (analog_y_axis == -1 && analog_x_axis != axis && controller_number == port) {
|
||||
} else if (analog_y_axis == -1 && analog_x_axis != axis &&
|
||||
controller_number == static_cast<int>(port)) {
|
||||
analog_y_axis = axis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "common/logging/log.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/protocol.h"
|
||||
|
||||
@@ -25,10 +25,10 @@ std::bitset<CB_IDS.size()> callbacks_ran_flags;
|
||||
u64 expected_callback = 0;
|
||||
|
||||
template <unsigned int IDX>
|
||||
void HostCallbackTemplate(u64 userdata, std::chrono::nanoseconds ns_late) {
|
||||
void HostCallbackTemplate(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
static_assert(IDX < CB_IDS.size(), "IDX out of range");
|
||||
callbacks_ran_flags.set(IDX);
|
||||
REQUIRE(CB_IDS[IDX] == userdata);
|
||||
REQUIRE(CB_IDS[IDX] == user_data);
|
||||
REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
|
||||
delays[IDX] = ns_late.count();
|
||||
++expected_callback;
|
||||
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
const Tegra::DmaPusher& DmaPusher() const;
|
||||
|
||||
struct Regs {
|
||||
static constexpr size_t NUM_REGS = 0x100;
|
||||
static constexpr size_t NUM_REGS = 0x40;
|
||||
|
||||
union {
|
||||
struct {
|
||||
@@ -271,7 +271,7 @@ public:
|
||||
u32 semaphore_trigger;
|
||||
INSERT_UNION_PADDING_WORDS(0xC);
|
||||
|
||||
// The puser and the puller share the reference counter, the pusher only has read
|
||||
// The pusher and the puller share the reference counter, the pusher only has read
|
||||
// access
|
||||
u32 reference_count;
|
||||
INSERT_UNION_PADDING_WORDS(0x5);
|
||||
|
||||
@@ -532,10 +532,6 @@ void RasterizerVulkan::Clear() {
|
||||
|
||||
scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,
|
||||
clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) {
|
||||
VkClearValue clear_value;
|
||||
clear_value.depthStencil.depth = clear_depth;
|
||||
clear_value.depthStencil.stencil = clear_stencil;
|
||||
|
||||
VkClearAttachment attachment;
|
||||
attachment.aspectMask = aspect_flags;
|
||||
attachment.colorAttachment = 0;
|
||||
|
||||
@@ -156,6 +156,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
|
||||
.minImageCount = requested_image_count,
|
||||
.imageFormat = surface_format.format,
|
||||
.imageColorSpace = surface_format.colorSpace,
|
||||
.imageExtent = {},
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
@@ -204,6 +205,7 @@ void VKSwapchain::CreateImageViews() {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = {},
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = image_format,
|
||||
.components =
|
||||
|
||||
@@ -138,6 +138,7 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP
|
||||
.flags = 0,
|
||||
.imageType = SurfaceTargetToImage(params.target),
|
||||
.format = format,
|
||||
.extent = {},
|
||||
.mipLevels = params.num_levels,
|
||||
.arrayLayers = static_cast<u32>(params.GetNumLayers()),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
@@ -458,6 +459,7 @@ VkImageView CachedSurfaceView::GetAttachment() {
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = surface.GetImageHandle(),
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_1D,
|
||||
.format = surface.GetImage().GetFormat(),
|
||||
.components =
|
||||
{
|
||||
|
||||
@@ -170,26 +170,6 @@
|
||||
<string>Dump</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="dump_decompressed_nso">
|
||||
<property name="whatsThis">
|
||||
<string>When checked, any NSO yuzu tries to load or patch will be copied decompressed to the yuzu/dump directory.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dump Decompressed NSOs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="dump_exefs">
|
||||
<property name="whatsThis">
|
||||
<string>When checked, any game that yuzu loads will have its ExeFS dumped to the yuzu/dump directory.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dump ExeFS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="reporting_services">
|
||||
<property name="text">
|
||||
@@ -257,8 +237,6 @@
|
||||
<tabstop>open_log_button</tabstop>
|
||||
<tabstop>homebrew_args_edit</tabstop>
|
||||
<tabstop>enable_graphics_debugging</tabstop>
|
||||
<tabstop>dump_decompressed_nso</tabstop>
|
||||
<tabstop>dump_exefs</tabstop>
|
||||
<tabstop>reporting_services</tabstop>
|
||||
<tabstop>quest_flag</tabstop>
|
||||
</tabstops>
|
||||
|
||||