Project Andio

This commit is contained in:
Kelebek1
2022-07-16 23:48:45 +01:00
parent 6e36f4d230
commit 458da8a948
270 changed files with 33712 additions and 8445 deletions

View File

@ -0,0 +1,125 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/renderer/memory/memory_pool_info.h"
#include "common/common_types.h"
namespace AudioCore::AudioRenderer {
/**
* Represents a region of mapped or unmapped memory.
*/
class AddressInfo {
public:
AddressInfo() = default;
AddressInfo(CpuAddr cpu_address_, u64 size_) : cpu_address{cpu_address_}, size{size_} {}
/**
* Setup a new AddressInfo.
*
* @param cpu_address - The CPU address of this region.
* @param size - The size of this region.
*/
void Setup(CpuAddr cpu_address_, u64 size_) {
cpu_address = cpu_address_;
size = size_;
memory_pool = nullptr;
dsp_address = 0;
}
/**
* Get the CPU address.
*
* @return The CpuAddr address
*/
CpuAddr GetCpuAddr() const {
return cpu_address;
}
/**
* Assign this region to a memory pool.
*
* @param memory_pool_ - Memory pool to assign.
* @return The CpuAddr address of this region.
*/
void SetPool(MemoryPoolInfo* memory_pool_) {
memory_pool = memory_pool_;
}
/**
* Get the size of this region.
*
* @return The size of this region.
*/
u64 GetSize() const {
return size;
}
/**
* Get the ADSP address for this region.
*
* @return The ADSP address for this region.
*/
CpuAddr GetForceMappedDspAddr() const {
return dsp_address;
}
/**
* Set the ADSP address for this region.
*
* @param dsp_addr - The new ADSP address for this region.
*/
void SetForceMappedDspAddr(CpuAddr dsp_addr) {
dsp_address = dsp_addr;
}
/**
* Check whether this region has an active memory pool.
*
* @return True if this region has a mapped memory pool, otherwise false.
*/
bool HasMappedMemoryPool() const {
return memory_pool != nullptr && memory_pool->GetDspAddress() != 0;
}
/**
* Check whether this region is mapped to the ADSP.
*
* @return True if this region is mapped, otherwise false.
*/
bool IsMapped() const {
return HasMappedMemoryPool() || dsp_address != 0;
}
/**
* Get a usable reference to this region of memory.
*
* @param mark_in_use - Whether this region should be marked as being in use.
* @return A valid memory address if valid, otherwise 0.
*/
CpuAddr GetReference(bool mark_in_use) {
if (!HasMappedMemoryPool()) {
return dsp_address;
}
if (mark_in_use) {
memory_pool->SetUsed(true);
}
return memory_pool->Translate(cpu_address, size);
}
private:
/// CPU address of this region
CpuAddr cpu_address;
/// Size of this region
u64 size;
/// The memory this region is mapped to
MemoryPoolInfo* memory_pool;
/// ADSP address of this region
CpuAddr dsp_address;
};
} // namespace AudioCore::AudioRenderer

View File

@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/renderer/memory/memory_pool_info.h"
namespace AudioCore::AudioRenderer {
CpuAddr MemoryPoolInfo::GetCpuAddress() const {
return cpu_address;
}
CpuAddr MemoryPoolInfo::GetDspAddress() const {
return dsp_address;
}
u64 MemoryPoolInfo::GetSize() const {
return size;
}
MemoryPoolInfo::Location MemoryPoolInfo::GetLocation() const {
return location;
}
void MemoryPoolInfo::SetCpuAddress(const CpuAddr address, const u64 size_) {
cpu_address = address;
size = size_;
}
void MemoryPoolInfo::SetDspAddress(const CpuAddr address) {
dsp_address = address;
}
bool MemoryPoolInfo::Contains(const CpuAddr address_, const u64 size_) const {
return cpu_address <= address_ && (address_ + size_) <= (cpu_address + size);
}
bool MemoryPoolInfo::IsMapped() const {
return dsp_address != 0;
}
CpuAddr MemoryPoolInfo::Translate(const CpuAddr address, const u64 size_) const {
if (!Contains(address, size_)) {
return 0;
}
if (!IsMapped()) {
return 0;
}
return dsp_address + (address - cpu_address);
}
void MemoryPoolInfo::SetUsed(const bool used) {
in_use = used;
}
bool MemoryPoolInfo::IsUsed() const {
return in_use;
}
} // namespace AudioCore::AudioRenderer

