@ -17,7 +17,8 @@ constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)};
class IAudioRenderer final : public ServiceFramework < IAudioRenderer > {
class IAudioRenderer final : public ServiceFramework < IAudioRenderer > {
public :
public :
IAudioRenderer ( ) : ServiceFramework ( " IAudioRenderer " ) {
IAudioRenderer ( AudioRendererParameters audren_params )
: ServiceFramework ( " IAudioRenderer " ) , worker_params ( audren_params ) {
static const FunctionInfo functions [ ] = {
static const FunctionInfo functions [ ] = {
{ 0 , nullptr , " GetAudioRendererSampleRate " } ,
{ 0 , nullptr , " GetAudioRendererSampleRate " } ,
{ 1 , nullptr , " GetAudioRendererSampleCount " } ,
{ 1 , nullptr , " GetAudioRendererSampleCount " } ,
@ -60,16 +61,27 @@ private:
AudioRendererConfig config ;
AudioRendererConfig config ;
auto buf = ctx . ReadBuffer ( ) ;
auto buf = ctx . ReadBuffer ( ) ;
std : : memcpy ( & config , buf . data ( ) , sizeof ( AudioRendererConfig ) ) ;
std : : memcpy ( & config , buf . data ( ) , sizeof ( AudioRendererConfig ) ) ;
u32 memory_pool_count = worker_params . effect_count + ( worker_params . voice_count * 4 ) ;
AudioRendererResponse response_data { config } ;
std : : vector < MemoryPoolInfo > mem_pool_info ( memory_pool_count ) ;
std : : memcpy ( mem_pool_info . data ( ) ,
buf . data ( ) + sizeof ( AudioRendererConfig ) + config . behavior_size ,
memory_pool_count * sizeof ( MemoryPoolInfo ) ) ;
AudioRendererResponse response_data { worker_params } ;
ASSERT ( ctx . GetWriteBufferSize ( ) = = response_data . total_size ) ;
ASSERT ( ctx . GetWriteBufferSize ( ) = = response_data . total_size ) ;
std : : vector < u8 > output ( response_data . total_size ) ;
std : : vector < u8 > output ( response_data . total_size ) ;
std : : memcpy ( output . data ( ) , & response_data , sizeof ( AudioRendererResponse ) ) ;
std : : memcpy ( output . data ( ) , & response_data , sizeof ( AudioRendererResponse ) ) ;
std : : vector < MemoryPoolEntry > memory_pool ( config . memory_pools_size / 0x20 ) ;
std : : vector < MemoryPoolEntry > memory_pool ( memory_pool_count ) ;
for ( auto & entry : memory_pool ) {
for ( unsigned i = 0 ; i < memory_pool . size ( ) ; i + + ) {
entry . state = 5 ;
if ( mem_pool_info [ i ] . pool_state = = MemoryPoolStates : : RequestAttach )
memory_pool [ i ] . state = MemoryPoolStates : : Attached ;
else if ( mem_pool_info [ i ] . pool_state = = MemoryPoolStates : : RequestDetach )
memory_pool [ i ] . state = MemoryPoolStates : : Detached ;
else
memory_pool [ i ] . state = mem_pool_info [ i ] . pool_state ;
}
}
std : : memcpy ( output . data ( ) + sizeof ( AudioRendererResponse ) , memory_pool . data ( ) ,
std : : memcpy ( output . data ( ) + sizeof ( AudioRendererResponse ) , memory_pool . data ( ) ,
response_data . memory_pools_size ) ;
response_data . memory_pools_size ) ;
@ -108,14 +120,32 @@ private:
NGLOG_WARNING ( Service_Audio , " (STUBBED) called " ) ;
NGLOG_WARNING ( Service_Audio , " (STUBBED) called " ) ;
}
}
enum class MemoryPoolStates : u32 { // Should be LE
Invalid = 0x0 ,
Unknown = 0x1 ,
RequestDetach = 0x2 ,
Detached = 0x3 ,
RequestAttach = 0x4 ,
Attached = 0x5 ,
Released = 0x6 ,
} ;
struct MemoryPoolEntry {
struct MemoryPoolEntry {
u32_le state ;
MemoryPoolStates state ;
u32_le unknown_4 ;
u32_le unknown_4 ;
u32_le unknown_8 ;
u32_le unknown_8 ;
u32_le unknown_c ;
u32_le unknown_c ;
} ;
} ;
static_assert ( sizeof ( MemoryPoolEntry ) = = 0x10 , " MemoryPoolEntry has wrong size " ) ;
static_assert ( sizeof ( MemoryPoolEntry ) = = 0x10 , " MemoryPoolEntry has wrong size " ) ;
struct MemoryPoolInfo {
u64_le pool_address ;
u64_le pool_size ;
MemoryPoolStates pool_state ;
INSERT_PADDING_WORDS ( 3 ) ; // Unknown
} ;
static_assert ( sizeof ( MemoryPoolInfo ) = = 0x20 , " MemoryPoolInfo has wrong size " ) ;
struct AudioRendererConfig {
struct AudioRendererConfig {
u32 revision ;
u32 revision ;
u32 behavior_size ;
u32 behavior_size ;
@ -132,13 +162,13 @@ private:
static_assert ( sizeof ( AudioRendererConfig ) = = 0x40 , " AudioRendererConfig has wrong size " ) ;
static_assert ( sizeof ( AudioRendererConfig ) = = 0x40 , " AudioRendererConfig has wrong size " ) ;
struct AudioRendererResponse {
struct AudioRendererResponse {
AudioRendererResponse ( const AudioRenderer Config & config ) {
AudioRendererResponse ( const AudioRenderer Parameters & config ) {
revision = config . revision ;
revision = config . revision ;
error_info_size = 0xb0 ;
error_info_size = 0xb0 ;
memory_pools_size = ( config . memory_pools_size / 0x20 ) * 0x10 ;
memory_pools_size = ( config . effect_count + ( config . voice_count * 4 ) ) * 0x10 ;
voices_size = ( config . voices_size / 0x170 ) * 0x10 ;
voices_size = config . voice_count * 0x10 ;
effects_size = ( config . effects_size / 0xC0 ) * 0x10 ;
effects_size = config . effect_count * 0x10 ;
sinks_size = ( config . sinks_size / 0x140 ) * 0x20 ;
sinks_size = config . sink_count * 0x20 ;
performance_manager_size = 0x10 ;
performance_manager_size = 0x10 ;
total_size = sizeof ( AudioRendererResponse ) + error_info_size + memory_pools_size +
total_size = sizeof ( AudioRendererResponse ) + error_info_size + memory_pools_size +
voices_size + effects_size + sinks_size + performance_manager_size ;
voices_size + effects_size + sinks_size + performance_manager_size ;
@ -162,6 +192,7 @@ private:
CoreTiming : : EventType * audio_event ;
CoreTiming : : EventType * audio_event ;
Kernel : : SharedPtr < Kernel : : Event > system_event ;
Kernel : : SharedPtr < Kernel : : Event > system_event ;
AudioRendererParameters worker_params ;
} ;
} ;
class IAudioDevice final : public ServiceFramework < IAudioDevice > {
class IAudioDevice final : public ServiceFramework < IAudioDevice > {
@ -259,10 +290,12 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
}
}
void AudRenU : : OpenAudioRenderer ( Kernel : : HLERequestContext & ctx ) {
void AudRenU : : OpenAudioRenderer ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp { ctx } ;
auto params = rp . PopRaw < AudioRendererParameters > ( ) ;
IPC : : ResponseBuilder rb { ctx , 2 , 0 , 1 } ;
IPC : : ResponseBuilder rb { ctx , 2 , 0 , 1 } ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushIpcInterface < Audio : : IAudioRenderer > ( ) ;
rb . PushIpcInterface < Audio : : IAudioRenderer > ( std : : move ( params ) ) ;
NGLOG_DEBUG ( Service_Audio , " called " ) ;
NGLOG_DEBUG ( Service_Audio , " called " ) ;
}
}
@ -271,19 +304,19 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC : : RequestParser rp { ctx } ;
IPC : : RequestParser rp { ctx } ;
auto params = rp . PopRaw < AudioRendererParameters > ( ) ;
auto params = rp . PopRaw < AudioRendererParameters > ( ) ;
u64 buffer_sz = Common : : AlignUp ( 4 * params . unknown 8, 0x40 ) ;
u64 buffer_sz = Common : : AlignUp ( 4 * params . unknown _ 8, 0x40 ) ;
buffer_sz + = params . unknown C * 1024 ;
buffer_sz + = params . unknown _c * 1024 ;
buffer_sz + = 0x940 * ( params . unknown C + 1 ) ;
buffer_sz + = 0x940 * ( params . unknown _c + 1 ) ;
buffer_sz + = 0x3F0 * params . voice_count ;
buffer_sz + = 0x3F0 * params . voice_count ;
buffer_sz + = Common : : AlignUp ( 8 * ( params . unknown C + 1 ) , 0x10 ) ;
buffer_sz + = Common : : AlignUp ( 8 * ( params . unknown _c + 1 ) , 0x10 ) ;
buffer_sz + = Common : : AlignUp ( 8 * params . voice_count , 0x10 ) ;
buffer_sz + = Common : : AlignUp ( 8 * params . voice_count , 0x10 ) ;
buffer_sz + =
buffer_sz + =
Common : : AlignUp ( ( 0x3C0 * ( params . sink_count + params . unknown C ) + 4 * params . sample_count ) *
Common : : AlignUp ( ( 0x3C0 * ( params . sink_count + params . unknown _c ) + 4 * params . sample_count ) *
( params . unknown 8 + 6 ) ,
( params . unknown _ 8 + 6 ) ,
0x40 ) ;
0x40 ) ;
if ( IsFeatureSupported ( AudioFeatures : : Splitter , params . magic ) ) {
if ( IsFeatureSupported ( AudioFeatures : : Splitter , params . revision ) ) {
u32 count = params . unknown C + 1 ;
u32 count = params . unknown _c + 1 ;
u64 node_count = Common : : AlignUp ( count , 0x40 ) ;
u64 node_count = Common : : AlignUp ( count , 0x40 ) ;
u64 node_state_buffer_sz =
u64 node_state_buffer_sz =
4 * ( node_count * node_count ) + 0xC * node_count + 2 * ( node_count / 8 ) ;
4 * ( node_count * node_count ) + 0xC * node_count + 2 * ( node_count / 8 ) ;
@ -298,20 +331,20 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
}
}
buffer_sz + = 0x20 * ( params . effect_count + 4 * params . voice_count ) + 0x50 ;
buffer_sz + = 0x20 * ( params . effect_count + 4 * params . voice_count ) + 0x50 ;
if ( IsFeatureSupported ( AudioFeatures : : Splitter , params . magic ) ) {
if ( IsFeatureSupported ( AudioFeatures : : Splitter , params . revision ) ) {
buffer_sz + = 0xE0 * params . unknown 2c;
buffer_sz + = 0xE0 * params . unknown _ 2c;
buffer_sz + = 0x20 * params . splitter_count ;
buffer_sz + = 0x20 * params . splitter_count ;
buffer_sz + = Common : : AlignUp ( 4 * params . unknown 2c, 0x10 ) ;
buffer_sz + = Common : : AlignUp ( 4 * params . unknown _ 2c, 0x10 ) ;
}
}
buffer_sz = Common : : AlignUp ( buffer_sz , 0x40 ) + 0x170 * params . sink_count ;
buffer_sz = Common : : AlignUp ( buffer_sz , 0x40 ) + 0x170 * params . sink_count ;
u64 output_sz = buffer_sz + 0x280 * params . sink_count + 0x4B0 * params . effect_count +
u64 output_sz = buffer_sz + 0x280 * params . sink_count + 0x4B0 * params . effect_count +
( ( params . voice_count * 256 ) | 0x40 ) ;
( ( params . voice_count * 256 ) | 0x40 ) ;
if ( params . unknown 1c > = 1 ) {
if ( params . unknown _ 1c > = 1 ) {
output_sz = Common : : AlignUp ( ( ( 16 * params . sink_count + 16 * params . effect_count +
output_sz = Common : : AlignUp ( ( ( 16 * params . sink_count + 16 * params . effect_count +
16 * params . voice_count + 16 ) +
16 * params . voice_count + 16 ) +
0x658 ) *
0x658 ) *
( params . unknown 1c + 1 ) +
( params . unknown _ 1c + 1 ) +
0xc0 ,
0xc0 ,
0x40 ) +
0x40 ) +
output_sz ;
output_sz ;