summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/android/app/src/main/jni/native.cpp1
-rw-r--r--src/audio_core/CMakeLists.txt15
-rw-r--r--src/audio_core/adsp/adsp.cpp18
-rw-r--r--src/audio_core/adsp/adsp.h50
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp220
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.h116
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_buffer.h23
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp (renamed from src/audio_core/renderer/adsp/command_list_processor.cpp)29
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.h (renamed from src/audio_core/renderer/adsp/command_list_processor.h)21
-rw-r--r--src/audio_core/adsp/mailbox.h69
-rw-r--r--src/audio_core/audio_core.cpp4
-rw-r--r--src/audio_core/audio_core.h6
-rw-r--r--src/audio_core/audio_event.cpp1
-rw-r--r--src/audio_core/audio_in_manager.cpp2
-rw-r--r--src/audio_core/audio_in_manager.h4
-rw-r--r--src/audio_core/audio_out_manager.cpp2
-rw-r--r--src/audio_core/audio_out_manager.h3
-rw-r--r--src/audio_core/audio_render_manager.cpp4
-rw-r--r--src/audio_core/audio_render_manager.h4
-rw-r--r--src/audio_core/common/audio_renderer_parameter.h6
-rw-r--r--src/audio_core/renderer/adsp/adsp.cpp117
-rw-r--r--src/audio_core/renderer/adsp/adsp.h171
-rw-r--r--src/audio_core/renderer/adsp/audio_renderer.cpp225
-rw-r--r--src/audio_core/renderer/adsp/audio_renderer.h204
-rw-r--r--src/audio_core/renderer/adsp/command_buffer.h21
-rw-r--r--src/audio_core/renderer/audio_device.cpp4
-rw-r--r--src/audio_core/renderer/audio_device.h4
-rw-r--r--src/audio_core/renderer/audio_renderer.cpp4
-rw-r--r--src/audio_core/renderer/audio_renderer.h6
-rw-r--r--src/audio_core/renderer/behavior/behavior_info.cpp4
-rw-r--r--src/audio_core/renderer/behavior/behavior_info.h8
-rw-r--r--src/audio_core/renderer/behavior/info_updater.cpp4
-rw-r--r--src/audio_core/renderer/behavior/info_updater.h4
-rw-r--r--src/audio_core/renderer/command/command_buffer.cpp4
-rw-r--r--src/audio_core/renderer/command/command_buffer.h4
-rw-r--r--src/audio_core/renderer/command/command_generator.cpp4
-rw-r--r--src/audio_core/renderer/command/command_generator.h4
-rw-r--r--src/audio_core/renderer/command/command_list_header.h4
-rw-r--r--src/audio_core/renderer/command/command_processing_time_estimator.cpp4
-rw-r--r--src/audio_core/renderer/command/command_processing_time_estimator.h4
-rw-r--r--src/audio_core/renderer/command/data_source/adpcm.cpp24
-rw-r--r--src/audio_core/renderer/command/data_source/adpcm.h23
-rw-r--r--src/audio_core/renderer/command/data_source/decode.cpp110
-rw-r--r--src/audio_core/renderer/command/data_source/decode.h4
-rw-r--r--src/audio_core/renderer/command/data_source/pcm_float.cpp28
-rw-r--r--src/audio_core/renderer/command/data_source/pcm_float.h23
-rw-r--r--src/audio_core/renderer/command/data_source/pcm_int16.cpp28
-rw-r--r--src/audio_core/renderer/command/data_source/pcm_int16.h23
-rw-r--r--src/audio_core/renderer/command/effect/aux_.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/aux_.h13
-rw-r--r--src/audio_core/renderer/command/effect/biquad_filter.cpp14
-rw-r--r--src/audio_core/renderer/command/effect/biquad_filter.h13
-rw-r--r--src/audio_core/renderer/command/effect/capture.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/capture.h13
-rw-r--r--src/audio_core/renderer/command/effect/compressor.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/compressor.h13
-rw-r--r--src/audio_core/renderer/command/effect/delay.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/delay.h13
-rw-r--r--src/audio_core/renderer/command/effect/i3dl2_reverb.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/i3dl2_reverb.h13
-rw-r--r--src/audio_core/renderer/command/effect/light_limiter.cpp22
-rw-r--r--src/audio_core/renderer/command/effect/light_limiter.h19
-rw-r--r--src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp14
-rw-r--r--src/audio_core/renderer/command/effect/multi_tap_biquad_filter.h13
-rw-r--r--src/audio_core/renderer/command/effect/reverb.cpp12
-rw-r--r--src/audio_core/renderer/command/effect/reverb.h13
-rw-r--r--src/audio_core/renderer/command/icommand.h17
-rw-r--r--src/audio_core/renderer/command/mix/clear_mix.cpp14
-rw-r--r--src/audio_core/renderer/command/mix/clear_mix.h13
-rw-r--r--src/audio_core/renderer/command/mix/copy_mix.cpp14
-rw-r--r--src/audio_core/renderer/command/mix/copy_mix.h13
-rw-r--r--src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp14
-rw-r--r--src/audio_core/renderer/command/mix/depop_for_mix_buffers.h13
-rw-r--r--src/audio_core/renderer/command/mix/depop_prepare.cpp14
-rw-r--r--src/audio_core/renderer/command/mix/depop_prepare.h13
-rw-r--r--src/audio_core/renderer/command/mix/mix.cpp12
-rw-r--r--src/audio_core/renderer/command/mix/mix.h13
-rw-r--r--src/audio_core/renderer/command/mix/mix_ramp.cpp13
-rw-r--r--src/audio_core/renderer/command/mix/mix_ramp.h13
-rw-r--r--src/audio_core/renderer/command/mix/mix_ramp_grouped.cpp13
-rw-r--r--src/audio_core/renderer/command/mix/mix_ramp_grouped.h13
-rw-r--r--src/audio_core/renderer/command/mix/volume.cpp12
-rw-r--r--src/audio_core/renderer/command/mix/volume.h13
-rw-r--r--src/audio_core/renderer/command/mix/volume_ramp.cpp13
-rw-r--r--src/audio_core/renderer/command/mix/volume_ramp.h13
-rw-r--r--src/audio_core/renderer/command/performance/performance.cpp20
-rw-r--r--src/audio_core/renderer/command/performance/performance.h13
-rw-r--r--src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.cpp14
-rw-r--r--src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.h13
-rw-r--r--src/audio_core/renderer/command/resample/resample.cpp4
-rw-r--r--src/audio_core/renderer/command/resample/resample.h4
-rw-r--r--src/audio_core/renderer/command/resample/upsample.cpp12
-rw-r--r--src/audio_core/renderer/command/resample/upsample.h13
-rw-r--r--src/audio_core/renderer/command/sink/circular_buffer.cpp14
-rw-r--r--src/audio_core/renderer/command/sink/circular_buffer.h13
-rw-r--r--src/audio_core/renderer/command/sink/device.cpp12
-rw-r--r--src/audio_core/renderer/command/sink/device.h13
-rw-r--r--src/audio_core/renderer/effect/aux_.cpp4
-rw-r--r--src/audio_core/renderer/effect/aux_.h4
-rw-r--r--src/audio_core/renderer/effect/biquad_filter.cpp4
-rw-r--r--src/audio_core/renderer/effect/biquad_filter.h4
-rw-r--r--src/audio_core/renderer/effect/buffer_mixer.cpp4
-rw-r--r--src/audio_core/renderer/effect/buffer_mixer.h4
-rw-r--r--src/audio_core/renderer/effect/capture.cpp4
-rw-r--r--src/audio_core/renderer/effect/capture.h4
-rw-r--r--src/audio_core/renderer/effect/compressor.cpp4
-rw-r--r--src/audio_core/renderer/effect/compressor.h4
-rw-r--r--src/audio_core/renderer/effect/delay.cpp4
-rw-r--r--src/audio_core/renderer/effect/delay.h4
-rw-r--r--src/audio_core/renderer/effect/effect_context.cpp4
-rw-r--r--src/audio_core/renderer/effect/effect_context.h4
-rw-r--r--src/audio_core/renderer/effect/effect_info_base.h4
-rw-r--r--src/audio_core/renderer/effect/effect_reset.h4
-rw-r--r--src/audio_core/renderer/effect/effect_result_state.h4
-rw-r--r--src/audio_core/renderer/effect/i3dl2.cpp4
-rw-r--r--src/audio_core/renderer/effect/i3dl2.h4
-rw-r--r--src/audio_core/renderer/effect/light_limiter.cpp4
-rw-r--r--src/audio_core/renderer/effect/light_limiter.h4
-rw-r--r--src/audio_core/renderer/effect/reverb.cpp4
-rw-r--r--src/audio_core/renderer/effect/reverb.h4
-rw-r--r--src/audio_core/renderer/memory/address_info.h4
-rw-r--r--src/audio_core/renderer/memory/memory_pool_info.cpp4
-rw-r--r--src/audio_core/renderer/memory/memory_pool_info.h4
-rw-r--r--src/audio_core/renderer/memory/pool_mapper.cpp4
-rw-r--r--src/audio_core/renderer/memory/pool_mapper.h4
-rw-r--r--src/audio_core/renderer/mix/mix_context.cpp4
-rw-r--r--src/audio_core/renderer/mix/mix_context.h4
-rw-r--r--src/audio_core/renderer/mix/mix_info.cpp4
-rw-r--r--src/audio_core/renderer/mix/mix_info.h4
-rw-r--r--src/audio_core/renderer/nodes/bit_array.h4
-rw-r--r--src/audio_core/renderer/nodes/edge_matrix.cpp4
-rw-r--r--src/audio_core/renderer/nodes/edge_matrix.h4
-rw-r--r--src/audio_core/renderer/nodes/node_states.cpp4
-rw-r--r--src/audio_core/renderer/nodes/node_states.h4
-rw-r--r--src/audio_core/renderer/performance/detail_aspect.cpp4
-rw-r--r--src/audio_core/renderer/performance/detail_aspect.h4
-rw-r--r--src/audio_core/renderer/performance/entry_aspect.cpp4
-rw-r--r--src/audio_core/renderer/performance/entry_aspect.h4
-rw-r--r--src/audio_core/renderer/performance/performance_detail.h4
-rw-r--r--src/audio_core/renderer/performance/performance_entry.h4
-rw-r--r--src/audio_core/renderer/performance/performance_entry_addresses.h4
-rw-r--r--src/audio_core/renderer/performance/performance_frame_header.h4
-rw-r--r--src/audio_core/renderer/performance/performance_manager.cpp4
-rw-r--r--src/audio_core/renderer/performance/performance_manager.h4
-rw-r--r--src/audio_core/renderer/sink/circular_buffer_sink_info.cpp4
-rw-r--r--src/audio_core/renderer/sink/circular_buffer_sink_info.h4
-rw-r--r--src/audio_core/renderer/sink/device_sink_info.cpp4
-rw-r--r--src/audio_core/renderer/sink/device_sink_info.h4
-rw-r--r--src/audio_core/renderer/sink/sink_context.cpp4
-rw-r--r--src/audio_core/renderer/sink/sink_context.h4
-rw-r--r--src/audio_core/renderer/sink/sink_info_base.cpp4
-rw-r--r--src/audio_core/renderer/sink/sink_info_base.h4
-rw-r--r--src/audio_core/renderer/splitter/splitter_context.cpp4
-rw-r--r--src/audio_core/renderer/splitter/splitter_context.h4
-rw-r--r--src/audio_core/renderer/splitter/splitter_destinations_data.cpp4
-rw-r--r--src/audio_core/renderer/splitter/splitter_destinations_data.h4
-rw-r--r--src/audio_core/renderer/splitter/splitter_info.cpp4
-rw-r--r--src/audio_core/renderer/splitter/splitter_info.h4
-rw-r--r--src/audio_core/renderer/system.cpp42
-rw-r--r--src/audio_core/renderer/system.h16
-rw-r--r--src/audio_core/renderer/system_manager.cpp30
-rw-r--r--src/audio_core/renderer/system_manager.h21
-rw-r--r--src/audio_core/renderer/upsampler/upsampler_info.h4
-rw-r--r--src/audio_core/renderer/upsampler/upsampler_manager.cpp4
-rw-r--r--src/audio_core/renderer/upsampler/upsampler_manager.h4
-rw-r--r--src/audio_core/renderer/upsampler/upsampler_state.h4
-rw-r--r--src/audio_core/renderer/voice/voice_channel_resource.h4
-rw-r--r--src/audio_core/renderer/voice/voice_context.cpp4
-rw-r--r--src/audio_core/renderer/voice/voice_context.h4
-rw-r--r--src/audio_core/renderer/voice/voice_info.cpp4
-rw-r--r--src/audio_core/renderer/voice/voice_info.h4
-rw-r--r--src/audio_core/renderer/voice/voice_state.h4
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/fs/path_util.cpp6
-rw-r--r--src/core/CMakeLists.txt16
-rw-r--r--src/core/core.cpp33
-rw-r--r--src/core/core.h14
-rw-r--r--src/core/crypto/key_manager.cpp226
-rw-r--r--src/core/crypto/key_manager.h59
-rw-r--r--src/core/file_sys/content_archive.cpp17
-rw-r--r--src/core/file_sys/nca_metadata.cpp4
-rw-r--r--src/core/file_sys/nca_metadata.h1
-rw-r--r--src/core/file_sys/registered_cache.cpp28
-rw-r--r--src/core/file_sys/registered_cache.h5
-rw-r--r--src/core/file_sys/submission_package.cpp35
-rw-r--r--src/core/file_sys/submission_package.h1
-rw-r--r--src/core/hle/kernel/k_capabilities.cpp1
-rw-r--r--src/core/hle/service/am/am.cpp65
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp11
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit_types.h3
-rw-r--r--src/core/hle/service/audio/audin_u.cpp4
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/es/es.cpp10
-rw-r--r--src/core/hle/service/mii/mii.cpp139
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp717
-rw-r--r--src/core/hle/service/mii/mii_manager.h42
-rw-r--r--src/core/hle/service/mii/mii_result.h20
-rw-r--r--src/core/hle/service/mii/mii_types.h694
-rw-r--r--src/core/hle/service/mii/mii_util.h59
-rw-r--r--src/core/hle/service/mii/raw_data.h26
-rw-r--r--src/core/hle/service/mii/types.h553
-rw-r--r--src/core/hle/service/mii/types/char_info.cpp482
-rw-r--r--src/core/hle/service/mii/types/char_info.h137
-rw-r--r--src/core/hle/service/mii/types/core_data.cpp601
-rw-r--r--src/core/hle/service/mii/types/core_data.h216
-rw-r--r--src/core/hle/service/mii/types/raw_data.cpp (renamed from src/core/hle/service/mii/raw_data.cpp)1400
-rw-r--r--src/core/hle/service/mii/types/raw_data.h73
-rw-r--r--src/core/hle/service/mii/types/store_data.cpp643
-rw-r--r--src/core/hle/service/mii/types/store_data.h145
-rw-r--r--src/core/hle/service/mii/types/ver3_store_data.cpp241
-rw-r--r--src/core/hle/service/mii/types/ver3_store_data.h160
-rw-r--r--src/core/hle/service/nfc/common/device.cpp25
-rw-r--r--src/core/hle/service/nfp/nfp_types.h6
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp4
-rw-r--r--src/core/hle/service/ssl/ssl_backend_schannel.cpp3
-rw-r--r--src/core/internal_network/network.cpp89
-rw-r--r--src/core/internal_network/network.h3
-rw-r--r--src/core/loader/loader.cpp4
-rw-r--r--src/core/loader/loader.h10
-rw-r--r--src/core/loader/nca.cpp76
-rw-r--r--src/core/loader/nca.h2
-rw-r--r--src/core/loader/nsp.cpp36
-rw-r--r--src/core/loader/nsp.h2
-rw-r--r--src/core/loader/xci.cpp34
-rw-r--r--src/core/loader/xci.h2
-rw-r--r--src/dedicated_room/yuzu_room.cpp6
-rw-r--r--src/input_common/CMakeLists.txt2
-rw-r--r--src/network/room.cpp2
-rw-r--r--src/shader_recompiler/CMakeLists.txt2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp4
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp10
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp3
-rw-r--r--src/tests/common/ring_buffer.cpp2
-rw-r--r--src/video_core/dma_pusher.cpp34
-rw-r--r--src/video_core/dma_pusher.h5
-rw-r--r--src/video_core/engines/engine_interface.h8
-rw-r--r--src/video_core/engines/engine_upload.h8
-rw-r--r--src/video_core/engines/kepler_compute.cpp20
-rw-r--r--src/video_core/engines/kepler_compute.h17
-rw-r--r--src/video_core/engines/maxwell_3d.cpp6
-rw-r--r--src/video_core/engines/puller.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp11
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp18
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp14
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.cpp27
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.h2
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp8
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp1
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h5
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.cpp3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp28
-rw-r--r--src/yuzu/configuration/shared_widget.cpp2
-rw-r--r--src/yuzu/game_list.cpp9
-rw-r--r--src/yuzu/game_list.h4
-rw-r--r--src/yuzu/main.cpp389
-rw-r--r--src/yuzu/main.h16
-rw-r--r--src/yuzu/main.ui6
-rw-r--r--src/yuzu_cmd/yuzu.cpp3
266 files changed, 6840 insertions, 3788 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6068c7a1f..d7f68618c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,7 +24,7 @@ if (MSVC)
# Ensure that projects build with Unicode support.
add_definitions(-DUNICODE -D_UNICODE)
- # /W3 - Level 3 warnings
+ # /W4 - Level 4 warnings
# /MP - Multi-threaded compilation
# /Zi - Output debugging information
# /Zm - Specifies the precompiled header memory allocation limit
@@ -61,7 +61,7 @@ if (MSVC)
/external:W0 # Sets the default warning level to 0 for external headers, effectively turning off warnings for external headers
# Warnings
- /W3
+ /W4
/WX
/we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
@@ -84,12 +84,17 @@ if (MSVC)
/wd4100 # 'identifier': unreferenced formal parameter
/wd4324 # 'struct_name': structure was padded due to __declspec(align())
+ /wd4201 # nonstandard extension used : nameless struct/union
+ /wd4702 # unreachable code (when used with LTO)
)
if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS)
# when caching, we need to use /Z7 to downgrade debug info to use an older but more cacheable format
# Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21
add_compile_options(/Z7)
+ # Avoid D9025 warning
+ string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
else()
add_compile_options(/Zi)
endif()
@@ -105,6 +110,8 @@ if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
else()
add_compile_options(
+ -fwrapv
+
-Werror=all
-Werror=extra
-Werror=missing-declarations
@@ -129,7 +136,6 @@ else()
if (ARCHITECTURE_x86_64)
add_compile_options("-mcx16")
- add_compile_options("-fwrapv")
endif()
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 0f2a6d9e4..b9ecefa74 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -270,6 +270,7 @@ public:
m_vulkan_library);
m_system.SetFilesystem(m_vfs);
+ m_system.GetUserChannel().clear();
// Initialize system.
jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index e7b595459..67dfe0290 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -2,6 +2,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
add_library(audio_core STATIC
+ adsp/adsp.cpp
+ adsp/adsp.h
+ adsp/mailbox.h
+ adsp/apps/audio_renderer/audio_renderer.cpp
+ adsp/apps/audio_renderer/audio_renderer.h
+ adsp/apps/audio_renderer/command_buffer.h
+ adsp/apps/audio_renderer/command_list_processor.cpp
+ adsp/apps/audio_renderer/command_list_processor.h
audio_core.cpp
audio_core.h
audio_event.h
@@ -32,13 +40,6 @@ add_library(audio_core STATIC
out/audio_out_system.cpp
out/audio_out_system.h
precompiled_headers.h
- renderer/adsp/adsp.cpp
- renderer/adsp/adsp.h
- renderer/adsp/audio_renderer.cpp
- renderer/adsp/audio_renderer.h
- renderer/adsp/command_buffer.h
- renderer/adsp/command_list_processor.cpp
- renderer/adsp/command_list_processor.h
renderer/audio_device.cpp
renderer/audio_device.h
renderer/audio_renderer.h
diff --git a/src/audio_core/adsp/adsp.cpp b/src/audio_core/adsp/adsp.cpp
new file mode 100644
index 000000000..0580990f5
--- /dev/null
+++ b/src/audio_core/adsp/adsp.cpp
@@ -0,0 +1,18 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/adsp/adsp.h"
+#include "core/core.h"
+
+namespace AudioCore::ADSP {
+
+ADSP::ADSP(Core::System& system, Sink::Sink& sink) {
+ audio_renderer =
+ std::make_unique<AudioRenderer::AudioRenderer>(system, system.ApplicationMemory(), sink);
+}
+
+AudioRenderer::AudioRenderer& ADSP::AudioRenderer() {
+ return *audio_renderer.get();
+}
+
+} // namespace AudioCore::ADSP
diff --git a/src/audio_core/adsp/adsp.h b/src/audio_core/adsp/adsp.h
new file mode 100644
index 000000000..bd5bcc63b
--- /dev/null
+++ b/src/audio_core/adsp/adsp.h
@@ -0,0 +1,50 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/adsp/apps/audio_renderer/audio_renderer.h"
+#include "common/common_types.h"
+
+namespace Core {
+class System;
+} // namespace Core
+
+namespace AudioCore {
+namespace Sink {
+class Sink;
+}
+
+namespace ADSP {
+
+/**
+ * Represents the ADSP embedded within the audio sysmodule.
+ * This is a 32-bit Linux4Tegra kernel from nVidia, which is launched with the sysmodule on boot.
+ *
+ * The kernel will run the apps you write for it, Nintendo have the following:
+ *
+ * Gmix - Responsible for mixing final audio and sending it out to hardware. This is last place all
+ * audio samples end up, and we skip it entirely, since we have very different backends and
+ * mixing is implicitly handled by the OS (but also due to lack of research/simplicity).
+ *
+ * AudioRenderer - Receives command lists generated by the audio render
+ * system on the host, processes them, and sends the samples to Gmix.
+ *
+ * OpusDecoder - Contains libopus, and decodes Opus audio packets into raw pcm data.
+ *
+ * Communication between the host and ADSP is done through mailboxes, and mapping of shared memory.
+ */
+class ADSP {
+public:
+ explicit ADSP(Core::System& system, Sink::Sink& sink);
+ ~ADSP() = default;
+
+ AudioRenderer::AudioRenderer& AudioRenderer();
+
+private:
+ /// AudioRenderer app
+ std::unique_ptr<AudioRenderer::AudioRenderer> audio_renderer{};
+};
+
+} // namespace ADSP
+} // namespace AudioCore
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
new file mode 100644
index 000000000..2e549bc6f
--- /dev/null
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
@@ -0,0 +1,220 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <array>
+#include <chrono>
+
+#include "audio_core/adsp/apps/audio_renderer/audio_renderer.h"
+#include "audio_core/audio_core.h"
+#include "audio_core/common/common.h"
+#include "audio_core/sink/sink.h"
+#include "common/logging/log.h"
+#include "common/microprofile.h"
+#include "common/thread.h"
+#include "core/core.h"
+#include "core/core_timing.h"
+
+MICROPROFILE_DEFINE(Audio_Renderer, "Audio", "DSP", MP_RGB(60, 19, 97));
+
+namespace AudioCore::ADSP::AudioRenderer {
+
+AudioRenderer::AudioRenderer(Core::System& system_, Core::Memory::Memory& memory_,
+ Sink::Sink& sink_)
+ : system{system_}, memory{memory_}, sink{sink_} {}
+
+AudioRenderer::~AudioRenderer() {
+ Stop();
+}
+
+void AudioRenderer::Start() {
+ CreateSinkStreams();
+
+ mailbox.Initialize(AppMailboxId::AudioRenderer);
+
+ main_thread = std::jthread([this](std::stop_token stop_token) { Main(stop_token); });
+
+ mailbox.Send(Direction::DSP, {Message::InitializeOK, {}});
+ if (mailbox.Receive(Direction::Host).msg != Message::InitializeOK) {
+ LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown "
+ "message response from ADSP!");
+ return;
+ }
+ running = true;
+}
+
+void AudioRenderer::Stop() {
+ if (!running) {
+ return;
+ }
+
+ mailbox.Send(Direction::DSP, {Message::Shutdown, {}});
+ if (mailbox.Receive(Direction::Host).msg != Message::Shutdown) {
+ LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown "
+ "message response from ADSP!");
+ }
+ main_thread.request_stop();
+ main_thread.join();
+
+ for (auto& stream : streams) {
+ if (stream) {
+ stream->Stop();
+ sink.CloseStream(stream);
+ stream = nullptr;
+ }
+ }
+ running = false;
+}
+
+void AudioRenderer::Signal() {
+ signalled_tick = system.CoreTiming().GetGlobalTimeNs().count();
+ Send(Direction::DSP, {Message::Render, {}});
+}
+
+void AudioRenderer::Wait() {
+ auto received = Receive(Direction::Host);
+ if (received.msg != Message::RenderResponse) {
+ LOG_ERROR(Service_Audio,
+ "Did not receive the expected render response from the AudioRenderer! Expected "
+ "{}, got {}",
+ Message::RenderResponse, received.msg);
+ }
+}
+
+void AudioRenderer::Send(Direction dir, MailboxMessage message) {
+ mailbox.Send(dir, std::move(message));
+}
+
+MailboxMessage AudioRenderer::Receive(Direction dir, bool block) {
+ return mailbox.Receive(dir, block);
+}
+
+void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
+ u64 applet_resource_user_id, bool reset) noexcept {
+ command_buffers[session_id].buffer = buffer;
+ command_buffers[session_id].size = size;
+ command_buffers[session_id].time_limit = time_limit;
+ command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
+ command_buffers[session_id].reset_buffer = reset;
+}
+
+u32 AudioRenderer::GetRemainCommandCount(s32 session_id) const noexcept {
+ return command_buffers[session_id].remaining_command_count;
+}
+
+void AudioRenderer::ClearRemainCommandCount(s32 session_id) noexcept {
+ command_buffers[session_id].remaining_command_count = 0;
+}
+
+u64 AudioRenderer::GetRenderingStartTick(s32 session_id) const noexcept {
+ return (1000 * command_buffers[session_id].render_time_taken_us) + signalled_tick;
+}
+
+void AudioRenderer::CreateSinkStreams() {
+ u32 channels{sink.GetDeviceChannels()};
+ for (u32 i = 0; i < MaxRendererSessions; i++) {
+ std::string name{fmt::format("ADSP_RenderStream-{}", i)};
+ streams[i] =
+ sink.AcquireSinkStream(system, channels, name, ::AudioCore::Sink::StreamType::Render);
+ streams[i]->SetRingSize(4);
+ }
+}
+
+void AudioRenderer::Main(std::stop_token stop_token) {
+ static constexpr char name[]{"AudioRenderer"};
+ MicroProfileOnThreadCreate(name);
+ Common::SetCurrentThreadName(name);
+ Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
+
+ // TODO: Create buffer map/unmap thread + mailbox
+ // TODO: Create gMix devices, initialize them here
+
+ if (mailbox.Receive(Direction::DSP).msg != Message::InitializeOK) {
+ LOG_ERROR(Service_Audio,
+ "ADSP Audio Renderer -- Failed to receive initialize message from host!");
+ return;
+ }
+
+ mailbox.Send(Direction::Host, {Message::InitializeOK, {}});
+
+ // 0.12 seconds (2,304,000 / 19,200,000)
+ constexpr u64 max_process_time{2'304'000ULL};
+
+ while (!stop_token.stop_requested()) {
+ auto received{mailbox.Receive(Direction::DSP)};
+ switch (received.msg) {
+ case Message::Shutdown:
+ mailbox.Send(Direction::Host, {Message::Shutdown, {}});
+ return;
+
+ case Message::Render: {
+ if (system.IsShuttingDown()) [[unlikely]] {
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ mailbox.Send(Direction::Host, {Message::RenderResponse, {}});
+ continue;
+ }
+ std::array<bool, MaxRendererSessions> buffers_reset{};
+ std::array<u64, MaxRendererSessions> render_times_taken{};
+ const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()};
+
+ for (u32 index = 0; index < MaxRendererSessions; index++) {
+ auto& command_buffer{command_buffers[index]};
+ auto& command_list_processor{command_list_processors[index]};
+
+ // Check this buffer is valid, as it may not be used.
+ if (command_buffer.buffer != 0) {
+ // If there are no remaining commands (from the previous list),
+ // this is a new command list, initialize it.
+ if (command_buffer.remaining_command_count == 0) {
+ command_list_processor.Initialize(system, command_buffer.buffer,
+ command_buffer.size, streams[index]);
+ }
+
+ if (command_buffer.reset_buffer && !buffers_reset[index]) {
+ streams[index]->ClearQueue();
+ buffers_reset[index] = true;
+ }
+
+ u64 max_time{max_process_time};
+ if (index == 1 && command_buffer.applet_resource_user_id ==
+ command_buffers[0].applet_resource_user_id) {
+ max_time = max_process_time - render_times_taken[0];
+ if (render_times_taken[0] > max_process_time) {
+ max_time = 0;
+ }
+ }
+
+ max_time = std::min(command_buffer.time_limit, max_time);
+ command_list_processor.SetProcessTimeMax(max_time);
+
+ if (index == 0) {
+ streams[index]->WaitFreeSpace(stop_token);
+ }
+
+ // Process the command list
+ {
+ MICROPROFILE_SCOPE(Audio_Renderer);
+ render_times_taken[index] =
+ command_list_processor.Process(index) - start_time;
+ }
+
+ const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()};
+
+ command_buffer.remaining_command_count =
+ command_list_processor.GetRemainingCommandCount();
+ command_buffer.render_time_taken_us = end_time - start_time;
+ }
+ }
+
+ mailbox.Send(Direction::Host, {Message::RenderResponse, {}});
+ } break;
+
+ default:
+ LOG_WARNING(Service_Audio,
+ "ADSP AudioRenderer received an invalid message, msg={:02X}!",
+ received.msg);
+ break;
+ }
+ }
+}
+
+} // namespace AudioCore::ADSP::AudioRenderer
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
new file mode 100644
index 000000000..3f5b7dca2
--- /dev/null
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
@@ -0,0 +1,116 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <array>
+#include <memory>
+#include <thread>
+
+#include "audio_core/adsp/apps/audio_renderer/command_buffer.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
+#include "audio_core/adsp/mailbox.h"
+#include "common/common_types.h"
+#include "common/polyfill_thread.h"
+#include "common/reader_writer_queue.h"
+#include "common/thread.h"
+
+namespace Core {
+class System;
+namespace Timing {
+struct EventType;
+}
+namespace Memory {
+class Memory;
+}
+class System;
+} // namespace Core
+
+namespace AudioCore {
+namespace Sink {
+class Sink;
+}
+
+namespace ADSP::AudioRenderer {
+
+enum Message : u32 {
+ Invalid = 0x00,
+ MapUnmap_Map = 0x01,
+ MapUnmap_MapResponse = 0x02,
+ MapUnmap_Unmap = 0x03,
+ MapUnmap_UnmapResponse = 0x04,
+ MapUnmap_InvalidateCache = 0x05,
+ MapUnmap_InvalidateCacheResponse = 0x06,
+ MapUnmap_Shutdown = 0x07,
+ MapUnmap_ShutdownResponse = 0x08,
+ InitializeOK = 0x16,
+ RenderResponse = 0x20,
+ Render = 0x2A,
+ Shutdown = 0x34,
+};
+
+/**
+ * The AudioRenderer application running on the ADSP.
+ */
+class AudioRenderer {
+public:
+ explicit AudioRenderer(Core::System& system, Core::Memory::Memory& memory, Sink::Sink& sink);
+ ~AudioRenderer();
+
+ /**
+ * Start the AudioRenderer.
+ *
+ * @param mailbox The mailbox to use for this session.
+ */
+ void Start();
+
+ /**
+ * Stop the AudioRenderer.
+ */
+ void Stop();
+
+ void Signal();
+ void Wait();
+
+ void Send(Direction dir, MailboxMessage message);
+ MailboxMessage Receive(Direction dir, bool block = true);
+
+ void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
+ u64 applet_resource_user_id, bool reset) noexcept;
+ u32 GetRemainCommandCount(s32 session_id) const noexcept;
+ void ClearRemainCommandCount(s32 session_id) noexcept;
+ u64 GetRenderingStartTick(s32 session_id) const noexcept;
+
+private:
+ /**
+ * Main AudioRenderer thread, responsible for processing the command lists.
+ */
+ void Main(std::stop_token stop_token);
+
+ /**
+ * Creates the streams which will receive the processed samples.
+ */
+ void CreateSinkStreams();
+
+ /// Core system
+ Core::System& system;
+ /// Memory
+ Core::Memory::Memory& memory;
+ /// The output sink the AudioRenderer will use
+ Sink::Sink& sink;
+ /// The active mailbox
+ Mailbox mailbox;
+ /// Main thread
+ std::jthread main_thread{};
+ /// The current state
+ std::atomic<bool> running{};
+ std::array<CommandBuffer, MaxRendererSessions> command_buffers{};
+ /// The command lists to process
+ std::array<CommandListProcessor, MaxRendererSessions> command_list_processors{};
+ /// The streams which will receive the processed samples
+ std::array<Sink::SinkStream*, MaxRendererSessions> streams{};
+ u64 signalled_tick{0};
+};
+
+} // namespace ADSP::AudioRenderer
+} // namespace AudioCore
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
new file mode 100644
index 000000000..3fd1b09dc
--- /dev/null
+++ b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/common/common.h"
+#include "common/common_types.h"
+
+namespace AudioCore::ADSP::AudioRenderer {
+
+struct CommandBuffer {
+ // Set by the host
+ CpuAddr buffer{};
+ u64 size{};
+ u64 time_limit{};
+ u64 applet_resource_user_id{};
+ bool reset_buffer{};
+ // Set by the DSP
+ u32 remaining_command_count{};
+ u64 render_time_taken_us{};
+};
+
+} // namespace AudioCore::ADSP::AudioRenderer
diff --git a/src/audio_core/renderer/adsp/command_list_processor.cpp b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
index 3a0f1ae38..24e4d0496 100644
--- a/src/audio_core/renderer/adsp/command_list_processor.cpp
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
@@ -1,9 +1,9 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <string>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/command_list_header.h"
#include "audio_core/renderer/command/commands.h"
#include "common/settings.h"
@@ -11,15 +11,15 @@
#include "core/core_timing.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer::ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
Sink::SinkStream* stream_) {
system = &system_;
memory = &system->ApplicationMemory();
stream = stream_;
- header = reinterpret_cast<CommandListHeader*>(buffer);
- commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader));
+ header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
+ commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));
commands_buffer_size = size;
command_count = header->command_count;
sample_count = header->sample_count;
@@ -37,17 +37,12 @@ u32 CommandListProcessor::GetRemainingCommandCount() const {
return command_count - processed_command_count;
}
-void CommandListProcessor::SetBuffer(const CpuAddr buffer, const u64 size) {
- commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader));
- commands_buffer_size = size;
-}
-
Sink::SinkStream* CommandListProcessor::GetOutputSinkStream() const {
return stream;
}
u64 CommandListProcessor::Process(u32 session_id) {
- const auto start_time_{system->CoreTiming().GetClockTicks()};
+ const auto start_time_{system->CoreTiming().GetGlobalTimeUs().count()};
const auto command_base{CpuAddr(commands)};
if (processed_command_count > 0) {
@@ -60,12 +55,12 @@ u64 CommandListProcessor::Process(u32 session_id) {
std::string dump{fmt::format("\nSession {}\n", session_id)};
for (u32 index = 0; index < command_count; index++) {
- auto& command{*reinterpret_cast<ICommand*>(commands)};
+ auto& command{*reinterpret_cast<Renderer::ICommand*>(commands)};
if (command.magic != 0xCAFEBABE) {
LOG_ERROR(Service_Audio, "Command has invalid magic! Expected 0xCAFEBABE, got {:08X}",
command.magic);
- return system->CoreTiming().GetClockTicks() - start_time_;
+ return system->CoreTiming().GetGlobalTimeUs().count() - start_time_;
}
auto current_offset{CpuAddr(commands) - command_base};
@@ -74,8 +69,8 @@ u64 CommandListProcessor::Process(u32 session_id) {
LOG_ERROR(Service_Audio,
"Command exceeded command buffer, buffer size {:08X}, command ends at {:08X}",
commands_buffer_size,
- CpuAddr(commands) + command.size - sizeof(CommandListHeader));
- return system->CoreTiming().GetClockTicks() - start_time_;
+ CpuAddr(commands) + command.size - sizeof(Renderer::CommandListHeader));
+ return system->CoreTiming().GetGlobalTimeUs().count() - start_time_;
}
if (Settings::values.dump_audio_commands) {
@@ -101,8 +96,8 @@ u64 CommandListProcessor::Process(u32 session_id) {
last_dump = dump;
}
- end_time = system->CoreTiming().GetClockTicks();
+ end_time = system->CoreTiming().GetGlobalTimeUs().count();
return end_time - start_time_;
}
-} // namespace AudioCore::AudioRenderer::ADSP
+} // namespace AudioCore::ADSP::AudioRenderer
diff --git a/src/audio_core/renderer/adsp/command_list_processor.h b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
index d78269e1d..4e5fb793e 100644
--- a/src/audio_core/renderer/adsp/command_list_processor.h
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -6,6 +6,7 @@
#include <span>
#include "audio_core/common/common.h"
+#include "audio_core/renderer/command/command_list_header.h"
#include "common/common_types.h"
namespace Core {
@@ -20,10 +21,11 @@ namespace Sink {
class SinkStream;
}
-namespace AudioRenderer {
+namespace Renderer {
struct CommandListHeader;
+}
-namespace ADSP {
+namespace ADSP::AudioRenderer {
/**
* A processor for command lists given to the AudioRenderer.
@@ -55,14 +57,6 @@ public:
u32 GetRemainingCommandCount() const;
/**
- * Set the command buffer.
- *
- * @param buffer - The buffer to use.
- * @param size - The size of the buffer.
- */
- void SetBuffer(CpuAddr buffer, u64 size);
-
- /**
* Get the stream for this command list.
*
* @return The stream associated with this command list.
@@ -85,7 +79,7 @@ public:
/// Stream for the processed samples
Sink::SinkStream* stream{};
/// Header info for this command list
- CommandListHeader* header{};
+ Renderer::CommandListHeader* header{};
/// The command buffer
u8* commands{};
/// The command buffer size
@@ -114,6 +108,5 @@ public:
std::string last_dump{};
};
-} // namespace ADSP
-} // namespace AudioRenderer
+} // namespace ADSP::AudioRenderer
} // namespace AudioCore
diff --git a/src/audio_core/adsp/mailbox.h b/src/audio_core/adsp/mailbox.h
new file mode 100644
index 000000000..c31b73717
--- /dev/null
+++ b/src/audio_core/adsp/mailbox.h
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/bounded_threadsafe_queue.h"
+#include "common/common_types.h"
+
+namespace AudioCore::ADSP {
+
+enum class AppMailboxId : u32 {
+ Invalid = 0,
+ AudioRenderer = 50,
+ AudioRendererMemoryMapUnmap = 51,
+};
+
+enum class Direction : u32 {
+ Host,
+ DSP,
+};
+
+struct MailboxMessage {
+ u32 msg;
+ std::span<u8> data;
+};
+
+class Mailbox {
+public:
+ void Initialize(AppMailboxId id_) {
+ Reset();
+ id = id_;
+ }
+
+ AppMailboxId Id() const noexcept {
+ return id;
+ }
+
+ void Send(Direction dir, MailboxMessage&& message) {
+ auto& queue = dir == Direction::Host ? host_queue : adsp_queue;
+ queue.EmplaceWait(std::move(message));
+ }
+
+ MailboxMessage Receive(Direction dir, bool block = true) {
+ auto& queue = dir == Direction::Host ? host_queue : adsp_queue;
+ MailboxMessage t;
+ if (block) {
+ queue.PopWait(t);
+ } else {
+ queue.TryPop(t);
+ }
+ return t;
+ }
+
+ void Reset() {
+ id = AppMailboxId::Invalid;
+ MailboxMessage t;
+ while (host_queue.TryPop(t)) {
+ }
+ while (adsp_queue.TryPop(t)) {
+ }
+ }
+
+private:
+ AppMailboxId id{0};
+ Common::SPSCQueue<MailboxMessage> host_queue;
+ Common::SPSCQueue<MailboxMessage> adsp_queue;
+};
+
+} // namespace AudioCore::ADSP
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index 703ef4494..fcaab2b32 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -11,7 +11,7 @@ namespace AudioCore {
AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>()} {
CreateSinks();
// Must be created after the sinks
- adsp = std::make_unique<AudioRenderer::ADSP::ADSP>(system, *output_sink);
+ adsp = std::make_unique<ADSP::ADSP>(system, *output_sink);
}
AudioCore ::~AudioCore() {
@@ -43,7 +43,7 @@ Sink::Sink& AudioCore::GetInputSink() {
return *input_sink;
}
-AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() {
+ADSP::ADSP& AudioCore::ADSP() {
return *adsp;
}
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index ea047773e..e4e27fc66 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -5,8 +5,8 @@
#include <memory>
+#include "audio_core/adsp/adsp.h"
#include "audio_core/audio_manager.h"
-#include "audio_core/renderer/adsp/adsp.h"
#include "audio_core/sink/sink.h"
namespace Core {
@@ -55,7 +55,7 @@ public:
*
* @return Ref to the ADSP.
*/
- AudioRenderer::ADSP::ADSP& GetADSP();
+ ADSP::ADSP& ADSP();
private:
/**
@@ -70,7 +70,7 @@ private:
/// Sink used for audio input
std::unique_ptr<Sink::Sink> input_sink;
/// The ADSP in the sysmodule
- std::unique_ptr<AudioRenderer::ADSP::ADSP> adsp;
+ std::unique_ptr<ADSP::ADSP> adsp;
};
} // namespace AudioCore
diff --git a/src/audio_core/audio_event.cpp b/src/audio_core/audio_event.cpp
index d15568e1f..c23ef0990 100644
--- a/src/audio_core/audio_event.cpp
+++ b/src/audio_core/audio_event.cpp
@@ -20,7 +20,6 @@ size_t Event::GetManagerIndex(const Type type) const {
default:
UNREACHABLE();
}
- return 3;
}
void Event::SetAudioEvent(const Type type, const bool signalled) {
diff --git a/src/audio_core/audio_in_manager.cpp b/src/audio_core/audio_in_manager.cpp
index 3dfb613cb..a3667524f 100644
--- a/src/audio_core/audio_in_manager.cpp
+++ b/src/audio_core/audio_in_manager.cpp
@@ -73,7 +73,7 @@ void Manager::BufferReleaseAndRegister() {
}
}
-u32 Manager::GetDeviceNames(std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names,
+u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names,
[[maybe_unused]] const u32 max_count,
[[maybe_unused]] const bool filter) {
std::scoped_lock l{mutex};
diff --git a/src/audio_core/audio_in_manager.h b/src/audio_core/audio_in_manager.h
index 8a519df99..5c4614cd1 100644
--- a/src/audio_core/audio_in_manager.h
+++ b/src/audio_core/audio_in_manager.h
@@ -65,8 +65,8 @@ public:
*
* @return Number of names written.
*/
- u32 GetDeviceNames(std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names,
- u32 max_count, bool filter);
+ u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count,
+ bool filter);
/// Core system
Core::System& system;
diff --git a/src/audio_core/audio_out_manager.cpp b/src/audio_core/audio_out_manager.cpp
index f22821360..316ea7c81 100644
--- a/src/audio_core/audio_out_manager.cpp
+++ b/src/audio_core/audio_out_manager.cpp
@@ -73,7 +73,7 @@ void Manager::BufferReleaseAndRegister() {
}
u32 Manager::GetAudioOutDeviceNames(
- std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names) const {
+ std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const {
names.emplace_back("DeviceOut");
return 1;
}
diff --git a/src/audio_core/audio_out_manager.h b/src/audio_core/audio_out_manager.h
index 1e05ec5ed..c3e445d5d 100644
--- a/src/audio_core/audio_out_manager.h
+++ b/src/audio_core/audio_out_manager.h
@@ -61,8 +61,7 @@ public:
* @param names - Output container to write names to.
* @return Number of names written.
*/
- u32 GetAudioOutDeviceNames(
- std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names) const;
+ u32 GetAudioOutDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const;
/// Core system
Core::System& system;
diff --git a/src/audio_core/audio_render_manager.cpp b/src/audio_core/audio_render_manager.cpp
index 320715727..3c53e3afd 100644
--- a/src/audio_core/audio_render_manager.cpp
+++ b/src/audio_core/audio_render_manager.cpp
@@ -6,7 +6,7 @@
#include "audio_core/common/feature_support.h"
#include "core/core.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
Manager::Manager(Core::System& system_)
: system{system_}, system_manager{std::make_unique<SystemManager>(system)} {
@@ -67,4 +67,4 @@ bool Manager::RemoveSystem(System& system_) {
return system_manager->Remove(system_);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/audio_render_manager.h b/src/audio_core/audio_render_manager.h
index fffa5944d..45537b270 100644
--- a/src/audio_core/audio_render_manager.h
+++ b/src/audio_core/audio_render_manager.h
@@ -20,7 +20,7 @@ class System;
namespace AudioCore {
struct AudioRendererParameterInternal;
-namespace AudioRenderer {
+namespace Renderer {
/**
* Wrapper for the audio system manager, handles service calls.
*/
@@ -101,5 +101,5 @@ private:
std::unique_ptr<SystemManager> system_manager{};
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/common/audio_renderer_parameter.h b/src/audio_core/common/audio_renderer_parameter.h
index 8c7892bcf..6c4e9fdc6 100644
--- a/src/audio_core/common/audio_renderer_parameter.h
+++ b/src/audio_core/common/audio_renderer_parameter.h
@@ -51,10 +51,10 @@ struct AudioRendererSystemContext {
s32 session_id;
s8 channels;
s16 mix_buffer_count;
- AudioRenderer::BehaviorInfo* behavior;
+ Renderer::BehaviorInfo* behavior;
std::span<s32> depop_buffer;
- AudioRenderer::UpsamplerManager* upsampler_manager;
- AudioRenderer::MemoryPoolInfo* memory_pool_info;
+ Renderer::UpsamplerManager* upsampler_manager;
+ Renderer::MemoryPoolInfo* memory_pool_info;
};
} // namespace AudioCore
diff --git a/src/audio_core/renderer/adsp/adsp.cpp b/src/audio_core/renderer/adsp/adsp.cpp
deleted file mode 100644
index b1db31e93..000000000
--- a/src/audio_core/renderer/adsp/adsp.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "audio_core/renderer/adsp/adsp.h"
-#include "audio_core/renderer/adsp/command_buffer.h"
-#include "audio_core/sink/sink.h"
-#include "common/logging/log.h"
-#include "core/core.h"
-#include "core/core_timing.h"
-#include "core/memory.h"
-
-namespace AudioCore::AudioRenderer::ADSP {
-
-ADSP::ADSP(Core::System& system_, Sink::Sink& sink_)
- : system{system_}, memory{system.ApplicationMemory()}, sink{sink_} {}
-
-ADSP::~ADSP() {
- ClearCommandBuffers();
-}
-
-State ADSP::GetState() const {
- if (running) {
- return State::Started;
- }
- return State::Stopped;
-}
-
-AudioRenderer_Mailbox* ADSP::GetRenderMailbox() {
- return &render_mailbox;
-}
-
-void ADSP::ClearRemainCount(const u32 session_id) {
- render_mailbox.ClearRemainCount(session_id);
-}
-
-u64 ADSP::GetSignalledTick() const {
- return render_mailbox.GetSignalledTick();
-}
-
-u64 ADSP::GetTimeTaken() const {
- return render_mailbox.GetRenderTimeTaken();
-}
-
-u64 ADSP::GetRenderTimeTaken(const u32 session_id) {
- return render_mailbox.GetCommandBuffer(session_id).render_time_taken;
-}
-
-u32 ADSP::GetRemainCommandCount(const u32 session_id) const {
- return render_mailbox.GetRemainCommandCount(session_id);
-}
-
-void ADSP::SendCommandBuffer(const u32 session_id, const CommandBuffer& command_buffer) {
- render_mailbox.SetCommandBuffer(session_id, command_buffer);
-}
-
-u64 ADSP::GetRenderingStartTick(const u32 session_id) {
- return render_mailbox.GetSignalledTick() +
- render_mailbox.GetCommandBuffer(session_id).render_time_taken;
-}
-
-bool ADSP::Start() {
- if (running) {
- return running;
- }
-
- running = true;
- systems_active++;
- audio_renderer = std::make_unique<AudioRenderer>(system);
- audio_renderer->Start(&render_mailbox);
- render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_InitializeOK);
- if (render_mailbox.HostWaitMessage() != RenderMessage::AudioRenderer_InitializeOK) {
- LOG_ERROR(
- Service_Audio,
- "Host Audio Renderer -- Failed to receive initialize message response from ADSP!");
- }
- return running;
-}
-
-void ADSP::Stop() {
- systems_active--;
- if (running && systems_active == 0) {
- {
- std::scoped_lock l{mailbox_lock};
- render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_Shutdown);
- if (render_mailbox.HostWaitMessage() != RenderMessage::AudioRenderer_Shutdown) {
- LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown "
- "message response from ADSP!");
- }
- }
- audio_renderer->Stop();
- running = false;
- }
-}
-
-void ADSP::Signal() {
- const auto signalled_tick{system.CoreTiming().GetClockTicks()};
- render_mailbox.SetSignalledTick(signalled_tick);
- render_mailbox.HostSendMessage(RenderMessage::AudioRenderer_Render);
-}
-
-void ADSP::Wait() {
- std::scoped_lock l{mailbox_lock};
- auto response{render_mailbox.HostWaitMessage()};
- if (response != RenderMessage::AudioRenderer_RenderResponse) {
- LOG_ERROR(Service_Audio, "Invalid ADSP response message, expected 0x{:02X}, got 0x{:02X}",
- static_cast<u32>(RenderMessage::AudioRenderer_RenderResponse),
- static_cast<u32>(response));
- }
-
- ClearCommandBuffers();
-}
-
-void ADSP::ClearCommandBuffers() {
- render_mailbox.ClearCommandBuffers();
-}
-
-} // namespace AudioCore::AudioRenderer::ADSP
diff --git a/src/audio_core/renderer/adsp/adsp.h b/src/audio_core/renderer/adsp/adsp.h
deleted file mode 100644
index f7a2f25e4..000000000
--- a/src/audio_core/renderer/adsp/adsp.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <mutex>
-
-#include "audio_core/renderer/adsp/audio_renderer.h"
-#include "common/common_types.h"
-
-namespace Core {
-namespace Memory {
-class Memory;
-}
-class System;
-} // namespace Core
-
-namespace AudioCore {
-namespace Sink {
-class Sink;
-}
-
-namespace AudioRenderer::ADSP {
-struct CommandBuffer;
-
-enum class State {
- Started,
- Stopped,
-};
-
-/**
- * Represents the ADSP embedded within the audio sysmodule.
- * This is a 32-bit Linux4Tegra kernel from nVidia, which is launched with the sysmodule on boot.
- *
- * The kernel will run apps you program for it, Nintendo have the following:
- *
- * Gmix - Responsible for mixing final audio and sending it out to hardware. This is last place all
- * audio samples end up, and we skip it entirely, since we have very different backends and
- * mixing is implicitly handled by the OS (but also due to lack of research/simplicity).
- *
- * AudioRenderer - Receives command lists generated by the audio render
- * system, processes them, and sends the samples to Gmix.
- *
- * OpusDecoder - Contains libopus, and controls processing Opus audio and sends it to Gmix.
- * Not much research done here, TODO if needed.
- *
- * We only implement the AudioRenderer for now.
- *
- * Communication for the apps is done through mailboxes, and some shared memory.
- */
-class ADSP {
-public:
- explicit ADSP(Core::System& system, Sink::Sink& sink);
- ~ADSP();
-
- /**
- * Start the ADSP.
- *
- * @return True if started or already running, otherwise false.
- */
- bool Start();
-
- /**
- * Stop the ADSP.
- */
- void Stop();
-
- /**
- * Get the ADSP's state.
- *
- * @return Started or Stopped.
- */
- State GetState() const;
-
- /**
- * Get the AudioRenderer mailbox to communicate with it.
- *
- * @return The AudioRenderer mailbox.
- */
- AudioRenderer_Mailbox* GetRenderMailbox();
-
- /**
- * Get the tick the ADSP was signalled.
- *
- * @return The tick the ADSP was signalled.
- */
- u64 GetSignalledTick() const;
-
- /**
- * Get the total time it took for the ADSP to run the last command lists (both command lists).
- *
- * @return The tick the ADSP was signalled.
- */
- u64 GetTimeTaken() const;
-
- /**
- * Get the last time a given command list took to run.
- *
- * @param session_id - The session id to check (0 or 1).
- * @return The time it took.
- */
- u64 GetRenderTimeTaken(u32 session_id);
-
- /**
- * Clear the remaining command count for a given session.
- *
- * @param session_id - The session id to check (0 or 1).
- */
- void ClearRemainCount(u32 session_id);
-
- /**
- * Get the remaining number of commands left to process for a command list.
- *
- * @param session_id - The session id to check (0 or 1).
- * @return The number of commands remaining.
- */
- u32 GetRemainCommandCount(u32 session_id) const;
-
- /**
- * Get the last tick a command list started processing.
- *
- * @param session_id - The session id to check (0 or 1).
- * @return The last tick the given command list started.
- */
- u64 GetRenderingStartTick(u32 session_id);
-
- /**
- * Set a command buffer to be processed.
- *
- * @param session_id - The session id to check (0 or 1).
- * @param command_buffer - The command buffer to process.
- */
- void SendCommandBuffer(u32 session_id, const CommandBuffer& command_buffer);
-
- /**
- * Clear the command buffers (does not clear the time taken or the remaining command count)
- */
- void ClearCommandBuffers();
-
- /**
- * Signal the AudioRenderer to begin processing.
- */
- void Signal();
-
- /**
- * Wait for the AudioRenderer to finish processing.
- */
- void Wait();
-
-private:
- /// Core system
- Core::System& system;
- /// Core memory
- Core::Memory::Memory& memory;
- /// Number of systems active, used to prevent accidental shutdowns
- u8 systems_active{0};
- /// ADSP running state
- std::atomic<bool> running{false};
- /// Output sink used by the ADSP
- Sink::Sink& sink;
- /// AudioRenderer app
- std::unique_ptr<AudioRenderer> audio_renderer{};
- /// Communication for the AudioRenderer
- AudioRenderer_Mailbox render_mailbox{};
- /// Mailbox lock ffor the render mailbox
- std::mutex mailbox_lock;
-};
-
-} // namespace AudioRenderer::ADSP
-} // namespace AudioCore
diff --git a/src/audio_core/renderer/adsp/audio_renderer.cpp b/src/audio_core/renderer/adsp/audio_renderer.cpp
deleted file mode 100644
index 9ca716b60..000000000
--- a/src/audio_core/renderer/adsp/audio_renderer.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <array>
-#include <chrono>
-
-#include "audio_core/audio_core.h"
-#include "audio_core/common/common.h"
-#include "audio_core/renderer/adsp/audio_renderer.h"
-#include "audio_core/sink/sink.h"
-#include "common/logging/log.h"
-#include "common/microprofile.h"
-#include "common/thread.h"
-#include "core/core.h"
-#include "core/core_timing.h"
-
-MICROPROFILE_DEFINE(Audio_Renderer, "Audio", "DSP", MP_RGB(60, 19, 97));
-
-namespace AudioCore::AudioRenderer::ADSP {
-
-void AudioRenderer_Mailbox::HostSendMessage(RenderMessage message_) {
- adsp_messages.enqueue(message_);
- adsp_event.Set();
-}
-
-RenderMessage AudioRenderer_Mailbox::HostWaitMessage() {
- host_event.Wait();
- RenderMessage msg{RenderMessage::Invalid};
- if (!host_messages.try_dequeue(msg)) {
- LOG_ERROR(Service_Audio, "Failed to dequeue host message!");
- }
- return msg;
-}
-
-void AudioRenderer_Mailbox::ADSPSendMessage(const RenderMessage message_) {
- host_messages.enqueue(message_);
- host_event.Set();
-}
-
-RenderMessage AudioRenderer_Mailbox::ADSPWaitMessage() {
- adsp_event.Wait();
- RenderMessage msg{RenderMessage::Invalid};
- if (!adsp_messages.try_dequeue(msg)) {
- LOG_ERROR(Service_Audio, "Failed to dequeue ADSP message!");
- }
- return msg;
-}
-
-CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const u32 session_id) {
- return command_buffers[session_id];
-}
-
-void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, const CommandBuffer& buffer) {
- command_buffers[session_id] = buffer;
-}
-
-u64 AudioRenderer_Mailbox::GetRenderTimeTaken() const {
- return command_buffers[0].render_time_taken + command_buffers[1].render_time_taken;
-}
-
-u64 AudioRenderer_Mailbox::GetSignalledTick() const {
- return signalled_tick;
-}
-
-void AudioRenderer_Mailbox::SetSignalledTick(const u64 tick) {
- signalled_tick = tick;
-}
-
-void AudioRenderer_Mailbox::ClearRemainCount(const u32 session_id) {
- command_buffers[session_id].remaining_command_count = 0;
-}
-
-u32 AudioRenderer_Mailbox::GetRemainCommandCount(const u32 session_id) const {
- return command_buffers[session_id].remaining_command_count;
-}
-
-void AudioRenderer_Mailbox::ClearCommandBuffers() {
- command_buffers[0].buffer = 0;
- command_buffers[0].size = 0;
- command_buffers[0].reset_buffers = false;
- command_buffers[1].buffer = 0;
- command_buffers[1].size = 0;
- command_buffers[1].reset_buffers = false;
-}
-
-AudioRenderer::AudioRenderer(Core::System& system_)
- : system{system_}, sink{system.AudioCore().GetOutputSink()} {
- CreateSinkStreams();
-}
-
-AudioRenderer::~AudioRenderer() {
- Stop();
- for (auto& stream : streams) {
- if (stream) {
- sink.CloseStream(stream);
- }
- stream = nullptr;
- }
-}
-
-void AudioRenderer::Start(AudioRenderer_Mailbox* mailbox_) {
- if (running) {
- return;
- }
-
- mailbox = mailbox_;
- thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(stop_token); });
- running = true;
-}
-
-void AudioRenderer::Stop() {
- if (!running) {
- return;
- }
-
- for (auto& stream : streams) {
- stream->Stop();
- }
- thread.join();
- running = false;
-}
-
-void AudioRenderer::CreateSinkStreams() {
- u32 channels{sink.GetDeviceChannels()};
- for (u32 i = 0; i < MaxRendererSessions; i++) {
- std::string name{fmt::format("ADSP_RenderStream-{}", i)};
- streams[i] =
- sink.AcquireSinkStream(system, channels, name, ::AudioCore::Sink::StreamType::Render);
- streams[i]->SetRingSize(4);
- }
-}
-
-void AudioRenderer::ThreadFunc(std::stop_token stop_token) {
- static constexpr char name[]{"AudioRenderer"};
- MicroProfileOnThreadCreate(name);
- Common::SetCurrentThreadName(name);
- Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
- if (mailbox->ADSPWaitMessage() != RenderMessage::AudioRenderer_InitializeOK) {
- LOG_ERROR(Service_Audio,
- "ADSP Audio Renderer -- Failed to receive initialize message from host!");
- return;
- }
-
- mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_InitializeOK);
-
- // 0.12 seconds (2304000 / 19200000)
- constexpr u64 max_process_time{2'304'000ULL};
-
- while (!stop_token.stop_requested()) {
- auto message{mailbox->ADSPWaitMessage()};
- switch (message) {
- case RenderMessage::AudioRenderer_Shutdown:
- mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_Shutdown);
- return;
-
- case RenderMessage::AudioRenderer_Render: {
- if (system.IsShuttingDown()) [[unlikely]] {
- std::this_thread::sleep_for(std::chrono::milliseconds(5));
- mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_RenderResponse);
- continue;
- }
- std::array<bool, MaxRendererSessions> buffers_reset{};
- std::array<u64, MaxRendererSessions> render_times_taken{};
- const auto start_time{system.CoreTiming().GetClockTicks()};
-
- for (u32 index = 0; index < 2; index++) {
- auto& command_buffer{mailbox->GetCommandBuffer(index)};
- auto& command_list_processor{command_list_processors[index]};
-
- // Check this buffer is valid, as it may not be used.
- if (command_buffer.buffer != 0) {
- // If there are no remaining commands (from the previous list),
- // this is a new command list, initialize it.
- if (command_buffer.remaining_command_count == 0) {
- command_list_processor.Initialize(system, command_buffer.buffer,
- command_buffer.size, streams[index]);
- }
-
- if (command_buffer.reset_buffers && !buffers_reset[index]) {
- streams[index]->ClearQueue();
- buffers_reset[index] = true;
- }
-
- u64 max_time{max_process_time};
- if (index == 1 && command_buffer.applet_resource_user_id ==
- mailbox->GetCommandBuffer(0).applet_resource_user_id) {
- max_time = max_process_time - render_times_taken[0];
- if (render_times_taken[0] > max_process_time) {
- max_time = 0;
- }
- }
-
- max_time = std::min(command_buffer.time_limit, max_time);
- command_list_processor.SetProcessTimeMax(max_time);
-
- streams[index]->WaitFreeSpace(stop_token);
-
- // Process the command list
- {
- MICROPROFILE_SCOPE(Audio_Renderer);
- render_times_taken[index] =
- command_list_processor.Process(index) - start_time;
- }
-
- const auto end_time{system.CoreTiming().GetClockTicks()};
-
- command_buffer.remaining_command_count =
- command_list_processor.GetRemainingCommandCount();
- command_buffer.render_time_taken = end_time - start_time;
- }
- }
-
- mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_RenderResponse);
- } break;
-
- default:
- LOG_WARNING(Service_Audio,
- "ADSP AudioRenderer received an invalid message, msg={:02X}!",
- static_cast<u32>(message));
- break;
- }
- }
-}
-
-} // namespace AudioCore::AudioRenderer::ADSP
diff --git a/src/audio_core/renderer/adsp/audio_renderer.h b/src/audio_core/renderer/adsp/audio_renderer.h
deleted file mode 100644
index 88e558183..000000000
--- a/src/audio_core/renderer/adsp/audio_renderer.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <array>
-#include <memory>
-#include <thread>
-
-#include "audio_core/renderer/adsp/command_buffer.h"
-#include "audio_core/renderer/adsp/command_list_processor.h"
-#include "common/common_types.h"
-#include "common/polyfill_thread.h"
-#include "common/reader_writer_queue.h"
-#include "common/thread.h"
-
-namespace Core {
-namespace Timing {
-struct EventType;
-}
-class System;
-} // namespace Core
-
-namespace AudioCore {
-namespace Sink {
-class Sink;
-}
-
-namespace AudioRenderer::ADSP {
-
-enum class RenderMessage {
- /* 0x00 */ Invalid,
- /* 0x01 */ AudioRenderer_MapUnmap_Map,
- /* 0x02 */ AudioRenderer_MapUnmap_MapResponse,
- /* 0x03 */ AudioRenderer_MapUnmap_Unmap,
- /* 0x04 */ AudioRenderer_MapUnmap_UnmapResponse,
- /* 0x05 */ AudioRenderer_MapUnmap_InvalidateCache,
- /* 0x06 */ AudioRenderer_MapUnmap_InvalidateCacheResponse,
- /* 0x07 */ AudioRenderer_MapUnmap_Shutdown,
- /* 0x08 */ AudioRenderer_MapUnmap_ShutdownResponse,
- /* 0x16 */ AudioRenderer_InitializeOK = 0x16,
- /* 0x20 */ AudioRenderer_RenderResponse = 0x20,
- /* 0x2A */ AudioRenderer_Render = 0x2A,
- /* 0x34 */ AudioRenderer_Shutdown = 0x34,
-};
-
-/**
- * A mailbox for the AudioRenderer, allowing communication between the host and the AudioRenderer
- * running on the ADSP.
- */
-class AudioRenderer_Mailbox {
-public:
- /**
- * Send a message from the host to the AudioRenderer.
- *
- * @param message - The message to send to the AudioRenderer.
- */
- void HostSendMessage(RenderMessage message);
-
- /**
- * Host wait for a message from the AudioRenderer.
- *
- * @return The message returned from the AudioRenderer.
- */
- RenderMessage HostWaitMessage();
-
- /**
- * Send a message from the AudioRenderer to the host.
- *
- * @param message - The message to send to the host.
- */
- void ADSPSendMessage(RenderMessage message);
-
- /**
- * AudioRenderer wait for a message from the host.
- *
- * @return The message returned from the AudioRenderer.
- */
- RenderMessage ADSPWaitMessage();
-
- /**
- * Get the command buffer with the given session id (0 or 1).
- *
- * @param session_id - The session id to get (0 or 1).
- * @return The command buffer.
- */
- CommandBuffer& GetCommandBuffer(u32 session_id);
-
- /**
- * Set the command buffer with the given session id (0 or 1).
- *
- * @param session_id - The session id to get (0 or 1).
- * @param buffer - The command buffer to set.
- */
- void SetCommandBuffer(u32 session_id, const CommandBuffer& buffer);
-
- /**
- * Get the total render time taken for the last command lists sent.
- *
- * @return Total render time taken for the last command lists.
- */
- u64 GetRenderTimeTaken() const;
-
- /**
- * Get the tick the AudioRenderer was signalled.
- *
- * @return The tick the AudioRenderer was signalled.
- */
- u64 GetSignalledTick() const;
-
- /**
- * Set the tick the AudioRenderer was signalled.
- *
- * @param tick - The tick the AudioRenderer was signalled.
- */
- void SetSignalledTick(u64 tick);
-
- /**
- * Clear the remaining command count.
- *
- * @param session_id - Index for which command list to clear (0 or 1).
- */
- void ClearRemainCount(u32 session_id);
-
- /**
- * Get the remaining command count for a given command list.
- *
- * @param session_id - Index for which command list to clear (0 or 1).
- * @return The remaining command count.
- */
- u32 GetRemainCommandCount(u32 session_id) const;
-
- /**
- * Clear the command buffers (does not clear the time taken or the remaining command count).
- */
- void ClearCommandBuffers();
-
-private:
- /// Host signalling event
- Common::Event host_event{};
- /// AudioRenderer signalling event
- Common::Event adsp_event{};
- /// Host message queue
-
- Common::ReaderWriterQueue<RenderMessage> host_messages{};
- /// AudioRenderer message queue
-
- Common::ReaderWriterQueue<RenderMessage> adsp_messages{};
- /// Command buffers
-
- std::array<CommandBuffer, MaxRendererSessions> command_buffers{};
- /// Tick the AudioRnederer was signalled
- u64 signalled_tick{};
-};
-
-/**
- * The AudioRenderer application running on the ADSP.
- */
-class AudioRenderer {
-public:
- explicit AudioRenderer(Core::System& system);
- ~AudioRenderer();
-
- /**
- * Start the AudioRenderer.
- *
- * @param mailbox The mailbox to use for this session.
- */
- void Start(AudioRenderer_Mailbox* mailbox);
-
- /**
- * Stop the AudioRenderer.
- */
- void Stop();
-
-private:
- /**
- * Main AudioRenderer thread, responsible for processing the command lists.
- */
- void ThreadFunc(std::stop_token stop_token);
-
- /**
- * Creates the streams which will receive the processed samples.
- */
- void CreateSinkStreams();
-
- /// Core system
- Core::System& system;
- /// Main thread
- std::jthread thread{};
- /// The current state
- std::atomic<bool> running{};
- /// The active mailbox
- AudioRenderer_Mailbox* mailbox{};
- /// The command lists to process
- std::array<CommandListProcessor, MaxRendererSessions> command_list_processors{};
- /// The output sink the AudioRenderer will use
- Sink::Sink& sink;
- /// The streams which will receive the processed samples
- std::array<Sink::SinkStream*, MaxRendererSessions> streams;
-};
-
-} // namespace AudioRenderer::ADSP
-} // namespace AudioCore
diff --git a/src/audio_core/renderer/adsp/command_buffer.h b/src/audio_core/renderer/adsp/command_buffer.h
deleted file mode 100644
index 880b279d8..000000000
--- a/src/audio_core/renderer/adsp/command_buffer.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "audio_core/common/common.h"
-#include "common/common_types.h"
-
-namespace AudioCore::AudioRenderer::ADSP {
-
-struct CommandBuffer {
- CpuAddr buffer;
- u64 size;
- u64 time_limit;
- u32 remaining_command_count;
- bool reset_buffers;
- u64 applet_resource_user_id;
- u64 render_time_taken;
-};
-
-} // namespace AudioCore::AudioRenderer::ADSP
diff --git a/src/audio_core/renderer/audio_device.cpp b/src/audio_core/renderer/audio_device.cpp
index 0d9d8f6ce..2d9bf82bb 100644
--- a/src/audio_core/renderer/audio_device.cpp
+++ b/src/audio_core/renderer/audio_device.cpp
@@ -10,7 +10,7 @@
#include "audio_core/sink/sink.h"
#include "core/core.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
constexpr std::array usb_device_names{
AudioDevice::AudioDeviceName{"AudioStereoJackOutput"},
@@ -71,4 +71,4 @@ f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) const {
return output_sink.GetDeviceVolume();
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/audio_device.h b/src/audio_core/renderer/audio_device.h
index dd6be70ee..ca4040add 100644
--- a/src/audio_core/renderer/audio_device.h
+++ b/src/audio_core/renderer/audio_device.h
@@ -16,7 +16,7 @@ namespace Sink {
class Sink;
}
-namespace AudioRenderer {
+namespace Renderer {
/**
* An interface to an output audio device available to the Switch.
*/
@@ -76,5 +76,5 @@ private:
const u32 user_revision;
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/renderer/audio_renderer.cpp b/src/audio_core/renderer/audio_renderer.cpp
index a8257eb2e..09efe9be9 100644
--- a/src/audio_core/renderer/audio_renderer.cpp
+++ b/src/audio_core/renderer/audio_renderer.cpp
@@ -9,7 +9,7 @@
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/errors.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event)
: core{system_}, manager{manager_}, system{system_, rendered_event} {}
@@ -64,4 +64,4 @@ Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performa
return system.Update(input, performance, output);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/audio_renderer.h b/src/audio_core/renderer/audio_renderer.h
index 90c6f9727..24650278b 100644
--- a/src/audio_core/renderer/audio_renderer.h
+++ b/src/audio_core/renderer/audio_renderer.h
@@ -19,7 +19,7 @@ class KTransferMemory;
namespace AudioCore {
struct AudioRendererParameterInternal;
-namespace AudioRenderer {
+namespace Renderer {
class Manager;
/**
@@ -31,7 +31,7 @@ public:
/**
* Initialize the renderer.
- * Registers the system with the AudioRenderer::Manager, allocates workbuffers and initializes
+ * Registers the system with the Renderer::Manager, allocates workbuffers and initializes
* everything to a default state.
*
* @param params - Input parameters to initialize the system with.
@@ -93,5 +93,5 @@ private:
System system;
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/renderer/behavior/behavior_info.cpp b/src/audio_core/renderer/behavior/behavior_info.cpp
index 3d2a91312..058539042 100644
--- a/src/audio_core/renderer/behavior/behavior_info.cpp
+++ b/src/audio_core/renderer/behavior/behavior_info.cpp
@@ -4,7 +4,7 @@
#include "audio_core/common/feature_support.h"
#include "audio_core/renderer/behavior/behavior_info.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
BehaviorInfo::BehaviorInfo() : process_revision{CurrentRevision} {}
@@ -190,4 +190,4 @@ bool BehaviorInfo::IsI3dl2ReverbChannelMappingChanged() const {
return CheckFeatureSupported(SupportTags::I3dl2ReverbChannelMappingChange, user_revision);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/behavior/behavior_info.h b/src/audio_core/renderer/behavior/behavior_info.h
index b52340229..a4958857a 100644
--- a/src/audio_core/renderer/behavior/behavior_info.h
+++ b/src/audio_core/renderer/behavior/behavior_info.h
@@ -10,7 +10,7 @@
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Holds host and user revisions, checks whether render features can be enabled, and reports errors.
*/
@@ -264,7 +264,7 @@ public:
/**
* Check if skipping voice pitch and sample rate conversion is supported.
* This speeds up the data source commands by skipping resampling if unwanted.
- * See AudioCore::AudioRenderer::DecodeFromWaveBuffers
+ * See AudioCore::Renderer::DecodeFromWaveBuffers
*
* @return True if supported, otherwise false.
*/
@@ -273,7 +273,7 @@ public:
/**
* Check if resetting played sample count at loop points is supported.
* This resets the number of samples played in a voice state when a loop point is reached.
- * See AudioCore::AudioRenderer::DecodeFromWaveBuffers
+ * See AudioCore::Renderer::DecodeFromWaveBuffers
*
* @return True if supported, otherwise false.
*/
@@ -373,4 +373,4 @@ public:
u32 error_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp
index e312eb166..667711e17 100644
--- a/src/audio_core/renderer/behavior/info_updater.cpp
+++ b/src/audio_core/renderer/behavior/info_updater.cpp
@@ -15,7 +15,7 @@
#include "audio_core/renderer/splitter/splitter_context.h"
#include "audio_core/renderer/voice/voice_context.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
const u32 process_handle_, BehaviorInfo& behaviour_)
@@ -536,4 +536,4 @@ Result InfoUpdater::CheckConsumedSize() {
return ResultSuccess;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/behavior/info_updater.h b/src/audio_core/renderer/behavior/info_updater.h
index c817d8d8d..fb4b7d25a 100644
--- a/src/audio_core/renderer/behavior/info_updater.h
+++ b/src/audio_core/renderer/behavior/info_updater.h
@@ -8,7 +8,7 @@
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class BehaviorInfo;
class VoiceContext;
class MixContext;
@@ -202,4 +202,4 @@ private:
BehaviorInfo& behaviour;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_buffer.cpp b/src/audio_core/renderer/command/command_buffer.cpp
index 0bd418306..67d43e69a 100644
--- a/src/audio_core/renderer/command/command_buffer.cpp
+++ b/src/audio_core/renderer/command/command_buffer.cpp
@@ -16,7 +16,7 @@
#include "audio_core/renderer/voice/voice_info.h"
#include "audio_core/renderer/voice/voice_state.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
template <typename T, CommandId Id>
T& CommandBuffer::GenerateStart(const s32 node_id) {
@@ -713,4 +713,4 @@ void CommandBuffer::GenerateCompressorCommand(s16 buffer_offset, EffectInfoBase&
GenerateEnd<CompressorCommand>(cmd);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_buffer.h b/src/audio_core/renderer/command/command_buffer.h
index 162170846..12e8c2c81 100644
--- a/src/audio_core/renderer/command/command_buffer.h
+++ b/src/audio_core/renderer/command/command_buffer.h
@@ -10,7 +10,7 @@
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct UpsamplerInfo;
struct VoiceState;
class EffectInfoBase;
@@ -465,4 +465,4 @@ private:
void GenerateEnd(T& cmd);
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp
index fba84c7bd..ccb186209 100644
--- a/src/audio_core/renderer/command/command_generator.cpp
+++ b/src/audio_core/renderer/command/command_generator.cpp
@@ -21,7 +21,7 @@
#include "audio_core/renderer/voice/voice_context.h"
#include "common/alignment.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
CommandGenerator::CommandGenerator(CommandBuffer& command_buffer_,
const CommandListHeader& command_list_header_,
@@ -793,4 +793,4 @@ void CommandGenerator::GeneratePerformanceCommand(
command_buffer.GeneratePerformanceCommand(node_id, state, entry_addresses);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_generator.h b/src/audio_core/renderer/command/command_generator.h
index b3cd7b408..38ee2a64e 100644
--- a/src/audio_core/renderer/command/command_generator.h
+++ b/src/audio_core/renderer/command/command_generator.h
@@ -12,7 +12,7 @@
namespace AudioCore {
struct AudioRendererSystemContext;
-namespace AudioRenderer {
+namespace Renderer {
class CommandBuffer;
struct CommandListHeader;
class VoiceContext;
@@ -345,5 +345,5 @@ private:
PerformanceManager* performance_manager;
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/renderer/command/command_list_header.h b/src/audio_core/renderer/command/command_list_header.h
index 988530b1f..de9ee070b 100644
--- a/src/audio_core/renderer/command/command_list_header.h
+++ b/src/audio_core/renderer/command/command_list_header.h
@@ -8,7 +8,7 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct CommandListHeader {
u64 buffer_size;
@@ -19,4 +19,4 @@ struct CommandListHeader {
u32 sample_rate;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_processing_time_estimator.cpp b/src/audio_core/renderer/command/command_processing_time_estimator.cpp
index 3091f587a..a48a016b1 100644
--- a/src/audio_core/renderer/command/command_processing_time_estimator.cpp
+++ b/src/audio_core/renderer/command/command_processing_time_estimator.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/command/command_processing_time_estimator.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
u32 CommandProcessingTimeEstimatorVersion1::Estimate(
const PcmInt16DataSourceVersion1Command& command) const {
@@ -3617,4 +3617,4 @@ u32 CommandProcessingTimeEstimatorVersion5::Estimate(const CompressorCommand& co
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/command_processing_time_estimator.h b/src/audio_core/renderer/command/command_processing_time_estimator.h
index 452217196..1c76e4ba4 100644
--- a/src/audio_core/renderer/command/command_processing_time_estimator.h
+++ b/src/audio_core/renderer/command/command_processing_time_estimator.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/command/commands.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Estimate the processing time required for all commands.
*/
@@ -251,4 +251,4 @@ private:
u32 buffer_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/adpcm.cpp b/src/audio_core/renderer/command/data_source/adpcm.cpp
index e66ed2990..e7f82d3b3 100644
--- a/src/audio_core/renderer/command/data_source/adpcm.cpp
+++ b/src/audio_core/renderer/command/data_source/adpcm.cpp
@@ -3,23 +3,29 @@
#include <span>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/data_source/adpcm.h"
#include "audio_core/renderer/command/data_source/decode.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void AdpcmDataSourceVersion1Command::Dump(const ADSP::CommandListProcessor& processor,
+void AdpcmDataSourceVersion1Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("AdpcmDataSourceVersion1Command\n\toutput_index {:02X} source sample "
"rate {} target sample rate {} src quality {}\n",
output_index, sample_rate, processor.target_sample_rate, src_quality);
}
-void AdpcmDataSourceVersion1Command::Process(const ADSP::CommandListProcessor& processor) {
+void AdpcmDataSourceVersion1Command::Process(const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
+ for (auto& wave_buffer : wave_buffers) {
+ wave_buffer.loop_start_offset = wave_buffer.start_offset;
+ wave_buffer.loop_end_offset = wave_buffer.end_offset;
+ wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
+ }
+
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::Adpcm},
.output{out_buffer},
@@ -41,18 +47,18 @@ void AdpcmDataSourceVersion1Command::Process(const ADSP::CommandListProcessor& p
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool AdpcmDataSourceVersion1Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool AdpcmDataSourceVersion1Command::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-void AdpcmDataSourceVersion2Command::Dump(const ADSP::CommandListProcessor& processor,
+void AdpcmDataSourceVersion2Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("AdpcmDataSourceVersion2Command\n\toutput_index {:02X} source sample "
"rate {} target sample rate {} src quality {}\n",
output_index, sample_rate, processor.target_sample_rate, src_quality);
}
-void AdpcmDataSourceVersion2Command::Process(const ADSP::CommandListProcessor& processor) {
+void AdpcmDataSourceVersion2Command::Process(const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
@@ -77,8 +83,8 @@ void AdpcmDataSourceVersion2Command::Process(const ADSP::CommandListProcessor& p
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool AdpcmDataSourceVersion2Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool AdpcmDataSourceVersion2Command::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/adpcm.h b/src/audio_core/renderer/command/data_source/adpcm.h
index a9cf9cee4..487846f0c 100644
--- a/src/audio_core/renderer/command/data_source/adpcm.h
+++ b/src/audio_core/renderer/command/data_source/adpcm.h
@@ -11,11 +11,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command to decode ADPCM-encoded version 1 wavebuffers
* into the output_index mix buffer.
@@ -27,14 +28,14 @@ struct AdpcmDataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -42,13 +43,13 @@ struct AdpcmDataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -75,14 +76,14 @@ struct AdpcmDataSourceVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -90,13 +91,13 @@ struct AdpcmDataSourceVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -116,4 +117,4 @@ struct AdpcmDataSourceVersion2Command : ICommand {
u64 data_size;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp
index 257aa866e..911dae3c1 100644
--- a/src/audio_core/renderer/command/data_source/decode.cpp
+++ b/src/audio_core/renderer/command/data_source/decode.cpp
@@ -11,7 +11,7 @@
#include "common/scratch_buffer.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
constexpr u32 TempBufferSize = 0x3F00;
constexpr std::array<u8, 3> PitchBySrcQuality = {4, 8, 4};
@@ -123,11 +123,13 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
return 0;
}
- auto samples_to_process{
- std::min(req.end_offset - req.start_offset - req.offset, req.samples_to_read)};
+ auto start_pos{req.start_offset + req.offset};
+ auto samples_to_process{std::min(req.end_offset - start_pos, req.samples_to_read)};
+ if (samples_to_process == 0) {
+ return 0;
+ }
auto samples_to_read{samples_to_process};
- auto start_pos{req.start_offset + req.offset};
auto samples_remaining_in_frame{start_pos % SamplesPerFrame};
auto position_in_frame{(start_pos / SamplesPerFrame) * NibblesPerFrame +
samples_remaining_in_frame};
@@ -225,13 +227,24 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
* @param args - The wavebuffer data, and information for how to decode it.
*/
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) {
+ static constexpr auto EndWaveBuffer = [](auto& voice_state, auto& wavebuffer, auto& index,
+ auto& played_samples, auto& consumed) -> void {
+ voice_state.wave_buffer_valid[index] = false;
+ voice_state.loop_count = 0;
+
+ if (wavebuffer.stream_ended) {
+ played_samples = 0;
+ }
+
+ index = (index + 1) % MaxWaveBuffers;
+ consumed++;
+ };
auto& voice_state{*args.voice_state};
auto remaining_sample_count{args.sample_count};
auto fraction{voice_state.fraction};
- const auto sample_rate_ratio{
- (Common::FixedPoint<49, 15>(args.source_sample_rate) / args.target_sample_rate) *
- args.pitch};
+ const auto sample_rate_ratio{Common::FixedPoint<49, 15>(
+ (f32)args.source_sample_rate / (f32)args.target_sample_rate * (f32)args.pitch)};
const auto size_required{fraction + remaining_sample_count * sample_rate_ratio};
if (size_required < 0) {
@@ -298,22 +311,23 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
auto end_offset{wavebuffer.end_offset};
if (wavebuffer.loop && voice_state.loop_count > 0 &&
- wavebuffer.loop_start_offset != 0 && wavebuffer.loop_end_offset != 0 &&
wavebuffer.loop_start_offset <= wavebuffer.loop_end_offset) {
start_offset = wavebuffer.loop_start_offset;
end_offset = wavebuffer.loop_end_offset;
}
- DecodeArg decode_arg{.buffer{wavebuffer.buffer},
- .buffer_size{wavebuffer.buffer_size},
- .start_offset{start_offset},
- .end_offset{end_offset},
- .channel_count{args.channel_count},
- .coefficients{},
- .adpcm_context{nullptr},
- .target_channel{args.channel},
- .offset{offset},
- .samples_to_read{samples_to_read - samples_read}};
+ DecodeArg decode_arg{
+ .buffer{wavebuffer.buffer},
+ .buffer_size{wavebuffer.buffer_size},
+ .start_offset{start_offset},
+ .end_offset{end_offset},
+ .channel_count{args.channel_count},
+ .coefficients{},
+ .adpcm_context{nullptr},
+ .target_channel{args.channel},
+ .offset{offset},
+ .samples_to_read{samples_to_read - samples_read},
+ };
s32 samples_decoded{0};
@@ -350,42 +364,30 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
temp_buffer_pos += samples_decoded;
offset += samples_decoded;
- if (samples_decoded == 0 || offset >= end_offset - start_offset) {
- offset = 0;
- if (!wavebuffer.loop) {
- voice_state.wave_buffer_valid[wavebuffer_index] = false;
- voice_state.loop_count = 0;
-
- if (wavebuffer.stream_ended) {
- played_sample_count = 0;
- }
-
- wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
- wavebuffers_consumed++;
- } else {
- voice_state.loop_count++;
- if (wavebuffer.loop_count > 0 &&
- (voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
- voice_state.wave_buffer_valid[wavebuffer_index] = false;
- voice_state.loop_count = 0;
-
- if (wavebuffer.stream_ended) {
- played_sample_count = 0;
- }
-
- wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
- wavebuffers_consumed++;
- }
-
- if (samples_decoded == 0) {
- is_buffer_starved = true;
- break;
- }
-
- if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
- played_sample_count = 0;
- }
+ if (samples_decoded && offset < end_offset - start_offset) {
+ continue;
+ }
+
+ offset = 0;
+ if (wavebuffer.loop) {
+ voice_state.loop_count++;
+ if (wavebuffer.loop_count >= 0 &&
+ (voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
+ EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
+ wavebuffers_consumed);
+ }
+
+ if (samples_decoded == 0) {
+ is_buffer_starved = true;
+ break;
+ }
+
+ if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
+ played_sample_count = 0;
}
+ } else {
+ EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
+ wavebuffers_consumed);
}
}
@@ -423,4 +425,4 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
voice_state.fraction = fraction;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/decode.h b/src/audio_core/renderer/command/data_source/decode.h
index 4d63d6fa8..5f52f32f0 100644
--- a/src/audio_core/renderer/command/data_source/decode.h
+++ b/src/audio_core/renderer/command/data_source/decode.h
@@ -15,7 +15,7 @@ namespace Core::Memory {
class Memory;
}
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct DecodeFromWaveBuffersArgs {
SampleFormat sample_format;
@@ -56,4 +56,4 @@ struct DecodeArg {
*/
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args);
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/pcm_float.cpp b/src/audio_core/renderer/command/data_source/pcm_float.cpp
index be77fab69..d1f685656 100644
--- a/src/audio_core/renderer/command/data_source/pcm_float.cpp
+++ b/src/audio_core/renderer/command/data_source/pcm_float.cpp
@@ -1,13 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/data_source/decode.h"
#include "audio_core/renderer/command/data_source/pcm_float.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void PcmFloatDataSourceVersion1Command::Dump(const ADSP::CommandListProcessor& processor,
+void PcmFloatDataSourceVersion1Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string +=
fmt::format("PcmFloatDataSourceVersion1Command\n\toutput_index {:02X} channel {} "
@@ -16,10 +16,17 @@ void PcmFloatDataSourceVersion1Command::Dump(const ADSP::CommandListProcessor& p
processor.target_sample_rate, src_quality);
}
-void PcmFloatDataSourceVersion1Command::Process(const ADSP::CommandListProcessor& processor) {
+void PcmFloatDataSourceVersion1Command::Process(
+ const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
+ for (auto& wave_buffer : wave_buffers) {
+ wave_buffer.loop_start_offset = wave_buffer.start_offset;
+ wave_buffer.loop_end_offset = wave_buffer.end_offset;
+ wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
+ }
+
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::PcmFloat},
.output{out_buffer},
@@ -41,11 +48,12 @@ void PcmFloatDataSourceVersion1Command::Process(const ADSP::CommandListProcessor
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool PcmFloatDataSourceVersion1Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool PcmFloatDataSourceVersion1Command::Verify(
+ const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-void PcmFloatDataSourceVersion2Command::Dump(const ADSP::CommandListProcessor& processor,
+void PcmFloatDataSourceVersion2Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string +=
fmt::format("PcmFloatDataSourceVersion2Command\n\toutput_index {:02X} channel {} "
@@ -54,7 +62,8 @@ void PcmFloatDataSourceVersion2Command::Dump(const ADSP::CommandListProcessor& p
processor.target_sample_rate, src_quality);
}
-void PcmFloatDataSourceVersion2Command::Process(const ADSP::CommandListProcessor& processor) {
+void PcmFloatDataSourceVersion2Command::Process(
+ const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
@@ -79,8 +88,9 @@ void PcmFloatDataSourceVersion2Command::Process(const ADSP::CommandListProcessor
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool PcmFloatDataSourceVersion2Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool PcmFloatDataSourceVersion2Command::Verify(
+ const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/pcm_float.h b/src/audio_core/renderer/command/data_source/pcm_float.h
index e4af77c20..2c9d1877e 100644
--- a/src/audio_core/renderer/command/data_source/pcm_float.h
+++ b/src/audio_core/renderer/command/data_source/pcm_float.h
@@ -9,11 +9,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command to decode PCM float-encoded version 1 wavebuffers
* into the output_index mix buffer.
@@ -25,14 +26,14 @@ struct PcmFloatDataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,13 +41,13 @@ struct PcmFloatDataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -73,14 +74,14 @@ struct PcmFloatDataSourceVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -88,13 +89,13 @@ struct PcmFloatDataSourceVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -110,4 +111,4 @@ struct PcmFloatDataSourceVersion2Command : ICommand {
CpuAddr voice_state;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/pcm_int16.cpp b/src/audio_core/renderer/command/data_source/pcm_int16.cpp
index 7a27463e4..c89a5aaac 100644
--- a/src/audio_core/renderer/command/data_source/pcm_int16.cpp
+++ b/src/audio_core/renderer/command/data_source/pcm_int16.cpp
@@ -3,13 +3,13 @@
#include <span>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/data_source/decode.h"
#include "audio_core/renderer/command/data_source/pcm_int16.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void PcmInt16DataSourceVersion1Command::Dump(const ADSP::CommandListProcessor& processor,
+void PcmInt16DataSourceVersion1Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string +=
fmt::format("PcmInt16DataSourceVersion1Command\n\toutput_index {:02X} channel {} "
@@ -18,10 +18,17 @@ void PcmInt16DataSourceVersion1Command::Dump(const ADSP::CommandListProcessor& p
processor.target_sample_rate, src_quality);
}
-void PcmInt16DataSourceVersion1Command::Process(const ADSP::CommandListProcessor& processor) {
+void PcmInt16DataSourceVersion1Command::Process(
+ const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
+ for (auto& wave_buffer : wave_buffers) {
+ wave_buffer.loop_start_offset = wave_buffer.start_offset;
+ wave_buffer.loop_end_offset = wave_buffer.end_offset;
+ wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
+ }
+
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::PcmInt16},
.output{out_buffer},
@@ -43,11 +50,12 @@ void PcmInt16DataSourceVersion1Command::Process(const ADSP::CommandListProcessor
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool PcmInt16DataSourceVersion1Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool PcmInt16DataSourceVersion1Command::Verify(
+ const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-void PcmInt16DataSourceVersion2Command::Dump(const ADSP::CommandListProcessor& processor,
+void PcmInt16DataSourceVersion2Command::Dump(const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string +=
fmt::format("PcmInt16DataSourceVersion2Command\n\toutput_index {:02X} channel {} "
@@ -56,7 +64,8 @@ void PcmInt16DataSourceVersion2Command::Dump(const ADSP::CommandListProcessor& p
processor.target_sample_rate, src_quality);
}
-void PcmInt16DataSourceVersion2Command::Process(const ADSP::CommandListProcessor& processor) {
+void PcmInt16DataSourceVersion2Command::Process(
+ const AudioRenderer::CommandListProcessor& processor) {
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
DecodeFromWaveBuffersArgs args{
@@ -80,8 +89,9 @@ void PcmInt16DataSourceVersion2Command::Process(const ADSP::CommandListProcessor
DecodeFromWaveBuffers(*processor.memory, args);
}
-bool PcmInt16DataSourceVersion2Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool PcmInt16DataSourceVersion2Command::Verify(
+ const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/data_source/pcm_int16.h b/src/audio_core/renderer/command/data_source/pcm_int16.h
index 5de1ad60d..2c013f003 100644
--- a/src/audio_core/renderer/command/data_source/pcm_int16.h
+++ b/src/audio_core/renderer/command/data_source/pcm_int16.h
@@ -9,11 +9,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command to decode PCM s16-encoded version 1 wavebuffers
* into the output_index mix buffer.
@@ -25,14 +26,14 @@ struct PcmInt16DataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,13 +41,13 @@ struct PcmInt16DataSourceVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -72,26 +73,26 @@ struct PcmInt16DataSourceVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Quality used for sample rate conversion
SrcQuality src_quality;
/// Mix buffer index for decoded samples
s16 output_index;
- /// Flags to control decoding (see AudioCore::AudioRenderer::VoiceInfo::Flags)
+ /// Flags to control decoding (see AudioCore::Renderer::VoiceInfo::Flags)
u16 flags;
/// Wavebuffer sample rate
u32 sample_rate;
@@ -107,4 +108,4 @@ struct PcmInt16DataSourceVersion2Command : ICommand {
CpuAddr voice_state;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp
index a3e12b3e7..74d9c229f 100644
--- a/src/audio_core/renderer/command/effect/aux_.cpp
+++ b/src/audio_core/renderer/command/effect/aux_.cpp
@@ -1,13 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/aux_.h"
#include "audio_core/renderer/effect/aux_.h"
#include "core/core.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Reset an AuxBuffer.
*
@@ -175,13 +175,13 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
return read_count_;
}
-void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void AuxCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("AuxCommand\n\tenabled {} input {:02X} output {:02X}\n", effect_enabled,
input, output);
}
-void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
+void AuxCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto input_buffer{
processor.mix_buffers.subspan(input * processor.sample_count, processor.sample_count)};
auto output_buffer{
@@ -208,8 +208,8 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool AuxCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool AuxCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/aux_.h b/src/audio_core/renderer/command/effect/aux_.h
index 825c93732..da1e55261 100644
--- a/src/audio_core/renderer/command/effect/aux_.h
+++ b/src/audio_core/renderer/command/effect/aux_.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command to read and write an auxiliary buffer, writing the input mix buffer to game
* memory, and reading into the output buffer from game memory.
@@ -24,14 +25,14 @@ struct AuxCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct AuxCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer index
s16 input;
@@ -63,4 +64,4 @@ struct AuxCommand : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/biquad_filter.cpp b/src/audio_core/renderer/command/effect/biquad_filter.cpp
index dea6423dc..3392e7747 100644
--- a/src/audio_core/renderer/command/effect/biquad_filter.cpp
+++ b/src/audio_core/renderer/command/effect/biquad_filter.cpp
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/biquad_filter.h"
#include "audio_core/renderer/voice/voice_state.h"
#include "common/bit_cast.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Biquad filter float implementation.
*
@@ -76,14 +76,14 @@ static void ApplyBiquadFilterInt(std::span<s32> output, std::span<const s32> inp
}
}
-void BiquadFilterCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void BiquadFilterCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format(
"BiquadFilterCommand\n\tinput {:02X} output {:02X} needs_init {} use_float_processing {}\n",
input, output, needs_init, use_float_processing);
}
-void BiquadFilterCommand::Process(const ADSP::CommandListProcessor& processor) {
+void BiquadFilterCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto state_{reinterpret_cast<VoiceState::BiquadFilterState*>(state)};
if (needs_init) {
*state_ = {};
@@ -103,8 +103,8 @@ void BiquadFilterCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool BiquadFilterCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool BiquadFilterCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/biquad_filter.h b/src/audio_core/renderer/command/effect/biquad_filter.h
index 4c9c42d29..0e903930a 100644
--- a/src/audio_core/renderer/command/effect/biquad_filter.h
+++ b/src/audio_core/renderer/command/effect/biquad_filter.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/voice/voice_state.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for applying a biquad filter to the input mix buffer, saving the results to
* the output mix buffer.
@@ -26,14 +27,14 @@ struct BiquadFilterCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct BiquadFilterCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer index
s16 input;
@@ -71,4 +72,4 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
std::array<s16, 3>& b, std::array<s16, 2>& a,
VoiceState::BiquadFilterState& state, const u32 sample_count);
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/capture.cpp b/src/audio_core/renderer/command/effect/capture.cpp
index 042fd286e..f235ce027 100644
--- a/src/audio_core/renderer/command/effect/capture.cpp
+++ b/src/audio_core/renderer/command/effect/capture.cpp
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/capture.h"
#include "audio_core/renderer/effect/aux_.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Reset an AuxBuffer.
*
@@ -118,13 +118,13 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
return write_count_;
}
-void CaptureCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void CaptureCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("CaptureCommand\n\tenabled {} input {:02X} output {:02X}", effect_enabled,
input, output);
}
-void CaptureCommand::Process(const ADSP::CommandListProcessor& processor) {
+void CaptureCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
if (effect_enabled) {
auto input_buffer{
processor.mix_buffers.subspan(input * processor.sample_count, processor.sample_count)};
@@ -135,8 +135,8 @@ void CaptureCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool CaptureCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool CaptureCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/capture.h b/src/audio_core/renderer/command/effect/capture.h
index 8670acb24..a0016c6f6 100644
--- a/src/audio_core/renderer/command/effect/capture.h
+++ b/src/audio_core/renderer/command/effect/capture.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for capturing a mix buffer. That is, writing it back to a given game memory
* address.
@@ -24,14 +25,14 @@ struct CaptureCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct CaptureCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer index
s16 input;
@@ -59,4 +60,4 @@ struct CaptureCommand : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/compressor.cpp b/src/audio_core/renderer/command/effect/compressor.cpp
index ee9b68d5b..7ff707f4e 100644
--- a/src/audio_core/renderer/command/effect/compressor.cpp
+++ b/src/audio_core/renderer/command/effect/compressor.cpp
@@ -5,11 +5,11 @@
#include <span>
#include <vector>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/compressor.h"
#include "audio_core/renderer/effect/compressor.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
static void SetCompressorEffectParameter(const CompressorInfo::ParameterVersion2& params,
CompressorInfo::State& state) {
@@ -110,7 +110,7 @@ static void ApplyCompressorEffect(const CompressorInfo::ParameterVersion2& param
}
}
-void CompressorCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void CompressorCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("CompressorCommand\n\tenabled {} \n\tinputs: ", effect_enabled);
for (s16 i = 0; i < parameter.channel_count; i++) {
@@ -123,7 +123,7 @@ void CompressorCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor&
string += "\n";
}
-void CompressorCommand::Process(const ADSP::CommandListProcessor& processor) {
+void CompressorCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -148,8 +148,8 @@ void CompressorCommand::Process(const ADSP::CommandListProcessor& processor) {
processor.sample_count);
}
-bool CompressorCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool CompressorCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/compressor.h b/src/audio_core/renderer/command/effect/compressor.h
index f8e96cb43..c011aa927 100644
--- a/src/audio_core/renderer/command/effect/compressor.h
+++ b/src/audio_core/renderer/command/effect/compressor.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/effect/compressor.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for limiting volume between a high and low threshold.
* Version 1.
@@ -26,14 +27,14 @@ struct CompressorCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct CompressorCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -57,4 +58,4 @@ struct CompressorCommand : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/delay.cpp b/src/audio_core/renderer/command/effect/delay.cpp
index e536cbb1e..ffb298c07 100644
--- a/src/audio_core/renderer/command/effect/delay.cpp
+++ b/src/audio_core/renderer/command/effect/delay.cpp
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/delay.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Update the DelayInfo state according to the given parameters.
*
@@ -194,7 +194,7 @@ static void ApplyDelayEffect(const DelayInfo::ParameterVersion1& params, DelayIn
}
}
-void DelayCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void DelayCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("DelayCommand\n\tenabled {} \n\tinputs: ", effect_enabled);
for (u32 i = 0; i < MaxChannels; i++) {
@@ -207,7 +207,7 @@ void DelayCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proce
string += "\n";
}
-void DelayCommand::Process(const ADSP::CommandListProcessor& processor) {
+void DelayCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -231,8 +231,8 @@ void DelayCommand::Process(const ADSP::CommandListProcessor& processor) {
processor.sample_count);
}
-bool DelayCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool DelayCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/delay.h b/src/audio_core/renderer/command/effect/delay.h
index b7a15ae6b..bfeac7af4 100644
--- a/src/audio_core/renderer/command/effect/delay.h
+++ b/src/audio_core/renderer/command/effect/delay.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/effect/delay.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for a delay effect. Delays inputs mix buffers according to the parameters
* and state, outputs receives the delayed samples.
@@ -26,14 +27,14 @@ struct DelayCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct DelayCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -57,4 +58,4 @@ struct DelayCommand : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp
index d2bfb67cc..ecfdfabc6 100644
--- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp
+++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp
@@ -3,11 +3,11 @@
#include <numbers>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/i3dl2_reverb.h"
#include "common/polyfill_ranges.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
constexpr std::array<f32, I3dl2ReverbInfo::MaxDelayLines> MinDelayLineTimes{
5.0f,
@@ -394,7 +394,7 @@ static void ApplyI3dl2ReverbEffect(const I3dl2ReverbInfo::ParameterVersion1& par
}
}
-void I3dl2ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void I3dl2ReverbCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("I3dl2ReverbCommand\n\tenabled {} \n\tinputs: ", effect_enabled);
for (u32 i = 0; i < parameter.channel_count; i++) {
@@ -407,7 +407,7 @@ void I3dl2ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor&
string += "\n";
}
-void I3dl2ReverbCommand::Process(const ADSP::CommandListProcessor& processor) {
+void I3dl2ReverbCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -431,8 +431,8 @@ void I3dl2ReverbCommand::Process(const ADSP::CommandListProcessor& processor) {
processor.sample_count);
}
-bool I3dl2ReverbCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool I3dl2ReverbCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.h b/src/audio_core/renderer/command/effect/i3dl2_reverb.h
index 243877056..e4c538ae8 100644
--- a/src/audio_core/renderer/command/effect/i3dl2_reverb.h
+++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/effect/i3dl2.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for a I3DL2Reverb effect. Apply a reverb to inputs mix buffer according to
* the I3DL2 spec, outputs receives the results.
@@ -26,14 +27,14 @@ struct I3dl2ReverbCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct I3dl2ReverbCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -57,4 +58,4 @@ struct I3dl2ReverbCommand : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/light_limiter.cpp b/src/audio_core/renderer/command/effect/light_limiter.cpp
index 4161a9821..63aa06f5c 100644
--- a/src/audio_core/renderer/command/effect/light_limiter.cpp
+++ b/src/audio_core/renderer/command/effect/light_limiter.cpp
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/light_limiter.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Update the LightLimiterInfo state according to the given parameters.
* A no-op.
@@ -133,8 +133,8 @@ static void ApplyLightLimiterEffect(const LightLimiterInfo::ParameterVersion2& p
}
}
-void LightLimiterVersion1Command::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void LightLimiterVersion1Command::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("LightLimiterVersion1Command\n\tinputs: ");
for (u32 i = 0; i < MaxChannels; i++) {
string += fmt::format("{:02X}, ", inputs[i]);
@@ -146,7 +146,7 @@ void LightLimiterVersion1Command::Dump([[maybe_unused]] const ADSP::CommandListP
string += "\n";
}
-void LightLimiterVersion1Command::Process(const ADSP::CommandListProcessor& processor) {
+void LightLimiterVersion1Command::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -172,12 +172,12 @@ void LightLimiterVersion1Command::Process(const ADSP::CommandListProcessor& proc
processor.sample_count, statistics);
}
-bool LightLimiterVersion1Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool LightLimiterVersion1Command::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-void LightLimiterVersion2Command::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void LightLimiterVersion2Command::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("LightLimiterVersion2Command\n\tinputs: \n");
for (u32 i = 0; i < MaxChannels; i++) {
string += fmt::format("{:02X}, ", inputs[i]);
@@ -189,7 +189,7 @@ void LightLimiterVersion2Command::Dump([[maybe_unused]] const ADSP::CommandListP
string += "\n";
}
-void LightLimiterVersion2Command::Process(const ADSP::CommandListProcessor& processor) {
+void LightLimiterVersion2Command::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -215,8 +215,8 @@ void LightLimiterVersion2Command::Process(const ADSP::CommandListProcessor& proc
processor.sample_count, statistics);
}
-bool LightLimiterVersion2Command::Verify(const ADSP::CommandListProcessor& processor) {
+bool LightLimiterVersion2Command::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/light_limiter.h b/src/audio_core/renderer/command/effect/light_limiter.h
index 5d98272c7..6e3ee1b53 100644
--- a/src/audio_core/renderer/command/effect/light_limiter.h
+++ b/src/audio_core/renderer/command/effect/light_limiter.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/effect/light_limiter.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for limiting volume between a high and low threshold.
* Version 1.
@@ -26,14 +27,14 @@ struct LightLimiterVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct LightLimiterVersion1Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -68,21 +69,21 @@ struct LightLimiterVersion2Command : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
*
* @param processor - The CommandListProcessor processing this command.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -100,4 +101,4 @@ struct LightLimiterVersion2Command : ICommand {
bool effect_enabled;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
index 48a7cba8a..208bbeaf2 100644
--- a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
+++ b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
@@ -1,20 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/biquad_filter.h"
#include "audio_core/renderer/command/effect/multi_tap_biquad_filter.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void MultiTapBiquadFilterCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void MultiTapBiquadFilterCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format(
"MultiTapBiquadFilterCommand\n\tinput {:02X}\n\toutput {:02X}\n\tneeds_init ({}, {})\n",
input, output, needs_init[0], needs_init[1]);
}
-void MultiTapBiquadFilterCommand::Process(const ADSP::CommandListProcessor& processor) {
+void MultiTapBiquadFilterCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
if (filter_tap_count > MaxBiquadFilters) {
LOG_ERROR(Service_Audio, "Too many filter taps! {}", filter_tap_count);
filter_tap_count = MaxBiquadFilters;
@@ -38,8 +38,8 @@ void MultiTapBiquadFilterCommand::Process(const ADSP::CommandListProcessor& proc
}
}
-bool MultiTapBiquadFilterCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool MultiTapBiquadFilterCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.h b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.h
index 99c2c0830..50fce80b0 100644
--- a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.h
+++ b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/voice/voice_info.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for applying multiple biquads at once.
*/
@@ -25,14 +26,14 @@ struct MultiTapBiquadFilterCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct MultiTapBiquadFilterCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer index
s16 input;
@@ -56,4 +57,4 @@ struct MultiTapBiquadFilterCommand : ICommand {
u8 filter_tap_count;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp
index fc2f15a5e..7f152a962 100644
--- a/src/audio_core/renderer/command/effect/reverb.cpp
+++ b/src/audio_core/renderer/command/effect/reverb.cpp
@@ -4,11 +4,11 @@
#include <numbers>
#include <ranges>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/effect/reverb.h"
#include "common/polyfill_ranges.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
constexpr std::array<f32, ReverbInfo::MaxDelayLines> FdnMaxDelayLineTimes = {
53.9532470703125f,
@@ -396,7 +396,7 @@ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, Rever
}
}
-void ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void ReverbCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format(
"ReverbCommand\n\tenabled {} long_size_pre_delay_supported {}\n\tinputs: ", effect_enabled,
@@ -411,7 +411,7 @@ void ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proc
string += "\n";
}
-void ReverbCommand::Process(const ADSP::CommandListProcessor& processor) {
+void ReverbCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
std::array<std::span<const s32>, MaxChannels> input_buffers{};
std::array<std::span<s32>, MaxChannels> output_buffers{};
@@ -435,8 +435,8 @@ void ReverbCommand::Process(const ADSP::CommandListProcessor& processor) {
processor.sample_count);
}
-bool ReverbCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool ReverbCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/effect/reverb.h b/src/audio_core/renderer/command/effect/reverb.h
index 328756150..2056c73f2 100644
--- a/src/audio_core/renderer/command/effect/reverb.h
+++ b/src/audio_core/renderer/command/effect/reverb.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/effect/reverb.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for a Reverb effect. Apply a reverb to inputs mix buffer, outputs receives
* the results.
@@ -26,14 +27,14 @@ struct ReverbCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -41,7 +42,7 @@ struct ReverbCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -59,4 +60,4 @@ struct ReverbCommand : ICommand {
bool long_size_pre_delay_supported;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/icommand.h b/src/audio_core/renderer/command/icommand.h
index f2dd41254..10a78ddf2 100644
--- a/src/audio_core/renderer/command/icommand.h
+++ b/src/audio_core/renderer/command/icommand.h
@@ -3,14 +3,18 @@
#pragma once
+#include <string>
+
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+using namespace ::AudioCore::ADSP;
+
enum class CommandId : u8 {
/* 0x00 */ Invalid,
/* 0x01 */ DataSourcePcmInt16Version1,
@@ -59,14 +63,15 @@ struct ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- virtual void Dump(const ADSP::CommandListProcessor& processor, std::string& string) = 0;
+ virtual void Dump(const AudioRenderer::CommandListProcessor& processor,
+ std::string& string) = 0;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- virtual void Process(const ADSP::CommandListProcessor& processor) = 0;
+ virtual void Process(const AudioRenderer::CommandListProcessor& processor) = 0;
/**
* Verify this command's data is valid.
@@ -74,7 +79,7 @@ struct ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- virtual bool Verify(const ADSP::CommandListProcessor& processor) = 0;
+ virtual bool Verify(const AudioRenderer::CommandListProcessor& processor) = 0;
/// Command magic 0xCAFEBABE
u32 magic{};
@@ -90,4 +95,4 @@ struct ICommand {
u32 node_id{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/clear_mix.cpp b/src/audio_core/renderer/command/mix/clear_mix.cpp
index 4f649d6a8..060d7cb28 100644
--- a/src/audio_core/renderer/command/mix/clear_mix.cpp
+++ b/src/audio_core/renderer/command/mix/clear_mix.cpp
@@ -3,22 +3,22 @@
#include <string>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/clear_mix.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void ClearMixBufferCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void ClearMixBufferCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("ClearMixBufferCommand\n");
}
-void ClearMixBufferCommand::Process(const ADSP::CommandListProcessor& processor) {
+void ClearMixBufferCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
memset(processor.mix_buffers.data(), 0, processor.mix_buffers.size_bytes());
}
-bool ClearMixBufferCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool ClearMixBufferCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/clear_mix.h b/src/audio_core/renderer/command/mix/clear_mix.h
index 956ec0b65..650fa1a8a 100644
--- a/src/audio_core/renderer/command/mix/clear_mix.h
+++ b/src/audio_core/renderer/command/mix/clear_mix.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for a clearing the mix buffers.
* Used at the start of each command list.
@@ -24,14 +25,14 @@ struct ClearMixBufferCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct ClearMixBufferCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/copy_mix.cpp b/src/audio_core/renderer/command/mix/copy_mix.cpp
index 1d49f1644..5d386f95a 100644
--- a/src/audio_core/renderer/command/mix/copy_mix.cpp
+++ b/src/audio_core/renderer/command/mix/copy_mix.cpp
@@ -1,18 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/copy_mix.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void CopyMixBufferCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void CopyMixBufferCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("CopyMixBufferCommand\n\tinput {:02X} output {:02X}\n", input_index,
output_index);
}
-void CopyMixBufferCommand::Process(const ADSP::CommandListProcessor& processor) {
+void CopyMixBufferCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto output{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
auto input{processor.mix_buffers.subspan(input_index * processor.sample_count,
@@ -20,8 +20,8 @@ void CopyMixBufferCommand::Process(const ADSP::CommandListProcessor& processor)
std::memcpy(output.data(), input.data(), processor.sample_count * sizeof(s32));
}
-bool CopyMixBufferCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool CopyMixBufferCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/copy_mix.h b/src/audio_core/renderer/command/mix/copy_mix.h
index a59007fb6..ae247c3f8 100644
--- a/src/audio_core/renderer/command/mix/copy_mix.h
+++ b/src/audio_core/renderer/command/mix/copy_mix.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for a copying a mix buffer from input to output.
*/
@@ -23,14 +24,14 @@ struct CopyMixBufferCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -38,7 +39,7 @@ struct CopyMixBufferCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer index
s16 input_index;
@@ -46,4 +47,4 @@ struct CopyMixBufferCommand : ICommand {
s16 output_index;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp
index c2bc10061..caedb56b7 100644
--- a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp
+++ b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/common/common.h"
-#include "audio_core/renderer/adsp/command_list_processor.h"
#include "audio_core/renderer/command/mix/depop_for_mix_buffers.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Apply depopping. Add the depopped sample to each incoming new sample, decaying it each time
* according to decay.
@@ -36,13 +36,13 @@ static s32 ApplyDepopMix(std::span<s32> output, const s32 depop_sample,
}
}
-void DepopForMixBuffersCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void DepopForMixBuffersCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("DepopForMixBuffersCommand\n\tinput {:02X} count {} decay {}\n", input,
count, decay.to_float());
}
-void DepopForMixBuffersCommand::Process(const ADSP::CommandListProcessor& processor) {
+void DepopForMixBuffersCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto end_index{std::min(processor.buffer_count, input + count)};
std::span<s32> depop_buff{reinterpret_cast<s32*>(depop_buffer), end_index};
@@ -57,8 +57,8 @@ void DepopForMixBuffersCommand::Process(const ADSP::CommandListProcessor& proces
}
}
-bool DepopForMixBuffersCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool DepopForMixBuffersCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.h b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.h
index e7268ff27..699d38988 100644
--- a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.h
+++ b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.h
@@ -9,11 +9,12 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for depopping a mix buffer.
* Adds a cumulation of previous samples to the current mix buffer with a decay.
@@ -25,14 +26,14 @@ struct DepopForMixBuffersCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct DepopForMixBuffersCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Starting input mix buffer index
u32 input;
@@ -52,4 +53,4 @@ struct DepopForMixBuffersCommand : ICommand {
CpuAddr depop_buffer;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/depop_prepare.cpp b/src/audio_core/renderer/command/mix/depop_prepare.cpp
index 69bb78ccc..2faf4681a 100644
--- a/src/audio_core/renderer/command/mix/depop_prepare.cpp
+++ b/src/audio_core/renderer/command/mix/depop_prepare.cpp
@@ -1,15 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/depop_prepare.h"
#include "audio_core/renderer/voice/voice_state.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void DepopPrepareCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void DepopPrepareCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("DepopPrepareCommand\n\tinputs: ");
for (u32 i = 0; i < buffer_count; i++) {
string += fmt::format("{:02X}, ", inputs[i]);
@@ -17,7 +17,7 @@ void DepopPrepareCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor
string += "\n";
}
-void DepopPrepareCommand::Process(const ADSP::CommandListProcessor& processor) {
+void DepopPrepareCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto samples{reinterpret_cast<s32*>(previous_samples)};
auto buffer{reinterpret_cast<s32*>(depop_buffer)};
@@ -29,8 +29,8 @@ void DepopPrepareCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool DepopPrepareCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool DepopPrepareCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/depop_prepare.h b/src/audio_core/renderer/command/mix/depop_prepare.h
index a5465da9a..161a94461 100644
--- a/src/audio_core/renderer/command/mix/depop_prepare.h
+++ b/src/audio_core/renderer/command/mix/depop_prepare.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for preparing depop.
* Adds the previusly output last samples to the depop buffer.
@@ -24,14 +25,14 @@ struct DepopPrepareCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct DepopPrepareCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Depop buffer offset for each mix buffer
std::array<s16, MaxMixBuffers> inputs;
@@ -51,4 +52,4 @@ struct DepopPrepareCommand : ICommand {
CpuAddr depop_buffer;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix.cpp b/src/audio_core/renderer/command/mix/mix.cpp
index 8ecf9b05a..8bd689b88 100644
--- a/src/audio_core/renderer/command/mix/mix.cpp
+++ b/src/audio_core/renderer/command/mix/mix.cpp
@@ -5,11 +5,11 @@
#include <limits>
#include <span>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/mix.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Mix input mix buffer into output mix buffer, with volume applied to the input.
*
@@ -28,7 +28,7 @@ static void ApplyMix(std::span<s32> output, std::span<const s32> input, const f3
}
}
-void MixCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void MixCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("MixCommand");
string += fmt::format("\n\tinput {:02X}", input_index);
@@ -37,7 +37,7 @@ void MixCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& process
string += "\n";
}
-void MixCommand::Process(const ADSP::CommandListProcessor& processor) {
+void MixCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto output{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
auto input{processor.mix_buffers.subspan(input_index * processor.sample_count,
@@ -63,8 +63,8 @@ void MixCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool MixCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool MixCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix.h b/src/audio_core/renderer/command/mix/mix.h
index 0201cf171..64c812382 100644
--- a/src/audio_core/renderer/command/mix/mix.h
+++ b/src/audio_core/renderer/command/mix/mix.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for mixing an input mix buffer to an output mix buffer, with a volume
* applied to the input.
@@ -24,14 +25,14 @@ struct MixCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct MixCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Fixed point precision
u8 precision;
@@ -51,4 +52,4 @@ struct MixCommand : ICommand {
f32 volume;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix_ramp.cpp b/src/audio_core/renderer/command/mix/mix_ramp.cpp
index d67123cd8..2f6500da5 100644
--- a/src/audio_core/renderer/command/mix/mix_ramp.cpp
+++ b/src/audio_core/renderer/command/mix/mix_ramp.cpp
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/mix_ramp.h"
#include "common/fixed_point.h"
#include "common/logging/log.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
template <size_t Q>
s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, const f32 volume_,
@@ -33,7 +33,8 @@ s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, const f32 vo
template s32 ApplyMixRamp<15>(std::span<s32>, std::span<const s32>, f32, f32, u32);
template s32 ApplyMixRamp<23>(std::span<s32>, std::span<const s32>, f32, f32, u32);
-void MixRampCommand::Dump(const ADSP::CommandListProcessor& processor, std::string& string) {
+void MixRampCommand::Dump(const AudioRenderer::CommandListProcessor& processor,
+ std::string& string) {
const auto ramp{(volume - prev_volume) / static_cast<f32>(processor.sample_count)};
string += fmt::format("MixRampCommand");
string += fmt::format("\n\tinput {:02X}", input_index);
@@ -44,7 +45,7 @@ void MixRampCommand::Dump(const ADSP::CommandListProcessor& processor, std::stri
string += "\n";
}
-void MixRampCommand::Process(const ADSP::CommandListProcessor& processor) {
+void MixRampCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto output{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
auto input{processor.mix_buffers.subspan(input_index * processor.sample_count,
@@ -75,8 +76,8 @@ void MixRampCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool MixRampCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool MixRampCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix_ramp.h b/src/audio_core/renderer/command/mix/mix_ramp.h
index 52f74a273..92209b53a 100644
--- a/src/audio_core/renderer/command/mix/mix_ramp.h
+++ b/src/audio_core/renderer/command/mix/mix_ramp.h
@@ -9,11 +9,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for mixing an input mix buffer to an output mix buffer, with a volume
* applied to the input, and volume ramping to smooth out the transition.
@@ -25,14 +26,14 @@ struct MixRampCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct MixRampCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Fixed point precision
u8 precision;
@@ -70,4 +71,4 @@ template <size_t Q>
s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, f32 volume_, f32 ramp_,
u32 sample_count);
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix_ramp_grouped.cpp b/src/audio_core/renderer/command/mix/mix_ramp_grouped.cpp
index 43dbef9fc..64138a9bf 100644
--- a/src/audio_core/renderer/command/mix/mix_ramp_grouped.cpp
+++ b/src/audio_core/renderer/command/mix/mix_ramp_grouped.cpp
@@ -1,13 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/mix_ramp.h"
#include "audio_core/renderer/command/mix/mix_ramp_grouped.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void MixRampGroupedCommand::Dump(const ADSP::CommandListProcessor& processor, std::string& string) {
+void MixRampGroupedCommand::Dump(const AudioRenderer::CommandListProcessor& processor,
+ std::string& string) {
string += "MixRampGroupedCommand";
for (u32 i = 0; i < buffer_count; i++) {
string += fmt::format("\n\t{}", i);
@@ -21,7 +22,7 @@ void MixRampGroupedCommand::Dump(const ADSP::CommandListProcessor& processor, st
}
}
-void MixRampGroupedCommand::Process(const ADSP::CommandListProcessor& processor) {
+void MixRampGroupedCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
std::span<s32> prev_samples = {reinterpret_cast<s32*>(previous_samples), MaxMixBuffers};
for (u32 i = 0; i < buffer_count; i++) {
@@ -58,8 +59,8 @@ void MixRampGroupedCommand::Process(const ADSP::CommandListProcessor& processor)
}
}
-bool MixRampGroupedCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool MixRampGroupedCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/mix_ramp_grouped.h b/src/audio_core/renderer/command/mix/mix_ramp_grouped.h
index 3b0ce67ef..9621e42a3 100644
--- a/src/audio_core/renderer/command/mix/mix_ramp_grouped.h
+++ b/src/audio_core/renderer/command/mix/mix_ramp_grouped.h
@@ -9,11 +9,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for mixing multiple input mix buffers to multiple output mix buffers, with
* a volume applied to the input, and volume ramping to smooth out the transition.
@@ -25,14 +26,14 @@ struct MixRampGroupedCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct MixRampGroupedCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Fixed point precision
u8 precision;
@@ -58,4 +59,4 @@ struct MixRampGroupedCommand : ICommand {
CpuAddr previous_samples;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/volume.cpp b/src/audio_core/renderer/command/mix/volume.cpp
index b045fb062..92baf6cc3 100644
--- a/src/audio_core/renderer/command/mix/volume.cpp
+++ b/src/audio_core/renderer/command/mix/volume.cpp
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/volume.h"
#include "common/fixed_point.h"
#include "common/logging/log.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Apply volume to the input mix buffer, saving to the output buffer.
*
@@ -29,7 +29,7 @@ static void ApplyUniformGain(std::span<s32> output, std::span<const s32> input,
}
}
-void VolumeCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void VolumeCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("VolumeCommand");
string += fmt::format("\n\tinput {:02X}", input_index);
@@ -38,7 +38,7 @@ void VolumeCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proc
string += "\n";
}
-void VolumeCommand::Process(const ADSP::CommandListProcessor& processor) {
+void VolumeCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
// If input and output buffers are the same, and the volume is 1.0f, this won't do
// anything, so just skip.
if (input_index == output_index && volume == 1.0f) {
@@ -65,8 +65,8 @@ void VolumeCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool VolumeCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool VolumeCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/volume.h b/src/audio_core/renderer/command/mix/volume.h
index 6ae9fb794..fbb8156ca 100644
--- a/src/audio_core/renderer/command/mix/volume.h
+++ b/src/audio_core/renderer/command/mix/volume.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for applying volume to a mix buffer.
*/
@@ -23,14 +24,14 @@ struct VolumeCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -38,7 +39,7 @@ struct VolumeCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Fixed point precision
u8 precision;
@@ -50,4 +51,4 @@ struct VolumeCommand : ICommand {
f32 volume;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/volume_ramp.cpp b/src/audio_core/renderer/command/mix/volume_ramp.cpp
index 424307148..fdc751957 100644
--- a/src/audio_core/renderer/command/mix/volume_ramp.cpp
+++ b/src/audio_core/renderer/command/mix/volume_ramp.cpp
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/mix/volume_ramp.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Apply volume with ramping to the input mix buffer, saving to the output buffer.
*
@@ -38,7 +38,8 @@ static void ApplyLinearEnvelopeGain(std::span<s32> output, std::span<const s32>
}
}
-void VolumeRampCommand::Dump(const ADSP::CommandListProcessor& processor, std::string& string) {
+void VolumeRampCommand::Dump(const AudioRenderer::CommandListProcessor& processor,
+ std::string& string) {
const auto ramp{(volume - prev_volume) / static_cast<f32>(processor.sample_count)};
string += fmt::format("VolumeRampCommand");
string += fmt::format("\n\tinput {:02X}", input_index);
@@ -49,7 +50,7 @@ void VolumeRampCommand::Dump(const ADSP::CommandListProcessor& processor, std::s
string += "\n";
}
-void VolumeRampCommand::Process(const ADSP::CommandListProcessor& processor) {
+void VolumeRampCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto output{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
auto input{processor.mix_buffers.subspan(input_index * processor.sample_count,
@@ -77,8 +78,8 @@ void VolumeRampCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool VolumeRampCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool VolumeRampCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/mix/volume_ramp.h b/src/audio_core/renderer/command/mix/volume_ramp.h
index 77b61547e..d9794fb95 100644
--- a/src/audio_core/renderer/command/mix/volume_ramp.h
+++ b/src/audio_core/renderer/command/mix/volume_ramp.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for applying volume to a mix buffer, with ramping for the volume to smooth
* out the transition.
@@ -24,14 +25,14 @@ struct VolumeRampCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct VolumeRampCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Fixed point precision
u8 precision;
@@ -53,4 +54,4 @@ struct VolumeRampCommand : ICommand {
f32 volume;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/performance/performance.cpp b/src/audio_core/renderer/command/performance/performance.cpp
index 4a881547f..f0cfcc9fd 100644
--- a/src/audio_core/renderer/command/performance/performance.cpp
+++ b/src/audio_core/renderer/command/performance/performance.cpp
@@ -1,25 +1,25 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/performance/performance.h"
#include "core/core.h"
#include "core/core_timing.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void PerformanceCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void PerformanceCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("PerformanceCommand\n\tstate {}\n", static_cast<u32>(state));
}
-void PerformanceCommand::Process(const ADSP::CommandListProcessor& processor) {
+void PerformanceCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto base{entry_address.translated_address};
if (state == PerformanceState::Start) {
auto start_time_ptr{reinterpret_cast<u32*>(base + entry_address.entry_start_time_offset)};
*start_time_ptr =
- static_cast<u32>(processor.system->CoreTiming().GetClockTicks() - processor.start_time -
- processor.current_processing_time);
+ static_cast<u32>(processor.system->CoreTiming().GetGlobalTimeUs().count() -
+ processor.start_time - processor.current_processing_time);
} else if (state == PerformanceState::Stop) {
auto processed_time_ptr{
reinterpret_cast<u32*>(base + entry_address.entry_processed_time_offset)};
@@ -27,14 +27,14 @@ void PerformanceCommand::Process(const ADSP::CommandListProcessor& processor) {
reinterpret_cast<u32*>(base + entry_address.header_entry_count_offset)};
*processed_time_ptr =
- static_cast<u32>(processor.system->CoreTiming().GetClockTicks() - processor.start_time -
- processor.current_processing_time);
+ static_cast<u32>(processor.system->CoreTiming().GetGlobalTimeUs().count() -
+ processor.start_time - processor.current_processing_time);
(*entry_count_ptr)++;
}
}
-bool PerformanceCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool PerformanceCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/performance/performance.h b/src/audio_core/renderer/command/performance/performance.h
index 11a7d6c08..522e51e34 100644
--- a/src/audio_core/renderer/command/performance/performance.h
+++ b/src/audio_core/renderer/command/performance/performance.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for writing AudioRenderer performance metrics back to the sysmodule.
*/
@@ -25,14 +26,14 @@ struct PerformanceCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct PerformanceCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// State of the performance
PerformanceState state;
@@ -48,4 +49,4 @@ struct PerformanceCommand : ICommand {
PerformanceEntryAddresses entry_address;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.cpp b/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.cpp
index 1fd90308a..f9b289887 100644
--- a/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.cpp
+++ b/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.cpp
@@ -1,13 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/resample/downmix_6ch_to_2ch.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void DownMix6chTo2chCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void DownMix6chTo2chCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format("DownMix6chTo2chCommand\n\tinputs: ");
for (u32 i = 0; i < MaxChannels; i++) {
string += fmt::format("{:02X}, ", inputs[i]);
@@ -19,7 +19,7 @@ void DownMix6chTo2chCommand::Dump([[maybe_unused]] const ADSP::CommandListProces
string += "\n";
}
-void DownMix6chTo2chCommand::Process(const ADSP::CommandListProcessor& processor) {
+void DownMix6chTo2chCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
auto in_front_left{
processor.mix_buffers.subspan(inputs[0] * processor.sample_count, processor.sample_count)};
auto in_front_right{
@@ -67,8 +67,8 @@ void DownMix6chTo2chCommand::Process(const ADSP::CommandListProcessor& processor
std::memset(out_back_right.data(), 0, out_back_right.size_bytes());
}
-bool DownMix6chTo2chCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool DownMix6chTo2chCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.h b/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.h
index dc133a73b..96cbc5506 100644
--- a/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.h
+++ b/src/audio_core/renderer/command/resample/downmix_6ch_to_2ch.h
@@ -9,11 +9,12 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for downmixing 6 channels to 2.
* Channel layout (SMPTE):
@@ -31,14 +32,14 @@ struct DownMix6chTo2chCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -46,7 +47,7 @@ struct DownMix6chTo2chCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Input mix buffer offsets for each channel
std::array<s16, MaxChannels> inputs;
@@ -56,4 +57,4 @@ struct DownMix6chTo2chCommand : ICommand {
std::array<Common::FixedPoint<48, 16>, 4> down_mix_coeff;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/resample.cpp b/src/audio_core/renderer/command/resample/resample.cpp
index 070c9d2b8..51f4ba39e 100644
--- a/src/audio_core/renderer/command/resample/resample.cpp
+++ b/src/audio_core/renderer/command/resample/resample.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/command/resample/resample.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
static void ResampleLowQuality(std::span<s32> output, std::span<const s16> input,
const Common::FixedPoint<49, 15>& sample_rate_ratio,
@@ -880,4 +880,4 @@ void Resample(std::span<s32> output, std::span<const s16> input,
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/resample.h b/src/audio_core/renderer/command/resample/resample.h
index ba9209b82..134aff0c9 100644
--- a/src/audio_core/renderer/command/resample/resample.h
+++ b/src/audio_core/renderer/command/resample/resample.h
@@ -9,7 +9,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Resample an input buffer into an output buffer, according to the sample_rate_ratio.
*
@@ -26,4 +26,4 @@ void Resample(std::span<s32> output, std::span<const s16> input,
const Common::FixedPoint<49, 15>& sample_rate_ratio,
Common::FixedPoint<49, 15>& fraction, u32 samples_to_write, SrcQuality src_quality);
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/upsample.cpp b/src/audio_core/renderer/command/resample/upsample.cpp
index 86ddee1a4..691d70390 100644
--- a/src/audio_core/renderer/command/resample/upsample.cpp
+++ b/src/audio_core/renderer/command/resample/upsample.cpp
@@ -3,11 +3,11 @@
#include <array>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/resample/upsample.h"
#include "audio_core/renderer/upsampler/upsampler_info.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Upsampling impl. Input must be 8K, 16K or 32K, output is 48K.
*
@@ -198,7 +198,7 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
}
}
-auto UpsampleCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+auto UpsampleCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) -> void {
string += fmt::format("UpsampleCommand\n\tsource_sample_count {} source_sample_rate {}",
source_sample_count, source_sample_rate);
@@ -213,7 +213,7 @@ auto UpsampleCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& pr
string += "\n";
}
-void UpsampleCommand::Process(const ADSP::CommandListProcessor& processor) {
+void UpsampleCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
const auto info{reinterpret_cast<UpsamplerInfo*>(upsampler_info)};
const auto input_count{std::min(info->input_count, buffer_count)};
const std::span<const s16> inputs_{reinterpret_cast<const s16*>(inputs), input_count};
@@ -234,8 +234,8 @@ void UpsampleCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool UpsampleCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool UpsampleCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/resample/upsample.h b/src/audio_core/renderer/command/resample/upsample.h
index bfc94e8af..877271ba9 100644
--- a/src/audio_core/renderer/command/resample/upsample.h
+++ b/src/audio_core/renderer/command/resample/upsample.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for upsampling a mix buffer to 48Khz.
* Input must be 8Khz, 16Khz or 32Khz, and output will be 48Khz.
@@ -24,14 +25,14 @@ struct UpsampleCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -39,7 +40,7 @@ struct UpsampleCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Pointer to the output samples buffer.
CpuAddr samples_buffer;
@@ -57,4 +58,4 @@ struct UpsampleCommand : ICommand {
CpuAddr upsampler_info;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/sink/circular_buffer.cpp b/src/audio_core/renderer/command/sink/circular_buffer.cpp
index e2ce59792..e056d15a6 100644
--- a/src/audio_core/renderer/command/sink/circular_buffer.cpp
+++ b/src/audio_core/renderer/command/sink/circular_buffer.cpp
@@ -3,14 +3,14 @@
#include <vector>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/sink/circular_buffer.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void CircularBufferSinkCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
- std::string& string) {
+void CircularBufferSinkCommand::Dump(
+ [[maybe_unused]] const AudioRenderer::CommandListProcessor& processor, std::string& string) {
string += fmt::format(
"CircularBufferSinkCommand\n\tinput_count {} ring size {:04X} ring pos {:04X}\n\tinputs: ",
input_count, size, pos);
@@ -20,7 +20,7 @@ void CircularBufferSinkCommand::Dump([[maybe_unused]] const ADSP::CommandListPro
string += "\n";
}
-void CircularBufferSinkCommand::Process(const ADSP::CommandListProcessor& processor) {
+void CircularBufferSinkCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
constexpr s32 min{std::numeric_limits<s16>::min()};
constexpr s32 max{std::numeric_limits<s16>::max()};
@@ -41,8 +41,8 @@ void CircularBufferSinkCommand::Process(const ADSP::CommandListProcessor& proces
}
}
-bool CircularBufferSinkCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool CircularBufferSinkCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/sink/circular_buffer.h b/src/audio_core/renderer/command/sink/circular_buffer.h
index e7d5be26e..a3234a406 100644
--- a/src/audio_core/renderer/command/sink/circular_buffer.h
+++ b/src/audio_core/renderer/command/sink/circular_buffer.h
@@ -8,11 +8,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for sinking samples to a circular buffer.
*/
@@ -23,14 +24,14 @@ struct CircularBufferSinkCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -38,7 +39,7 @@ struct CircularBufferSinkCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Number of input mix buffers
u32 input_count;
@@ -52,4 +53,4 @@ struct CircularBufferSinkCommand : ICommand {
u32 pos;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/sink/device.cpp b/src/audio_core/renderer/command/sink/device.cpp
index 5f74dd7ad..3480ed475 100644
--- a/src/audio_core/renderer/command/sink/device.cpp
+++ b/src/audio_core/renderer/command/sink/device.cpp
@@ -3,13 +3,13 @@
#include <algorithm>
-#include "audio_core/renderer/adsp/command_list_processor.h"
+#include "audio_core/adsp/apps/audio_renderer/command_list_processor.h"
#include "audio_core/renderer/command/sink/device.h"
#include "audio_core/sink/sink.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
-void DeviceSinkCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
+void DeviceSinkCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProcessor& processor,
std::string& string) {
string += fmt::format("DeviceSinkCommand\n\t{} session {} input_count {}\n\tinputs: ",
std::string_view(name), session_id, input_count);
@@ -19,7 +19,7 @@ void DeviceSinkCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor&
string += "\n";
}
-void DeviceSinkCommand::Process(const ADSP::CommandListProcessor& processor) {
+void DeviceSinkCommand::Process(const AudioRenderer::CommandListProcessor& processor) {
constexpr s32 min = std::numeric_limits<s16>::min();
constexpr s32 max = std::numeric_limits<s16>::max();
@@ -51,8 +51,8 @@ void DeviceSinkCommand::Process(const ADSP::CommandListProcessor& processor) {
}
}
-bool DeviceSinkCommand::Verify(const ADSP::CommandListProcessor& processor) {
+bool DeviceSinkCommand::Verify(const AudioRenderer::CommandListProcessor& processor) {
return true;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/command/sink/device.h b/src/audio_core/renderer/command/sink/device.h
index 1099bcf8c..385b51ecc 100644
--- a/src/audio_core/renderer/command/sink/device.h
+++ b/src/audio_core/renderer/command/sink/device.h
@@ -10,11 +10,12 @@
#include "audio_core/renderer/command/icommand.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP::AudioRenderer {
class CommandListProcessor;
}
+namespace AudioCore::Renderer {
+
/**
* AudioRenderer command for sinking samples to an output device.
*/
@@ -25,14 +26,14 @@ struct DeviceSinkCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @param string - The string to print into.
*/
- void Dump(const ADSP::CommandListProcessor& processor, std::string& string) override;
+ void Dump(const AudioRenderer::CommandListProcessor& processor, std::string& string) override;
/**
* Process this command.
*
* @param processor - The CommandListProcessor processing this command.
*/
- void Process(const ADSP::CommandListProcessor& processor) override;
+ void Process(const AudioRenderer::CommandListProcessor& processor) override;
/**
* Verify this command's data is valid.
@@ -40,7 +41,7 @@ struct DeviceSinkCommand : ICommand {
* @param processor - The CommandListProcessor processing this command.
* @return True if the command is valid, otherwise false.
*/
- bool Verify(const ADSP::CommandListProcessor& processor) override;
+ bool Verify(const AudioRenderer::CommandListProcessor& processor) override;
/// Device name
char name[0x100];
@@ -54,4 +55,4 @@ struct DeviceSinkCommand : ICommand {
std::array<s16, MaxChannels> inputs;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/aux_.cpp b/src/audio_core/renderer/effect/aux_.cpp
index 51e780ef1..1c1411eff 100644
--- a/src/audio_core/renderer/effect/aux_.cpp
+++ b/src/audio_core/renderer/effect/aux_.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/aux_.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void AuxInfo::Update(BehaviorInfo::ErrorInfo& error_info, const InParameterVersion1& in_params,
const PoolMapper& pool_mapper) {
@@ -90,4 +90,4 @@ CpuAddr AuxInfo::GetWorkbuffer(s32 index) {
return workbuffers[index].GetReference(true);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/aux_.h b/src/audio_core/renderer/effect/aux_.h
index 4d3d9e3d9..c5b3058da 100644
--- a/src/audio_core/renderer/effect/aux_.h
+++ b/src/audio_core/renderer/effect/aux_.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/effect/effect_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Auxiliary Buffer used for Aux commands.
* Send and return buffers are available (names from the game's perspective).
@@ -120,4 +120,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/biquad_filter.cpp b/src/audio_core/renderer/effect/biquad_filter.cpp
index a1efb3231..08161d840 100644
--- a/src/audio_core/renderer/effect/biquad_filter.cpp
+++ b/src/audio_core/renderer/effect/biquad_filter.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/biquad_filter.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void BiquadFilterInfo::Update(BehaviorInfo::ErrorInfo& error_info,
const InParameterVersion1& in_params, const PoolMapper& pool_mapper) {
@@ -49,4 +49,4 @@ void BiquadFilterInfo::InitializeResultState(EffectResultState& result_state) {}
void BiquadFilterInfo::UpdateResultState(EffectResultState& cpu_state,
EffectResultState& dsp_state) {}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/biquad_filter.h b/src/audio_core/renderer/effect/biquad_filter.h
index f53fd5bab..5a22899ab 100644
--- a/src/audio_core/renderer/effect/biquad_filter.h
+++ b/src/audio_core/renderer/effect/biquad_filter.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/effect/effect_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class BiquadFilterInfo : public EffectInfoBase {
public:
@@ -76,4 +76,4 @@ public:
void UpdateResultState(EffectResultState& cpu_state, EffectResultState& dsp_state) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/buffer_mixer.cpp b/src/audio_core/renderer/effect/buffer_mixer.cpp
index 9c8877f01..826e246ec 100644
--- a/src/audio_core/renderer/effect/buffer_mixer.cpp
+++ b/src/audio_core/renderer/effect/buffer_mixer.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/buffer_mixer.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void BufferMixerInfo::Update(BehaviorInfo::ErrorInfo& error_info,
const InParameterVersion1& in_params, const PoolMapper& pool_mapper) {
@@ -46,4 +46,4 @@ void BufferMixerInfo::InitializeResultState(EffectResultState& result_state) {}
void BufferMixerInfo::UpdateResultState(EffectResultState& cpu_state,
EffectResultState& dsp_state) {}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/buffer_mixer.h b/src/audio_core/renderer/effect/buffer_mixer.h
index 23eed4a8b..0c01ef38d 100644
--- a/src/audio_core/renderer/effect/buffer_mixer.h
+++ b/src/audio_core/renderer/effect/buffer_mixer.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/effect/effect_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class BufferMixerInfo : public EffectInfoBase {
public:
@@ -72,4 +72,4 @@ public:
void UpdateResultState(EffectResultState& cpu_state, EffectResultState& dsp_state) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/capture.cpp b/src/audio_core/renderer/effect/capture.cpp
index 3f038efdb..dfa062a59 100644
--- a/src/audio_core/renderer/effect/capture.cpp
+++ b/src/audio_core/renderer/effect/capture.cpp
@@ -4,7 +4,7 @@
#include "audio_core/renderer/effect/aux_.h"
#include "audio_core/renderer/effect/capture.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void CaptureInfo::Update(BehaviorInfo::ErrorInfo& error_info, const InParameterVersion1& in_params,
const PoolMapper& pool_mapper) {
@@ -79,4 +79,4 @@ CpuAddr CaptureInfo::GetWorkbuffer(s32 index) {
return workbuffers[index].GetReference(true);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/capture.h b/src/audio_core/renderer/effect/capture.h
index 6fbed8e6b..cbe71e22a 100644
--- a/src/audio_core/renderer/effect/capture.h
+++ b/src/audio_core/renderer/effect/capture.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/effect/effect_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class CaptureInfo : public EffectInfoBase {
public:
@@ -62,4 +62,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/compressor.cpp b/src/audio_core/renderer/effect/compressor.cpp
index 220ae02f9..fea0aefcf 100644
--- a/src/audio_core/renderer/effect/compressor.cpp
+++ b/src/audio_core/renderer/effect/compressor.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/compressor.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void CompressorInfo::Update(BehaviorInfo::ErrorInfo& error_info,
const InParameterVersion1& in_params, const PoolMapper& pool_mapper) {}
@@ -37,4 +37,4 @@ CpuAddr CompressorInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/compressor.h b/src/audio_core/renderer/effect/compressor.h
index 019a5ae58..cda55c284 100644
--- a/src/audio_core/renderer/effect/compressor.h
+++ b/src/audio_core/renderer/effect/compressor.h
@@ -10,7 +10,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class CompressorInfo : public EffectInfoBase {
public:
@@ -103,4 +103,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/delay.cpp b/src/audio_core/renderer/effect/delay.cpp
index d9853efd9..e038d4498 100644
--- a/src/audio_core/renderer/effect/delay.cpp
+++ b/src/audio_core/renderer/effect/delay.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/delay.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void DelayInfo::Update(BehaviorInfo::ErrorInfo& error_info, const InParameterVersion1& in_params,
const PoolMapper& pool_mapper) {
@@ -90,4 +90,4 @@ CpuAddr DelayInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/delay.h b/src/audio_core/renderer/effect/delay.h
index accc42a06..47417fbc6 100644
--- a/src/audio_core/renderer/effect/delay.h
+++ b/src/audio_core/renderer/effect/delay.h
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class DelayInfo : public EffectInfoBase {
public:
@@ -132,4 +132,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/effect_context.cpp b/src/audio_core/renderer/effect/effect_context.cpp
index 74c7801c9..00f6d7822 100644
--- a/src/audio_core/renderer/effect/effect_context.cpp
+++ b/src/audio_core/renderer/effect/effect_context.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/effect_context.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void EffectContext::Initialize(std::span<EffectInfoBase> effect_infos_, const u32 effect_count_,
std::span<EffectResultState> result_states_cpu_,
@@ -38,4 +38,4 @@ void EffectContext::UpdateStateByDspShared() {
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/effect_context.h b/src/audio_core/renderer/effect/effect_context.h
index 8f6d6e7d8..8364c5521 100644
--- a/src/audio_core/renderer/effect/effect_context.h
+++ b/src/audio_core/renderer/effect/effect_context.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/effect/effect_result_state.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class EffectContext {
public:
@@ -72,4 +72,4 @@ private:
size_t dsp_state_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/effect_info_base.h b/src/audio_core/renderer/effect/effect_info_base.h
index dbdccf278..b49503409 100644
--- a/src/audio_core/renderer/effect/effect_info_base.h
+++ b/src/audio_core/renderer/effect/effect_info_base.h
@@ -12,7 +12,7 @@
#include "audio_core/renderer/memory/pool_mapper.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Base of all effects. Holds various data and functions used for all derived effects.
* Should not be used directly.
@@ -432,4 +432,4 @@ protected:
std::array<u8, sizeof(State)> state{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/effect_reset.h b/src/audio_core/renderer/effect/effect_reset.h
index 1ea67e334..c9e3b4b78 100644
--- a/src/audio_core/renderer/effect/effect_reset.h
+++ b/src/audio_core/renderer/effect/effect_reset.h
@@ -14,7 +14,7 @@
#include "audio_core/renderer/effect/reverb.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Reset an effect, and create a new one of the given type.
*
@@ -68,4 +68,4 @@ static void ResetEffect(EffectInfoBase* effect, const EffectInfoBase::Type type)
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/effect_result_state.h b/src/audio_core/renderer/effect/effect_result_state.h
index ae096ad69..f4d4b6086 100644
--- a/src/audio_core/renderer/effect/effect_result_state.h
+++ b/src/audio_core/renderer/effect/effect_result_state.h
@@ -7,10 +7,10 @@
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct EffectResultState {
std::array<u8, 0x80> state;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/i3dl2.cpp b/src/audio_core/renderer/effect/i3dl2.cpp
index 960b29cfc..a3c324c1e 100644
--- a/src/audio_core/renderer/effect/i3dl2.cpp
+++ b/src/audio_core/renderer/effect/i3dl2.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/i3dl2.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void I3dl2ReverbInfo::Update(BehaviorInfo::ErrorInfo& error_info,
const InParameterVersion1& in_params, const PoolMapper& pool_mapper) {
@@ -91,4 +91,4 @@ CpuAddr I3dl2ReverbInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/i3dl2.h b/src/audio_core/renderer/effect/i3dl2.h
index 6e3ffd1d4..e0432b4ae 100644
--- a/src/audio_core/renderer/effect/i3dl2.h
+++ b/src/audio_core/renderer/effect/i3dl2.h
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class I3dl2ReverbInfo : public EffectInfoBase {
public:
@@ -198,4 +198,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/light_limiter.cpp b/src/audio_core/renderer/effect/light_limiter.cpp
index 1635a952d..9c8ea3c49 100644
--- a/src/audio_core/renderer/effect/light_limiter.cpp
+++ b/src/audio_core/renderer/effect/light_limiter.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/light_limiter.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void LightLimiterInfo::Update(BehaviorInfo::ErrorInfo& error_info,
const InParameterVersion1& in_params, const PoolMapper& pool_mapper) {
@@ -78,4 +78,4 @@ CpuAddr LightLimiterInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/light_limiter.h b/src/audio_core/renderer/effect/light_limiter.h
index 338d67bbc..7f2ede405 100644
--- a/src/audio_core/renderer/effect/light_limiter.h
+++ b/src/audio_core/renderer/effect/light_limiter.h
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class LightLimiterInfo : public EffectInfoBase {
public:
@@ -135,4 +135,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/reverb.cpp b/src/audio_core/renderer/effect/reverb.cpp
index 2d32383d0..4da72469a 100644
--- a/src/audio_core/renderer/effect/reverb.cpp
+++ b/src/audio_core/renderer/effect/reverb.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/effect/reverb.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void ReverbInfo::Update(BehaviorInfo::ErrorInfo& error_info, const InParameterVersion1& in_params,
const PoolMapper& pool_mapper) {
@@ -90,4 +90,4 @@ CpuAddr ReverbInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/effect/reverb.h b/src/audio_core/renderer/effect/reverb.h
index 6cc345ef6..52a048da6 100644
--- a/src/audio_core/renderer/effect/reverb.h
+++ b/src/audio_core/renderer/effect/reverb.h
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class ReverbInfo : public EffectInfoBase {
public:
@@ -187,4 +187,4 @@ public:
CpuAddr GetWorkbuffer(s32 index) override;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/memory/address_info.h b/src/audio_core/renderer/memory/address_info.h
index bb5c930e1..c81ef1b8a 100644
--- a/src/audio_core/renderer/memory/address_info.h
+++ b/src/audio_core/renderer/memory/address_info.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/memory/memory_pool_info.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Represents a region of mapped or unmapped memory.
@@ -121,4 +121,4 @@ private:
CpuAddr dsp_address;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/memory/memory_pool_info.cpp b/src/audio_core/renderer/memory/memory_pool_info.cpp
index 9b7824af1..03b44d5f3 100644
--- a/src/audio_core/renderer/memory/memory_pool_info.cpp
+++ b/src/audio_core/renderer/memory/memory_pool_info.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/memory/memory_pool_info.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
CpuAddr MemoryPoolInfo::GetCpuAddress() const {
return cpu_address;
@@ -58,4 +58,4 @@ bool MemoryPoolInfo::IsUsed() const {
return in_use;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/memory/memory_pool_info.h b/src/audio_core/renderer/memory/memory_pool_info.h
index 80c571bc1..2f9c85184 100644
--- a/src/audio_core/renderer/memory/memory_pool_info.h
+++ b/src/audio_core/renderer/memory/memory_pool_info.h
@@ -8,7 +8,7 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* CPU pools are mapped in user memory with the supplied process_handle (see PoolMapper).
*/
@@ -167,4 +167,4 @@ private:
bool in_use{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/memory/pool_mapper.cpp b/src/audio_core/renderer/memory/pool_mapper.cpp
index 7fd2b5f47..999bb746b 100644
--- a/src/audio_core/renderer/memory/pool_mapper.cpp
+++ b/src/audio_core/renderer/memory/pool_mapper.cpp
@@ -6,7 +6,7 @@
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
PoolMapper::PoolMapper(u32 process_handle_, bool force_map_)
: process_handle{process_handle_}, force_map{force_map_} {}
@@ -240,4 +240,4 @@ bool PoolMapper::InitializeSystemPool(MemoryPoolInfo& pool, const u8* memory,
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/memory/pool_mapper.h b/src/audio_core/renderer/memory/pool_mapper.h
index 9a691da7a..95ae5d8ea 100644
--- a/src/audio_core/renderer/memory/pool_mapper.h
+++ b/src/audio_core/renderer/memory/pool_mapper.h
@@ -10,7 +10,7 @@
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class AddressInfo;
/**
@@ -176,4 +176,4 @@ private:
bool force_map;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/mix/mix_context.cpp b/src/audio_core/renderer/mix/mix_context.cpp
index 3a18ae7c2..c712610bb 100644
--- a/src/audio_core/renderer/mix/mix_context.cpp
+++ b/src/audio_core/renderer/mix/mix_context.cpp
@@ -7,7 +7,7 @@
#include "audio_core/renderer/splitter/splitter_context.h"
#include "common/polyfill_ranges.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void MixContext::Initialize(std::span<MixInfo*> sorted_mix_infos_, std::span<MixInfo> mix_infos_,
const u32 count_, std::span<s32> effect_process_order_buffer_,
@@ -139,4 +139,4 @@ EdgeMatrix& MixContext::GetEdgeMatrix() {
return edge_matrix;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/mix/mix_context.h b/src/audio_core/renderer/mix/mix_context.h
index bcd9637da..ce19ec8d6 100644
--- a/src/audio_core/renderer/mix/mix_context.h
+++ b/src/audio_core/renderer/mix/mix_context.h
@@ -10,7 +10,7 @@
#include "audio_core/renderer/nodes/node_states.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class SplitterContext;
/*
@@ -121,4 +121,4 @@ private:
EdgeMatrix edge_matrix{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/mix/mix_info.cpp b/src/audio_core/renderer/mix/mix_info.cpp
index cc18e57ee..5e44bde18 100644
--- a/src/audio_core/renderer/mix/mix_info.cpp
+++ b/src/audio_core/renderer/mix/mix_info.cpp
@@ -7,7 +7,7 @@
#include "audio_core/renderer/nodes/edge_matrix.h"
#include "audio_core/renderer/splitter/splitter_context.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
MixInfo::MixInfo(std::span<s32> effect_order_buffer_, s32 effect_count_, BehaviorInfo& behavior)
: effect_order_buffer{effect_order_buffer_}, effect_count{effect_count_},
@@ -117,4 +117,4 @@ bool MixInfo::HasAnyConnection() const {
return dst_mix_id != UnusedMixId || dst_splitter_id != UnusedSplitterId;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/mix/mix_info.h b/src/audio_core/renderer/mix/mix_info.h
index b5fa4c0c7..7005daa4f 100644
--- a/src/audio_core/renderer/mix/mix_info.h
+++ b/src/audio_core/renderer/mix/mix_info.h
@@ -9,7 +9,7 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class EdgeMatrix;
class SplitterContext;
class EffectContext;
@@ -121,4 +121,4 @@ public:
const bool long_size_pre_delay_supported;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/nodes/bit_array.h b/src/audio_core/renderer/nodes/bit_array.h
index b0d53cd51..d8a2d09d0 100644
--- a/src/audio_core/renderer/nodes/bit_array.h
+++ b/src/audio_core/renderer/nodes/bit_array.h
@@ -7,7 +7,7 @@
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Represents an array of bits used for nodes and edges for the mixing graph.
*/
@@ -22,4 +22,4 @@ struct BitArray {
u32 size{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/nodes/edge_matrix.cpp b/src/audio_core/renderer/nodes/edge_matrix.cpp
index 5573f33b9..c28773b22 100644
--- a/src/audio_core/renderer/nodes/edge_matrix.cpp
+++ b/src/audio_core/renderer/nodes/edge_matrix.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/nodes/edge_matrix.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void EdgeMatrix::Initialize([[maybe_unused]] std::span<u8> buffer,
[[maybe_unused]] const u64 node_buffer_size, const u32 count_) {
@@ -35,4 +35,4 @@ u32 EdgeMatrix::GetNodeCount() const {
return count;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/nodes/edge_matrix.h b/src/audio_core/renderer/nodes/edge_matrix.h
index 27a20e43e..0271c23b1 100644
--- a/src/audio_core/renderer/nodes/edge_matrix.h
+++ b/src/audio_core/renderer/nodes/edge_matrix.h
@@ -9,7 +9,7 @@
#include "common/alignment.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* An edge matrix, holding the connections for each node to every other node in the graph.
*/
@@ -79,4 +79,4 @@ private:
u32 count;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/nodes/node_states.cpp b/src/audio_core/renderer/nodes/node_states.cpp
index b7a44a54c..028a58041 100644
--- a/src/audio_core/renderer/nodes/node_states.cpp
+++ b/src/audio_core/renderer/nodes/node_states.cpp
@@ -4,7 +4,7 @@
#include "audio_core/renderer/nodes/node_states.h"
#include "common/logging/log.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void NodeStates::Initialize(std::span<u8> buffer_, [[maybe_unused]] const u64 node_buffer_size,
const u32 count) {
@@ -138,4 +138,4 @@ std::pair<std::span<u32>::reverse_iterator, size_t> NodeStates::GetSortedResuls(
return {results.rbegin(), result_pos};
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/nodes/node_states.h b/src/audio_core/renderer/nodes/node_states.h
index e768cd4b5..991a82841 100644
--- a/src/audio_core/renderer/nodes/node_states.h
+++ b/src/audio_core/renderer/nodes/node_states.h
@@ -10,7 +10,7 @@
#include "common/alignment.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Graph utility functions for sorting and getting results from the DAG.
*/
@@ -192,4 +192,4 @@ private:
Stack stack{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/detail_aspect.cpp b/src/audio_core/renderer/performance/detail_aspect.cpp
index f6405937f..ef8b47cee 100644
--- a/src/audio_core/renderer/performance/detail_aspect.cpp
+++ b/src/audio_core/renderer/performance/detail_aspect.cpp
@@ -5,7 +5,7 @@
#include "audio_core/renderer/command/command_generator.h"
#include "audio_core/renderer/performance/detail_aspect.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
DetailAspect::DetailAspect(CommandGenerator& command_generator_,
const PerformanceEntryType entry_type, const s32 node_id_,
@@ -22,4 +22,4 @@ DetailAspect::DetailAspect(CommandGenerator& command_generator_,
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/detail_aspect.h b/src/audio_core/renderer/performance/detail_aspect.h
index 736c331b9..0bd7f80c8 100644
--- a/src/audio_core/renderer/performance/detail_aspect.h
+++ b/src/audio_core/renderer/performance/detail_aspect.h
@@ -7,7 +7,7 @@
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class CommandGenerator;
/**
@@ -29,4 +29,4 @@ public:
s32 node_id;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/entry_aspect.cpp b/src/audio_core/renderer/performance/entry_aspect.cpp
index dd4165803..c9241a639 100644
--- a/src/audio_core/renderer/performance/entry_aspect.cpp
+++ b/src/audio_core/renderer/performance/entry_aspect.cpp
@@ -5,7 +5,7 @@
#include "audio_core/renderer/command/command_generator.h"
#include "audio_core/renderer/performance/entry_aspect.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
EntryAspect::EntryAspect(CommandGenerator& command_generator_, const PerformanceEntryType type,
const s32 node_id_)
@@ -20,4 +20,4 @@ EntryAspect::EntryAspect(CommandGenerator& command_generator_, const Performance
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/entry_aspect.h b/src/audio_core/renderer/performance/entry_aspect.h
index 14c9e3baf..f99287d68 100644
--- a/src/audio_core/renderer/performance/entry_aspect.h
+++ b/src/audio_core/renderer/performance/entry_aspect.h
@@ -7,7 +7,7 @@
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class CommandGenerator;
/**
@@ -28,4 +28,4 @@ public:
s32 node_id;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_detail.h b/src/audio_core/renderer/performance/performance_detail.h
index f603b9026..2b0cf9422 100644
--- a/src/audio_core/renderer/performance/performance_detail.h
+++ b/src/audio_core/renderer/performance/performance_detail.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/performance/performance_entry.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
enum class PerformanceDetailType : u8 {
Invalid,
@@ -47,4 +47,4 @@ struct PerformanceDetailVersion2 {
static_assert(sizeof(PerformanceDetailVersion2) == 0x18,
"PerformanceDetailVersion2 has the wrong size!");
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_entry.h b/src/audio_core/renderer/performance/performance_entry.h
index d6b1158db..dbd6053a5 100644
--- a/src/audio_core/renderer/performance/performance_entry.h
+++ b/src/audio_core/renderer/performance/performance_entry.h
@@ -5,7 +5,7 @@
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
enum class PerformanceEntryType : u8 {
Invalid,
@@ -34,4 +34,4 @@ struct PerformanceEntryVersion2 {
static_assert(sizeof(PerformanceEntryVersion2) == 0x18,
"PerformanceEntryVersion2 has the wrong size!");
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_entry_addresses.h b/src/audio_core/renderer/performance/performance_entry_addresses.h
index e381d765c..51eee975f 100644
--- a/src/audio_core/renderer/performance/performance_entry_addresses.h
+++ b/src/audio_core/renderer/performance/performance_entry_addresses.h
@@ -5,7 +5,7 @@
#include "audio_core/common/common.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct PerformanceEntryAddresses {
CpuAddr translated_address;
@@ -14,4 +14,4 @@ struct PerformanceEntryAddresses {
CpuAddr entry_processed_time_offset;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_frame_header.h b/src/audio_core/renderer/performance/performance_frame_header.h
index b1848284e..24e4989f8 100644
--- a/src/audio_core/renderer/performance/performance_frame_header.h
+++ b/src/audio_core/renderer/performance/performance_frame_header.h
@@ -5,7 +5,7 @@
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct PerformanceFrameHeaderVersion1 {
/* 0x00 */ u32 magic; // "PERF"
@@ -33,4 +33,4 @@ struct PerformanceFrameHeaderVersion2 {
static_assert(sizeof(PerformanceFrameHeaderVersion2) == 0x30,
"PerformanceFrameHeaderVersion2 has the wrong size!");
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_manager.cpp b/src/audio_core/renderer/performance/performance_manager.cpp
index 8aa0f5ed0..ce736db71 100644
--- a/src/audio_core/renderer/performance/performance_manager.cpp
+++ b/src/audio_core/renderer/performance/performance_manager.cpp
@@ -6,7 +6,7 @@
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_funcs.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void PerformanceManager::CreateImpl(const size_t version) {
switch (version) {
@@ -643,4 +643,4 @@ void PerformanceManagerImpl<PerformanceVersion::Version2, PerformanceFrameHeader
target_node_id = target_node_id_;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/performance/performance_manager.h b/src/audio_core/renderer/performance/performance_manager.h
index b65caa9b6..ffd0fa1fb 100644
--- a/src/audio_core/renderer/performance/performance_manager.h
+++ b/src/audio_core/renderer/performance/performance_manager.h
@@ -14,7 +14,7 @@
#include "audio_core/renderer/performance/performance_frame_header.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class BehaviorInfo;
class MemoryPoolInfo;
@@ -272,4 +272,4 @@ private:
PerformanceVersion version{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp b/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp
index d91f10402..0ede02b6b 100644
--- a/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp
+++ b/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp
@@ -5,7 +5,7 @@
#include "audio_core/renderer/sink/circular_buffer_sink_info.h"
#include "audio_core/renderer/upsampler/upsampler_manager.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
CircularBufferSinkInfo::CircularBufferSinkInfo() {
state.fill(0);
@@ -73,4 +73,4 @@ void CircularBufferSinkInfo::UpdateForCommandGeneration() {
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/circular_buffer_sink_info.h b/src/audio_core/renderer/sink/circular_buffer_sink_info.h
index 3356213ea..d4e61d641 100644
--- a/src/audio_core/renderer/sink/circular_buffer_sink_info.h
+++ b/src/audio_core/renderer/sink/circular_buffer_sink_info.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/sink/sink_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Info for a circular buffer sink.
*/
@@ -38,4 +38,4 @@ public:
static_assert(sizeof(CircularBufferSinkInfo) <= sizeof(SinkInfoBase),
"CircularBufferSinkInfo is too large!");
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/device_sink_info.cpp b/src/audio_core/renderer/sink/device_sink_info.cpp
index b7b3d6f1d..2de05e38e 100644
--- a/src/audio_core/renderer/sink/device_sink_info.cpp
+++ b/src/audio_core/renderer/sink/device_sink_info.cpp
@@ -4,7 +4,7 @@
#include "audio_core/renderer/sink/device_sink_info.h"
#include "audio_core/renderer/upsampler/upsampler_manager.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
DeviceSinkInfo::DeviceSinkInfo() {
state.fill(0);
@@ -54,4 +54,4 @@ void DeviceSinkInfo::Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_
void DeviceSinkInfo::UpdateForCommandGeneration() {}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/device_sink_info.h b/src/audio_core/renderer/sink/device_sink_info.h
index a1c441454..7974ae820 100644
--- a/src/audio_core/renderer/sink/device_sink_info.h
+++ b/src/audio_core/renderer/sink/device_sink_info.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/sink/sink_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Info for a device sink.
*/
@@ -37,4 +37,4 @@ public:
};
static_assert(sizeof(DeviceSinkInfo) <= sizeof(SinkInfoBase), "DeviceSinkInfo is too large!");
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/sink_context.cpp b/src/audio_core/renderer/sink/sink_context.cpp
index 634bc1cf9..a4f9cac21 100644
--- a/src/audio_core/renderer/sink/sink_context.cpp
+++ b/src/audio_core/renderer/sink/sink_context.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/sink/sink_context.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void SinkContext::Initialize(std::span<SinkInfoBase> sink_infos_, const u32 sink_count_) {
sink_infos = sink_infos_;
@@ -18,4 +18,4 @@ u32 SinkContext::GetCount() const {
return sink_count;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/sink_context.h b/src/audio_core/renderer/sink/sink_context.h
index 185572e29..66925b48e 100644
--- a/src/audio_core/renderer/sink/sink_context.h
+++ b/src/audio_core/renderer/sink/sink_context.h
@@ -8,7 +8,7 @@
#include "audio_core/renderer/sink/sink_info_base.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Manages output sinks.
*/
@@ -44,4 +44,4 @@ private:
u32 sink_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/sink_info_base.cpp b/src/audio_core/renderer/sink/sink_info_base.cpp
index 4279beaa0..8a064f15a 100644
--- a/src/audio_core/renderer/sink/sink_info_base.cpp
+++ b/src/audio_core/renderer/sink/sink_info_base.cpp
@@ -4,7 +4,7 @@
#include "audio_core/renderer/memory/pool_mapper.h"
#include "audio_core/renderer/sink/sink_info_base.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
void SinkInfoBase::CleanUp() {
type = Type::Invalid;
@@ -48,4 +48,4 @@ u8* SinkInfoBase::GetParameter() {
return parameter.data();
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/sink/sink_info_base.h b/src/audio_core/renderer/sink/sink_info_base.h
index a1b855f20..e10d1cb38 100644
--- a/src/audio_core/renderer/sink/sink_info_base.h
+++ b/src/audio_core/renderer/sink/sink_info_base.h
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
struct UpsamplerInfo;
class PoolMapper;
@@ -174,4 +174,4 @@ protected:
parameter{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/splitter/splitter_context.cpp b/src/audio_core/renderer/splitter/splitter_context.cpp
index 7a23ba43f..686150ea6 100644
--- a/src/audio_core/renderer/splitter/splitter_context.cpp
+++ b/src/audio_core/renderer/splitter/splitter_context.cpp
@@ -7,7 +7,7 @@
#include "audio_core/renderer/splitter/splitter_context.h"
#include "common/alignment.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
SplitterDestinationData* SplitterContext::GetDesintationData(const s32 splitter_id,
const s32 destination_id) {
@@ -214,4 +214,4 @@ u64 SplitterContext::CalcWorkBufferSize(const BehaviorInfo& behavior,
return size;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/splitter/splitter_context.h b/src/audio_core/renderer/splitter/splitter_context.h
index 1a63db1d3..556e6dcc3 100644
--- a/src/audio_core/renderer/splitter/splitter_context.h
+++ b/src/audio_core/renderer/splitter/splitter_context.h
@@ -13,7 +13,7 @@ namespace AudioCore {
struct AudioRendererParameterInternal;
class WorkbufferAllocator;
-namespace AudioRenderer {
+namespace Renderer {
class BehaviorInfo;
/**
@@ -185,5 +185,5 @@ private:
bool splitter_bug_fixed{};
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/renderer/splitter/splitter_destinations_data.cpp b/src/audio_core/renderer/splitter/splitter_destinations_data.cpp
index b27d44896..5ec37e48e 100644
--- a/src/audio_core/renderer/splitter/splitter_destinations_data.cpp
+++ b/src/audio_core/renderer/splitter/splitter_destinations_data.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/splitter/splitter_destinations_data.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
SplitterDestinationData::SplitterDestinationData(const s32 id_) : id{id_} {}
@@ -84,4 +84,4 @@ void SplitterDestinationData::SetNext(SplitterDestinationData* next_) {
next = next_;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/splitter/splitter_destinations_data.h b/src/audio_core/renderer/splitter/splitter_destinations_data.h
index d55ce0ad3..90edfc667 100644
--- a/src/audio_core/renderer/splitter/splitter_destinations_data.h
+++ b/src/audio_core/renderer/splitter/splitter_destinations_data.h
@@ -9,7 +9,7 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Represents a mixing node, can be connected to a previous and next destination forming a chain
* that a certain mix buffer will pass through to output.
@@ -132,4 +132,4 @@ private:
bool need_update{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/splitter/splitter_info.cpp b/src/audio_core/renderer/splitter/splitter_info.cpp
index 1aee6720b..beb5b7f19 100644
--- a/src/audio_core/renderer/splitter/splitter_info.cpp
+++ b/src/audio_core/renderer/splitter/splitter_info.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/splitter/splitter_info.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
SplitterInfo::SplitterInfo(const s32 id_) : id{id_} {}
@@ -76,4 +76,4 @@ void SplitterInfo::SetDestinations(SplitterDestinationData* destinations_) {
destinations = destinations_;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/splitter/splitter_info.h b/src/audio_core/renderer/splitter/splitter_info.h
index b0ad01fe0..c1e4c2df1 100644
--- a/src/audio_core/renderer/splitter/splitter_info.h
+++ b/src/audio_core/renderer/splitter/splitter_info.h
@@ -6,7 +6,7 @@
#include "audio_core/renderer/splitter/splitter_destinations_data.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Represents a splitter, wraps multiple output destinations to split an input mix into.
*/
@@ -104,4 +104,4 @@ private:
u32 channel_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index 6e07baa54..d29754634 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -4,12 +4,13 @@
#include <chrono>
#include <span>
+#include "audio_core/adsp/apps/audio_renderer/audio_renderer.h"
+#include "audio_core/adsp/apps/audio_renderer/command_buffer.h"
#include "audio_core/audio_core.h"
#include "audio_core/common/audio_renderer_parameter.h"
#include "audio_core/common/common.h"
#include "audio_core/common/feature_support.h"
#include "audio_core/common/workbuffer_allocator.h"
-#include "audio_core/renderer/adsp/adsp.h"
#include "audio_core/renderer/behavior/info_updater.h"
#include "audio_core/renderer/command/command_buffer.h"
#include "audio_core/renderer/command/command_generator.h"
@@ -34,7 +35,7 @@
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/memory.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
u64 System::GetWorkBufferSize(const AudioRendererParameterInternal& params) {
BehaviorInfo behavior;
@@ -95,7 +96,8 @@ u64 System::GetWorkBufferSize(const AudioRendererParameterInternal& params) {
}
System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
- : core{core_}, adsp{core.AudioCore().GetADSP()}, adsp_rendered_event{adsp_rendered_event_} {}
+ : core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()},
+ adsp_rendered_event{adsp_rendered_event_} {}
Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
@@ -443,7 +445,7 @@ void System::Stop() {
Result System::Update(std::span<const u8> input, std::span<u8> performance, std::span<u8> output) {
std::scoped_lock l{lock};
- const auto start_time{core.CoreTiming().GetClockTicks()};
+ const auto start_time{core.CoreTiming().GetGlobalTimeNs().count()};
std::memset(output.data(), 0, output.size());
InfoUpdater info_updater(input, output, process_handle, behavior);
@@ -535,7 +537,7 @@ Result System::Update(std::span<const u8> input, std::span<u8> performance, std:
adsp_rendered_event->Clear();
num_times_updated++;
- const auto end_time{core.CoreTiming().GetClockTicks()};
+ const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()};
ticks_spent_updating += end_time - start_time;
return ResultSuccess;
@@ -583,7 +585,7 @@ void System::SendCommandToDsp() {
if (initialized) {
if (active) {
terminate_event.Reset();
- const auto remaining_command_count{adsp.GetRemainCommandCount(session_id)};
+ const auto remaining_command_count{audio_renderer.GetRemainCommandCount(session_id)};
u64 command_size{0};
if (remaining_command_count) {
@@ -607,26 +609,18 @@ void System::SendCommandToDsp() {
time_limit_percent = 70.0f;
}
- ADSP::CommandBuffer command_buffer{
- .buffer{translated_addr},
- .size{command_size},
- .time_limit{
- static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
- (static_cast<f32>(render_time_limit_percent) / 100.0f))},
- .remaining_command_count{remaining_command_count},
- .reset_buffers{reset_command_buffers},
- .applet_resource_user_id{applet_resource_user_id},
- .render_time_taken{adsp.GetRenderTimeTaken(session_id)},
- };
-
- adsp.SendCommandBuffer(session_id, command_buffer);
+ auto time_limit{
+ static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
+ (static_cast<f32>(render_time_limit_percent) / 100.0f))};
+ audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
+ applet_resource_user_id, reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {
adsp_rendered_event->Signal();
}
} else {
- adsp.ClearRemainCount(session_id);
+ audio_renderer.ClearRemainCommandCount(session_id);
terminate_event.Set();
}
}
@@ -635,7 +629,7 @@ void System::SendCommandToDsp() {
u64 System::GenerateCommand(std::span<u8> in_command_buffer,
[[maybe_unused]] u64 command_buffer_size_) {
PoolMapper::ClearUseState(memory_pool_workbuffer, memory_pool_count);
- const auto start_time{core.CoreTiming().GetClockTicks()};
+ const auto start_time{core.CoreTiming().GetGlobalTimeNs().count()};
auto command_list_header{reinterpret_cast<CommandListHeader*>(in_command_buffer.data())};
@@ -732,10 +726,10 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
effect_context.UpdateStateByDspShared();
}
- const auto end_time{core.CoreTiming().GetClockTicks()};
+ const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()};
total_ticks_elapsed += end_time - start_time;
num_command_lists_generated++;
- render_start_tick = adsp.GetRenderingStartTick(session_id);
+ render_start_tick = audio_renderer.GetRenderingStartTick(session_id);
frames_elapsed++;
return command_buffer.size;
@@ -819,4 +813,4 @@ u32 System::DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time
return voices_dropped;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h
index e328783b6..8a8341710 100644
--- a/src/audio_core/renderer/system.h
+++ b/src/audio_core/renderer/system.h
@@ -34,12 +34,16 @@ class KTransferMemory;
namespace AudioCore {
struct AudioRendererParameterInternal;
-
-namespace AudioRenderer {
-class CommandBuffer;
namespace ADSP {
class ADSP;
+namespace AudioRenderer {
+class AudioRenderer;
}
+} // namespace ADSP
+
+namespace Renderer {
+using namespace ::AudioCore::ADSP;
+class CommandBuffer;
/**
* Audio Renderer System, the main worker for audio rendering.
@@ -213,8 +217,8 @@ public:
private:
/// Core system
Core::System& core;
- /// Reference to the ADSP for communication
- ADSP::ADSP& adsp;
+ /// Reference to the ADSP's AudioRenderer for communication
+ ::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
/// Is this system initialized?
bool initialized{};
/// Is this system currently active?
@@ -319,5 +323,5 @@ private:
f32 drop_voice_param{1.0f};
};
-} // namespace AudioRenderer
+} // namespace Renderer
} // namespace AudioCore
diff --git a/src/audio_core/renderer/system_manager.cpp b/src/audio_core/renderer/system_manager.cpp
index 300ecdbf1..a0b8ef29e 100644
--- a/src/audio_core/renderer/system_manager.cpp
+++ b/src/audio_core/renderer/system_manager.cpp
@@ -3,8 +3,8 @@
#include <chrono>
+#include "audio_core/adsp/adsp.h"
#include "audio_core/audio_core.h"
-#include "audio_core/renderer/adsp/adsp.h"
#include "audio_core/renderer/system_manager.h"
#include "common/microprofile.h"
#include "common/thread.h"
@@ -14,24 +14,21 @@
MICROPROFILE_DEFINE(Audio_RenderSystemManager, "Audio", "Render System Manager",
MP_RGB(60, 19, 97));
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
SystemManager::SystemManager(Core::System& core_)
- : core{core_}, adsp{core.AudioCore().GetADSP()}, mailbox{adsp.GetRenderMailbox()} {}
+ : core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()} {}
SystemManager::~SystemManager() {
Stop();
}
-bool SystemManager::InitializeUnsafe() {
+void SystemManager::InitializeUnsafe() {
if (!active) {
- if (adsp.Start()) {
- active = true;
- thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(stop_token); });
- }
+ active = true;
+ audio_renderer.Start();
+ thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(stop_token); });
}
-
- return adsp.GetState() == ADSP::State::Started;
}
void SystemManager::Stop() {
@@ -41,7 +38,7 @@ void SystemManager::Stop() {
active = false;
thread.request_stop();
thread.join();
- adsp.Stop();
+ audio_renderer.Stop();
}
bool SystemManager::Add(System& system_) {
@@ -55,10 +52,7 @@ bool SystemManager::Add(System& system_) {
{
std::scoped_lock l{mutex1};
if (systems.empty()) {
- if (!InitializeUnsafe()) {
- LOG_ERROR(Service_Audio, "Failed to start the AudioRenderer SystemManager");
- return false;
- }
+ InitializeUnsafe();
}
}
@@ -100,9 +94,9 @@ void SystemManager::ThreadFunc(std::stop_token stop_token) {
}
}
- adsp.Signal();
- adsp.Wait();
+ audio_renderer.Signal();
+ audio_renderer.Wait();
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/system_manager.h b/src/audio_core/renderer/system_manager.h
index 9681fd121..62e8e5f15 100644
--- a/src/audio_core/renderer/system_manager.h
+++ b/src/audio_core/renderer/system_manager.h
@@ -18,11 +18,14 @@ struct EventType;
class System;
} // namespace Core
-namespace AudioCore::AudioRenderer {
-namespace ADSP {
+namespace AudioCore::ADSP {
class ADSP;
-class AudioRenderer_Mailbox;
-} // namespace ADSP
+namespace AudioRenderer {
+class AudioRenderer;
+} // namespace AudioRenderer
+} // namespace AudioCore::ADSP
+
+namespace AudioCore::Renderer {
/**
* Manages all audio renderers, responsible for triggering command list generation and signalling
@@ -38,7 +41,7 @@ public:
*
* @return True if successfully initialized, otherwise false.
*/
- bool InitializeUnsafe();
+ void InitializeUnsafe();
/**
* Stop the system manager.
@@ -80,10 +83,8 @@ private:
std::mutex mutex2{};
/// Is the system manager thread active?
std::atomic<bool> active{};
- /// Reference to the ADSP for communication
- ADSP::ADSP& adsp;
- /// AudioRenderer mailbox for communication
- ADSP::AudioRenderer_Mailbox* mailbox{};
+ /// Reference to the ADSP's AudioRenderer for communication
+ ::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/upsampler/upsampler_info.h b/src/audio_core/renderer/upsampler/upsampler_info.h
index a43c15af3..85c87f137 100644
--- a/src/audio_core/renderer/upsampler/upsampler_info.h
+++ b/src/audio_core/renderer/upsampler/upsampler_info.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/upsampler/upsampler_state.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class UpsamplerManager;
/**
@@ -32,4 +32,4 @@ struct UpsamplerInfo {
std::array<s16, MaxChannels> inputs{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/upsampler/upsampler_manager.cpp b/src/audio_core/renderer/upsampler/upsampler_manager.cpp
index 4c76a5066..ef740f6c9 100644
--- a/src/audio_core/renderer/upsampler/upsampler_manager.cpp
+++ b/src/audio_core/renderer/upsampler/upsampler_manager.cpp
@@ -3,7 +3,7 @@
#include "audio_core/renderer/upsampler/upsampler_manager.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
UpsamplerManager::UpsamplerManager(const u32 count_, std::span<UpsamplerInfo> infos_,
std::span<s32> workbuffer_)
@@ -41,4 +41,4 @@ void UpsamplerManager::Free(UpsamplerInfo* info) {
info->enabled = false;
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/upsampler/upsampler_manager.h b/src/audio_core/renderer/upsampler/upsampler_manager.h
index 83c697c0c..263e5718b 100644
--- a/src/audio_core/renderer/upsampler/upsampler_manager.h
+++ b/src/audio_core/renderer/upsampler/upsampler_manager.h
@@ -9,7 +9,7 @@
#include "audio_core/renderer/upsampler/upsampler_info.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Manages and has utility functions for upsampler infos.
*/
@@ -42,4 +42,4 @@ private:
std::mutex lock{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/upsampler/upsampler_state.h b/src/audio_core/renderer/upsampler/upsampler_state.h
index 28cebe200..dc7b31d42 100644
--- a/src/audio_core/renderer/upsampler/upsampler_state.h
+++ b/src/audio_core/renderer/upsampler/upsampler_state.h
@@ -8,7 +8,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Upsampling state used by the AudioRenderer across calls.
*/
@@ -37,4 +37,4 @@ struct UpsamplerState {
u8 sample_index;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_channel_resource.h b/src/audio_core/renderer/voice/voice_channel_resource.h
index 26ab4ccce..4f19c2fcc 100644
--- a/src/audio_core/renderer/voice/voice_channel_resource.h
+++ b/src/audio_core/renderer/voice/voice_channel_resource.h
@@ -8,7 +8,7 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Represents one channel for mixing a voice.
*/
@@ -35,4 +35,4 @@ public:
bool in_use{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_context.cpp b/src/audio_core/renderer/voice/voice_context.cpp
index 16a3e839d..c3644e38b 100644
--- a/src/audio_core/renderer/voice/voice_context.cpp
+++ b/src/audio_core/renderer/voice/voice_context.cpp
@@ -6,7 +6,7 @@
#include "audio_core/renderer/voice/voice_context.h"
#include "common/polyfill_ranges.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
VoiceState& VoiceContext::GetDspSharedState(const u32 index) {
if (index >= dsp_states.size()) {
@@ -84,4 +84,4 @@ void VoiceContext::UpdateStateByDspShared() {
std::memcpy(cpu_states.data(), dsp_states.data(), voice_count * sizeof(VoiceState));
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_context.h b/src/audio_core/renderer/voice/voice_context.h
index 43b677154..138ab2773 100644
--- a/src/audio_core/renderer/voice/voice_context.h
+++ b/src/audio_core/renderer/voice/voice_context.h
@@ -10,7 +10,7 @@
#include "audio_core/renderer/voice/voice_state.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Contains all voices, with utility functions for managing them.
*/
@@ -123,4 +123,4 @@ private:
u32 active_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_info.cpp b/src/audio_core/renderer/voice/voice_info.cpp
index c0bfb23fc..6239cfab7 100644
--- a/src/audio_core/renderer/voice/voice_info.cpp
+++ b/src/audio_core/renderer/voice/voice_info.cpp
@@ -6,7 +6,7 @@
#include "audio_core/renderer/voice/voice_info.h"
#include "audio_core/renderer/voice/voice_state.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
VoiceInfo::VoiceInfo() {
Initialize();
@@ -405,4 +405,4 @@ void VoiceInfo::ResetResources(VoiceContext& voice_context) const {
}
}
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_info.h b/src/audio_core/renderer/voice/voice_info.h
index 3c5d3e04f..14a687dcb 100644
--- a/src/audio_core/renderer/voice/voice_info.h
+++ b/src/audio_core/renderer/voice/voice_info.h
@@ -12,7 +12,7 @@
#include "audio_core/renderer/memory/address_info.h"
#include "common/common_types.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
class PoolMapper;
class VoiceContext;
struct VoiceState;
@@ -377,4 +377,4 @@ public:
u8 flush_buffer_count{};
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/audio_core/renderer/voice/voice_state.h b/src/audio_core/renderer/voice/voice_state.h
index ce947233f..c7aee167b 100644
--- a/src/audio_core/renderer/voice/voice_state.h
+++ b/src/audio_core/renderer/voice/voice_state.h
@@ -9,7 +9,7 @@
#include "common/common_types.h"
#include "common/fixed_point.h"
-namespace AudioCore::AudioRenderer {
+namespace AudioCore::Renderer {
/**
* Holds a state for a voice. One is kept host-side, and one is used by the AudioRenderer,
* host-side is updated on the next iteration.
@@ -67,4 +67,4 @@ struct VoiceState {
s32 loop_count;
};
-} // namespace AudioCore::AudioRenderer
+} // namespace AudioCore::Renderer
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index bf97d9ba2..34877b461 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -151,6 +151,10 @@ add_library(common STATIC
zstd_compression.h
)
+if (YUZU_ENABLE_PORTABLE)
+ add_compile_definitions(YUZU_ENABLE_PORTABLE)
+endif()
+
if (WIN32)
target_sources(common PRIVATE
windows/timer_resolution.cpp
@@ -191,8 +195,6 @@ if (MSVC)
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
)
target_compile_options(common PRIVATE
- /W4
-
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index d71cfacc6..dce219fcf 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -88,8 +88,9 @@ public:
fs::path yuzu_path_config;
#ifdef _WIN32
+#ifdef YUZU_ENABLE_PORTABLE
yuzu_path = GetExeDirectory() / PORTABLE_DIR;
-
+#endif
if (!IsDir(yuzu_path)) {
yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR;
}
@@ -101,8 +102,9 @@ public:
yuzu_path_cache = yuzu_path / CACHE_DIR;
yuzu_path_config = yuzu_path / CONFIG_DIR;
#else
+#ifdef YUZU_ENABLE_PORTABLE
yuzu_path = GetCurrentDir() / PORTABLE_DIR;
-
+#endif
if (Exists(yuzu_path) && IsDir(yuzu_path)) {
yuzu_path_cache = yuzu_path / CACHE_DIR;
yuzu_path_config = yuzu_path / CONFIG_DIR;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 012648d69..c33910ade 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -584,13 +584,23 @@ add_library(core STATIC
hle/service/lm/lm.h
hle/service/mig/mig.cpp
hle/service/mig/mig.h
+ hle/service/mii/types/char_info.cpp
+ hle/service/mii/types/char_info.h
+ hle/service/mii/types/core_data.cpp
+ hle/service/mii/types/core_data.h
+ hle/service/mii/types/raw_data.cpp
+ hle/service/mii/types/raw_data.h
+ hle/service/mii/types/store_data.cpp
+ hle/service/mii/types/store_data.h
+ hle/service/mii/types/ver3_store_data.cpp
+ hle/service/mii/types/ver3_store_data.h
hle/service/mii/mii.cpp
hle/service/mii/mii.h
hle/service/mii/mii_manager.cpp
hle/service/mii/mii_manager.h
- hle/service/mii/raw_data.cpp
- hle/service/mii/raw_data.h
- hle/service/mii/types.h
+ hle/service/mii/mii_result.h
+ hle/service/mii/mii_types.h
+ hle/service/mii/mii_util.h
hle/service/mm/mm_u.cpp
hle/service/mm/mm_u.h
hle/service/mnpp/mnpp_app.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 2f67e60a9..2d6e61398 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -273,7 +273,8 @@ struct System::Impl {
time_manager.Initialize();
is_powered_on = true;
- exit_lock = false;
+ exit_locked = false;
+ exit_requested = false;
microprofile_cpu[0] = MICROPROFILE_TOKEN(ARM_CPU0);
microprofile_cpu[1] = MICROPROFILE_TOKEN(ARM_CPU1);
@@ -398,12 +399,14 @@ struct System::Impl {
}
is_powered_on = false;
- exit_lock = false;
+ exit_locked = false;
+ exit_requested = false;
if (gpu_core != nullptr) {
gpu_core->NotifyShutdown();
}
+ Network::CancelPendingSocketOperations();
kernel.SuspendApplication(true);
if (services) {
services->KillNVNFlinger();
@@ -425,6 +428,7 @@ struct System::Impl {
debugger.reset();
kernel.Shutdown();
memory.Reset();
+ Network::RestartSocketOperations();
if (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info{};
@@ -507,7 +511,8 @@ struct System::Impl {
CpuManager cpu_manager;
std::atomic_bool is_powered_on{};
- bool exit_lock = false;
+ bool exit_locked = false;
+ bool exit_requested = false;
bool nvdec_active{};
@@ -559,6 +564,8 @@ struct System::Impl {
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
gpu_dirty_memory_write_manager{};
+
+ std::deque<std::vector<u8>> user_channel;
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
@@ -943,12 +950,20 @@ const Service::Time::TimeManager& System::GetTimeManager() const {
return impl->time_manager;
}
-void System::SetExitLock(bool locked) {
- impl->exit_lock = locked;
+void System::SetExitLocked(bool locked) {
+ impl->exit_locked = locked;
+}
+
+bool System::GetExitLocked() const {
+ return impl->exit_locked;
}
-bool System::GetExitLock() const {
- return impl->exit_lock;
+void System::SetExitRequested(bool requested) {
+ impl->exit_requested = requested;
+}
+
+bool System::GetExitRequested() const {
+ return impl->exit_requested;
}
void System::SetApplicationProcessBuildID(const CurrentBuildProcessID& id) {
@@ -1025,6 +1040,10 @@ void System::ExecuteProgram(std::size_t program_index) {
}
}
+std::deque<std::vector<u8>>& System::GetUserChannel() {
+ return impl->user_channel;
+}
+
void System::RegisterExitCallback(ExitCallback&& callback) {
impl->exit_callback = std::move(callback);
}
diff --git a/src/core/core.h b/src/core/core.h
index c70ea1965..fba312125 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -4,6 +4,7 @@
#pragma once
#include <cstddef>
+#include <deque>
#include <functional>
#include <memory>
#include <mutex>
@@ -412,8 +413,11 @@ public:
/// Gets an immutable reference to the Room Network.
[[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const;
- void SetExitLock(bool locked);
- [[nodiscard]] bool GetExitLock() const;
+ void SetExitLocked(bool locked);
+ bool GetExitLocked() const;
+
+ void SetExitRequested(bool requested);
+ bool GetExitRequested() const;
void SetApplicationProcessBuildID(const CurrentBuildProcessID& id);
[[nodiscard]] const CurrentBuildProcessID& GetApplicationProcessBuildID() const;
@@ -456,6 +460,12 @@ public:
*/
void ExecuteProgram(std::size_t program_index);
+ /**
+ * Gets a reference to the user channel stack.
+ * It is used to transfer data between programs.
+ */
+ [[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
+
/// Type used for the frontend to designate a callback for System to exit the application.
using ExitCallback = std::function<void()>;
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 4ff2c50e5..e13c5cdc7 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -35,7 +35,6 @@ namespace Core::Crypto {
namespace {
constexpr u64 CURRENT_CRYPTO_REVISION = 0x5;
-constexpr u64 FULL_TICKET_SIZE = 0x400;
using Common::AsArray;
@@ -156,6 +155,10 @@ u64 GetSignatureTypePaddingSize(SignatureType type) {
UNREACHABLE();
}
+bool Ticket::IsValid() const {
+ return !std::holds_alternative<std::monostate>(data);
+}
+
SignatureType Ticket::GetSignatureType() const {
if (const auto* ticket = std::get_if<RSA4096Ticket>(&data)) {
return ticket->sig_type;
@@ -210,6 +213,54 @@ Ticket Ticket::SynthesizeCommon(Key128 title_key, const std::array<u8, 16>& righ
return Ticket{out};
}
+Ticket Ticket::Read(const FileSys::VirtualFile& file) {
+ // Attempt to read up to the largest ticket size, and make sure we read at least a signature
+ // type.
+ std::array<u8, sizeof(RSA4096Ticket)> raw_data{};
+ auto read_size = file->Read(raw_data.data(), raw_data.size(), 0);
+ if (read_size < sizeof(SignatureType)) {
+ LOG_WARNING(Crypto, "Attempted to read ticket file with invalid size {}.", read_size);
+ return Ticket{std::monostate()};
+ }
+ return Read(std::span{raw_data});
+}
+
+Ticket Ticket::Read(std::span<const u8> raw_data) {
+ // Some tools read only 0x180 bytes of ticket data instead of 0x2C0, so
+ // just make sure we have at least the bare minimum of data to work with.
+ SignatureType sig_type;
+ if (raw_data.size() < sizeof(SignatureType)) {
+ LOG_WARNING(Crypto, "Attempted to parse ticket buffer with invalid size {}.",
+ raw_data.size());
+ return Ticket{std::monostate()};
+ }
+ std::memcpy(&sig_type, raw_data.data(), sizeof(sig_type));
+
+ switch (sig_type) {
+ case SignatureType::RSA_4096_SHA1:
+ case SignatureType::RSA_4096_SHA256: {
+ RSA4096Ticket ticket{};
+ std::memcpy(&ticket, raw_data.data(), sizeof(ticket));
+ return Ticket{ticket};
+ }
+ case SignatureType::RSA_2048_SHA1:
+ case SignatureType::RSA_2048_SHA256: {
+ RSA2048Ticket ticket{};
+ std::memcpy(&ticket, raw_data.data(), sizeof(ticket));
+ return Ticket{ticket};
+ }
+ case SignatureType::ECDSA_SHA1:
+ case SignatureType::ECDSA_SHA256: {
+ ECDSATicket ticket{};
+ std::memcpy(&ticket, raw_data.data(), sizeof(ticket));
+ return Ticket{ticket};
+ }
+ default:
+ LOG_WARNING(Crypto, "Attempted to parse ticket buffer with invalid type {}.", sig_type);
+ return Ticket{std::monostate()};
+ }
+}
+
Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed) {
Key128 out{};
@@ -290,9 +341,9 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
}
}
-RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const {
+void KeyManager::DeriveETicketRSAKey() {
if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) {
- return {};
+ return;
}
const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek);
@@ -304,12 +355,12 @@ RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const {
rsa_1.Transcode(eticket_extended_kek.data() + 0x10, eticket_extended_kek.size() - 0x10,
extended_dec.data(), Op::Decrypt);
- RSAKeyPair<2048> rsa_key{};
- std::memcpy(rsa_key.decryption_key.data(), extended_dec.data(), rsa_key.decryption_key.size());
- std::memcpy(rsa_key.modulus.data(), extended_dec.data() + 0x100, rsa_key.modulus.size());
- std::memcpy(rsa_key.exponent.data(), extended_dec.data() + 0x200, rsa_key.exponent.size());
-
- return rsa_key;
+ std::memcpy(eticket_rsa_keypair.decryption_key.data(), extended_dec.data(),
+ eticket_rsa_keypair.decryption_key.size());
+ std::memcpy(eticket_rsa_keypair.modulus.data(), extended_dec.data() + 0x100,
+ eticket_rsa_keypair.modulus.size());
+ std::memcpy(eticket_rsa_keypair.exponent.data(), extended_dec.data() + 0x200,
+ eticket_rsa_keypair.exponent.size());
}
Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) {
@@ -447,10 +498,12 @@ std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save) {
for (std::size_t offset = 0; offset + 0x4 < buffer.size(); ++offset) {
if (buffer[offset] == 0x4 && buffer[offset + 1] == 0x0 && buffer[offset + 2] == 0x1 &&
buffer[offset + 3] == 0x0) {
- out.emplace_back();
- auto& next = out.back();
- std::memcpy(&next, buffer.data() + offset, sizeof(Ticket));
- offset += FULL_TICKET_SIZE;
+ // NOTE: Assumes ticket blob will only contain RSA-2048 tickets.
+ auto ticket = Ticket::Read(std::span{buffer.data() + offset, sizeof(RSA2048Ticket)});
+ offset += sizeof(RSA2048Ticket);
+ if (ticket.IsValid()) {
+ out.push_back(ticket);
+ }
}
}
@@ -503,25 +556,36 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
return offset;
}
-std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
- const RSAKeyPair<2048>& key) {
+std::optional<Key128> KeyManager::ParseTicketTitleKey(const Ticket& ticket) {
+ if (!ticket.IsValid()) {
+ LOG_WARNING(Crypto, "Attempted to parse title key of invalid ticket.");
+ return std::nullopt;
+ }
+
+ if (ticket.GetData().rights_id == Key128{}) {
+ LOG_WARNING(Crypto, "Attempted to parse title key of ticket with no rights ID.");
+ return std::nullopt;
+ }
+
const auto issuer = ticket.GetData().issuer;
if (IsAllZeroArray(issuer)) {
+ LOG_WARNING(Crypto, "Attempted to parse title key of ticket with invalid issuer.");
return std::nullopt;
}
+
if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') {
- LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority.");
+ LOG_WARNING(Crypto, "Parsing ticket with non-standard certificate authority.");
}
- Key128 rights_id = ticket.GetData().rights_id;
-
- if (rights_id == Key128{}) {
- return std::nullopt;
+ if (ticket.GetData().type == TitleKeyType::Common) {
+ return ticket.GetData().title_key_common;
}
- if (!std::any_of(ticket.GetData().title_key_common_pad.begin(),
- ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) {
- return std::make_pair(rights_id, ticket.GetData().title_key_common);
+ if (eticket_rsa_keypair == RSAKeyPair<2048>{}) {
+ LOG_WARNING(
+ Crypto,
+ "Skipping personalized ticket title key parsing due to missing ETicket RSA key-pair.");
+ return std::nullopt;
}
mbedtls_mpi D; // RSA Private Exponent
@@ -534,9 +598,12 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
mbedtls_mpi_init(&S);
mbedtls_mpi_init(&M);
- mbedtls_mpi_read_binary(&D, key.decryption_key.data(), key.decryption_key.size());
- mbedtls_mpi_read_binary(&N, key.modulus.data(), key.modulus.size());
- mbedtls_mpi_read_binary(&S, ticket.GetData().title_key_block.data(), 0x100);
+ const auto& title_key_block = ticket.GetData().title_key_block;
+ mbedtls_mpi_read_binary(&D, eticket_rsa_keypair.decryption_key.data(),
+ eticket_rsa_keypair.decryption_key.size());
+ mbedtls_mpi_read_binary(&N, eticket_rsa_keypair.modulus.data(),
+ eticket_rsa_keypair.modulus.size());
+ mbedtls_mpi_read_binary(&S, title_key_block.data(), title_key_block.size());
mbedtls_mpi_exp_mod(&M, &S, &D, &N, nullptr);
@@ -564,8 +631,7 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
Key128 key_temp{};
std::memcpy(key_temp.data(), m_2.data() + *offset, key_temp.size());
-
- return std::make_pair(rights_id, key_temp);
+ return key_temp;
}
KeyManager::KeyManager() {
@@ -669,6 +735,14 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti
encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]);
} else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) {
eticket_extended_kek = Common::HexStringToArray<576>(out[1]);
+ } else if (out[0].compare(0, 19, "eticket_rsa_keypair") == 0) {
+ const auto key_data = Common::HexStringToArray<528>(out[1]);
+ std::memcpy(eticket_rsa_keypair.decryption_key.data(), key_data.data(),
+ eticket_rsa_keypair.decryption_key.size());
+ std::memcpy(eticket_rsa_keypair.modulus.data(), key_data.data() + 0x100,
+ eticket_rsa_keypair.modulus.size());
+ std::memcpy(eticket_rsa_keypair.exponent.data(), key_data.data() + 0x200,
+ eticket_rsa_keypair.exponent.size());
} else {
for (const auto& kv : KEYS_VARIABLE_LENGTH) {
if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) {
@@ -1110,56 +1184,38 @@ void KeyManager::DeriveETicket(PartitionDataManager& data,
eticket_extended_kek = data.GetETicketExtendedKek();
WriteKeyToFile(KeyCategory::Console, "eticket_extended_kek", eticket_extended_kek);
+ DeriveETicketRSAKey();
PopulateTickets();
}
void KeyManager::PopulateTickets() {
- const auto rsa_key = GetETicketRSAKey();
-
- if (rsa_key == RSAKeyPair<2048>{}) {
+ if (ticket_databases_loaded) {
return;
}
+ ticket_databases_loaded = true;
- if (!common_tickets.empty() && !personal_tickets.empty()) {
- return;
- }
+ std::vector<Ticket> tickets;
const auto system_save_e1_path =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e1";
-
- const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
+ if (Common::FS::Exists(system_save_e1_path)) {
+ const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read,
+ Common::FS::FileType::BinaryFile};
+ const auto blob1 = GetTicketblob(save_e1);
+ tickets.insert(tickets.end(), blob1.begin(), blob1.end());
+ }
const auto system_save_e2_path =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e2";
+ if (Common::FS::Exists(system_save_e2_path)) {
+ const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read,
+ Common::FS::FileType::BinaryFile};
+ const auto blob2 = GetTicketblob(save_e2);
+ tickets.insert(tickets.end(), blob2.begin(), blob2.end());
+ }
- const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
-
- const auto blob2 = GetTicketblob(save_e2);
- auto res = GetTicketblob(save_e1);
-
- const auto idx = res.size();
- res.insert(res.end(), blob2.begin(), blob2.end());
-
- for (std::size_t i = 0; i < res.size(); ++i) {
- const auto common = i < idx;
- const auto pair = ParseTicket(res[i], rsa_key);
- if (!pair) {
- continue;
- }
-
- const auto& [rid, key] = *pair;
- u128 rights_id;
- std::memcpy(rights_id.data(), rid.data(), rid.size());
-
- if (common) {
- common_tickets[rights_id] = res[i];
- } else {
- personal_tickets[rights_id] = res[i];
- }
-
- SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
+ for (const auto& ticket : tickets) {
+ AddTicket(ticket);
}
}
@@ -1291,41 +1347,33 @@ const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const {
return personal_tickets;
}
-bool KeyManager::AddTicketCommon(Ticket raw) {
- const auto rsa_key = GetETicketRSAKey();
- if (rsa_key == RSAKeyPair<2048>{}) {
- return false;
- }
-
- const auto pair = ParseTicket(raw, rsa_key);
- if (!pair) {
+bool KeyManager::AddTicket(const Ticket& ticket) {
+ if (!ticket.IsValid()) {
+ LOG_WARNING(Crypto, "Attempted to add invalid ticket.");
return false;
}
- const auto& [rid, key] = *pair;
+ const auto& rid = ticket.GetData().rights_id;
u128 rights_id;
std::memcpy(rights_id.data(), rid.data(), rid.size());
- common_tickets[rights_id] = raw;
- SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
- return true;
-}
+ if (ticket.GetData().type == Core::Crypto::TitleKeyType::Common) {
+ common_tickets[rights_id] = ticket;
+ } else {
+ personal_tickets[rights_id] = ticket;
+ }
-bool KeyManager::AddTicketPersonalized(Ticket raw) {
- const auto rsa_key = GetETicketRSAKey();
- if (rsa_key == RSAKeyPair<2048>{}) {
- return false;
+ if (HasKey(S128KeyType::Titlekey, rights_id[1], rights_id[0])) {
+ LOG_DEBUG(Crypto,
+ "Skipping parsing title key from ticket for known rights ID {:016X}{:016X}.",
+ rights_id[1], rights_id[0]);
+ return true;
}
- const auto pair = ParseTicket(raw, rsa_key);
- if (!pair) {
+ const auto key = ParseTicketTitleKey(ticket);
+ if (!key) {
return false;
}
-
- const auto& [rid, key] = *pair;
- u128 rights_id;
- std::memcpy(rights_id.data(), rid.data(), rid.size());
- common_tickets[rights_id] = raw;
- SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
+ SetKey(S128KeyType::Titlekey, key.value(), rights_id[1], rights_id[0]);
return true;
}
} // namespace Core::Crypto
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index 8c864503b..2250eccec 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -7,6 +7,7 @@
#include <filesystem>
#include <map>
#include <optional>
+#include <span>
#include <string>
#include <variant>
@@ -29,8 +30,6 @@ enum class ResultStatus : u16;
namespace Core::Crypto {
-constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180;
-
using Key128 = std::array<u8, 0x10>;
using Key256 = std::array<u8, 0x20>;
using SHA256Hash = std::array<u8, 0x20>;
@@ -82,6 +81,7 @@ struct RSA4096Ticket {
INSERT_PADDING_BYTES(0x3C);
TicketData data;
};
+static_assert(sizeof(RSA4096Ticket) == 0x500, "RSA4096Ticket has incorrect size.");
struct RSA2048Ticket {
SignatureType sig_type;
@@ -89,6 +89,7 @@ struct RSA2048Ticket {
INSERT_PADDING_BYTES(0x3C);
TicketData data;
};
+static_assert(sizeof(RSA2048Ticket) == 0x400, "RSA2048Ticket has incorrect size.");
struct ECDSATicket {
SignatureType sig_type;
@@ -96,16 +97,41 @@ struct ECDSATicket {
INSERT_PADDING_BYTES(0x40);
TicketData data;
};
+static_assert(sizeof(ECDSATicket) == 0x340, "ECDSATicket has incorrect size.");
struct Ticket {
- std::variant<RSA4096Ticket, RSA2048Ticket, ECDSATicket> data;
-
- SignatureType GetSignatureType() const;
- TicketData& GetData();
- const TicketData& GetData() const;
- u64 GetSize() const;
-
+ std::variant<std::monostate, RSA4096Ticket, RSA2048Ticket, ECDSATicket> data;
+
+ [[nodiscard]] bool IsValid() const;
+ [[nodiscard]] SignatureType GetSignatureType() const;
+ [[nodiscard]] TicketData& GetData();
+ [[nodiscard]] const TicketData& GetData() const;
+ [[nodiscard]] u64 GetSize() const;
+
+ /**
+ * Synthesizes a common ticket given a title key and rights ID.
+ *
+ * @param title_key Title key to store in the ticket.
+ * @param rights_id Rights ID the ticket is for.
+ * @return The synthesized common ticket.
+ */
static Ticket SynthesizeCommon(Key128 title_key, const std::array<u8, 0x10>& rights_id);
+
+ /**
+ * Reads a ticket from a file.
+ *
+ * @param file File to read the ticket from.
+ * @return The read ticket. If the ticket data is invalid, Ticket::IsValid() will be false.
+ */
+ static Ticket Read(const FileSys::VirtualFile& file);
+
+ /**
+ * Reads a ticket from a memory buffer.
+ *
+ * @param raw_data Buffer to read the ticket from.
+ * @return The read ticket. If the ticket data is invalid, Ticket::IsValid() will be false.
+ */
+ static Ticket Read(std::span<const u8> raw_data);
};
static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
@@ -264,8 +290,7 @@ public:
const std::map<u128, Ticket>& GetCommonTickets() const;
const std::map<u128, Ticket>& GetPersonalizedTickets() const;
- bool AddTicketCommon(Ticket raw);
- bool AddTicketPersonalized(Ticket raw);
+ bool AddTicket(const Ticket& ticket);
void ReloadKeys();
bool AreKeysLoaded() const;
@@ -279,10 +304,12 @@ private:
// Map from rights ID to ticket
std::map<u128, Ticket> common_tickets;
std::map<u128, Ticket> personal_tickets;
+ bool ticket_databases_loaded = false;
std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{};
std::array<std::array<u8, 0x90>, 0x20> keyblobs{};
std::array<u8, 576> eticket_extended_kek{};
+ RSAKeyPair<2048> eticket_rsa_keypair{};
bool dev_mode;
void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys);
@@ -293,10 +320,13 @@ private:
void DeriveGeneralPurposeKeys(std::size_t crypto_revision);
- RSAKeyPair<2048> GetETicketRSAKey() const;
+ void DeriveETicketRSAKey();
void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
+
+ /// Parses the title key section of a ticket.
+ std::optional<Key128> ParseTicketTitleKey(const Ticket& ticket);
};
Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed);
@@ -311,9 +341,4 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save);
-// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority
-// (offset 0x140-0x144 is zero)
-std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
- const RSAKeyPair<2048>& eticket_extended_key);
-
} // namespace Core::Crypto
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 44e6852fe..7d2f0abb8 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -22,6 +22,10 @@
namespace FileSys {
+static u8 MasterKeyIdForKeyGeneration(u8 key_generation) {
+ return std::max<u8>(key_generation, 1) - 1;
+}
+
NCA::NCA(VirtualFile file_, const NCA* base_nca)
: file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
if (file == nullptr) {
@@ -41,12 +45,17 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
return;
}
+ // Ensure we have the proper key area keys to continue.
+ const u8 master_key_id = MasterKeyIdForKeyGeneration(reader->GetKeyGeneration());
+ if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, reader->GetKeyIndex())) {
+ status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
+ return;
+ }
+
RightsId rights_id{};
reader->GetRightsId(rights_id.data(), rights_id.size());
if (rights_id != RightsId{}) {
// External decryption key required; provide it here.
- const auto key_generation = std::max<s32>(reader->GetKeyGeneration(), 1) - 1;
-
u128 rights_id_u128;
std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id));
@@ -57,12 +66,12 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
return;
}
- if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, key_generation)) {
+ if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
status = Loader::ResultStatus::ErrorMissingTitlekek;
return;
}
- auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, key_generation);
+ auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id);
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB);
cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(),
Core::Crypto::Op::Decrypt);
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp
index 52c78020c..f4a774675 100644
--- a/src/core/file_sys/nca_metadata.cpp
+++ b/src/core/file_sys/nca_metadata.cpp
@@ -45,6 +45,10 @@ CNMT::CNMT(CNMTHeader header_, OptionalHeader opt_header_,
CNMT::~CNMT() = default;
+const CNMTHeader& CNMT::GetHeader() const {
+ return header;
+}
+
u64 CNMT::GetTitleID() const {
return header.title_id;
}
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h
index c59ece010..68e463b5f 100644
--- a/src/core/file_sys/nca_metadata.h
+++ b/src/core/file_sys/nca_metadata.h
@@ -89,6 +89,7 @@ public:
std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_);
~CNMT();
+ const CNMTHeader& GetHeader() const;
u64 GetTitleID() const;
u32 GetTitleVersion() const;
TitleType GetType() const;
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index f70adab82..e33b00d89 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -9,6 +9,7 @@
#include "common/fs/path_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/scope_exit.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/common_funcs.h"
@@ -625,7 +626,7 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
nca->GetTitleId() != title_id) {
// Create fake cnmt for patch to multiprogram application
const auto sub_nca_result =
- InstallEntry(*nca, TitleType::Update, overwrite_if_exists, copy);
+ InstallEntry(*nca, cnmt.GetHeader(), record, overwrite_if_exists, copy);
if (sub_nca_result != InstallResult::Success) {
return sub_nca_result;
}
@@ -672,6 +673,31 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
}
+InstallResult RegisteredCache::InstallEntry(const NCA& nca, const CNMTHeader& base_header,
+ const ContentRecord& base_record,
+ bool overwrite_if_exists, const VfsCopyFunction& copy) {
+ const CNMTHeader header{
+ .title_id = nca.GetTitleId(),
+ .title_version = base_header.title_version,
+ .type = base_header.type,
+ .reserved = {},
+ .table_offset = 0x10,
+ .number_content_entries = 1,
+ .number_meta_entries = 0,
+ .attributes = 0,
+ .reserved2 = {},
+ .is_committed = 0,
+ .required_download_system_version = 0,
+ .reserved3 = {},
+ };
+ const OptionalHeader opt_header{0, 0};
+ const CNMT new_cnmt(header, opt_header, {base_record}, {});
+ if (!RawInstallYuzuMeta(new_cnmt)) {
+ return InstallResult::ErrorMetaFailed;
+ }
+ return RawInstallNCA(nca, copy, overwrite_if_exists, base_record.nca_id);
+}
+
bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
bool removed_data = false;
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index bd7f53eaf..64815a845 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -24,6 +24,7 @@ enum class NCAContentType : u8;
enum class TitleType : u8;
struct ContentRecord;
+struct CNMTHeader;
struct MetaRecord;
class RegisteredCache;
@@ -169,6 +170,10 @@ public:
InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
+ InstallResult InstallEntry(const NCA& nca, const CNMTHeader& base_header,
+ const ContentRecord& base_record, bool overwrite_if_exists = false,
+ const VfsCopyFunction& copy = &VfsRawCopy);
+
// Removes an existing entry based on title id
bool RemoveExistingEntry(u64 title_id) const;
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index e1e89ce2d..68e8ec22f 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -164,24 +164,6 @@ VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType titl
return nullptr;
}
-std::vector<Core::Crypto::Key128> NSP::GetTitlekey() const {
- if (extracted)
- LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
- std::vector<Core::Crypto::Key128> out;
- for (const auto& ticket_file : ticket_files) {
- if (ticket_file == nullptr ||
- ticket_file->GetSize() <
- Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
- continue;
- }
-
- out.emplace_back();
- ticket_file->Read(out.back().data(), out.back().size(),
- Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
- }
- return out;
-}
-
std::vector<VirtualFile> NSP::GetFiles() const {
return pfs->GetFiles();
}
@@ -208,22 +190,11 @@ void NSP::SetTicketKeys(const std::vector<VirtualFile>& files) {
continue;
}
- if (ticket_file->GetSize() <
- Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
+ auto ticket = Core::Crypto::Ticket::Read(ticket_file);
+ if (!keys.AddTicket(ticket)) {
+ LOG_WARNING(Common_Filesystem, "Could not load NSP ticket {}", ticket_file->GetName());
continue;
}
-
- Core::Crypto::Key128 key{};
- ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
-
- // We get the name without the extension in order to create the rights ID.
- std::string name_only(ticket_file->GetName());
- name_only.erase(name_only.size() - 4);
-
- const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
- u128 rights_id;
- std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
- keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
}
}
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h
index 27f97c725..915bffca9 100644
--- a/src/core/file_sys/submission_package.h
+++ b/src/core/file_sys/submission_package.h
@@ -53,7 +53,6 @@ public:
TitleType title_type = TitleType::Application) const;
VirtualFile GetNCAFile(u64 title_id, ContentRecordType type,
TitleType title_type = TitleType::Application) const;
- std::vector<Core::Crypto::Key128> GetTitlekey() const;
std::vector<VirtualFile> GetFiles() const override;
diff --git a/src/core/hle/kernel/k_capabilities.cpp b/src/core/hle/kernel/k_capabilities.cpp
index 90e4e8fb0..e7da7a21d 100644
--- a/src/core/hle/kernel/k_capabilities.cpp
+++ b/src/core/hle/kernel/k_capabilities.cpp
@@ -156,7 +156,6 @@ Result KCapabilities::MapIoPage_(const u32 cap, KPageTable* page_table) {
const u64 phys_addr = MapIoPage{cap}.address.Value() * PageSize;
const size_t num_pages = 1;
const size_t size = num_pages * PageSize;
- R_UNLESS(num_pages != 0, ResultInvalidSize);
R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress);
R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index da33f0e44..f9c4f9678 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -46,7 +46,7 @@ constexpr Result ResultNoMessages{ErrorModule::AM, 3};
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
enum class LaunchParameterKind : u32 {
- ApplicationSpecific = 1,
+ UserChannel = 1,
AccountPreselectedUser = 2,
};
@@ -341,7 +341,7 @@ void ISelfController::Exit(HLERequestContext& ctx) {
void ISelfController::LockExit(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
- system.SetExitLock(true);
+ system.SetExitLocked(true);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -350,10 +350,14 @@ void ISelfController::LockExit(HLERequestContext& ctx) {
void ISelfController::UnlockExit(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
- system.SetExitLock(false);
+ system.SetExitLocked(false);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
+
+ if (system.GetExitRequested()) {
+ system.Exit();
+ }
}
void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
@@ -1514,27 +1518,26 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto kind = rp.PopEnum<LaunchParameterKind>();
- LOG_DEBUG(Service_AM, "called, kind={:08X}", kind);
-
- if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
- const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
- return system.GetFileSystemController().GetBCATDirectory(tid);
- });
- const auto build_id_full = system.GetApplicationProcessBuildID();
- u64 build_id{};
- std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
-
- auto data =
- backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
- if (data.has_value()) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorage>(system, std::move(*data));
- launch_popped_application_specific = true;
+ LOG_INFO(Service_AM, "called, kind={:08X}", kind);
+
+ if (kind == LaunchParameterKind::UserChannel) {
+ auto channel = system.GetUserChannel();
+ if (channel.empty()) {
+ LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(AM::ResultNoDataInChannel);
return;
}
+
+ auto data = channel.back();
+ channel.pop_back();
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IStorage>(system, std::move(data));
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
!launch_popped_account_preselect) {
+ // TODO: Verify this is hw-accurate
LaunchParameterAccountPreselectedUser params{};
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
@@ -1546,7 +1549,6 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
params.current_user = *uuid;
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
rb.Push(ResultSuccess);
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
@@ -1554,12 +1556,11 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
launch_popped_account_preselect = true;
- return;
+ } else {
+ LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(AM::ResultNoDataInChannel);
}
-
- LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultNoDataInChannel);
}
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
@@ -1851,14 +1852,22 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
}
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
+ LOG_DEBUG(Service_AM, "called");
+
+ system.GetUserChannel().clear();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
+ LOG_DEBUG(Service_AM, "called");
+
+ IPC::RequestParser rp{ctx};
+ const auto storage = rp.PopIpcInterface<IStorage>().lock();
+ if (storage) {
+ system.GetUserChannel().push_back(storage->GetData());
+ }
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index d68998f04..f75a665b2 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -339,7 +339,6 @@ private:
KernelHelpers::ServiceContext service_context;
- bool launch_popped_application_specific = false;
bool launch_popped_account_preselect = false;
s32 previous_program_index{-1};
Kernel::KEvent* gpu_error_detected_event;
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index d1f652c09..350a90818 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -85,15 +85,18 @@ void MiiEdit::Execute() {
break;
case MiiEditAppletMode::CreateMii:
case MiiEditAppletMode::EditMii: {
- Service::Mii::MiiManager mii_manager;
+ Mii::CharInfo char_info{};
+ Mii::StoreData store_data{};
+ store_data.BuildBase(Mii::Gender::Male);
+ char_info.SetFromStoreData(store_data);
- const MiiEditCharInfo char_info{
+ const MiiEditCharInfo edit_char_info{
.mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
? applet_input_v4.char_info.mii_info
- : mii_manager.BuildDefault(0)},
+ : char_info},
};
- MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
+ MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
break;
}
default:
diff --git a/src/core/hle/service/am/applets/applet_mii_edit_types.h b/src/core/hle/service/am/applets/applet_mii_edit_types.h
index 4705d019f..f3d764073 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit_types.h
+++ b/src/core/hle/service/am/applets/applet_mii_edit_types.h
@@ -7,7 +7,8 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
-#include "core/hle/service/mii/types.h"
+#include "common/uuid.h"
+#include "core/hle/service/mii/types/char_info.h"
namespace Service::AM::Applets {
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 526a39130..56fee4591 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -220,7 +220,7 @@ AudInU::AudInU(Core::System& system_)
AudInU::~AudInU() = default;
void AudInU::ListAudioIns(HLERequestContext& ctx) {
- using namespace AudioCore::AudioRenderer;
+ using namespace AudioCore::Renderer;
LOG_DEBUG(Service_Audio, "called");
@@ -240,7 +240,7 @@ void AudInU::ListAudioIns(HLERequestContext& ctx) {
}
void AudInU::ListAudioInsAutoFiltered(HLERequestContext& ctx) {
- using namespace AudioCore::AudioRenderer;
+ using namespace AudioCore::Renderer;
LOG_DEBUG(Service_Audio, "called");
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 23f84a29f..ca683d72c 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -228,7 +228,7 @@ AudOutU::AudOutU(Core::System& system_)
AudOutU::~AudOutU() = default;
void AudOutU::ListAudioOuts(HLERequestContext& ctx) {
- using namespace AudioCore::AudioRenderer;
+ using namespace AudioCore::Renderer;
std::scoped_lock l{impl->mutex};
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index b723b65c8..2f09cade5 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -26,7 +26,7 @@
#include "core/hle/service/ipc_helpers.h"
#include "core/memory.h"
-using namespace AudioCore::AudioRenderer;
+using namespace AudioCore::Renderer;
namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index d8e9c8719..3d7993a16 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -28,7 +28,7 @@ private:
void GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx);
KernelHelpers::ServiceContext service_context;
- std::unique_ptr<AudioCore::AudioRenderer::Manager> impl;
+ std::unique_ptr<AudioCore::Renderer::Manager> impl;
u32 num_audio_devices{0};
};
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index 446f46b3c..9eaae4c4b 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -122,20 +122,18 @@ private:
}
void ImportTicket(HLERequestContext& ctx) {
- const auto ticket = ctx.ReadBuffer();
+ const auto raw_ticket = ctx.ReadBuffer();
[[maybe_unused]] const auto cert = ctx.ReadBuffer(1);
- if (ticket.size() < sizeof(Core::Crypto::Ticket)) {
+ if (raw_ticket.size() < sizeof(Core::Crypto::Ticket)) {
LOG_ERROR(Service_ETicket, "The input buffer is not large enough!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERROR_INVALID_ARGUMENT);
return;
}
- Core::Crypto::Ticket raw{};
- std::memcpy(&raw, ticket.data(), sizeof(Core::Crypto::Ticket));
-
- if (!keys.AddTicketPersonalized(raw)) {
+ Core::Crypto::Ticket ticket = Core::Crypto::Ticket::Read(raw_ticket);
+ if (!keys.AddTicket(ticket)) {
LOG_ERROR(Service_ETicket, "The ticket could not be imported!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERROR_INVALID_ARGUMENT);
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 65c11a2f3..3b83c5ed7 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -7,17 +7,16 @@
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mii/mii_manager.h"
+#include "core/hle/service/mii/mii_result.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
namespace Service::Mii {
-constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
-
class IDatabaseService final : public ServiceFramework<IDatabaseService> {
public:
- explicit IDatabaseService(Core::System& system_)
- : ServiceFramework{system_, "IDatabaseService"} {
+ explicit IDatabaseService(Core::System& system_, bool is_system_)
+ : ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IDatabaseService::IsUpdated, "IsUpdated"},
@@ -54,34 +53,27 @@ public:
}
private:
- template <typename T>
- std::vector<u8> SerializeArray(const std::vector<T>& values) {
- std::vector<u8> out(values.size() * sizeof(T));
- std::size_t offset{};
- for (const auto& value : values) {
- std::memcpy(out.data() + offset, &value, sizeof(T));
- offset += sizeof(T);
- }
- return out;
- }
-
void IsUpdated(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+ const bool is_updated = manager.IsUpdated(metadata, source_flag);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter));
+ rb.Push<u8>(is_updated);
}
void IsFullDatabase(HLERequestContext& ctx) {
LOG_DEBUG(Service_Mii, "called");
+ const bool is_full_database = manager.IsFullDatabase();
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.Push(manager.IsFullDatabase());
+ rb.Push<u8>(is_full_database);
}
void GetCount(HLERequestContext& ctx) {
@@ -90,57 +82,63 @@ private:
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+ const u32 mii_count = manager.GetCount(metadata, source_flag);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.Push<u32>(manager.GetCount(source_flag));
+ rb.Push(mii_count);
}
void Get(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
+ const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
- LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+ LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
+
+ u32 mii_count{};
+ std::vector<CharInfoElement> char_info_elements(output_size);
+ Result result = manager.Get(metadata, char_info_elements, mii_count, source_flag);
- const auto default_miis{manager.GetDefault(source_flag)};
- if (default_miis.size() > 0) {
- ctx.WriteBuffer(SerializeArray(default_miis));
+ if (mii_count != 0) {
+ ctx.WriteBuffer(char_info_elements);
}
IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(default_miis.size()));
+ rb.Push(result);
+ rb.Push(mii_count);
}
void Get1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
+ const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
- LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+ LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
- const auto default_miis{manager.GetDefault(source_flag)};
+ u32 mii_count{};
+ std::vector<CharInfo> char_info(output_size);
+ Result result = manager.Get(metadata, char_info, mii_count, source_flag);
- std::vector<CharInfo> values;
- for (const auto& element : default_miis) {
- values.emplace_back(element.info);
+ if (mii_count != 0) {
+ ctx.WriteBuffer(char_info);
}
- ctx.WriteBuffer(SerializeArray(values));
-
IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(default_miis.size()));
+ rb.Push(result);
+ rb.Push(mii_count);
}
void UpdateLatest(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto info{rp.PopRaw<CharInfo>()};
+ const auto char_info{rp.PopRaw<CharInfo>()};
const auto source_flag{rp.PopRaw<SourceFlag>()};
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
CharInfo new_char_info{};
- const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)};
- if (result != ResultSuccess) {
+ const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag);
+ if (result.IsFailure()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
return;
@@ -153,7 +151,6 @@ private:
void BuildRandom(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
-
const auto age{rp.PopRaw<Age>()};
const auto gender{rp.PopRaw<Gender>()};
const auto race{rp.PopRaw<Race>()};
@@ -162,47 +159,48 @@ private:
if (age > Age::All) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ARGUMENT);
- LOG_ERROR(Service_Mii, "invalid age={}", age);
+ rb.Push(ResultInvalidArgument);
return;
}
if (gender > Gender::All) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ARGUMENT);
- LOG_ERROR(Service_Mii, "invalid gender={}", gender);
+ rb.Push(ResultInvalidArgument);
return;
}
if (race > Race::All) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ARGUMENT);
- LOG_ERROR(Service_Mii, "invalid race={}", race);
+ rb.Push(ResultInvalidArgument);
return;
}
+ CharInfo char_info{};
+ manager.BuildRandom(char_info, age, gender, race);
+
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
- rb.PushRaw<CharInfo>(manager.BuildRandom(age, gender, race));
+ rb.PushRaw<CharInfo>(char_info);
}
void BuildDefault(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index{rp.Pop<u32>()};
- LOG_DEBUG(Service_Mii, "called with index={}", index);
+ LOG_INFO(Service_Mii, "called with index={}", index);
if (index > 5) {
- LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
- index);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ARGUMENT);
+ rb.Push(ResultInvalidArgument);
return;
}
+ CharInfo char_info{};
+ manager.BuildDefault(char_info, index);
+
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
- rb.PushRaw<CharInfo>(manager.BuildDefault(index));
+ rb.PushRaw<CharInfo>(char_info);
}
void GetIndex(HLERequestContext& ctx) {
@@ -211,19 +209,21 @@ private:
LOG_DEBUG(Service_Mii, "called");
- u32 index{};
+ s32 index{};
+ const auto result = manager.GetIndex(metadata, info, index);
+
IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(manager.GetIndex(info, index));
+ rb.Push(result);
rb.Push(index);
}
void SetInterfaceVersion(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- current_interface_version = rp.PopRaw<u32>();
+ const auto interface_version{rp.PopRaw<u32>()};
- LOG_DEBUG(Service_Mii, "called, interface_version={:08X}", current_interface_version);
+ LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
- UNIMPLEMENTED_IF(current_interface_version != 1);
+ manager.SetInterfaceVersion(metadata, interface_version);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -231,30 +231,27 @@ private:
void Convert(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
-
const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
LOG_INFO(Service_Mii, "called");
+ CharInfo char_info{};
+ manager.ConvertV3ToCharInfo(char_info, mii_v3);
+
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
- rb.PushRaw<CharInfo>(manager.ConvertV3ToCharInfo(mii_v3));
- }
-
- constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
- return current_interface_version >= interface_version;
+ rb.PushRaw<CharInfo>(char_info);
}
- MiiManager manager;
-
- u32 current_interface_version{};
- u64 current_update_counter{};
+ MiiManager manager{};
+ DatabaseSessionMetadata metadata{};
+ bool is_system{};
};
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
public:
- explicit MiiDBModule(Core::System& system_, const char* name_)
- : ServiceFramework{system_, name_} {
+ explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_)
+ : ServiceFramework{system_, name_}, is_system{is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
@@ -268,10 +265,12 @@ private:
void GetDatabaseService(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDatabaseService>(system);
+ rb.PushIpcInterface<IDatabaseService>(system, is_system);
LOG_DEBUG(Service_Mii, "called");
}
+
+ bool is_system{};
};
class MiiImg final : public ServiceFramework<MiiImg> {
@@ -303,8 +302,10 @@ public:
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e"));
- server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u"));
+ server_manager->RegisterNamedService("mii:e",
+ std::make_shared<MiiDBModule>(system, "mii:e", true));
+ server_manager->RegisterNamedService("mii:u",
+ std::make_shared<MiiDBModule>(system, "mii:u", false));
server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 46125d473..292d63777 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -10,386 +10,24 @@
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/mii/mii_manager.h"
-#include "core/hle/service/mii/raw_data.h"
+#include "core/hle/service/mii/mii_result.h"
+#include "core/hle/service/mii/mii_util.h"
+#include "core/hle/service/mii/types/core_data.h"
+#include "core/hle/service/mii/types/raw_data.h"
namespace Service::Mii {
-
-namespace {
-
-constexpr Result ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
-
-constexpr std::size_t BaseMiiCount{2};
constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
-constexpr MiiStoreData::Name DefaultMiiName{u'y', u'u', u'z', u'u'};
-constexpr std::array<u8, 8> HairColorLookup{8, 1, 2, 3, 4, 5, 6, 7};
-constexpr std::array<u8, 6> EyeColorLookup{8, 9, 10, 11, 12, 13};
-constexpr std::array<u8, 5> MouthColorLookup{19, 20, 21, 22, 23};
-constexpr std::array<u8, 7> GlassesColorLookup{8, 14, 15, 16, 17, 18, 0};
-constexpr std::array<u8, 62> EyeRotateLookup{
- {0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
- 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
- 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04}};
-constexpr std::array<u8, 24> EyebrowRotateLookup{{0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07,
- 0x04, 0x07, 0x06, 0x08, 0x05, 0x05, 0x06, 0x06,
- 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05}};
-
-template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
-std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
- std::array<T, DestArraySize> out{};
- std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
- return out;
-}
-
-CharInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
- MiiStoreBitFields bf;
- std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
-
- return {
- .uuid = data.data.uuid,
- .name = ResizeArray<char16_t, 10, 11>(data.data.name),
- .font_region = static_cast<u8>(bf.font_region.Value()),
- .favorite_color = static_cast<u8>(bf.favorite_color.Value()),
- .gender = static_cast<u8>(bf.gender.Value()),
- .height = static_cast<u8>(bf.height.Value()),
- .build = static_cast<u8>(bf.build.Value()),
- .type = static_cast<u8>(bf.type.Value()),
- .region_move = static_cast<u8>(bf.region_move.Value()),
- .faceline_type = static_cast<u8>(bf.faceline_type.Value()),
- .faceline_color = static_cast<u8>(bf.faceline_color.Value()),
- .faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()),
- .faceline_make = static_cast<u8>(bf.faceline_makeup.Value()),
- .hair_type = static_cast<u8>(bf.hair_type.Value()),
- .hair_color = static_cast<u8>(bf.hair_color.Value()),
- .hair_flip = static_cast<u8>(bf.hair_flip.Value()),
- .eye_type = static_cast<u8>(bf.eye_type.Value()),
- .eye_color = static_cast<u8>(bf.eye_color.Value()),
- .eye_scale = static_cast<u8>(bf.eye_scale.Value()),
- .eye_aspect = static_cast<u8>(bf.eye_aspect.Value()),
- .eye_rotate = static_cast<u8>(bf.eye_rotate.Value()),
- .eye_x = static_cast<u8>(bf.eye_x.Value()),
- .eye_y = static_cast<u8>(bf.eye_y.Value()),
- .eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()),
- .eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()),
- .eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()),
- .eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()),
- .eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()),
- .eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()),
- .eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3),
- .nose_type = static_cast<u8>(bf.nose_type.Value()),
- .nose_scale = static_cast<u8>(bf.nose_scale.Value()),
- .nose_y = static_cast<u8>(bf.nose_y.Value()),
- .mouth_type = static_cast<u8>(bf.mouth_type.Value()),
- .mouth_color = static_cast<u8>(bf.mouth_color.Value()),
- .mouth_scale = static_cast<u8>(bf.mouth_scale.Value()),
- .mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()),
- .mouth_y = static_cast<u8>(bf.mouth_y.Value()),
- .beard_color = static_cast<u8>(bf.beard_color.Value()),
- .beard_type = static_cast<u8>(bf.beard_type.Value()),
- .mustache_type = static_cast<u8>(bf.mustache_type.Value()),
- .mustache_scale = static_cast<u8>(bf.mustache_scale.Value()),
- .mustache_y = static_cast<u8>(bf.mustache_y.Value()),
- .glasses_type = static_cast<u8>(bf.glasses_type.Value()),
- .glasses_color = static_cast<u8>(bf.glasses_color.Value()),
- .glasses_scale = static_cast<u8>(bf.glasses_scale.Value()),
- .glasses_y = static_cast<u8>(bf.glasses_y.Value()),
- .mole_type = static_cast<u8>(bf.mole_type.Value()),
- .mole_scale = static_cast<u8>(bf.mole_scale.Value()),
- .mole_x = static_cast<u8>(bf.mole_x.Value()),
- .mole_y = static_cast<u8>(bf.mole_y.Value()),
- .padding = 0,
- };
-}
-
-u16 GenerateCrc16(const void* data, std::size_t size) {
- s32 crc{};
- for (std::size_t i = 0; i < size; i++) {
- crc ^= static_cast<const u8*>(data)[i] << 8;
- for (std::size_t j = 0; j < 8; j++) {
- crc <<= 1;
- if ((crc & 0x10000) != 0) {
- crc = (crc ^ 0x1021) & 0xFFFF;
- }
- }
- }
- return Common::swap16(static_cast<u16>(crc));
-}
-
-template <typename T>
-T GetRandomValue(T min, T max) {
- std::random_device device;
- std::mt19937 gen(device());
- std::uniform_int_distribution<u64> distribution(static_cast<u64>(min), static_cast<u64>(max));
- return static_cast<T>(distribution(gen));
-}
-
-template <typename T>
-T GetRandomValue(T max) {
- return GetRandomValue<T>({}, max);
-}
-
-MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
- MiiStoreBitFields bf{};
-
- if (gender == Gender::All) {
- gender = GetRandomValue<Gender>(Gender::Maximum);
- }
-
- bf.gender.Assign(gender);
- bf.favorite_color.Assign(GetRandomValue<u8>(11));
- bf.region_move.Assign(0);
- bf.font_region.Assign(FontRegion::Standard);
- bf.type.Assign(0);
- bf.height.Assign(64);
- bf.build.Assign(64);
-
- if (age == Age::All) {
- const auto temp{GetRandomValue<int>(10)};
- if (temp >= 8) {
- age = Age::Old;
- } else if (temp >= 4) {
- age = Age::Normal;
- } else {
- age = Age::Young;
- }
- }
-
- if (race == Race::All) {
- const auto temp{GetRandomValue<int>(10)};
- if (temp >= 8) {
- race = Race::Black;
- } else if (temp >= 4) {
- race = Race::White;
- } else {
- race = Race::Asian;
- }
- }
-
- u32 axis_y{};
- if (gender == Gender::Female && age == Age::Young) {
- axis_y = GetRandomValue<u32>(3);
- }
-
- const std::size_t index{3 * static_cast<std::size_t>(age) +
- 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
-
- const auto faceline_type_info{RawData::RandomMiiFaceline.at(index)};
- const auto faceline_color_info{RawData::RandomMiiFacelineColor.at(
- 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
- const auto faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
- const auto faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
- const auto hair_type_info{RawData::RandomMiiHairType.at(index)};
- const auto hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
- static_cast<std::size_t>(age))};
- const auto eye_type_info{RawData::RandomMiiEyeType.at(index)};
- const auto eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
- const auto eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
- const auto nose_type_info{RawData::RandomMiiNoseType.at(index)};
- const auto mouth_type_info{RawData::RandomMiiMouthType.at(index)};
- const auto glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
-
- bf.faceline_type.Assign(
- faceline_type_info.values[GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
- bf.faceline_color.Assign(
- faceline_color_info.values[GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
- bf.faceline_wrinkle.Assign(
- faceline_wrinkle_info
- .values[GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
- bf.faceline_makeup.Assign(
- faceline_makeup_info
- .values[GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
-
- bf.hair_type.Assign(
- hair_type_info.values[GetRandomValue<std::size_t>(hair_type_info.values_count)]);
- bf.hair_color.Assign(
- HairColorLookup[hair_color_info
- .values[GetRandomValue<std::size_t>(hair_color_info.values_count)]]);
- bf.hair_flip.Assign(GetRandomValue<HairFlip>(HairFlip::Maximum));
-
- bf.eye_type.Assign(
- eye_type_info.values[GetRandomValue<std::size_t>(eye_type_info.values_count)]);
-
- const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
- const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
- const auto eye_rotate_offset{32 - EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
- const auto eye_rotate{32 - EyeRotateLookup[bf.eye_type]};
-
- bf.eye_color.Assign(
- EyeColorLookup[eye_color_info
- .values[GetRandomValue<std::size_t>(eye_color_info.values_count)]]);
- bf.eye_scale.Assign(4);
- bf.eye_aspect.Assign(3);
- bf.eye_rotate.Assign(eye_rotate_offset - eye_rotate);
- bf.eye_x.Assign(2);
- bf.eye_y.Assign(axis_y + 12);
-
- bf.eyebrow_type.Assign(
- eyebrow_type_info.values[GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
-
- const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
- const auto eyebrow_y{race == Race::Asian ? 9 : 10};
- const auto eyebrow_rotate_offset{32 - EyebrowRotateLookup[eyebrow_rotate_1] + 6};
- const auto eyebrow_rotate{
- 32 - EyebrowRotateLookup[static_cast<std::size_t>(bf.eyebrow_type.Value())]};
-
- bf.eyebrow_color.Assign(bf.hair_color);
- bf.eyebrow_scale.Assign(4);
- bf.eyebrow_aspect.Assign(3);
- bf.eyebrow_rotate.Assign(eyebrow_rotate_offset - eyebrow_rotate);
- bf.eyebrow_x.Assign(2);
- bf.eyebrow_y.Assign(axis_y + eyebrow_y);
-
- const auto nose_scale{gender == Gender::Female ? 3 : 4};
-
- bf.nose_type.Assign(
- nose_type_info.values[GetRandomValue<std::size_t>(nose_type_info.values_count)]);
- bf.nose_scale.Assign(nose_scale);
- bf.nose_y.Assign(axis_y + 9);
-
- const auto mouth_color{gender == Gender::Female ? GetRandomValue<int>(4) : 0};
-
- bf.mouth_type.Assign(
- mouth_type_info.values[GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
- bf.mouth_color.Assign(MouthColorLookup[mouth_color]);
- bf.mouth_scale.Assign(4);
- bf.mouth_aspect.Assign(3);
- bf.mouth_y.Assign(axis_y + 13);
-
- bf.beard_color.Assign(bf.hair_color);
- bf.mustache_scale.Assign(4);
-
- if (gender == Gender::Male && age != Age::Young && GetRandomValue<int>(10) < 2) {
- const auto mustache_and_beard_flag{
- GetRandomValue<BeardAndMustacheFlag>(BeardAndMustacheFlag::All)};
-
- auto beard_type{BeardType::None};
- auto mustache_type{MustacheType::None};
-
- if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
- BeardAndMustacheFlag::Beard) {
- beard_type = GetRandomValue<BeardType>(BeardType::Beard1, BeardType::Beard5);
- }
-
- if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
- BeardAndMustacheFlag::Mustache) {
- mustache_type =
- GetRandomValue<MustacheType>(MustacheType::Mustache1, MustacheType::Mustache5);
- }
-
- bf.mustache_type.Assign(mustache_type);
- bf.beard_type.Assign(beard_type);
- bf.mustache_y.Assign(10);
- } else {
- bf.mustache_type.Assign(MustacheType::None);
- bf.beard_type.Assign(BeardType::None);
- bf.mustache_y.Assign(axis_y + 10);
- }
-
- const auto glasses_type_start{GetRandomValue<std::size_t>(100)};
- u8 glasses_type{};
- while (glasses_type_start < glasses_type_info.values[glasses_type]) {
- if (++glasses_type >= glasses_type_info.values_count) {
- ASSERT(false);
- break;
- }
- }
-
- bf.glasses_type.Assign(glasses_type);
- bf.glasses_color.Assign(GlassesColorLookup[0]);
- bf.glasses_scale.Assign(4);
- bf.glasses_y.Assign(axis_y + 10);
-
- bf.mole_type.Assign(0);
- bf.mole_scale.Assign(4);
- bf.mole_x.Assign(2);
- bf.mole_y.Assign(20);
-
- return {DefaultMiiName, bf, user_id};
-}
-
-MiiStoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
- MiiStoreBitFields bf{};
-
- bf.font_region.Assign(info.font_region);
- bf.favorite_color.Assign(info.favorite_color);
- bf.gender.Assign(info.gender);
- bf.height.Assign(info.height);
- bf.build.Assign(info.weight);
- bf.type.Assign(info.type);
- bf.region_move.Assign(info.region);
- bf.faceline_type.Assign(info.face_type);
- bf.faceline_color.Assign(info.face_color);
- bf.faceline_wrinkle.Assign(info.face_wrinkle);
- bf.faceline_makeup.Assign(info.face_makeup);
- bf.hair_type.Assign(info.hair_type);
- bf.hair_color.Assign(HairColorLookup[info.hair_color]);
- bf.hair_flip.Assign(static_cast<HairFlip>(info.hair_flip));
- bf.eye_type.Assign(info.eye_type);
- bf.eye_color.Assign(EyeColorLookup[info.eye_color]);
- bf.eye_scale.Assign(info.eye_scale);
- bf.eye_aspect.Assign(info.eye_aspect);
- bf.eye_rotate.Assign(info.eye_rotate);
- bf.eye_x.Assign(info.eye_x);
- bf.eye_y.Assign(info.eye_y);
- bf.eyebrow_type.Assign(info.eyebrow_type);
- bf.eyebrow_color.Assign(HairColorLookup[info.eyebrow_color]);
- bf.eyebrow_scale.Assign(info.eyebrow_scale);
- bf.eyebrow_aspect.Assign(info.eyebrow_aspect);
- bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
- bf.eyebrow_x.Assign(info.eyebrow_x);
- bf.eyebrow_y.Assign(info.eyebrow_y - 3);
- bf.nose_type.Assign(info.nose_type);
- bf.nose_scale.Assign(info.nose_scale);
- bf.nose_y.Assign(info.nose_y);
- bf.mouth_type.Assign(info.mouth_type);
- bf.mouth_color.Assign(MouthColorLookup[info.mouth_color]);
- bf.mouth_scale.Assign(info.mouth_scale);
- bf.mouth_aspect.Assign(info.mouth_aspect);
- bf.mouth_y.Assign(info.mouth_y);
- bf.beard_color.Assign(HairColorLookup[info.beard_color]);
- bf.beard_type.Assign(static_cast<BeardType>(info.beard_type));
- bf.mustache_type.Assign(static_cast<MustacheType>(info.mustache_type));
- bf.mustache_scale.Assign(info.mustache_scale);
- bf.mustache_y.Assign(info.mustache_y);
- bf.glasses_type.Assign(info.glasses_type);
- bf.glasses_color.Assign(GlassesColorLookup[info.glasses_color]);
- bf.glasses_scale.Assign(info.glasses_scale);
- bf.glasses_y.Assign(info.glasses_y);
- bf.mole_type.Assign(info.mole_type);
- bf.mole_scale.Assign(info.mole_scale);
- bf.mole_x.Assign(info.mole_x);
- bf.mole_y.Assign(info.mole_y);
-
- return {DefaultMiiName, bf, user_id};
-}
-
-} // namespace
-
-MiiStoreData::MiiStoreData() = default;
-
-MiiStoreData::MiiStoreData(const MiiStoreData::Name& name, const MiiStoreBitFields& bit_fields,
- const Common::UUID& user_id) {
- data.name = name;
- data.uuid = Common::UUID::MakeRandomRFC4122V4();
-
- std::memcpy(data.data.data(), &bit_fields, sizeof(MiiStoreBitFields));
- data_crc = GenerateCrc16(data.data.data(), sizeof(data));
- device_crc = GenerateCrc16(&user_id, sizeof(Common::UUID));
-}
+MiiManager::MiiManager() {}
-MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
-
-bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
+bool MiiManager::IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
return false;
}
- const bool result{current_update_counter != update_counter};
-
- current_update_counter = update_counter;
-
- return result;
+ const auto metadata_update_counter = metadata.update_counter;
+ metadata.update_counter = update_counter;
+ return metadata_update_counter != update_counter;
}
bool MiiManager::IsFullDatabase() const {
@@ -397,301 +35,138 @@ bool MiiManager::IsFullDatabase() const {
return false;
}
-u32 MiiManager::GetCount(SourceFlag source_flag) const {
- std::size_t count{};
+u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
+ u32 mii_count{};
+ if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
+ mii_count += DefaultMiiCount;
+ }
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
// TODO(bunnei): We don't implement the Mii database, but when we do, update this
- count += 0;
}
- if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
- count += (DefaultMiiCount - BaseMiiCount);
- }
- return static_cast<u32>(count);
+ return mii_count;
}
-Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) {
+Result MiiManager::UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
+ const CharInfo& char_info, SourceFlag source_flag) {
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
- return ERROR_CANNOT_FIND_ENTRY;
+ return ResultNotFound;
}
// TODO(bunnei): We don't implement the Mii database, so we can't have an entry
- return ERROR_CANNOT_FIND_ENTRY;
+ return ResultNotFound;
}
-CharInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
- return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
+void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
+ StoreData store_data{};
+ store_data.BuildDefault(index);
+ out_char_info.SetFromStoreData(store_data);
}
-CharInfo MiiManager::BuildDefault(std::size_t index) {
- return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::DefaultMii.at(index), user_id));
+void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
+ StoreData store_data{};
+ store_data.BuildBase(gender);
+ out_char_info.SetFromStoreData(store_data);
}
-CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
- Service::Mii::MiiManager manager;
- auto mii = manager.BuildDefault(0);
-
- if (!ValidateV3Info(mii_v3)) {
- return mii;
- }
-
- // TODO: We are ignoring a bunch of data from the mii_v3
-
- mii.gender = static_cast<u8>(mii_v3.mii_information.gender);
- mii.favorite_color = static_cast<u8>(mii_v3.mii_information.favorite_color);
- mii.height = mii_v3.height;
- mii.build = mii_v3.build;
-
- // Copy name until string terminator
- mii.name = {};
- for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
- mii.name[index] = mii_v3.mii_name[index];
- if (mii.name[index] == 0) {
- break;
- }
- }
-
- mii.font_region = mii_v3.region_information.character_set;
-
- mii.faceline_type = mii_v3.appearance_bits1.face_shape;
- mii.faceline_color = mii_v3.appearance_bits1.skin_color;
- mii.faceline_wrinkle = mii_v3.appearance_bits2.wrinkles;
- mii.faceline_make = mii_v3.appearance_bits2.makeup;
-
- mii.hair_type = mii_v3.hair_style;
- mii.hair_color = mii_v3.appearance_bits3.hair_color;
- mii.hair_flip = mii_v3.appearance_bits3.flip_hair;
-
- mii.eye_type = static_cast<u8>(mii_v3.appearance_bits4.eye_type);
- mii.eye_color = static_cast<u8>(mii_v3.appearance_bits4.eye_color);
- mii.eye_scale = static_cast<u8>(mii_v3.appearance_bits4.eye_scale);
- mii.eye_aspect = static_cast<u8>(mii_v3.appearance_bits4.eye_vertical_stretch);
- mii.eye_rotate = static_cast<u8>(mii_v3.appearance_bits4.eye_rotation);
- mii.eye_x = static_cast<u8>(mii_v3.appearance_bits4.eye_spacing);
- mii.eye_y = static_cast<u8>(mii_v3.appearance_bits4.eye_y_position);
-
- mii.eyebrow_type = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_style);
- mii.eyebrow_color = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_color);
- mii.eyebrow_scale = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_scale);
- mii.eyebrow_aspect = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_yscale);
- mii.eyebrow_rotate = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_rotation);
- mii.eyebrow_x = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_spacing);
- mii.eyebrow_y = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_y_position);
-
- mii.nose_type = static_cast<u8>(mii_v3.appearance_bits6.nose_type);
- mii.nose_scale = static_cast<u8>(mii_v3.appearance_bits6.nose_scale);
- mii.nose_y = static_cast<u8>(mii_v3.appearance_bits6.nose_y_position);
-
- mii.mouth_type = static_cast<u8>(mii_v3.appearance_bits7.mouth_type);
- mii.mouth_color = static_cast<u8>(mii_v3.appearance_bits7.mouth_color);
- mii.mouth_scale = static_cast<u8>(mii_v3.appearance_bits7.mouth_scale);
- mii.mouth_aspect = static_cast<u8>(mii_v3.appearance_bits7.mouth_horizontal_stretch);
- mii.mouth_y = static_cast<u8>(mii_v3.appearance_bits8.mouth_y_position);
-
- mii.mustache_type = static_cast<u8>(mii_v3.appearance_bits8.mustache_type);
- mii.mustache_scale = static_cast<u8>(mii_v3.appearance_bits9.mustache_scale);
- mii.mustache_y = static_cast<u8>(mii_v3.appearance_bits9.mustache_y_position);
-
- mii.beard_type = static_cast<u8>(mii_v3.appearance_bits9.bear_type);
- mii.beard_color = static_cast<u8>(mii_v3.appearance_bits9.facial_hair_color);
-
- mii.glasses_type = static_cast<u8>(mii_v3.appearance_bits10.glasses_type);
- mii.glasses_color = static_cast<u8>(mii_v3.appearance_bits10.glasses_color);
- mii.glasses_scale = static_cast<u8>(mii_v3.appearance_bits10.glasses_scale);
- mii.glasses_y = static_cast<u8>(mii_v3.appearance_bits10.glasses_y_position);
-
- mii.mole_type = static_cast<u8>(mii_v3.appearance_bits11.mole_enabled);
- mii.mole_scale = static_cast<u8>(mii_v3.appearance_bits11.mole_scale);
- mii.mole_x = static_cast<u8>(mii_v3.appearance_bits11.mole_x_position);
- mii.mole_y = static_cast<u8>(mii_v3.appearance_bits11.mole_y_position);
-
- // TODO: Validate mii data
-
- return mii;
+void MiiManager::BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const {
+ StoreData store_data{};
+ store_data.BuildRandom(age, gender, race);
+ out_char_info.SetFromStoreData(store_data);
}
-Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const {
- Service::Mii::MiiManager manager;
- Ver3StoreData mii_v3{};
-
- // TODO: We are ignoring a bunch of data from the mii_v3
-
- mii_v3.version = 1;
- mii_v3.mii_information.gender.Assign(mii.gender);
- mii_v3.mii_information.favorite_color.Assign(mii.favorite_color);
- mii_v3.height = mii.height;
- mii_v3.build = mii.build;
+void MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
+ StoreData store_data{};
+ mii_v3.BuildToStoreData(store_data);
+ out_char_info.SetFromStoreData(store_data);
+}
- // Copy name until string terminator
- mii_v3.mii_name = {};
- for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
- mii_v3.mii_name[index] = mii.name[index];
- if (mii_v3.mii_name[index] == 0) {
- break;
- }
+Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
+ std::span<CharInfoElement> out_elements, u32& out_count,
+ SourceFlag source_flag) {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return BuildDefault(out_elements, out_count, source_flag);
}
- mii_v3.region_information.character_set.Assign(mii.font_region);
+ // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
- mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type);
- mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle);
- mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make);
+ // Include default Mii at the end of the list
+ return BuildDefault(out_elements, out_count, source_flag);
+}
- mii_v3.hair_style = mii.hair_type;
- mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip);
+Result MiiManager::Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
+ u32& out_count, SourceFlag source_flag) {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return BuildDefault(out_char_info, out_count, source_flag);
+ }
- mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type);
- mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale);
- mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect);
- mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate);
- mii_v3.appearance_bits4.eye_spacing.Assign(mii.eye_x);
- mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y);
+ // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
- mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type);
- mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale);
- mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect);
- mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate);
- mii_v3.appearance_bits5.eyebrow_spacing.Assign(mii.eyebrow_x);
- mii_v3.appearance_bits5.eyebrow_y_position.Assign(mii.eyebrow_y);
+ // Include default Mii at the end of the list
+ return BuildDefault(out_char_info, out_count, source_flag);
+}
- mii_v3.appearance_bits6.nose_type.Assign(mii.nose_type);
- mii_v3.appearance_bits6.nose_scale.Assign(mii.nose_scale);
- mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y);
+Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
+ SourceFlag source_flag) {
+ if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+ return ResultSuccess;
+ }
- mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type);
- mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale);
- mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect);
- mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y);
+ StoreData store_data{};
- mii_v3.appearance_bits8.mustache_type.Assign(mii.mustache_type);
- mii_v3.appearance_bits9.mustache_scale.Assign(mii.mustache_scale);
- mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y);
+ for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+ if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
- mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type);
+ store_data.BuildDefault(static_cast<u32>(index));
- mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale);
- mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y);
+ out_elements[out_count].source = Source::Default;
+ out_elements[out_count].char_info.SetFromStoreData(store_data);
+ out_count++;
+ }
- mii_v3.appearance_bits11.mole_enabled.Assign(mii.mole_type);
- mii_v3.appearance_bits11.mole_scale.Assign(mii.mole_scale);
- mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x);
- mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y);
+ return ResultSuccess;
+}
- // These types are converted to V3 from a table
- mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]);
- mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]);
- mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]);
- mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]);
- mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]);
- mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]);
- mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]);
- mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]);
+Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_count,
+ SourceFlag source_flag) {
+ if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+ return ResultSuccess;
+ }
- mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16));
+ StoreData store_data{};
- // TODO: Validate mii_v3 data
+ for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+ if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
- return mii_v3;
-}
+ store_data.BuildDefault(static_cast<u32>(index));
-NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const {
- return {
- .faceline_color = static_cast<u8>(mii.faceline_color & 0xf),
- .hair_color = static_cast<u8>(mii.hair_color & 0x7f),
- .eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
- .eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
- .mouth_color = static_cast<u8>(mii.mouth_color & 0x7f),
- .beard_color = static_cast<u8>(mii.beard_color & 0x7f),
- .glass_color = static_cast<u8>(mii.glasses_color & 0x7f),
- .glass_type = static_cast<u8>(mii.glasses_type & 0x1f),
- };
-}
+ out_char_info[out_count].SetFromStoreData(store_data);
+ out_count++;
+ }
-bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
- bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
-
- is_valid = is_valid && (mii_v3.mii_name[0] != 0);
-
- is_valid = is_valid && (mii_v3.mii_information.birth_month < 13);
- is_valid = is_valid && (mii_v3.mii_information.birth_day < 32);
- is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12);
- is_valid = is_valid && (mii_v3.height < 128);
- is_valid = is_valid && (mii_v3.build < 128);
-
- is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12);
- is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7);
- is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12);
- is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12);
-
- is_valid = is_valid && (mii_v3.hair_style < 132);
- is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8);
-
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13);
- is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19);
-
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12);
- is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19);
-
- is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18);
- is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9);
- is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19);
-
- is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36);
- is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5);
- is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9);
- is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7);
- is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19);
-
- is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6);
- is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7);
- is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17);
-
- is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6);
- is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8);
-
- is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9);
- is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6);
- is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8);
- is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21);
-
- is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2);
- is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9);
- is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17);
- is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31);
-
- return is_valid;
+ return ResultSuccess;
}
-std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) {
- std::vector<MiiInfoElement> result;
+Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
+ s32& out_index) {
- if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
- return result;
+ if (char_info.Verify() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
}
- for (std::size_t index = BaseMiiCount; index < DefaultMiiCount; index++) {
- result.emplace_back(BuildDefault(index), Source::Default);
- }
-
- return result;
-}
-
-Result MiiManager::GetIndex([[maybe_unused]] const CharInfo& info, u32& index) {
constexpr u32 INVALID_INDEX{0xFFFFFFFF};
- index = INVALID_INDEX;
+ out_index = INVALID_INDEX;
// TODO(bunnei): We don't implement the Mii database, so we can't have an index
- return ERROR_CANNOT_FIND_ENTRY;
+ return ResultNotFound;
+}
+
+void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) {
+ metadata.interface_version = version;
}
} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index 45c2be3c8..a2e7a6d73 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -6,7 +6,10 @@
#include <vector>
#include "core/hle/result.h"
-#include "core/hle/service/mii/types.h"
+#include "core/hle/service/mii/mii_types.h"
+#include "core/hle/service/mii/types/char_info.h"
+#include "core/hle/service/mii/types/store_data.h"
+#include "core/hle/service/mii/types/ver3_store_data.h"
namespace Service::Mii {
@@ -16,25 +19,30 @@ class MiiManager {
public:
MiiManager();
- bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
- bool IsFullDatabase() const;
- u32 GetCount(SourceFlag source_flag) const;
- Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag);
- CharInfo BuildRandom(Age age, Gender gender, Race race);
- CharInfo BuildDefault(std::size_t index);
- CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
- bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
- std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag);
- Result GetIndex(const CharInfo& info, u32& index);
-
- // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
- Ver3StoreData BuildFromStoreData(const CharInfo& mii) const;
+ bool IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
- // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData
- NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const;
+ bool IsFullDatabase() const;
+ u32 GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
+ Result UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
+ const CharInfo& char_info, SourceFlag source_flag);
+ Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfoElement> out_elements,
+ u32& out_count, SourceFlag source_flag);
+ Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
+ u32& out_count, SourceFlag source_flag);
+ void BuildDefault(CharInfo& out_char_info, u32 index) const;
+ void BuildBase(CharInfo& out_char_info, Gender gender) const;
+ void BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const;
+ void ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const;
+ std::vector<CharInfoElement> GetDefault(SourceFlag source_flag);
+ Result GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
+ s32& out_index);
+ void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version);
private:
- const Common::UUID user_id{};
+ Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
+ SourceFlag source_flag);
+ Result BuildDefault(std::span<CharInfo> out_char_info, u32& out_count, SourceFlag source_flag);
+
u64 update_counter{};
};
diff --git a/src/core/hle/service/mii/mii_result.h b/src/core/hle/service/mii/mii_result.h
new file mode 100644
index 000000000..021cb76da
--- /dev/null
+++ b/src/core/hle/service/mii/mii_result.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::Mii {
+
+constexpr Result ResultInvalidArgument{ErrorModule::Mii, 1};
+constexpr Result ResultInvalidArgumentSize{ErrorModule::Mii, 2};
+constexpr Result ResultNotUpdated{ErrorModule::Mii, 3};
+constexpr Result ResultNotFound{ErrorModule::Mii, 4};
+constexpr Result ResultDatabaseFull{ErrorModule::Mii, 5};
+constexpr Result ResultInvalidCharInfo{ErrorModule::Mii, 100};
+constexpr Result ResultInvalidStoreData{ErrorModule::Mii, 109};
+constexpr Result ResultInvalidOperation{ErrorModule::Mii, 202};
+constexpr Result ResultPermissionDenied{ErrorModule::Mii, 203};
+
+}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_types.h b/src/core/hle/service/mii/mii_types.h
new file mode 100644
index 000000000..95476f745
--- /dev/null
+++ b/src/core/hle/service/mii/mii_types.h
@@ -0,0 +1,694 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <array>
+#include <type_traits>
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/uuid.h"
+
+namespace Service::Mii {
+
+constexpr u8 MaxHeight = 127;
+constexpr u8 MaxBuild = 127;
+constexpr u8 MaxType = 1;
+constexpr u8 MaxRegionMove = 3;
+constexpr u8 MaxEyeScale = 7;
+constexpr u8 MaxEyeAspect = 6;
+constexpr u8 MaxEyeRotate = 7;
+constexpr u8 MaxEyeX = 12;
+constexpr u8 MaxEyeY = 18;
+constexpr u8 MaxEyebrowScale = 8;
+constexpr u8 MaxEyebrowAspect = 6;
+constexpr u8 MaxEyebrowRotate = 11;
+constexpr u8 MaxEyebrowX = 12;
+constexpr u8 MaxEyebrowY = 18;
+constexpr u8 MaxNoseScale = 8;
+constexpr u8 MaxNoseY = 18;
+constexpr u8 MaxMouthScale = 8;
+constexpr u8 MaxMoutAspect = 6;
+constexpr u8 MaxMouthY = 18;
+constexpr u8 MaxMustacheScale = 8;
+constexpr u8 MasMustacheY = 16;
+constexpr u8 MaxGlassScale = 7;
+constexpr u8 MaxGlassY = 20;
+constexpr u8 MaxMoleScale = 8;
+constexpr u8 MaxMoleX = 16;
+constexpr u8 MaxMoleY = 30;
+constexpr u8 MaxVer3CommonColor = 7;
+constexpr u8 MaxVer3GlassType = 8;
+
+enum class Age : u8 {
+ Young,
+ Normal,
+ Old,
+ All, // Default
+
+ Max = All,
+};
+
+enum class Gender : u8 {
+ Male,
+ Female,
+ All, // Default
+
+ Max = Female,
+};
+
+enum class Race : u8 {
+ Black,
+ White,
+ Asian,
+ All, // Default
+
+ Max = All,
+};
+
+enum class HairType : u8 {
+ NormalLong, // Default
+ NormalShort,
+ NormalMedium,
+ NormalExtraLong,
+ NormalLongBottom,
+ NormalTwoPeaks,
+ PartingLong,
+ FrontLock,
+ PartingShort,
+ PartingExtraLongCurved,
+ PartingExtraLong,
+ PartingMiddleLong,
+ PartingSquared,
+ PartingLongBottom,
+ PeaksTop,
+ PeaksSquared,
+ PartingPeaks,
+ PeaksLongBottom,
+ Peaks,
+ PeaksRounded,
+ PeaksSide,
+ PeaksMedium,
+ PeaksLong,
+ PeaksRoundedLong,
+ PartingFrontPeaks,
+ PartingLongFront,
+ PartingLongRounded,
+ PartingFrontPeaksLong,
+ PartingExtraLongRounded,
+ LongRounded,
+ NormalUnknown1,
+ NormalUnknown2,
+ NormalUnknown3,
+ NormalUnknown4,
+ NormalUnknown5,
+ NormalUnknown6,
+ DreadLocks,
+ PlatedMats,
+ Caps,
+ Afro,
+ PlatedMatsLong,
+ Beanie,
+ Short,
+ ShortTopLongSide,
+ ShortUnknown1,
+ ShortUnknown2,
+ MilitaryParting,
+ Military,
+ ShortUnknown3,
+ ShortUnknown4,
+ ShortUnknown5,
+ ShortUnknown6,
+ NoneTop,
+ None,
+ LongUnknown1,
+ LongUnknown2,
+ LongUnknown3,
+ LongUnknown4,
+ LongUnknown5,
+ LongUnknown6,
+ LongUnknown7,
+ LongUnknown8,
+ LongUnknown9,
+ LongUnknown10,
+ LongUnknown11,
+ LongUnknown12,
+ LongUnknown13,
+ LongUnknown14,
+ LongUnknown15,
+ LongUnknown16,
+ LongUnknown17,
+ LongUnknown18,
+ LongUnknown19,
+ LongUnknown20,
+ LongUnknown21,
+ LongUnknown22,
+ LongUnknown23,
+ LongUnknown24,
+ LongUnknown25,
+ LongUnknown26,
+ LongUnknown27,
+ LongUnknown28,
+ LongUnknown29,
+ LongUnknown30,
+ LongUnknown31,
+ LongUnknown32,
+ LongUnknown33,
+ LongUnknown34,
+ LongUnknown35,
+ LongUnknown36,
+ LongUnknown37,
+ LongUnknown38,
+ LongUnknown39,
+ LongUnknown40,
+ LongUnknown41,
+ LongUnknown42,
+ LongUnknown43,
+ LongUnknown44,
+ LongUnknown45,
+ LongUnknown46,
+ LongUnknown47,
+ LongUnknown48,
+ LongUnknown49,
+ LongUnknown50,
+ LongUnknown51,
+ LongUnknown52,
+ LongUnknown53,
+ LongUnknown54,
+ LongUnknown55,
+ LongUnknown56,
+ LongUnknown57,
+ LongUnknown58,
+ LongUnknown59,
+ LongUnknown60,
+ LongUnknown61,
+ LongUnknown62,
+ LongUnknown63,
+ LongUnknown64,
+ LongUnknown65,
+ LongUnknown66,
+ TwoMediumFrontStrandsOneLongBackPonyTail,
+ TwoFrontStrandsLongBackPonyTail,
+ PartingFrontTwoLongBackPonyTails,
+ TwoFrontStrandsOneLongBackPonyTail,
+ LongBackPonyTail,
+ LongFrontTwoLongBackPonyTails,
+ StrandsTwoShortSidedPonyTails,
+ TwoMediumSidedPonyTails,
+ ShortFrontTwoBackPonyTails,
+ TwoShortSidedPonyTails,
+ TwoLongSidedPonyTails,
+ LongFrontTwoBackPonyTails,
+
+ Max = LongFrontTwoBackPonyTails,
+};
+
+enum class MoleType : u8 {
+ None, // Default
+ OneDot,
+
+ Max = OneDot,
+};
+
+enum class HairFlip : u8 {
+ Left, // Default
+ Right,
+
+ Max = Right,
+};
+
+enum class CommonColor : u8 {
+ // For simplicity common colors aren't listed
+ Max = 99,
+ Count = 100,
+};
+
+enum class FavoriteColor : u8 {
+ Red, // Default
+ Orange,
+ Yellow,
+ LimeGreen,
+ Green,
+ Blue,
+ LightBlue,
+ Pink,
+ Purple,
+ Brown,
+ White,
+ Black,
+
+ Max = Black,
+};
+
+enum class EyeType : u8 {
+ Normal, // Default
+ NormalLash,
+ WhiteLash,
+ WhiteNoBottom,
+ OvalAngledWhite,
+ AngryWhite,
+ DotLashType1,
+ Line,
+ DotLine,
+ OvalWhite,
+ RoundedWhite,
+ NormalShadow,
+ CircleWhite,
+ Circle,
+ CircleWhiteStroke,
+ NormalOvalNoBottom,
+ NormalOvalLarge,
+ NormalRoundedNoBottom,
+ SmallLash,
+ Small,
+ TwoSmall,
+ NormalLongLash,
+ WhiteTwoLashes,
+ WhiteThreeLashes,
+ DotAngry,
+ DotAngled,
+ Oval,
+ SmallWhite,
+ WhiteAngledNoBottom,
+ WhiteAngledNoLeft,
+ SmallWhiteTwoLashes,
+ LeafWhiteLash,
+ WhiteLargeNoBottom,
+ Dot,
+ DotLashType2,
+ DotThreeLashes,
+ WhiteOvalTop,
+ WhiteOvalBottom,
+ WhiteOvalBottomFlat,
+ WhiteOvalTwoLashes,
+ WhiteOvalThreeLashes,
+ WhiteOvalNoBottomTwoLashes,
+ DotWhite,
+ WhiteOvalTopFlat,
+ WhiteThinLeaf,
+ StarThreeLashes,
+ LineTwoLashes,
+ CrowsFeet,
+ WhiteNoBottomFlat,
+ WhiteNoBottomRounded,
+ WhiteSmallBottomLine,
+ WhiteNoBottomLash,
+ WhiteNoPartialBottomLash,
+ WhiteOvalBottomLine,
+ WhiteNoBottomLashTopLine,
+ WhiteNoPartialBottomTwoLashes,
+ NormalTopLine,
+ WhiteOvalLash,
+ RoundTired,
+ WhiteLarge,
+
+ Max = WhiteLarge,
+};
+
+enum class MouthType : u8 {
+ Neutral, // Default
+ NeutralLips,
+ Smile,
+ SmileStroke,
+ SmileTeeth,
+ LipsSmall,
+ LipsLarge,
+ Wave,
+ WaveAngrySmall,
+ NeutralStrokeLarge,
+ TeethSurprised,
+ LipsExtraLarge,
+ LipsUp,
+ NeutralDown,
+ Surprised,
+ TeethMiddle,
+ NeutralStroke,
+ LipsExtraSmall,
+ Malicious,
+ LipsDual,
+ NeutralComma,
+ NeutralUp,
+ TeethLarge,
+ WaveAngry,
+ LipsSexy,
+ SmileInverted,
+ LipsSexyOutline,
+ SmileRounded,
+ LipsTeeth,
+ NeutralOpen,
+ TeethRounded,
+ WaveAngrySmallInverted,
+ NeutralCommaInverted,
+ TeethFull,
+ SmileDownLine,
+ Kiss,
+
+ Max = Kiss,
+};
+
+enum class FontRegion : u8 {
+ Standard, // Default
+ China,
+ Korea,
+ Taiwan,
+
+ Max = Taiwan,
+};
+
+enum class FacelineType : u8 {
+ Sharp, // Default
+ Rounded,
+ SharpRounded,
+ SharpRoundedSmall,
+ Large,
+ LargeRounded,
+ SharpSmall,
+ Flat,
+ Bump,
+ Angular,
+ FlatRounded,
+ AngularSmall,
+
+ Max = AngularSmall,
+};
+
+enum class FacelineColor : u8 {
+ Beige, // Default
+ WarmBeige,
+ Natural,
+ Honey,
+ Chestnut,
+ Porcelain,
+ Ivory,
+ WarmIvory,
+ Almond,
+ Espresso,
+
+ Max = Espresso,
+ Count = Max + 1,
+};
+
+enum class FacelineWrinkle : u8 {
+ None, // Default
+ TearTroughs,
+ FacialPain,
+ Cheeks,
+ Folds,
+ UnderTheEyes,
+ SplitChin,
+ Chin,
+ BrowDroop,
+ MouthFrown,
+ CrowsFeet,
+ FoldsCrowsFrown,
+
+ Max = FoldsCrowsFrown,
+};
+
+enum class FacelineMake : u8 {
+ None, // Default
+ CheekPorcelain,
+ CheekNatural,
+ EyeShadowBlue,
+ CheekBlushPorcelain,
+ CheekBlushNatural,
+ CheekPorcelainEyeShadowBlue,
+ CheekPorcelainEyeShadowNatural,
+ CheekBlushPorcelainEyeShadowEspresso,
+ Freckles,
+ LionsManeBeard,
+ StubbleBeard,
+
+ Max = StubbleBeard,
+};
+
+enum class EyebrowType : u8 {
+ FlatAngledLarge, // Default
+ LowArchRoundedThin,
+ SoftAngledLarge,
+ MediumArchRoundedThin,
+ RoundedMedium,
+ LowArchMedium,
+ RoundedThin,
+ UpThin,
+ MediumArchRoundedMedium,
+ RoundedLarge,
+ UpLarge,
+ FlatAngledLargeInverted,
+ MediumArchFlat,
+ AngledThin,
+ HorizontalLarge,
+ HighArchFlat,
+ Flat,
+ MediumArchLarge,
+ LowArchThin,
+ RoundedThinInverted,
+ HighArchLarge,
+ Hairy,
+ Dotted,
+ None,
+
+ Max = None,
+};
+
+enum class NoseType : u8 {
+ Normal, // Default
+ Rounded,
+ Dot,
+ Arrow,
+ Roman,
+ Triangle,
+ Button,
+ RoundedInverted,
+ Potato,
+ Grecian,
+ Snub,
+ Aquiline,
+ ArrowLeft,
+ RoundedLarge,
+ Hooked,
+ Fat,
+ Droopy,
+ ArrowLarge,
+
+ Max = ArrowLarge,
+};
+
+enum class BeardType : u8 {
+ None,
+ Goatee,
+ GoateeLong,
+ LionsManeLong,
+ LionsMane,
+ Full,
+
+ Min = Goatee,
+ Max = Full,
+};
+
+enum class MustacheType : u8 {
+ None,
+ Walrus,
+ Pencil,
+ Horseshoe,
+ Normal,
+ Toothbrush,
+
+ Min = Walrus,
+ Max = Toothbrush,
+};
+
+enum class GlassType : u8 {
+ None,
+ Oval,
+ Wayfarer,
+ Rectangle,
+ TopRimless,
+ Rounded,
+ Oversized,
+ CatEye,
+ Square,
+ BottomRimless,
+ SemiOpaqueRounded,
+ SemiOpaqueCatEye,
+ SemiOpaqueOval,
+ SemiOpaqueRectangle,
+ SemiOpaqueAviator,
+ OpaqueRounded,
+ OpaqueCatEye,
+ OpaqueOval,
+ OpaqueRectangle,
+ OpaqueAviator,
+
+ Max = OpaqueAviator,
+ Count = Max + 1,
+};
+
+enum class BeardAndMustacheFlag : u32 {
+ Beard = 1,
+ Mustache,
+ All = Beard | Mustache,
+};
+DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
+
+enum class Source : u32 {
+ Database = 0,
+ Default = 1,
+ Account = 2,
+ Friend = 3,
+};
+
+enum class SourceFlag : u32 {
+ None = 0,
+ Database = 1 << 0,
+ Default = 1 << 1,
+};
+DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
+
+enum class ValidationResult : u32 {
+ NoErrors = 0x0,
+ InvalidBeardColor = 0x1,
+ InvalidBeardType = 0x2,
+ InvalidBuild = 0x3,
+ InvalidEyeAspect = 0x4,
+ InvalidEyeColor = 0x5,
+ InvalidEyeRotate = 0x6,
+ InvalidEyeScale = 0x7,
+ InvalidEyeType = 0x8,
+ InvalidEyeX = 0x9,
+ InvalidEyeY = 0xa,
+ InvalidEyebrowAspect = 0xb,
+ InvalidEyebrowColor = 0xc,
+ InvalidEyebrowRotate = 0xd,
+ InvalidEyebrowScale = 0xe,
+ InvalidEyebrowType = 0xf,
+ InvalidEyebrowX = 0x10,
+ InvalidEyebrowY = 0x11,
+ InvalidFacelineColor = 0x12,
+ InvalidFacelineMake = 0x13,
+ InvalidFacelineWrinkle = 0x14,
+ InvalidFacelineType = 0x15,
+ InvalidColor = 0x16,
+ InvalidFont = 0x17,
+ InvalidGender = 0x18,
+ InvalidGlassColor = 0x19,
+ InvalidGlassScale = 0x1a,
+ InvalidGlassType = 0x1b,
+ InvalidGlassY = 0x1c,
+ InvalidHairColor = 0x1d,
+ InvalidHairFlip = 0x1e,
+ InvalidHairType = 0x1f,
+ InvalidHeight = 0x20,
+ InvalidMoleScale = 0x21,
+ InvalidMoleType = 0x22,
+ InvalidMoleX = 0x23,
+ InvalidMoleY = 0x24,
+ InvalidMouthAspect = 0x25,
+ InvalidMouthColor = 0x26,
+ InvalidMouthScale = 0x27,
+ InvalidMouthType = 0x28,
+ InvalidMouthY = 0x29,
+ InvalidMustacheScale = 0x2a,
+ InvalidMustacheType = 0x2b,
+ InvalidMustacheY = 0x2c,
+ InvalidNoseScale = 0x2e,
+ InvalidNoseType = 0x2f,
+ InvalidNoseY = 0x30,
+ InvalidRegionMove = 0x31,
+ InvalidCreateId = 0x32,
+ InvalidName = 0x33,
+ InvalidType = 0x35,
+};
+
+struct Nickname {
+ static constexpr std::size_t MaxNameSize = 10;
+ std::array<char16_t, MaxNameSize> data;
+
+ // Checks for null, non-zero terminated or dirty strings
+ bool IsValid() const {
+ if (data[0] == 0) {
+ return false;
+ }
+
+ if (data[MaxNameSize] != 0) {
+ return false;
+ }
+ std::size_t index = 1;
+ while (data[index] != 0) {
+ index++;
+ }
+ while (index < MaxNameSize && data[index] == 0) {
+ index++;
+ }
+ return index == MaxNameSize;
+ }
+};
+static_assert(sizeof(Nickname) == 0x14, "Nickname is an invalid size");
+
+struct DefaultMii {
+ u32 face_type{};
+ u32 face_color{};
+ u32 face_wrinkle{};
+ u32 face_makeup{};
+ u32 hair_type{};
+ u32 hair_color{};
+ u32 hair_flip{};
+ u32 eye_type{};
+ u32 eye_color{};
+ u32 eye_scale{};
+ u32 eye_aspect{};
+ u32 eye_rotate{};
+ u32 eye_x{};
+ u32 eye_y{};
+ u32 eyebrow_type{};
+ u32 eyebrow_color{};
+ u32 eyebrow_scale{};
+ u32 eyebrow_aspect{};
+ u32 eyebrow_rotate{};
+ u32 eyebrow_x{};
+ u32 eyebrow_y{};
+ u32 nose_type{};
+ u32 nose_scale{};
+ u32 nose_y{};
+ u32 mouth_type{};
+ u32 mouth_color{};
+ u32 mouth_scale{};
+ u32 mouth_aspect{};
+ u32 mouth_y{};
+ u32 mustache_type{};
+ u32 beard_type{};
+ u32 beard_color{};
+ u32 mustache_scale{};
+ u32 mustache_y{};
+ u32 glasses_type{};
+ u32 glasses_color{};
+ u32 glasses_scale{};
+ u32 glasses_y{};
+ u32 mole_type{};
+ u32 mole_scale{};
+ u32 mole_x{};
+ u32 mole_y{};
+ u32 height{};
+ u32 weight{};
+ u32 gender{};
+ u32 favorite_color{};
+ u32 region_move{};
+ u32 font_region{};
+ u32 type{};
+ Nickname nickname;
+};
+static_assert(sizeof(DefaultMii) == 0xd8, "DefaultMii has incorrect size.");
+
+struct DatabaseSessionMetadata {
+ u32 interface_version;
+ u32 magic;
+ u64 update_counter;
+
+ bool IsInterfaceVersionSupported(u32 version) const {
+ return version <= interface_version;
+ }
+};
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_util.h b/src/core/hle/service/mii/mii_util.h
new file mode 100644
index 000000000..ddb544c23
--- /dev/null
+++ b/src/core/hle/service/mii/mii_util.h
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <random>
+#include <span>
+
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "common/uuid.h"
+#include "core/hle/service/mii/mii_types.h"
+
+namespace Service::Mii {
+class MiiUtil {
+public:
+ static u16 CalculateCrc16(const void* data, std::size_t size) {
+ s32 crc{};
+ for (std::size_t i = 0; i < size; i++) {
+ crc ^= static_cast<const u8*>(data)[i] << 8;
+ for (std::size_t j = 0; j < 8; j++) {
+ crc <<= 1;
+ if ((crc & 0x10000) != 0) {
+ crc = (crc ^ 0x1021) & 0xFFFF;
+ }
+ }
+ }
+ return Common::swap16(static_cast<u16>(crc));
+ }
+
+ static Common::UUID MakeCreateId() {
+ return Common::UUID::MakeRandomRFC4122V4();
+ }
+
+ static Common::UUID GetDeviceId() {
+ // This should be nn::settings::detail::GetMiiAuthorId()
+ return Common::UUID::MakeDefault();
+ }
+
+ template <typename T>
+ static T GetRandomValue(T min, T max) {
+ std::random_device device;
+ std::mt19937 gen(device());
+ std::uniform_int_distribution<u64> distribution(static_cast<u64>(min),
+ static_cast<u64>(max));
+ return static_cast<T>(distribution(gen));
+ }
+
+ template <typename T>
+ static T GetRandomValue(T max) {
+ return GetRandomValue<T>({}, max);
+ }
+
+ static bool IsFontRegionValid(FontRegion font, std::span<const char16_t> text) {
+ // TODO: This function needs to check against the font tables
+ return true;
+ }
+};
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
deleted file mode 100644
index c2bec68d4..000000000
--- a/src/core/hle/service/mii/raw_data.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <array>
-
-#include "core/hle/service/mii/types.h"
-
-namespace Service::Mii::RawData {
-
-extern const std::array<Service::Mii::DefaultMii, 8> DefaultMii;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFaceline;
-extern const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineWrinkle;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineMakeup;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType;
-extern const std::array<Service::Mii::RandomMiiData3, 9> RandomMiiHairColor;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyeType;
-extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiEyeColor;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyebrowType;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiNoseType;
-extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiMouthType;
-extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiGlassType;
-
-} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
deleted file mode 100644
index c48d08d79..000000000
--- a/src/core/hle/service/mii/types.h
+++ /dev/null
@@ -1,553 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <array>
-#include <type_traits>
-
-#include "common/bit_field.h"
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "common/uuid.h"
-
-namespace Service::Mii {
-
-enum class Age : u32 {
- Young,
- Normal,
- Old,
- All,
-};
-
-enum class BeardType : u32 {
- None,
- Beard1,
- Beard2,
- Beard3,
- Beard4,
- Beard5,
-};
-
-enum class BeardAndMustacheFlag : u32 {
- Beard = 1,
- Mustache,
- All = Beard | Mustache,
-};
-DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
-
-enum class FontRegion : u32 {
- Standard,
- China,
- Korea,
- Taiwan,
-};
-
-enum class Gender : u32 {
- Male,
- Female,
- All,
- Maximum = Female,
-};
-
-enum class HairFlip : u32 {
- Left,
- Right,
- Maximum = Right,
-};
-
-enum class MustacheType : u32 {
- None,
- Mustache1,
- Mustache2,
- Mustache3,
- Mustache4,
- Mustache5,
-};
-
-enum class Race : u32 {
- Black,
- White,
- Asian,
- All,
-};
-
-enum class Source : u32 {
- Database = 0,
- Default = 1,
- Account = 2,
- Friend = 3,
-};
-
-enum class SourceFlag : u32 {
- None = 0,
- Database = 1 << 0,
- Default = 1 << 1,
-};
-DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
-
-// nn::mii::CharInfo
-struct CharInfo {
- Common::UUID uuid;
- std::array<char16_t, 11> name;
- u8 font_region;
- u8 favorite_color;
- u8 gender;
- u8 height;
- u8 build;
- u8 type;
- u8 region_move;
- u8 faceline_type;
- u8 faceline_color;
- u8 faceline_wrinkle;
- u8 faceline_make;
- u8 hair_type;
- u8 hair_color;
- u8 hair_flip;
- u8 eye_type;
- u8 eye_color;
- u8 eye_scale;
- u8 eye_aspect;
- u8 eye_rotate;
- u8 eye_x;
- u8 eye_y;
- u8 eyebrow_type;
- u8 eyebrow_color;
- u8 eyebrow_scale;
- u8 eyebrow_aspect;
- u8 eyebrow_rotate;
- u8 eyebrow_x;
- u8 eyebrow_y;
- u8 nose_type;
- u8 nose_scale;
- u8 nose_y;
- u8 mouth_type;
- u8 mouth_color;
- u8 mouth_scale;
- u8 mouth_aspect;
- u8 mouth_y;
- u8 beard_color;
- u8 beard_type;
- u8 mustache_type;
- u8 mustache_scale;
- u8 mustache_y;
- u8 glasses_type;
- u8 glasses_color;
- u8 glasses_scale;
- u8 glasses_y;
- u8 mole_type;
- u8 mole_scale;
- u8 mole_x;
- u8 mole_y;
- u8 padding;
-};
-static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
-static_assert(std::has_unique_object_representations_v<CharInfo>,
- "All bits of CharInfo must contribute to its value.");
-
-#pragma pack(push, 4)
-
-struct MiiInfoElement {
- MiiInfoElement(const CharInfo& info_, Source source_) : info{info_}, source{source_} {}
-
- CharInfo info{};
- Source source{};
-};
-static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
-
-struct MiiStoreBitFields {
- union {
- u32 word_0{};
-
- BitField<0, 8, u32> hair_type;
- BitField<8, 7, u32> height;
- BitField<15, 1, u32> mole_type;
- BitField<16, 7, u32> build;
- BitField<23, 1, HairFlip> hair_flip;
- BitField<24, 7, u32> hair_color;
- BitField<31, 1, u32> type;
- };
-
- union {
- u32 word_1{};
-
- BitField<0, 7, u32> eye_color;
- BitField<7, 1, Gender> gender;
- BitField<8, 7, u32> eyebrow_color;
- BitField<16, 7, u32> mouth_color;
- BitField<24, 7, u32> beard_color;
- };
-
- union {
- u32 word_2{};
-
- BitField<0, 7, u32> glasses_color;
- BitField<8, 6, u32> eye_type;
- BitField<14, 2, u32> region_move;
- BitField<16, 6, u32> mouth_type;
- BitField<22, 2, FontRegion> font_region;
- BitField<24, 5, u32> eye_y;
- BitField<29, 3, u32> glasses_scale;
- };
-
- union {
- u32 word_3{};
-
- BitField<0, 5, u32> eyebrow_type;
- BitField<5, 3, MustacheType> mustache_type;
- BitField<8, 5, u32> nose_type;
- BitField<13, 3, BeardType> beard_type;
- BitField<16, 5, u32> nose_y;
- BitField<21, 3, u32> mouth_aspect;
- BitField<24, 5, u32> mouth_y;
- BitField<29, 3, u32> eyebrow_aspect;
- };
-
- union {
- u32 word_4{};
-
- BitField<0, 5, u32> mustache_y;
- BitField<5, 3, u32> eye_rotate;
- BitField<8, 5, u32> glasses_y;
- BitField<13, 3, u32> eye_aspect;
- BitField<16, 5, u32> mole_x;
- BitField<21, 3, u32> eye_scale;
- BitField<24, 5, u32> mole_y;
- };
-
- union {
- u32 word_5{};
-
- BitField<0, 5, u32> glasses_type;
- BitField<8, 4, u32> favorite_color;
- BitField<12, 4, u32> faceline_type;
- BitField<16, 4, u32> faceline_color;
- BitField<20, 4, u32> faceline_wrinkle;
- BitField<24, 4, u32> faceline_makeup;
- BitField<28, 4, u32> eye_x;
- };
-
- union {
- u32 word_6{};
-
- BitField<0, 4, u32> eyebrow_scale;
- BitField<4, 4, u32> eyebrow_rotate;
- BitField<8, 4, u32> eyebrow_x;
- BitField<12, 4, u32> eyebrow_y;
- BitField<16, 4, u32> nose_scale;
- BitField<20, 4, u32> mouth_scale;
- BitField<24, 4, u32> mustache_scale;
- BitField<28, 4, u32> mole_scale;
- };
-};
-static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
-static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
- "MiiStoreBitFields is not trivially copyable.");
-
-// This is nn::mii::Ver3StoreData
-// Based on citra HLE::Applets::MiiData and PretendoNetwork.
-// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
-// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
-struct Ver3StoreData {
- u8 version;
- union {
- u8 raw;
-
- BitField<0, 1, u8> allow_copying;
- BitField<1, 1, u8> profanity_flag;
- BitField<2, 2, u8> region_lock;
- BitField<4, 2, u8> character_set;
- } region_information;
- u16_be mii_id;
- u64_be system_id;
- u32_be specialness_and_creation_date;
- std::array<u8, 0x6> creator_mac;
- u16_be padding;
- union {
- u16 raw;
-
- BitField<0, 1, u16> gender;
- BitField<1, 4, u16> birth_month;
- BitField<5, 5, u16> birth_day;
- BitField<10, 4, u16> favorite_color;
- BitField<14, 1, u16> favorite;
- } mii_information;
- std::array<char16_t, 0xA> mii_name;
- u8 height;
- u8 build;
- union {
- u8 raw;
-
- BitField<0, 1, u8> disable_sharing;
- BitField<1, 4, u8> face_shape;
- BitField<5, 3, u8> skin_color;
- } appearance_bits1;
- union {
- u8 raw;
-
- BitField<0, 4, u8> wrinkles;
- BitField<4, 4, u8> makeup;
- } appearance_bits2;
- u8 hair_style;
- union {
- u8 raw;
-
- BitField<0, 3, u8> hair_color;
- BitField<3, 1, u8> flip_hair;
- } appearance_bits3;
- union {
- u32 raw;
-
- BitField<0, 6, u32> eye_type;
- BitField<6, 3, u32> eye_color;
- BitField<9, 4, u32> eye_scale;
- BitField<13, 3, u32> eye_vertical_stretch;
- BitField<16, 5, u32> eye_rotation;
- BitField<21, 4, u32> eye_spacing;
- BitField<25, 5, u32> eye_y_position;
- } appearance_bits4;
- union {
- u32 raw;
-
- BitField<0, 5, u32> eyebrow_style;
- BitField<5, 3, u32> eyebrow_color;
- BitField<8, 4, u32> eyebrow_scale;
- BitField<12, 3, u32> eyebrow_yscale;
- BitField<16, 4, u32> eyebrow_rotation;
- BitField<21, 4, u32> eyebrow_spacing;
- BitField<25, 5, u32> eyebrow_y_position;
- } appearance_bits5;
- union {
- u16 raw;
-
- BitField<0, 5, u16> nose_type;
- BitField<5, 4, u16> nose_scale;
- BitField<9, 5, u16> nose_y_position;
- } appearance_bits6;
- union {
- u16 raw;
-
- BitField<0, 6, u16> mouth_type;
- BitField<6, 3, u16> mouth_color;
- BitField<9, 4, u16> mouth_scale;
- BitField<13, 3, u16> mouth_horizontal_stretch;
- } appearance_bits7;
- union {
- u8 raw;
-
- BitField<0, 5, u8> mouth_y_position;
- BitField<5, 3, u8> mustache_type;
- } appearance_bits8;
- u8 allow_copying;
- union {
- u16 raw;
-
- BitField<0, 3, u16> bear_type;
- BitField<3, 3, u16> facial_hair_color;
- BitField<6, 4, u16> mustache_scale;
- BitField<10, 5, u16> mustache_y_position;
- } appearance_bits9;
- union {
- u16 raw;
-
- BitField<0, 4, u16> glasses_type;
- BitField<4, 3, u16> glasses_color;
- BitField<7, 4, u16> glasses_scale;
- BitField<11, 5, u16> glasses_y_position;
- } appearance_bits10;
- union {
- u16 raw;
-
- BitField<0, 1, u16> mole_enabled;
- BitField<1, 4, u16> mole_scale;
- BitField<5, 5, u16> mole_x_position;
- BitField<10, 5, u16> mole_y_position;
- } appearance_bits11;
-
- std::array<u16_le, 0xA> author_name;
- INSERT_PADDING_BYTES(0x2);
- u16_be crc;
-};
-static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
-
-struct NfpStoreDataExtension {
- u8 faceline_color;
- u8 hair_color;
- u8 eye_color;
- u8 eyebrow_color;
- u8 mouth_color;
- u8 beard_color;
- u8 glass_color;
- u8 glass_type;
-};
-static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
-
-constexpr std::array<u8, 0x10> Ver3FacelineColorTable{
- 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
-};
-
-constexpr std::array<u8, 100> Ver3HairColorTable{
- 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
- 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
- 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
- 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
-};
-
-constexpr std::array<u8, 100> Ver3EyeColorTable{
- 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
- 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
- 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
- 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
- 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
-};
-
-constexpr std::array<u8, 100> Ver3MouthlineColorTable{
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
- 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
- 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
- 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
- 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
- 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
-};
-
-constexpr std::array<u8, 100> Ver3GlassColorTable{
- 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
- 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
- 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
- 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
- 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
-};
-
-constexpr std::array<u8, 20> Ver3GlassTypeTable{
- 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
- 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
-};
-
-struct MiiStoreData {
- using Name = std::array<char16_t, 10>;
-
- MiiStoreData();
- MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
- const Common::UUID& user_id);
-
- // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
- // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
- // not suitable for our uses.
- struct {
- std::array<u8, 0x1C> data{};
- static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
-
- Name name{};
- Common::UUID uuid{};
- } data;
-
- u16 data_crc{};
- u16 device_crc{};
-};
-static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
-
-struct MiiStoreDataElement {
- MiiStoreData data{};
- Source source{};
-};
-static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
-
-struct MiiDatabase {
- u32 magic{}; // 'NFDB'
- std::array<MiiStoreData, 0x64> miis{};
- INSERT_PADDING_BYTES(1);
- u8 count{};
- u16 crc{};
-};
-static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
-
-struct RandomMiiValues {
- std::array<u8, 0xbc> values{};
-};
-static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
-
-struct RandomMiiData4 {
- Gender gender{};
- Age age{};
- Race race{};
- u32 values_count{};
- std::array<u32, 47> values{};
-};
-static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
-
-struct RandomMiiData3 {
- u32 arg_1;
- u32 arg_2;
- u32 values_count;
- std::array<u32, 47> values{};
-};
-static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
-
-struct RandomMiiData2 {
- u32 arg_1;
- u32 values_count;
- std::array<u32, 47> values{};
-};
-static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
-
-struct DefaultMii {
- u32 face_type{};
- u32 face_color{};
- u32 face_wrinkle{};
- u32 face_makeup{};
- u32 hair_type{};
- u32 hair_color{};
- u32 hair_flip{};
- u32 eye_type{};
- u32 eye_color{};
- u32 eye_scale{};
- u32 eye_aspect{};
- u32 eye_rotate{};
- u32 eye_x{};
- u32 eye_y{};
- u32 eyebrow_type{};
- u32 eyebrow_color{};
- u32 eyebrow_scale{};
- u32 eyebrow_aspect{};
- u32 eyebrow_rotate{};
- u32 eyebrow_x{};
- u32 eyebrow_y{};
- u32 nose_type{};
- u32 nose_scale{};
- u32 nose_y{};
- u32 mouth_type{};
- u32 mouth_color{};
- u32 mouth_scale{};
- u32 mouth_aspect{};
- u32 mouth_y{};
- u32 mustache_type{};
- u32 beard_type{};
- u32 beard_color{};
- u32 mustache_scale{};
- u32 mustache_y{};
- u32 glasses_type{};
- u32 glasses_color{};
- u32 glasses_scale{};
- u32 glasses_y{};
- u32 mole_type{};
- u32 mole_scale{};
- u32 mole_x{};
- u32 mole_y{};
- u32 height{};
- u32 weight{};
- Gender gender{};
- u32 favorite_color{};
- u32 region{};
- FontRegion font_region{};
- u32 type{};
- INSERT_PADDING_WORDS(5);
-};
-static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
-
-#pragma pack(pop)
-
-} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp
new file mode 100644
index 000000000..bb948c628
--- /dev/null
+++ b/src/core/hle/service/mii/types/char_info.cpp
@@ -0,0 +1,482 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/mii/types/char_info.h"
+#include "core/hle/service/mii/types/store_data.h"
+
+namespace Service::Mii {
+
+void CharInfo::SetFromStoreData(const StoreData& store_data) {
+ name = store_data.GetNickname();
+ null_terminator = '\0';
+ create_id = store_data.GetCreateId();
+ font_region = store_data.GetFontRegion();
+ favorite_color = store_data.GetFavoriteColor();
+ gender = store_data.GetGender();
+ height = store_data.GetHeight();
+ build = store_data.GetBuild();
+ type = store_data.GetType();
+ region_move = store_data.GetRegionMove();
+ faceline_type = store_data.GetFacelineType();
+ faceline_color = store_data.GetFacelineColor();
+ faceline_wrinkle = store_data.GetFacelineWrinkle();
+ faceline_make = store_data.GetFacelineMake();
+ hair_type = store_data.GetHairType();
+ hair_color = store_data.GetHairColor();
+ hair_flip = store_data.GetHairFlip();
+ eye_type = store_data.GetEyeType();
+ eye_color = store_data.GetEyeColor();
+ eye_scale = store_data.GetEyeScale();
+ eye_aspect = store_data.GetEyeAspect();
+ eye_rotate = store_data.GetEyeRotate();
+ eye_x = store_data.GetEyeX();
+ eye_y = store_data.GetEyeY();
+ eyebrow_type = store_data.GetEyebrowType();
+ eyebrow_color = store_data.GetEyebrowColor();
+ eyebrow_scale = store_data.GetEyebrowScale();
+ eyebrow_aspect = store_data.GetEyebrowAspect();
+ eyebrow_rotate = store_data.GetEyebrowRotate();
+ eyebrow_x = store_data.GetEyebrowX();
+ eyebrow_y = store_data.GetEyebrowY();
+ nose_type = store_data.GetNoseType();
+ nose_scale = store_data.GetNoseScale();
+ nose_y = store_data.GetNoseY();
+ mouth_type = store_data.GetMouthType();
+ mouth_color = store_data.GetMouthColor();
+ mouth_scale = store_data.GetMouthScale();
+ mouth_aspect = store_data.GetMouthAspect();
+ mouth_y = store_data.GetMouthY();
+ beard_color = store_data.GetBeardColor();
+ beard_type = store_data.GetBeardType();
+ mustache_type = store_data.GetMustacheType();
+ mustache_scale = store_data.GetMustacheScale();
+ mustache_y = store_data.GetMustacheY();
+ glass_type = store_data.GetGlassType();
+ glass_color = store_data.GetGlassColor();
+ glass_scale = store_data.GetGlassScale();
+ glass_y = store_data.GetGlassY();
+ mole_type = store_data.GetMoleType();
+ mole_scale = store_data.GetMoleScale();
+ mole_x = store_data.GetMoleX();
+ mole_y = store_data.GetMoleY();
+ padding = '\0';
+}
+
+ValidationResult CharInfo::Verify() const {
+ if (!create_id.IsValid()) {
+ return ValidationResult::InvalidCreateId;
+ }
+ if (!name.IsValid()) {
+ return ValidationResult::InvalidName;
+ }
+ if (font_region > FontRegion::Max) {
+ return ValidationResult::InvalidFont;
+ }
+ if (favorite_color > FavoriteColor::Max) {
+ return ValidationResult::InvalidColor;
+ }
+ if (gender > Gender::Max) {
+ return ValidationResult::InvalidGender;
+ }
+ if (height > MaxHeight) {
+ return ValidationResult::InvalidHeight;
+ }
+ if (build > MaxBuild) {
+ return ValidationResult::InvalidBuild;
+ }
+ if (type > MaxType) {
+ return ValidationResult::InvalidType;
+ }
+ if (region_move > MaxRegionMove) {
+ return ValidationResult::InvalidRegionMove;
+ }
+ if (faceline_type > FacelineType::Max) {
+ return ValidationResult::InvalidFacelineType;
+ }
+ if (faceline_color > FacelineColor::Max) {
+ return ValidationResult::InvalidFacelineColor;
+ }
+ if (faceline_wrinkle > FacelineWrinkle::Max) {
+ return ValidationResult::InvalidFacelineWrinkle;
+ }
+ if (faceline_make > FacelineMake::Max) {
+ return ValidationResult::InvalidFacelineMake;
+ }
+ if (hair_type > HairType::Max) {
+ return ValidationResult::InvalidHairType;
+ }
+ if (hair_color > CommonColor::Max) {
+ return ValidationResult::InvalidHairColor;
+ }
+ if (hair_flip > HairFlip::Max) {
+ return ValidationResult::InvalidHairFlip;
+ }
+ if (eye_type > EyeType::Max) {
+ return ValidationResult::InvalidEyeType;
+ }
+ if (eye_color > CommonColor::Max) {
+ return ValidationResult::InvalidEyeColor;
+ }
+ if (eye_scale > MaxEyeScale) {
+ return ValidationResult::InvalidEyeScale;
+ }
+ if (eye_aspect > MaxEyeAspect) {
+ return ValidationResult::InvalidEyeAspect;
+ }
+ if (eye_rotate > MaxEyeX) {
+ return ValidationResult::InvalidEyeRotate;
+ }
+ if (eye_x > MaxEyeX) {
+ return ValidationResult::InvalidEyeX;
+ }
+ if (eye_y > MaxEyeY) {
+ return ValidationResult::InvalidEyeY;
+ }
+ if (eyebrow_type > EyebrowType::Max) {
+ return ValidationResult::InvalidEyebrowType;
+ }
+ if (eyebrow_color > CommonColor::Max) {
+ return ValidationResult::InvalidEyebrowColor;
+ }
+ if (eyebrow_scale > MaxEyebrowScale) {
+ return ValidationResult::InvalidEyebrowScale;
+ }
+ if (eyebrow_aspect > MaxEyebrowAspect) {
+ return ValidationResult::InvalidEyebrowAspect;
+ }
+ if (eyebrow_rotate > MaxEyebrowRotate) {
+ return ValidationResult::InvalidEyebrowRotate;
+ }
+ if (eyebrow_x > MaxEyebrowX) {
+ return ValidationResult::InvalidEyebrowX;
+ }
+ if (eyebrow_y > MaxEyebrowY) {
+ return ValidationResult::InvalidEyebrowY;
+ }
+ if (nose_type > NoseType::Max) {
+ return ValidationResult::InvalidNoseType;
+ }
+ if (nose_scale > MaxNoseScale) {
+ return ValidationResult::InvalidNoseScale;
+ }
+ if (nose_y > MaxNoseY) {
+ return ValidationResult::InvalidNoseY;
+ }
+ if (mouth_type > MouthType::Max) {
+ return ValidationResult::InvalidMouthType;
+ }
+ if (mouth_color > CommonColor::Max) {
+ return ValidationResult::InvalidMouthColor;
+ }
+ if (mouth_scale > MaxMouthScale) {
+ return ValidationResult::InvalidMouthScale;
+ }
+ if (mouth_aspect > MaxMoutAspect) {
+ return ValidationResult::InvalidMouthAspect;
+ }
+ if (mouth_y > MaxMouthY) {
+ return ValidationResult::InvalidMoleY;
+ }
+ if (beard_color > CommonColor::Max) {
+ return ValidationResult::InvalidBeardColor;
+ }
+ if (beard_type > BeardType::Max) {
+ return ValidationResult::InvalidBeardType;
+ }
+ if (mustache_type > MustacheType::Max) {
+ return ValidationResult::InvalidMustacheType;
+ }
+ if (mustache_scale > MaxMustacheScale) {
+ return ValidationResult::InvalidMustacheScale;
+ }
+ if (mustache_y > MasMustacheY) {
+ return ValidationResult::InvalidMustacheY;
+ }
+ if (glass_type > GlassType::Max) {
+ return ValidationResult::InvalidGlassType;
+ }
+ if (glass_color > CommonColor::Max) {
+ return ValidationResult::InvalidGlassColor;
+ }
+ if (glass_scale > MaxGlassScale) {
+ return ValidationResult::InvalidGlassScale;
+ }
+ if (glass_y > MaxGlassY) {
+ return ValidationResult::InvalidGlassY;
+ }
+ if (mole_type > MoleType::Max) {
+ return ValidationResult::InvalidMoleType;
+ }
+ if (mole_scale > MaxMoleScale) {
+ return ValidationResult::InvalidMoleScale;
+ }
+ if (mole_x > MaxMoleX) {
+ return ValidationResult::InvalidMoleX;
+ }
+ if (mole_y > MaxMoleY) {
+ return ValidationResult::InvalidMoleY;
+ }
+ return ValidationResult::NoErrors;
+}
+
+Common::UUID CharInfo::GetCreateId() const {
+ return create_id;
+}
+
+Nickname CharInfo::GetNickname() const {
+ return name;
+}
+
+FontRegion CharInfo::GetFontRegion() const {
+ return font_region;
+}
+
+FavoriteColor CharInfo::GetFavoriteColor() const {
+ return favorite_color;
+}
+
+Gender CharInfo::GetGender() const {
+ return gender;
+}
+
+u8 CharInfo::GetHeight() const {
+ return height;
+}
+
+u8 CharInfo::GetBuild() const {
+ return build;
+}
+
+u8 CharInfo::GetType() const {
+ return type;
+}
+
+u8 CharInfo::GetRegionMove() const {
+ return region_move;
+}
+
+FacelineType CharInfo::GetFacelineType() const {
+ return faceline_type;
+}
+
+FacelineColor CharInfo::GetFacelineColor() const {
+ return faceline_color;
+}
+
+FacelineWrinkle CharInfo::GetFacelineWrinkle() const {
+ return faceline_wrinkle;
+}
+
+FacelineMake CharInfo::GetFacelineMake() const {
+ return faceline_make;
+}
+
+HairType CharInfo::GetHairType() const {
+ return hair_type;
+}
+
+CommonColor CharInfo::GetHairColor() const {
+ return hair_color;
+}
+
+HairFlip CharInfo::GetHairFlip() const {
+ return hair_flip;
+}
+
+EyeType CharInfo::GetEyeType() const {
+ return eye_type;
+}
+
+CommonColor CharInfo::GetEyeColor() const {
+ return eye_color;
+}
+
+u8 CharInfo::GetEyeScale() const {
+ return eye_scale;
+}
+
+u8 CharInfo::GetEyeAspect() const {
+ return eye_aspect;
+}
+
+u8 CharInfo::GetEyeRotate() const {
+ return eye_rotate;
+}
+
+u8 CharInfo::GetEyeX() const {
+ return eye_x;
+}
+
+u8 CharInfo::GetEyeY() const {
+ return eye_y;
+}
+
+EyebrowType CharInfo::GetEyebrowType() const {
+ return eyebrow_type;
+}
+
+CommonColor CharInfo::GetEyebrowColor() const {
+ return eyebrow_color;
+}
+
+u8 CharInfo::GetEyebrowScale() const {
+ return eyebrow_scale;
+}
+
+u8 CharInfo::GetEyebrowAspect() const {
+ return eyebrow_aspect;
+}
+
+u8 CharInfo::GetEyebrowRotate() const {
+ return eyebrow_rotate;
+}
+
+u8 CharInfo::GetEyebrowX() const {
+ return eyebrow_x;
+}
+
+u8 CharInfo::GetEyebrowY() const {
+ return eyebrow_y;
+}
+
+NoseType CharInfo::GetNoseType() const {
+ return nose_type;
+}
+
+u8 CharInfo::GetNoseScale() const {
+ return nose_scale;
+}
+
+u8 CharInfo::GetNoseY() const {
+ return nose_y;
+}
+
+MouthType CharInfo::GetMouthType() const {
+ return mouth_type;
+}
+
+CommonColor CharInfo::GetMouthColor() const {
+ return mouth_color;
+}
+
+u8 CharInfo::GetMouthScale() const {
+ return mouth_scale;
+}
+
+u8 CharInfo::GetMouthAspect() const {
+ return mouth_aspect;
+}
+
+u8 CharInfo::GetMouthY() const {
+ return mouth_y;
+}
+
+CommonColor CharInfo::GetBeardColor() const {
+ return beard_color;
+}
+
+BeardType CharInfo::GetBeardType() const {
+ return beard_type;
+}
+
+MustacheType CharInfo::GetMustacheType() const {
+ return mustache_type;
+}
+
+u8 CharInfo::GetMustacheScale() const {
+ return mustache_scale;
+}
+
+u8 CharInfo::GetMustacheY() const {
+ return mustache_y;
+}
+
+GlassType CharInfo::GetGlassType() const {
+ return glass_type;
+}
+
+CommonColor CharInfo::GetGlassColor() const {
+ return glass_color;
+}
+
+u8 CharInfo::GetGlassScale() const {
+ return glass_scale;
+}
+
+u8 CharInfo::GetGlassY() const {
+ return glass_y;
+}
+
+MoleType CharInfo::GetMoleType() const {
+ return mole_type;
+}
+
+u8 CharInfo::GetMoleScale() const {
+ return mole_scale;
+}
+
+u8 CharInfo::GetMoleX() const {
+ return mole_x;
+}
+
+u8 CharInfo::GetMoleY() const {
+ return mole_y;
+}
+
+bool CharInfo::operator==(const CharInfo& info) {
+ bool is_identical = info.Verify() == ValidationResult::NoErrors;
+ is_identical &= name.data == info.GetNickname().data;
+ is_identical &= create_id == info.GetCreateId();
+ is_identical &= font_region == info.GetFontRegion();
+ is_identical &= favorite_color == info.GetFavoriteColor();
+ is_identical &= gender == info.GetGender();
+ is_identical &= height == info.GetHeight();
+ is_identical &= build == info.GetBuild();
+ is_identical &= type == info.GetType();
+ is_identical &= region_move == info.GetRegionMove();
+ is_identical &= faceline_type == info.GetFacelineType();
+ is_identical &= faceline_color == info.GetFacelineColor();
+ is_identical &= faceline_wrinkle == info.GetFacelineWrinkle();
+ is_identical &= faceline_make == info.GetFacelineMake();
+ is_identical &= hair_type == info.GetHairType();
+ is_identical &= hair_color == info.GetHairColor();
+ is_identical &= hair_flip == info.GetHairFlip();
+ is_identical &= eye_type == info.GetEyeType();
+ is_identical &= eye_color == info.GetEyeColor();
+ is_identical &= eye_scale == info.GetEyeScale();
+ is_identical &= eye_aspect == info.GetEyeAspect();
+ is_identical &= eye_rotate == info.GetEyeRotate();
+ is_identical &= eye_x == info.GetEyeX();
+ is_identical &= eye_y == info.GetEyeY();
+ is_identical &= eyebrow_type == info.GetEyebrowType();
+ is_identical &= eyebrow_color == info.GetEyebrowColor();
+ is_identical &= eyebrow_scale == info.GetEyebrowScale();
+ is_identical &= eyebrow_aspect == info.GetEyebrowAspect();
+ is_identical &= eyebrow_rotate == info.GetEyebrowRotate();
+ is_identical &= eyebrow_x == info.GetEyebrowX();
+ is_identical &= eyebrow_y == info.GetEyebrowY();
+ is_identical &= nose_type == info.GetNoseType();
+ is_identical &= nose_scale == info.GetNoseScale();
+ is_identical &= nose_y == info.GetNoseY();
+ is_identical &= mouth_type == info.GetMouthType();
+ is_identical &= mouth_color == info.GetMouthColor();
+ is_identical &= mouth_scale == info.GetMouthScale();
+ is_identical &= mouth_aspect == info.GetMouthAspect();
+ is_identical &= mouth_y == info.GetMouthY();
+ is_identical &= beard_color == info.GetBeardColor();
+ is_identical &= beard_type == info.GetBeardType();
+ is_identical &= mustache_type == info.GetMustacheType();
+ is_identical &= mustache_scale == info.GetMustacheScale();
+ is_identical &= mustache_y == info.GetMustacheY();
+ is_identical &= glass_type == info.GetGlassType();
+ is_identical &= glass_color == info.GetGlassColor();
+ is_identical &= glass_scale == info.GetGlassScale();
+ is_identical &= glass_y == info.GetGlassY();
+ is_identical &= mole_type == info.GetMoleType();
+ is_identical &= mole_scale == info.GetMoleScale();
+ is_identical &= mole_x == info.GetMoleX();
+ is_identical &= mole_y == info.GetMoleY();
+ return is_identical;
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/char_info.h b/src/core/hle/service/mii/types/char_info.h
new file mode 100644
index 000000000..d069b221f
--- /dev/null
+++ b/src/core/hle/service/mii/types/char_info.h
@@ -0,0 +1,137 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/mii/mii_types.h"
+
+namespace Service::Mii {
+class StoreData;
+
+// This is nn::mii::detail::CharInfoRaw
+class CharInfo {
+public:
+ void SetFromStoreData(const StoreData& store_data_raw);
+
+ ValidationResult Verify() const;
+
+ Common::UUID GetCreateId() const;
+ Nickname GetNickname() const;
+ FontRegion GetFontRegion() const;
+ FavoriteColor GetFavoriteColor() const;
+ Gender GetGender() const;
+ u8 GetHeight() const;
+ u8 GetBuild() const;
+ u8 GetType() const;
+ u8 GetRegionMove() const;
+ FacelineType GetFacelineType() const;
+ FacelineColor GetFacelineColor() const;
+ FacelineWrinkle GetFacelineWrinkle() const;
+ FacelineMake GetFacelineMake() const;
+ HairType GetHairType() const;
+ CommonColor GetHairColor() const;
+ HairFlip GetHairFlip() const;
+ EyeType GetEyeType() const;
+ CommonColor GetEyeColor() const;
+ u8 GetEyeScale() const;
+ u8 GetEyeAspect() const;
+ u8 GetEyeRotate() const;
+ u8 GetEyeX() const;
+ u8 GetEyeY() const;
+ EyebrowType GetEyebrowType() const;
+ CommonColor GetEyebrowColor() const;
+ u8 GetEyebrowScale() const;
+ u8 GetEyebrowAspect() const;
+ u8 GetEyebrowRotate() const;
+ u8 GetEyebrowX() const;
+ u8 GetEyebrowY() const;
+ NoseType GetNoseType() const;
+ u8 GetNoseScale() const;
+ u8 GetNoseY() const;
+ MouthType GetMouthType() const;
+ CommonColor GetMouthColor() const;
+ u8 GetMouthScale() const;
+ u8 GetMouthAspect() const;
+ u8 GetMouthY() const;
+ CommonColor GetBeardColor() const;
+ BeardType GetBeardType() const;
+ MustacheType GetMustacheType() const;
+ u8 GetMustacheScale() const;
+ u8 GetMustacheY() const;
+ GlassType GetGlassType() const;
+ CommonColor GetGlassColor() const;
+ u8 GetGlassScale() const;
+ u8 GetGlassY() const;
+ MoleType GetMoleType() const;
+ u8 GetMoleScale() const;
+ u8 GetMoleX() const;
+ u8 GetMoleY() const;
+
+ bool operator==(const CharInfo& info);
+
+private:
+ Common::UUID create_id;
+ Nickname name;
+ u16 null_terminator;
+ FontRegion font_region;
+ FavoriteColor favorite_color;
+ Gender gender;
+ u8 height;
+ u8 build;
+ u8 type;
+ u8 region_move;
+ FacelineType faceline_type;
+ FacelineColor faceline_color;
+ FacelineWrinkle faceline_wrinkle;
+ FacelineMake faceline_make;
+ HairType hair_type;
+ CommonColor hair_color;
+ HairFlip hair_flip;
+ EyeType eye_type;
+ CommonColor eye_color;
+ u8 eye_scale;
+ u8 eye_aspect;
+ u8 eye_rotate;
+ u8 eye_x;
+ u8 eye_y;
+ EyebrowType eyebrow_type;
+ CommonColor eyebrow_color;
+ u8 eyebrow_scale;
+ u8 eyebrow_aspect;
+ u8 eyebrow_rotate;
+ u8 eyebrow_x;
+ u8 eyebrow_y;
+ NoseType nose_type;
+ u8 nose_scale;
+ u8 nose_y;
+ MouthType mouth_type;
+ CommonColor mouth_color;
+ u8 mouth_scale;
+ u8 mouth_aspect;
+ u8 mouth_y;
+ CommonColor beard_color;
+ BeardType beard_type;
+ MustacheType mustache_type;
+ u8 mustache_scale;
+ u8 mustache_y;
+ GlassType glass_type;
+ CommonColor glass_color;
+ u8 glass_scale;
+ u8 glass_y;
+ MoleType mole_type;
+ u8 mole_scale;
+ u8 mole_x;
+ u8 mole_y;
+ u8 padding;
+};
+static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
+static_assert(std::has_unique_object_representations_v<CharInfo>,
+ "All bits of CharInfo must contribute to its value.");
+
+struct CharInfoElement {
+ CharInfo char_info{};
+ Source source{};
+};
+static_assert(sizeof(CharInfoElement) == 0x5c, "CharInfoElement has incorrect size.");
+
+}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/core_data.cpp b/src/core/hle/service/mii/types/core_data.cpp
new file mode 100644
index 000000000..659288b51
--- /dev/null
+++ b/src/core/hle/service/mii/types/core_data.cpp
@@ -0,0 +1,601 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/assert.h"
+#include "core/hle/service/mii/mii_util.h"
+#include "core/hle/service/mii/types/core_data.h"
+#include "core/hle/service/mii/types/raw_data.h"
+
+namespace Service::Mii {
+
+void CoreData::SetDefault() {
+ data = {};
+ name = GetDefaultNickname();
+}
+
+void CoreData::BuildRandom(Age age, Gender gender, Race race) {
+ if (gender == Gender::All) {
+ gender = MiiUtil::GetRandomValue(Gender::Max);
+ }
+
+ if (age == Age::All) {
+ const auto random{MiiUtil::GetRandomValue<int>(10)};
+ if (random >= 8) {
+ age = Age::Old;
+ } else if (random >= 4) {
+ age = Age::Normal;
+ } else {
+ age = Age::Young;
+ }
+ }
+
+ if (race == Race::All) {
+ const auto random{MiiUtil::GetRandomValue<int>(10)};
+ if (random >= 8) {
+ race = Race::Black;
+ } else if (random >= 4) {
+ race = Race::White;
+ } else {
+ race = Race::Asian;
+ }
+ }
+
+ SetGender(gender);
+ SetFavoriteColor(MiiUtil::GetRandomValue(FavoriteColor::Max));
+ SetRegionMove(0);
+ SetFontRegion(FontRegion::Standard);
+ SetType(0);
+ SetHeight(64);
+ SetBuild(64);
+
+ u32 axis_y{};
+ if (gender == Gender::Female && age == Age::Young) {
+ axis_y = MiiUtil::GetRandomValue<u32>(3);
+ }
+
+ const std::size_t index{3 * static_cast<std::size_t>(age) +
+ 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
+
+ const auto& faceline_type_info{RawData::RandomMiiFaceline.at(index)};
+ const auto& faceline_color_info{RawData::RandomMiiFacelineColor.at(
+ 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
+ const auto& faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
+ const auto& faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
+ const auto& hair_type_info{RawData::RandomMiiHairType.at(index)};
+ const auto& hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
+ static_cast<std::size_t>(age))};
+ const auto& eye_type_info{RawData::RandomMiiEyeType.at(index)};
+ const auto& eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
+ const auto& eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
+ const auto& nose_type_info{RawData::RandomMiiNoseType.at(index)};
+ const auto& mouth_type_info{RawData::RandomMiiMouthType.at(index)};
+ const auto& glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
+
+ data.faceline_type.Assign(
+ faceline_type_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
+ data.faceline_color.Assign(
+ faceline_color_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
+ data.faceline_wrinkle.Assign(
+ faceline_wrinkle_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
+ data.faceline_makeup.Assign(
+ faceline_makeup_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
+
+ data.hair_type.Assign(
+ hair_type_info.values[MiiUtil::GetRandomValue<std::size_t>(hair_type_info.values_count)]);
+ SetHairColor(RawData::GetHairColorFromVer3(
+ hair_color_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(hair_color_info.values_count)]));
+ SetHairFlip(MiiUtil::GetRandomValue(HairFlip::Max));
+
+ data.eye_type.Assign(
+ eye_type_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_type_info.values_count)]);
+
+ const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
+ const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
+ const auto eye_rotate_offset{32 - RawData::EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
+ const auto eye_rotate{32 - RawData::EyeRotateLookup[data.eye_type]};
+
+ SetEyeColor(RawData::GetEyeColorFromVer3(
+ eye_color_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_color_info.values_count)]));
+ SetEyeScale(4);
+ SetEyeAspect(3);
+ SetEyeRotate(static_cast<u8>(eye_rotate_offset - eye_rotate));
+ SetEyeX(2);
+ SetEyeY(static_cast<u8>(axis_y + 12));
+
+ data.eyebrow_type.Assign(
+ eyebrow_type_info
+ .values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
+
+ const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
+ const auto eyebrow_y{race == Race::Asian ? 9 : 10};
+ const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6};
+ const auto eyebrow_rotate{
+ 32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]};
+
+ SetEyebrowColor(GetHairColor());
+ SetEyebrowScale(4);
+ SetEyebrowAspect(3);
+ SetEyebrowRotate(static_cast<u8>(eyebrow_rotate_offset - eyebrow_rotate));
+ SetEyebrowX(2);
+ SetEyebrowY(static_cast<u8>(axis_y + eyebrow_y));
+
+ data.nose_type.Assign(
+ nose_type_info.values[MiiUtil::GetRandomValue<std::size_t>(nose_type_info.values_count)]);
+ SetNoseScale(gender == Gender::Female ? 3 : 4);
+ SetNoseY(static_cast<u8>(axis_y + 9));
+
+ const auto mouth_color{gender == Gender::Female ? MiiUtil::GetRandomValue<int>(4) : 0};
+
+ data.mouth_type.Assign(
+ mouth_type_info.values[MiiUtil::GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
+ SetMouthColor(RawData::GetMouthColorFromVer3(mouth_color));
+ SetMouthScale(4);
+ SetMouthAspect(3);
+ SetMouthY(static_cast<u8>(axis_y + 13));
+
+ SetBeardColor(GetHairColor());
+ SetMustacheScale(4);
+
+ if (gender == Gender::Male && age != Age::Young && MiiUtil::GetRandomValue<int>(10) < 2) {
+ const auto mustache_and_beard_flag{MiiUtil::GetRandomValue(BeardAndMustacheFlag::All)};
+
+ auto beard_type{BeardType::None};
+ auto mustache_type{MustacheType::None};
+
+ if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
+ BeardAndMustacheFlag::Beard) {
+ beard_type = MiiUtil::GetRandomValue(BeardType::Min, BeardType::Max);
+ }
+
+ if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
+ BeardAndMustacheFlag::Mustache) {
+ mustache_type = MiiUtil::GetRandomValue(MustacheType::Min, MustacheType::Max);
+ }
+
+ SetMustacheType(mustache_type);
+ SetBeardType(beard_type);
+ SetMustacheY(10);
+ } else {
+ SetMustacheType(MustacheType::None);
+ SetBeardType(BeardType::None);
+ SetMustacheY(static_cast<u8>(axis_y + 10));
+ }
+
+ const auto glasses_type_start{MiiUtil::GetRandomValue<std::size_t>(100)};
+ u8 glasses_type{};
+ while (glasses_type_start < glasses_type_info.values[glasses_type]) {
+ if (++glasses_type >= glasses_type_info.values_count) {
+ ASSERT(false);
+ break;
+ }
+ }
+
+ SetGlassType(static_cast<GlassType>(glasses_type));
+ SetGlassColor(RawData::GetGlassColorFromVer3(0));
+ SetGlassScale(4);
+
+ SetMoleType(MoleType::None);
+ SetMoleScale(4);
+ SetMoleX(2);
+ SetMoleY(20);
+}
+
+u32 CoreData::IsValid() const {
+ // TODO: Complete this
+ return 0;
+}
+
+void CoreData::SetFontRegion(FontRegion value) {
+ data.font_region.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetFavoriteColor(FavoriteColor value) {
+ data.favorite_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetGender(Gender value) {
+ data.gender.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetHeight(u8 value) {
+ data.height.Assign(value);
+}
+
+void CoreData::SetBuild(u8 value) {
+ data.build.Assign(value);
+}
+
+void CoreData::SetType(u8 value) {
+ data.type.Assign(value);
+}
+
+void CoreData::SetRegionMove(u8 value) {
+ data.region_move.Assign(value);
+}
+
+void CoreData::SetFacelineType(FacelineType value) {
+ data.faceline_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetFacelineColor(FacelineColor value) {
+ data.faceline_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetFacelineWrinkle(FacelineWrinkle value) {
+ data.faceline_wrinkle.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetFacelineMake(FacelineMake value) {
+ data.faceline_makeup.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetHairType(HairType value) {
+ data.hair_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetHairColor(CommonColor value) {
+ data.hair_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetHairFlip(HairFlip value) {
+ data.hair_flip.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetEyeType(EyeType value) {
+ data.eye_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetEyeColor(CommonColor value) {
+ data.eye_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetEyeScale(u8 value) {
+ data.eye_scale.Assign(value);
+}
+
+void CoreData::SetEyeAspect(u8 value) {
+ data.eye_aspect.Assign(value);
+}
+
+void CoreData::SetEyeRotate(u8 value) {
+ data.eye_rotate.Assign(value);
+}
+
+void CoreData::SetEyeX(u8 value) {
+ data.eye_x.Assign(value);
+}
+
+void CoreData::SetEyeY(u8 value) {
+ data.eye_y.Assign(value);
+}
+
+void CoreData::SetEyebrowType(EyebrowType value) {
+ data.eyebrow_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetEyebrowColor(CommonColor value) {
+ data.eyebrow_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetEyebrowScale(u8 value) {
+ data.eyebrow_scale.Assign(value);
+}
+
+void CoreData::SetEyebrowAspect(u8 value) {
+ data.eyebrow_aspect.Assign(value);
+}
+
+void CoreData::SetEyebrowRotate(u8 value) {
+ data.eyebrow_rotate.Assign(value);
+}
+
+void CoreData::SetEyebrowX(u8 value) {
+ data.eyebrow_x.Assign(value);
+}
+
+void CoreData::SetEyebrowY(u8 value) {
+ data.eyebrow_y.Assign(value);
+}
+
+void CoreData::SetNoseType(NoseType value) {
+ data.nose_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetNoseScale(u8 value) {
+ data.nose_scale.Assign(value);
+}
+
+void CoreData::SetNoseY(u8 value) {
+ data.nose_y.Assign(value);
+}
+
+void CoreData::SetMouthType(u8 value) {
+ data.mouth_type.Assign(value);
+}
+
+void CoreData::SetMouthColor(CommonColor value) {
+ data.mouth_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetMouthScale(u8 value) {
+ data.mouth_scale.Assign(value);
+}
+
+void CoreData::SetMouthAspect(u8 value) {
+ data.mouth_aspect.Assign(value);
+}
+
+void CoreData::SetMouthY(u8 value) {
+ data.mouth_y.Assign(value);
+}
+
+void CoreData::SetBeardColor(CommonColor value) {
+ data.beard_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetBeardType(BeardType value) {
+ data.beard_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetMustacheType(MustacheType value) {
+ data.mustache_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetMustacheScale(u8 value) {
+ data.mustache_scale.Assign(value);
+}
+
+void CoreData::SetMustacheY(u8 value) {
+ data.mustache_y.Assign(value);
+}
+
+void CoreData::SetGlassType(GlassType value) {
+ data.glasses_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetGlassColor(CommonColor value) {
+ data.glasses_color.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetGlassScale(u8 value) {
+ data.glasses_scale.Assign(value);
+}
+
+void CoreData::SetGlassY(u8 value) {
+ data.glasses_y.Assign(value);
+}
+
+void CoreData::SetMoleType(MoleType value) {
+ data.mole_type.Assign(static_cast<u32>(value));
+}
+
+void CoreData::SetMoleScale(u8 value) {
+ data.mole_scale.Assign(value);
+}
+
+void CoreData::SetMoleX(u8 value) {
+ data.mole_x.Assign(value);
+}
+
+void CoreData::SetMoleY(u8 value) {
+ data.mole_y.Assign(value);
+}
+
+void CoreData::SetNickname(Nickname nickname) {
+ name = nickname;
+}
+
+FontRegion CoreData::GetFontRegion() const {
+ return static_cast<FontRegion>(data.font_region.Value());
+}
+
+FavoriteColor CoreData::GetFavoriteColor() const {
+ return static_cast<FavoriteColor>(data.favorite_color.Value());
+}
+
+Gender CoreData::GetGender() const {
+ return static_cast<Gender>(data.gender.Value());
+}
+
+u8 CoreData::GetHeight() const {
+ return static_cast<u8>(data.height.Value());
+}
+
+u8 CoreData::GetBuild() const {
+ return static_cast<u8>(data.build.Value());
+}
+
+u8 CoreData::GetType() const {
+ return static_cast<u8>(data.type.Value());
+}
+
+u8 CoreData::GetRegionMove() const {
+ return static_cast<u8>(data.region_move.Value());
+}
+
+FacelineType CoreData::GetFacelineType() const {
+ return static_cast<FacelineType>(data.faceline_type.Value());
+}
+
+FacelineColor CoreData::GetFacelineColor() const {
+ return static_cast<FacelineColor>(data.faceline_color.Value());
+}
+
+FacelineWrinkle CoreData::GetFacelineWrinkle() const {
+ return static_cast<FacelineWrinkle>(data.faceline_wrinkle.Value());
+}
+
+FacelineMake CoreData::GetFacelineMake() const {
+ return static_cast<FacelineMake>(data.faceline_makeup.Value());
+}
+
+HairType CoreData::GetHairType() const {
+ return static_cast<HairType>(data.hair_type.Value());
+}
+
+CommonColor CoreData::GetHairColor() const {
+ return static_cast<CommonColor>(data.hair_color.Value());
+}
+
+HairFlip CoreData::GetHairFlip() const {
+ return static_cast<HairFlip>(data.hair_flip.Value());
+}
+
+EyeType CoreData::GetEyeType() const {
+ return static_cast<EyeType>(data.eye_type.Value());
+}
+
+CommonColor CoreData::GetEyeColor() const {
+ return static_cast<CommonColor>(data.eye_color.Value());
+}
+
+u8 CoreData::GetEyeScale() const {
+ return static_cast<u8>(data.eye_scale.Value());
+}
+
+u8 CoreData::GetEyeAspect() const {
+ return static_cast<u8>(data.eye_aspect.Value());
+}
+
+u8 CoreData::GetEyeRotate() const {
+ return static_cast<u8>(data.eye_rotate.Value());
+}
+
+u8 CoreData::GetEyeX() const {
+ return static_cast<u8>(data.eye_x.Value());
+}
+
+u8 CoreData::GetEyeY() const {
+ return static_cast<u8>(data.eye_y.Value());
+}
+
+EyebrowType CoreData::GetEyebrowType() const {
+ return static_cast<EyebrowType>(data.eyebrow_type.Value());
+}
+
+CommonColor CoreData::GetEyebrowColor() const {
+ return static_cast<CommonColor>(data.eyebrow_color.Value());
+}
+
+u8 CoreData::GetEyebrowScale() const {
+ return static_cast<u8>(data.eyebrow_scale.Value());
+}
+
+u8 CoreData::GetEyebrowAspect() const {
+ return static_cast<u8>(data.eyebrow_aspect.Value());
+}
+
+u8 CoreData::GetEyebrowRotate() const {
+ return static_cast<u8>(data.eyebrow_rotate.Value());
+}
+
+u8 CoreData::GetEyebrowX() const {
+ return static_cast<u8>(data.eyebrow_x.Value());
+}
+
+u8 CoreData::GetEyebrowY() const {
+ return static_cast<u8>(data.eyebrow_y.Value());
+}
+
+NoseType CoreData::GetNoseType() const {
+ return static_cast<NoseType>(data.nose_type.Value());
+}
+
+u8 CoreData::GetNoseScale() const {
+ return static_cast<u8>(data.nose_scale.Value());
+}
+
+u8 CoreData::GetNoseY() const {
+ return static_cast<u8>(data.nose_y.Value());
+}
+
+MouthType CoreData::GetMouthType() const {
+ return static_cast<MouthType>(data.mouth_type.Value());
+}
+
+CommonColor CoreData::GetMouthColor() const {
+ return static_cast<CommonColor>(data.mouth_color.Value());
+}
+
+u8 CoreData::GetMouthScale() const {
+ return static_cast<u8>(data.mouth_scale.Value());
+}
+
+u8 CoreData::GetMouthAspect() const {
+ return static_cast<u8>(data.mouth_aspect.Value());
+}
+
+u8 CoreData::GetMouthY() const {
+ return static_cast<u8>(data.mouth_y.Value());
+}
+
+CommonColor CoreData::GetBeardColor() const {
+ return static_cast<CommonColor>(data.beard_color.Value());
+}
+
+BeardType CoreData::GetBeardType() const {
+ return static_cast<BeardType>(data.beard_type.Value());
+}
+
+MustacheType CoreData::GetMustacheType() const {
+ return static_cast<MustacheType>(data.mustache_type.Value());
+}
+
+u8 CoreData::GetMustacheScale() const {
+ return static_cast<u8>(data.mustache_scale.Value());
+}
+
+u8 CoreData::GetMustacheY() const {
+ return static_cast<u8>(data.mustache_y.Value());
+}
+
+GlassType CoreData::GetGlassType() const {
+ return static_cast<GlassType>(data.glasses_type.Value());
+}
+
+CommonColor CoreData::GetGlassColor() const {
+ return static_cast<CommonColor>(data.glasses_color.Value());
+}
+
+u8 CoreData::GetGlassScale() const {
+ return static_cast<u8>(data.glasses_scale.Value());
+}
+
+u8 CoreData::GetGlassY() const {
+ return static_cast<u8>(data.glasses_y.Value());
+}
+
+MoleType CoreData::GetMoleType() const {
+ return static_cast<MoleType>(data.mole_type.Value());
+}
+
+u8 CoreData::GetMoleScale() const {
+ return static_cast<u8>(data.mole_scale.Value());
+}
+
+u8 CoreData::GetMoleX() const {
+ return static_cast<u8>(data.mole_x.Value());
+}
+
+u8 CoreData::GetMoleY() const {
+ return static_cast<u8>(data.mole_y.Value());
+}
+
+Nickname CoreData::GetNickname() const {
+ return name;
+}
+
+Nickname CoreData::GetDefaultNickname() const {
+ return {u'n', u'o', u' ', u'n', u'a', u'm', u'e'};
+}
+
+Nickname CoreData::GetInvalidNickname() const {
+ return {u'?', u'?', u'?'};
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/core_data.h b/src/core/hle/service/mii/types/core_data.h
new file mode 100644
index 000000000..cebcd2ee4
--- /dev/null
+++ b/src/core/hle/service/mii/types/core_data.h
@@ -0,0 +1,216 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/mii/mii_types.h"
+
+namespace Service::Mii {
+
+struct StoreDataBitFields {
+ union {
+ u32 word_0{};
+
+ BitField<0, 8, u32> hair_type;
+ BitField<8, 7, u32> height;
+ BitField<15, 1, u32> mole_type;
+ BitField<16, 7, u32> build;
+ BitField<23, 1, u32> hair_flip;
+ BitField<24, 7, u32> hair_color;
+ BitField<31, 1, u32> type;
+ };
+
+ union {
+ u32 word_1{};
+
+ BitField<0, 7, u32> eye_color;
+ BitField<7, 1, u32> gender;
+ BitField<8, 7, u32> eyebrow_color;
+ BitField<16, 7, u32> mouth_color;
+ BitField<24, 7, u32> beard_color;
+ };
+
+ union {
+ u32 word_2{};
+
+ BitField<0, 7, u32> glasses_color;
+ BitField<8, 6, u32> eye_type;
+ BitField<14, 2, u32> region_move;
+ BitField<16, 6, u32> mouth_type;
+ BitField<22, 2, u32> font_region;
+ BitField<24, 5, u32> eye_y;
+ BitField<29, 3, u32> glasses_scale;
+ };
+
+ union {
+ u32 word_3{};
+
+ BitField<0, 5, u32> eyebrow_type;
+ BitField<5, 3, u32> mustache_type;
+ BitField<8, 5, u32> nose_type;
+ BitField<13, 3, u32> beard_type;
+ BitField<16, 5, u32> nose_y;
+ BitField<21, 3, u32> mouth_aspect;
+ BitField<24, 5, u32> mouth_y;
+ BitField<29, 3, u32> eyebrow_aspect;
+ };
+
+ union {
+ u32 word_4{};
+
+ BitField<0, 5, u32> mustache_y;
+ BitField<5, 3, u32> eye_rotate;
+ BitField<8, 5, u32> glasses_y;
+ BitField<13, 3, u32> eye_aspect;
+ BitField<16, 5, u32> mole_x;
+ BitField<21, 3, u32> eye_scale;
+ BitField<24, 5, u32> mole_y;
+ };
+
+ union {
+ u32 word_5{};
+
+ BitField<0, 5, u32> glasses_type;
+ BitField<8, 4, u32> favorite_color;
+ BitField<12, 4, u32> faceline_type;
+ BitField<16, 4, u32> faceline_color;
+ BitField<20, 4, u32> faceline_wrinkle;
+ BitField<24, 4, u32> faceline_makeup;
+ BitField<28, 4, u32> eye_x;
+ };
+
+ union {
+ u32 word_6{};
+
+ BitField<0, 4, u32> eyebrow_scale;
+ BitField<4, 4, u32> eyebrow_rotate;
+ BitField<8, 4, u32> eyebrow_x;
+ BitField<12, 4, u32> eyebrow_y;
+ BitField<16, 4, u32> nose_scale;
+ BitField<20, 4, u32> mouth_scale;
+ BitField<24, 4, u32> mustache_scale;
+ BitField<28, 4, u32> mole_scale;
+ };
+};
+static_assert(sizeof(StoreDataBitFields) == 0x1c, "StoreDataBitFields has incorrect size.");
+static_assert(std::is_trivially_copyable_v<StoreDataBitFields>,
+ "StoreDataBitFields is not trivially copyable.");
+
+class CoreData {
+public:
+ void SetDefault();
+ void BuildRandom(Age age, Gender gender, Race race);
+
+ u32 IsValid() const;
+
+ void SetFontRegion(FontRegion value);
+ void SetFavoriteColor(FavoriteColor value);
+ void SetGender(Gender value);
+ void SetHeight(u8 value);
+ void SetBuild(u8 value);
+ void SetType(u8 value);
+ void SetRegionMove(u8 value);
+ void SetFacelineType(FacelineType value);
+ void SetFacelineColor(FacelineColor value);
+ void SetFacelineWrinkle(FacelineWrinkle value);
+ void SetFacelineMake(FacelineMake value);
+ void SetHairType(HairType value);
+ void SetHairColor(CommonColor value);
+ void SetHairFlip(HairFlip value);
+ void SetEyeType(EyeType value);
+ void SetEyeColor(CommonColor value);
+ void SetEyeScale(u8 value);
+ void SetEyeAspect(u8 value);
+ void SetEyeRotate(u8 value);
+ void SetEyeX(u8 value);
+ void SetEyeY(u8 value);
+ void SetEyebrowType(EyebrowType value);
+ void SetEyebrowColor(CommonColor value);
+ void SetEyebrowScale(u8 value);
+ void SetEyebrowAspect(u8 value);
+ void SetEyebrowRotate(u8 value);
+ void SetEyebrowX(u8 value);
+ void SetEyebrowY(u8 value);
+ void SetNoseType(NoseType value);
+ void SetNoseScale(u8 value);
+ void SetNoseY(u8 value);
+ void SetMouthType(u8 value);
+ void SetMouthColor(CommonColor value);
+ void SetMouthScale(u8 value);
+ void SetMouthAspect(u8 value);
+ void SetMouthY(u8 value);
+ void SetBeardColor(CommonColor value);
+ void SetBeardType(BeardType value);
+ void SetMustacheType(MustacheType value);
+ void SetMustacheScale(u8 value);
+ void SetMustacheY(u8 value);
+ void SetGlassType(GlassType value);
+ void SetGlassColor(CommonColor value);
+ void SetGlassScale(u8 value);
+ void SetGlassY(u8 value);
+ void SetMoleType(MoleType value);
+ void SetMoleScale(u8 value);
+ void SetMoleX(u8 value);
+ void SetMoleY(u8 value);
+ void SetNickname(Nickname nickname);
+
+ FontRegion GetFontRegion() const;
+ FavoriteColor GetFavoriteColor() const;
+ Gender GetGender() const;
+ u8 GetHeight() const;
+ u8 GetBuild() const;
+ u8 GetType() const;
+ u8 GetRegionMove() const;
+ FacelineType GetFacelineType() const;
+ FacelineColor GetFacelineColor() const;
+ FacelineWrinkle GetFacelineWrinkle() const;
+ FacelineMake GetFacelineMake() const;
+ HairType GetHairType() const;
+ CommonColor GetHairColor() const;
+ HairFlip GetHairFlip() const;
+ EyeType GetEyeType() const;
+ CommonColor GetEyeColor() const;
+ u8 GetEyeScale() const;
+ u8 GetEyeAspect() const;
+ u8 GetEyeRotate() const;
+ u8 GetEyeX() const;
+ u8 GetEyeY() const;
+ EyebrowType GetEyebrowType() const;
+ CommonColor GetEyebrowColor() const;
+ u8 GetEyebrowScale() const;
+ u8 GetEyebrowAspect() const;
+ u8 GetEyebrowRotate() const;
+ u8 GetEyebrowX() const;
+ u8 GetEyebrowY() const;
+ NoseType GetNoseType() const;
+ u8 GetNoseScale() const;
+ u8 GetNoseY() const;
+ MouthType GetMouthType() const;
+ CommonColor GetMouthColor() const;
+ u8 GetMouthScale() const;
+ u8 GetMouthAspect() const;
+ u8 GetMouthY() const;
+ CommonColor GetBeardColor() const;
+ BeardType GetBeardType() const;
+ MustacheType GetMustacheType() const;
+ u8 GetMustacheScale() const;
+ u8 GetMustacheY() const;
+ GlassType GetGlassType() const;
+ CommonColor GetGlassColor() const;
+ u8 GetGlassScale() const;
+ u8 GetGlassY() const;
+ MoleType GetMoleType() const;
+ u8 GetMoleScale() const;
+ u8 GetMoleX() const;
+ u8 GetMoleY() const;
+ Nickname GetNickname() const;
+ Nickname GetDefaultNickname() const;
+ Nickname GetInvalidNickname() const;
+
+private:
+ StoreDataBitFields data{};
+ Nickname name{};
+};
+static_assert(sizeof(CoreData) == 0x30, "CoreData has incorrect size.");
+
+}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.cpp b/src/core/hle/service/mii/types/raw_data.cpp
index 1442280c8..5143abcc8 100644
--- a/src/core/hle/service/mii/raw_data.cpp
+++ b/src/core/hle/service/mii/types/raw_data.cpp
@@ -1,11 +1,88 @@
// SPDX-FileCopyrightText: Ryujinx Team and Contributors
// SPDX-License-Identifier: MIT
-#include "core/hle/service/mii/raw_data.h"
+#include "core/hle/service/mii/types/raw_data.h"
namespace Service::Mii::RawData {
-const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
+constexpr std::array<u8, static_cast<u8>(FacelineColor::Count)> FromVer3FacelineColorTable{
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
+};
+
+constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3HairColorTable{
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
+ 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+ 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
+ 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
+ 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
+ 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
+};
+
+constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3EyeColorTable{
+ 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
+ 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+ 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
+ 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
+ 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
+ 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+};
+
+constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3MouthlineColorTable{
+ 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
+ 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
+ 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
+ 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
+ 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
+ 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
+};
+
+constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3GlassColorTable{
+ 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
+ 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+ 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
+ 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
+ 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
+ 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
+};
+
+constexpr std::array<u8, static_cast<u8>(GlassType::Count)> FromVer3GlassTypeTable{
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
+ 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
+};
+
+constexpr std::array<u8, 8> Ver3FacelineColorTable{
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5,
+};
+
+constexpr std::array<u8, 8> Ver3HairColorTable{
+ 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+};
+
+constexpr std::array<u8, 6> Ver3EyeColorTable{
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
+};
+
+constexpr std::array<u8, 5> Ver3MouthColorTable{
+ 0x13, 0x14, 0x15, 0x16, 0x17,
+};
+
+constexpr std::array<u8, 7> Ver3GlassColorTable{
+ 0x8, 0xe, 0xf, 0x10, 0x11, 0x12, 0x0,
+};
+
+const std::array<u8, 62> EyeRotateLookup{
+ 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
+ 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
+};
+
+const std::array<u8, 24> EyebrowRotateLookup{
+ 0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07, 0x04, 0x07, 0x06, 0x08,
+ 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05,
+};
+
+const std::array<Service::Mii::DefaultMii, 2> BaseMii{
Service::Mii::DefaultMii{
.face_type = 0,
.face_color = 0,
@@ -51,11 +128,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Male,
+ .gender = 0,
.favorite_color = 0,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -102,12 +180,16 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Female,
+ .gender = 1,
.favorite_color = 0,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
+};
+
+const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
Service::Mii::DefaultMii{
.face_type = 0,
.face_color = 4,
@@ -153,11 +235,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Male,
+ .gender = 0,
.favorite_color = 4,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -204,11 +287,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Male,
+ .gender = 0,
.favorite_color = 5,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -255,11 +339,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Male,
+ .gender = 0,
.favorite_color = 0,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -306,11 +391,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Female,
+ .gender = 1,
.favorite_color = 2,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -357,11 +443,12 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Female,
+ .gender = 1,
.favorite_color = 6,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
Service::Mii::DefaultMii{
.face_type = 0,
@@ -408,176 +495,177 @@ const std::array<Service::Mii::DefaultMii, 8> DefaultMii{
.mole_y = 20,
.height = 64,
.weight = 64,
- .gender = Gender::Female,
+ .gender = 1,
.favorite_color = 7,
- .region = 0,
- .font_region = FontRegion::Standard,
+ .region_move = 0,
+ .font_region = 0,
.type = 0,
+ .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFaceline{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiFaceline{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 13,
.values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 13,
.values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 10,
.values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
},
};
-const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor{
- Service::Mii::RandomMiiData3{
+const std::array<RandomMiiData3, 6> RandomMiiFacelineColor{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 0,
.values_count = 10,
.values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 1,
.values_count = 10,
.values = {0, 0, 0, 0, 1, 1, 2, 3, 3, 3},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 2,
.values_count = 10,
.values = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 0,
.values_count = 10,
.values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 1,
.values_count = 10,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 3},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 2,
.values_count = 10,
@@ -585,407 +673,407 @@ const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor{
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineWrinkle{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineMakeup{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiHairType{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 30,
.values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45,
47, 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 75, 76, 86, 89},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 31,
.values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47,
48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 31,
.values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47,
48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 38,
.values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 40, 42, 43, 44, 45, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 75, 76, 86, 89},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 39,
.values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 39,
.values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 18,
.values = {13, 23, 30, 36, 37, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 19,
.values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 19,
.values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 39,
.values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 24, 25, 26, 28, 46, 50, 61, 62, 63, 64, 69, 76, 77, 79, 80, 83, 85},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 42,
.values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50,
61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 42,
.values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50,
61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 44,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 42, 50,
58, 60, 62, 63, 64, 69, 71, 76, 79, 80, 81, 82, 83, 86},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 44,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58,
60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 44,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58,
60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 24,
.values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14,
16, 17, 18, 20, 21, 24, 25, 58, 62, 69, 76, 83},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 27,
.values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17,
18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 27,
.values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17,
18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85},
@@ -993,55 +1081,55 @@ const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType{
};
const std::array<RandomMiiData3, 9> RandomMiiHairColor{
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 0,
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 1,
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 0,
.arg_2 = 2,
.values_count = 20,
.values = {0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 0,
.values_count = 20,
.values = {2, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 1,
.values_count = 20,
.values = {2, 3, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 1,
.arg_2 = 2,
.values_count = 20,
.values = {2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 2,
.arg_2 = 0,
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 2,
.arg_2 = 1,
.values_count = 20,
.values = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3},
},
- Service::Mii::RandomMiiData3{
+ RandomMiiData3{
.arg_1 = 2,
.arg_2 = 2,
.values_count = 20,
@@ -1049,598 +1137,642 @@ const std::array<RandomMiiData3, 9> RandomMiiHairColor{
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyeType{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiEyeType{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 26,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27,
29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 26,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27,
29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 27,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 26, 27,
29, 32, 34, 36, 38, 39, 41, 43, 47, 48, 49, 53, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 35,
.values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29,
31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 35,
.values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29,
31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 35,
.values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 21, 22, 26, 27, 29,
31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 48, 49, 50, 53, 56, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 30,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21,
22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 30,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21,
22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 30,
.values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 21, 22,
26, 31, 32, 34, 36, 37, 39, 41, 44, 48, 49, 50, 51, 53, 57},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 39,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27,
28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 39,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27,
28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 40,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 26,
27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 46,
.values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17,
18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37,
38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 46,
.values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17,
18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37,
38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 46,
.values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18,
19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 37,
38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 34,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23,
24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 34,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23,
24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 35,
.values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24,
25, 26, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
},
};
-const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiEyeColor{
- Service::Mii::RandomMiiData2{
+const std::array<RandomMiiData2, 3> RandomMiiEyeColor{
+ RandomMiiData2{
.arg_1 = 0,
.values_count = 10,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
},
- Service::Mii::RandomMiiData2{
+ RandomMiiData2{
.arg_1 = 1,
.values_count = 10,
.values = {0, 1, 1, 2, 3, 3, 4, 4, 4, 5},
},
- Service::Mii::RandomMiiData2{
+ RandomMiiData2{
.arg_1 = 2,
.values_count = 10,
.values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyebrowType{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiEyebrowType{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 23,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 23,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 23,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 21,
.values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 21,
.values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 21,
.values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 9,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 9,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 9,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 11,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 11,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 11,
.values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 9,
.values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 9,
.values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 9,
.values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiNoseType{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiNoseType{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 11,
.values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 11,
.values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 11,
.values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 15,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 18,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 15,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 8,
.values = {0, 1, 3, 4, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 8,
.values = {0, 1, 3, 4, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 8,
.values = {0, 1, 3, 4, 8, 10, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 12,
.values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 11,
.values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 10,
.values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 12,
.values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 11,
.values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 10,
.values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14},
},
};
-const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiMouthType{
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Black,
+const std::array<RandomMiiData4, 18> RandomMiiMouthType{
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 25,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 17, 18,
19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 27,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17,
18, 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 28,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17,
18, 19, 21, 22, 23, 25, 26, 28, 30, 31, 32, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 24,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 26,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 26,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 24,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 26,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Male,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Male),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 26,
.values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Black),
.values_count = 25,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15,
17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Black),
.values_count = 26,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Black,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Black),
.values_count = 26,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::White),
.values_count = 25,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15,
17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::White),
.values_count = 26,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::White,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::White),
.values_count = 25,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 17, 18, 19, 21, 22, 23, 24, 25, 29, 33, 35},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Young,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Young),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 24,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14,
15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Normal,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Normal),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 25,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
},
- Service::Mii::RandomMiiData4{
- .gender = Gender::Female,
- .age = Age::Old,
- .race = Race::Asian,
+ RandomMiiData4{
+ .gender = static_cast<u32>(Gender::Female),
+ .age = static_cast<u32>(Age::Old),
+ .race = static_cast<u32>(Race::Asian),
.values_count = 25,
.values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
},
};
-const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiGlassType{
- Service::Mii::RandomMiiData2{
+const std::array<RandomMiiData2, 3> RandomMiiGlassType{
+ RandomMiiData2{
.arg_1 = 0,
.values_count = 9,
.values = {90, 94, 96, 100, 0, 0, 0, 0, 0},
},
- Service::Mii::RandomMiiData2{
+ RandomMiiData2{
.arg_1 = 1,
.values_count = 9,
.values = {83, 86, 90, 93, 94, 96, 98, 100, 0},
},
- Service::Mii::RandomMiiData2{
+ RandomMiiData2{
.arg_1 = 2,
.values_count = 9,
.values = {78, 83, 0, 93, 0, 0, 98, 100, 0},
},
};
+u8 FromVer3GetFacelineColor(u8 color) {
+ return FromVer3FacelineColorTable[color];
+}
+
+u8 FromVer3GetHairColor(u8 color) {
+ return FromVer3HairColorTable[color];
+}
+
+u8 FromVer3GetEyeColor(u8 color) {
+ return FromVer3EyeColorTable[color];
+}
+
+u8 FromVer3GetMouthlineColor(u8 color) {
+ return FromVer3MouthlineColorTable[color];
+}
+
+u8 FromVer3GetGlassColor(u8 color) {
+ return FromVer3GlassColorTable[color];
+}
+
+u8 FromVer3GetGlassType(u8 type) {
+ return FromVer3GlassTypeTable[type];
+}
+
+FacelineColor GetFacelineColorFromVer3(u32 color) {
+ return static_cast<FacelineColor>(Ver3FacelineColorTable[color]);
+}
+
+CommonColor GetHairColorFromVer3(u32 color) {
+ return static_cast<CommonColor>(Ver3HairColorTable[color]);
+}
+
+CommonColor GetEyeColorFromVer3(u32 color) {
+ return static_cast<CommonColor>(Ver3EyeColorTable[color]);
+}
+
+CommonColor GetMouthColorFromVer3(u32 color) {
+ return static_cast<CommonColor>(Ver3MouthColorTable[color]);
+}
+
+CommonColor GetGlassColorFromVer3(u32 color) {
+ return static_cast<CommonColor>(Ver3GlassColorTable[color]);
+}
+
} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types/raw_data.h b/src/core/hle/service/mii/types/raw_data.h
new file mode 100644
index 000000000..9a4cfa738
--- /dev/null
+++ b/src/core/hle/service/mii/types/raw_data.h
@@ -0,0 +1,73 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <array>
+
+#include "core/hle/service/mii/mii_types.h"
+
+namespace Service::Mii::RawData {
+
+struct RandomMiiValues {
+ std::array<u8, 188> values{};
+};
+static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
+
+struct RandomMiiData4 {
+ u32 gender{};
+ u32 age{};
+ u32 race{};
+ u32 values_count{};
+ std::array<u32, 47> values{};
+};
+static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
+
+struct RandomMiiData3 {
+ u32 arg_1;
+ u32 arg_2;
+ u32 values_count;
+ std::array<u32, 47> values{};
+};
+static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
+
+struct RandomMiiData2 {
+ u32 arg_1;
+ u32 values_count;
+ std::array<u32, 47> values{};
+};
+static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
+
+extern const std::array<Service::Mii::DefaultMii, 2> BaseMii;
+extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii;
+
+extern const std::array<u8, 62> EyeRotateLookup;
+extern const std::array<u8, 24> EyebrowRotateLookup;
+
+extern const std::array<RandomMiiData4, 18> RandomMiiFaceline;
+extern const std::array<RandomMiiData3, 6> RandomMiiFacelineColor;
+extern const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle;
+extern const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup;
+extern const std::array<RandomMiiData4, 18> RandomMiiHairType;
+extern const std::array<RandomMiiData3, 9> RandomMiiHairColor;
+extern const std::array<RandomMiiData4, 18> RandomMiiEyeType;
+extern const std::array<RandomMiiData2, 3> RandomMiiEyeColor;
+extern const std::array<RandomMiiData4, 18> RandomMiiEyebrowType;
+extern const std::array<RandomMiiData4, 18> RandomMiiNoseType;
+extern const std::array<RandomMiiData4, 18> RandomMiiMouthType;
+extern const std::array<RandomMiiData2, 3> RandomMiiGlassType;
+
+u8 FromVer3GetFacelineColor(u8 color);
+u8 FromVer3GetHairColor(u8 color);
+u8 FromVer3GetEyeColor(u8 color);
+u8 FromVer3GetMouthlineColor(u8 color);
+u8 FromVer3GetGlassColor(u8 color);
+u8 FromVer3GetGlassType(u8 type);
+
+FacelineColor GetFacelineColorFromVer3(u32 color);
+CommonColor GetHairColorFromVer3(u32 color);
+CommonColor GetEyeColorFromVer3(u32 color);
+CommonColor GetMouthColorFromVer3(u32 color);
+CommonColor GetGlassColorFromVer3(u32 color);
+
+} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types/store_data.cpp b/src/core/hle/service/mii/types/store_data.cpp
new file mode 100644
index 000000000..8fce636c7
--- /dev/null
+++ b/src/core/hle/service/mii/types/store_data.cpp
@@ -0,0 +1,643 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/mii/mii_util.h"
+#include "core/hle/service/mii/types/raw_data.h"
+#include "core/hle/service/mii/types/store_data.h"
+
+namespace Service::Mii {
+
+void StoreData::BuildDefault(u32 mii_index) {
+ const auto& default_mii = RawData::DefaultMii[mii_index];
+ core_data.SetDefault();
+
+ core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
+ core_data.SetFacelineColor(
+ RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
+ core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
+ core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
+
+ core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
+ core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
+ core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
+ core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
+ core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
+ core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
+ core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
+ core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
+ core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
+ core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
+
+ core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
+ core_data.SetEyebrowColor(
+ RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
+ core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
+ core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
+ core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
+ core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
+ core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
+
+ core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
+ core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
+ core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
+
+ core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
+ core_data.SetMouthColor(
+ RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
+ core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
+ core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
+ core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
+
+ core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
+ core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
+ core_data.SetBeardColor(
+ RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
+ core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
+ core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
+
+ core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
+ core_data.SetGlassColor(
+ RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
+ core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
+ core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
+
+ core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
+ core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
+ core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
+ core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
+
+ core_data.SetHeight(static_cast<u8>(default_mii.height));
+ core_data.SetBuild(static_cast<u8>(default_mii.weight));
+ core_data.SetGender(static_cast<Gender>(default_mii.gender));
+ core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
+ core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
+ core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
+ core_data.SetType(static_cast<u8>(default_mii.type));
+ core_data.SetNickname(default_mii.nickname);
+
+ const auto device_id = MiiUtil::GetDeviceId();
+ create_id = MiiUtil::MakeCreateId();
+ device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
+ data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
+}
+
+void StoreData::BuildBase(Gender gender) {
+ const auto& default_mii = RawData::BaseMii[gender == Gender::Female ? 1 : 0];
+ core_data.SetDefault();
+
+ core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
+ core_data.SetFacelineColor(
+ RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
+ core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
+ core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
+
+ core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
+ core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
+ core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
+ core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
+ core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
+ core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
+ core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
+ core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
+ core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
+ core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
+
+ core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
+ core_data.SetEyebrowColor(
+ RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
+ core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
+ core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
+ core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
+ core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
+ core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
+
+ core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
+ core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
+ core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
+
+ core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
+ core_data.SetMouthColor(
+ RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
+ core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
+ core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
+ core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
+
+ core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
+ core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
+ core_data.SetBeardColor(
+ RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
+ core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
+ core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
+
+ core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
+ core_data.SetGlassColor(
+ RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
+ core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
+ core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
+
+ core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
+ core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
+ core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
+ core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
+
+ core_data.SetHeight(static_cast<u8>(default_mii.height));
+ core_data.SetBuild(static_cast<u8>(default_mii.weight));
+ core_data.SetGender(static_cast<Gender>(default_mii.gender));
+ core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
+ core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
+ core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
+ core_data.SetType(static_cast<u8>(default_mii.type));
+ core_data.SetNickname(default_mii.nickname);
+
+ const auto device_id = MiiUtil::GetDeviceId();
+ create_id = MiiUtil::MakeCreateId();
+ device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
+ data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
+}
+
+void StoreData::BuildRandom(Age age, Gender gender, Race race) {
+ core_data.BuildRandom(age, gender, race);
+ const auto device_id = MiiUtil::GetDeviceId();
+ create_id = MiiUtil::MakeCreateId();
+ device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
+ data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
+}
+
+void StoreData::SetInvalidName() {
+ const auto& invalid_name = core_data.GetInvalidNickname();
+ const auto device_id = MiiUtil::GetDeviceId();
+ core_data.SetNickname(invalid_name);
+ device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
+ data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
+}
+
+bool StoreData::IsSpecial() const {
+ return GetType() == 1;
+}
+
+u32 StoreData::IsValid() const {
+ // TODO: complete this
+ return 0;
+}
+
+void StoreData::SetFontRegion(FontRegion value) {
+ core_data.SetFontRegion(value);
+}
+
+void StoreData::SetFavoriteColor(FavoriteColor value) {
+ core_data.SetFavoriteColor(value);
+}
+
+void StoreData::SetGender(Gender value) {
+ core_data.SetGender(value);
+}
+
+void StoreData::SetHeight(u8 value) {
+ core_data.SetHeight(value);
+}
+
+void StoreData::SetBuild(u8 value) {
+ core_data.SetBuild(value);
+}
+
+void StoreData::SetType(u8 value) {
+ core_data.SetType(value);
+}
+
+void StoreData::SetRegionMove(u8 value) {
+ core_data.SetRegionMove(value);
+}
+
+void StoreData::SetFacelineType(FacelineType value) {
+ core_data.SetFacelineType(value);
+}
+
+void StoreData::SetFacelineColor(FacelineColor value) {
+ core_data.SetFacelineColor(value);
+}
+
+void StoreData::SetFacelineWrinkle(FacelineWrinkle value) {
+ core_data.SetFacelineWrinkle(value);
+}
+
+void StoreData::SetFacelineMake(FacelineMake value) {
+ core_data.SetFacelineMake(value);
+}
+
+void StoreData::SetHairType(HairType value) {
+ core_data.SetHairType(value);
+}
+
+void StoreData::SetHairColor(CommonColor value) {
+ core_data.SetHairColor(value);
+}
+
+void StoreData::SetHairFlip(HairFlip value) {
+ core_data.SetHairFlip(value);
+}
+
+void StoreData::SetEyeType(EyeType value) {
+ core_data.SetEyeType(value);
+}
+
+void StoreData::SetEyeColor(CommonColor value) {
+ core_data.SetEyeColor(value);
+}
+
+void StoreData::SetEyeScale(u8 value) {
+ core_data.SetEyeScale(value);
+}
+
+void StoreData::SetEyeAspect(u8 value) {
+ core_data.SetEyeAspect(value);
+}
+
+void StoreData::SetEyeRotate(u8 value) {
+ core_data.SetEyeRotate(value);
+}
+
+void StoreData::SetEyeX(u8 value) {
+ core_data.SetEyeX(value);
+}
+
+void StoreData::SetEyeY(u8 value) {
+ core_data.SetEyeY(value);
+}
+
+void StoreData::SetEyebrowType(EyebrowType value) {
+ core_data.SetEyebrowType(value);
+}
+
+void StoreData::SetEyebrowColor(CommonColor value) {
+ core_data.SetEyebrowColor(value);
+}
+
+void StoreData::SetEyebrowScale(u8 value) {
+ core_data.SetEyebrowScale(value);
+}
+
+void StoreData::SetEyebrowAspect(u8 value) {
+ core_data.SetEyebrowAspect(value);
+}
+
+void StoreData::SetEyebrowRotate(u8 value) {
+ core_data.SetEyebrowRotate(value);
+}
+
+void StoreData::SetEyebrowX(u8 value) {
+ core_data.SetEyebrowX(value);
+}
+
+void StoreData::SetEyebrowY(u8 value) {
+ core_data.SetEyebrowY(value);
+}
+
+void StoreData::SetNoseType(NoseType value) {
+ core_data.SetNoseType(value);
+}
+
+void StoreData::SetNoseScale(u8 value) {
+ core_data.SetNoseScale(value);
+}
+
+void StoreData::SetNoseY(u8 value) {
+ core_data.SetNoseY(value);
+}
+
+void StoreData::SetMouthType(u8 value) {
+ core_data.SetMouthType(value);
+}
+
+void StoreData::SetMouthColor(CommonColor value) {
+ core_data.SetMouthColor(value);
+}
+
+void StoreData::SetMouthScale(u8 value) {
+ core_data.SetMouthScale(value);
+}
+
+void StoreData::SetMouthAspect(u8 value) {
+ core_data.SetMouthAspect(value);
+}
+
+void StoreData::SetMouthY(u8 value) {
+ core_data.SetMouthY(value);
+}
+
+void StoreData::SetBeardColor(CommonColor value) {
+ core_data.SetBeardColor(value);
+}
+
+void StoreData::SetBeardType(BeardType value) {
+ core_data.SetBeardType(value);
+}
+
+void StoreData::SetMustacheType(MustacheType value) {
+ core_data.SetMustacheType(value);
+}
+
+void StoreData::SetMustacheScale(u8 value) {
+ core_data.SetMustacheScale(value);
+}
+
+void StoreData::SetMustacheY(u8 value) {
+ core_data.SetMustacheY(value);
+}
+
+void StoreData::SetGlassType(GlassType value) {
+ core_data.SetGlassType(value);
+}
+
+void StoreData::SetGlassColor(CommonColor value) {
+ core_data.SetGlassColor(value);
+}
+
+void StoreData::SetGlassScale(u8 value) {
+ core_data.SetGlassScale(value);
+}
+
+void StoreData::SetGlassY(u8 value) {
+ core_data.SetGlassY(value);
+}
+
+void StoreData::SetMoleType(MoleType value) {
+ core_data.SetMoleType(value);
+}
+
+void StoreData::SetMoleScale(u8 value) {
+ core_data.SetMoleScale(value);
+}
+
+void StoreData::SetMoleX(u8 value) {
+ core_data.SetMoleX(value);
+}
+
+void StoreData::SetMoleY(u8 value) {
+ core_data.SetMoleY(value);
+}
+
+void StoreData::SetNickname(Nickname value) {
+ core_data.SetNickname(value);
+}
+
+Common::UUID StoreData::GetCreateId() const {
+ return create_id;
+}
+
+FontRegion StoreData::GetFontRegion() const {
+ return static_cast<FontRegion>(core_data.GetFontRegion());
+}
+
+FavoriteColor StoreData::GetFavoriteColor() const {
+ return core_data.GetFavoriteColor();
+}
+
+Gender StoreData::GetGender() const {
+ return core_data.GetGender();
+}
+
+u8 StoreData::GetHeight() const {
+ return core_data.GetHeight();
+}
+
+u8 StoreData::GetBuild() const {
+ return core_data.GetBuild();
+}
+
+u8 StoreData::GetType() const {
+ return core_data.GetType();
+}
+
+u8 StoreData::GetRegionMove() const {
+ return core_data.GetRegionMove();
+}
+
+FacelineType StoreData::GetFacelineType() const {
+ return core_data.GetFacelineType();
+}
+
+FacelineColor StoreData::GetFacelineColor() const {
+ return core_data.GetFacelineColor();
+}
+
+FacelineWrinkle StoreData::GetFacelineWrinkle() const {
+ return core_data.GetFacelineWrinkle();
+}
+
+FacelineMake StoreData::GetFacelineMake() const {
+ return core_data.GetFacelineMake();
+}
+
+HairType StoreData::GetHairType() const {
+ return core_data.GetHairType();
+}
+
+CommonColor StoreData::GetHairColor() const {
+ return core_data.GetHairColor();
+}
+
+HairFlip StoreData::GetHairFlip() const {
+ return core_data.GetHairFlip();
+}
+
+EyeType StoreData::GetEyeType() const {
+ return core_data.GetEyeType();
+}
+
+CommonColor StoreData::GetEyeColor() const {
+ return core_data.GetEyeColor();
+}
+
+u8 StoreData::GetEyeScale() const {
+ return core_data.GetEyeScale();
+}
+
+u8 StoreData::GetEyeAspect() const {
+ return core_data.GetEyeAspect();
+}
+
+u8 StoreData::GetEyeRotate() const {
+ return core_data.GetEyeRotate();
+}
+
+u8 StoreData::GetEyeX() const {
+ return core_data.GetEyeX();
+}
+
+u8 StoreData::GetEyeY() const {
+ return core_data.GetEyeY();
+}
+
+EyebrowType StoreData::GetEyebrowType() const {
+ return core_data.GetEyebrowType();
+}
+
+CommonColor StoreData::GetEyebrowColor() const {
+ return core_data.GetEyebrowColor();
+}
+
+u8 StoreData::GetEyebrowScale() const {
+ return core_data.GetEyebrowScale();
+}
+
+u8 StoreData::GetEyebrowAspect() const {
+ return core_data.GetEyebrowAspect();
+}
+
+u8 StoreData::GetEyebrowRotate() const {
+ return core_data.GetEyebrowRotate();
+}
+
+u8 StoreData::GetEyebrowX() const {
+ return core_data.GetEyebrowX();
+}
+
+u8 StoreData::GetEyebrowY() const {
+ return core_data.GetEyebrowY();
+}
+
+NoseType StoreData::GetNoseType() const {
+ return core_data.GetNoseType();
+}
+
+u8 StoreData::GetNoseScale() const {
+ return core_data.GetNoseScale();
+}
+
+u8 StoreData::GetNoseY() const {
+ return core_data.GetNoseY();
+}
+
+MouthType StoreData::GetMouthType() const {
+ return core_data.GetMouthType();
+}
+
+CommonColor StoreData::GetMouthColor() const {
+ return core_data.GetMouthColor();
+}
+
+u8 StoreData::GetMouthScale() const {
+ return core_data.GetMouthScale();
+}
+
+u8 StoreData::GetMouthAspect() const {
+ return core_data.GetMouthAspect();
+}
+
+u8 StoreData::GetMouthY() const {
+ return core_data.GetMouthY();
+}
+
+CommonColor StoreData::GetBeardColor() const {
+ return core_data.GetBeardColor();
+}
+
+BeardType StoreData::GetBeardType() const {
+ return core_data.GetBeardType();
+}
+
+MustacheType StoreData::GetMustacheType() const {
+ return core_data.GetMustacheType();
+}
+
+u8 StoreData::GetMustacheScale() const {
+ return core_data.GetMustacheScale();
+}
+
+u8 StoreData::GetMustacheY() const {
+ return core_data.GetMustacheY();
+}
+
+GlassType StoreData::GetGlassType() const {
+ return core_data.GetGlassType();
+}
+
+CommonColor StoreData::GetGlassColor() const {
+ return core_data.GetGlassColor();
+}
+
+u8 StoreData::GetGlassScale() const {
+ return core_data.GetGlassScale();
+}
+
+u8 StoreData::GetGlassY() const {
+ return core_data.GetGlassY();
+}
+
+MoleType StoreData::GetMoleType() const {
+ return core_data.GetMoleType();
+}
+
+u8 StoreData::GetMoleScale() const {
+ return core_data.GetMoleScale();
+}
+
+u8 StoreData::GetMoleX() const {
+ return core_data.GetMoleX();
+}
+
+u8 StoreData::GetMoleY() const {
+ return core_data.GetMoleY();
+}
+
+Nickname StoreData::GetNickname() const {
+ return core_data.GetNickname();
+}
+
+bool StoreData::operator==(const StoreData& data) {
+ bool is_identical = data.core_data.IsValid() == 0;
+ is_identical &= core_data.GetNickname().data == data.core_data.GetNickname().data;
+ is_identical &= GetCreateId() == data.GetCreateId();
+ is_identical &= GetFontRegion() == data.GetFontRegion();
+ is_identical &= GetFavoriteColor() == data.GetFavoriteColor();
+ is_identical &= GetGender() == data.GetGender();
+ is_identical &= GetHeight() == data.GetHeight();
+ is_identical &= GetBuild() == data.GetBuild();
+ is_identical &= GetType() == data.GetType();
+ is_identical &= GetRegionMove() == data.GetRegionMove();
+ is_identical &= GetFacelineType() == data.GetFacelineType();
+ is_identical &= GetFacelineColor() == data.GetFacelineColor();
+ is_identical &= GetFacelineWrinkle() == data.GetFacelineWrinkle();
+ is_identical &= GetFacelineMake() == data.GetFacelineMake();
+ is_identical &= GetHairType() == data.GetHairType();
+ is_identical &= GetHairColor() == data.GetHairColor();
+ is_identical &= GetHairFlip() == data.GetHairFlip();
+ is_identical &= GetEyeType() == data.GetEyeType();
+ is_identical &= GetEyeColor() == data.GetEyeColor();
+ is_identical &= GetEyeScale() == data.GetEyeScale();
+ is_identical &= GetEyeAspect() == data.GetEyeAspect();
+ is_identical &= GetEyeRotate() == data.GetEyeRotate();
+ is_identical &= GetEyeX() == data.GetEyeX();
+ is_identical &= GetEyeY() == data.GetEyeY();
+ is_identical &= GetEyebrowType() == data.GetEyebrowType();
+ is_identical &= GetEyebrowColor() == data.GetEyebrowColor();
+ is_identical &= GetEyebrowScale() == data.GetEyebrowScale();
+ is_identical &= GetEyebrowAspect() == data.GetEyebrowAspect();
+ is_identical &= GetEyebrowRotate() == data.GetEyebrowRotate();
+ is_identical &= GetEyebrowX() == data.GetEyebrowX();
+ is_identical &= GetEyebrowY() == data.GetEyebrowY();
+ is_identical &= GetNoseType() == data.GetNoseType();
+ is_identical &= GetNoseScale() == data.GetNoseScale();
+ is_identical &= GetNoseY() == data.GetNoseY();
+ is_identical &= GetMouthType() == data.GetMouthType();
+ is_identical &= GetMouthColor() == data.GetMouthColor();
+ is_identical &= GetMouthScale() == data.GetMouthScale();
+ is_identical &= GetMouthAspect() == data.GetMouthAspect();
+ is_identical &= GetMouthY() == data.GetMouthY();
+ is_identical &= GetBeardColor() == data.GetBeardColor();
+ is_identical &= GetBeardType() == data.GetBeardType();
+ is_identical &= GetMustacheType() == data.GetMustacheType();
+ is_identical &= GetMustacheScale() == data.GetMustacheScale();
+ is_identical &= GetMustacheY() == data.GetMustacheY();
+ is_identical &= GetGlassType() == data.GetGlassType();
+ is_identical &= GetGlassColor() == data.GetGlassColor();
+ is_identical &= GetGlassScale() == data.GetGlassScale();
+ is_identical &= GetGlassY() == data.GetGlassY();
+ is_identical &= GetMoleType() == data.GetMoleType();
+ is_identical &= GetMoleScale() == data.GetMoleScale();
+ is_identical &= GetMoleX() == data.GetMoleX();
+ is_identical &= data.GetMoleY() == data.GetMoleY();
+ return is_identical;
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/store_data.h b/src/core/hle/service/mii/types/store_data.h
new file mode 100644
index 000000000..224c32cf8
--- /dev/null
+++ b/src/core/hle/service/mii/types/store_data.h
@@ -0,0 +1,145 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/mii/mii_types.h"
+#include "core/hle/service/mii/types/core_data.h"
+
+namespace Service::Mii {
+
+class StoreData {
+public:
+ // nn::mii::detail::StoreDataRaw::BuildDefault
+ void BuildDefault(u32 mii_index);
+ // nn::mii::detail::StoreDataRaw::BuildDefault
+
+ void BuildBase(Gender gender);
+ // nn::mii::detail::StoreDataRaw::BuildRandom
+ void BuildRandom(Age age, Gender gender, Race race);
+
+ bool IsSpecial() const;
+
+ u32 IsValid() const;
+
+ void SetFontRegion(FontRegion value);
+ void SetFavoriteColor(FavoriteColor value);
+ void SetGender(Gender value);
+ void SetHeight(u8 value);
+ void SetBuild(u8 value);
+ void SetType(u8 value);
+ void SetRegionMove(u8 value);
+ void SetFacelineType(FacelineType value);
+ void SetFacelineColor(FacelineColor value);
+ void SetFacelineWrinkle(FacelineWrinkle value);
+ void SetFacelineMake(FacelineMake value);
+ void SetHairType(HairType value);
+ void SetHairColor(CommonColor value);
+ void SetHairFlip(HairFlip value);
+ void SetEyeType(EyeType value);
+ void SetEyeColor(CommonColor value);
+ void SetEyeScale(u8 value);
+ void SetEyeAspect(u8 value);
+ void SetEyeRotate(u8 value);
+ void SetEyeX(u8 value);
+ void SetEyeY(u8 value);
+ void SetEyebrowType(EyebrowType value);
+ void SetEyebrowColor(CommonColor value);
+ void SetEyebrowScale(u8 value);
+ void SetEyebrowAspect(u8 value);
+ void SetEyebrowRotate(u8 value);
+ void SetEyebrowX(u8 value);
+ void SetEyebrowY(u8 value);
+ void SetNoseType(NoseType value);
+ void SetNoseScale(u8 value);
+ void SetNoseY(u8 value);
+ void SetMouthType(u8 value);
+ void SetMouthColor(CommonColor value);
+ void SetMouthScale(u8 value);
+ void SetMouthAspect(u8 value);
+ void SetMouthY(u8 value);
+ void SetBeardColor(CommonColor value);
+ void SetBeardType(BeardType value);
+ void SetMustacheType(MustacheType value);
+ void SetMustacheScale(u8 value);
+ void SetMustacheY(u8 value);
+ void SetGlassType(GlassType value);
+ void SetGlassColor(CommonColor value);
+ void SetGlassScale(u8 value);
+ void SetGlassY(u8 value);
+ void SetMoleType(MoleType value);
+ void SetMoleScale(u8 value);
+ void SetMoleX(u8 value);
+ void SetMoleY(u8 value);
+ void SetNickname(Nickname nickname);
+ void SetInvalidName();
+
+ Common::UUID GetCreateId() const;
+ FontRegion GetFontRegion() const;
+ FavoriteColor GetFavoriteColor() const;
+ Gender GetGender() const;
+ u8 GetHeight() const;
+ u8 GetBuild() const;
+ u8 GetType() const;
+ u8 GetRegionMove() const;
+ FacelineType GetFacelineType() const;
+ FacelineColor GetFacelineColor() const;
+ FacelineWrinkle GetFacelineWrinkle() const;
+ FacelineMake GetFacelineMake() const;
+ HairType GetHairType() const;
+ CommonColor GetHairColor() const;
+ HairFlip GetHairFlip() const;
+ EyeType GetEyeType() const;
+ CommonColor GetEyeColor() const;
+ u8 GetEyeScale() const;
+ u8 GetEyeAspect() const;
+ u8 GetEyeRotate() const;
+ u8 GetEyeX() const;
+ u8 GetEyeY() const;
+ EyebrowType GetEyebrowType() const;
+ CommonColor GetEyebrowColor() const;
+ u8 GetEyebrowScale() const;
+ u8 GetEyebrowAspect() const;
+ u8 GetEyebrowRotate() const;
+ u8 GetEyebrowX() const;
+ u8 GetEyebrowY() const;
+ NoseType GetNoseType() const;
+ u8 GetNoseScale() const;
+ u8 GetNoseY() const;
+ MouthType GetMouthType() const;
+ CommonColor GetMouthColor() const;
+ u8 GetMouthScale() const;
+ u8 GetMouthAspect() const;
+ u8 GetMouthY() const;
+ CommonColor GetBeardColor() const;
+ BeardType GetBeardType() const;
+ MustacheType GetMustacheType() const;
+ u8 GetMustacheScale() const;
+ u8 GetMustacheY() const;
+ GlassType GetGlassType() const;
+ CommonColor GetGlassColor() const;
+ u8 GetGlassScale() const;
+ u8 GetGlassY() const;
+ MoleType GetMoleType() const;
+ u8 GetMoleScale() const;
+ u8 GetMoleX() const;
+ u8 GetMoleY() const;
+ Nickname GetNickname() const;
+
+ bool operator==(const StoreData& data);
+
+private:
+ CoreData core_data{};
+ Common::UUID create_id{};
+ u16 data_crc{};
+ u16 device_crc{};
+};
+static_assert(sizeof(StoreData) == 0x44, "StoreData has incorrect size.");
+
+struct StoreDataElement {
+ StoreData store_data{};
+ Source source{};
+};
+static_assert(sizeof(StoreDataElement) == 0x48, "StoreDataElement has incorrect size.");
+
+}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp
new file mode 100644
index 000000000..1c28e0b1b
--- /dev/null
+++ b/src/core/hle/service/mii/types/ver3_store_data.cpp
@@ -0,0 +1,241 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/mii/mii_util.h"
+#include "core/hle/service/mii/types/raw_data.h"
+#include "core/hle/service/mii/types/store_data.h"
+#include "core/hle/service/mii/types/ver3_store_data.h"
+
+namespace Service::Mii {
+
+void NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) {
+ faceline_color = static_cast<u8>(store_data.GetFacelineColor()) & 0xf;
+ hair_color = static_cast<u8>(store_data.GetHairColor()) & 0x7f;
+ eye_color = static_cast<u8>(store_data.GetEyeColor()) & 0x7f;
+ eyebrow_color = static_cast<u8>(store_data.GetEyebrowColor()) & 0x7f;
+ mouth_color = static_cast<u8>(store_data.GetMouthColor()) & 0x7f;
+ beard_color = static_cast<u8>(store_data.GetBeardColor()) & 0x7f;
+ glass_color = static_cast<u8>(store_data.GetGlassColor()) & 0x7f;
+ glass_type = static_cast<u8>(store_data.GetGlassType()) & 0x1f;
+}
+
+void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const {
+ out_store_data.BuildBase(Gender::Male);
+
+ if (!IsValid()) {
+ return;
+ }
+
+ // TODO: We are ignoring a bunch of data from the mii_v3
+
+ out_store_data.SetGender(static_cast<Gender>(mii_information.gender.Value()));
+ out_store_data.SetFavoriteColor(
+ static_cast<FavoriteColor>(mii_information.favorite_color.Value()));
+ out_store_data.SetHeight(height);
+ out_store_data.SetBuild(build);
+
+ out_store_data.SetNickname(mii_name);
+ out_store_data.SetFontRegion(
+ static_cast<FontRegion>(static_cast<u8>(region_information.font_region)));
+
+ out_store_data.SetFacelineType(
+ static_cast<FacelineType>(appearance_bits1.faceline_type.Value()));
+ out_store_data.SetFacelineColor(
+ static_cast<FacelineColor>(appearance_bits1.faceline_color.Value()));
+ out_store_data.SetFacelineWrinkle(
+ static_cast<FacelineWrinkle>(appearance_bits2.faceline_wrinkle.Value()));
+ out_store_data.SetFacelineMake(
+ static_cast<FacelineMake>(appearance_bits2.faceline_make.Value()));
+
+ out_store_data.SetHairType(static_cast<HairType>(hair_type));
+ out_store_data.SetHairColor(static_cast<CommonColor>(appearance_bits3.hair_color.Value()));
+ out_store_data.SetHairFlip(static_cast<HairFlip>(appearance_bits3.hair_flip.Value()));
+
+ out_store_data.SetEyeType(static_cast<EyeType>(appearance_bits4.eye_type.Value()));
+ out_store_data.SetEyeColor(static_cast<CommonColor>(appearance_bits4.eye_color.Value()));
+ out_store_data.SetEyeScale(static_cast<u8>(appearance_bits4.eye_scale));
+ out_store_data.SetEyeAspect(static_cast<u8>(appearance_bits4.eye_aspect));
+ out_store_data.SetEyeRotate(static_cast<u8>(appearance_bits4.eye_rotate));
+ out_store_data.SetEyeX(static_cast<u8>(appearance_bits4.eye_x));
+ out_store_data.SetEyeY(static_cast<u8>(appearance_bits4.eye_y));
+
+ out_store_data.SetEyebrowType(static_cast<EyebrowType>(appearance_bits5.eyebrow_type.Value()));
+ out_store_data.SetEyebrowColor(
+ static_cast<CommonColor>(appearance_bits5.eyebrow_color.Value()));
+ out_store_data.SetEyebrowScale(static_cast<u8>(appearance_bits5.eyebrow_scale));
+ out_store_data.SetEyebrowAspect(static_cast<u8>(appearance_bits5.eyebrow_aspect));
+ out_store_data.SetEyebrowRotate(static_cast<u8>(appearance_bits5.eyebrow_rotate));
+ out_store_data.SetEyebrowX(static_cast<u8>(appearance_bits5.eyebrow_x));
+ out_store_data.SetEyebrowY(static_cast<u8>(appearance_bits5.eyebrow_y));
+
+ out_store_data.SetNoseType(static_cast<NoseType>(appearance_bits6.nose_type.Value()));
+ out_store_data.SetNoseScale(static_cast<u8>(appearance_bits6.nose_scale));
+ out_store_data.SetNoseY(static_cast<u8>(appearance_bits6.nose_y));
+
+ out_store_data.SetMouthType(static_cast<u8>(appearance_bits7.mouth_type));
+ out_store_data.SetMouthColor(static_cast<CommonColor>(appearance_bits7.mouth_color.Value()));
+ out_store_data.SetMouthScale(static_cast<u8>(appearance_bits7.mouth_scale));
+ out_store_data.SetMouthAspect(static_cast<u8>(appearance_bits7.mouth_aspect));
+ out_store_data.SetMouthY(static_cast<u8>(appearance_bits8.mouth_y));
+
+ out_store_data.SetMustacheType(
+ static_cast<MustacheType>(appearance_bits8.mustache_type.Value()));
+ out_store_data.SetMustacheScale(static_cast<u8>(appearance_bits9.mustache_scale));
+ out_store_data.SetMustacheY(static_cast<u8>(appearance_bits9.mustache_y));
+
+ out_store_data.SetBeardType(static_cast<BeardType>(appearance_bits9.beard_type.Value()));
+ out_store_data.SetBeardColor(static_cast<CommonColor>(appearance_bits9.beard_color.Value()));
+
+ out_store_data.SetGlassType(static_cast<GlassType>(appearance_bits10.glass_type.Value()));
+ out_store_data.SetGlassColor(static_cast<CommonColor>(appearance_bits10.glass_color.Value()));
+ out_store_data.SetGlassScale(static_cast<u8>(appearance_bits10.glass_scale));
+ out_store_data.SetGlassY(static_cast<u8>(appearance_bits10.glass_y));
+
+ out_store_data.SetMoleType(static_cast<MoleType>(appearance_bits11.mole_type.Value()));
+ out_store_data.SetMoleScale(static_cast<u8>(appearance_bits11.mole_scale));
+ out_store_data.SetMoleX(static_cast<u8>(appearance_bits11.mole_x));
+ out_store_data.SetMoleY(static_cast<u8>(appearance_bits11.mole_y));
+}
+
+void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
+ version = 1;
+ mii_information.gender.Assign(static_cast<u8>(store_data.GetGender()));
+ mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor()));
+ height = store_data.GetHeight();
+ build = store_data.GetBuild();
+
+ mii_name = store_data.GetNickname();
+ region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion()));
+
+ appearance_bits1.faceline_type.Assign(static_cast<u8>(store_data.GetFacelineType()));
+ appearance_bits2.faceline_wrinkle.Assign(static_cast<u8>(store_data.GetFacelineWrinkle()));
+ appearance_bits2.faceline_make.Assign(static_cast<u8>(store_data.GetFacelineMake()));
+
+ hair_type = static_cast<u8>(store_data.GetHairType());
+ appearance_bits3.hair_flip.Assign(static_cast<u8>(store_data.GetHairFlip()));
+
+ appearance_bits4.eye_type.Assign(static_cast<u8>(store_data.GetEyeType()));
+ appearance_bits4.eye_scale.Assign(store_data.GetEyeScale());
+ appearance_bits4.eye_aspect.Assign(store_data.GetEyebrowAspect());
+ appearance_bits4.eye_rotate.Assign(store_data.GetEyeRotate());
+ appearance_bits4.eye_x.Assign(store_data.GetEyeX());
+ appearance_bits4.eye_y.Assign(store_data.GetEyeY());
+
+ appearance_bits5.eyebrow_type.Assign(static_cast<u8>(store_data.GetEyebrowType()));
+ appearance_bits5.eyebrow_scale.Assign(store_data.GetEyebrowScale());
+ appearance_bits5.eyebrow_aspect.Assign(store_data.GetEyebrowAspect());
+ appearance_bits5.eyebrow_rotate.Assign(store_data.GetEyebrowRotate());
+ appearance_bits5.eyebrow_x.Assign(store_data.GetEyebrowX());
+ appearance_bits5.eyebrow_y.Assign(store_data.GetEyebrowY());
+
+ appearance_bits6.nose_type.Assign(static_cast<u8>(store_data.GetNoseType()));
+ appearance_bits6.nose_scale.Assign(store_data.GetNoseScale());
+ appearance_bits6.nose_y.Assign(store_data.GetNoseY());
+
+ appearance_bits7.mouth_type.Assign(static_cast<u8>(store_data.GetMouthType()));
+ appearance_bits7.mouth_scale.Assign(store_data.GetMouthScale());
+ appearance_bits7.mouth_aspect.Assign(store_data.GetMouthAspect());
+ appearance_bits8.mouth_y.Assign(store_data.GetMouthY());
+
+ appearance_bits8.mustache_type.Assign(static_cast<u8>(store_data.GetMustacheType()));
+ appearance_bits9.mustache_scale.Assign(store_data.GetMustacheScale());
+ appearance_bits9.mustache_y.Assign(store_data.GetMustacheY());
+
+ appearance_bits9.beard_type.Assign(static_cast<u8>(store_data.GetBeardType()));
+
+ appearance_bits10.glass_scale.Assign(store_data.GetGlassScale());
+ appearance_bits10.glass_y.Assign(store_data.GetGlassY());
+
+ appearance_bits11.mole_type.Assign(static_cast<u8>(store_data.GetMoleType()));
+ appearance_bits11.mole_scale.Assign(store_data.GetMoleScale());
+ appearance_bits11.mole_x.Assign(store_data.GetMoleX());
+ appearance_bits11.mole_y.Assign(store_data.GetMoleY());
+
+ // These types are converted to V3 from a table
+ appearance_bits1.faceline_color.Assign(
+ RawData::FromVer3GetFacelineColor(static_cast<u8>(store_data.GetFacelineColor())));
+ appearance_bits3.hair_color.Assign(
+ RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetHairColor())));
+ appearance_bits4.eye_color.Assign(
+ RawData::FromVer3GetEyeColor(static_cast<u8>(store_data.GetEyeColor())));
+ appearance_bits5.eyebrow_color.Assign(
+ RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetEyebrowColor())));
+ appearance_bits7.mouth_color.Assign(
+ RawData::FromVer3GetMouthlineColor(static_cast<u8>(store_data.GetMouthColor())));
+ appearance_bits9.beard_color.Assign(
+ RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetBeardColor())));
+ appearance_bits10.glass_color.Assign(
+ RawData::FromVer3GetGlassColor(static_cast<u8>(store_data.GetGlassColor())));
+ appearance_bits10.glass_type.Assign(
+ RawData::FromVer3GetGlassType(static_cast<u8>(store_data.GetGlassType())));
+
+ crc = MiiUtil::CalculateCrc16(&version, sizeof(Ver3StoreData) - sizeof(u16));
+}
+
+u32 Ver3StoreData::IsValid() const {
+ bool is_valid = version == 0 || version == 3;
+
+ is_valid = is_valid && (mii_name.data[0] != '\0');
+
+ is_valid = is_valid && (mii_information.birth_month < 13);
+ is_valid = is_valid && (mii_information.birth_day < 32);
+ is_valid = is_valid && (mii_information.favorite_color <= static_cast<u8>(FavoriteColor::Max));
+ is_valid = is_valid && (height <= MaxHeight);
+ is_valid = is_valid && (build <= MaxBuild);
+
+ is_valid = is_valid && (appearance_bits1.faceline_type <= static_cast<u8>(FacelineType::Max));
+ is_valid = is_valid && (appearance_bits1.faceline_color <= MaxVer3CommonColor - 2);
+ is_valid =
+ is_valid && (appearance_bits2.faceline_wrinkle <= static_cast<u8>(FacelineWrinkle::Max));
+ is_valid = is_valid && (appearance_bits2.faceline_make <= static_cast<u8>(FacelineMake::Max));
+
+ is_valid = is_valid && (hair_type <= static_cast<u8>(HairType::Max));
+ is_valid = is_valid && (appearance_bits3.hair_color <= MaxVer3CommonColor);
+
+ is_valid = is_valid && (appearance_bits4.eye_type <= static_cast<u8>(EyeType::Max));
+ is_valid = is_valid && (appearance_bits4.eye_color <= MaxVer3CommonColor - 2);
+ is_valid = is_valid && (appearance_bits4.eye_scale <= MaxEyeScale);
+ is_valid = is_valid && (appearance_bits4.eye_aspect <= MaxEyeAspect);
+ is_valid = is_valid && (appearance_bits4.eye_rotate <= MaxEyeRotate);
+ is_valid = is_valid && (appearance_bits4.eye_x <= MaxEyeX);
+ is_valid = is_valid && (appearance_bits4.eye_y <= MaxEyeY);
+
+ is_valid = is_valid && (appearance_bits5.eyebrow_type <= static_cast<u8>(EyebrowType::Max));
+ is_valid = is_valid && (appearance_bits5.eyebrow_color <= MaxVer3CommonColor);
+ is_valid = is_valid && (appearance_bits5.eyebrow_scale <= MaxEyebrowScale);
+ is_valid = is_valid && (appearance_bits5.eyebrow_aspect <= MaxEyebrowAspect);
+ is_valid = is_valid && (appearance_bits5.eyebrow_rotate <= MaxEyebrowRotate);
+ is_valid = is_valid && (appearance_bits5.eyebrow_x <= MaxEyebrowX);
+ is_valid = is_valid && (appearance_bits5.eyebrow_y <= MaxEyebrowY);
+
+ is_valid = is_valid && (appearance_bits6.nose_type <= static_cast<u8>(NoseType::Max));
+ is_valid = is_valid && (appearance_bits6.nose_scale <= MaxNoseScale);
+ is_valid = is_valid && (appearance_bits6.nose_y <= MaxNoseY);
+
+ is_valid = is_valid && (appearance_bits7.mouth_type <= static_cast<u8>(MouthType::Max));
+ is_valid = is_valid && (appearance_bits7.mouth_color <= MaxVer3CommonColor - 3);
+ is_valid = is_valid && (appearance_bits7.mouth_scale <= MaxMouthScale);
+ is_valid = is_valid && (appearance_bits7.mouth_aspect <= MaxMoutAspect);
+ is_valid = is_valid && (appearance_bits8.mouth_y <= MaxMouthY);
+
+ is_valid = is_valid && (appearance_bits8.mustache_type <= static_cast<u8>(MustacheType::Max));
+ is_valid = is_valid && (appearance_bits9.mustache_scale < MaxMustacheScale);
+ is_valid = is_valid && (appearance_bits9.mustache_y <= MasMustacheY);
+
+ is_valid = is_valid && (appearance_bits9.beard_type <= static_cast<u8>(BeardType::Max));
+ is_valid = is_valid && (appearance_bits9.beard_color <= MaxVer3CommonColor);
+
+ is_valid = is_valid && (appearance_bits10.glass_type <= MaxVer3GlassType);
+ is_valid = is_valid && (appearance_bits10.glass_color <= MaxVer3CommonColor - 2);
+ is_valid = is_valid && (appearance_bits10.glass_scale <= MaxGlassScale);
+ is_valid = is_valid && (appearance_bits10.glass_y <= MaxGlassScale);
+
+ is_valid = is_valid && (appearance_bits11.mole_type <= static_cast<u8>(MoleType::Max));
+ is_valid = is_valid && (appearance_bits11.mole_scale <= MaxMoleScale);
+ is_valid = is_valid && (appearance_bits11.mole_x <= MaxMoleX);
+ is_valid = is_valid && (appearance_bits11.mole_y <= MaxMoleY);
+
+ return is_valid;
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/types/ver3_store_data.h b/src/core/hle/service/mii/types/ver3_store_data.h
new file mode 100644
index 000000000..47907bf7d
--- /dev/null
+++ b/src/core/hle/service/mii/types/ver3_store_data.h
@@ -0,0 +1,160 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/mii/mii_types.h"
+
+namespace Service::Mii {
+class StoreData;
+
+// This is nn::mii::Ver3StoreData
+// Based on citra HLE::Applets::MiiData and PretendoNetwork.
+// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
+// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
+
+struct NfpStoreDataExtension {
+ void SetFromStoreData(const StoreData& store_data);
+
+ u8 faceline_color;
+ u8 hair_color;
+ u8 eye_color;
+ u8 eyebrow_color;
+ u8 mouth_color;
+ u8 beard_color;
+ u8 glass_color;
+ u8 glass_type;
+};
+static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
+
+#pragma pack(push, 4)
+class Ver3StoreData {
+public:
+ void BuildToStoreData(StoreData& out_store_data) const;
+ void BuildFromStoreData(const StoreData& store_data);
+
+ u32 IsValid() const;
+
+ u8 version;
+ union {
+ u8 raw;
+
+ BitField<0, 1, u8> allow_copying;
+ BitField<1, 1, u8> profanity_flag;
+ BitField<2, 2, u8> region_lock;
+ BitField<4, 2, u8> font_region;
+ } region_information;
+ u16_be mii_id;
+ u64_be system_id;
+ u32_be specialness_and_creation_date;
+ std::array<u8, 6> creator_mac;
+ u16_be padding;
+ union {
+ u16 raw;
+
+ BitField<0, 1, u16> gender;
+ BitField<1, 4, u16> birth_month;
+ BitField<5, 5, u16> birth_day;
+ BitField<10, 4, u16> favorite_color;
+ BitField<14, 1, u16> favorite;
+ } mii_information;
+ Nickname mii_name;
+ u8 height;
+ u8 build;
+ union {
+ u8 raw;
+
+ BitField<0, 1, u8> disable_sharing;
+ BitField<1, 4, u8> faceline_type;
+ BitField<5, 3, u8> faceline_color;
+ } appearance_bits1;
+ union {
+ u8 raw;
+
+ BitField<0, 4, u8> faceline_wrinkle;
+ BitField<4, 4, u8> faceline_make;
+ } appearance_bits2;
+ u8 hair_type;
+ union {
+ u8 raw;
+
+ BitField<0, 3, u8> hair_color;
+ BitField<3, 1, u8> hair_flip;
+ } appearance_bits3;
+ union {
+ u32 raw;
+
+ BitField<0, 6, u32> eye_type;
+ BitField<6, 3, u32> eye_color;
+ BitField<9, 4, u32> eye_scale;
+ BitField<13, 3, u32> eye_aspect;
+ BitField<16, 5, u32> eye_rotate;
+ BitField<21, 4, u32> eye_x;
+ BitField<25, 5, u32> eye_y;
+ } appearance_bits4;
+ union {
+ u32 raw;
+
+ BitField<0, 5, u32> eyebrow_type;
+ BitField<5, 3, u32> eyebrow_color;
+ BitField<8, 4, u32> eyebrow_scale;
+ BitField<12, 3, u32> eyebrow_aspect;
+ BitField<16, 4, u32> eyebrow_rotate;
+ BitField<21, 4, u32> eyebrow_x;
+ BitField<25, 5, u32> eyebrow_y;
+ } appearance_bits5;
+ union {
+ u16 raw;
+
+ BitField<0, 5, u16> nose_type;
+ BitField<5, 4, u16> nose_scale;
+ BitField<9, 5, u16> nose_y;
+ } appearance_bits6;
+ union {
+ u16 raw;
+
+ BitField<0, 6, u16> mouth_type;
+ BitField<6, 3, u16> mouth_color;
+ BitField<9, 4, u16> mouth_scale;
+ BitField<13, 3, u16> mouth_aspect;
+ } appearance_bits7;
+ union {
+ u8 raw;
+
+ BitField<0, 5, u8> mouth_y;
+ BitField<5, 3, u8> mustache_type;
+ } appearance_bits8;
+ u8 allow_copying;
+ union {
+ u16 raw;
+
+ BitField<0, 3, u16> beard_type;
+ BitField<3, 3, u16> beard_color;
+ BitField<6, 4, u16> mustache_scale;
+ BitField<10, 5, u16> mustache_y;
+ } appearance_bits9;
+ union {
+ u16 raw;
+
+ BitField<0, 4, u16> glass_type;
+ BitField<4, 3, u16> glass_color;
+ BitField<7, 4, u16> glass_scale;
+ BitField<11, 5, u16> glass_y;
+ } appearance_bits10;
+ union {
+ u16 raw;
+
+ BitField<0, 1, u16> mole_type;
+ BitField<1, 4, u16> mole_scale;
+ BitField<5, 5, u16> mole_x;
+ BitField<10, 5, u16> mole_y;
+ } appearance_bits11;
+
+ Nickname author_name;
+ INSERT_PADDING_BYTES(0x2);
+ u16_be crc;
+};
+static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
+#pragma pack(pop)
+
+}; // namespace Service::Mii
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 49446bc42..5dda12343 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -28,7 +28,6 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/mii/mii_manager.h"
-#include "core/hle/service/mii/types.h"
#include "core/hle/service/nfc/common/amiibo_crypto.h"
#include "core/hle/service/nfc/common/device.h"
#include "core/hle/service/nfc/mifare_result.h"
@@ -681,12 +680,16 @@ Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const {
return ResultRegistrationIsNotInitialized;
}
- Service::Mii::MiiManager manager;
+ Mii::CharInfo char_info{};
+ Mii::StoreData store_data{};
+ tag_data.owner_mii.BuildToStoreData(store_data);
+ char_info.SetFromStoreData(store_data);
+
const auto& settings = tag_data.settings;
// TODO: Validate this data
register_info = {
- .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
+ .mii_char_info = char_info,
.creation_date = settings.init_date.GetWriteDate(),
.amiibo_name = GetAmiiboName(settings),
.font_region = settings.settings.font_region,
@@ -825,8 +828,11 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
return ResultWrongDeviceState;
}
- Service::Mii::MiiManager manager;
- const auto mii = manager.BuildDefault(0);
+ Service::Mii::StoreData store_data{};
+ Service::Mii::NfpStoreDataExtension extension{};
+ store_data.BuildBase(Mii::Gender::Male);
+ extension.SetFromStoreData(store_data);
+
auto& settings = tag_data.settings;
if (tag_data.settings.settings.amiibo_initialized == 0) {
@@ -835,8 +841,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
}
SetAmiiboName(settings, register_info.amiibo_name);
- tag_data.owner_mii = manager.BuildFromStoreData(mii);
- tag_data.mii_extension = manager.SetFromStoreData(mii);
+ tag_data.owner_mii.BuildFromStoreData(store_data);
+ tag_data.mii_extension = extension;
tag_data.unknown = 0;
tag_data.unknown2 = {};
settings.country_code_id = 0;
@@ -1453,7 +1459,7 @@ void NfcDevice::UpdateRegisterInfoCrc() {
void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
const NFP::EncryptedNTAG215File& encrypted_file) const {
- Service::Mii::MiiManager manager;
+ Service::Mii::StoreData store_data{};
auto& settings = stubbed_tag_data.settings;
stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file);
@@ -1467,7 +1473,8 @@ void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'});
settings.settings.font_region.Assign(0);
settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
- stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildDefault(0));
+ store_data.BuildBase(Mii::Gender::Male);
+ stubbed_tag_data.owner_mii.BuildFromStoreData(store_data);
// Admin info
settings.settings.amiibo_initialized.Assign(1);
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index aed12a7f8..f96d21220 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -6,7 +6,9 @@
#include <array>
#include "common/swap.h"
-#include "core/hle/service/mii/types.h"
+#include "core/hle/service/mii/types/char_info.h"
+#include "core/hle/service/mii/types/store_data.h"
+#include "core/hle/service/mii/types/ver3_store_data.h"
#include "core/hle/service/nfc/nfc_types.h"
namespace Service::NFP {
@@ -322,7 +324,7 @@ static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
// This is nn::nfp::RegisterInfoPrivate
struct RegisterInfoPrivate {
- Service::Mii::MiiStoreData mii_store_data;
+ Service::Mii::StoreData mii_store_data;
WriteDate creation_date;
AmiiboName amiibo_name;
u8 font_region;
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index a51ca5444..0ca05257e 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -160,8 +160,8 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
u32 address{};
auto& smmu_allocator = host1x.Allocator();
auto& smmu_memory_manager = host1x.MemoryManager();
- while (!(address =
- smmu_allocator.Allocate(static_cast<u32>(handle_description->aligned_size)))) {
+ while ((address = smmu_allocator.Allocate(
+ static_cast<u32>(handle_description->aligned_size))) == 0) {
// Free handles until the allocation succeeds
std::scoped_lock queueLock(unmap_queue_lock);
if (auto freeHandleDesc{unmap_queue.front()}) {
diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp
index d834a0c1f..212057cfc 100644
--- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp
+++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp
@@ -477,7 +477,8 @@ public:
return ResultInternalError;
}
PCCERT_CONTEXT some_cert = nullptr;
- while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) {
+ while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert)) !=
+ nullptr) {
out_certs->emplace_back(static_cast<u8*>(some_cert->pbCertEncoded),
static_cast<u8*>(some_cert->pbCertEncoded) +
some_cert->cbCertEncoded);
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp
index 5d28300e6..a983f23ea 100644
--- a/src/core/internal_network/network.cpp
+++ b/src/core/internal_network/network.cpp
@@ -48,15 +48,32 @@ enum class CallType {
using socklen_t = int;
+SOCKET interrupt_socket = static_cast<SOCKET>(-1);
+
+void InterruptSocketOperations() {
+ closesocket(interrupt_socket);
+}
+
+void AcknowledgeInterrupt() {
+ interrupt_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+}
+
void Initialize() {
WSADATA wsa_data;
(void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
+
+ AcknowledgeInterrupt();
}
void Finalize() {
+ InterruptSocketOperations();
WSACleanup();
}
+SOCKET GetInterruptSocket() {
+ return interrupt_socket;
+}
+
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
sockaddr_in result;
@@ -157,9 +174,42 @@ constexpr int SD_RECEIVE = SHUT_RD;
constexpr int SD_SEND = SHUT_WR;
constexpr int SD_BOTH = SHUT_RDWR;
-void Initialize() {}
+int interrupt_pipe_fd[2] = {-1, -1};
-void Finalize() {}
+void Initialize() {
+ if (pipe(interrupt_pipe_fd) != 0) {
+ LOG_ERROR(Network, "Failed to create interrupt pipe!");
+ }
+ int flags = fcntl(interrupt_pipe_fd[0], F_GETFL);
+ ASSERT_MSG(fcntl(interrupt_pipe_fd[0], F_SETFL, flags | O_NONBLOCK) == 0,
+ "Failed to set nonblocking state for interrupt pipe");
+}
+
+void Finalize() {
+ if (interrupt_pipe_fd[0] >= 0) {
+ close(interrupt_pipe_fd[0]);
+ }
+ if (interrupt_pipe_fd[1] >= 0) {
+ close(interrupt_pipe_fd[1]);
+ }
+}
+
+void InterruptSocketOperations() {
+ u8 value = 0;
+ ASSERT(write(interrupt_pipe_fd[1], &value, sizeof(value)) == 1);
+}
+
+void AcknowledgeInterrupt() {
+ u8 value = 0;
+ ssize_t ret = read(interrupt_pipe_fd[0], &value, sizeof(value));
+ if (ret != 1 && errno != EAGAIN && errno != EWOULDBLOCK) {
+ LOG_ERROR(Network, "Failed to acknowledge interrupt on shutdown");
+ }
+}
+
+SOCKET GetInterruptSocket() {
+ return interrupt_pipe_fd[0];
+}
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
sockaddr_in result;
@@ -490,6 +540,14 @@ NetworkInstance::~NetworkInstance() {
Finalize();
}
+void CancelPendingSocketOperations() {
+ InterruptSocketOperations();
+}
+
+void RestartSocketOperations() {
+ AcknowledgeInterrupt();
+}
+
std::optional<IPv4Address> GetHostIPv4Address() {
const auto network_interface = Network::GetSelectedNetworkInterface();
if (!network_interface.has_value()) {
@@ -560,7 +618,14 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
return result;
});
- const int result = WSAPoll(host_pollfds.data(), static_cast<ULONG>(num), timeout);
+ host_pollfds.push_back(WSAPOLLFD{
+ .fd = GetInterruptSocket(),
+ .events = POLLIN,
+ .revents = 0,
+ });
+
+ const int result =
+ WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), timeout);
if (result == 0) {
ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
[](WSAPOLLFD fd) { return fd.revents == 0; }));
@@ -627,6 +692,24 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
+
+ std::vector<WSAPOLLFD> host_pollfds{
+ WSAPOLLFD{fd, POLLIN, 0},
+ WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
+ };
+
+ while (true) {
+ const int pollres =
+ WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
+ if (host_pollfds[1].revents != 0) {
+ // Interrupt signaled before a client could be accepted, break
+ return {AcceptResult{}, Errno::AGAIN};
+ }
+ if (pollres > 0) {
+ break;
+ }
+ }
+
const SOCKET new_socket = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
if (new_socket == INVALID_SOCKET) {
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h
index c7e20ae34..b7b7d773a 100644
--- a/src/core/internal_network/network.h
+++ b/src/core/internal_network/network.h
@@ -96,6 +96,9 @@ public:
~NetworkInstance();
};
+void CancelPendingSocketOperations();
+void RestartSocketOperations();
+
#ifdef _WIN32
constexpr IPv4Address TranslateIPv4(in_addr addr) {
auto& bytes = addr.S_un.S_un_b;
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 07c65dc1a..b6e355622 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -108,7 +108,7 @@ std::string GetFileTypeString(FileType type) {
return "unknown";
}
-constexpr std::array<const char*, 66> RESULT_MESSAGES{
+constexpr std::array<const char*, 68> RESULT_MESSAGES{
"The operation completed successfully.",
"The loader requested to load is already loaded.",
"The operation is not implemented.",
@@ -175,6 +175,8 @@ constexpr std::array<const char*, 66> RESULT_MESSAGES{
"The KIP BLZ decompression of the section failed unexpectedly.",
"The INI file has a bad header.",
"The INI file contains more than the maximum allowable number of KIP files.",
+ "Integrity verification could not be performed for this file.",
+ "Integrity verification failed.",
};
std::string GetResultStatusString(ResultStatus status) {
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 721eb8e8c..b4828f7cd 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -3,6 +3,7 @@
#pragma once
+#include <functional>
#include <iosfwd>
#include <memory>
#include <optional>
@@ -132,6 +133,8 @@ enum class ResultStatus : u16 {
ErrorBLZDecompressionFailed,
ErrorBadINIHeader,
ErrorINITooManyKIPs,
+ ErrorIntegrityVerificationNotImplemented,
+ ErrorIntegrityVerificationFailed,
};
std::string GetResultStatusString(ResultStatus status);
@@ -170,6 +173,13 @@ public:
virtual LoadResult Load(Kernel::KProcess& process, Core::System& system) = 0;
/**
+ * Try to verify the integrity of the file.
+ */
+ virtual ResultStatus VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) {
+ return ResultStatus::ErrorIntegrityVerificationNotImplemented;
+ }
+
+ /**
* Get the code (typically .code section) of the application
*
* @param[out] buffer Reference to buffer to store data
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 09d40e695..4feb6968a 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -3,6 +3,8 @@
#include <utility>
+#include "common/hex_util.h"
+#include "common/scope_exit.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h"
@@ -12,6 +14,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/nca.h"
+#include "mbedtls/sha256.h"
namespace Loader {
@@ -80,6 +83,79 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::S
return load_result;
}
+ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) {
+ using namespace Common::Literals;
+
+ constexpr size_t NcaFileNameWithHashLength = 36;
+ constexpr size_t NcaFileNameHashLength = 32;
+ constexpr size_t NcaSha256HashLength = 32;
+ constexpr size_t NcaSha256HalfHashLength = NcaSha256HashLength / 2;
+
+ // Get the file name.
+ const auto name = file->GetName();
+
+ // We won't try to verify meta NCAs.
+ if (name.ends_with(".cnmt.nca")) {
+ return ResultStatus::Success;
+ }
+
+ // Check if we can verify this file. NCAs should be named after their hashes.
+ if (!name.ends_with(".nca") || name.size() != NcaFileNameWithHashLength) {
+ LOG_WARNING(Loader, "Unable to validate NCA with name {}", name);
+ return ResultStatus::ErrorIntegrityVerificationNotImplemented;
+ }
+
+ // Get the expected truncated hash of the NCA.
+ const auto input_hash =
+ Common::HexStringToVector(file->GetName().substr(0, NcaFileNameHashLength), false);
+
+ // Declare buffer to read into.
+ std::vector<u8> buffer(4_MiB);
+
+ // Initialize sha256 verification context.
+ mbedtls_sha256_context ctx;
+ mbedtls_sha256_init(&ctx);
+ mbedtls_sha256_starts_ret(&ctx, 0);
+
+ // Ensure we maintain a clean state on exit.
+ SCOPE_EXIT({ mbedtls_sha256_free(&ctx); });
+
+ // Declare counters.
+ const size_t total_size = file->GetSize();
+ size_t processed_size = 0;
+
+ // Begin iterating the file.
+ while (processed_size < total_size) {
+ // Refill the buffer.
+ const size_t intended_read_size = std::min(buffer.size(), total_size - processed_size);
+ const size_t read_size = file->Read(buffer.data(), intended_read_size, processed_size);
+
+ // Update the hash function with the buffer contents.
+ mbedtls_sha256_update_ret(&ctx, buffer.data(), read_size);
+
+ // Update counters.
+ processed_size += read_size;
+
+ // Call the progress function.
+ if (!progress_callback(processed_size, total_size)) {
+ return ResultStatus::ErrorIntegrityVerificationFailed;
+ }
+ }
+
+ // Finalize context and compute the output hash.
+ std::array<u8, NcaSha256HashLength> output_hash;
+ mbedtls_sha256_finish_ret(&ctx, output_hash.data());
+
+ // Compare to expected.
+ if (std::memcmp(input_hash.data(), output_hash.data(), NcaSha256HalfHashLength) != 0) {
+ LOG_ERROR(Loader, "NCA hash mismatch detected for file {}", name);
+ return ResultStatus::ErrorIntegrityVerificationFailed;
+ }
+
+ // File verified.
+ return ResultStatus::Success;
+}
+
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
if (nca == nullptr) {
return ResultStatus::ErrorNotInitialized;
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index cf356ce63..96779e27f 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -39,6 +39,8 @@ public:
LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
+ ResultStatus VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) override;
+
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index f9b2549a3..fe2af1ae6 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -117,6 +117,42 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
return result;
}
+ResultStatus AppLoader_NSP::VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) {
+ // Extracted-type NSPs can't be verified.
+ if (nsp->IsExtractedType()) {
+ return ResultStatus::ErrorIntegrityVerificationNotImplemented;
+ }
+
+ // Get list of all NCAs.
+ const auto ncas = nsp->GetNCAsCollapsed();
+
+ size_t total_size = 0;
+ size_t processed_size = 0;
+
+ // Loop over NCAs, collecting the total size to verify.
+ for (const auto& nca : ncas) {
+ total_size += nca->GetBaseFile()->GetSize();
+ }
+
+ // Loop over NCAs again, verifying each.
+ for (const auto& nca : ncas) {
+ AppLoader_NCA loader_nca(nca->GetBaseFile());
+
+ const auto NcaProgressCallback = [&](size_t nca_processed_size, size_t nca_total_size) {
+ return progress_callback(processed_size + nca_processed_size, total_size);
+ };
+
+ const auto verification_result = loader_nca.VerifyIntegrity(NcaProgressCallback);
+ if (verification_result != ResultStatus::Success) {
+ return verification_result;
+ }
+
+ processed_size += nca->GetBaseFile()->GetSize();
+ }
+
+ return ResultStatus::Success;
+}
+
ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& out_file) {
return secondary_loader->ReadRomFS(out_file);
}
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 79df4586a..7ce436c67 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -45,6 +45,8 @@ public:
LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
+ ResultStatus VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) override;
+
ResultStatus ReadRomFS(FileSys::VirtualFile& out_file) override;
ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 3a76bc788..12d72c380 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -85,6 +85,40 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::KProcess& process, Core::S
return result;
}
+ResultStatus AppLoader_XCI::VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) {
+ // Verify secure partition, as it is the only thing we can process.
+ auto secure_partition = xci->GetSecurePartitionNSP();
+
+ // Get list of all NCAs.
+ const auto ncas = secure_partition->GetNCAsCollapsed();
+
+ size_t total_size = 0;
+ size_t processed_size = 0;
+
+ // Loop over NCAs, collecting the total size to verify.
+ for (const auto& nca : ncas) {
+ total_size += nca->GetBaseFile()->GetSize();
+ }
+
+ // Loop over NCAs again, verifying each.
+ for (const auto& nca : ncas) {
+ AppLoader_NCA loader_nca(nca->GetBaseFile());
+
+ const auto NcaProgressCallback = [&](size_t nca_processed_size, size_t nca_total_size) {
+ return progress_callback(processed_size + nca_processed_size, total_size);
+ };
+
+ const auto verification_result = loader_nca.VerifyIntegrity(NcaProgressCallback);
+ if (verification_result != ResultStatus::Success) {
+ return verification_result;
+ }
+
+ processed_size += nca->GetBaseFile()->GetSize();
+ }
+
+ return ResultStatus::Success;
+}
+
ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& out_file) {
return nca_loader->ReadRomFS(out_file);
}
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index ff05e6f62..b02e136d3 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -45,6 +45,8 @@ public:
LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
+ ResultStatus VerifyIntegrity(std::function<bool(size_t, size_t)> progress_callback) override;
+
ResultStatus ReadRomFS(FileSys::VirtualFile& out_file) override;
ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
diff --git a/src/dedicated_room/yuzu_room.cpp b/src/dedicated_room/yuzu_room.cpp
index d707dabe2..93038f161 100644
--- a/src/dedicated_room/yuzu_room.cpp
+++ b/src/dedicated_room/yuzu_room.cpp
@@ -368,9 +368,9 @@ int main(int argc, char** argv) {
if (auto room = network.GetRoom().lock()) {
AnnounceMultiplayerRoom::GameInfo preferred_game_info{.name = preferred_game,
.id = preferred_game_id};
- if (!room->Create(room_name, room_description, bind_address, port, password, max_members,
- username, preferred_game_info, std::move(verify_backend), ban_list,
- enable_yuzu_mods)) {
+ if (!room->Create(room_name, room_description, bind_address, static_cast<u16>(port),
+ password, max_members, username, preferred_game_info,
+ std::move(verify_backend), ban_list, enable_yuzu_mods)) {
LOG_INFO(Network, "Failed to create room: ");
return -1;
}
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 322c29065..5c127c8ef 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -37,8 +37,6 @@ add_library(input_common STATIC
if (MSVC)
target_compile_options(input_common PRIVATE
- /W4
-
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
diff --git a/src/network/room.cpp b/src/network/room.cpp
index e456ea09c..d87db37de 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -805,7 +805,7 @@ IPv4Address Room::RoomImpl::GenerateFakeIPAddress() {
std::uniform_int_distribution<> dis(0x01, 0xFE); // Random byte between 1 and 0xFE
do {
for (std::size_t i = 2; i < result_ip.size(); ++i) {
- result_ip[i] = dis(random_gen);
+ result_ip[i] = static_cast<u8>(dis(random_gen));
}
} while (!IsValidFakeIPAddress(result_ip));
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index 07e75f9d8..83b763447 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -245,8 +245,6 @@ target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit)
if (MSVC)
target_compile_options(shader_recompiler PRIVATE
- /W4
-
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 34240b36f..8decdf399 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -204,9 +204,7 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind
if (def.count > 1) {
throw NotImplementedException("Indirect texture sample");
}
- const Id sampler_id{def.id};
- const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)};
- return ctx.OpImage(ctx.image_buffer_type, id);
+ return ctx.OpLoad(ctx.image_buffer_type, def.id);
} else {
const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
if (def.count > 1) {
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index bec5db173..72f69b7aa 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -74,6 +74,11 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
throw InvalidArgument("Invalid image format {}", format);
}
+spv::ImageFormat GetImageFormatForBuffer(ImageFormat format) {
+ const auto spv_format = GetImageFormat(format);
+ return spv_format == spv::ImageFormat::Unknown ? spv::ImageFormat::R32ui : spv_format;
+}
+
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
const spv::ImageFormat format{GetImageFormat(desc.format)};
const Id type{ctx.U32[1]};
@@ -1242,9 +1247,8 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
}
const spv::ImageFormat format{spv::ImageFormat::Unknown};
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
- sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
- const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
+ const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)};
texture_buffers.reserve(info.texture_buffer_descriptors.size());
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
if (desc.count != 1) {
@@ -1271,7 +1275,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
if (desc.count != 1) {
throw NotImplementedException("Array of image buffers");
}
- const spv::ImageFormat format{GetImageFormat(desc.format)};
+ const spv::ImageFormat format{GetImageFormatForBuffer(desc.format)};
const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index e63330f11..7c49fd504 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -206,7 +206,6 @@ public:
Id output_u32{};
Id image_buffer_type{};
- Id sampled_texture_buffer_type{};
Id image_u32{};
std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{};
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
index 753c62098..e593132e6 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
@@ -161,7 +161,8 @@ enum class SpecialRegister : u64 {
LOG_WARNING(Shader, "(STUBBED) SR_AFFINITY");
return ir.Imm32(0); // This is the default value hardware returns.
default:
- throw NotImplementedException("S2R special register {}", special_register);
+ LOG_CRITICAL(Shader, "(STUBBED) Special register {}", special_register);
+ return ir.Imm32(0); // This is the default value hardware returns.
}
}
} // Anonymous namespace
diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp
index e85f9977b..b6e3bc875 100644
--- a/src/tests/common/ring_buffer.cpp
+++ b/src/tests/common/ring_buffer.cpp
@@ -55,7 +55,7 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
// Pushing more values than space available should partially succeed.
{
std::vector<char> to_push(6);
- std::iota(to_push.begin(), to_push.end(), 88);
+ std::iota(to_push.begin(), to_push.end(), static_cast<char>(88));
const std::size_t count = buf.Push(to_push);
REQUIRE(count == 3U);
}
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 9f1b340a9..58ce0d8c2 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -14,6 +14,7 @@
namespace Tegra {
constexpr u32 MacroRegistersStart = 0xE00;
+constexpr u32 ComputeInline = 0x6D;
DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_,
Control::ChannelState& channel_state_)
@@ -83,12 +84,35 @@ bool DmaPusher::Step() {
dma_state.dma_get, command_list_header.size * sizeof(u32));
}
}
- Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
- Core::Memory::GuestMemoryFlags::UnsafeRead>
- headers(memory_manager, dma_state.dma_get, command_list_header.size, &command_headers);
- ProcessCommands(headers);
+ const auto safe_process = [&] {
+ Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
+ Core::Memory::GuestMemoryFlags::SafeRead>
+ headers(memory_manager, dma_state.dma_get, command_list_header.size,
+ &command_headers);
+ ProcessCommands(headers);
+ };
+ const auto unsafe_process = [&] {
+ Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
+ Core::Memory::GuestMemoryFlags::UnsafeRead>
+ headers(memory_manager, dma_state.dma_get, command_list_header.size,
+ &command_headers);
+ ProcessCommands(headers);
+ };
+ if (Settings::IsGPULevelHigh()) {
+ if (dma_state.method >= MacroRegistersStart) {
+ unsafe_process();
+ return true;
+ }
+ if (subchannel_type[dma_state.subchannel] == Engines::EngineTypes::KeplerCompute &&
+ dma_state.method == ComputeInline) {
+ unsafe_process();
+ return true;
+ }
+ safe_process();
+ return true;
+ }
+ unsafe_process();
}
-
return true;
}
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index 8a2784cdc..c9fab2d90 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -130,8 +130,10 @@ public:
void DispatchCalls();
- void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id) {
+ void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id,
+ Engines::EngineTypes engine_type) {
subchannels[subchannel_id] = engine;
+ subchannel_type[subchannel_id] = engine_type;
}
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
@@ -170,6 +172,7 @@ private:
const bool ib_enable{true}; ///< IB mode enabled
std::array<Engines::EngineInterface*, max_subchannels> subchannels{};
+ std::array<Engines::EngineTypes, max_subchannels> subchannel_type;
GPU& gpu;
Core::System& system;
diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h
index 392322358..54631ee6c 100644
--- a/src/video_core/engines/engine_interface.h
+++ b/src/video_core/engines/engine_interface.h
@@ -11,6 +11,14 @@
namespace Tegra::Engines {
+enum class EngineTypes : u32 {
+ KeplerCompute,
+ Maxwell3D,
+ Fermi2D,
+ MaxwellDMA,
+ KeplerMemory,
+};
+
class EngineInterface {
public:
virtual ~EngineInterface() = default;
diff --git a/src/video_core/engines/engine_upload.h b/src/video_core/engines/engine_upload.h
index 7242d2529..21bf8aeb4 100644
--- a/src/video_core/engines/engine_upload.h
+++ b/src/video_core/engines/engine_upload.h
@@ -69,6 +69,14 @@ public:
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
+ GPUVAddr ExecTargetAddress() const {
+ return regs.dest.Address();
+ }
+
+ u32 GetUploadSize() const {
+ return copy_size;
+ }
+
private:
void ProcessData(std::span<const u8> read_buffer);
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index a38d9528a..cd61ab222 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -43,16 +43,33 @@ void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_cal
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
+ UploadInfo info{.upload_address = upload_address,
+ .exec_address = upload_state.ExecTargetAddress(),
+ .copy_size = upload_state.GetUploadSize()};
+ uploads.push_back(info);
upload_state.ProcessExec(regs.exec_upload.linear != 0);
break;
}
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
+ upload_address = current_dma_segment;
upload_state.ProcessData(method_argument, is_last_call);
break;
}
- case KEPLER_COMPUTE_REG_INDEX(launch):
+ case KEPLER_COMPUTE_REG_INDEX(launch): {
+ const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address();
+
+ for (auto& data : uploads) {
+ const GPUVAddr offset = data.exec_address - launch_desc_loc;
+ if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x) &&
+ memory_manager.IsMemoryDirty(data.upload_address, data.copy_size)) {
+ indirect_compute = {data.upload_address};
+ }
+ }
+ uploads.clear();
ProcessLaunch();
+ indirect_compute = std::nullopt;
break;
+ }
default:
break;
}
@@ -62,6 +79,7 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun
u32 methods_pending) {
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(data_upload):
+ upload_address = current_dma_segment;
upload_state.ProcessData(base_start, amount);
return;
default:
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 2092e685f..735e05fb4 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -5,6 +5,7 @@
#include <array>
#include <cstddef>
+#include <optional>
#include <vector>
#include "common/bit_field.h"
#include "common/common_funcs.h"
@@ -36,6 +37,9 @@ namespace Tegra::Engines {
#define KEPLER_COMPUTE_REG_INDEX(field_name) \
(offsetof(Tegra::Engines::KeplerCompute::Regs, field_name) / sizeof(u32))
+#define LAUNCH_REG_INDEX(field_name) \
+ (offsetof(Tegra::Engines::KeplerCompute::LaunchParams, field_name) / sizeof(u32))
+
class KeplerCompute final : public EngineInterface {
public:
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
@@ -201,6 +205,10 @@ public:
void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
u32 methods_pending) override;
+ std::optional<GPUVAddr> GetIndirectComputeAddress() const {
+ return indirect_compute;
+ }
+
private:
void ProcessLaunch();
@@ -216,6 +224,15 @@ private:
MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state;
+ GPUVAddr upload_address;
+
+ struct UploadInfo {
+ GPUVAddr upload_address;
+ GPUVAddr exec_address;
+ u32 copy_size;
+ };
+ std::vector<UploadInfo> uploads;
+ std::optional<GPUVAddr> indirect_compute{};
};
#define ASSERT_REG_POSITION(field_name, position) \
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index c3696096d..06e349e43 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -257,6 +257,7 @@ u32 Maxwell3D::GetMaxCurrentVertices() {
const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin);
num_vertices = std::max(
num_vertices, address_size / std::max(attribute.SizeInBytes(), array.stride.Value()));
+ break;
}
return num_vertices;
}
@@ -269,10 +270,13 @@ size_t Maxwell3D::EstimateIndexBufferSize() {
std::numeric_limits<u32>::max()};
const size_t byte_size = regs.index_buffer.FormatSizeInBytes();
const size_t log2_byte_size = Common::Log2Ceil64(byte_size);
+ const size_t cap{GetMaxCurrentVertices() * 3 * byte_size};
+ const size_t lower_cap =
+ std::min<size_t>(static_cast<size_t>(end_address - start_address), cap);
return std::min<size_t>(
memory_manager.GetMemoryLayoutSize(start_address, byte_size * max_sizes[log2_byte_size]) /
byte_size,
- static_cast<size_t>(end_address - start_address));
+ lower_cap);
}
u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp
index 7718a09b3..6de2543b7 100644
--- a/src/video_core/engines/puller.cpp
+++ b/src/video_core/engines/puller.cpp
@@ -34,19 +34,24 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) {
bound_engines[method_call.subchannel] = engine_id;
switch (engine_id) {
case EngineID::FERMI_TWOD_A:
- dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel);
+ dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel,
+ EngineTypes::Fermi2D);
break;
case EngineID::MAXWELL_B:
- dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel);
+ dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel,
+ EngineTypes::Maxwell3D);
break;
case EngineID::KEPLER_COMPUTE_B:
- dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel);
+ dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel,
+ EngineTypes::KeplerCompute);
break;
case EngineID::MAXWELL_DMA_COPY_A:
- dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel);
+ dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel,
+ EngineTypes::MaxwellDMA);
break;
case EngineID::KEPLER_INLINE_TO_MEMORY_B:
- dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel);
+ dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel,
+ EngineTypes::KeplerMemory);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 1ba31be88..dd03efecd 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -380,6 +380,17 @@ void RasterizerOpenGL::DispatchCompute() {
pipeline->SetEngine(kepler_compute, gpu_memory);
pipeline->Configure();
const auto& qmd{kepler_compute->launch_description};
+ auto indirect_address = kepler_compute->GetIndirectComputeAddress();
+ if (indirect_address) {
+ // DispatchIndirect
+ static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
+ const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
+ const auto [buffer, offset] =
+ buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
+ glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->Handle());
+ glDispatchComputeIndirect(static_cast<GLintptr>(offset));
+ return;
+ }
glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
++num_queued_commands;
has_written_global_memory |= pipeline->WritesGlobalMemory();
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 454bb66a4..c4c30d807 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -66,21 +66,6 @@ std::string BuildCommaSeparatedExtensions(
return fmt::format("{}", fmt::join(available_extensions, ","));
}
-DebugCallback MakeDebugCallback(const vk::Instance& instance, const vk::InstanceDispatch& dld) {
- if (!Settings::values.renderer_debug) {
- return DebugCallback{};
- }
- const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
- const auto it = std::ranges::find_if(*properties, [](const auto& prop) {
- return std::strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, prop.extensionName) == 0;
- });
- if (it != properties->end()) {
- return CreateDebugUtilsCallback(instance);
- } else {
- return CreateDebugReportCallback(instance);
- }
-}
-
} // Anonymous namespace
Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
@@ -103,7 +88,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())),
instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
Settings::values.renderer_debug.GetValue())),
- debug_callback(MakeDebugCallback(instance, dld)),
+ debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance)
+ : vk::DebugUtilsMessenger{}),
surface(CreateSurface(instance, render_window.GetWindowInfo())),
device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(),
scheduler(device, state_tracker),
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 89e98425e..590bc1c64 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -35,8 +35,6 @@ class GPU;
namespace Vulkan {
-using DebugCallback = std::variant<vk::DebugUtilsMessenger, vk::DebugReportCallback>;
-
Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
VkSurfaceKHR surface);
@@ -75,7 +73,7 @@ private:
vk::InstanceDispatch dld;
vk::Instance instance;
- DebugCallback debug_callback;
+ vk::DebugUtilsMessenger debug_messenger;
vk::SurfaceKHR surface;
ScreenInfo screen_info;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 60a6ac651..e15865d16 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -529,17 +529,20 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
buffer_handles.push_back(handle);
}
if (device.IsExtExtendedDynamicStateSupported()) {
- scheduler.Record([bindings_ = std::move(bindings),
+ scheduler.Record([this, bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers2EXT(bindings_.min_index,
- bindings_.max_index - bindings_.min_index,
+ std::min(bindings_.max_index - bindings_.min_index,
+ device.GetMaxVertexInputBindings()),
buffer_handles_.data(), bindings_.offsets.data(),
bindings_.sizes.data(), bindings_.strides.data());
});
} else {
- scheduler.Record([bindings_ = std::move(bindings),
+ scheduler.Record([this, bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
- cmdbuf.BindVertexBuffers(bindings_.min_index, bindings_.max_index - bindings_.min_index,
+ cmdbuf.BindVertexBuffers(bindings_.min_index,
+ std::min(bindings_.max_index - bindings_.min_index,
+ device.GetMaxVertexInputBindings()),
buffer_handles_.data(), bindings_.offsets.data());
});
}
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index fe432dfe1..4f83a88e1 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -665,6 +665,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
std::move(modules), infos);
} catch (const Shader::Exception& exception) {
+ auto hash = key.Hash();
+ size_t env_index{0};
+ for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
+ if (key.unique_hashes[index] == 0) {
+ continue;
+ }
+ Shader::Environment& env{*envs[env_index]};
+ ++env_index;
+
+ const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))};
+ Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0);
+ env.Dump(hash, key.unique_hashes[index]);
+ }
LOG_ERROR(Render_Vulkan, "{}", exception.what());
return nullptr;
}
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 032f694bc..01e76a82c 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -463,6 +463,20 @@ void RasterizerVulkan::DispatchCompute() {
pipeline->Configure(*kepler_compute, *gpu_memory, scheduler, buffer_cache, texture_cache);
const auto& qmd{kepler_compute->launch_description};
+ auto indirect_address = kepler_compute->GetIndirectComputeAddress();
+ if (indirect_address) {
+ // DispatchIndirect
+ static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
+ const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
+ const auto [buffer, offset] =
+ buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
+ scheduler.RequestOutsideRenderPassOperationContext();
+ scheduler.Record([indirect_buffer = buffer->Handle(),
+ indirect_offset = offset](vk::CommandBuffer cmdbuf) {
+ cmdbuf.DispatchIndirect(indirect_buffer, indirect_offset);
+ });
+ return;
+ }
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
index 67e8065a4..448df2d3a 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
@@ -63,22 +63,6 @@ VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
return VK_FALSE;
}
-VkBool32 DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
- uint64_t object, size_t location, int32_t messageCode,
- const char* pLayerPrefix, const char* pMessage, void* pUserData) {
- const VkDebugReportFlagBitsEXT severity = static_cast<VkDebugReportFlagBitsEXT>(flags);
- const std::string_view message{pMessage};
- if (severity & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
- LOG_CRITICAL(Render_Vulkan, "{}", message);
- } else if (severity & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
- LOG_WARNING(Render_Vulkan, "{}", message);
- } else if (severity & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
- LOG_INFO(Render_Vulkan, "{}", message);
- } else if (severity & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
- LOG_DEBUG(Render_Vulkan, "{}", message);
- }
- return VK_FALSE;
-}
} // Anonymous namespace
vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) {
@@ -98,15 +82,4 @@ vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) {
});
}
-vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance) {
- return instance.CreateDebugReportCallback({
- .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
- .pNext = nullptr,
- .flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
- VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
- .pfnCallback = DebugReportCallback,
- .pUserData = nullptr,
- });
-}
-
} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.h b/src/video_core/vulkan_common/vulkan_debug_callback.h
index a8af7b406..5e940782f 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.h
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.h
@@ -9,6 +9,4 @@ namespace Vulkan {
vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance);
-vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance);
-
} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp
index bc16145be..180657a75 100644
--- a/src/video_core/vulkan_common/vulkan_instance.cpp
+++ b/src/video_core/vulkan_common/vulkan_instance.cpp
@@ -76,11 +76,9 @@ namespace {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
}
#endif
- if (enable_validation) {
- const bool debug_utils =
- AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
- extensions.push_back(debug_utils ? VK_EXT_DEBUG_UTILS_EXTENSION_NAME
- : VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+ if (enable_validation &&
+ AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME})) {
+ extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
return extensions;
}
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 78e5a248f..c3f388d89 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -92,6 +92,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdCopyImage);
X(vkCmdCopyImageToBuffer);
X(vkCmdDispatch);
+ X(vkCmdDispatchIndirect);
X(vkCmdDraw);
X(vkCmdDrawIndexed);
X(vkCmdDrawIndirect);
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index c226a2a29..049fa8038 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -203,6 +203,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdCopyImage vkCmdCopyImage{};
PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{};
PFN_vkCmdDispatch vkCmdDispatch{};
+ PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect{};
PFN_vkCmdDraw vkCmdDraw{};
PFN_vkCmdDrawIndexed vkCmdDrawIndexed{};
PFN_vkCmdDrawIndirect vkCmdDrawIndirect{};
@@ -1209,6 +1210,10 @@ public:
dld->vkCmdDispatch(handle, x, y, z);
}
+ void DispatchIndirect(VkBuffer indirect_buffer, VkDeviceSize offset) const noexcept {
+ dld->vkCmdDispatchIndirect(handle, indirect_buffer, offset);
+ }
+
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
Span<VkBufferMemoryBarrier> buffer_barriers,
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp
index 4988fcc83..b457a736a 100644
--- a/src/yuzu/applets/qt_amiibo_settings.cpp
+++ b/src/yuzu/applets/qt_amiibo_settings.cpp
@@ -160,7 +160,8 @@ void QtAmiiboSettingsDialog::LoadAmiiboData() {
}
const auto amiibo_name = std::string(register_info.amiibo_name.data());
- const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data());
+ const auto owner_name =
+ Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data());
const auto creation_date =
QDate(register_info.creation_date.year, register_info.creation_date.month,
register_info.creation_date.day);
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 8622dc184..fd6bebf0f 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -193,14 +193,10 @@ void ConfigureGraphics::PopulateVSyncModeSelection() {
: vsync_mode_combobox_enum_map[current_index];
int index{};
const int device{vulkan_device_combobox->currentIndex()}; //< current selected Vulkan device
- if (device == -1) {
- // Invalid device
- return;
- }
const auto& present_modes = //< relevant vector of present modes for the selected device or API
- backend == Settings::RendererBackend::Vulkan ? device_present_modes[device]
- : default_present_modes;
+ backend == Settings::RendererBackend::Vulkan && device > -1 ? device_present_modes[device]
+ : default_present_modes;
vsync_mode_combobox->clear();
vsync_mode_combobox_enum_map.clear();
@@ -497,11 +493,19 @@ void ConfigureGraphics::RetrieveVulkanDevices() {
}
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
- if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled()) {
- return Settings::values.renderer_backend.GetValue(true);
+ const auto selected_backend = [&]() {
+ if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled()) {
+ return Settings::values.renderer_backend.GetValue(true);
+ }
+ return static_cast<Settings::RendererBackend>(
+ combobox_translations.at(Settings::EnumMetadata<Settings::RendererBackend>::Index())
+ .at(api_combobox->currentIndex())
+ .first);
+ }();
+
+ if (selected_backend == Settings::RendererBackend::Vulkan &&
+ UISettings::values.has_broken_vulkan) {
+ return Settings::RendererBackend::OpenGL;
}
- return static_cast<Settings::RendererBackend>(
- combobox_translations.at(Settings::EnumMetadata<Settings::RendererBackend>::Index())
- .at(api_combobox->currentIndex())
- .first);
+ return selected_backend;
}
diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp
index 7721e58f9..d63093985 100644
--- a/src/yuzu/configuration/shared_widget.cpp
+++ b/src/yuzu/configuration/shared_widget.cpp
@@ -194,7 +194,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
return group;
}
- const auto get_selected = [=]() -> u32 {
+ const auto get_selected = [=]() -> int {
for (const auto& [id, button] : radio_buttons) {
if (button->isChecked()) {
return id;
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index b5a02700d..f254c1e1c 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -557,6 +557,7 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
QMenu* dump_romfs_menu = context_menu.addMenu(tr("Dump RomFS"));
QAction* dump_romfs = dump_romfs_menu->addAction(tr("Dump RomFS"));
QAction* dump_romfs_sdmc = dump_romfs_menu->addAction(tr("Dump RomFS to SDMC"));
+ QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity"));
QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
#ifndef WIN32
@@ -588,10 +589,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
});
connect(start_game, &QAction::triggered, [this, path]() {
- emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal);
+ emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal,
+ AmLaunchType::UserInitiated);
});
connect(start_game_global, &QAction::triggered, [this, path]() {
- emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global);
+ emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global,
+ AmLaunchType::UserInitiated);
});
connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
@@ -628,6 +631,8 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
connect(dump_romfs_sdmc, &QAction::triggered, [this, program_id, path]() {
emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::SDMC);
});
+ connect(verify_integrity, &QAction::triggered,
+ [this, path]() { emit VerifyIntegrityRequested(path); });
connect(copy_tid, &QAction::triggered,
[this, program_id]() { emit CopyTIDRequested(program_id); });
connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() {
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 6c2f75e53..1fcbbf0ba 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -28,6 +28,7 @@ class GameListWorker;
class GameListSearchField;
class GameListDir;
class GMainWindow;
+enum class AmLaunchType;
enum class StartGameType;
namespace FileSys {
@@ -103,7 +104,7 @@ public:
signals:
void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
- StartGameType type);
+ StartGameType type, AmLaunchType launch_type);
void GameChosen(const QString& game_path, const u64 title_id = 0);
void ShouldCancelWorker();
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
@@ -113,6 +114,7 @@ signals:
void RemoveFileRequested(u64 program_id, GameListRemoveTarget target,
const std::string& game_path);
void DumpRomFSRequested(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
+ void VerifyIntegrityRequested(const std::string& game_path);
void CopyTIDRequested(u64 program_id);
void CreateShortcut(u64 program_id, const std::string& game_path,
GameListShortcutTarget target);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 33c9fd0af..97d216638 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -8,6 +8,7 @@
#include <iostream>
#include <memory>
#include <thread>
+#include "core/loader/nca.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@@ -442,8 +443,13 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
"#yuzu-starts-with-the-error-broken-vulkan-installation-detected'>"
"here for instructions to fix the issue</a>."));
+#ifdef HAS_OPENGL
Settings::values.renderer_backend = Settings::RendererBackend::OpenGL;
+#else
+ Settings::values.renderer_backend = Settings::RendererBackend::Null;
+#endif
+ UpdateAPIText();
renderer_status_button->setDisabled(true);
renderer_status_button->setChecked(false);
} else {
@@ -1447,6 +1453,8 @@ void GMainWindow::ConnectWidgetEvents() {
&GMainWindow::OnGameListRemoveInstalledEntry);
connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile);
connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS);
+ connect(game_list, &GameList::VerifyIntegrityRequested, this,
+ &GMainWindow::OnGameListVerifyIntegrity);
connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID);
connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
&GMainWindow::OnGameListNavigateToGamedbEntry);
@@ -1547,6 +1555,7 @@ void GMainWindow::ConnectMenuEvents() {
// Help
connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);
+ connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents);
connect_menu(ui->action_About, &GMainWindow::OnAbout);
}
@@ -1698,7 +1707,8 @@ void GMainWindow::AllowOSSleep() {
#endif
}
-bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) {
+bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
+ AmLaunchType launch_type) {
// Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr) {
ShutdownGame();
@@ -1710,6 +1720,10 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
system->SetFilesystem(vfs);
+ if (launch_type == AmLaunchType::UserInitiated) {
+ system->GetUserChannel().clear();
+ }
+
system->SetAppletFrontendSet({
std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings
(UISettings::values.controller_applet_disabled.GetValue() == true)
@@ -1849,7 +1863,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
}
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
- StartGameType type) {
+ StartGameType type, AmLaunchType launch_type) {
LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list
@@ -1893,7 +1907,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
}
}
- if (!LoadROM(filename, program_id, program_index)) {
+ if (!LoadROM(filename, program_id, program_index, launch_type)) {
return;
}
@@ -2010,8 +2024,16 @@ bool GMainWindow::OnShutdownBegin() {
emit EmulationStopping();
+ int shutdown_time = 1000;
+
+ if (system->DebuggerEnabled()) {
+ shutdown_time = 0;
+ } else if (system->GetExitLocked()) {
+ shutdown_time = 5000;
+ }
+
shutdown_timer.setSingleShot(true);
- shutdown_timer.start(system->DebuggerEnabled() ? 0 : 5000);
+ shutdown_timer.start(shutdown_time);
connect(&shutdown_timer, &QTimer::timeout, this, &GMainWindow::OnEmulationStopTimeExpired);
connect(emu_thread.get(), &QThread::finished, this, &GMainWindow::OnEmulationStopped);
@@ -2267,40 +2289,62 @@ void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
}
-static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) {
- std::size_t out = 0;
-
- for (const auto& subdir : dir->GetSubdirectories()) {
- out += 1 + CalculateRomFSEntrySize(subdir, full);
- }
-
- return out + (full ? dir->GetFiles().size() : 0);
-}
-
-static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src,
- const FileSys::VirtualDir& dest, std::size_t block_size, bool full) {
+static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog,
+ const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest,
+ bool full) {
if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
return false;
if (dialog.wasCanceled())
return false;
+ std::vector<u8> buffer(CopyBufferSize);
+ auto last_timestamp = std::chrono::steady_clock::now();
+
+ const auto QtRawCopy = [&](const FileSys::VirtualFile& src_file,
+ const FileSys::VirtualFile& dest_file) {
+ if (src_file == nullptr || dest_file == nullptr) {
+ return false;
+ }
+ if (!dest_file->Resize(src_file->GetSize())) {
+ return false;
+ }
+
+ for (std::size_t i = 0; i < src_file->GetSize(); i += buffer.size()) {
+ if (dialog.wasCanceled()) {
+ dest_file->Resize(0);
+ return false;
+ }
+
+ using namespace std::literals::chrono_literals;
+ const auto new_timestamp = std::chrono::steady_clock::now();
+
+ if ((new_timestamp - last_timestamp) > 33ms) {
+ last_timestamp = new_timestamp;
+ dialog.setValue(
+ static_cast<int>(std::min(read_size, total_size) * 100 / total_size));
+ QCoreApplication::processEvents();
+ }
+
+ const auto read = src_file->Read(buffer.data(), buffer.size(), i);
+ dest_file->Write(buffer.data(), read, i);
+
+ read_size += read;
+ }
+
+ return true;
+ };
+
if (full) {
for (const auto& file : src->GetFiles()) {
const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName());
- if (!FileSys::VfsRawCopy(file, out, block_size))
- return false;
- dialog.setValue(dialog.value() + 1);
- if (dialog.wasCanceled())
+ if (!QtRawCopy(file, out))
return false;
}
}
for (const auto& dir : src->GetSubdirectories()) {
const auto out = dest->CreateSubdirectory(dir->GetName());
- if (!RomFSRawCopy(dialog, dir, out, block_size, full))
- return false;
- dialog.setValue(dialog.value() + 1);
- if (dialog.wasCanceled())
+ if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full))
return false;
}
@@ -2573,50 +2617,48 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
- FileSys::VirtualFile base_romfs;
- if (loader->ReadRomFS(base_romfs) != Loader::ResultStatus::Success) {
- failed();
- return;
- }
+ FileSys::VirtualFile packed_update_raw{};
+ loader->ReadUpdateRaw(packed_update_raw);
const auto& installed = system->GetContentProvider();
- const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id);
- if (!romfs_title_id) {
+ u64 title_id{};
+ u8 raw_type{};
+ if (!SelectRomFSDumpTarget(installed, program_id, &title_id, &raw_type)) {
failed();
return;
}
- const auto type = *romfs_title_id == program_id ? FileSys::ContentRecordType::Program
- : FileSys::ContentRecordType::Data;
- const auto base_nca = installed.GetEntry(*romfs_title_id, type);
+ const auto type = static_cast<FileSys::ContentRecordType>(raw_type);
+ const auto base_nca = installed.GetEntry(title_id, type);
if (!base_nca) {
failed();
return;
}
+ const FileSys::NCA update_nca{packed_update_raw, nullptr};
+ if (type != FileSys::ContentRecordType::Program ||
+ update_nca.GetStatus() != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS ||
+ update_nca.GetTitleId() != FileSys::GetUpdateTitleID(title_id)) {
+ packed_update_raw = {};
+ }
+
+ const auto base_romfs = base_nca->GetRomFS();
+ if (!base_romfs) {
+ failed();
+ return;
+ }
+
const auto dump_dir =
target == DumpRomFSTarget::Normal
? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)
: Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "atmosphere" / "contents";
- const auto romfs_dir = fmt::format("{:016X}/romfs", *romfs_title_id);
+ const auto romfs_dir = fmt::format("{:016X}/romfs", title_id);
const auto path = Common::FS::PathToUTF8String(dump_dir / romfs_dir);
- FileSys::VirtualFile romfs;
-
- if (*romfs_title_id == program_id) {
- const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), installed};
- romfs = pm.PatchRomFS(base_nca.get(), base_romfs, type, nullptr, false);
- } else {
- romfs = installed.GetEntry(*romfs_title_id, type)->GetRomFS();
- }
-
- const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full);
- if (extracted == nullptr) {
- failed();
- return;
- }
+ const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), installed};
+ auto romfs = pm.PatchRomFS(base_nca.get(), base_romfs, type, packed_update_raw, false);
const auto out = VfsFilesystemCreateDirectoryWrapper(vfs, path, FileSys::Mode::ReadWrite);
@@ -2640,11 +2682,16 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
+ const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full);
+ if (extracted == nullptr) {
+ failed();
+ return;
+ }
+
const auto full = res == selections.constFirst();
- const auto entry_size = CalculateRomFSEntrySize(extracted, full);
- // The minimum required space is the size of the extracted RomFS + 1 GiB
- const auto minimum_free_space = extracted->GetSize() + 0x40000000;
+ // The expected required space is the size of the RomFS + 1 GiB
+ const auto minimum_free_space = romfs->GetSize() + 0x40000000;
if (full && Common::FS::GetFreeSpaceSize(path) < minimum_free_space) {
QMessageBox::warning(this, tr("RomFS Extraction Failed!"),
@@ -2655,12 +2702,15 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
- QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0,
- static_cast<s32>(entry_size), this);
+ QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, 100, this);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
+ progress.setAutoClose(false);
+ progress.setAutoReset(false);
+
+ size_t read_size = 0;
- if (RomFSRawCopy(progress, extracted, out, 0x400000, full)) {
+ if (RomFSRawCopy(romfs->GetSize(), read_size, progress, extracted, out, full)) {
progress.close();
QMessageBox::information(this, tr("RomFS Extraction Succeeded!"),
tr("The operation completed successfully."));
@@ -2672,6 +2722,54 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
}
}
+void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) {
+ const auto NotImplemented = [this] {
+ QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"),
+ tr("File contents were not checked for validity."));
+ };
+ const auto Failed = [this] {
+ QMessageBox::critical(this, tr("Integrity verification failed!"),
+ tr("File contents may be corrupt."));
+ };
+
+ const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
+ if (loader == nullptr) {
+ NotImplemented();
+ return;
+ }
+
+ QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this);
+ progress.setWindowModality(Qt::WindowModal);
+ progress.setMinimumDuration(100);
+ progress.setAutoClose(false);
+ progress.setAutoReset(false);
+
+ const auto QtProgressCallback = [&](size_t processed_size, size_t total_size) {
+ if (progress.wasCanceled()) {
+ return false;
+ }
+
+ progress.setValue(static_cast<int>((processed_size * 100) / total_size));
+ return true;
+ };
+
+ const auto status = loader->VerifyIntegrity(QtProgressCallback);
+ if (progress.wasCanceled() ||
+ status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) {
+ NotImplemented();
+ return;
+ }
+
+ if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) {
+ Failed();
+ return;
+ }
+
+ progress.close();
+ QMessageBox::information(this, tr("Integrity verification succeeded!"),
+ tr("The operation completed successfully."));
+}
+
void GMainWindow::OnGameListCopyTID(u64 program_id) {
QClipboard* clipboard = QGuiApplication::clipboard();
clipboard->setText(QString::fromStdString(fmt::format("{:016X}", program_id)));
@@ -3261,7 +3359,7 @@ void GMainWindow::OnPauseContinueGame() {
}
void GMainWindow::OnStopGame() {
- if (system->GetExitLock() && !ConfirmForceLockedExit()) {
+ if (system->GetExitLocked() && !ConfirmForceLockedExit()) {
return;
}
@@ -3278,7 +3376,8 @@ void GMainWindow::OnLoadComplete() {
void GMainWindow::OnExecuteProgram(std::size_t program_index) {
ShutdownGame();
- BootGame(last_filename_booted, 0, program_index);
+ BootGame(last_filename_booted, 0, program_index, StartGameType::Normal,
+ AmLaunchType::ApplicationInitiated);
}
void GMainWindow::OnExit() {
@@ -3758,10 +3857,14 @@ void GMainWindow::OnToggleAdaptingFilter() {
void GMainWindow::OnToggleGraphicsAPI() {
auto api = Settings::values.renderer_backend.GetValue();
- if (api == Settings::RendererBackend::OpenGL) {
+ if (api != Settings::RendererBackend::Vulkan) {
api = Settings::RendererBackend::Vulkan;
} else {
+#ifdef HAS_OPENGL
api = Settings::RendererBackend::OpenGL;
+#else
+ api = Settings::RendererBackend::Null;
+#endif
}
Settings::values.renderer_backend.SetValue(api);
renderer_status_button->setChecked(api == Settings::RendererBackend::Vulkan);
@@ -3905,6 +4008,108 @@ void GMainWindow::OnOpenYuzuFolder() {
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::YuzuDir))));
}
+void GMainWindow::OnVerifyInstalledContents() {
+ // Declare sizes.
+ size_t total_size = 0;
+ size_t processed_size = 0;
+
+ // Initialize a progress dialog.
+ QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this);
+ progress.setWindowModality(Qt::WindowModal);
+ progress.setMinimumDuration(100);
+ progress.setAutoClose(false);
+ progress.setAutoReset(false);
+
+ // Declare a list of file names which failed to verify.
+ std::vector<std::string> failed;
+
+ // Declare progress callback.
+ auto QtProgressCallback = [&](size_t nca_processed, size_t nca_total) {
+ if (progress.wasCanceled()) {
+ return false;
+ }
+ progress.setValue(static_cast<int>(((processed_size + nca_processed) * 100) / total_size));
+ return true;
+ };
+
+ // Get content registries.
+ auto bis_contents = system->GetFileSystemController().GetSystemNANDContents();
+ auto user_contents = system->GetFileSystemController().GetUserNANDContents();
+
+ std::vector<FileSys::RegisteredCache*> content_providers;
+ if (bis_contents) {
+ content_providers.push_back(bis_contents);
+ }
+ if (user_contents) {
+ content_providers.push_back(user_contents);
+ }
+
+ // Get associated NCA files.
+ std::vector<FileSys::VirtualFile> nca_files;
+
+ // Get all installed IDs.
+ for (auto nca_provider : content_providers) {
+ const auto entries = nca_provider->ListEntriesFilter();
+
+ for (const auto& entry : entries) {
+ auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type);
+ if (!nca_file) {
+ continue;
+ }
+
+ total_size += nca_file->GetSize();
+ nca_files.push_back(std::move(nca_file));
+ }
+ }
+
+ // Using the NCA loader, determine if all NCAs are valid.
+ for (auto& nca_file : nca_files) {
+ Loader::AppLoader_NCA nca_loader(nca_file);
+
+ auto status = nca_loader.VerifyIntegrity(QtProgressCallback);
+ if (progress.wasCanceled()) {
+ break;
+ }
+ if (status != Loader::ResultStatus::Success) {
+ FileSys::NCA nca(nca_file);
+ const auto title_id = nca.GetTitleId();
+ std::string title_name = "unknown";
+
+ const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id),
+ FileSys::ContentRecordType::Control);
+ if (control && control->GetStatus() == Loader::ResultStatus::Success) {
+ const FileSys::PatchManager pm{title_id, system->GetFileSystemController(),
+ *provider};
+ const auto [nacp, logo] = pm.ParseControlNCA(*control);
+ if (nacp) {
+ title_name = nacp->GetApplicationName();
+ }
+ }
+
+ if (title_id > 0) {
+ failed.push_back(
+ fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name));
+ } else {
+ failed.push_back(fmt::format("{} (unknown)", nca_file->GetName()));
+ }
+ }
+
+ processed_size += nca_file->GetSize();
+ }
+
+ progress.close();
+
+ if (failed.size() > 0) {
+ auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(failed, "\n")));
+ QMessageBox::critical(
+ this, tr("Integrity verification failed!"),
+ tr("Verification failed for the following files:\n\n%1").arg(failed_names));
+ } else {
+ QMessageBox::information(this, tr("Integrity verification succeeded!"),
+ tr("The operation completed successfully."));
+ }
+}
+
void GMainWindow::OnAbout() {
AboutDialog aboutDialog(this);
aboutDialog.exec();
@@ -4350,28 +4555,41 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
return mii_nca->GetRomFS().get() != nullptr;
}
-std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed,
- u64 program_id) {
- const auto dlc_entries =
- installed.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
- std::vector<FileSys::ContentProviderEntry> dlc_match;
- dlc_match.reserve(dlc_entries.size());
- std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
- [&program_id, &installed](const FileSys::ContentProviderEntry& entry) {
- return FileSys::GetBaseTitleID(entry.title_id) == program_id &&
- installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success;
- });
-
- std::vector<u64> romfs_tids;
- romfs_tids.push_back(program_id);
- for (const auto& entry : dlc_match) {
- romfs_tids.push_back(entry.title_id);
- }
-
- if (romfs_tids.size() > 1) {
- QStringList list{QStringLiteral("Base")};
- for (std::size_t i = 1; i < romfs_tids.size(); ++i) {
- list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF));
+bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
+ u64* selected_title_id, u8* selected_content_record_type) {
+ using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>;
+ boost::container::flat_map<u64, ContentInfo> available_title_ids;
+
+ const auto RetrieveEntries = [&](FileSys::TitleType title_type,
+ FileSys::ContentRecordType record_type) {
+ const auto entries = installed.ListEntriesFilter(title_type, record_type);
+ for (const auto& entry : entries) {
+ if (FileSys::GetBaseTitleID(entry.title_id) == program_id &&
+ installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) {
+ available_title_ids[entry.title_id] = {title_type, record_type};
+ }
+ }
+ };
+
+ RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
+ RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
+
+ if (available_title_ids.empty()) {
+ return false;
+ }
+
+ size_t title_index = 0;
+
+ if (available_title_ids.size() > 1) {
+ QStringList list;
+ for (auto& [title_id, content_info] : available_title_ids) {
+ const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id));
+ if (content_info.first == FileSys::TitleType::Application) {
+ list.push_back(QStringLiteral("Application [%1]").arg(hex_title_id));
+ } else {
+ list.push_back(
+ QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id));
+ }
}
bool ok;
@@ -4379,13 +4597,16 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
this, tr("Select RomFS Dump Target"),
tr("Please select which RomFS you would like to dump."), list, 0, false, &ok);
if (!ok) {
- return {};
+ return false;
}
- return romfs_tids[list.indexOf(res)];
+ title_index = list.indexOf(res);
}
- return program_id;
+ const auto selected_info = available_title_ids.nth(title_index);
+ *selected_title_id = selected_info->first;
+ *selected_content_record_type = static_cast<u8>(selected_info->second.second);
+ return true;
}
bool GMainWindow::ConfirmClose() {
@@ -4515,6 +4736,8 @@ void GMainWindow::RequestGameExit() {
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
bool has_signalled = false;
+ system->SetExitRequested(true);
+
if (applet_oe != nullptr) {
applet_oe->GetMessageQueue()->RequestExit();
has_signalled = true;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 1b7055122..cf191f698 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -58,6 +58,11 @@ enum class StartGameType {
Global, // Only uses global configuration
};
+enum class AmLaunchType {
+ UserInitiated,
+ ApplicationInitiated,
+};
+
namespace Core {
enum class SystemResultStatus : u32;
class System;
@@ -239,9 +244,11 @@ private:
void PreventOSSleep();
void AllowOSSleep();
- bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index);
+ bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
+ AmLaunchType launch_type);
void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0,
- StartGameType with_config = StartGameType::Normal);
+ StartGameType with_config = StartGameType::Normal,
+ AmLaunchType launch_type = AmLaunchType::UserInitiated);
void ShutdownGame();
void ShowTelemetryCallout();
@@ -313,6 +320,7 @@ private slots:
void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target,
const std::string& game_path);
void OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
+ void OnGameListVerifyIntegrity(const std::string& game_path);
void OnGameListCopyTID(u64 program_id);
void OnGameListNavigateToGamedbEntry(u64 program_id,
const CompatibilityList& compatibility_list);
@@ -342,6 +350,7 @@ private slots:
void OnConfigurePerGame();
void OnLoadAmiibo();
void OnOpenYuzuFolder();
+ void OnVerifyInstalledContents();
void OnAbout();
void OnToggleFilterBar();
void OnToggleStatusBar();
@@ -375,7 +384,8 @@ private:
void RemoveAllTransferableShaderCaches(u64 program_id);
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
void RemoveCacheStorage(u64 program_id);
- std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
+ bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
+ u64* selected_title_id, u8* selected_content_record_type);
InstallResult InstallNSPXCI(const QString& filename);
InstallResult InstallNCA(const QString& filename);
void MigrateConfigFiles();
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index 013ba0ceb..e54d7d75d 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -148,6 +148,7 @@
<addaction name="action_Configure_Tas"/>
</widget>
<addaction name="action_Rederive"/>
+ <addaction name="action_Verify_installed_contents"/>
<addaction name="separator"/>
<addaction name="action_Capture_Screenshot"/>
<addaction name="menuTAS"/>
@@ -214,6 +215,11 @@
<string>&amp;Reinitialize keys...</string>
</property>
</action>
+ <action name="action_Verify_installed_contents">
+ <property name="text">
+ <string>Verify installed contents</string>
+ </property>
+ </action>
<action name="action_About">
<property name="text">
<string>&amp;About yuzu</string>
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index d0433ffc6..55d0938f7 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -265,7 +265,7 @@ int main(int argc, char** argv) {
password = match[2];
address = match[3];
if (!match[4].str().empty())
- port = std::stoi(match[4]);
+ port = static_cast<u16>(std::stoi(match[4]));
std::regex nickname_re("^[a-zA-Z0-9._\\- ]+$");
if (!std::regex_match(nickname, nickname_re)) {
std::cout
@@ -358,6 +358,7 @@ int main(int argc, char** argv) {
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
+ system.GetUserChannel().clear();
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)};