View File

@ -0,0 +1,170 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "audio_core/common/common.h"
#include "common/common_types.h"
namespace AudioCore::AudioRenderer {
/**
* CPU pools are mapped in user memory with the supplied process_handle (see PoolMapper).
*/
class MemoryPoolInfo {
public:
/**
* The location of this pool.
* CPU pools are mapped in user memory with the supplied process_handle (see PoolMapper).
* DSP pools are mapped in the current process sysmodule.
*/
enum class Location {
CPU = 1,
DSP = 2,
};
/**
* Current state of the pool
*/
enum class State {
Invalid,
Aquired,
RequestDetach,
Detached,
RequestAttach,
Attached,
Released,
};
/**
* Result code for updating the pool (See InfoUpdater::Update)
*/
enum class ResultState {
Success,
BadParam,
MapFailed,
InUse,
};
/**
* Input parameters coming from the game which are used to update current pools
* (See InfoUpdater::Update)
*/
struct InParameter {
/* 0x00 */ u64 address;
/* 0x08 */ u64 size;
/* 0x10 */ State state;
/* 0x14 */ bool in_use;
/* 0x18 */ char unk18[0x8];
};
static_assert(sizeof(InParameter) == 0x20, "MemoryPoolInfo::InParameter has the wrong size!");
/**
* Output status sent back to the game on update (See InfoUpdater::Update)
*/
struct OutStatus {
/* 0x00 */ State state;
/* 0x04 */ char unk04[0xC];
};
static_assert(sizeof(OutStatus) == 0x10, "MemoryPoolInfo::OutStatus has the wrong size!");
MemoryPoolInfo() = default;
MemoryPoolInfo(Location location_) : location{location_} {}
/**
* Get the CPU address for this pool.
*
* @return The CPU address of this pool.
*/
CpuAddr GetCpuAddress() const;
/**
* Get the DSP address for this pool.
*
* @return The DSP address of this pool.
*/
CpuAddr GetDspAddress() const;
/**
* Get the size of this pool.
*
* @return The size of this pool.
*/
u64 GetSize() const;
/**
* Get the location of this pool.
*
* @return The location for the pool (see MemoryPoolInfo::Location).
*/
Location GetLocation() const;
/**
* Set the CPU address for this pool.
*
* @param address - The new CPU address for this pool.
* @param size - The new size for this pool.
*/
void SetCpuAddress(CpuAddr address, u64 size);
/**
* Set the DSP address for this pool.
*
* @param address - The new DSP address for this pool.
*/
void SetDspAddress(CpuAddr address);
/**
* Check whether the pool contains a given range.
*
* @param address - The buffer address to look for.
* @param size - The size of the given buffer.
* @return True if the range is within this pool, otherwise false.
*/
bool Contains(CpuAddr address, u64 size) const;
/**
* Check whether this pool is mapped, which is when the dsp address is set.
*
* @return True if the pool is mapped, otherwise false.
*/
bool IsMapped() const;
/**
* Translates a given CPU range into a relative offset for the DSP.
*
* @param address - The buffer address to look for.
* @param size - The size of the given buffer.
* @return Pointer to the DSP-mapped memory.
*/
CpuAddr Translate(CpuAddr address, u64 size) const;
/**
* Set or unset whether this memory pool is in use.
*
* @param used - Use state for this pool.
*/
void SetUsed(bool used);
/**
* Get whether this pool is in use.
*
* @return True if in use, otherwise false.
*/
bool IsUsed() const;
private:
/// Base address for the CPU-side memory
CpuAddr cpu_address{};
/// Base address for the DSP-side memory
CpuAddr dsp_address{};
/// Size of this pool
u64 size{};
/// Location of this pool, either CPU or DSP
Location location{Location::DSP};
/// If this pool is in use
bool in_use{};
};
} // namespace AudioCore::AudioRenderer

View File

