mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-17 21:57:52 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fdb415fbdd | |||
| b8c6085e5a |
@@ -12,7 +12,7 @@
|
||||
namespace AudioCore {
|
||||
|
||||
AudioCore::AudioCore(Core::System& system) {
|
||||
audio_manager.emplace();
|
||||
audio_manager.emplace(system);
|
||||
CreateSinks();
|
||||
// Must be created after the sinks
|
||||
adsp.emplace(system, *output_sink);
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
namespace AudioCore::AudioIn {
|
||||
|
||||
Manager::Manager(Core::System& system_) : system{system_} {
|
||||
Manager::Manager(Core::System& system) {
|
||||
std::iota(session_ids.begin(), session_ids.end(), 0);
|
||||
num_free_sessions = MaxInSessions;
|
||||
}
|
||||
|
||||
Result Manager::AcquireSessionId(size_t& session_id) {
|
||||
Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
|
||||
if (num_free_sessions == 0) {
|
||||
LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more");
|
||||
return Service::Audio::ResultOutOfSessions;
|
||||
@@ -31,7 +31,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void Manager::ReleaseSessionId(const size_t session_id) {
|
||||
void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
|
||||
std::scoped_lock l{mutex};
|
||||
LOG_DEBUG(Service_Audio, "Freeing AudioIn session {}", session_id);
|
||||
session_ids[free_session_id] = session_id;
|
||||
@@ -41,21 +41,20 @@ void Manager::ReleaseSessionId(const size_t session_id) {
|
||||
applet_resource_user_ids[session_id] = 0;
|
||||
}
|
||||
|
||||
Result Manager::LinkToManager() {
|
||||
Result Manager::LinkToManager(Core::System& system) {
|
||||
std::scoped_lock l{mutex};
|
||||
if (!linked_to_manager) {
|
||||
system.AudioCore().GetAudioManager().SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this));
|
||||
system.AudioCore().GetAudioManager().SetInManager(&Manager::BufferReleaseAndRegister);
|
||||
linked_to_manager = true;
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void Manager::Start() {
|
||||
void Manager::Start(Core::System& system) {
|
||||
if (sessions_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::scoped_lock l{mutex};
|
||||
for (auto& session : sessions) {
|
||||
if (session) {
|
||||
@@ -66,21 +65,19 @@ void Manager::Start() {
|
||||
sessions_started = true;
|
||||
}
|
||||
|
||||
void Manager::BufferReleaseAndRegister() {
|
||||
std::scoped_lock l{mutex};
|
||||
for (auto& session : sessions) {
|
||||
void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
|
||||
Manager* this_ = (Manager*)data;
|
||||
std::scoped_lock l{this_->mutex};
|
||||
for (auto& session : this_->sessions) {
|
||||
if (session != nullptr) {
|
||||
session->ReleaseAndRegisterBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
|
||||
[[maybe_unused]] const bool filter) {
|
||||
u32 Manager::GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, [[maybe_unused]] const bool filter) {
|
||||
std::scoped_lock l{mutex};
|
||||
|
||||
LinkToManager();
|
||||
|
||||
LinkToManager(system);
|
||||
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
|
||||
if (!input_devices.empty() && !names.empty()) {
|
||||
names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -30,31 +33,29 @@ public:
|
||||
* @param session_id - Output session_id.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result AcquireSessionId(size_t& session_id);
|
||||
Result AcquireSessionId(Core::System& system, size_t& session_id);
|
||||
|
||||
/**
|
||||
* Release a session id on close.
|
||||
*
|
||||
* @param session_id - Session id to free.
|
||||
*/
|
||||
void ReleaseSessionId(size_t session_id);
|
||||
void ReleaseSessionId(Core::System& system, const size_t session_id);
|
||||
|
||||
/**
|
||||
* Link the audio in manager to the main audio manager.
|
||||
*
|
||||
* @return Result code.
|
||||
*/
|
||||
Result LinkToManager();
|
||||
Result LinkToManager(Core::System& system);
|
||||
|
||||
/**
|
||||
* Start the audio in manager.
|
||||
*/
|
||||
void Start();
|
||||
void Start(Core::System& system);
|
||||
|
||||
/**
|
||||
* Callback function, called by the audio manager when the audio in event is signalled.
|
||||
*/
|
||||
void BufferReleaseAndRegister();
|
||||
/// @brief Callback function, called by the audio manager when the audio in event is signalled.
|
||||
static void BufferReleaseAndRegister(void *data, Core::System& system) noexcept;
|
||||
|
||||
/**
|
||||
* Get a list of audio in device names.
|
||||
@@ -64,10 +65,8 @@ public:
|
||||
*
|
||||
* @return Number of names written.
|
||||
*/
|
||||
u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
|
||||
u32 GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
|
||||
|
||||
/// Core system
|
||||
Core::System& system;
|
||||
/// Array of session ids
|
||||
std::array<size_t, MaxInSessions> session_ids{};
|
||||
/// Array of resource user ids
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
AudioManager::AudioManager() {
|
||||
thread = std::jthread([this](std::stop_token stop_token) {
|
||||
AudioManager::AudioManager(Core::System& system) {
|
||||
thread = std::jthread([&](std::stop_token stop_token) {
|
||||
Common::SetCurrentThreadName("AudioManager");
|
||||
std::unique_lock l{events.GetAudioEventLock()};
|
||||
events.ClearEvents();
|
||||
@@ -25,7 +25,7 @@ AudioManager::AudioManager() {
|
||||
const auto event_type = Event::Type(i);
|
||||
if (events.CheckAudioEventSet(event_type) || timed_out) {
|
||||
if (buffer_events[i]) {
|
||||
buffer_events[i]();
|
||||
buffer_events[i](this, system);
|
||||
}
|
||||
}
|
||||
events.SetAudioEvent(event_type, false);
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
#include "audio_core/audio_event.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
union Result;
|
||||
|
||||
namespace AudioCore {
|
||||
@@ -34,10 +38,9 @@ namespace AudioCore {
|
||||
* This is only used by audio in and audio out.
|
||||
*/
|
||||
class AudioManager {
|
||||
using BufferEventFunc = std::function<void()>;
|
||||
|
||||
using BufferEventFunc = void (*)(void *data, Core::System& system) noexcept;
|
||||
public:
|
||||
explicit AudioManager();
|
||||
explicit AudioManager(Core::System& system);
|
||||
|
||||
/**
|
||||
* Shutdown the audio manager.
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
namespace AudioCore::AudioOut {
|
||||
|
||||
Manager::Manager(Core::System& system_) : system{system_} {
|
||||
Manager::Manager(Core::System& system) {
|
||||
std::iota(session_ids.begin(), session_ids.end(), 0);
|
||||
num_free_sessions = MaxOutSessions;
|
||||
}
|
||||
|
||||
Result Manager::AcquireSessionId(size_t& session_id) {
|
||||
Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
|
||||
if (num_free_sessions == 0) {
|
||||
LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more");
|
||||
return Service::Audio::ResultOutOfSessions;
|
||||
@@ -30,7 +30,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void Manager::ReleaseSessionId(const size_t session_id) {
|
||||
void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
|
||||
std::scoped_lock l{mutex};
|
||||
LOG_DEBUG(Service_Audio, "Freeing AudioOut session {}", session_id);
|
||||
session_ids[free_session_id] = session_id;
|
||||
@@ -40,17 +40,17 @@ void Manager::ReleaseSessionId(const size_t session_id) {
|
||||
applet_resource_user_ids[session_id] = 0;
|
||||
}
|
||||
|
||||
Result Manager::LinkToManager() {
|
||||
Result Manager::LinkToManager(Core::System& system) {
|
||||
std::scoped_lock l{mutex};
|
||||
if (!linked_to_manager) {
|
||||
system.AudioCore().GetAudioManager().SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this));
|
||||
system.AudioCore().GetAudioManager().SetOutManager(&Manager::BufferReleaseAndRegister);
|
||||
linked_to_manager = true;
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void Manager::Start() {
|
||||
void Manager::Start(Core::System& system) {
|
||||
if (sessions_started) {
|
||||
return;
|
||||
}
|
||||
@@ -65,19 +65,14 @@ void Manager::Start() {
|
||||
sessions_started = true;
|
||||
}
|
||||
|
||||
void Manager::BufferReleaseAndRegister() {
|
||||
std::scoped_lock l{mutex};
|
||||
for (auto& session : sessions) {
|
||||
void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
|
||||
Manager* this_ = (Manager*)data;
|
||||
std::scoped_lock l{this_->mutex};
|
||||
for (auto& session : this_->sessions) {
|
||||
if (session != nullptr) {
|
||||
session->ReleaseAndRegisterBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 Manager::GetAudioOutDeviceNames(
|
||||
std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const {
|
||||
names.emplace_back("DeviceOut");
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace AudioCore::AudioOut
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -29,42 +32,32 @@ public:
|
||||
* @param session_id - Output session_id.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result AcquireSessionId(size_t& session_id);
|
||||
Result AcquireSessionId(Core::System& system, size_t& session_id);
|
||||
|
||||
/**
|
||||
* Release a session id on close.
|
||||
*
|
||||
* @param session_id - Session id to free.
|
||||
*/
|
||||
void ReleaseSessionId(size_t session_id);
|
||||
void ReleaseSessionId(Core::System& system, const size_t session_id);
|
||||
|
||||
/**
|
||||
* Link this manager to the main audio manager.
|
||||
*
|
||||
* @return Result code.
|
||||
*/
|
||||
Result LinkToManager();
|
||||
Result LinkToManager(Core::System& system);
|
||||
|
||||
/**
|
||||
* Start the audio out manager.
|
||||
*/
|
||||
void Start();
|
||||
void Start(Core::System& system);
|
||||
|
||||
/**
|
||||
* Callback function, called by the audio manager when the audio out event is signalled.
|
||||
*/
|
||||
void BufferReleaseAndRegister();
|
||||
static void BufferReleaseAndRegister(void* data, Core::System& system) noexcept;
|
||||
|
||||
/**
|
||||
* Get a list of audio out device names.
|
||||
*
|
||||
* @param names - Output container to write names to.
|
||||
* @return Number of names written.
|
||||
*/
|
||||
u32 GetAudioOutDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const;
|
||||
|
||||
/// Core system
|
||||
Core::System& system;
|
||||
/// Array of session ids
|
||||
std::array<size_t, MaxOutSessions> session_ids{};
|
||||
/// Array of resource user ids
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "audio_core/audio_render_manager.h"
|
||||
#include "audio_core/common/audio_renderer_parameter.h"
|
||||
#include "audio_core/renderer/system_manager.h"
|
||||
#include "audio_core/common/feature_support.h"
|
||||
#include "core/core.h"
|
||||
|
||||
namespace AudioCore::Renderer {
|
||||
|
||||
Manager::Manager(Core::System& system_)
|
||||
: system{system_}, system_manager{std::make_unique<SystemManager>(system)} {
|
||||
: system_manager{std::make_unique<SystemManager>(system_)}
|
||||
{
|
||||
std::iota(session_ids.begin(), session_ids.end(), 0);
|
||||
}
|
||||
|
||||
@@ -59,11 +64,11 @@ u32 Manager::GetSessionCount() const {
|
||||
return session_count;
|
||||
}
|
||||
|
||||
bool Manager::AddSystem(System& system_) {
|
||||
bool Manager::AddSystem(Renderer::System& system_) {
|
||||
return system_manager->Add(system_);
|
||||
}
|
||||
|
||||
bool Manager::RemoveSystem(System& system_) {
|
||||
bool Manager::RemoveSystem(Renderer::System& system_) {
|
||||
return system_manager->Remove(system_);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -71,7 +74,7 @@ public:
|
||||
* @param system - The system to add.
|
||||
* @return True if the system was successfully added, otherwise false.
|
||||
*/
|
||||
bool AddSystem(System& system);
|
||||
bool AddSystem(Renderer::System& system);
|
||||
|
||||
/**
|
||||
* Remove a renderer system from the manager.
|
||||
@@ -79,7 +82,7 @@ public:
|
||||
* @param system - The system to remove.
|
||||
* @return True if the system was successfully removed, otherwise false.
|
||||
*/
|
||||
bool RemoveSystem(System& system);
|
||||
bool RemoveSystem(Renderer::System& system);
|
||||
|
||||
/**
|
||||
* Free a session id when the system wants to shut down.
|
||||
@@ -89,8 +92,6 @@ public:
|
||||
void ReleaseSessionId(s32 session_id);
|
||||
|
||||
private:
|
||||
/// Core system
|
||||
Core::System& system;
|
||||
/// Session ids, -1 when in use
|
||||
std::array<s32, MaxRendererSessions> session_ids{};
|
||||
/// Number of active renderers
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -16,8 +19,9 @@ namespace AudioCore {
|
||||
*/
|
||||
class WorkbufferAllocator {
|
||||
public:
|
||||
explicit WorkbufferAllocator(std::span<u8> buffer_, u64 size_)
|
||||
: buffer{reinterpret_cast<u64>(buffer_.data())}, size{size_} {}
|
||||
explicit WorkbufferAllocator(std::span<u8> buffer_)
|
||||
: buffer{buffer_}
|
||||
{}
|
||||
|
||||
/**
|
||||
* Allocate the given count of T elements, aligned to alignment.
|
||||
@@ -29,36 +33,31 @@ public:
|
||||
template <typename T>
|
||||
std::span<T> Allocate(u64 count, u64 alignment) {
|
||||
u64 out{0};
|
||||
u64 byte_size{count * sizeof(T)};
|
||||
|
||||
u64 byte_size = count * sizeof(T);
|
||||
if (byte_size > 0) {
|
||||
auto current{buffer + offset};
|
||||
auto current{uintptr_t(buffer.data()) + offset};
|
||||
auto aligned_buffer{Common::AlignUp(current, alignment)};
|
||||
if (aligned_buffer + byte_size <= buffer + size) {
|
||||
if (aligned_buffer + byte_size <= uintptr_t(buffer.data()) + buffer.size()) {
|
||||
out = aligned_buffer;
|
||||
offset = byte_size - buffer + aligned_buffer;
|
||||
offset = byte_size - uintptr_t(buffer.data()) + aligned_buffer;
|
||||
} else {
|
||||
LOG_ERROR(
|
||||
Service_Audio,
|
||||
"Allocated buffer was too small to hold new alloc.\nAllocator size={:08X}, "
|
||||
"offset={:08X}.\nAttempting to allocate {:08X} with alignment={:02X}",
|
||||
size, offset, byte_size, alignment);
|
||||
buffer.size(), offset, byte_size, alignment);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return std::span<T>(reinterpret_cast<T*>(out), count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Align the current offset to the given alignment.
|
||||
*
|
||||
* @param alignment - The required starting alignment.
|
||||
*/
|
||||
/// @brief Align the current offset to the given alignment.
|
||||
/// @param alignment - The required starting alignment.
|
||||
void Align(u64 alignment) {
|
||||
auto current{buffer + offset};
|
||||
auto current{uintptr_t(buffer.data()) + offset};
|
||||
auto aligned_buffer{Common::AlignUp(current, alignment)};
|
||||
offset = 0 - buffer + aligned_buffer;
|
||||
offset = 0 - uintptr_t(buffer.data()) + aligned_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +75,7 @@ public:
|
||||
* @return The size of the current buffer.
|
||||
*/
|
||||
u64 GetSize() const {
|
||||
return size;
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,14 +84,11 @@ public:
|
||||
* @return The remaining size left in the buffer.
|
||||
*/
|
||||
u64 GetRemainingSize() const {
|
||||
return size - offset;
|
||||
return buffer.size() - offset;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The buffer into which we are allocating.
|
||||
u64 buffer;
|
||||
/// Size of the buffer we're allocating to.
|
||||
u64 size;
|
||||
const std::span<u8> buffer;
|
||||
/// Current offset into the buffer, an error will be thrown if it exceeds size.
|
||||
u64 offset{};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,42 +11,43 @@
|
||||
namespace AudioCore::AudioIn {
|
||||
|
||||
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
||||
session_id_} {}
|
||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}
|
||||
, audio_system{system_, event, session_id_}
|
||||
{}
|
||||
|
||||
void In::Free() {
|
||||
void In::Free(Core::System& system) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
manager.ReleaseSessionId(system.GetSessionId());
|
||||
manager.ReleaseSessionId(system, audio_system.GetSessionId());
|
||||
}
|
||||
|
||||
System& In::GetSystem() {
|
||||
return system;
|
||||
return audio_system;
|
||||
}
|
||||
|
||||
AudioIn::State In::GetState() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetState();
|
||||
return audio_system.GetState();
|
||||
}
|
||||
|
||||
Result In::StartSystem() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.Start();
|
||||
return audio_system.Start();
|
||||
}
|
||||
|
||||
void In::StartSession() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
system.StartSession();
|
||||
audio_system.StartSession();
|
||||
}
|
||||
|
||||
Result In::StopSystem() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.Stop();
|
||||
return audio_system.Stop();
|
||||
}
|
||||
|
||||
Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
|
||||
if (system.AppendBuffer(buffer, tag)) {
|
||||
if (audio_system.AppendBuffer(buffer, tag)) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
return Service::Audio::ResultBufferCountReached;
|
||||
@@ -51,20 +55,20 @@ Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
|
||||
|
||||
void In::ReleaseAndRegisterBuffers() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
if (system.GetState() == State::Started) {
|
||||
system.ReleaseBuffers();
|
||||
system.RegisterBuffers();
|
||||
if (audio_system.GetState() == State::Started) {
|
||||
audio_system.ReleaseBuffers();
|
||||
audio_system.RegisterBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
bool In::FlushAudioInBuffers() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.FlushAudioInBuffers();
|
||||
return audio_system.FlushAudioInBuffers();
|
||||
}
|
||||
|
||||
u32 In::GetReleasedBuffers(std::span<u64> tags) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetReleasedBuffers(tags);
|
||||
return audio_system.GetReleasedBuffers(tags);
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& In::GetBufferEvent() {
|
||||
@@ -74,27 +78,27 @@ Kernel::KReadableEvent& In::GetBufferEvent() {
|
||||
|
||||
f32 In::GetVolume() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetVolume();
|
||||
return audio_system.GetVolume();
|
||||
}
|
||||
|
||||
void In::SetVolume(f32 volume) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
system.SetVolume(volume);
|
||||
audio_system.SetVolume(volume);
|
||||
}
|
||||
|
||||
bool In::ContainsAudioBuffer(u64 tag) const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.ContainsAudioBuffer(tag);
|
||||
return audio_system.ContainsAudioBuffer(tag);
|
||||
}
|
||||
|
||||
u32 In::GetBufferCount() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetBufferCount();
|
||||
return audio_system.GetBufferCount();
|
||||
}
|
||||
|
||||
u64 In::GetPlayedSampleCount() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetPlayedSampleCount();
|
||||
return audio_system.GetPlayedSampleCount();
|
||||
}
|
||||
|
||||
} // namespace AudioCore::AudioIn
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -30,7 +33,7 @@ public:
|
||||
/**
|
||||
* Free this audio in from the audio in manager.
|
||||
*/
|
||||
void Free();
|
||||
void Free(Core::System& system);
|
||||
|
||||
/**
|
||||
* Get this audio in's system.
|
||||
@@ -141,7 +144,7 @@ private:
|
||||
/// Buffer event, signalled when buffers are ready to be released
|
||||
Kernel::KEvent* event;
|
||||
/// Main audio in system
|
||||
System system;
|
||||
System audio_system;
|
||||
};
|
||||
|
||||
} // namespace AudioCore::AudioIn
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,42 +11,43 @@
|
||||
namespace AudioCore::AudioOut {
|
||||
|
||||
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
||||
session_id_} {}
|
||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}
|
||||
, audio_system{system_, event, session_id_}
|
||||
{}
|
||||
|
||||
void Out::Free() {
|
||||
void Out::Free(Core::System& system) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
manager.ReleaseSessionId(system.GetSessionId());
|
||||
manager.ReleaseSessionId(system, audio_system.GetSessionId());
|
||||
}
|
||||
|
||||
System& Out::GetSystem() {
|
||||
return system;
|
||||
return audio_system;
|
||||
}
|
||||
|
||||
AudioOut::State Out::GetState() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetState();
|
||||
return audio_system.GetState();
|
||||
}
|
||||
|
||||
Result Out::StartSystem() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.Start();
|
||||
return audio_system.Start();
|
||||
}
|
||||
|
||||
void Out::StartSession() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
system.StartSession();
|
||||
audio_system.StartSession();
|
||||
}
|
||||
|
||||
Result Out::StopSystem() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.Stop();
|
||||
return audio_system.Stop();
|
||||
}
|
||||
|
||||
Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
|
||||
if (system.AppendBuffer(buffer, tag)) {
|
||||
if (audio_system.AppendBuffer(buffer, tag)) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
return Service::Audio::ResultBufferCountReached;
|
||||
@@ -51,20 +55,20 @@ Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
|
||||
|
||||
void Out::ReleaseAndRegisterBuffers() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
if (system.GetState() == State::Started) {
|
||||
system.ReleaseBuffers();
|
||||
system.RegisterBuffers();
|
||||
if (audio_system.GetState() == State::Started) {
|
||||
audio_system.ReleaseBuffers();
|
||||
audio_system.RegisterBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
bool Out::FlushAudioOutBuffers() {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.FlushAudioOutBuffers();
|
||||
return audio_system.FlushAudioOutBuffers();
|
||||
}
|
||||
|
||||
u32 Out::GetReleasedBuffers(std::span<u64> tags) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetReleasedBuffers(tags);
|
||||
return audio_system.GetReleasedBuffers(tags);
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& Out::GetBufferEvent() {
|
||||
@@ -74,27 +78,27 @@ Kernel::KReadableEvent& Out::GetBufferEvent() {
|
||||
|
||||
f32 Out::GetVolume() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetVolume();
|
||||
return audio_system.GetVolume();
|
||||
}
|
||||
|
||||
void Out::SetVolume(const f32 volume) {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
system.SetVolume(volume);
|
||||
audio_system.SetVolume(volume);
|
||||
}
|
||||
|
||||
bool Out::ContainsAudioBuffer(const u64 tag) const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.ContainsAudioBuffer(tag);
|
||||
return audio_system.ContainsAudioBuffer(tag);
|
||||
}
|
||||
|
||||
u32 Out::GetBufferCount() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetBufferCount();
|
||||
return audio_system.GetBufferCount();
|
||||
}
|
||||
|
||||
u64 Out::GetPlayedSampleCount() const {
|
||||
std::scoped_lock l{parent_mutex};
|
||||
return system.GetPlayedSampleCount();
|
||||
return audio_system.GetPlayedSampleCount();
|
||||
}
|
||||
|
||||
} // namespace AudioCore::AudioOut
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -30,7 +33,7 @@ public:
|
||||
/**
|
||||
* Free this audio out from the audio out manager.
|
||||
*/
|
||||
void Free();
|
||||
void Free(Core::System& system);
|
||||
|
||||
/**
|
||||
* Get this audio out's system.
|
||||
@@ -141,7 +144,7 @@ private:
|
||||
/// Buffer event, signalled when buffers are ready to be released
|
||||
Kernel::KEvent* event;
|
||||
/// Main audio out system
|
||||
System system;
|
||||
System audio_system;
|
||||
};
|
||||
|
||||
} // namespace AudioCore::AudioOut
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -13,56 +16,48 @@
|
||||
namespace AudioCore::Renderer {
|
||||
|
||||
Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event)
|
||||
: core{system_}, manager{manager_}, system{system_, rendered_event} {}
|
||||
: system{system_}, manager{manager_}
|
||||
, audio_system{system_, rendered_event}
|
||||
{}
|
||||
|
||||
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory,
|
||||
const u64 transfer_memory_size, Kernel::KProcess* process_handle,
|
||||
const u64 applet_resource_user_id, const s32 session_id) {
|
||||
Result Renderer::Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, Kernel::KProcess* process_handle, const u64 applet_resource_user_id, const s32 session_id) {
|
||||
if (params.execution_mode == ExecutionMode::Auto) {
|
||||
if (!manager.AddSystem(system)) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
"Both Audio Render sessions are in use, cannot create any more");
|
||||
if (!manager.AddSystem(audio_system)) {
|
||||
LOG_ERROR(Service_Audio, "Both Audio Render sessions are in use, cannot create any more");
|
||||
return Service::Audio::ResultOutOfSessions;
|
||||
}
|
||||
system_registered = true;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
|
||||
applet_resource_user_id, session_id);
|
||||
|
||||
audio_system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void Renderer::Finalize() {
|
||||
auto session_id{system.GetSessionId()};
|
||||
|
||||
system.Finalize();
|
||||
|
||||
auto const session_id{audio_system.GetSessionId()};
|
||||
audio_system.Finalize();
|
||||
if (system_registered) {
|
||||
manager.RemoveSystem(system);
|
||||
manager.RemoveSystem(audio_system);
|
||||
system_registered = false;
|
||||
}
|
||||
|
||||
manager.ReleaseSessionId(session_id);
|
||||
}
|
||||
|
||||
System& Renderer::GetSystem() {
|
||||
return system;
|
||||
return audio_system;
|
||||
}
|
||||
|
||||
void Renderer::Start() {
|
||||
system.Start();
|
||||
audio_system.Start();
|
||||
}
|
||||
|
||||
void Renderer::Stop() {
|
||||
system.Stop();
|
||||
audio_system.Stop();
|
||||
}
|
||||
|
||||
Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance,
|
||||
std::span<u8> output) {
|
||||
return system.Update(input, performance, output);
|
||||
Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance, std::span<u8> output) {
|
||||
return audio_system.Update(input, performance, output);
|
||||
}
|
||||
|
||||
} // namespace AudioCore::Renderer
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -84,7 +87,7 @@ public:
|
||||
|
||||
private:
|
||||
/// System core
|
||||
Core::System& core;
|
||||
Core::System& system;
|
||||
/// Manager this renderer is registered with
|
||||
Manager& manager;
|
||||
/// Is the audio renderer initialized?
|
||||
@@ -92,7 +95,7 @@ private:
|
||||
/// Is the system registered with the manager?
|
||||
bool system_registered{};
|
||||
/// Audio render system, main driver of audio rendering
|
||||
System system;
|
||||
System audio_system;
|
||||
};
|
||||
|
||||
} // namespace Renderer
|
||||
|
||||
@@ -145,7 +145,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||
PoolMapper pool_mapper(process_handle, false);
|
||||
pool_mapper.InitializeSystemPool(memory_pool_info, workbuffer.get(), workbuffer_size);
|
||||
|
||||
WorkbufferAllocator allocator({workbuffer.get(), workbuffer_size}, workbuffer_size);
|
||||
WorkbufferAllocator allocator({workbuffer.get(), workbuffer_size});
|
||||
|
||||
samples_workbuffer =
|
||||
allocator.Allocate<s32>((voice_channels + mix_buffer_count) * sample_count, 0x10);
|
||||
|
||||
@@ -50,7 +50,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
|
||||
}
|
||||
|
||||
IAudioIn::~IAudioIn() {
|
||||
impl->Free();
|
||||
impl->Free(system);
|
||||
service_context.CloseEvent(event);
|
||||
process->Close(system.Kernel());
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -65,7 +68,7 @@ Result IAudioInManager::OpenAudioInAuto(
|
||||
Result IAudioInManager::ListAudioInsAutoFiltered(
|
||||
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
*out_count = impl->GetDeviceNames(out_audio_ins, true);
|
||||
*out_count = impl->GetDeviceNames(system, out_audio_ins, true);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
@@ -90,8 +93,8 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
|
||||
|
||||
size_t new_session_id{};
|
||||
|
||||
R_TRY(impl->LinkToManager());
|
||||
R_TRY(impl->AcquireSessionId(new_session_id));
|
||||
R_TRY(impl->LinkToManager(system));
|
||||
R_TRY(impl->AcquireSessionId(system, new_session_id));
|
||||
|
||||
LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
|
||||
impl->num_free_sessions);
|
||||
|
||||
@@ -46,7 +46,7 @@ IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
|
||||
}
|
||||
|
||||
IAudioOut::~IAudioOut() {
|
||||
impl->Free();
|
||||
impl->Free(system);
|
||||
service_context.CloseEvent(event);
|
||||
process->Close(system.Kernel());
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ Result IAudioOutManager::OpenAudioOutAuto(
|
||||
}
|
||||
|
||||
size_t new_session_id{};
|
||||
R_TRY(impl->LinkToManager());
|
||||
R_TRY(impl->AcquireSessionId(new_session_id));
|
||||
R_TRY(impl->LinkToManager(system));
|
||||
R_TRY(impl->AcquireSessionId(system, new_session_id));
|
||||
|
||||
const auto device_name = Common::StringFromBuffer(name[0].name);
|
||||
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
|
||||
|
||||
@@ -137,7 +137,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{405, nullptr, "ListApplicationControlCacheEntryInfo"},
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, &IApplicationManagerInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{408, &IApplicationManagerInterface::ListApplicationIcon, "ListApplicationIcon"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{411, nullptr, "Unknown411"}, //19.0.0+
|
||||
{412, nullptr, "Unknown412"}, //19.0.0+
|
||||
{413, nullptr, "Unknown413"}, //19.0.0+
|
||||
@@ -848,9 +848,4 @@ void IApplicationManagerInterface::ListApplicationTitle(HLERequestContext& ctx)
|
||||
IReadOnlyApplicationControlDataInterface(system).ListApplicationTitle(ctx);
|
||||
}
|
||||
|
||||
void IApplicationManagerInterface::ListApplicationIcon(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IReadOnlyApplicationControlDataInterface(system).ListApplicationIcon(ctx);
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
|
||||
@@ -75,7 +75,6 @@ public:
|
||||
u64 application_id);
|
||||
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
void ListApplicationIcon(HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
@@ -14,16 +14,12 @@
|
||||
#include <stb_image_resize.h>
|
||||
#include <stb_image_write.h>
|
||||
|
||||
#include "common/logging.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/ns/ns_results.h"
|
||||
@@ -79,26 +75,24 @@ void SanitizeJPEGImageSize(std::vector<u8>& image) {
|
||||
|
||||
// IAsyncValue implementation for ListApplicationTitle
|
||||
// https://switchbrew.org/wiki/NS_services#ListApplicationTitle
|
||||
class IAsyncValue final : public ServiceFramework<IAsyncValue> {
|
||||
class IAsyncValueForListApplicationTitle final : public ServiceFramework<IAsyncValueForListApplicationTitle> {
|
||||
public:
|
||||
explicit IAsyncValue(Core::System& system_, s32 offset, s32 size)
|
||||
: ServiceFramework{system_, "IAsyncValue"}
|
||||
, service_context{system_, "IAsyncValue"}
|
||||
, data_offset{offset}
|
||||
, data_size{size}
|
||||
{
|
||||
explicit IAsyncValueForListApplicationTitle(Core::System& system_, s32 offset, s32 size)
|
||||
: ServiceFramework{system_, "IAsyncValue"}, service_context{system_, "IAsyncValue"},
|
||||
data_offset{offset}, data_size{size} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IAsyncValue::GetSize>, "GetSize"},
|
||||
{1, D<&IAsyncValue::Get>, "Get"},
|
||||
{2, D<&IAsyncValue::Cancel>, "Cancel"},
|
||||
{3, D<&IAsyncValue::GetErrorContext>, "GetErrorContext"},
|
||||
{0, &IAsyncValueForListApplicationTitle::GetSize, "GetSize"},
|
||||
{1, &IAsyncValueForListApplicationTitle::Get, "Get"},
|
||||
{2, &IAsyncValueForListApplicationTitle::Cancel, "Cancel"},
|
||||
{3, &IAsyncValueForListApplicationTitle::GetErrorContext, "GetErrorContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
completion_event = service_context.CreateEvent("IAsyncValue:Completion");
|
||||
completion_event->GetReadableEvent().Signal(system.Kernel());
|
||||
}
|
||||
|
||||
~IAsyncValue() override {
|
||||
~IAsyncValueForListApplicationTitle() override {
|
||||
service_context.CloseEvent(completion_event);
|
||||
}
|
||||
|
||||
@@ -107,24 +101,35 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Result GetSize(Out<s64> out_data_size) {
|
||||
void GetSize(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_data_size = data_size;
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<s64>(data_size);
|
||||
}
|
||||
Result Get(OutBuffer<BufferAttr_HipcMapAlias> out_data_offset) {
|
||||
|
||||
void Get(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
std::memcpy(out_data_offset.data(), &data_offset, sizeof(s32));
|
||||
R_SUCCEED();
|
||||
std::vector<u8> buffer(sizeof(s32));
|
||||
std::memcpy(buffer.data(), &data_offset, sizeof(s32));
|
||||
ctx.WriteBuffer(buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
Result Cancel() {
|
||||
|
||||
void Cancel(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
Result GetErrorContext() {
|
||||
|
||||
void GetErrorContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* completion_event{};
|
||||
s32 data_offset;
|
||||
@@ -142,7 +147,6 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData2>, "GetApplicationControlData"},
|
||||
{10, &IReadOnlyApplicationControlDataInterface::ListApplicationIcon, "ListApplicationIcon"},
|
||||
{13, &IReadOnlyApplicationControlDataInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData3>, "GetApplicationControlData"},
|
||||
};
|
||||
@@ -159,7 +163,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||
application_control_source, application_id);
|
||||
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
const auto size = out_buffer.size();
|
||||
|
||||
@@ -167,7 +172,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
|
||||
|
||||
if (size < total_size) {
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size);
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
|
||||
size);
|
||||
R_THROW(ResultUnknown);
|
||||
}
|
||||
|
||||
@@ -175,7 +181,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
const auto bytes = control.first->GetRawBytes();
|
||||
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero", application_id);
|
||||
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
|
||||
application_id);
|
||||
std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
|
||||
}
|
||||
|
||||
@@ -200,12 +207,15 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
|
||||
// Convert to application language, get priority list
|
||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||
if (application_language == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", language_code);
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
|
||||
language_code);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
|
||||
if (!priority_list) {
|
||||
LOG_ERROR(Service_NS, "Could not find application language priorities! application_language={}", *application_language);
|
||||
LOG_ERROR(Service_NS,
|
||||
"Could not find application language priorities! application_language={}",
|
||||
*application_language);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
|
||||
@@ -249,7 +259,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
|
||||
const auto nacp_size = sizeof(FileSys::RawNACP);
|
||||
|
||||
if (size < nacp_size) {
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})", size, nacp_size);
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})",
|
||||
size, nacp_size);
|
||||
R_THROW(ResultUnknown);
|
||||
}
|
||||
|
||||
@@ -300,83 +311,63 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NS, "(stubbed)");
|
||||
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const u64 app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
|
||||
size_t out_length = 0;
|
||||
if (t_mem != nullptr && app_count > 0) {
|
||||
auto& memory = system.ApplicationMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
// u64 - app count
|
||||
memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64));
|
||||
out_length += sizeof(u64);
|
||||
// [list of u64] - size of icons
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
u64 full_size = control.second->GetSize();
|
||||
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
|
||||
out_length += sizeof(u64);
|
||||
}
|
||||
// [list of raw icon data]
|
||||
std::vector<u8> full_icon_data;
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
auto const full_size = control.second->GetSize();
|
||||
if (full_size > 0) {
|
||||
full_icon_data.resize(full_size);
|
||||
control.second->Read(full_icon_data.data(), full_size, 0);
|
||||
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
|
||||
out_length += full_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto async_value = std::make_shared<IAsyncValue>(system, 0, s32(out_length));
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(ctx, async_value->ReadableEvent());
|
||||
rb.PushIpcInterface(ctx, std::move(async_value));
|
||||
}
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
/*
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto control_source = rp.PopRaw<u8>();
|
||||
rp.Skip(7, false);
|
||||
auto transfer_memory_size = rp.Pop<u64>();
|
||||
*/
|
||||
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
|
||||
std::vector<u64> application_ids(app_count);
|
||||
if (app_count > 0) {
|
||||
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
|
||||
}
|
||||
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
|
||||
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
|
||||
const size_t total_data_size = app_count * title_entry_size;
|
||||
|
||||
constexpr s32 data_offset = 0;
|
||||
|
||||
if (t_mem != nullptr && app_count > 0) {
|
||||
auto& memory = system.ApplicationMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const u64 app_id = application_ids[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
FileSys::LanguageEntry entry{};
|
||||
if (control.first != nullptr) {
|
||||
entry = control.first->GetLanguageEntry();
|
||||
}
|
||||
|
||||
const size_t offset = i * title_entry_size;
|
||||
memory.WriteBlock(t_mem_address + offset, &entry, title_entry_size);
|
||||
}
|
||||
}
|
||||
auto async_value = std::make_shared<IAsyncValue>(system, data_offset, s32(total_data_size));
|
||||
|
||||
auto async_value = std::make_shared<IAsyncValueForListApplicationTitle>(
|
||||
system, data_offset, static_cast<s32>(total_data_size));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(ctx, async_value->ReadableEvent());
|
||||
rb.PushIpcInterface(ctx, std::move(async_value));
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_flags_a, Out<u32> out_flags_b, Out<u32> out_actual_size, ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_flags_a, Out<u32> out_flags_b,
|
||||
Out<u32> out_actual_size, ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
|
||||
LOG_INFO(Service_NS, "called with control_source={}, flags=({:02X},{:02X}), application_id={:016X}",
|
||||
application_control_source, flag1, flag2, application_id);
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ public:
|
||||
u8 flag1,
|
||||
u8 flag2,
|
||||
u64 application_id);
|
||||
void ListApplicationIcon(HLERequestContext& ctx);
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
Result GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
@@ -16,8 +16,10 @@ IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::S
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"},
|
||||
{1, nullptr, "NotifyApplicationFailure"},
|
||||
{2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>, "IsDataCorruptedResult"},
|
||||
{3, D<&IReadOnlyApplicationRecordInterface::ListApplicationRecord>, "ListApplicationRecord"},
|
||||
{2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>,
|
||||
"IsDataCorruptedResult"},
|
||||
{3, D<&IReadOnlyApplicationRecordInterface::ListApplicationRecord>,
|
||||
"ListApplicationRecord"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
Reference in New Issue
Block a user