diff options
Diffstat (limited to 'src/core')
37 files changed, 450 insertions, 499 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c1cc62a45..9dbe5bdca 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2018 yuzu Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + add_library(core STATIC announce_multiplayer_session.cpp announce_multiplayer_session.h @@ -448,6 +451,7 @@ add_library(core STATIC hle/service/hid/hidbus.h hle/service/hid/irs.cpp hle/service/hid/irs.h + hle/service/hid/irs_ring_lifo.h hle/service/hid/ring_lifo.h hle/service/hid/xcd.cpp hle/service/hid/xcd.h @@ -723,8 +727,6 @@ add_library(core STATIC internal_network/sockets.h loader/deconstructed_rom_directory.cpp loader/deconstructed_rom_directory.h - loader/elf.cpp - loader/elf.h loader/kip.cpp loader/kip.h loader/loader.cpp diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index c092db9ff..73f259525 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index 6aae79c48..e9123c13d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <fmt/format.h> #include "common/logging/log.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index f271b2070..5b2a51636 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/core.cpp b/src/core/core.cpp index 95791a07f..ea32a4a8d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <array> #include <atomic> diff --git a/src/core/core.h b/src/core/core.h index 13122dd61..0ce3b1d60 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 5425637f5..2dbb99c8b 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -6,9 +6,7 @@ #include <string> #include <tuple> -#include "common/logging/log.h" #include "common/microprofile.h" -#include "common/thread.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/hardware_properties.h" @@ -44,10 +42,10 @@ CoreTiming::CoreTiming() CoreTiming::~CoreTiming() = default; -void CoreTiming::ThreadEntry(CoreTiming& instance, size_t id) { - const std::string name = "yuzu:HostTiming_" + std::to_string(id); - MicroProfileOnThreadCreate(name.c_str()); - Common::SetCurrentThreadName(name.c_str()); +void CoreTiming::ThreadEntry(CoreTiming& instance) { + constexpr char name[] = "yuzu:HostTiming"; + MicroProfileOnThreadCreate(name); + Common::SetCurrentThreadName(name); Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical); instance.on_thread_init(); instance.ThreadLoop(); @@ -63,127 +61,100 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { -> std::optional<std::chrono::nanoseconds> { return std::nullopt; }; ev_lost = CreateEvent("_lost_event", empty_timed_callback); if (is_multicore) { - worker_threads.emplace_back(ThreadEntry, std::ref(*this), 0); + timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); } } void CoreTiming::Shutdown() { - is_paused = true; + paused = true; shutting_down = true; - std::atomic_thread_fence(std::memory_order_release); - - event_cv.notify_all(); - wait_pause_cv.notify_all(); - for (auto& thread : worker_threads) { - thread.join(); + pause_event.Set(); + event.Set(); + if (timer_thread) { + timer_thread->join(); } - worker_threads.clear(); pause_callbacks.clear(); ClearPendingEvents(); + timer_thread.reset(); has_started = false; } -void CoreTiming::Pause(bool is_paused_) { - std::unique_lock main_lock(event_mutex); - if (is_paused_ == paused_state.load(std::memory_order_relaxed)) { - return; - } - if (is_multicore) { - is_paused = is_paused_; - event_cv.notify_all(); - if (!is_paused_) { - wait_pause_cv.notify_all(); - } - } - paused_state.store(is_paused_, std::memory_order_relaxed); +void CoreTiming::Pause(bool is_paused) { + paused = is_paused; + pause_event.Set(); - if (!is_paused_) { + if (!is_paused) { pause_end_time = GetGlobalTimeNs().count(); } for (auto& cb : pause_callbacks) { - cb(is_paused_); + cb(is_paused); } } -void CoreTiming::SyncPause(bool is_paused_) { - std::unique_lock main_lock(event_mutex); - if (is_paused_ == paused_state.load(std::memory_order_relaxed)) { +void CoreTiming::SyncPause(bool is_paused) { + if (is_paused == paused && paused_set == paused) { return; } - if (is_multicore) { - is_paused = is_paused_; - event_cv.notify_all(); - if (!is_paused_) { - wait_pause_cv.notify_all(); - } - } - paused_state.store(is_paused_, std::memory_order_relaxed); - if (is_multicore) { - if (is_paused_) { - wait_signal_cv.wait(main_lock, [this] { return pause_count == worker_threads.size(); }); - } else { - wait_signal_cv.wait(main_lock, [this] { return pause_count == 0; }); + Pause(is_paused); + if (timer_thread) { + if (!is_paused) { + pause_event.Set(); } + event.Set(); + while (paused_set != is_paused) + ; } - if (!is_paused_) { + if (!is_paused) { pause_end_time = GetGlobalTimeNs().count(); } for (auto& cb : pause_callbacks) { - cb(is_paused_); + cb(is_paused); } } bool CoreTiming::IsRunning() const { - return !paused_state.load(std::memory_order_acquire); + return !paused_set; } bool CoreTiming::HasPendingEvents() const { - std::unique_lock main_lock(event_mutex); - return !event_queue.empty() || pending_events.load(std::memory_order_relaxed) != 0; + return !(wait_set && event_queue.empty()); } void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, bool absolute_time) { + { + std::scoped_lock scope{basic_lock}; + const auto next_time{absolute_time ? ns_into_future : GetGlobalTimeNs() + ns_into_future}; - std::unique_lock main_lock(event_mutex); - const auto next_time{absolute_time ? ns_into_future : GetGlobalTimeNs() + ns_into_future}; - - event_queue.emplace_back(Event{next_time.count(), event_fifo_id++, user_data, event_type, 0}); - pending_events.fetch_add(1, std::memory_order_relaxed); - - std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - - if (is_multicore) { - event_cv.notify_one(); + event_queue.emplace_back( + Event{next_time.count(), event_fifo_id++, user_data, event_type, 0}); + std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); } + + event.Set(); } void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, std::chrono::nanoseconds resched_time, const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, bool absolute_time) { - std::unique_lock main_lock(event_mutex); + std::scoped_lock scope{basic_lock}; const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; event_queue.emplace_back( Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()}); - pending_events.fetch_add(1, std::memory_order_relaxed); std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - - if (is_multicore) { - event_cv.notify_one(); - } } void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data) { - std::unique_lock main_lock(event_mutex); + 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.user_data == user_data; }); @@ -192,7 +163,6 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, if (itr != event_queue.end()) { event_queue.erase(itr, event_queue.end()); std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - pending_events.fetch_sub(1, std::memory_order_relaxed); } } @@ -232,12 +202,11 @@ u64 CoreTiming::GetClockTicks() const { } void CoreTiming::ClearPendingEvents() { - std::unique_lock main_lock(event_mutex); event_queue.clear(); } void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { - std::unique_lock main_lock(event_mutex); + std::scoped_lock lock{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(); @@ -251,28 +220,27 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { } void CoreTiming::RegisterPauseCallback(PauseCallback&& callback) { - std::unique_lock main_lock(event_mutex); + std::scoped_lock lock{basic_lock}; pause_callbacks.emplace_back(std::move(callback)); } std::optional<s64> CoreTiming::Advance() { + std::scoped_lock lock{advance_lock, basic_lock}; global_timer = GetGlobalTimeNs().count(); - std::unique_lock main_lock(event_mutex); while (!event_queue.empty() && event_queue.front().time <= global_timer) { Event evt = std::move(event_queue.front()); std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); event_queue.pop_back(); if (const auto event_type{evt.type.lock()}) { - event_mutex.unlock(); + basic_lock.unlock(); const auto new_schedule_time{event_type->callback( evt.user_data, evt.time, std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt.time})}; - event_mutex.lock(); - pending_events.fetch_sub(1, std::memory_order_relaxed); + basic_lock.lock(); if (evt.reschedule_time != 0) { // If this event was scheduled into a pause, its time now is going to be way behind. @@ -285,9 +253,9 @@ std::optional<s64> CoreTiming::Advance() { const auto next_schedule_time{new_schedule_time.has_value() ? new_schedule_time.value().count() : evt.reschedule_time}; + event_queue.emplace_back( Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); - pending_events.fetch_add(1, std::memory_order_relaxed); std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); } } @@ -304,34 +272,27 @@ std::optional<s64> CoreTiming::Advance() { } void CoreTiming::ThreadLoop() { - const auto predicate = [this] { return !event_queue.empty() || is_paused; }; has_started = true; while (!shutting_down) { - while (!is_paused && !shutting_down) { + while (!paused) { + paused_set = false; const auto next_time = Advance(); if (next_time) { if (*next_time > 0) { std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); - std::unique_lock main_lock(event_mutex); - event_cv.wait_for(main_lock, next_time_ns, predicate); + event.WaitFor(next_time_ns); } } else { - std::unique_lock main_lock(event_mutex); - event_cv.wait(main_lock, predicate); + wait_set = true; + event.Wait(); } + wait_set = false; } - std::unique_lock main_lock(event_mutex); - pause_count++; - if (pause_count == worker_threads.size()) { - clock->Pause(true); - wait_signal_cv.notify_all(); - } - wait_pause_cv.wait(main_lock, [this] { return !is_paused || shutting_down; }); - pause_count--; - if (pause_count == 0) { - clock->Pause(false); - wait_signal_cv.notify_all(); - } + + paused_set = true; + clock->Pause(true); + pause_event.Wait(); + clock->Pause(false); } } diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 09b6ed81a..6aa3ae923 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -5,7 +5,6 @@ #include <atomic> #include <chrono> -#include <condition_variable> #include <functional> #include <memory> #include <mutex> @@ -15,6 +14,7 @@ #include <vector> #include "common/common_types.h" +#include "common/thread.h" #include "common/wall_clock.h" namespace Core::Timing { @@ -143,7 +143,7 @@ private: /// Clear all pending events. This should ONLY be done on exit. void ClearPendingEvents(); - static void ThreadEntry(CoreTiming& instance, size_t id); + static void ThreadEntry(CoreTiming& instance); void ThreadLoop(); std::unique_ptr<Common::WallClock> clock; @@ -156,24 +156,21 @@ private: // accomodated by the standard adaptor class. std::vector<Event> event_queue; u64 event_fifo_id = 0; - std::atomic<size_t> pending_events{}; std::shared_ptr<EventType> ev_lost; + Common::Event event{}; + Common::Event pause_event{}; + std::mutex basic_lock; + std::mutex advance_lock; + std::unique_ptr<std::thread> timer_thread; + std::atomic<bool> paused{}; + std::atomic<bool> paused_set{}; + std::atomic<bool> wait_set{}; + std::atomic<bool> shutting_down{}; std::atomic<bool> has_started{}; std::function<void()> on_thread_init{}; - std::vector<std::thread> worker_threads; - - std::condition_variable event_cv; - std::condition_variable wait_pause_cv; - std::condition_variable wait_signal_cv; - mutable std::mutex event_mutex; - - std::atomic<bool> paused_state{}; - bool is_paused{}; - bool shutting_down{}; bool is_multicore{}; - size_t pause_count{}; s64 pause_end_time{}; /// Cycle timing diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index ff15b3e23..7cee0c7df 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h @@ -1,6 +1,5 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index a405e3c94..094d1e713 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -17,6 +17,8 @@ struct KeyboardInitializeParameters { std::u16string sub_text; std::u16string guide_text; std::u16string initial_text; + char16_t left_optional_symbol_key; + char16_t right_optional_symbol_key; u32 max_text_length; u32 min_text_length; s32 initial_cursor_position; diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 57c6ffc43..1be2dccb0 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <mutex> #include "core/frontend/emu_window.h" diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index b3bffecb2..ac1906d5e 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 602e12606..416da15ec 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -1,6 +1,5 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 004bb2005..d631c0357 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -1,6 +1,5 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index d63e77d15..3cb22ff4d 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -1,6 +1,5 @@ -// Copyright 2021 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2021 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include "common/scope_exit.h" #include "core/hle/kernel/hle_ipc.h" diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index ef8583efc..e17eff28f 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -1,6 +1,5 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index b662788b3..d3e99665f 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1,6 +1,5 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2015 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> #include <bitset> diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 5e3e22ad8..d56d73bab 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -1,6 +1,5 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2015 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index b77735736..8ff1545b6 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" #include "core/core.h" diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 2c1db0e70..34cb98456 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/result.h b/src/core/hle/result.h index aa9e5b89d..4de44cd06 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp index faa092957..c18236045 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp @@ -536,6 +536,8 @@ void SoftwareKeyboard::InitializeFrontendNormalKeyboard() { .sub_text{std::move(sub_text)}, .guide_text{std::move(guide_text)}, .initial_text{initial_text}, + .left_optional_symbol_key{swkbd_config_common.left_optional_symbol_key}, + .right_optional_symbol_key{swkbd_config_common.right_optional_symbol_key}, .max_text_length{max_text_length}, .min_text_length{min_text_length}, .initial_cursor_position{initial_cursor_position}, @@ -591,6 +593,8 @@ void SoftwareKeyboard::InitializeFrontendInlineKeyboardOld() { .sub_text{}, .guide_text{}, .initial_text{current_text}, + .left_optional_symbol_key{appear_arg.left_optional_symbol_key}, + .right_optional_symbol_key{appear_arg.right_optional_symbol_key}, .max_text_length{max_text_length}, .min_text_length{min_text_length}, .initial_cursor_position{initial_cursor_position}, @@ -632,6 +636,8 @@ void SoftwareKeyboard::InitializeFrontendInlineKeyboardNew() { .sub_text{}, .guide_text{}, .initial_text{current_text}, + .left_optional_symbol_key{appear_arg.left_optional_symbol_key}, + .right_optional_symbol_key{appear_arg.right_optional_symbol_key}, .max_text_length{max_text_length}, .min_text_length{min_text_length}, .initial_cursor_position{initial_cursor_position}, diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index d5107e41f..c4b44cbf9 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -166,7 +166,7 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { if (result.IsSuccess()) { auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); - MakeProcessor<ClusteringProcessor>(parameters.camera_handle, device); + MakeProcessorWithCoreContext<ClusteringProcessor>(parameters.camera_handle, device); auto& image_transfer_processor = GetProcessor<ClusteringProcessor>(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); diff --git a/src/core/hle/service/hid/irs_ring_lifo.h b/src/core/hle/service/hid/irs_ring_lifo.h new file mode 100644 index 000000000..255d1d296 --- /dev/null +++ b/src/core/hle/service/hid/irs_ring_lifo.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> + +#include "common/common_types.h" + +namespace Service::IRS { + +template <typename State, std::size_t max_buffer_size> +struct Lifo { + s64 sampling_number{}; + s64 buffer_count{}; + std::array<State, max_buffer_size> entries{}; + + const State& ReadCurrentEntry() const { + return entries[GetBufferTail()]; + } + + const State& ReadPreviousEntry() const { + return entries[GetPreviousEntryIndex()]; + } + + s64 GetBufferTail() const { + return sampling_number % max_buffer_size; + } + + std::size_t GetPreviousEntryIndex() const { + return static_cast<size_t>((GetBufferTail() + max_buffer_size - 1) % max_buffer_size); + } + + std::size_t GetNextEntryIndex() const { + return static_cast<size_t>((GetBufferTail() + 1) % max_buffer_size); + } + + void WriteNextEntry(const State& new_state) { + if (buffer_count < static_cast<s64>(max_buffer_size)) { + buffer_count++; + } + sampling_number++; + entries[GetBufferTail()] = new_state; + } +}; + +} // namespace Service::IRS diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp index 6479af212..e2f4ae876 100644 --- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp +++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp @@ -1,34 +1,265 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include <queue> + +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/irsensor/clustering_processor.h" namespace Service::IRS { -ClusteringProcessor::ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format) - : device(device_format) { +ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_, + Core::IrSensor::DeviceFormat& device_format, + std::size_t npad_index) + : device{device_format} { + npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); + device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; + SetDefaultConfig(); + + shared_memory = std::construct_at( + reinterpret_cast<ClusteringSharedMemory*>(&device_format.state.processor_raw_data)); + + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, + .is_npad_service = true, + }; + callback_key = npad_device->SetCallback(engine_callback); } -ClusteringProcessor::~ClusteringProcessor() = default; +ClusteringProcessor::~ClusteringProcessor() { + npad_device->DeleteCallback(callback_key); +}; -void ClusteringProcessor::StartProcessor() {} +void ClusteringProcessor::StartProcessor() { + device.camera_status = Core::IrSensor::IrCameraStatus::Available; + device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; +} void ClusteringProcessor::SuspendProcessor() {} void ClusteringProcessor::StopProcessor() {} +void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { + if (type != Core::HID::ControllerTriggerType::IrSensor) { + return; + } + + next_state = {}; + const auto camera_data = npad_device->GetCamera(); + auto filtered_image = camera_data.data; + + RemoveLowIntensityData(filtered_image); + + const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); + const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); + const auto window_end_x = + window_start_x + static_cast<std::size_t>(current_config.window_of_interest.width); + const auto window_end_y = + window_start_y + static_cast<std::size_t>(current_config.window_of_interest.height); + + for (std::size_t y = window_start_y; y < window_end_y; y++) { + for (std::size_t x = window_start_x; x < window_end_x; x++) { + u8 pixel = GetPixel(filtered_image, x, y); + if (pixel == 0) { + continue; + } + const auto cluster = GetClusterProperties(filtered_image, x, y); + if (cluster.pixel_count > current_config.pixel_count_max) { + continue; + } + if (cluster.pixel_count < current_config.pixel_count_min) { + continue; + } + // Cluster object limit reached + if (next_state.object_count >= next_state.data.size()) { + continue; + } + next_state.data[next_state.object_count] = cluster; + next_state.object_count++; + } + } + + next_state.sampling_number = camera_data.sample; + next_state.timestamp = next_state.timestamp + 131; + next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; + shared_memory->clustering_lifo.WriteNextEntry(next_state); + + if (!IsProcessorActive()) { + StartProcessor(); + } +} + +void ClusteringProcessor::RemoveLowIntensityData(std::vector<u8>& data) { + for (u8& pixel : data) { + if (pixel < current_config.pixel_count_min) { + pixel = 0; + } + } +} + +ClusteringProcessor::ClusteringData ClusteringProcessor::GetClusterProperties(std::vector<u8>& data, + std::size_t x, + std::size_t y) { + using DataPoint = Common::Point<std::size_t>; + std::queue<DataPoint> search_points{}; + ClusteringData current_cluster = GetPixelProperties(data, x, y); + SetPixel(data, x, y, 0); + search_points.emplace<DataPoint>({x, y}); + + while (!search_points.empty()) { + const auto point = search_points.front(); + search_points.pop(); + + // Avoid negative numbers + if (point.x == 0 || point.y == 0) { + continue; + } + + std::array<DataPoint, 4> new_points{ + DataPoint{point.x - 1, point.y}, + {point.x, point.y - 1}, + {point.x + 1, point.y}, + {point.x, point.y + 1}, + }; + + for (const auto new_point : new_points) { + if (new_point.x >= width) { + continue; + } + if (new_point.y >= height) { + continue; + } + if (GetPixel(data, new_point.x, new_point.y) < current_config.object_intensity_min) { + continue; + } + const ClusteringData cluster = GetPixelProperties(data, new_point.x, new_point.y); + current_cluster = MergeCluster(current_cluster, cluster); + SetPixel(data, new_point.x, new_point.y, 0); + search_points.emplace<DataPoint>({new_point.x, new_point.y}); + } + } + + return current_cluster; +} + +ClusteringProcessor::ClusteringData ClusteringProcessor::GetPixelProperties( + const std::vector<u8>& data, std::size_t x, std::size_t y) const { + return { + .average_intensity = GetPixel(data, x, y) / 255.0f, + .centroid = + { + .x = static_cast<f32>(x), + .y = static_cast<f32>(y), + + }, + .pixel_count = 1, + .bound = + { + .x = static_cast<s16>(x), + .y = static_cast<s16>(y), + .width = 1, + .height = 1, + }, + }; +} + +ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster( + const ClusteringData a, const ClusteringData b) const { + const f32 a_pixel_count = static_cast<f32>(a.pixel_count); + const f32 b_pixel_count = static_cast<f32>(b.pixel_count); + const f32 pixel_count = a_pixel_count + b_pixel_count; + const f32 average_intensity = + (a.average_intensity * a_pixel_count + b.average_intensity * b_pixel_count) / pixel_count; + const Core::IrSensor::IrsCentroid centroid = { + .x = (a.centroid.x * a_pixel_count + b.centroid.x * b_pixel_count) / pixel_count, + .y = (a.centroid.y * a_pixel_count + b.centroid.y * b_pixel_count) / pixel_count, + }; + s16 bound_start_x = a.bound.x < b.bound.x ? a.bound.x : b.bound.x; + s16 bound_start_y = a.bound.y < b.bound.y ? a.bound.y : b.bound.y; + s16 a_bound_end_x = a.bound.x + a.bound.width; + s16 a_bound_end_y = a.bound.y + a.bound.height; + s16 b_bound_end_x = b.bound.x + b.bound.width; + s16 b_bound_end_y = b.bound.y + b.bound.height; + + const Core::IrSensor::IrsRect bound = { + .x = bound_start_x, + .y = bound_start_y, + .width = a_bound_end_x > b_bound_end_x ? static_cast<s16>(a_bound_end_x - bound_start_x) + : static_cast<s16>(b_bound_end_x - bound_start_x), + .height = a_bound_end_y > b_bound_end_y ? static_cast<s16>(a_bound_end_y - bound_start_y) + : static_cast<s16>(b_bound_end_y - bound_start_y), + }; + + return { + .average_intensity = average_intensity, + .centroid = centroid, + .pixel_count = static_cast<u32>(pixel_count), + .bound = bound, + }; +} + +u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { + if ((y * width) + x > data.size()) { + return 0; + } + return data[(y * width) + x]; +} + +void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { + if ((y * width) + x > data.size()) { + return; + } + data[(y * width) + x] = value; +} + +void ClusteringProcessor::SetDefaultConfig() { + using namespace std::literals::chrono_literals; + current_config.camera_config.exposure_time = std::chrono::microseconds(200ms).count(); + current_config.camera_config.gain = 2; + current_config.camera_config.is_negative_used = false; + current_config.camera_config.light_target = Core::IrSensor::CameraLightTarget::BrightLeds; + current_config.window_of_interest = { + .x = 0, + .y = 0, + .width = width, + .height = height, + }; + current_config.pixel_count_min = 3; + current_config.pixel_count_max = static_cast<u32>(GetDataSize(format)); + current_config.is_external_light_filter_enabled = true; + current_config.object_intensity_min = 150; + + npad_device->SetCameraFormat(format); +} + void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { current_config.camera_config.exposure_time = config.camera_config.exposure_time; current_config.camera_config.gain = config.camera_config.gain; current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; current_config.camera_config.light_target = static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); + current_config.window_of_interest = config.window_of_interest; current_config.pixel_count_min = config.pixel_count_min; current_config.pixel_count_max = config.pixel_count_max; current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; current_config.object_intensity_min = config.object_intensity_min; + + LOG_INFO(Service_IRS, + "Processor config, exposure_time={}, gain={}, is_negative_used={}, " + "light_target={}, window_of_interest=({}, {}, {}, {}), pixel_count_min={}, " + "pixel_count_max={}, is_external_light_filter_enabled={}, object_intensity_min={}", + current_config.camera_config.exposure_time, current_config.camera_config.gain, + current_config.camera_config.is_negative_used, + current_config.camera_config.light_target, current_config.window_of_interest.x, + current_config.window_of_interest.y, current_config.window_of_interest.width, + current_config.window_of_interest.height, current_config.pixel_count_min, + current_config.pixel_count_max, current_config.is_external_light_filter_enabled, + current_config.object_intensity_min); + + npad_device->SetCameraFormat(format); } } // namespace Service::IRS diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h index 6e2ba8846..dc01a8ea7 100644 --- a/src/core/hle/service/hid/irsensor/clustering_processor.h +++ b/src/core/hle/service/hid/irsensor/clustering_processor.h @@ -5,12 +5,19 @@ #include "common/common_types.h" #include "core/hid/irs_types.h" +#include "core/hle/service/hid/irs_ring_lifo.h" #include "core/hle/service/hid/irsensor/processor_base.h" +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID + namespace Service::IRS { class ClusteringProcessor final : public ProcessorBase { public: - explicit ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format); + explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_, + Core::IrSensor::DeviceFormat& device_format, + std::size_t npad_index); ~ClusteringProcessor() override; // Called when the processor is initialized @@ -26,6 +33,10 @@ public: void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); private: + static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size320x240; + static constexpr std::size_t width = 320; + static constexpr std::size_t height = 240; + // This is nn::irsensor::ClusteringProcessorConfig struct ClusteringProcessorConfig { Core::IrSensor::CameraConfig camera_config; @@ -68,7 +79,32 @@ private: static_assert(sizeof(ClusteringProcessorState) == 0x198, "ClusteringProcessorState is an invalid size"); + struct ClusteringSharedMemory { + Service::IRS::Lifo<ClusteringProcessorState, 6> clustering_lifo; + static_assert(sizeof(clustering_lifo) == 0x9A0, "clustering_lifo is an invalid size"); + INSERT_PADDING_WORDS(0x11F); + }; + static_assert(sizeof(ClusteringSharedMemory) == 0xE20, + "ClusteringSharedMemory is an invalid size"); + + void OnControllerUpdate(Core::HID::ControllerTriggerType type); + void RemoveLowIntensityData(std::vector<u8>& data); + ClusteringData GetClusterProperties(std::vector<u8>& data, std::size_t x, std::size_t y); + ClusteringData GetPixelProperties(const std::vector<u8>& data, std::size_t x, + std::size_t y) const; + ClusteringData MergeCluster(const ClusteringData a, const ClusteringData b) const; + u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; + void SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value); + + // Sets config parameters of the camera + void SetDefaultConfig(); + + ClusteringSharedMemory* shared_memory = nullptr; + ClusteringProcessorState next_state{}; + ClusteringProcessorConfig current_config{}; Core::IrSensor::DeviceFormat& device; + Core::HID::EmulatedController* npad_device; + int callback_key{}; }; } // namespace Service::IRS diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index c64291e7f..dadaf897f 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -194,13 +194,16 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, Kernel::HLERequestContext& ctx) { const auto guard = LockService(); + Result result = ResultSuccess; + switch (ctx.GetCommandType()) { case IPC::CommandType::Close: case IPC::CommandType::TIPC_Close: { session.Close(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); - return IPC::ERR_REMOTE_PROCESS_DEAD; + result = IPC::ERR_REMOTE_PROCESS_DEAD; + break; } case IPC::CommandType::ControlWithContext: case IPC::CommandType::Control: { @@ -227,7 +230,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, ctx.WriteToOutgoingCommandBuffer(ctx.GetThread()); } - return ResultSuccess; + return result; } /// Initialize Services diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp deleted file mode 100644 index dfb10c34f..000000000 --- a/src/core/loader/elf.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project -// SPDX-FileCopyrightText: 2014 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <cstring> -#include <memory> -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/elf.h" -#include "common/logging/log.h" -#include "core/hle/kernel/code_set.h" -#include "core/hle/kernel/k_page_table.h" -#include "core/hle/kernel/k_process.h" -#include "core/loader/elf.h" -#include "core/memory.h" - -using namespace Common::ELF; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// ElfReader class - -typedef int SectionID; - -class ElfReader { -private: - char* base; - u32* base32; - - Elf32_Ehdr* header; - Elf32_Phdr* segments; - Elf32_Shdr* sections; - - u32* sectionAddrs; - bool relocate; - VAddr entryPoint; - -public: - explicit ElfReader(void* ptr); - - u32 Read32(int off) const { - return base32[off >> 2]; - } - - // Quick accessors - u16 GetType() const { - return header->e_type; - } - u16 GetMachine() const { - return header->e_machine; - } - VAddr GetEntryPoint() const { - return entryPoint; - } - u32 GetFlags() const { - return (u32)(header->e_flags); - } - Kernel::CodeSet LoadInto(VAddr vaddr); - - int GetNumSegments() const { - return (int)(header->e_phnum); - } - int GetNumSections() const { - return (int)(header->e_shnum); - } - const u8* GetPtr(int offset) const { - return (u8*)base + offset; - } - const char* GetSectionName(int section) const; - const u8* GetSectionDataPtr(int section) const { - if (section < 0 || section >= header->e_shnum) - return nullptr; - if (sections[section].sh_type != ElfShtNobits) - return GetPtr(sections[section].sh_offset); - else - return nullptr; - } - bool IsCodeSection(int section) const { - return sections[section].sh_type == ElfShtProgBits; - } - const u8* GetSegmentPtr(int segment) { - return GetPtr(segments[segment].p_offset); - } - u32 GetSectionAddr(SectionID section) const { - return sectionAddrs[section]; - } - unsigned int GetSectionSize(SectionID section) const { - return sections[section].sh_size; - } - SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found - - bool DidRelocate() const { - return relocate; - } -}; - -ElfReader::ElfReader(void* ptr) { - base = (char*)ptr; - base32 = (u32*)ptr; - header = (Elf32_Ehdr*)ptr; - - segments = (Elf32_Phdr*)(base + header->e_phoff); - sections = (Elf32_Shdr*)(base + header->e_shoff); - - entryPoint = header->e_entry; -} - -const char* ElfReader::GetSectionName(int section) const { - if (sections[section].sh_type == ElfShtNull) - return nullptr; - - int name_offset = sections[section].sh_name; - const char* ptr = reinterpret_cast<const char*>(GetSectionDataPtr(header->e_shstrndx)); - - if (ptr) - return ptr + name_offset; - - return nullptr; -} - -Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) { - LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); - - // Should we relocate? - relocate = (header->e_type != ElfTypeExec); - - if (relocate) { - LOG_DEBUG(Loader, "Relocatable module"); - entryPoint += vaddr; - } else { - LOG_DEBUG(Loader, "Prerelocated executable"); - } - LOG_DEBUG(Loader, "{} segments:", header->e_phnum); - - // First pass : Get the bits into RAM - const VAddr base_addr = relocate ? vaddr : 0; - - u64 total_image_size = 0; - for (unsigned int i = 0; i < header->e_phnum; ++i) { - const Elf32_Phdr* p = &segments[i]; - if (p->p_type == ElfPtLoad) { - total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF; - } - } - - Kernel::PhysicalMemory program_image(total_image_size); - std::size_t current_image_position = 0; - - Kernel::CodeSet codeset; - - for (unsigned int i = 0; i < header->e_phnum; ++i) { - const Elf32_Phdr* p = &segments[i]; - LOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type, - p->p_vaddr, p->p_filesz, p->p_memsz); - - if (p->p_type == ElfPtLoad) { - Kernel::CodeSet::Segment* codeset_segment; - u32 permission_flags = p->p_flags & (ElfPfRead | ElfPfWrite | ElfPfExec); - if (permission_flags == (ElfPfRead | ElfPfExec)) { - codeset_segment = &codeset.CodeSegment(); - } else if (permission_flags == (ElfPfRead)) { - codeset_segment = &codeset.RODataSegment(); - } else if (permission_flags == (ElfPfRead | ElfPfWrite)) { - codeset_segment = &codeset.DataSegment(); - } else { - LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i, - p->p_flags); - continue; - } - - if (codeset_segment->size != 0) { - LOG_ERROR(Loader, - "ELF has more than one segment of the same type. Skipping extra " - "segment (id {})", - i); - continue; - } - - const VAddr segment_addr = base_addr + p->p_vaddr; - const u32 aligned_size = (p->p_memsz + 0xFFF) & ~0xFFF; - - codeset_segment->offset = current_image_position; - codeset_segment->addr = segment_addr; - codeset_segment->size = aligned_size; - - std::memcpy(program_image.data() + current_image_position, GetSegmentPtr(i), - p->p_filesz); - current_image_position += aligned_size; - } - } - - codeset.entrypoint = base_addr + header->e_entry; - codeset.memory = std::move(program_image); - - LOG_DEBUG(Loader, "Done loading."); - - return codeset; -} - -SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const { - for (int i = firstSection; i < header->e_shnum; i++) { - const char* secname = GetSectionName(i); - - if (secname != nullptr && strcmp(name, secname) == 0) - return i; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Loader namespace - -namespace Loader { - -AppLoader_ELF::AppLoader_ELF(FileSys::VirtualFile file_) : AppLoader(std::move(file_)) {} - -FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& elf_file) { - static constexpr u16 ELF_MACHINE_ARM{0x28}; - - u32 magic = 0; - if (4 != elf_file->ReadObject(&magic)) { - return FileType::Error; - } - - u16 machine = 0; - if (2 != elf_file->ReadObject(&machine, 18)) { - return FileType::Error; - } - - if (Common::MakeMagic('\x7f', 'E', 'L', 'F') == magic && ELF_MACHINE_ARM == machine) { - return FileType::ELF; - } - - return FileType::Error; -} - -AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::KProcess& process, - [[maybe_unused]] Core::System& system) { - if (is_loaded) { - return {ResultStatus::ErrorAlreadyLoaded, {}}; - } - - std::vector<u8> buffer = file->ReadAllBytes(); - if (buffer.size() != file->GetSize()) { - return {ResultStatus::ErrorIncorrectELFFileSize, {}}; - } - - const VAddr base_address = process.PageTable().GetCodeRegionStart(); - ElfReader elf_reader(&buffer[0]); - Kernel::CodeSet codeset = elf_reader.LoadInto(base_address); - const VAddr entry_point = codeset.entrypoint; - - // Setup the process code layout - if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), buffer.size()).IsError()) { - return {ResultStatus::ErrorNotInitialized, {}}; - } - - process.LoadModule(std::move(codeset), entry_point); - - is_loaded = true; - return {ResultStatus::Success, LoadParameters{48, Core::Memory::DEFAULT_STACK_SIZE}}; -} - -} // namespace Loader diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h deleted file mode 100644 index acd33dc3d..000000000 --- a/src/core/loader/elf.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project -// SPDX-FileCopyrightText: 2014 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/loader/loader.h" - -namespace Core { -class System; -} - -namespace Loader { - -/// Loads an ELF/AXF file -class AppLoader_ELF final : public AppLoader { -public: - explicit AppLoader_ELF(FileSys::VirtualFile file); - - /** - * Identifies whether or not the given file is an ELF file. - * - * @param elf_file The file to identify. - * - * @return FileType::ELF, or FileType::Error if the file is not an ELF file. - */ - static FileType IdentifyType(const FileSys::VirtualFile& elf_file); - - FileType GetFileType() const override { - return IdentifyType(file); - } - - LoadResult Load(Kernel::KProcess& process, Core::System& system) override; -}; - -} // namespace Loader diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 994ee891f..104d16efa 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -12,7 +12,6 @@ #include "core/core.h" #include "core/hle/kernel/k_process.h" #include "core/loader/deconstructed_rom_directory.h" -#include "core/loader/elf.h" #include "core/loader/kip.h" #include "core/loader/nax.h" #include "core/loader/nca.h" @@ -39,8 +38,6 @@ std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { FileType IdentifyFile(FileSys::VirtualFile file) { if (const auto romdir_type = IdentifyFileLoader<AppLoader_DeconstructedRomDirectory>(file)) { return *romdir_type; - } else if (const auto elf_type = IdentifyFileLoader<AppLoader_ELF>(file)) { - return *elf_type; } else if (const auto nso_type = IdentifyFileLoader<AppLoader_NSO>(file)) { return *nso_type; } else if (const auto nro_type = IdentifyFileLoader<AppLoader_NRO>(file)) { @@ -69,8 +66,6 @@ FileType GuessFromFilename(const std::string& name) { const std::string extension = Common::ToLower(std::string(Common::FS::GetExtensionFromFilename(name))); - if (extension == "elf") - return FileType::ELF; if (extension == "nro") return FileType::NRO; if (extension == "nso") @@ -89,8 +84,6 @@ FileType GuessFromFilename(const std::string& name) { std::string GetFileTypeString(FileType type) { switch (type) { - case FileType::ELF: - return "ELF"; case FileType::NRO: return "NRO"; case FileType::NSO: @@ -208,10 +201,6 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V FileType type, u64 program_id, std::size_t program_index) { switch (type) { - // Standard ELF file format. - case FileType::ELF: - return std::make_unique<AppLoader_ELF>(std::move(file)); - // NX NSO file format. case FileType::NSO: return std::make_unique<AppLoader_NSO>(std::move(file)); diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 7bf4faaf1..7b43f70ed 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -34,7 +34,6 @@ namespace Loader { enum class FileType { Error, Unknown, - ELF, NSO, NRO, NCA, diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 635449fce..1b44280b5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1,6 +1,5 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2015 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> #include <cstring> diff --git a/src/core/memory.h b/src/core/memory.h index 780c45385..2a21fbcfd 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 6ef459b7a..f09c176f8 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> #include <chrono> diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index 816202588..dd6becc02 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 654db0b52..abcf6eb11 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <array> diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 6f3d45bea..887dc98f3 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -1,6 +1,5 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once |