@ -0,0 +1,243 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/renderer/memory/address_info.h"
#include "audio_core/renderer/memory/pool_mapper.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace AudioCore::AudioRenderer {
PoolMapper::PoolMapper(u32 process_handle_, bool force_map_)
: process_handle{process_handle_}, force_map{force_map_} {}
PoolMapper::PoolMapper(u32 process_handle_, std::span<MemoryPoolInfo> pool_infos_, u32 pool_count_,
bool force_map_)
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
pool_count{pool_count_}, force_map{force_map_} {}
void PoolMapper::ClearUseState(std::span<MemoryPoolInfo> pools, const u32 count) {
for (u32 i = 0; i < count; i++) {
pools[i].SetUsed(false);
}
}
MemoryPoolInfo* PoolMapper::FindMemoryPool(MemoryPoolInfo* pools, const u64 count,
const CpuAddr address, const u64 size) const {
auto pool{pools};
for (u64 i = 0; i < count; i++, pool++) {
if (pool->Contains(address, size)) {
return pool;
}
}
return nullptr;
}
MemoryPoolInfo* PoolMapper::FindMemoryPool(const CpuAddr address, const u64 size) const {
auto pool{pool_infos};
for (u64 i = 0; i < pool_count; i++, pool++) {
if (pool->Contains(address, size)) {
return pool;
}
}
return nullptr;
}
bool PoolMapper::FillDspAddr(AddressInfo& address_info, MemoryPoolInfo* pools,
const u32 count) const {
if (address_info.GetCpuAddr() == 0) {
address_info.SetPool(nullptr);
return false;
}
auto found_pool{
FindMemoryPool(pools, count, address_info.GetCpuAddr(), address_info.GetSize())};
if (found_pool != nullptr) {
address_info.SetPool(found_pool);
return true;
}
if (force_map) {
address_info.SetForceMappedDspAddr(address_info.GetCpuAddr());
} else {
address_info.SetPool(nullptr);
}
return false;
}
bool PoolMapper::FillDspAddr(AddressInfo& address_info) const {
if (address_info.GetCpuAddr() == 0) {
address_info.SetPool(nullptr);
return false;
}
auto found_pool{FindMemoryPool(address_info.GetCpuAddr(), address_info.GetSize())};
if (found_pool != nullptr) {
address_info.SetPool(found_pool);
return true;
}
if (force_map) {
address_info.SetForceMappedDspAddr(address_info.GetCpuAddr());
} else {
address_info.SetPool(nullptr);
}
return false;
}
bool PoolMapper::TryAttachBuffer(BehaviorInfo::ErrorInfo& error_info, AddressInfo& address_info,
const CpuAddr address, const u64 size) const {
address_info.Setup(address, size);
if (!FillDspAddr(address_info)) {
error_info.error_code = Service::Audio::ERR_POOL_MAPPING_FAILED;
error_info.address = address;
return force_map;
}
error_info.error_code = ResultSuccess;
error_info.address = CpuAddr(0);
return true;
}
bool PoolMapper::IsForceMapEnabled() const {
return force_map;
}
u32 PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
switch (pool->GetLocation()) {
case MemoryPoolInfo::Location::CPU:
return process_handle;
case MemoryPoolInfo::Location::DSP:
return Kernel::Svc::CurrentProcess;
}
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
return Kernel::Svc::CurrentProcess;
}
bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
[[maybe_unused]] const u64 size) const {
// nn::audio::dsp::MapUserPointer(handle, cpu_addr, size);
return true;
}
bool PoolMapper::Map(MemoryPoolInfo& pool) const {
switch (pool.GetLocation()) {
case MemoryPoolInfo::Location::CPU:
// Map with process_handle
pool.SetDspAddress(pool.GetCpuAddress());
return true;
case MemoryPoolInfo::Location::DSP:
// Map with Kernel::Svc::CurrentProcess
pool.SetDspAddress(pool.GetCpuAddress());
return true;
default:
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location={}!",
static_cast<u32>(pool.GetLocation()));
return false;
}
}
bool PoolMapper::Unmap([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
[[maybe_unused]] const u64 size) const {
// nn::audio::dsp::UnmapUserPointer(handle, cpu_addr, size);
return true;
}
bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
[[maybe_unused]] u32 handle{0};
switch (pool.GetLocation()) {
case MemoryPoolInfo::Location::CPU:
handle = process_handle;
break;
case MemoryPoolInfo::Location::DSP:
handle = Kernel::Svc::CurrentProcess;
break;
}
// nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);
pool.SetCpuAddress(0, 0);
pool.SetDspAddress(0);
return true;
}
void PoolMapper::ForceUnmapPointer(const AddressInfo& address_info) const {
if (force_map) {
[[maybe_unused]] auto found_pool{
FindMemoryPool(address_info.GetCpuAddr(), address_info.GetSize())};
// nn::audio::dsp::UnmapUserPointer(this->processHandle, address_info.GetCpuAddr(), 0);
}
}
MemoryPoolInfo::ResultState PoolMapper::Update(MemoryPoolInfo& pool,
const MemoryPoolInfo::InParameter& in_params,
MemoryPoolInfo::OutStatus& out_params) const {
if (in_params.state != MemoryPoolInfo::State::RequestAttach &&
in_params.state != MemoryPoolInfo::State::RequestDetach) {
return MemoryPoolInfo::ResultState::Success;
}
if (in_params.address == 0 || in_params.size == 0 || !Common::Is4KBAligned(in_params.address) ||
!Common::Is4KBAligned(in_params.size)) {
return MemoryPoolInfo::ResultState::BadParam;
}
switch (in_params.state) {
case MemoryPoolInfo::State::RequestAttach:
pool.SetCpuAddress(in_params.address, in_params.size);
Map(pool);
if (pool.IsMapped()) {
out_params.state = MemoryPoolInfo::State::Attached;
return MemoryPoolInfo::ResultState::Success;
}
pool.SetCpuAddress(0, 0);
return MemoryPoolInfo::ResultState::MapFailed;
case MemoryPoolInfo::State::RequestDetach:
if (pool.GetCpuAddress() != in_params.address || pool.GetSize() != in_params.size) {
return MemoryPoolInfo::ResultState::BadParam;
}
if (pool.IsUsed()) {
return MemoryPoolInfo::ResultState::InUse;
}
Unmap(pool);
pool.SetCpuAddress(0, 0);
pool.SetDspAddress(0);
out_params.state = MemoryPoolInfo::State::Detached;
return MemoryPoolInfo::ResultState::Success;
default:
LOG_ERROR(Service_Audio, "Invalid MemoryPoolInfo::State!");
break;
}
return MemoryPoolInfo::ResultState::Success;
}
bool PoolMapper::InitializeSystemPool(MemoryPoolInfo& pool, const u8* memory,
const u64 size_) const {
switch (pool.GetLocation()) {
case MemoryPoolInfo::Location::CPU:
return false;
case MemoryPoolInfo::Location::DSP:
pool.SetCpuAddress(reinterpret_cast<u64>(memory), size_);
if (Map(Kernel::Svc::CurrentProcess, reinterpret_cast<u64>(memory), size_)) {
pool.SetDspAddress(pool.GetCpuAddress());
return true;
}
return false;
default:
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location={}!",
static_cast<u32>(pool.GetLocation()));
return false;
}
}
} // namespace AudioCore::AudioRenderer

