diff options
Diffstat (limited to 'src/core')
23 files changed, 152 insertions, 130 deletions
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index d4097a510..7ccca1089 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp @@ -76,7 +76,7 @@ std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const { } std::vector<std::shared_ptr<VfsDirectory>> PartitionFilesystem::GetSubdirectories() const { - return {}; + return pfs_dirs; } std::string PartitionFilesystem::GetName() const { diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 16c8ad90b..3f690f12a 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -42,7 +42,7 @@ bool VfsFile::WriteByte(u8 data, size_t offset) { return Write(&data, 1, offset) == 1; } -size_t VfsFile::WriteBytes(std::vector<u8> data, size_t offset) { +size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) { return Write(data.data(), data.size(), offset); } diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index a5213e0cc..db3c77eac 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -59,8 +59,7 @@ struct VfsFile : NonCopyable { // Returns the number of bytes (sizeof(T)*number_elements) read successfully. template <typename T> size_t ReadArray(T* data, size_t number_elements, size_t offset = 0) const { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); return Read(reinterpret_cast<u8*>(data), number_elements * sizeof(T), offset); } @@ -69,8 +68,7 @@ struct VfsFile : NonCopyable { // Returns the number of bytes read successfully. template <typename T> size_t ReadBytes(T* data, size_t size, size_t offset = 0) const { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); return Read(reinterpret_cast<u8*>(data), size, offset); } @@ -78,8 +76,7 @@ struct VfsFile : NonCopyable { // Returns the number of bytes read successfully (sizeof(T)). template <typename T> size_t ReadObject(T* data, size_t offset = 0) const { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); return Read(reinterpret_cast<u8*>(data), sizeof(T), offset); } @@ -88,33 +85,29 @@ struct VfsFile : NonCopyable { virtual bool WriteByte(u8 data, size_t offset = 0); // Writes a vector of bytes to offset in file and returns the number of bytes successfully // written. - virtual size_t WriteBytes(std::vector<u8> data, size_t offset = 0); + virtual size_t WriteBytes(const std::vector<u8>& data, size_t offset = 0); // Writes an array of type T, size number_elements to offset in file. // Returns the number of bytes (sizeof(T)*number_elements) written successfully. template <typename T> - size_t WriteArray(T* data, size_t number_elements, size_t offset = 0) { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); - + size_t WriteArray(const T* data, size_t number_elements, size_t offset = 0) { + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); return Write(data, number_elements * sizeof(T), offset); } // Writes size bytes starting at memory location data to offset in file. // Returns the number of bytes written successfully. template <typename T> - size_t WriteBytes(T* data, size_t size, size_t offset = 0) { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); - return Write(reinterpret_cast<u8*>(data), size, offset); + size_t WriteBytes(const T* data, size_t size, size_t offset = 0) { + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); + return Write(reinterpret_cast<const u8*>(data), size, offset); } // Writes one object of type T to offset in file. // Returns the number of bytes written successfully (sizeof(T)). template <typename T> size_t WriteObject(const T& data, size_t offset = 0) { - static_assert(std::is_trivially_copyable<T>::value, - "Data type must be trivially copyable."); + static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); return Write(&data, sizeof(T), offset); } diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp index 288499cb5..217e02235 100644 --- a/src/core/file_sys/vfs_offset.cpp +++ b/src/core/file_sys/vfs_offset.cpp @@ -2,13 +2,16 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> +#include <utility> + #include "core/file_sys/vfs_offset.h" namespace FileSys { OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_, - const std::string& name_) - : file(file_), offset(offset_), size(size_), name(name_) {} + std::string name_) + : file(std::move(file_)), offset(offset_), size(size_), name(std::move(name_)) {} std::string OffsetVfsFile::GetName() const { return name.empty() ? file->GetName() : name; @@ -73,7 +76,7 @@ bool OffsetVfsFile::WriteByte(u8 data, size_t r_offset) { return false; } -size_t OffsetVfsFile::WriteBytes(std::vector<u8> data, size_t r_offset) { +size_t OffsetVfsFile::WriteBytes(const std::vector<u8>& data, size_t r_offset) { return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset); } @@ -86,7 +89,7 @@ size_t OffsetVfsFile::GetOffset() const { } size_t OffsetVfsFile::TrimToFit(size_t r_size, size_t r_offset) const { - return std::max<size_t>(std::min<size_t>(size - r_offset, r_size), 0); + return std::clamp(r_size, size_t{0}, size - r_offset); } } // namespace FileSys diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h index adc615b38..ded4827f5 100644 --- a/src/core/file_sys/vfs_offset.h +++ b/src/core/file_sys/vfs_offset.h @@ -14,7 +14,7 @@ namespace FileSys { // the size of this wrapper. struct OffsetVfsFile : public VfsFile { OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0, - const std::string& new_name = ""); + std::string new_name = ""); std::string GetName() const override; size_t GetSize() const override; @@ -28,7 +28,7 @@ struct OffsetVfsFile : public VfsFile { std::vector<u8> ReadBytes(size_t size, size_t offset) const override; std::vector<u8> ReadAllBytes() const override; bool WriteByte(u8 data, size_t offset) override; - size_t WriteBytes(std::vector<u8> data, size_t offset) override; + size_t WriteBytes(const std::vector<u8>& data, size_t offset) override; bool Rename(const std::string& name) override; diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 24605a273..8b5b06f31 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -175,6 +175,25 @@ public: void Push(const First& first_value, const Other&... other_values); /** + * Helper function for pushing strongly-typed enumeration values. + * + * @tparam Enum The enumeration type to be pushed + * + * @param value The value to push. + * + * @note The underlying size of the enumeration type is the size of the + * data that gets pushed. e.g. "enum class SomeEnum : u16" will + * push a u16-sized amount of data. + */ + template <typename Enum> + void PushEnum(Enum value) { + static_assert(std::is_enum_v<Enum>, "T must be an enum type within a PushEnum call."); + static_assert(!std::is_convertible_v<Enum, int>, + "enum type in PushEnum must be a strongly typed enum."); + Push(static_cast<std::underlying_type_t<Enum>>(value)); + } + + /** * @brief Copies the content of the given trivially copyable class to the buffer as a normal * param * @note: The input class must be correctly packed/padded to fit hardware layout. diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index dcc68aabf..233fdab25 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -20,7 +20,7 @@ namespace AddressArbiter { static ResultCode WaitForAddress(VAddr address, s64 timeout) { SharedPtr<Thread> current_thread = GetCurrentThread(); current_thread->arb_wait_address = address; - current_thread->status = THREADSTATUS_WAIT_ARB; + current_thread->status = ThreadStatus::WaitArb; current_thread->wakeup_callback = nullptr; current_thread->WakeAfterDelay(timeout); @@ -65,7 +65,7 @@ static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num // Signal the waiting threads. for (size_t i = 0; i < last; i++) { - ASSERT(waiting_threads[i]->status == THREADSTATUS_WAIT_ARB); + ASSERT(waiting_threads[i]->status == ThreadStatus::WaitArb); waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS); waiting_threads[i]->arb_wait_address = 0; waiting_threads[i]->ResumeFromWait(); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 8f40bdd5a..f24392520 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -38,7 +38,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread, thread->wakeup_callback = [context = *this, callback](ThreadWakeupReason reason, SharedPtr<Thread> thread, SharedPtr<WaitObject> object, size_t index) mutable -> bool { - ASSERT(thread->status == THREADSTATUS_WAIT_HLE_EVENT); + ASSERT(thread->status == ThreadStatus::WaitHLEEvent); callback(thread, context, reason); context.WriteToOutgoingCommandBuffer(*thread); return true; @@ -50,7 +50,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread, } event->Clear(); - thread->status = THREADSTATUS_WAIT_HLE_EVENT; + thread->status = ThreadStatus::WaitHLEEvent; thread->wait_objects = {event}; event->AddWaitingThread(thread); diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 65560226d..3f1de3258 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -28,7 +28,7 @@ static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread( if (thread->mutex_wait_address != mutex_addr) continue; - ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); + ASSERT(thread->status == ThreadStatus::WaitMutex); ++num_waiters; if (highest_priority_thread == nullptr || @@ -83,7 +83,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, GetCurrentThread()->mutex_wait_address = address; GetCurrentThread()->wait_handle = requesting_thread_handle; - GetCurrentThread()->status = THREADSTATUS_WAIT_MUTEX; + GetCurrentThread()->status = ThreadStatus::WaitMutex; GetCurrentThread()->wakeup_callback = nullptr; // Update the lock holder thread's priority to prevent priority inversion. @@ -121,7 +121,7 @@ ResultCode Mutex::Release(VAddr address) { // Grant the mutex to the next waiting thread and resume it. Memory::Write32(address, mutex_value); - ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); + ASSERT(thread->status == ThreadStatus::WaitMutex); thread->ResumeFromWait(); thread->lock_owner = nullptr; diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 82829f6bb..e307eec98 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -34,7 +34,7 @@ Thread* Scheduler::PopNextReadyThread() { Thread* next = nullptr; Thread* thread = GetCurrentThread(); - if (thread && thread->status == THREADSTATUS_RUNNING) { + if (thread && thread->status == ThreadStatus::Running) { // We have to do better than the current thread. // This call returns null when that's not possible. next = ready_queue.pop_first_better(thread->current_priority); @@ -59,17 +59,17 @@ void Scheduler::SwitchContext(Thread* new_thread) { // Save the TPIDR_EL0 system register in case it was modified. previous_thread->tpidr_el0 = cpu_core->GetTPIDR_EL0(); - if (previous_thread->status == THREADSTATUS_RUNNING) { + if (previous_thread->status == ThreadStatus::Running) { // This is only the case when a reschedule is triggered without the current thread // yielding execution (i.e. an event triggered, system core time-sliced, etc) ready_queue.push_front(previous_thread->current_priority, previous_thread); - previous_thread->status = THREADSTATUS_READY; + previous_thread->status = ThreadStatus::Ready; } } // Load context of new thread if (new_thread) { - ASSERT_MSG(new_thread->status == THREADSTATUS_READY, + ASSERT_MSG(new_thread->status == ThreadStatus::Ready, "Thread must be ready to become running."); // Cancel any outstanding wakeup events for this thread @@ -80,7 +80,7 @@ void Scheduler::SwitchContext(Thread* new_thread) { current_thread = new_thread; ready_queue.remove(new_thread->current_priority, new_thread); - new_thread->status = THREADSTATUS_RUNNING; + new_thread->status = ThreadStatus::Running; if (previous_process != current_thread->owner_process) { Core::CurrentProcess() = current_thread->owner_process; @@ -132,14 +132,14 @@ void Scheduler::RemoveThread(Thread* thread) { void Scheduler::ScheduleThread(Thread* thread, u32 priority) { std::lock_guard<std::mutex> lock(scheduler_mutex); - ASSERT(thread->status == THREADSTATUS_READY); + ASSERT(thread->status == ThreadStatus::Ready); ready_queue.push_back(priority, thread); } void Scheduler::UnscheduleThread(Thread* thread, u32 priority) { std::lock_guard<std::mutex> lock(scheduler_mutex); - ASSERT(thread->status == THREADSTATUS_READY); + ASSERT(thread->status == ThreadStatus::Ready); ready_queue.remove(priority, thread); } @@ -147,7 +147,7 @@ void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { std::lock_guard<std::mutex> lock(scheduler_mutex); // If thread was ready, adjust queues - if (thread->status == THREADSTATUS_READY) + if (thread->status == ThreadStatus::Ready) ready_queue.move(thread, thread->current_priority, priority); else ready_queue.prepare(priority); diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 19d17af4f..29b163528 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -110,10 +110,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { result = hle_handler->HandleSyncRequest(context); } - if (thread->status == THREADSTATUS_RUNNING) { + if (thread->status == ThreadStatus::Running) { // Put the thread to sleep until the server replies, it will be awoken in // svcReplyAndReceive for LLE servers. - thread->status = THREADSTATUS_WAIT_IPC; + thread->status = ThreadStatus::WaitIPC; if (hle_handler != nullptr) { // For HLE services, we put the request threads to sleep for a short duration to diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c6b0bb442..6b2995fe2 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -133,7 +133,7 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) { /// Default thread wakeup callback for WaitSynchronization static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, SharedPtr<WaitObject> object, size_t index) { - ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); + ASSERT(thread->status == ThreadStatus::WaitSynchAny); if (reason == ThreadWakeupReason::Timeout) { thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); @@ -197,7 +197,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 object->AddWaitingThread(thread); thread->wait_objects = std::move(objects); - thread->status = THREADSTATUS_WAIT_SYNCH_ANY; + thread->status = ThreadStatus::WaitSynchAny; // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); @@ -217,7 +217,7 @@ static ResultCode CancelSynchronization(Handle thread_handle) { return ERR_INVALID_HANDLE; } - ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); + ASSERT(thread->status == ThreadStatus::WaitSynchAny); thread->SetWaitSynchronizationResult( ResultCode(ErrorModule::Kernel, ErrCodes::SynchronizationCanceled)); thread->ResumeFromWait(); @@ -468,8 +468,8 @@ static void ExitProcess() { continue; // TODO(Subv): When are the other running/ready threads terminated? - ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || - thread->status == THREADSTATUS_WAIT_SYNCH_ALL, + ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny || + thread->status == ThreadStatus::WaitSynchAll, "Exiting processes with non-waiting threads is currently unimplemented"); thread->Stop(); @@ -545,7 +545,7 @@ static ResultCode StartThread(Handle thread_handle) { return ERR_INVALID_HANDLE; } - ASSERT(thread->status == THREADSTATUS_DORMANT); + ASSERT(thread->status == ThreadStatus::Dormant); thread->ResumeFromWait(); Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule(); @@ -596,7 +596,7 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var current_thread->condvar_wait_address = condition_variable_addr; current_thread->mutex_wait_address = mutex_addr; current_thread->wait_handle = thread_handle; - current_thread->status = THREADSTATUS_WAIT_MUTEX; + current_thread->status = ThreadStatus::WaitMutex; current_thread->wakeup_callback = nullptr; current_thread->WakeAfterDelay(nano_seconds); @@ -656,7 +656,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target if (mutex_val == 0) { // We were able to acquire the mutex, resume this thread. Memory::Write32(thread->mutex_wait_address, thread->wait_handle); - ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); + ASSERT(thread->status == ThreadStatus::WaitMutex); thread->ResumeFromWait(); auto lock_owner = thread->lock_owner; @@ -672,8 +672,8 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); auto owner = g_handle_table.Get<Thread>(owner_handle); ASSERT(owner); - ASSERT(thread->status != THREADSTATUS_RUNNING); - thread->status = THREADSTATUS_WAIT_MUTEX; + ASSERT(thread->status != ThreadStatus::Running); + thread->status = ThreadStatus::WaitMutex; thread->wakeup_callback = nullptr; // Signal that the mutex now has a waiting thread. diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 7f1e18831..cd85c4b7c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -30,7 +30,7 @@ namespace Kernel { static CoreTiming::EventType* ThreadWakeupEventType = nullptr; bool Thread::ShouldWait(Thread* thread) const { - return status != THREADSTATUS_DEAD; + return status != ThreadStatus::Dead; } void Thread::Acquire(Thread* thread) { @@ -63,11 +63,11 @@ void Thread::Stop() { // Clean up thread from ready queue // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) - if (status == THREADSTATUS_READY) { + if (status == ThreadStatus::Ready) { scheduler->UnscheduleThread(this, current_priority); } - status = THREADSTATUS_DEAD; + status = ThreadStatus::Dead; WakeupAllWaitingThreads(); @@ -86,7 +86,7 @@ void Thread::Stop() { void WaitCurrentThread_Sleep() { Thread* thread = GetCurrentThread(); - thread->status = THREADSTATUS_WAIT_SLEEP; + thread->status = ThreadStatus::WaitSleep; } void ExitCurrentThread() { @@ -110,10 +110,9 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { bool resume = true; - if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || - thread->status == THREADSTATUS_WAIT_SYNCH_ALL || - thread->status == THREADSTATUS_WAIT_HLE_EVENT) { - + if (thread->status == ThreadStatus::WaitSynchAny || + thread->status == ThreadStatus::WaitSynchAll || + thread->status == ThreadStatus::WaitHLEEvent) { // Remove the thread from each of its waiting objects' waitlists for (auto& object : thread->wait_objects) object->RemoveWaitingThread(thread.get()); @@ -126,7 +125,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 || thread->wait_handle) { - ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); + ASSERT(thread->status == ThreadStatus::WaitMutex); thread->mutex_wait_address = 0; thread->condvar_wait_address = 0; thread->wait_handle = 0; @@ -141,7 +140,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { } if (thread->arb_wait_address != 0) { - ASSERT(thread->status == THREADSTATUS_WAIT_ARB); + ASSERT(thread->status == ThreadStatus::WaitArb); thread->arb_wait_address = 0; } @@ -178,28 +177,28 @@ void Thread::ResumeFromWait() { ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); switch (status) { - case THREADSTATUS_WAIT_SYNCH_ALL: - case THREADSTATUS_WAIT_SYNCH_ANY: - case THREADSTATUS_WAIT_HLE_EVENT: - case THREADSTATUS_WAIT_SLEEP: - case THREADSTATUS_WAIT_IPC: - case THREADSTATUS_WAIT_MUTEX: - case THREADSTATUS_WAIT_ARB: + case ThreadStatus::WaitSynchAll: + case ThreadStatus::WaitSynchAny: + case ThreadStatus::WaitHLEEvent: + case ThreadStatus::WaitSleep: + case ThreadStatus::WaitIPC: + case ThreadStatus::WaitMutex: + case ThreadStatus::WaitArb: break; - case THREADSTATUS_READY: + case ThreadStatus::Ready: // The thread's wakeup callback must have already been cleared when the thread was first // awoken. ASSERT(wakeup_callback == nullptr); // If the thread is waiting on multiple wait objects, it might be awoken more than once // before actually resuming. We can ignore subsequent wakeups if the thread status has - // already been set to THREADSTATUS_READY. + // already been set to ThreadStatus::Ready. return; - case THREADSTATUS_RUNNING: + case ThreadStatus::Running: DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId()); return; - case THREADSTATUS_DEAD: + case ThreadStatus::Dead: // This should never happen, as threads must complete before being stopped. DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.", GetObjectId()); @@ -208,7 +207,7 @@ void Thread::ResumeFromWait() { wakeup_callback = nullptr; - status = THREADSTATUS_READY; + status = ThreadStatus::Ready; boost::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask); if (!new_processor_id) { @@ -310,7 +309,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, SharedPtr<Thread> thread(new Thread); thread->thread_id = NewThreadId(); - thread->status = THREADSTATUS_DORMANT; + thread->status = ThreadStatus::Dormant; thread->entry_point = entry_point; thread->stack_top = stack_top; thread->tpidr_el0 = 0; @@ -472,7 +471,7 @@ void Thread::ChangeCore(u32 core, u64 mask) { ideal_core = core; affinity_mask = mask; - if (status != THREADSTATUS_READY) { + if (status != ThreadStatus::Ready) { return; } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 5fe72c55c..6218960d2 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -36,18 +36,18 @@ enum ThreadProcessorId : s32 { (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3) }; -enum ThreadStatus { - THREADSTATUS_RUNNING, ///< Currently running - THREADSTATUS_READY, ///< Ready to run - THREADSTATUS_WAIT_HLE_EVENT, ///< Waiting for hle event to finish - THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC - THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request - THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false - THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true - THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc - THREADSTATUS_WAIT_ARB, ///< Waiting due to a SignalToAddress/WaitForAddress svc - THREADSTATUS_DORMANT, ///< Created but not yet made ready - THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated +enum class ThreadStatus { + Running, ///< Currently running + Ready, ///< Ready to run + WaitHLEEvent, ///< Waiting for hle event to finish + WaitSleep, ///< Waiting due to a SleepThread SVC + WaitIPC, ///< Waiting for the reply from an IPC request + WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false + WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true + WaitMutex, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc + WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc + Dormant, ///< Created but not yet made ready + Dead ///< Run to completion, or forcefully terminated }; enum class ThreadWakeupReason { @@ -202,14 +202,14 @@ public: * with wait_all = true. */ bool IsSleepingOnWaitAll() const { - return status == THREADSTATUS_WAIT_SYNCH_ALL; + return status == ThreadStatus::WaitSynchAll; } ARM_Interface::ThreadContext context; u32 thread_id; - u32 status; + ThreadStatus status; VAddr entry_point; VAddr stack_top; diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index b08ac72c1..eb3c92e66 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -38,9 +38,9 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { for (const auto& thread : waiting_threads) { // The list of waiting threads must not contain threads that are not waiting to be awakened. - ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || - thread->status == THREADSTATUS_WAIT_SYNCH_ALL || - thread->status == THREADSTATUS_WAIT_HLE_EVENT, + ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny || + thread->status == ThreadStatus::WaitSynchAll || + thread->status == ThreadStatus::WaitHLEEvent, "Inconsistent thread statuses in waiting_threads"); if (thread->current_priority >= candidate_priority) @@ -49,10 +49,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { if (ShouldWait(thread.get())) continue; - // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or - // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready. + // A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or + // in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready. bool ready_to_run = true; - if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) { + if (thread->status == ThreadStatus::WaitSynchAll) { ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), [&thread](const SharedPtr<WaitObject>& object) { return object->ShouldWait(thread.get()); diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 8ee39b54c..3e1c2c0a0 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -82,14 +82,16 @@ private: LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(true); // TODO: Check when this is supposed to return true and when not + rb.Push(false); // TODO: Check when this is supposed to return true and when not } void GetAccountId(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.Push<u64>(0x12345678ABCDEF); + // TODO(Subv): Find out what this actually does and implement it. Stub it as an error for + // now since we do not implement NNID. Returning a bogus id here will cause games to send + // invalid IPC requests after ListOpenUsers is called. + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); } }; @@ -104,7 +106,7 @@ void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); // TODO(Subv): There is only one user for now. const std::vector<u128> user_ids = {DEFAULT_USER_ID}; - ctx.WriteBuffer(user_ids.data(), user_ids.size() * sizeof(u128)); + ctx.WriteBuffer(user_ids); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -113,7 +115,7 @@ void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); // TODO(Subv): There is only one user for now. const std::vector<u128> user_ids = {DEFAULT_USER_ID}; - ctx.WriteBuffer(user_ids.data(), user_ids.size() * sizeof(u128)); + ctx.WriteBuffer(user_ids); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp index 751d73f8d..ce943d829 100644 --- a/src/core/hle/service/apm/interface.cpp +++ b/src/core/hle/service/apm/interface.cpp @@ -20,6 +20,21 @@ public: } private: + enum class PerformanceConfiguration : u32 { + Config1 = 0x00010000, + Config2 = 0x00010001, + Config3 = 0x00010002, + Config4 = 0x00020000, + Config5 = 0x00020001, + Config6 = 0x00020002, + Config7 = 0x00020003, + Config8 = 0x00020004, + Config9 = 0x00020005, + Config10 = 0x00020006, + Config11 = 0x92220007, + Config12 = 0x92220008, + }; + void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -40,7 +55,7 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); // Performance configuration + rb.Push<u32>(static_cast<u32>(PerformanceConfiguration::Config1)); LOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode)); } diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 4217ea4fb..154bc12da 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> #include <vector> #include "common/logging/log.h" #include "core/core_timing.h" @@ -167,7 +168,7 @@ void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - const std::string audio_interface = "AudioInterface"; + constexpr std::array<char, 15> audio_interface{{"AudioInterface"}}; ctx.WriteBuffer(audio_interface); IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 6903f52d6..e623f4f8e 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> + #include "common/alignment.h" #include "common/logging/log.h" #include "core/core_timing.h" @@ -298,7 +300,7 @@ private: LOG_WARNING(Service_Audio, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - const std::string audio_interface = "AudioInterface"; + constexpr std::array<char, 15> audio_interface{{"AudioInterface"}}; ctx.WriteBuffer(audio_interface); IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); @@ -323,7 +325,7 @@ private: LOG_WARNING(Service_Audio, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - const std::string audio_interface = "AudioDevice"; + constexpr std::array<char, 12> audio_interface{{"AudioDevice"}}; ctx.WriteBuffer(audio_interface); IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 19b8667ba..394963a69 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -83,16 +83,13 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { - const VAddr load_addr = next_load_addr; const FileSys::VirtualFile module_file = dir->GetFile(module); - if (module_file != nullptr) + if (module_file != nullptr) { + const VAddr load_addr = next_load_addr; next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr); - if (next_load_addr) { LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); // Register module with GDBStub GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); - } else { - next_load_addr = load_addr; } } diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index e73b253b2..c80df23be 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <utility> #include <vector> #include "common/file_util.h" @@ -21,7 +22,7 @@ namespace Loader { -AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(file) {} +AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) { // TODO(DarkLordZach): Assuming everything is decrypted. Add crypto support. diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 465b827bb..c020399f2 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <utility> #include <vector> #include "common/common_funcs.h" @@ -48,7 +49,7 @@ struct ModHeader { }; static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size."); -AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(file) {} +AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) { // Read NSO header diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index c66561bf4..06b1b33f4 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -69,29 +69,18 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) { static std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, const NsoSegmentHeader& header) { std::vector<u8> uncompressed_data(header.size); - const int bytes_uncompressed = LZ4_decompress_safe( - reinterpret_cast<const char*>(compressed_data.data()), - reinterpret_cast<char*>(uncompressed_data.data()), compressed_data.size(), header.size); + const int bytes_uncompressed = + LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()), + reinterpret_cast<char*>(uncompressed_data.data()), + static_cast<int>(compressed_data.size()), header.size); - ASSERT_MSG(bytes_uncompressed == header.size && bytes_uncompressed == uncompressed_data.size(), + ASSERT_MSG(bytes_uncompressed == static_cast<int>(header.size) && + bytes_uncompressed == static_cast<int>(uncompressed_data.size()), "{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size()); return uncompressed_data; } -static std::vector<u8> ReadSegment(FileUtil::IOFile& file, const NsoSegmentHeader& header, - size_t compressed_size) { - std::vector<u8> compressed_data(compressed_size); - - file.Seek(header.offset, SEEK_SET); - if (compressed_size != file.ReadBytes(compressed_data.data(), compressed_size)) { - LOG_CRITICAL(Loader, "Failed to read {} NSO LZ4 compressed bytes", compressed_size); - return {}; - } - - return DecompressSegment(compressed_data, header); -} - static constexpr u32 PageAlignSize(u32 size) { return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; } |