View File

@ -0,0 +1,179 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <span>
#include "audio_core/renderer/behavior/behavior_info.h"
#include "audio_core/renderer/memory/memory_pool_info.h"
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
namespace AudioCore::AudioRenderer {
class AddressInfo;
/**
* Utility functions for managing MemoryPoolInfos
*/
class PoolMapper {
public:
explicit PoolMapper(u32 process_handle, bool force_map);
explicit PoolMapper(u32 process_handle, std::span<MemoryPoolInfo> pool_infos, u32 pool_count,
bool force_map);
/**
* Clear the usage state for all given pools.
*
* @param pools - The memory pools to clear.
* @param count - The number of pools.
*/
static void ClearUseState(std::span<MemoryPoolInfo> pools, u32 count);
/**
* Find the memory pool containing the given address and size from a given list of pools.
*
* @param pools - The memory pools to search within.
* @param count - The number of pools.
* @param address - The address of the region to find.
* @param size - The size of the region to find.
* @return Pointer to the memory pool if found, otherwise nullptr.
*/
MemoryPoolInfo* FindMemoryPool(MemoryPoolInfo* pools, u64 count, CpuAddr address,
u64 size) const;
/**
* Find the memory pool containing the given address and size from the PoolMapper's memory pool.
*
* @param address - The address of the region to find.
* @param size - The size of the region to find.
* @return Pointer to the memory pool if found, otherwise nullptr.
*/
MemoryPoolInfo* FindMemoryPool(CpuAddr address, u64 size) const;
/**
* Set the PoolMapper's memory pool to one in the given list of pools, which contains
* address_info.
*
* @param address_info - The expected region to find within pools.
* @param pools - The list of pools to search within.
* @param count - The number of pools given.
* @return True if successfully mapped, otherwise false.
*/
bool FillDspAddr(AddressInfo& address_info, MemoryPoolInfo* pools, u32 count) const;
/**
* Set the PoolMapper's memory pool to the one containing address_info.
*
* @param address_info - The address to find the memory pool for.
* @return True if successfully mapped, otherwise false.
*/
bool FillDspAddr(AddressInfo& address_info) const;
/**
* Try to attach a {address, size} region to the given address_info, and map it. Fills in the
* given error_info and address_info.
*
* @param error_info - Output error info.
* @param address_info - Output address info, initialized with the given {address, size} and
* attempted to map.
* @param address - Address of the region to map.
* @param size - Size of the region to map.
* @return True if successfully attached, otherwise false.
*/
bool TryAttachBuffer(BehaviorInfo::ErrorInfo& error_info, AddressInfo& address_info,
CpuAddr address, u64 size) const;
/**
* Return whether force mapping is enabled.
*
* @return True if force mapping is enabled, otherwise false.
*/
bool IsForceMapEnabled() const;
/**
* Get the process handle, depending on location.
*
* @param pool - The pool to check the location of.
* @return CurrentProcessHandle if location == DSP,
* the PoolMapper's process_handle if location == CPU
*/
u32 GetProcessHandle(const MemoryPoolInfo* pool) const;
/**
* Map the given region with the given handle. This is a no-op.
*
* @param handle - The process handle to map to.
* @param cpu_addr - Address to map.
* @param size - Size to map.
* @return True if successfully mapped, otherwise false.
*/
bool Map(u32 handle, CpuAddr cpu_addr, u64 size) const;
/**
* Map the given memory pool.
*
* @param pool - The pool to map.
* @return True if successfully mapped, otherwise false.
*/
bool Map(MemoryPoolInfo& pool) const;
/**
* Unmap the given region with the given handle.
*
* @param handle - The process handle to unmap to.
* @param cpu_addr - Address to unmap.
* @param size - Size to unmap.
* @return True if successfully unmapped, otherwise false.
*/
bool Unmap(u32 handle, CpuAddr cpu_addr, u64 size) const;
/**
* Unmap the given memory pool.
*
* @param pool - The pool to unmap.
* @return True if successfully unmapped, otherwise false.
*/
bool Unmap(MemoryPoolInfo& pool) const;
/**
* Forcibly unmap the given region.
*
* @param address_info - The region to unmap.
*/
void ForceUnmapPointer(const AddressInfo& address_info) const;
/**
* Update the given memory pool.
*
* @param pool - Pool to update.
* @param in_params - Input parameters for the update.
* @param out_params - Output parameters for the update.
* @return The result of the update. See MemoryPoolInfo::ResultState
*/
MemoryPoolInfo::ResultState Update(MemoryPoolInfo& pool,
const MemoryPoolInfo::InParameter& in_params,
MemoryPoolInfo::OutStatus& out_params) const;
/**
* Initialize the PoolMapper's memory pool.
*
* @param pool - Input pool to initialize.
* @param memory - Pointer to the memory region for the pool.
* @param size - Size of the memory region for the pool.
* @return True if initialized successfully, otherwise false.
*/
bool InitializeSystemPool(MemoryPoolInfo& pool, const u8* memory, u64 size) const;
private:
/// Process handle for this mapper, used when location == CPU
u32 process_handle;
/// List of memory pools assigned to this mapper
MemoryPoolInfo* pool_infos{};
/// The number of pools
u64 pool_count{};
/// Is forced mapping enabled
bool force_map;
};
} // namespace AudioCore::AudioRenderer