diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..48098124 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,48 @@ +Checks: > + bugprone-*, + cppcoreguidelines-*, + modernize-*, + performance-*, + readability-*, + -bugprone-easily-swappable-parameters, + -bugprone-exception-escape, + -bugprone-unchecked-optional-access, + -bugprone-derived-method-shadowing-base-method, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-pro-type-static-cast-downcast, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -modernize-use-trailing-return-type, + -modernize-use-integer-sign-comparison, + -readability-magic-numbers, + -readability-uppercase-literal-suffix, + -readability-identifier-length, + -readability-braces-around-statements, + -readability-function-cognitive-complexity, + -readability-else-after-return, + -readability-avoid-nested-conditional-operator, + -readability-math-missing-parentheses, + + -bugprone-macro-parentheses, + -cppcoreguidelines-pro-type-member-init, + -cppcoreguidelines-init-variables, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-prefer-member-initializer, + -modernize-use-nodiscard, + -readability-qualified-auto, + -readability-avoid-const-params-in-decls, + -readability-convert-member-functions-to-static, + -performance-enum-size, + -performance-no-int-to-ptr, + -clang-analyzer-optin.performance.Padding +WarningsAsErrors: '' +HeaderFilterRegex: '.*' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4498c410..15910412 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,14 +64,13 @@ jobs: echo "Installing Intel Homebrew" NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi - - brew install boost fmt sdl3 dylibbundler ' else echo "Installing arm64 deps" - brew install boost fmt sdl3 dylibbundler fi + brew install llvm boost fmt sdl3 dylibbundler + - name: Verify CMake Version run: cmake --version @@ -96,11 +95,12 @@ jobs: - name: Build Hydra run: | cmake hydra -B build \ - -DCMAKE_OSX_ARCHITECTURES=${{ env.ARCH }} \ - -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \ - -DFRONTEND=${{ env.FRONTEND_MODE }} \ - -DMACOS_BUNDLE=ON \ - -GNinja + -DCMAKE_OSX_ARCHITECTURES=${{ env.ARCH }} \ + -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \ + -DCLANG_TIDY_ENABLED=OFF \ + -DMACOS_BUNDLE=ON \ + -DFRONTEND=${{ env.FRONTEND_MODE }} \ + -GNinja ninja -C build dylibbundler -of -cd -b -x build/bin/Hydra.app/Contents/MacOS/Hydra -d build/bin/Hydra.app/Contents/libs while install_name_tool -delete_rpath @executable_path/../libs/ build/bin/Hydra.app/Contents/MacOS/Hydra 2>/dev/null; do :; done diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e7310f5..a38e4ec0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,35 @@ set(CMAKE_POLICY_VERSION_MINIMUM 3.15) include(FetchContent) +# Use LLVM clang instead of the system default one on Apple +# TODO: test with Xcode +if (APPLE AND NOT CMAKE_GENERATOR STREQUAL "Xcode") + # Find LLVM + execute_process( + COMMAND brew --prefix llvm + OUTPUT_VARIABLE LLVM_ROOT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + if (LLVM_ROOT) + message(STATUS "Using Homebrew LLVM: ${LLVM_ROOT}") + set(CMAKE_C_COMPILER "${LLVM_ROOT}/bin/clang") + set(CMAKE_CXX_COMPILER "${LLVM_ROOT}/bin/clang++") + + # Manually set sysroot + execute_process( + COMMAND xcrun --show-sdk-path + OUTPUT_VARIABLE SDK_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(CMAKE_OSX_SYSROOT "${SDK_PATH}" CACHE PATH "Sysroot") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot ${SDK_PATH}" CACHE STRING "Flags") + else () + message(WARNING "LLVM not found via brew. Falling back to default system compiler.") + endif () +endif () + project(hydra VERSION 0.4.2 LANGUAGES CXX) set(IOS_DEPLOYMENT_TARGET 17.4.0) @@ -13,6 +42,7 @@ else () set(TARGET_ARCHS "${CMAKE_HOST_SYSTEM_PROCESSOR}") endif () +option(CLANG_TIDY_ENABLED "Enable clang-tidy" ON) option(CUBEB_ENABLED "Enable the cubeb audio backend" ON) option(SDL_ENABLED "Enable building SDL files" ON) if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") @@ -44,7 +74,9 @@ endif () set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_SCAN_FOR_MODULES OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_COLOR_DIAGNOSTICS ON) if (CMAKE_BUILD_TYPE STREQUAL "Release") set(GIT_HASH_SHORT "") @@ -102,38 +134,50 @@ endif () # Externals +# elf +include_directories(SYSTEM externals/elf/include) + # toml11 -#add_subdirectory(externals/toml11) # Hatch already uses toml11 +#add_subdirectory(externals/toml11 SYSTEM) # Hatch already uses toml11 # dynarmic -add_subdirectory(externals/dynarmic) +add_subdirectory(externals/dynarmic SYSTEM) # cubeb if (CUBEB_ENABLED) set(BUILD_TESTS OFF) set(BUILD_TOOLS OFF) - add_subdirectory(externals/cubeb) + add_subdirectory(externals/cubeb SYSTEM) endif () # luft -#add_subdirectory(externals/luft) +#add_subdirectory(externals/luft SYSTEM) # hatch -add_subdirectory(externals/hatch) +add_subdirectory(externals/hatch SYSTEM) # libyaz0 -add_subdirectory(externals/libyaz0) +add_subdirectory(externals/libyaz0 SYSTEM) # nx2elf -add_subdirectory(externals/nx2elf) +add_subdirectory(externals/nx2elf SYSTEM) # date set(BUILD_TZ_LIB ON) -add_subdirectory(externals/date) +add_subdirectory(externals/date SYSTEM) set(CMAKE_COMPILE_WARNING_AS_ERROR ON) -add_library(hydra_warnings INTERFACE) -target_compile_options(hydra_warnings INTERFACE +add_library(hydra_compile_options INTERFACE) +target_compile_options(hydra_compile_options INTERFACE + # TODO: uncomment + #-fno-exceptions + #-fno-asynchronous-unwind-tables + -fno-rtti + # TODO: uncomment + #-fno-threadsafe-statics + -fvisibility=hidden + + # Warnings -Wall -Wextra -Wpedantic @@ -146,6 +190,9 @@ target_compile_options(hydra_warnings INTERFACE -Wnon-virtual-dtor -Wold-style-cast + # Disabled warnings + -Wno-missing-designated-field-initializers + # Extensions -Wno-c99-extensions -Wno-gnu-anonymous-struct @@ -156,7 +203,7 @@ target_compile_options(hydra_warnings INTERFACE -Wno-gnu-zero-variadic-macro-arguments ) -include_directories(externals/metal-cpp externals/dynarmic externals/stb) +include_directories(SYSTEM externals/metal-cpp externals/dynarmic externals/stb) if (HYPERVISOR_ENABLED) add_compile_definitions(HYDRA_HYPERVISOR_ENABLED) diff --git a/README.md b/README.md index 31337b58..eba0f2c3 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ You can download the latest release from [here](https://github.com/SamoZ256/hydr You can install Hydra dependencies with a package manager of your choice, like `brew`. ```sh -brew install cmake ninja sdl3 fmt +brew install cmake ninja llvm boost fmt sdl3 ``` ### Building diff --git a/src/common/elf.h b/externals/elf/include/elf.h similarity index 100% rename from src/common/elf.h rename to externals/elf/include/elf.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b351547a..17b50c15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,9 @@ include_directories(.) +if (CLANG_TIDY_ENABLED) + set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-use-color;-extra-arg-before=-Wno-unknown-warning-option") +endif () + add_subdirectory(common) add_subdirectory(core) add_subdirectory(frontend) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 41117b41..bf9a75c7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -8,7 +8,6 @@ add_library(hydra-common functions.hpp atomic.hpp literals.hpp - optional_helper.hpp string.hpp time.hpp hash.hpp @@ -26,8 +25,6 @@ add_library(hydra-common config.cpp config.hpp common.hpp - elf.h - stb.cpp io/stream.hpp io/continuous_stream.hpp io/memory_stream.hpp @@ -36,7 +33,7 @@ add_library(hydra-common io/sparse_stream.hpp ) -target_link_libraries(hydra-common PRIVATE hydra_warnings) +target_link_libraries(hydra-common PRIVATE hydra_compile_options) target_link_libraries(hydra-common PUBLIC fmt::fmt toml11::toml11) target_precompile_headers(hydra-common PUBLIC common.hpp) diff --git a/src/common/common.hpp b/src/common/common.hpp index 9ea5a9f4..86236154 100644 --- a/src/common/common.hpp +++ b/src/common/common.hpp @@ -23,7 +23,6 @@ #include "common/literals.hpp" #include "common/log.hpp" #include "common/objc.hpp" -#include "common/optional_helper.hpp" #include "common/platform.hpp" #include "common/range.hpp" #include "common/small_cache.hpp" diff --git a/src/common/config.cpp b/src/common/config.cpp index 5e0dbbca..8febaedc 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -34,7 +34,7 @@ template <> struct from { template static CustomResolution from_toml(const basic_value& v) { - const auto str = v.as_string(); + const auto& str = v.as_string(); const auto x_pos = str.find('x'); if (x_pos == std::string::npos) LOG_FATAL(Other, "Invalid custom display resolution {}", str); @@ -45,7 +45,7 @@ struct from { if (!str_to_num(std::string_view(str).substr(x_pos + 1), res.y())) LOG_FATAL(Other, "Invalid custom display resolution {}", str); - return CustomResolution(res); + return {res}; } }; @@ -72,7 +72,7 @@ Config::Config() { } else { LOG_FATAL(Other, "Failed to find HOME path"); } -#elif defined(PLATFORM_WINDOWS) +#elifdef PLATFORM_WINDOWS if (const char* app_data = std::getenv("APPDATA")) { app_data_path = fmt::format("{}/" APP_NAME, app_data); logs_path = fmt::format("{}/logs", app_data_path); // TODO diff --git a/src/common/config.hpp b/src/common/config.hpp index 8e29fd17..3f2ff14f 100644 --- a/src/common/config.hpp +++ b/src/common/config.hpp @@ -91,9 +91,9 @@ class Config { void Log(); // Paths - const std::string_view GetAppDataPath() const { return app_data_path; } - const std::string_view GetLogsPath() const { return logs_path; } - const std::string_view GetPicturesPath() const { return pictures_path; } + std::string_view GetAppDataPath() const { return app_data_path; } + std::string_view GetLogsPath() const { return logs_path; } + std::string_view GetPicturesPath() const { return pictures_path; } std::string GetConfigPath() const { return fmt::format("{}/config.toml", app_data_path); diff --git a/src/common/dynamic_pool.hpp b/src/common/dynamic_pool.hpp index 74d54934..8dc7fc33 100644 --- a/src/common/dynamic_pool.hpp +++ b/src/common/dynamic_pool.hpp @@ -8,7 +8,7 @@ namespace hydra { template class DynamicPool : public Pool, T, allow_zero_handle> { public: - u32 _AllocateIndex() { + u32 AllocateIndex_() { // TODO: look for a free index first const auto index = static_cast(objects.size()); @@ -17,14 +17,14 @@ class DynamicPool : public Pool, T, allow_zero_handle> { return index; } - void _FreeByIndex(u32 index) { + void FreeByIndex_(u32 index) { if (index == objects.size() - 1) objects.pop_back(); else free_slots.push_back(index); } - bool _IsValidByIndex(u32 index) const { + bool IsValidByIndex_(u32 index) const { if (index >= objects.size()) return false; @@ -32,9 +32,9 @@ class DynamicPool : public Pool, T, allow_zero_handle> { free_slots.end(); } - T& _GetByIndex(u32 index) { return objects[index]; } + T& GetByIndex_(u32 index) { return objects[index]; } - const T& _GetByIndex(u32 index) const { return objects[index]; } + const T& GetByIndex_(u32 index) const { return objects[index]; } usize GetCapacity() const { return objects.size(); } diff --git a/src/common/filesystem.hpp b/src/common/filesystem.hpp index 99147a5e..e8582219 100644 --- a/src/common/filesystem.hpp +++ b/src/common/filesystem.hpp @@ -10,33 +10,34 @@ namespace hydra { #ifdef PLATFORM_APPLE -inline std::string get_bundle_resource_path(const std::string& filename) { +inline std::string GetBundleResourcePath(const std::string& filename) { CFBundleRef main_bundle = CFBundleGetMainBundle(); - if (!main_bundle) { + if (main_bundle == nullptr) { LOG_FATAL(Common, APP_NAME " is not a bundle"); return ""; } - CFStringRef cf_filename = CFStringCreateWithCString(NULL, filename.c_str(), - kCFStringEncodingUTF8); + CFStringRef cf_filename = CFStringCreateWithCString( + nullptr, filename.c_str(), kCFStringEncodingUTF8); CFURLRef resource_url = - CFBundleCopyResourceURL(main_bundle, cf_filename, NULL, NULL); + CFBundleCopyResourceURL(main_bundle, cf_filename, nullptr, nullptr); - if (resource_url == NULL) { + if (resource_url == nullptr) { CFRelease(cf_filename); return ""; } CFStringRef resource_path = CFURLCopyFileSystemPath(resource_url, kCFURLPOSIXPathStyle); - char path[PATH_MAX]; - CFStringGetCString(resource_path, path, PATH_MAX, kCFStringEncodingUTF8); + std::array path; + CFStringGetCString(resource_path, path.data(), PATH_MAX, + kCFStringEncodingUTF8); CFRelease(cf_filename); CFRelease(resource_url); CFRelease(resource_path); - return std::string(path); + return {path.data(), path.size()}; } #endif diff --git a/src/common/functions.hpp b/src/common/functions.hpp index badd04c0..f131640e 100644 --- a/src/common/functions.hpp +++ b/src/common/functions.hpp @@ -70,7 +70,7 @@ T align_down(T v, T alignment) { } template -PtrT* align_ptr(PtrT* ptr, AlignmentT alignment) { +PtrT* AlignPtr(PtrT* ptr, AlignmentT alignment) { return reinterpret_cast( align(reinterpret_cast(ptr), static_cast(alignment))); } @@ -108,21 +108,6 @@ inline std::string to_upper(const std::string_view str) { return result; } -/* -inline constexpr u64 str_to_u64(const char* str, usize idx = 0, - u64 result = 0) { - return (str[idx] == '\0' || idx >= 8) - ? result - : str_to_u64(str, idx + 1, - result | (static_cast(str[idx]) << (idx * 8))); -} -*/ - -inline std::string u64_to_str(u64 value) { - char* str = reinterpret_cast(&value); - return std::string(str, std::min(strlen(str), static_cast(8))); -} - inline std::string demangle(const char* mangled_name) { i32 status; std::unique_ptr result{ diff --git a/src/common/hash.hpp b/src/common/hash.hpp index 04263948..ffe15cb3 100644 --- a/src/common/hash.hpp +++ b/src/common/hash.hpp @@ -6,9 +6,7 @@ namespace hydra { class HashCode { public: - HashCode() - : v1{prime1 + prime2}, v2{prime2}, v3{0}, v4{prime1}, queue1{0}, - queue2{0}, queue3{0}, length{0} {} + HashCode() : v1{prime1 + prime2}, v2{prime2}, v4{prime1} {} void Add(u32 value) { u32 previous_length = length++; @@ -45,13 +43,15 @@ class HashCode { } template - void Add(const T& value) requires std::is_trivially_copyable_v { + void Add(const T& value) + requires std::is_trivially_copyable_v + { const u8* bytes = reinterpret_cast(&value); for (usize i = 0; i < sizeof(T); ++i) Add(static_cast(bytes[i])); } - u32 ToHashCode() { + u32 ToHashCode() const { u32 hash = length < 4 ? MixEmptyState() : MixState(v1, v2, v3, v4); hash += length * 4; @@ -76,9 +76,9 @@ class HashCode { static constexpr u32 prime4 = 668265263u; static constexpr u32 prime5 = 374761393u; - u32 v1, v2, v3, v4; - u32 queue1, queue2, queue3; - u32 length; + u32 v1, v2, v3{0}, v4; + u32 queue1{0}, queue2{0}, queue3{0}; + u32 length{0}; static u32 Round(u32 hash, u32 input) { return std::rotl(hash + input * prime2, 13) * prime1; diff --git a/src/common/io/continuous_stream.hpp b/src/common/io/continuous_stream.hpp index ca8fbfef..134a00a3 100644 --- a/src/common/io/continuous_stream.hpp +++ b/src/common/io/continuous_stream.hpp @@ -6,6 +6,12 @@ namespace hydra::io { class IContinuousStream : public IStream { public: + IContinuousStream() noexcept = default; + ~IContinuousStream() noexcept = default; + + MAKE_DEFAULT_COPYABLE(IContinuousStream); + MAKE_NON_MOVABLE(IContinuousStream); + u64 GetSeek() const override { return seek; } void SeekTo(u64 seek_) override { seek = seek_; } void SeekBy(u64 offset) override { seek += offset; } diff --git a/src/common/io/memory_stream.hpp b/src/common/io/memory_stream.hpp index 201bfb9b..1a3f9212 100644 --- a/src/common/io/memory_stream.hpp +++ b/src/common/io/memory_stream.hpp @@ -8,6 +8,9 @@ class MemoryStream : public IContinuousStream { public: MemoryStream(std::span data_) : data{data_} {} + MAKE_DEFAULT_COPYABLE(MemoryStream); + MAKE_DEFAULT_MOVABLE(MemoryStream); + u64 GetSize() const override { return data.size(); } u8* GetPtr() override { return data.data(); } diff --git a/src/common/io/sparse_stream.hpp b/src/common/io/sparse_stream.hpp index eb3ac9b1..499a043b 100644 --- a/src/common/io/sparse_stream.hpp +++ b/src/common/io/sparse_stream.hpp @@ -5,19 +5,15 @@ namespace hydra::io { -struct SparseStreamEntry { - Range range; - IStream* stream; -}; - class SparseStream : public IStream { public: - enum class Error { - SeekOutOfBounds, + struct Entry { + Range range; + IStream* stream; }; // Entries must be sorted by offset - SparseStream(const std::vector& entries_, u64 size_) + SparseStream(std::vector entries_, u64 size_) : entries{std::move(entries_)}, size{size_} {} u64 GetSeek() const override { return seek; } @@ -34,13 +30,14 @@ class SparseStream : public IStream { void ReadRaw(std::span buffer) override { while (!buffer.empty()) { - ASSERT_THROWING_DEBUG(seek <= size, Common, Error::SeekOutOfBounds, - "Seek out of bounds"); + ASSERT_DEBUG(seek + buffer.size() <= size, Common, + "Seek out of bounds ({} > {})", seek + buffer.size(), + size); const auto entry = GetEntry(seek); const auto max_read_size = std::min( entry.range.GetEnd() - seek, static_cast(buffer.size())); - if (entry.stream) { + if (entry.stream != nullptr) { entry.stream->SeekTo(seek - entry.range.GetBegin()); entry.stream->ReadRaw(buffer.subspan(0, max_read_size)); } else { @@ -55,13 +52,14 @@ class SparseStream : public IStream { void WriteRaw(std::span buffer) override { while (!buffer.empty()) { - ASSERT_THROWING_DEBUG(seek <= size, Common, Error::SeekOutOfBounds, - "Seek out of bounds"); + ASSERT_DEBUG(seek + buffer.size() <= size, Common, + "Seek out of bounds ({} > {})", seek + buffer.size(), + size); const auto entry = GetEntry(seek); const auto max_write_size = std::min( entry.range.GetEnd() - seek, static_cast(buffer.size())); - if (entry.stream) { + if (entry.stream != nullptr) { entry.stream->SeekTo(seek - entry.range.GetBegin()); entry.stream->WriteRaw(buffer.subspan(0, max_write_size)); } @@ -72,16 +70,16 @@ class SparseStream : public IStream { } protected: - std::vector entries; + std::vector entries; private: u64 size; u64 seek{0}; - std::optional cached_entry{std::nullopt}; + std::optional cached_entry{std::nullopt}; // Helpers - SparseStreamEntry GetEntry(u64 offset) { + Entry GetEntry(u64 offset) { // First, check if the entry has been cached if (cached_entry.has_value()) { const auto entry = cached_entry.value(); @@ -92,24 +90,24 @@ class SparseStream : public IStream { // Find the entry that contains the offset auto next_it = std::upper_bound(entries.begin(), entries.end(), offset, - [](u64 offset, const SparseStreamEntry& entry) { + [](u64 offset, const Entry& entry) { return offset < entry.range.GetBegin(); }); // If the offset is before the first entry, return an empty entry if (next_it == entries.begin()) - return {.stream = nullptr, .range = {0, next_it->range.GetBegin()}}; + return {.range = {0, next_it->range.GetBegin()}, .stream = nullptr}; auto it = std::prev(next_it); // Check if entry is past the range if (!it->range.Contains(offset)) { if (next_it == entries.end()) - return {.stream = nullptr, - .range = {it->range.GetEnd(), size - offset}}; + return {.range = {it->range.GetEnd(), size - offset}, + .stream = nullptr}; - return {.stream = nullptr, - .range = {it->range.GetEnd(), next_it->range.GetBegin()}}; + return {.range = {it->range.GetEnd(), next_it->range.GetBegin()}, + .stream = nullptr}; } // Cache the entry and return it @@ -118,6 +116,7 @@ class SparseStream : public IStream { } }; +// TODO: remove class OwnedSparseStream : public SparseStream { public: using SparseStream::SparseStream; @@ -126,6 +125,8 @@ class OwnedSparseStream : public SparseStream { for (auto entry : entries) delete entry.stream; } + + MAKE_NON_COPYABLE(OwnedSparseStream); }; } // namespace hydra::io diff --git a/src/common/io/stream.hpp b/src/common/io/stream.hpp index 75d852c6..f5a1384f 100644 --- a/src/common/io/stream.hpp +++ b/src/common/io/stream.hpp @@ -10,7 +10,11 @@ class IStream { friend class SparseStream; public: - virtual ~IStream() = default; + IStream() = default; + virtual ~IStream() noexcept = default; + + MAKE_DEFAULT_COPYABLE(IStream); + MAKE_DEFAULT_MOVABLE(IStream); virtual u64 GetSeek() const = 0; virtual void SeekTo(u64 seek) { @@ -26,7 +30,7 @@ class IStream { // Read template - const T Read() { + T Read() { T result; ReadRaw(std::span(reinterpret_cast(&result), sizeof(T))); return result; @@ -62,7 +66,7 @@ class IStream { std::string_view ReadString(usize size) { const auto ptr = ReadPtr(); - return std::string_view(ptr, size); + return {ptr, size}; } std::string_view ReadNullTerminatedString() { @@ -73,7 +77,7 @@ class IStream { size++; } - return std::string_view(ptr, size); + return {ptr, size}; } // Write diff --git a/src/common/io/stream_view.hpp b/src/common/io/stream_view.hpp index c6f4ceef..1c95ab65 100644 --- a/src/common/io/stream_view.hpp +++ b/src/common/io/stream_view.hpp @@ -37,11 +37,14 @@ class StreamView : public IStream { u64 size; }; +// TODO: remove class OwnedStreamView : public StreamView { public: using StreamView::StreamView; ~OwnedStreamView() override { delete base; } + + MAKE_NON_COPYABLE(OwnedStreamView); }; } // namespace hydra::io diff --git a/src/common/linked_list.hpp b/src/common/linked_list.hpp index a4c5e44f..7b3d6269 100644 --- a/src/common/linked_list.hpp +++ b/src/common/linked_list.hpp @@ -11,7 +11,7 @@ class LinkedListNode { friend class LinkedList; public: - LinkedListNode(const T& value_) : value{value_}, next{nullptr} {} + LinkedListNode(const T& value_) : value{value_} {} operator const T&() const { return value; } const T* operator->() const { return &value; } @@ -19,7 +19,7 @@ class LinkedListNode { private: T value; - LinkedListNode* next; + LinkedListNode* next{nullptr}; public: CONST_REF_GETTER(value, Get); @@ -32,8 +32,7 @@ class LinkedListNode { friend class LinkedList; public: - LinkedListNode(const T& value_) - : value{value_}, next{nullptr}, prev{nullptr} {} + LinkedListNode(const T& value_) : value{value_} {} operator const T&() const { return value; } const T* operator->() const { return &value; } @@ -41,8 +40,8 @@ class LinkedListNode { private: T value; - LinkedListNode* next; - LinkedListNode* prev; + LinkedListNode* next{nullptr}; + LinkedListNode* prev{nullptr}; public: CONST_REF_GETTER(value, Get); @@ -52,16 +51,16 @@ class LinkedListNode { template class LinkedList { + using Node = LinkedListNode; + public: enum class Error { Empty, InvalidNode, }; - LinkedList() : head{nullptr}, tail{nullptr}, size{0} {} - void AddFirst(const T& value) { - auto node = new LinkedListNode(value); + auto node = new Node(value); if (!head) { head = tail = node; } else { @@ -74,7 +73,7 @@ class LinkedList { } void AddLast(const T& value) { - auto node = new LinkedListNode(value); + auto node = new Node(value); if (!head) { head = tail = node; } else { @@ -87,7 +86,7 @@ class LinkedList { } void RemoveFirst() { - ASSERT_THROWING_DEBUG(head, Common, Error::Empty, "List is empty"); + ASSERT_DEBUG(head, Common, "List is empty"); auto node = head; head = head->next; @@ -98,7 +97,7 @@ class LinkedList { } bool RemoveLast() { - ASSERT_THROWING_DEBUG(head, Common, Error::Empty, "List is empty"); + ASSERT_DEBUG(head, Common, "List is empty"); if (!head->next) { delete head; @@ -114,11 +113,9 @@ class LinkedList { size--; } - LinkedListNode* - Remove(LinkedListNode* target) { - ASSERT_THROWING_DEBUG(target, Common, Error::InvalidNode, - "Invalid node"); - ASSERT_THROWING_DEBUG(head, Common, Error::Empty, "List is empty"); + Node* Remove(Node* target) { + ASSERT_DEBUG(target, Common, "Invalid node"); + ASSERT_DEBUG(head, Common, "List is empty"); if constexpr (is_doubly_linked) { // A more efficient way to remove a node from a doubly linked list @@ -127,8 +124,7 @@ class LinkedList { if (target == head) { head = target->next; } else { - ASSERT_THROWING_DEBUG(target->prev, Common, Error::InvalidNode, - "Invalid node"); + ASSERT_DEBUG(target->prev, Common, "Invalid node"); target->prev->next = target->next; } @@ -136,8 +132,7 @@ class LinkedList { if (target == tail) { tail = target->prev; } else { - ASSERT_THROWING_DEBUG(target->next, Common, Error::InvalidNode, - "Invalid node"); + ASSERT_DEBUG(target->next, Common, "Invalid node"); target->next->prev = target->prev; } @@ -159,8 +154,7 @@ class LinkedList { auto node = head; while (node->next && node->next != target) node = node->next; - ASSERT_THROWING_DEBUG(node->next, Common, Error::InvalidNode, - "Invalid node"); + ASSERT_DEBUG(node->next, Common, "Invalid node"); node->next = target->next; delete target; @@ -171,10 +165,10 @@ class LinkedList { } } - - void Remove(const T& target) requires is_doubly_linked { - ASSERT_THROWING_DEBUG(target, Common, Error::InvalidNode, - "Invalid node"); + void Remove(const T& target) + requires is_doubly_linked + { + ASSERT_DEBUG(target, Common, "Invalid node"); // Remove all occurrences of the target for (auto node = head; node;) { @@ -192,9 +186,9 @@ class LinkedList { } private: - LinkedListNode* head; - LinkedListNode* tail; - usize size; + Node* head{nullptr}; + Node* tail{nullptr}; + usize size{0}; public: GETTER(head, GetHead); diff --git a/src/common/log.cpp b/src/common/log.cpp index 7b087d69..7fff007a 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -1,5 +1,7 @@ #include "common/log.hpp" +#include + #include "common/config.hpp" namespace hydra { @@ -10,16 +12,8 @@ constexpr usize MAX_LOG_FILES = 3; } -// TODO: will the destructor ever get called? -Logger::~Logger() { - if (ofs) { - ofs->close(); - delete ofs; - } -} - void Logger::EnsureOutputStream() { - if (ofs) + if (ofs.has_value()) return; const auto logs_path = CONFIG_INSTANCE.GetLogsPath(); @@ -33,7 +27,7 @@ void Logger::EnsureOutputStream() { // Delete oldest logs if needed if (logs.size() >= MAX_LOG_FILES) { - std::sort(logs.begin(), logs.end(), [](const auto& a, const auto& b) { + std::ranges::sort(logs, [](const auto& a, const auto& b) { return std::filesystem::last_write_time(a) < std::filesystem::last_write_time(b); }); @@ -47,7 +41,7 @@ void Logger::EnsureOutputStream() { // TODO: version const auto path = fmt::format("{}/" APP_NAME "_{:%Y-%m-%d_%H-%M-%S}.log", logs_path, std::chrono::system_clock::now()); - ofs = new std::ofstream(path); + ofs = std::ofstream(path); // Get start time start_time = clock_t::now(); diff --git a/src/common/log.hpp b/src/common/log.hpp index 0486c630..656d230e 100644 --- a/src/common/log.hpp +++ b/src/common/log.hpp @@ -15,7 +15,7 @@ #define LOG(level, c, ...) \ LOGGER_INSTANCE.Log(LogLevel::level, LogClass::c, \ - trim_source_path(__FILE__), __LINE__, __func__, \ + TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #ifdef HYDRA_DEBUG @@ -59,11 +59,6 @@ if (!(condition)) { \ LOG_FATAL(c, __VA_ARGS__); \ } -#define ASSERT_THROWING(condition, c, err, ...) \ - if (!(condition)) { \ - LOG_ERROR_ON_DEBUG(c, __VA_ARGS__); \ - throw err; \ - } #define ASSERT_ALIGNMENT(value, alignment, c, name) \ ASSERT(is_aligned(value, alignment), c, \ @@ -72,8 +67,6 @@ #ifdef HYDRA_DEBUG #define ASSERT_DEBUG(condition, c, ...) ASSERT(condition, c, __VA_ARGS__) -#define ASSERT_THROWING_DEBUG(condition, c, err, ...) \ - ASSERT_THROWING(condition, c, err, __VA_ARGS__) #define ASSERT_ALIGNMENT_DEBUG(value, alignment, c, name) \ ASSERT_ALIGNMENT(value, alignment, c, name) #else @@ -81,9 +74,6 @@ #define ASSERT_DEBUG(condition, c, ...) \ if (condition) { \ } -#define ASSERT_THROWING_DEBUG(condition, c, err, ...) \ - if (condition) { \ - } #define ASSERT_ALIGNMENT_DEBUG(value, alignment, c, name) #endif @@ -93,9 +83,9 @@ namespace hydra { // From yuzu -constexpr const char* trim_source_path(std::string_view source) { +constexpr const char* TrimSourcePath(std::string_view source) { const auto rfind = [source](const std::string_view match) { - return source.rfind(match) == source.npos + return source.rfind(match) == std::string_view::npos ? 0 : (source.rfind(match) + match.size()); }; @@ -170,7 +160,7 @@ struct LogMessage { std::string str; }; -typedef std::function log_callback_fn_t; +using log_callback_fn_t = std::function; class Logger { public: @@ -179,9 +169,13 @@ class Logger { return instance; } - ~Logger(); + Logger() noexcept = default; + ~Logger() noexcept = default; + + MAKE_NON_COPYABLE(Logger); + MAKE_NON_MOVABLE(Logger); - void InstallCallback(log_callback_fn_t callback_) { + void InstallCallback(const log_callback_fn_t& callback_) { std::lock_guard lock(mutex); callback = callback_; } @@ -271,9 +265,6 @@ class Logger { break; } - default: - throw std::runtime_error("Invalid logging output"); - break; } } @@ -291,10 +282,10 @@ class Logger { } private: - typedef std::chrono::high_resolution_clock clock_t; + using clock_t = std::chrono::high_resolution_clock; std::mutex mutex; - std::ofstream* ofs{nullptr}; + std::optional ofs{}; std::optional callback{}; LogOutput output{LogOutput::StdOut}; diff --git a/src/common/lz4.cpp b/src/common/lz4.cpp index 8305e6e4..479214c4 100644 --- a/src/common/lz4.cpp +++ b/src/common/lz4.cpp @@ -1,11 +1,13 @@ #include "common/lz4.hpp" +#include + namespace hydra { namespace { u32 GetLength(std::span src, u32& cmp_pos, u32 length) { - u8 sum; + u8 sum = 0; if (length == 0xf) { do { length += sum = src[cmp_pos++]; @@ -30,7 +32,7 @@ void DecompressLZ4(std::span src, std::span dst) { // Copy literal chunk lit_count = GetLength(src, cmp_pos, lit_count); - memcpy(dst.data() + dec_pos, src.data() + cmp_pos, lit_count); + std::memcpy(dst.data() + dec_pos, src.data() + cmp_pos, lit_count); cmp_pos += lit_count; dec_pos += lit_count; @@ -48,7 +50,7 @@ void DecompressLZ4(std::span src, std::span dst) { u32 enc_pos = dec_pos - back; if (enc_count <= back) { - memcpy(dst.data() + dec_pos, dst.data() + enc_pos, enc_count); + std::memcpy(dst.data() + dec_pos, dst.data() + enc_pos, enc_count); dec_pos += enc_count; } else { diff --git a/src/common/lz4.hpp b/src/common/lz4.hpp index 038f5743..a75b7a4a 100644 --- a/src/common/lz4.hpp +++ b/src/common/lz4.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "common/type_aliases.hpp" namespace hydra { diff --git a/src/common/macros.hpp b/src/common/macros.hpp index 27252733..0facb327 100644 --- a/src/common/macros.hpp +++ b/src/common/macros.hpp @@ -4,7 +4,27 @@ #define sizeof_array(array) (sizeof(array) / sizeof(array[0])) -#define PACKED __attribute__((packed, aligned(1))) +#define CONCAT_IMPL(a, b) a##b +#define CONCAT(a, b) CONCAT_IMPL(a, b) + +#define UNIQUE_SUFFIX(var) CONCAT(var, __LINE__) + +#define ASSIGN_OR(var, expected, fail_statement) \ + const auto UNIQUE_SUFFIX(_) = expected; \ + if (!UNIQUE_SUFFIX(_).has_value()) \ + fail_statement; \ + var = UNIQUE_SUFFIX(_).value(); + +#define ASSIGN_OR_RETURN_VALUE(var, expected, ret) \ + ASSIGN_OR(var, expected, return ret) +#define ASSIGN_OR_RETURN(var, expected) ASSIGN_OR_RETURN_VALUE(var, expected, ) +#define ASSIGN_OR_RETURN_ERROR(var, expected) \ + ASSIGN_OR_RETURN_VALUE(var, expected, std::unexpected(expected.error())) + +#define ASSIGN_OR_CONTINUE(var, expected, ret) \ + ASSIGN_OR(var, expected, continue) + +#define ASSIGN_OR_BREAK(var, expected, ret) ASSIGN_OR(var, expected, break) #define ONCE(code) \ { \ @@ -24,61 +44,70 @@ #define BIT(n) (1u << (n)) #define BITL(n) (1ul << (n)) -#define UNDERLYING(t) std::underlying_type_t - #define ENABLE_ENUM_ARITHMETIC_OPERATORS(type) \ [[maybe_unused]] inline type operator+(type a, type b) { \ - return static_cast(static_cast(a) + \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) + \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type operator-(type a, type b) { \ - return static_cast(static_cast(a) - \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) - \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type operator*(type a, type b) { \ - return static_cast(static_cast(a) * \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) * \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type operator/(type a, type b) { \ - return static_cast(static_cast(a) / \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) / \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type operator++(type& x, i32) { \ const auto tmp = x; \ - x = static_cast(static_cast(x) + 1); \ + x = static_cast(static_cast>(x) + \ + 1); \ return tmp; \ } \ [[maybe_unused]] inline type operator--(type& x, i32) { \ const auto tmp = x; \ - x = static_cast(static_cast(x) - 1); \ + x = static_cast(static_cast>(x) - \ + 1); \ return tmp; \ } \ [[maybe_unused]] inline type& operator++(type& x) { \ - x = static_cast(static_cast(x) + 1); \ + x = static_cast(static_cast>(x) + \ + 1); \ return x; \ } \ [[maybe_unused]] inline type& operator--(type& x) { \ - x = static_cast(static_cast(x) - 1); \ + x = static_cast(static_cast>(x) - \ + 1); \ return x; \ } #define ENABLE_ENUM_BITWISE_OPERATORS(type) \ [[maybe_unused]] inline type operator|(type a, type b) { \ - return static_cast(static_cast(a) | \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) | \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type& operator|=(type& a, type b) { \ return a = a | b; \ } \ [[maybe_unused]] inline type operator&(type a, type b) { \ - return static_cast(static_cast(a) & \ - static_cast(b)); \ + return static_cast( \ + static_cast>(a) & \ + static_cast>(b)); \ } \ [[maybe_unused]] inline type& operator&=(type& a, type b) { \ return a = a & b; \ } \ [[maybe_unused]] inline type operator~(type a) { \ - return static_cast(~static_cast(a)); \ + return static_cast( \ + ~static_cast>(a)); \ } \ [[maybe_unused]] inline bool any(type a) { return a != type::None; } @@ -261,3 +290,44 @@ return formatter::format(name, ctx); \ } \ }; + +#define MAKE_DEFAULT_COPYABLE(type) \ + type(const type&) noexcept = default; \ + type& operator=(const type&) noexcept = default; + +#define MAKE_NON_COPYABLE(type) \ + type(const type&) = delete; \ + type& operator=(const type&) = delete; + +#define MAKE_DEFAULT_MOVABLE(type) \ + type(type&&) noexcept = default; \ + type& operator=(type&&) noexcept = default; + +#define MAKE_NON_MOVABLE(type) \ + type(type&&) = delete; \ + type& operator=(type&&) = delete; + +#define SWAP_CASE(member) std::swap(a.member, b.member); + +#define MAKE_MOVE_ASSIGNABLE(type, ...) \ + type& operator=(type&& other) noexcept { \ + if (this != &other) { \ + type temp(std::move(other)); \ + swap(*this, temp); \ + } \ + return *this; \ + } \ + friend void swap(type& a, type& b) { FOR_EACH_0_1(SWAP_CASE, __VA_ARGS__) } + +#define MOVE_CASE(member, value) \ + , member { value } +#define MOVE_MEMBERS(member1, value1, ...) \ + member1{value1} FOR_EACH_0_2(MOVE_CASE, __VA_ARGS__) + +#define PASS_TO_MAKE_MOVE_ASSIGNABLE_CASE(member, value) , member +#define PASS_TO_MAKE_MOVE_ASSIGNABLE(member1, value1, ...) \ + member1 FOR_EACH_0_2(PASS_TO_MAKE_MOVE_ASSIGNABLE_CASE, __VA_ARGS__) + +#define MAKE_MOVABLE(type, ...) \ + type(type&& other) noexcept : MOVE_MEMBERS(__VA_ARGS__) {} \ + MAKE_MOVE_ASSIGNABLE(type, PASS_TO_MAKE_MOVE_ASSIGNABLE(__VA_ARGS__)) diff --git a/src/common/objc.hpp b/src/common/objc.hpp index 40ea4ec6..9e5802cf 100644 --- a/src/common/objc.hpp +++ b/src/common/objc.hpp @@ -7,7 +7,7 @@ namespace hydra { #ifndef __OBJC__ -typedef void* id; +using id = void*; #endif } // namespace hydra diff --git a/src/common/optional_helper.hpp b/src/common/optional_helper.hpp deleted file mode 100644 index 0a7a8828..00000000 --- a/src/common/optional_helper.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -namespace hydra { - -template -T* unwrap_or_null(std::optional& opt) { - return opt ? std::addressof(opt.value()) : nullptr; -} - -template -const T* unwrap_or_null(const std::optional& opt) { - return opt ? std::addressof(opt.value()) : nullptr; -} - -} // namespace hydra diff --git a/src/common/pool.hpp b/src/common/pool.hpp index f87fff63..9b05e455 100644 --- a/src/common/pool.hpp +++ b/src/common/pool.hpp @@ -8,45 +8,41 @@ namespace hydra { template class Pool { public: - enum class Error { - InvalidHandle, - }; - handle_id_t AllocateHandle() { - return IndexToHandle(THIS->_AllocateIndex()); + return IndexToHandle(THIS->AllocateIndex_()); } - T& Allocate() { return THIS->_GetByIndex(THIS->_AllocateIndex()); } + T& Allocate() { return THIS->GetByIndex_(THIS->AllocateIndex_()); } - handle_id_t Add(const T& object) { - const auto index = THIS->_AllocateIndex(); - THIS->_GetByIndex(index) = object; + handle_id_t Insert(const T& object) { + const auto index = THIS->AllocateIndex_(); + THIS->GetByIndex_(index) = object; return IndexToHandle(index); } void Free(handle_id_t handle_id) { - THIS->_FreeByIndex(HandleToIndex(handle_id)); + THIS->FreeByIndex_(HandleToIndex(handle_id)); } bool IsValid(handle_id_t handle_id) const { - return CONST_THIS->_IsValidByIndex(HandleToIndex(handle_id)); + return CONST_THIS->IsValidByIndex_(HandleToIndex(handle_id)); } T& Get(handle_id_t handle_id) { AssertHandle(handle_id); - return THIS->_GetByIndex(HandleToIndex(handle_id)); + return THIS->GetByIndex_(HandleToIndex(handle_id)); } const T& Get(handle_id_t handle_id) const { AssertHandle(handle_id); - return CONST_THIS->_GetByIndex(HandleToIndex(handle_id)); + return CONST_THIS->GetByIndex_(HandleToIndex(handle_id)); } private: // Helpers void AssertHandle(handle_id_t handle_id) const { - ASSERT_THROWING_DEBUG(IsValid(handle_id), Common, Error::InvalidHandle, - "Invalid handle {}", handle_id); + ASSERT_DEBUG(IsValid(handle_id), Common, "Invalid handle {}", + handle_id); } static handle_id_t IndexToHandle(u32 index) { @@ -60,8 +56,8 @@ class Pool { if constexpr (allow_zero_handle) { return handle_id; } else { - ASSERT_THROWING_DEBUG(handle_id != INVALID_HANDLE_ID, Common, - Error::InvalidHandle, "Invalid handle"); + ASSERT_DEBUG(handle_id != INVALID_HANDLE_ID, Common, + "Invalid handle"); return handle_id - 1; } } diff --git a/src/common/small_cache.hpp b/src/common/small_cache.hpp index ab5e7150..c1a97597 100644 --- a/src/common/small_cache.hpp +++ b/src/common/small_cache.hpp @@ -87,13 +87,11 @@ class SmallCache { map_iter slow_it; }; - SmallCache() = default; + SmallCache() noexcept = default; + ~SmallCache() noexcept = default; - SmallCache(const SmallCache&) = delete; - SmallCache& operator=(const SmallCache&) = delete; - - SmallCache(SmallCache&&) = default; - SmallCache& operator=(SmallCache&&) = default; + MAKE_NON_COPYABLE(SmallCache); + MAKE_DEFAULT_MOVABLE(SmallCache); // TODO: const versions as well iterator begin() { return iterator(this, 0); } @@ -115,12 +113,8 @@ class SmallCache { slow_cache.clear(); } - enum class AddError { - AlreadyPresent, - }; - template - T& Add(KeyT key, Args&&... args) { + T& Insert(KeyT key, Args&&... args) { // Insert into fast cache if possible for (auto& entry : fast_cache) { if (!entry.has_value()) { @@ -129,9 +123,8 @@ class SmallCache { std::forward_as_tuple(std::forward(args)...)); return entry.value().second; } else { - ASSERT_THROWING(entry.value().first != key, Common, - AddError::AlreadyPresent, - "Entry already present"); + ASSERT_DEBUG(entry.value().first != key, Common, + "Entry already present"); } } @@ -139,8 +132,7 @@ class SmallCache { auto res = slow_cache.emplace( std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(std::forward(args)...)); - ASSERT_THROWING(res.second, Common, AddError::AlreadyPresent, - "Entry already present"); + ASSERT_DEBUG(res.second, Common, "Entry already present"); return res.first->second; } diff --git a/src/common/static_pool.hpp b/src/common/static_pool.hpp index c4180f2f..183824a6 100644 --- a/src/common/static_pool.hpp +++ b/src/common/static_pool.hpp @@ -17,14 +17,14 @@ class StaticPool : public Pool, T, allow_zero_handle> { free_slots[i] = std::numeric_limits::max(); } - u32 _AllocateIndex() { + u32 AllocateIndex_() { if (crnt < size) { Take(crnt); return crnt++; } for (u32 i = 0; i < size; i++) { - if (!_IsValidByIndex(i)) { + if (!IsValidByIndex_(i)) { Take(i); return i; } @@ -37,9 +37,9 @@ class StaticPool : public Pool, T, allow_zero_handle> { return invalid(); } - void _FreeByIndex(u32 index) { FREE_SLOT(index) |= MASK(index); } + void FreeByIndex_(u32 index) { FREE_SLOT(index) |= MASK(index); } - bool _IsValidByIndex(u32 index) const { + bool IsValidByIndex_(u32 index) const { if (index >= crnt) return false; @@ -47,15 +47,15 @@ class StaticPool : public Pool, T, allow_zero_handle> { return !is_free; } - T& _GetByIndex(u32 index) { return objects[index]; } + T& GetByIndex_(u32 index) { return objects[index]; } - const T& _GetByIndex(u32 index) const { return objects[index]; } + const T& GetByIndex_(u32 index) const { return objects[index]; } usize GetCapacity() const { return size; } private: - T objects[size]; - u8 free_slots[FREE_SIZE]; + std::array objects; + std::array free_slots; u32 crnt{0}; void Take(u32 index) { FREE_SLOT(index) &= ~MASK(index); } diff --git a/src/common/string.hpp b/src/common/string.hpp index 2980d71f..b0d78f14 100644 --- a/src/common/string.hpp +++ b/src/common/string.hpp @@ -5,7 +5,7 @@ namespace hydra { // TODO: make sure the string's length doesn't exceed 8 characters -inline constexpr u64 ToU64String(std::string_view str) { +inline constexpr u64 StringAsU64(std::string_view str) { u64 res = 0; for (u32 i = 0; i < str.size(); i++) res |= static_cast(str[i]) << (i * 8); @@ -13,36 +13,40 @@ inline constexpr u64 ToU64String(std::string_view str) { return res; } +// TODO: rework? +inline std::string U64AsString(u64 value) { + char* str = reinterpret_cast(&value); + return {str, std::min(strlen(str), 8)}; +} + inline constexpr u64 operator"" _u64(const char* str, unsigned long len) { - return ToU64String(std::string_view(str, len)); + return StringAsU64(std::string_view(str, len)); } -constexpr usize size_of_string(char value) { +constexpr usize SizeOfString(char value) { (void)value; return 1; } -constexpr usize size_of_string(std::string_view value) { return value.size(); } +constexpr usize SizeOfString(std::string_view value) { return value.size(); } -constexpr usize size_of_string(const std::string& value) { - return value.size(); -} +constexpr usize SizeOfString(const std::string& value) { return value.size(); } template -std::vector split(std::string_view s, Delimiter delimiter) { +std::vector Split(std::string_view s, Delimiter delimiter) { std::vector tokens; usize pos = 0; while ((pos = s.find(delimiter)) != std::string::npos) { std::string_view token = s.substr(0, pos); tokens.push_back(T(token)); - s = s.substr(pos + size_of_string(delimiter)); + s = s.substr(pos + SizeOfString(delimiter)); } tokens.push_back(T(s)); return tokens; } -inline std::string utf16_to_utf8(const std::u16string& utf16_str) { +inline std::optional Utf16ToUtf8(const std::u16string& utf16_str) { std::string utf8_str; utf8_str.reserve(utf16_str.size() * 3); // Reserve space to avoid reallocations @@ -54,19 +58,14 @@ inline std::string utf16_to_utf8(const std::u16string& utf16_str) { // Handle surrogate pairs if (unit >= 0xd800 && unit <= 0xdbff) { // High surrogate - if (i + 1 >= utf16_str.size()) { - throw std::invalid_argument( - "Invalid UTF-16: unpaired high surrogate"); - } + if (i + 1 >= utf16_str.size()) + return std::nullopt; char16_t low = utf16_str[++i]; - if (low < 0xDC00 || low > 0xDFFF) { - throw std::invalid_argument( - "Invalid UTF-16: invalid low surrogate"); - } + if (low < 0xDC00 || low > 0xDFFF) + return std::nullopt; codepoint = 0x10000u + ((unit & 0x3ffu) << 10) + (low & 0x3ffu); } else if (unit >= 0xdc00 && unit <= 0xdfff) { - throw std::invalid_argument( - "Invalid UTF-16: unpaired low surrogate"); + return std::nullopt; } else { codepoint = unit; } @@ -90,20 +89,20 @@ inline std::string utf16_to_utf8(const std::u16string& utf16_str) { static_cast(0x80 | ((codepoint >> 6) & 0x3f))); utf8_str.push_back(static_cast(0x80 | (codepoint & 0x3f))); } else { - throw std::invalid_argument("Invalid Unicode codepoint"); + return std::nullopt; } } return utf8_str; } -inline std::u16string utf8_to_utf16(const std::string& utf8_str) { +inline std::optional Utf8ToUtf16(const std::string& utf8_str) { std::u16string utf16_str; utf16_str.reserve(utf8_str.size()); // Reserve space to avoid reallocations for (usize i = 0; i < utf8_str.size();) { char32_t codepoint = 0; - unsigned char byte = static_cast(utf8_str[i]); + const auto byte = static_cast(utf8_str[i]); // Determine the number of bytes in this UTF-8 character if (byte <= 0x7F) { @@ -112,69 +111,50 @@ inline std::u16string utf8_to_utf16(const std::string& utf8_str) { i += 1; } else if ((byte & 0xE0) == 0xC0) { // 2-byte character - if (i + 1 >= utf8_str.size()) { - throw std::invalid_argument( - "Invalid UTF-8: incomplete 2-byte sequence"); - } - unsigned char byte2 = static_cast(utf8_str[i + 1]); - if ((byte2 & 0xC0) != 0x80) { - throw std::invalid_argument( - "Invalid UTF-8: invalid continuation byte"); - } + if (i + 1 >= utf8_str.size()) + return std::nullopt; + const auto byte2 = static_cast(utf8_str[i + 1]); + if ((byte2 & 0xC0) != 0x80) + return std::nullopt; codepoint = ((byte & 0x1fu) << 6) | (byte2 & 0x3fu); - if (codepoint < 0x80) { - throw std::invalid_argument("Invalid UTF-8: overlong encoding"); - } + if (codepoint < 0x80) + return std::nullopt; i += 2; } else if ((byte & 0xf0) == 0xe0) { // 3-byte character - if (i + 2 >= utf8_str.size()) { - throw std::invalid_argument( - "Invalid UTF-8: incomplete 3-byte sequence"); - } - unsigned char byte2 = static_cast(utf8_str[i + 1]); - unsigned char byte3 = static_cast(utf8_str[i + 2]); - if ((byte2 & 0xc0) != 0x80 || (byte3 & 0xc0) != 0x80) { - throw std::invalid_argument( - "Invalid UTF-8: invalid continuation byte"); - } + if (i + 2 >= utf8_str.size()) + return std::nullopt; + const auto byte2 = static_cast(utf8_str[i + 1]); + const auto byte3 = static_cast(utf8_str[i + 2]); + if ((byte2 & 0xc0) != 0x80 || (byte3 & 0xc0) != 0x80) + return std::nullopt; codepoint = ((byte & 0x0fu) << 12) | ((byte2 & 0x3fu) << 6) | (byte3 & 0x3fu); - if (codepoint < 0x800) { - throw std::invalid_argument("Invalid UTF-8: overlong encoding"); - } + if (codepoint < 0x800) + return std::nullopt; // Check for UTF-16 surrogate range (which is invalid in UTF-8) - if (codepoint >= 0xd800 && codepoint <= 0xdfff) { - throw std::invalid_argument( - "Invalid UTF-8: surrogate codepoint"); - } + if (codepoint >= 0xd800 && codepoint <= 0xdfff) + return std::nullopt; i += 3; } else if ((byte & 0xf8) == 0xf0) { // 4-byte character - if (i + 3 >= utf8_str.size()) { - throw std::invalid_argument( - "Invalid UTF-8: incomplete 4-byte sequence"); - } - unsigned char byte2 = static_cast(utf8_str[i + 1]); - unsigned char byte3 = static_cast(utf8_str[i + 2]); - unsigned char byte4 = static_cast(utf8_str[i + 3]); + if (i + 3 >= utf8_str.size()) + return std::nullopt; + const auto byte2 = static_cast(utf8_str[i + 1]); + const auto byte3 = static_cast(utf8_str[i + 2]); + const auto byte4 = static_cast(utf8_str[i + 3]); if ((byte2 & 0xc0) != 0x80 || (byte3 & 0xc0) != 0x80 || - (byte4 & 0xc0) != 0x80) { - throw std::invalid_argument( - "Invalid UTF-8: invalid continuation byte"); - } + (byte4 & 0xc0) != 0x80) + return std::nullopt; codepoint = ((byte & 0x07u) << 18) | ((byte2 & 0x3fu) << 12) | ((byte3 & 0x3fu) << 6) | (byte4 & 0x3fu); - if (codepoint < 0x10000) { - throw std::invalid_argument("Invalid UTF-8: overlong encoding"); - } - if (codepoint > 0x10ffff) { - throw std::invalid_argument( - "Invalid UTF-8: codepoint too large"); - } + if (codepoint < 0x10000) + return std::nullopt; + if (codepoint > 0x10ffff) + return std::nullopt; i += 4; } else { - throw std::invalid_argument("Invalid UTF-8: invalid start byte"); + return std::nullopt; } // Convert codepoint to UTF-16 @@ -184,9 +164,9 @@ inline std::u16string utf8_to_utf16(const std::string& utf8_str) { } else { // Needs a surrogate pair codepoint -= 0x10000; - char16_t high_surrogate = + const auto high_surrogate = static_cast(0xd800 + (codepoint >> 10)); - char16_t low_surrogate = + const auto low_surrogate = static_cast(0xdc00 + (codepoint & 0x3ff)); utf16_str.push_back(high_surrogate); utf16_str.push_back(low_surrogate); diff --git a/src/common/toml_helper.hpp b/src/common/toml_helper.hpp index d4af7d42..50f10c79 100644 --- a/src/common/toml_helper.hpp +++ b/src/common/toml_helper.hpp @@ -16,7 +16,7 @@ struct from> { \ template \ static std::optional from_toml(const basic_value& v) { \ - const auto str = v.as_string(); \ + const auto& str = v.as_string(); \ FOR_EACH_1_2(TOML11_CONVERSION_TOML_TO_ENUM_CASE, e, __VA_ARGS__) \ return std::nullopt; \ } \ diff --git a/src/common/type_aliases.hpp b/src/common/type_aliases.hpp index 7f6f90e4..6afa97f5 100644 --- a/src/common/type_aliases.hpp +++ b/src/common/type_aliases.hpp @@ -1,21 +1,22 @@ #pragma once #include +#include namespace hydra { -using i8 = int8_t; -using i16 = int16_t; -using i32 = int32_t; -using i64 = int64_t; +using i8 = std::int8_t; +using i16 = std::int16_t; +using i32 = std::int32_t; +using i64 = std::int64_t; using i128 = __int128_t; -using u8 = uint8_t; -using u16 = uint16_t; -using u32 = uint32_t; -using u64 = uint64_t; +using u8 = std::uint8_t; +using u16 = std::uint16_t; +using u32 = std::uint32_t; +using u64 = std::uint64_t; using u128 = __uint128_t; -using usize = size_t; -using uptr = uintptr_t; +using usize = std::size_t; +using uptr = std::uintptr_t; using f32 = float; using f64 = double; diff --git a/src/common/types.hpp b/src/common/types.hpp index 6fd3459d..71c8c176 100644 --- a/src/common/types.hpp +++ b/src/common/types.hpp @@ -31,16 +31,16 @@ using BitField64 = BitField; template class vec { public: - vec() = default; - vec(const T& value) { + constexpr vec() = default; + constexpr vec(const T& value) { for (u32 i = 0; i < component_count; i++) components[i] = value; } - vec(const std::initializer_list& values) { + constexpr vec(const std::initializer_list& values) { std::copy(values.begin(), values.end(), components.begin()); } template - vec(const vec& other) { + constexpr vec(const vec& other) { for (u32 i = 0; i < component_count; i++) components[i] = static_cast(other[i]); } @@ -216,7 +216,7 @@ struct Rect2D { vec origin; vec size; - Rect2D() {} + Rect2D() = default; Rect2D(vec origin_, vec size_) : origin{origin_}, size{size_} {} @@ -230,27 +230,33 @@ using IntRect2D = Rect2D; using UIntRect2D = Rect2D; using FloatRect2D = Rect2D; +// TODO: handle this better +#pragma pack(push, 1) template -class aligned { +class Aligned { public: static_assert(sizeof(T) <= alignment); - aligned() {} - aligned(const T& value_) : value{value_} {} - void operator=(const T& new_value) { value = new_value; } + Aligned() = default; + Aligned(const T& value_) : value{value_} {} + Aligned& operator=(const T& new_value) { + value = new_value; + return *this; + } operator T&() { return value; } operator const T&() const { return value; } - void ZeroOutPadding() { std::memset(_padding, 0, sizeof_array(_padding)); } + void ZeroOutPadding() { std::fill(padding.begin(), padding.end(), 0); } private: T value; - u8 _padding[alignment - sizeof(T)]; + std::array padding; public: CONST_REF_GETTER(value, Get); -} PACKED; +}; +#pragma pack(pop) template class strong_typedef { @@ -258,7 +264,10 @@ class strong_typedef { strong_typedef() : value{} {} strong_typedef(const T& value_) : value{value_} {} - void operator=(const T& new_value) { value = new_value; } + strong_typedef& operator=(const T& new_value) { + value = new_value; + return *this; + } operator T&() { return value; } operator const T&() const { return value; } @@ -285,7 +294,10 @@ class strong_number_typedef { requires std::is_signed_v : value{static_cast(value_)} {} - void operator=(const T& new_value) { value = new_value; } + strong_number_typedef& operator=(const T& new_value) { + value = new_value; + return *this; + } void operator+=(const T& other) { value += other; } void operator-=(const T& other) { value -= other; } void operator*=(const T& other) { value *= other; } @@ -313,7 +325,8 @@ class strong_number_typedef { template class CacheBase { public: - ~CacheBase() { + CacheBase() noexcept = default; + ~CacheBase() noexcept { for (auto& [key, value] : cache) { THIS->DestroyElement(value); } @@ -321,6 +334,8 @@ class CacheBase { THIS->Destroy(); } + MAKE_NON_COPYABLE(CacheBase); + T& Find(const DescriptorT& descriptor) { u32 hash = THIS->Hash(descriptor); auto it = cache.find(hash); @@ -342,7 +357,7 @@ class CacheBase { } // namespace hydra template -struct fmt::formatter> : formatter { +struct fmt::formatter> : formatter { fmt::formatter value_formatter; constexpr auto parse(fmt::format_parse_context& ctx) { @@ -350,7 +365,7 @@ struct fmt::formatter> : formatter { } template - auto format(const hydra::aligned& value, + auto format(const hydra::Aligned& value, FormatContext& ctx) const { return value_formatter.format(value.Get(), ctx); } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 12cf65e9..a2fa3bf6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -67,8 +67,8 @@ add_library(hydra-core horizon/filesystem/romfs/builder.hpp horizon/filesystem/romfs/romfs.cpp horizon/filesystem/romfs/romfs.hpp - horizon/loader/loader_base.cpp - horizon/loader/loader_base.hpp + horizon/loader/loader.cpp + horizon/loader/loader.hpp horizon/loader/nro_loader.cpp horizon/loader/nro_loader.hpp horizon/loader/nso_loader.cpp @@ -661,6 +661,11 @@ add_library(hydra-core title.hpp c_api.cpp c_api.h + stb.cpp +) + +set_source_files_properties(c_api.cpp c_api.h PROPERTIES + SKIP_LINTING ON ) if (HYPERVISOR_ENABLED) @@ -701,9 +706,9 @@ if (SDL_ENABLED) ) endif () -target_include_directories(hydra-core PRIVATE ${CMAKE_SOURCE_DIR}/externals/libyaz0/include) +target_include_directories(hydra-core SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/externals/libyaz0/include) # TODO: only link Apple frameworks if Apple -target_link_libraries(hydra-core PRIVATE hydra_warnings "-framework Foundation" "-framework Metal" "-framework QuartzCore" "-framework GameController" dynarmic hatch libyaz0 nx2elf date::date date::date-tz hydra-common) +target_link_libraries(hydra-core PRIVATE hydra_compile_options "-framework Foundation" "-framework Metal" "-framework QuartzCore" "-framework GameController" dynarmic hatch libyaz0 nx2elf date::date date::date-tz hydra-common) if (HYPERVISOR_ENABLED) target_link_libraries(hydra-core PRIVATE "-framework Hypervisor") diff --git a/src/core/audio/core.hpp b/src/core/audio/core.hpp index e73f3e36..a6cc42da 100644 --- a/src/core/audio/core.hpp +++ b/src/core/audio/core.hpp @@ -6,10 +6,6 @@ namespace hydra::audio { class ICore { public: - enum class Error { - InitializationFailed, - }; - virtual ~ICore() = default; virtual IStream* diff --git a/src/core/audio/cubeb/core.cpp b/src/core/audio/cubeb/core.cpp index 81fe55b9..b3bfe346 100644 --- a/src/core/audio/cubeb/core.cpp +++ b/src/core/audio/cubeb/core.cpp @@ -6,8 +6,8 @@ namespace hydra::audio::cubeb { Core::Core() { const auto res = cubeb_init(&context, "Hydra", nullptr); - ASSERT_THROWING(res == CUBEB_OK, Cubeb, Error::InitializationFailed, - "Failed to initialize cubeb context: {}", res); + ASSERT(res == CUBEB_OK, Cubeb, "Failed to initialize cubeb context: {}", + res); } IStream* diff --git a/src/core/audio/cubeb/stream.cpp b/src/core/audio/cubeb/stream.cpp index 6241ed31..4dc9e61f 100644 --- a/src/core/audio/cubeb/stream.cpp +++ b/src/core/audio/cubeb/stream.cpp @@ -1,5 +1,7 @@ #include "core/audio/cubeb/stream.hpp" +#include + #include "core/audio/cubeb/core.hpp" namespace hydra::audio::cubeb { @@ -29,7 +31,8 @@ cubeb_channel_layout to_cubeb_layout(u16 channel_count) { Stream::Stream(Core& core_, PcmFormat format, u32 sample_rate, u16 channel_count, buffer_finished_callback_fn_t buffer_finished_callback) - : IStream(format, sample_rate, channel_count, buffer_finished_callback), + : IStream(format, sample_rate, channel_count, + std::move(buffer_finished_callback)), core{core_} { // TODO: allow different channel counts if (channel_count != 2) @@ -48,8 +51,8 @@ Stream::Stream(Core& core_, PcmFormat format, u32 sample_rate, core.context, &stream, "Hydra stream", nullptr, nullptr, nullptr, ¶ms, 512, &Stream::DataCallback, &Stream::StateCallback, this); // TODO: format result - ASSERT_THROWING(res == CUBEB_OK, Cubeb, Error::InitializationFailed, - "Failed to initialize cubeb stream: {}", res); + ASSERT(res == CUBEB_OK, Cubeb, "Failed to initialize cubeb stream: {}", + res); } Stream::~Stream() { cubeb_stream_destroy(stream); } @@ -63,7 +66,7 @@ void Stream::Stop() { void Stream::EnqueueBuffer(buffer_id_t id, std::span buffer) { std::unique_lock lock(buffer_mutex); - buffer_queue.push({id, buffer}); + buffer_queue.emplace(id, buffer); } long Stream::DataCallback(cubeb_stream* stream, void* user_data, diff --git a/src/core/audio/null/stream.hpp b/src/core/audio/null/stream.hpp index ab5ff5d1..84f80d73 100644 --- a/src/core/audio/null/stream.hpp +++ b/src/core/audio/null/stream.hpp @@ -9,7 +9,7 @@ class Stream final : public IStream { Stream(PcmFormat format, u32 sample_rate, u16 channel_count, buffer_finished_callback_fn_t buffer_finished_callback) : IStream(format, sample_rate, channel_count, - buffer_finished_callback) {} + std::move(buffer_finished_callback)) {} void Start() override { state = StreamState::Started; } void Stop() override { state = StreamState::Stopped; } diff --git a/src/core/audio/stream.hpp b/src/core/audio/stream.hpp index 4828418a..c948a99d 100644 --- a/src/core/audio/stream.hpp +++ b/src/core/audio/stream.hpp @@ -6,20 +6,16 @@ namespace hydra::audio { using buffer_id_t = u64; -typedef std::function buffer_finished_callback_fn_t; +using buffer_finished_callback_fn_t = std::function; class IStream { public: - enum class Error { - InitializationFailed, - }; - IStream(PcmFormat format_, u32 sample_rate_, u16 channel_count_, buffer_finished_callback_fn_t buffer_finished_callback_) : format{format_}, sample_rate{sample_rate_}, - channel_count{channel_count_}, buffer_finished_callback{ - buffer_finished_callback_} {} - virtual ~IStream() {} + channel_count{channel_count_}, + buffer_finished_callback{std::move(buffer_finished_callback_)} {} + virtual ~IStream() noexcept = default; virtual void Start() = 0; virtual void Stop() = 0; diff --git a/src/core/c_api.cpp b/src/core/c_api.cpp index 2018591d..63c50fd6 100644 --- a/src/core/c_api.cpp +++ b/src/core/c_api.cpp @@ -16,11 +16,11 @@ namespace { hydra_string hydra_string_from_string_view(std::string_view str) { - return hydra_string{str.data(), str.size()}; + return hydra_string{.data = str.data(), .size = str.size()}; } std::string_view string_view_from_hydra_string(hydra_string str) { - return std::string_view(str.data, str.size); + return {str.data, str.size}; } } // namespace @@ -56,8 +56,8 @@ HYDRA_EXPORT void hydra_string_list_set(void* list, uint32_t index, } HYDRA_EXPORT void hydra_string_list_append(void* list, hydra_string value) { - reinterpret_cast*>(list)->push_back( - std::string(string_view_from_hydra_string(value))); + reinterpret_cast*>(list)->emplace_back( + string_view_from_hydra_string(value)); } // String view list @@ -471,67 +471,68 @@ HYDRA_EXPORT hydra_string hydra_time_zone_manager_get_location(void* manager, // Loader HYDRA_EXPORT void* hydra_create_loader_from_path(hydra_string path, void* plugin_manager) { - try { - return hydra::horizon::loader::LoaderBase::CreateFromPath( - string_view_from_hydra_string(path), - reinterpret_cast( - plugin_manager)); - } catch (...) { - // TODO: return an error - return nullptr; - } + // TODO: return the error + return hydra::horizon::loader::ILoader::CreateFromPath( + string_view_from_hydra_string(path), + (plugin_manager != nullptr) + ? std::make_optional( + reinterpret_cast< + hydra::horizon::loader::plugins::Manager*>( + plugin_manager)) + : std::nullopt) + .value_or(nullptr); } HYDRA_EXPORT void hydra_loader_destroy(void* loader) { - delete reinterpret_cast(loader); + delete reinterpret_cast(loader); } HYDRA_EXPORT uint64_t hydra_loader_get_title_id(void* loader) { - return reinterpret_cast(loader) + return reinterpret_cast(loader) ->GetTitleID(); } HYDRA_EXPORT void* hydra_loader_load_nacp(void* loader) { - return reinterpret_cast(loader) + return reinterpret_cast(loader) ->LoadNacp(); } HYDRA_EXPORT void* hydra_loader_load_icon(void* loader, uint32_t* width, uint32_t* height) { - return reinterpret_cast(loader) - ->LoadIcon(*width, *height); + return reinterpret_cast(loader)->LoadIcon( + *width, *height); } HYDRA_EXPORT bool hydra_loader_has_icon(const void* loader) { - return reinterpret_cast(loader) + return reinterpret_cast(loader) ->HasIcon(); } HYDRA_EXPORT void hydra_loader_extract_icon(const void* loader, hydra_string path) { - reinterpret_cast(loader) + reinterpret_cast(loader) ->ExtractIcon(string_view_from_hydra_string(path)); } HYDRA_EXPORT bool hydra_loader_has_exefs(const void* loader) { - return reinterpret_cast(loader) + return reinterpret_cast(loader) ->HasExeFs(); } HYDRA_EXPORT void hydra_loader_extract_exefs(const void* loader, hydra_string path) { - reinterpret_cast(loader) + reinterpret_cast(loader) ->ExtractExeFs(string_view_from_hydra_string(path)); } HYDRA_EXPORT bool hydra_loader_has_romfs(const void* loader) { - return reinterpret_cast(loader) + return reinterpret_cast(loader) ->HasRomFs(); } HYDRA_EXPORT void hydra_loader_extract_romfs(const void* loader, hydra_string path) { - reinterpret_cast(loader) + reinterpret_cast(loader) ->ExtractRomFs(string_view_from_hydra_string(path)); } @@ -566,13 +567,18 @@ HYDRA_EXPORT void hydra_loader_plugin_manager_refresh(void* manager) { // Plugin HYDRA_EXPORT void* hydra_create_loader_plugin(hydra_string path) { - try { - return new hydra::horizon::loader::plugins::Plugin( - std::string(string_view_from_hydra_string(path))); - } catch (...) { - // TODO: return an error - return nullptr; - } + // TODO: return the error + return hydra::horizon::loader::plugins::Plugin::Create( + std::string(string_view_from_hydra_string(path))) + .transform([](hydra::horizon::loader::plugins::Plugin plugin) { + // HACK + auto ptr = + reinterpret_cast( + malloc(sizeof(hydra::horizon::loader::plugins::Plugin))); + *ptr = std::move(plugin); + return ptr; + }) + .value_or(nullptr); } HYDRA_EXPORT void hydra_loader_plugin_destroy(void* plugin) { @@ -820,7 +826,7 @@ HYDRA_EXPORT void hydra_system_set_surface(void* system, void* surface) { HYDRA_EXPORT void hydra_system_load_and_start(void* system, void* loader) { reinterpret_cast(system)->LoadAndStart( - reinterpret_cast(loader)); + reinterpret_cast(loader)); } HYDRA_EXPORT void hydra_system_request_stop(void* system) { diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 8a39176d..d5e14672 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -20,11 +20,11 @@ ResolvedStackFrame StackFrame::Resolve() const { switch (type) { case StackFrameType::Host: // TODO - return {"libhydra.dylib", "", addr}; + return {.module = "libhydra.dylib", .function = "", .addr = addr}; case StackFrameType::Guest: { const auto& module = debugger->GetModuleTable().FindSymbol(addr); const auto& function = debugger->GetFunctionTable().FindSymbol(addr); - return {module, function, addr}; + return {.module = module, .function = function, .addr = addr}; } } } @@ -43,11 +43,6 @@ void Thread::Log(const Message& msg) { msg_tail = (msg_tail + 1) % messages.size(); } -Debugger::~Debugger() { - if (gdb_server) - delete gdb_server; -} - void Debugger::RegisterThisThread(const std::string_view thread_name) { std::unique_lock lock(mutex); ASSERT(threads.try_emplace(std::this_thread::get_id(), thread_name).second, @@ -64,7 +59,7 @@ void Debugger::RegisterGuestThreadForThisThread( GET_THIS_THREAD(); thread.guest_thread = guest_thread; - if (gdb_server) + if (gdb_server.has_value()) gdb_server->RegisterThread(thread); } @@ -74,17 +69,17 @@ void Debugger::UnregisterGuestThreadForThisThread() { } void Debugger::ActivateGdbServer(System& system) { - gdb_server = new GdbServer(system, *this); + gdb_server.emplace(system, *this); } void Debugger::NotifySupervisorPaused(horizon::kernel::GuestThread* thread, Signal signal) { - if (gdb_server) + if (gdb_server.has_value()) gdb_server->NotifySupervisorPaused(thread, signal); } void Debugger::BreakpointHit(horizon::kernel::GuestThread* thread) { - if (gdb_server) + if (gdb_server.has_value()) gdb_server->BreakpointHit(thread); } @@ -93,7 +88,7 @@ void Debugger::LogOnThisThread(const LogMessage& msg) { lock.unlock(); auto stack_trace = GetStackTrace(thread); lock.lock(); - thread.Log({msg, stack_trace}); + thread.Log({.log = msg, .stack_trace = stack_trace}); } void Debugger::BreakOnThisThreadImpl(const std::string_view reason) { diff --git a/src/core/debugger/debugger.hpp b/src/core/debugger/debugger.hpp index 199bcde4..5cdd6af0 100644 --- a/src/core/debugger/debugger.hpp +++ b/src/core/debugger/debugger.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/debugger/const.hpp" +#include "core/debugger/gdb_server.hpp" namespace hydra { class System; @@ -33,7 +33,6 @@ class IFile; namespace hydra::debugger { -class GdbServer; class Debugger; struct ResolvedStackFrame { @@ -138,7 +137,7 @@ class Debugger { public: Debugger(const std::string_view name_, horizon::kernel::Process* process_) : name{name_}, process{process_} {} - ~Debugger(); + ~Debugger() noexcept = default; void RegisterExecutable(const std::string_view exe_name, horizon::filesystem::IFile* executable) { @@ -188,7 +187,7 @@ class Debugger { SymbolTable module_table; SymbolTable function_table; - GdbServer* gdb_server{nullptr}; + std::optional gdb_server; void LogOnThisThread(const LogMessage& msg); void BreakOnThisThreadImpl(const std::string_view reason); diff --git a/src/core/debugger/debugger_manager.cpp b/src/core/debugger/debugger_manager.cpp index 52886190..3c0d409a 100644 --- a/src/core/debugger/debugger_manager.cpp +++ b/src/core/debugger/debugger_manager.cpp @@ -53,7 +53,7 @@ DebuggerManager::GetDebugger(hydra::horizon::kernel::Process* process) { return hydra_debugger; { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); auto it = debuggers.find(process); ASSERT_DEBUG(it != debuggers.end(), Debugger, "Process \"{}\" not found", process->GetDebugName()); @@ -64,7 +64,7 @@ DebuggerManager::GetDebugger(hydra::horizon::kernel::Process* process) { Debugger& DebuggerManager::GetDebuggerForCurrentProcess() { // Get the corresponding process auto process = HYDRA_PROCESS; - if (horizon::kernel::tls_current_thread) + if (horizon::kernel::tls_current_thread != nullptr) process = horizon::kernel::tls_current_thread->GetProcess(); return GetDebugger(process); diff --git a/src/core/debugger/gdb_server.cpp b/src/core/debugger/gdb_server.cpp index 2689c805..126f4c3f 100644 --- a/src/core/debugger/gdb_server.cpp +++ b/src/core/debugger/gdb_server.cpp @@ -6,9 +6,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" - #include - #pragma GCC diagnostic pop #include "core/debugger/debugger_manager.hpp" @@ -250,7 +248,6 @@ GdbServer::GdbServer(System& system_, Debugger& debugger_) addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); - if (bind(server_socket, reinterpret_cast(&addr), sizeof(addr)) == -1) { LOG_ERROR(Debugger, "Failed to bind GDB socket"); @@ -286,13 +283,13 @@ GdbServer::~GdbServer() { void GdbServer::NotifySupervisorPaused(horizon::kernel::GuestThread* thread, Signal signal) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); NotifySupervisorPausedImpl(thread, signal); } void GdbServer::RegisterThread(Thread& thread) { if (system.GetCpu().GetFeatures().supports_native_breakpoints) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); for (const auto addr : breakpoint_addresses) thread.guest_thread->GetThread()->InsertBreakpoint(addr); } @@ -304,7 +301,7 @@ void GdbServer::BreakpointHit(horizon::kernel::GuestThread* thread) { // We got the lock { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); breakpoint_thread = thread; debugger.process->SupervisorPause(); @@ -470,7 +467,7 @@ void GdbServer::HandleVCont(std::string_view command) { } while (pos != std::string::npos); // TODO: how does this work? - if (thread) { + if (thread != nullptr) { // TODO: implement ASSERT_DEBUG(lock_execution, Debugger, "Non-locked execution not implemented"); @@ -533,7 +530,7 @@ void GdbServer::HandleQuery(std::string_view command) { void GdbServer::HandleSetActiveThread(std::string_view command) { const auto thread = GET_THREAD_FROM_ID(std::stoull(command.substr(1).data(), nullptr, 16)); - if (thread) { + if (thread != nullptr) { // TODO: check if thread is valid // if (debugger.threads.contains(thread)) { // crnt_thread = thread; @@ -638,9 +635,9 @@ void GdbServer::HandleRemoveBreakpoint(std::string_view command) { "Invalid software breakpoint size 0x{:x}", size); if (system.GetCpu().GetFeatures().supports_native_breakpoints) { - breakpoint_addresses.erase(std::find(breakpoint_addresses.begin(), - breakpoint_addresses.end(), - addr)); + breakpoint_addresses.erase(std::ranges::find(breakpoint_addresses, + + addr)); for (const auto& [_, thread] : debugger.threads) thread.guest_thread->GetThread()->RemoveBreakpoint(addr); } else { @@ -723,7 +720,7 @@ void GdbServer::HandleGetExecutables() { SendPacket(output); } -void GdbServer::SendPacket(std::string_view data) { +void GdbServer::SendPacket(std::string_view data) const { ASSERT_DEBUG(client_socket != -1, Debugger, "Client socket is not valid"); u8 checksum = 0; @@ -736,7 +733,7 @@ void GdbServer::SendPacket(std::string_view data) { send(client_socket, packet.data(), packet.size(), 0); } -void GdbServer::SendStatus(char status) { +void GdbServer::SendStatus(char status) const { if (!do_ack) return; diff --git a/src/core/debugger/gdb_server.hpp b/src/core/debugger/gdb_server.hpp index 360126f8..3eb0b0ad 100644 --- a/src/core/debugger/gdb_server.hpp +++ b/src/core/debugger/gdb_server.hpp @@ -50,8 +50,8 @@ class GdbServer { void ServerLoop(); void Poll(); - void SendPacket(std::string_view data); - void SendStatus(char status); + void SendPacket(std::string_view data) const; + void SendStatus(char status) const; void ProcessPackets(); void HandleCommand(std::string_view command); @@ -66,15 +66,15 @@ class GdbServer { void HandleInsertBreakpoint(std::string_view command); void HandleRemoveBreakpoint(std::string_view command); - void HandleRcmd(std::string_view command); + void HandleRcmd(std::string_view cmd); void HandleGetExecutables(); // Helpers - void SetNonBlocking(i32 socket); + static void SetNonBlocking(i32 socket); std::string ReadReg(u32 id); - std::string GetThreadStatus(horizon::kernel::GuestThread* thread, + static std::string GetThreadStatus(horizon::kernel::GuestThread* thread, Signal signal); - std::string PageFromBuffer(std::string_view buffer, std::string_view page); + static std::string PageFromBuffer(std::string_view buffer, std::string_view page); void NotifySupervisorPausedImpl(horizon::kernel::GuestThread* thread, Signal signal); diff --git a/src/core/horizon/applets/applet_base.cpp b/src/core/horizon/applets/applet_base.cpp index 0f0f66dc..73c2ef81 100644 --- a/src/core/horizon/applets/applet_base.cpp +++ b/src/core/horizon/applets/applet_base.cpp @@ -16,10 +16,10 @@ void AppletBase::Start(System& system) { // TODO: create process - thread = new std::thread([&]() { + thread.emplace([&]() { GET_CURRENT_PROCESS_DEBUGGER().RegisterThisThread("Applet"); result = Run(system); - controller.GetStateChangedEvent()->Signal(); + controller.GetStateChangedEvent().Signal(); GET_CURRENT_PROCESS_DEBUGGER().UnregisterThisThread(); }); } diff --git a/src/core/horizon/applets/applet_base.hpp b/src/core/horizon/applets/applet_base.hpp index f177eb6c..efa92dc0 100644 --- a/src/core/horizon/applets/applet_base.hpp +++ b/src/core/horizon/applets/applet_base.hpp @@ -9,13 +9,7 @@ class AppletBase { public: AppletBase(services::am::internal::LibraryAppletController& controller_) : controller{controller_} {} - virtual ~AppletBase() { - if (thread) { - // TODO: join? - thread->join(); - delete thread; - } - } + virtual ~AppletBase() noexcept = default; void Start(System& system); @@ -29,7 +23,7 @@ class AppletBase { // Data io::MemoryStream PopInDataRaw() { auto data = controller.PopInData()->GetData(); - return io::MemoryStream(data); + return {data}; } template @@ -41,23 +35,23 @@ class AppletBase { return stream.Read(); } - void PushOutDataRaw(std::span data) { - controller.PushOutData(new services::am::IStorage(data)); + void PushOutDataRaw(std::vector data) { + controller.PushOutData(new services::am::IStorage(std::move(data))); } template void PushOutData(const T& data) { - auto ptr = reinterpret_cast(malloc(sizeof(T))); - memcpy(ptr, &data, sizeof(T)); - PushOutDataRaw(std::span{ptr, sizeof(T)}); + std::vector bytes(sizeof(T)); + std::memcpy(bytes.data(), &data, sizeof(T)); + PushOutDataRaw(std::move(bytes)); } // Interactive data io::MemoryStream PopInteractiveInDataRaw() { // TODO: wait - // controller.GetInteractiveInDataEvent()->Wait(); + // controller.GetInteractiveInDataEvent().Wait(); auto data = controller.PopInteractiveInData()->GetData(); - return io::MemoryStream(data); + return {data}; } template @@ -69,21 +63,22 @@ class AppletBase { return stream.Read(); } - void PushInteractiveOutDataRaw(std::span data) { - controller.PushInteractiveOutData(new services::am::IStorage(data)); + void PushInteractiveOutDataRaw(std::vector data) { + controller.PushInteractiveOutData( + new services::am::IStorage(std::move(data))); } template void PushInteractiveOutData(const T& data) { - auto ptr = reinterpret_cast(malloc(sizeof(T))); - memcpy(ptr, &data, sizeof(T)); - PushInteractiveOutDataRaw(std::span{ptr, sizeof(T)}); + std::vector bytes(sizeof(T)); + std::memcpy(bytes.data(), &data, sizeof(T)); + PushInteractiveOutDataRaw(std::move(bytes)); } private: services::am::internal::LibraryAppletController& controller; - std::thread* thread{nullptr}; + std::optional thread; result_t result{RESULT_SUCCESS}; }; diff --git a/src/core/horizon/applets/software_keyboard/applet.cpp b/src/core/horizon/applets/software_keyboard/applet.cpp index 96c4525a..682247a3 100644 --- a/src/core/horizon/applets/software_keyboard/applet.cpp +++ b/src/core/horizon/applets/software_keyboard/applet.cpp @@ -27,21 +27,27 @@ result_t Applet::Run(System& system) { // Text input std::string output_text_utf8; result = system.GetUIHandler().ShowSoftwareKeyboard( - utf16_to_utf8(std::u16string(config.header_text)), - utf16_to_utf8(std::u16string(config.sub_text)), - utf16_to_utf8(std::u16string(config.guide_text)), output_text_utf8); - output_text = utf8_to_utf16(output_text_utf8); + Utf16ToUtf8(std::u16string(config.header_text)).value_or(""), + Utf16ToUtf8(std::u16string(config.sub_text)).value_or(""), + Utf16ToUtf8(std::u16string(config.guide_text)).value_or(""), + output_text_utf8); + const auto output_text_opt = Utf8ToUtf16(output_text_utf8); + ASSERT(output_text_opt.has_value(), Applets, + "Failed to convert UTF-8 to UTF-16: {}", output_text_utf8); + output_text = output_text_opt.value(); + if (!config.text_check_enabled) break; // Verify - usize size = sizeof(u64) + (output_text.size() + 1) * sizeof(char16_t); - auto ptr = reinterpret_cast(malloc(size)); - io::MemoryStream stream(std::span(ptr, size)); + const usize size = + sizeof(u64) + ((output_text.size() + 1) * sizeof(char16_t)); + std::vector bytes(size); + io::MemoryStream stream(bytes); stream.Write(size); stream.WriteSpan(std::span(output_text)); stream.Write(u'\0'); - PushInteractiveOutDataRaw({ptr, size}); + PushInteractiveOutDataRaw(std::move(bytes)); auto reader = PopInteractiveInDataRaw(); auto res = reader.Read(); @@ -55,19 +61,19 @@ result_t Applet::Run(System& system) { ? ui::MessageDialogType::Error : ui::MessageDialogType::Info), "Text input", // TODO: better text - utf16_to_utf8(msg)); + Utf16ToUtf8(msg).value_or("")); } // Output { - usize size = sizeof(SoftwareKeyboardResult) + - (output_text.size() + 1) * sizeof(char16_t); - auto ptr = reinterpret_cast(std::malloc(size)); - io::MemoryStream stream(std::span(ptr, size)); + const usize size = sizeof(SoftwareKeyboardResult) + + ((output_text.size() + 1) * sizeof(char16_t)); + std::vector bytes(size); + io::MemoryStream stream(bytes); stream.Write(result); stream.WriteSpan(std::span(output_text)); stream.Write(u'\0'); - PushOutDataRaw({ptr, size}); + PushOutDataRaw(std::move(bytes)); } return RESULT_SUCCESS; diff --git a/src/core/horizon/const.hpp b/src/core/horizon/const.hpp index f8e20356..25808e41 100644 --- a/src/core/horizon/const.hpp +++ b/src/core/horizon/const.hpp @@ -91,7 +91,6 @@ inline LanguageCode ToLanguageCode(SystemLanguage lang) { case SystemLanguage::BrazilianPortuguese: return LanguageCode::BrazilianPortuguese; case SystemLanguage::Polish: - return LanguageCode::AmericanEnglish; // No equivalent case SystemLanguage::Thai: return LanguageCode::AmericanEnglish; // No equivalent } diff --git a/src/core/horizon/display/binder.cpp b/src/core/horizon/display/binder.cpp index 039b50bd..9d4d37b7 100644 --- a/src/core/horizon/display/binder.cpp +++ b/src/core/horizon/display/binder.cpp @@ -5,7 +5,7 @@ namespace hydra::horizon::display { void Binder::AddBuffer(i32 slot, const GraphicBuffer& buff) { - std::lock_guard lock(queue_mutex); + std::scoped_lock lock(queue_mutex); buffers[slot].initialized = true; buffers[slot].buffer = buff; buffer_count++; @@ -44,8 +44,8 @@ i32 Binder::GetAvailableSlot() { void Binder::QueueBuffer(System& system, i32 slot, const BqBufferInput& input) { { - std::lock_guard lock(queue_mutex); - queued_buffers.push({slot, input}); + std::scoped_lock lock(queue_mutex); + queued_buffers.emplace(slot, input); buffers[slot].queued = true; } @@ -65,7 +65,7 @@ i32 Binder::ConsumeBuffer(BqBufferInput& out_input) { i32 slot; { // Wait for a buffer to become available - std::lock_guard lock(queue_mutex); + std::scoped_lock lock(queue_mutex); // TODO: should we wait? // queue_cv.wait_for(lock, std::chrono::milliseconds(67), // [&] { return !queued_buffers.empty(); }); @@ -93,7 +93,7 @@ i32 Binder::ConsumeBuffer(BqBufferInput& out_input) { void Binder::UnqueueAllBuffers() { { // Wait for a buffer to become available - std::lock_guard lock(queue_mutex); + std::scoped_lock lock(queue_mutex); // Unqueue all while (!queued_buffers.empty()) { diff --git a/src/core/horizon/display/binder.hpp b/src/core/horizon/display/binder.hpp index 866cd86c..28073628 100644 --- a/src/core/horizon/display/binder.hpp +++ b/src/core/horizon/display/binder.hpp @@ -34,12 +34,13 @@ struct Buffer { struct NvFence { u32 id; u32 value; -} PACKED; +}; +#pragma pack(push, 1) struct NvMultiFence { u32 num_fences; NvFence fences[4]; -} PACKED; +}; enum class TransformFlags : u32 { None = 0, @@ -67,14 +68,15 @@ struct BqBufferInput { u32 _unknown; u32 swap_interval; // TODO: float? NvMultiFence fence; -} PACKED; +}; struct BqBufferOutput { u32 width; u32 height; u32 transform_hint; u32 num_pending_buffers; -} PACKED; +}; +#pragma pack(pop) constexpr usize MAX_BINDER_BUFFER_COUNT = 8; // TODO: what should this be? @@ -85,9 +87,9 @@ struct AccumulatedTime { explicit operator bool() const { return sample_count != 0; } explicit operator f32() const { - return f32(std::chrono::duration_cast>(value) + return static_cast(std::chrono::duration_cast>(value) .count()) / - f32(sample_count); + static_cast(sample_count); } AccumulatedTime& operator+=(const std::chrono::nanoseconds other) { @@ -121,7 +123,7 @@ struct Binder { void UnqueueAllBuffers(); const GraphicBuffer& GetBuffer(i32 slot) { - std::lock_guard lock(queue_mutex); + std::scoped_lock lock(queue_mutex); return buffers[slot].buffer; } diff --git a/src/core/horizon/display/driver.cpp b/src/core/horizon/display/driver.cpp index f8dc0568..67b13c4f 100644 --- a/src/core/horizon/display/driver.cpp +++ b/src/core/horizon/display/driver.cpp @@ -5,14 +5,14 @@ namespace hydra::horizon::display { Driver::Driver(System& system_) : system{system_} { - display_pool.Add(new Display()); + display_pool.Insert(new Display()); } bool Driver::AcquirePresentTextures( hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer) { bool acquired = false; { - std::lock_guard lock(layer_mutex); + std::scoped_lock lock(layer_mutex); for (u32 layer_id = 1; layer_id < layer_pool.GetCapacity() + 1; layer_id++) { if (!layer_pool.IsValid(layer_id)) @@ -29,7 +29,7 @@ void Driver::Present( hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer, hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor, u32 width, u32 height) { - std::lock_guard lock(layer_mutex); + std::scoped_lock lock(layer_mutex); std::vector sorted_layers; for (u32 layer_id = 1; layer_id < layer_pool.GetCapacity() + 1; layer_id++) { @@ -78,7 +78,7 @@ void Driver::Present( void Driver::SignalVSync() { // NOTE: we signal all displays at once for simplicity - std::lock_guard lock(display_mutex); + std::scoped_lock lock(display_mutex); for (u32 display_id = 1; display_id < layer_pool.GetCapacity() + 1; display_id++) { if (!display_pool.IsValid(display_id)) @@ -88,7 +88,7 @@ void Driver::SignalVSync() { } Layer* Driver::GetFirstLayerForProcess(kernel::Process* process) { - std::lock_guard lock(layer_mutex); + std::scoped_lock lock(layer_mutex); for (u32 layer_id = 1; layer_id < layer_pool.GetCapacity() + 1; layer_id++) { if (!layer_pool.IsValid(layer_id)) diff --git a/src/core/horizon/display/driver.hpp b/src/core/horizon/display/driver.hpp index 36c1c9d8..26ad5dde 100644 --- a/src/core/horizon/display/driver.hpp +++ b/src/core/horizon/display/driver.hpp @@ -11,11 +11,12 @@ class Driver { // Displays Display& GetDisplay(handle_id_t id) { - std::lock_guard lock(display_mutex); + std::scoped_lock lock(display_mutex); return *display_pool.Get(id); } handle_id_t GetDisplayIDFromName(const std::string& name) { + (void)this; LOG_NOT_IMPLEMENTED(Horizon, "GetDisplayIDFromName (name: {})", name); // HACK @@ -28,35 +29,35 @@ class Driver { // Layers u32 CreateLayer(kernel::Process* process, u32 binder_id) { - std::lock_guard lock(layer_mutex); - return layer_pool.Add(new Layer(system, process, binder_id)); + std::scoped_lock lock(layer_mutex); + return layer_pool.Insert(new Layer(system, process, binder_id)); } void DestroyLayer(u32 id) { - std::lock_guard lock(layer_mutex); + std::scoped_lock lock(layer_mutex); delete layer_pool.Get(id); layer_pool.Free(id); } Layer& GetLayer(u32 id) { - std::lock_guard lock(layer_mutex); + std::scoped_lock lock(layer_mutex); return *layer_pool.Get(id); } // Binders u32 CreateBinder() { - std::lock_guard lock(binder_mutex); - return binder_pool.Add(new Binder()); + std::scoped_lock lock(binder_mutex); + return binder_pool.Insert(new Binder()); } void DestroyBinder(u32 id) { - std::lock_guard lock(binder_mutex); + std::scoped_lock lock(binder_mutex); delete binder_pool.Get(id); binder_pool.Free(id); } Binder& GetBinder(u32 id) { - std::lock_guard lock(binder_mutex); + std::scoped_lock lock(binder_mutex); return *binder_pool.Get(id); } diff --git a/src/core/horizon/display/layer.cpp b/src/core/horizon/display/layer.cpp index 745980d3..ba22cfaf 100644 --- a/src/core/horizon/display/layer.cpp +++ b/src/core/horizon/display/layer.cpp @@ -35,13 +35,13 @@ bool Layer::AcquirePresentTexture( // HACK if (src_rect.size.x() == 0) { - src_rect.size.x() = - static_cast(present_texture->GetBase()->GetDescriptor().width); + src_rect.size.x() = static_cast( + present_texture.value()->GetBase()->GetDescriptor().width); ONCE(LOG_WARN(Other, "Invalid src width")); } if (src_rect.size.y() == 0) { src_rect.size.y() = static_cast( - present_texture->GetBase()->GetDescriptor().height); + present_texture.value()->GetBase()->GetDescriptor().height); ONCE(LOG_WARN(Other, "Invalid src height")); } @@ -64,15 +64,14 @@ bool Layer::AcquirePresentTexture( void Layer::Present(hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer, hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor, FloatRect2D dst_rect, f32 dst_scale, bool transparent) { - if (!present_texture) - return; + ASSIGN_OR_RETURN(auto present_tex, present_texture); // Size if (size != LAYER_SIZE_AUTO) dst_rect.size = float2(size) * dst_scale; // Draw - compositor->DrawTexture(command_buffer, present_texture, src_rect, dst_rect, + compositor->DrawTexture(command_buffer, present_tex, src_rect, dst_rect, transparent); } diff --git a/src/core/horizon/display/layer.hpp b/src/core/horizon/display/layer.hpp index 92c4e62c..2d02cb23 100644 --- a/src/core/horizon/display/layer.hpp +++ b/src/core/horizon/display/layer.hpp @@ -12,8 +12,7 @@ namespace hydra::horizon::display { class Driver; -#define LAYER_SIZE_AUTO \ - uint2 { 0, 0 } +#define LAYER_SIZE_AUTO uint2{0, 0} class Layer { public: @@ -43,7 +42,7 @@ class Layer { i64 z{0}; // Present - hw::tegra_x1::gpu::renderer::ITextureView* present_texture{nullptr}; + std::optional present_texture; IntRect2D src_rect; public: diff --git a/src/core/horizon/filesystem/content_archive.cpp b/src/core/horizon/filesystem/content_archive.cpp index c1b761b8..1a26d6af 100644 --- a/src/core/horizon/filesystem/content_archive.cpp +++ b/src/core/horizon/filesystem/content_archive.cpp @@ -120,22 +120,22 @@ enum class KeyAreaEncryptionKeyIndex : u8 { enum class KeyGeneration : u8 { _3_0_1 = 3, - _4_0_0, - _5_0_0, - _6_0_0, - _6_2_0, - _7_0_0, - _8_1_0, - _9_0_0, - _9_1_0, - _12_1_0, - _13_0_0, - _14_0_0, - _15_0_0, - _16_0_0, - _17_0_0, - _18_0_0, - _19_0_0, + _4_0_0 = 4, + _5_0_0 = 5, + _6_0_0 = 6, + _6_2_0 = 7, + _7_0_0 = 8, + _8_1_0 = 9, + _9_0_0 = 10, + _9_1_0 = 11, + _12_1_0 = 12, + _13_0_0 = 13, + _14_0_0 = 14, + _15_0_0 = 15, + _16_0_0 = 16, + _17_0_0 = 17, + _18_0_0 = 18, + _19_0_0 = 19, Invalid = 0xff, }; @@ -205,9 +205,8 @@ ContentArchive::ContentArchive(IFile* file) { // Header const auto header = stream->Read
(); // TODO: allow other NCA versions as well - ASSERT_THROWING(header.magic == make_magic4('N', 'C', 'A', '3'), Filesystem, - Error::InvalidMagic, "Invalid NCA magic 0x{:08x}", - header.magic); + ASSERT(header.magic == make_magic4('N', 'C', 'A', '3'), Filesystem, + "Invalid NCA magic 0x{:08x}", header.magic); content_type = header.content_type; title_id = header.program_id; @@ -234,10 +233,9 @@ ContentArchive::ContentArchive(IFile* file) { switch (type) { case SectionType::Code: case SectionType::Logo: { - ASSERT_THROWING( - fs_header.hash_type == HashType::HierarchicalSha256Hash, - Filesystem, Error::UnsupportedHashType, - "Invalid hash type \"{}\" for PFS0", fs_header.hash_type); + ASSERT(fs_header.hash_type == HashType::HierarchicalSha256Hash, + Filesystem, "Invalid hash type \"{}\" for PFS0", + fs_header.hash_type); const auto& layer_region = fs_header.hierarchical_sha_256_data.pfs0_region; diff --git a/src/core/horizon/filesystem/content_archive.hpp b/src/core/horizon/filesystem/content_archive.hpp index 4da24e02..fd1ba7b8 100644 --- a/src/core/horizon/filesystem/content_archive.hpp +++ b/src/core/horizon/filesystem/content_archive.hpp @@ -16,11 +16,6 @@ enum class ContentArchiveContentType : u8 { class ContentArchive final : public Directory { public: - enum class Error { - InvalidMagic, - UnsupportedHashType, - }; - ContentArchive(IFile* file); private: diff --git a/src/core/horizon/filesystem/directory.cpp b/src/core/horizon/filesystem/directory.cpp index 438a240b..d1fd407a 100644 --- a/src/core/horizon/filesystem/directory.cpp +++ b/src/core/horizon/filesystem/directory.cpp @@ -9,14 +9,13 @@ namespace hydra::horizon::filesystem { Directory::Directory(const std::string_view host_path) { - ASSERT_THROWING(std::filesystem::is_directory(host_path), Filesystem, - InitError::NotADirectory, "\"{}\" is not a directory", - host_path); + ASSERT(std::filesystem::is_directory(host_path), Filesystem, + "\"{}\" is not a directory", host_path); for (const auto& entry : std::filesystem::directory_iterator(host_path)) { const auto& entry_path = entry.path().string(); const auto entry_name = - entry_path.substr(entry_path.find_last_of("/") + 1); + entry_path.substr(entry_path.find_last_of('/') + 1); // Ignore certain entries if (entry_name == ".DS_Store") @@ -37,7 +36,7 @@ Directory::~Directory() { void Directory::Save(std::string_view host_path) const { std::filesystem::create_directories(host_path); for (const auto& entry : entries) { - if (!entry.second) + if (entry.second == nullptr) continue; entry.second->Save(fmt::format("{}/{}", host_path, entry.first)); @@ -47,25 +46,23 @@ void Directory::Save(std::string_view host_path) const { FsResult Directory::Delete(bool recursive) { if (!recursive) { for (const auto& entry : entries) { - if (entry.second && entry.second->IsDirectory()) + if ((entry.second != nullptr) && entry.second->IsDirectory()) return FsResult::DirectoryNotEmpty; } } for (const auto& entry : entries) { - if (!entry.second) + if (entry.second == nullptr) continue; if (entry.second->IsDirectory()) { - auto dir = dynamic_cast(entry.second); - ASSERT_DEBUG(dir, Filesystem, "This should not happen"); + auto dir = static_cast(entry.second); const auto res = dir->Delete(true); if (res != FsResult::Success) return res; delete dir; } else { - auto file = dynamic_cast(entry.second); - ASSERT_DEBUG(file, Filesystem, "This should not happen"); + auto file = static_cast(entry.second); const auto res = file->Delete(); if (res != FsResult::Success) return res; @@ -133,9 +130,9 @@ FsResult Directory::GetFile(const std::string_view path, if (res != FsResult::Success) return res; - out_file = dynamic_cast(entry); - if (!out_file) + if (!entry->IsFile()) return FsResult::NotAFile; + out_file = static_cast(entry); return FsResult::Success; } @@ -147,9 +144,9 @@ FsResult Directory::GetDirectory(const std::string_view path, if (res != FsResult::Success) return res; - out_directory = dynamic_cast(entry); - if (!out_directory) + if (!entry->IsDirectory()) return FsResult::NotADirectory; + out_directory = static_cast(entry); return FsResult::Success; } @@ -159,14 +156,14 @@ FsResult Directory::AddEntryImpl(const std::span path, const auto entry_name = path[0]; auto& e = entries[std::string(entry_name)]; if (path.size() == 1) { - if (e) + if (e != nullptr) return FsResult::AlreadyExists; entry->SetParent(this); e = entry; return FsResult::Success; } else { - if (!e) { + if (e == nullptr) { if (add_intermediate) { e = new Directory(); e->SetParent(this); @@ -175,9 +172,9 @@ FsResult Directory::AddEntryImpl(const std::span path, } } - auto sub_dir = dynamic_cast(e); - if (!sub_dir) + if (!e->IsDirectory()) return FsResult::NotADirectory; + auto sub_dir = static_cast(e); return sub_dir->AddEntryImpl(path.subspan(1), entry, add_intermediate); } @@ -203,9 +200,9 @@ FsResult Directory::DeleteEntryImpl(const std::span path, if (it == entries.end()) return FsResult::DoesNotExist; - auto sub_dir = dynamic_cast(it->second); - if (!sub_dir) + if (!it->second->IsDirectory()) return FsResult::NotADirectory; + auto sub_dir = static_cast(it->second); return sub_dir->DeleteEntryImpl(path.subspan(1), recursive); } @@ -225,16 +222,16 @@ FsResult Directory::GetEntryImpl(const std::span path, if (it == entries.end()) return FsResult::DoesNotExist; - auto sub_dir = dynamic_cast(it->second); - if (!sub_dir) + if (!it->second->IsDirectory()) return FsResult::NotADirectory; + auto sub_dir = static_cast(it->second); return sub_dir->GetEntryImpl(path.subspan(1), out_entry); } } void Directory::BreakPath(std::string_view path, - std::vector& out_path) const { + std::vector& out_path) { // Reserve the maximum possible count out_path.reserve( static_cast(std::count(path.begin(), path.end(), '/'))); diff --git a/src/core/horizon/filesystem/directory.hpp b/src/core/horizon/filesystem/directory.hpp index 949aae15..bdec3a68 100644 --- a/src/core/horizon/filesystem/directory.hpp +++ b/src/core/horizon/filesystem/directory.hpp @@ -8,10 +8,6 @@ class IFile; class Directory : public IEntry { public: - enum class InitError { - NotADirectory, - }; - Directory() = default; Directory(const std::string_view host_path); ~Directory() override; @@ -55,8 +51,8 @@ class Directory : public IEntry { IEntry*& out_entry) const; // Helpers - void BreakPath(std::string_view path, - std::vector& out_path) const; + static void BreakPath(std::string_view path, + std::vector& out_path) ; }; } // namespace hydra::horizon::filesystem diff --git a/src/core/horizon/filesystem/disk_file.cpp b/src/core/horizon/filesystem/disk_file.cpp index d72f5ee8..5d110f1b 100644 --- a/src/core/horizon/filesystem/disk_file.cpp +++ b/src/core/horizon/filesystem/disk_file.cpp @@ -7,9 +7,8 @@ DiskFile::DiskFile(const std::string_view path_, bool is_mutable_) if (std::filesystem::exists(path)) { // size = std::filesystem::file_size(host_path); } else { - ASSERT_THROWING(is_mutable, Filesystem, - InitError::ImmutableFileDoesNotExist, - "Immutable file \"{}\" does not exist", path); + ASSERT(is_mutable, Filesystem, "Immutable file \"{}\" does not exist", + path); // Intermediate directories std::filesystem::create_directories( diff --git a/src/core/horizon/filesystem/disk_file.hpp b/src/core/horizon/filesystem/disk_file.hpp index 4679d9d5..43414c6d 100644 --- a/src/core/horizon/filesystem/disk_file.hpp +++ b/src/core/horizon/filesystem/disk_file.hpp @@ -31,10 +31,6 @@ class DiskStream : public io::IostreamStream { class DiskFile : public IFile { public: - enum class InitError { - ImmutableFileDoesNotExist, - }; - DiskFile(const std::string_view path_, bool is_mutable_ = false); ~DiskFile() override; diff --git a/src/core/horizon/filesystem/file_view.hpp b/src/core/horizon/filesystem/file_view.hpp index 8684a80f..0f7e63f8 100644 --- a/src/core/horizon/filesystem/file_view.hpp +++ b/src/core/horizon/filesystem/file_view.hpp @@ -6,20 +6,16 @@ namespace hydra::horizon::filesystem { class FileView : public IFile { public: - enum class InitError { - SizeTooLarge, - }; - FileView(IFile* base_, u64 offset_, u64 size_ = invalid()) : base{base_}, offset{offset_}, size{size_} { - if (size == invalid()) + if (size == invalid()) { size = base->GetSize() - offset; - else - ASSERT_THROWING(size <= base->GetSize() - offset, Filesystem, - InitError::SizeTooLarge, - "File view size (0x{:08x}) is too large " - "(max size: 0x{:08x})", - size, base->GetSize() - offset); + } else { + ASSERT(size <= base->GetSize() - offset, Filesystem, + "File view size (0x{:08x}) is too large " + "(max size: 0x{:08x})", + size, base->GetSize() - offset); + } } io::IStream* Open(FileOpenFlags flags) override { diff --git a/src/core/horizon/filesystem/filesystem.cpp b/src/core/horizon/filesystem/filesystem.cpp index e0b4e2e6..4024a427 100644 --- a/src/core/horizon/filesystem/filesystem.cpp +++ b/src/core/horizon/filesystem/filesystem.cpp @@ -24,8 +24,8 @@ auto& device = it->second; #define VERIFY_MOUNT(mount) \ - ASSERT(mount.find("/") == std::string::npos, Filesystem, \ - "Invalid mount point \"{}\"", mount); + ASSERT(!mount.contains('/'), Filesystem, "Invalid mount point \"{}\"", \ + mount); namespace hydra::horizon::filesystem { @@ -130,7 +130,7 @@ FsResult Filesystem::GetDirectory(const std::string_view path, void Filesystem::MountImpl(const std::string_view mount, Directory* root) { VERIFY_MOUNT(mount); - devices.emplace(std::make_pair(mount, root)); + devices.emplace(mount, root); LOG_INFO(Filesystem, "Mounted \"{}\"", mount); } diff --git a/src/core/horizon/filesystem/memory_file.hpp b/src/core/horizon/filesystem/memory_file.hpp index 0dc1578e..a2bbb15d 100644 --- a/src/core/horizon/filesystem/memory_file.hpp +++ b/src/core/horizon/filesystem/memory_file.hpp @@ -6,7 +6,7 @@ namespace hydra::horizon::filesystem { class MemoryFile : public IFile { public: - MemoryFile(const std::vector& data_) : data{std::move(data_)} {} + MemoryFile(std::vector data_) : data{std::move(data_)} {} MemoryFile(u64 size) : data(size) {} void Resize(u64 new_size) override { data.resize(new_size); } diff --git a/src/core/horizon/filesystem/partition_filesystem.hpp b/src/core/horizon/filesystem/partition_filesystem.hpp index 6843f114..504c7da9 100644 --- a/src/core/horizon/filesystem/partition_filesystem.hpp +++ b/src/core/horizon/filesystem/partition_filesystem.hpp @@ -21,7 +21,7 @@ struct HfsEntry { u32 string_offset; u32 hashed_region_size; u64 _reserved_x18; - u8 hash[0x20]; + std::array hash; }; struct PfsHeader { @@ -35,10 +35,6 @@ struct PfsHeader { class PartitionFilesystem final : public Directory { public: - enum class Error { - InvalidMagic, - }; - // HACK: need to use a method instead of a constructor, since we have a // template parameter template @@ -48,20 +44,18 @@ class PartitionFilesystem final : public Directory { // Header const auto header = stream->Read(); if (!is_hfs) { - ASSERT_THROWING(header.magic == make_magic4('P', 'F', 'S', '0'), - Filesystem, Error::InvalidMagic, - "Invalid PFS0 magic 0x{:08x}", header.magic); + ASSERT(header.magic == make_magic4('P', 'F', 'S', '0'), Filesystem, + "Invalid PFS0 magic 0x{:08x}", header.magic); } else { - ASSERT_THROWING(header.magic == make_magic4('H', 'F', 'S', '0'), - Filesystem, Error::InvalidMagic, - "Invalid HFS0 magic 0x{:08x}", header.magic); + ASSERT(header.magic == make_magic4('H', 'F', 'S', '0'), Filesystem, + "Invalid HFS0 magic 0x{:08x}", header.magic); } using EntryType = std::conditional_t; const u64 entries_offset = sizeof(PfsHeader); const u64 string_table_offset = - entries_offset + sizeof(EntryType) * header.entry_count; + entries_offset + (sizeof(EntryType) * header.entry_count); const u64 data_offset = string_table_offset + header.string_table_size; // String table diff --git a/src/core/horizon/filesystem/romfs/builder.cpp b/src/core/horizon/filesystem/romfs/builder.cpp index 24227bb4..d640eece 100644 --- a/src/core/horizon/filesystem/romfs/builder.cpp +++ b/src/core/horizon/filesystem/romfs/builder.cpp @@ -1,6 +1,7 @@ #include "core/horizon/filesystem/romfs/builder.hpp" #include +#include #include "core/horizon/filesystem/file_view.hpp" #include "core/horizon/filesystem/memory_file.hpp" @@ -62,7 +63,7 @@ u64 Builder::CalcHashTableSize(u64 entries) { } void Builder::VisitDirectory(Directory* dir, - std::shared_ptr parent) { + const std::shared_ptr& parent) { for (const auto& [name, entry] : dir->GetEntries()) { if (entry->IsDirectory()) { auto ctx = std::make_shared(); @@ -107,10 +108,10 @@ std::vector Builder::Build() { VisitDirectory(root_dir, root); - std::sort(directories.begin(), directories.end(), - [](auto& a, auto& b) { return a->path < b->path; }); - std::sort(files.begin(), files.end(), - [](auto& a, auto& b) { return a->path < b->path; }); + std::ranges::sort(directories, + [](auto& a, auto& b) { return a->path < b->path; }); + std::ranges::sort(files, + [](auto& a, auto& b) { return a->path < b->path; }); // Assign file offsets u32 entry_offset = 0; @@ -123,8 +124,7 @@ std::vector Builder::Build() { sizeof(FileEntry) + align(file->path_len - file->name_offset, 4u); } // Assign deferred parent/sibling ownership - for (auto it = files.rbegin(); it != files.rend(); ++it) { - auto& cur_file = *it; + for (auto& cur_file : std::views::reverse(files)) { cur_file->sibling = cur_file->parent->file; cur_file->parent->file = cur_file; } @@ -166,23 +166,26 @@ std::vector Builder::Build() { Header header{}; header.header_size = sizeof(Header); header.data_offset = DATA_OFFSET; - header.directory_hash = {align(header.data_offset + data_size, 4ull), - dir_hash_table_size}; - header.directory_meta = {header.directory_hash.offset + - header.directory_hash.size, - dir_table_size}; - header.file_hash = {header.directory_meta.offset + - header.directory_meta.size, - file_hash_table_size}; - header.file_meta = {header.file_hash.offset + header.file_hash.size, - file_table_size}; + header.directory_hash = {.offset = + align(header.data_offset + data_size, 4ull), + .size = dir_hash_table_size}; + header.directory_meta = {.offset = header.directory_hash.offset + + header.directory_hash.size, + .size = dir_table_size}; + header.file_hash = {.offset = header.directory_meta.offset + + header.directory_meta.size, + .size = file_hash_table_size}; + header.file_meta = {.offset = + header.file_hash.offset + header.file_hash.size, + .size = file_table_size}; std::vector out; // Header output - out.push_back({0, new MemoryFile(std::vector( - reinterpret_cast(&header), - reinterpret_cast(&header) + sizeof(Header)))}); + out.push_back({.offset = 0, + .file = new MemoryFile(std::vector( + reinterpret_cast(&header), + reinterpret_cast(&header) + sizeof(Header)))}); // Populate file table for (const auto& file : files) { @@ -211,7 +214,8 @@ std::vector Builder::Build() { file->path.data() + file->name_offset, name_len); // Emit file data - out.push_back({DATA_OFFSET + file->offset, file->source}); + out.push_back( + {.offset = DATA_OFFSET + file->offset, .file = file->source}); } // Populate directory table @@ -243,8 +247,8 @@ std::vector Builder::Build() { } // Metadata output - out.push_back( - {header.directory_hash.offset, new MemoryFile(std::move(metadata))}); + out.push_back({.offset = header.directory_hash.offset, + .file = new MemoryFile(std::move(metadata))}); return out; } diff --git a/src/core/horizon/filesystem/romfs/builder.hpp b/src/core/horizon/filesystem/romfs/builder.hpp index a8eec090..57b91a2a 100644 --- a/src/core/horizon/filesystem/romfs/builder.hpp +++ b/src/core/horizon/filesystem/romfs/builder.hpp @@ -27,7 +27,7 @@ class Builder { u64 dir_hash_table_size = 0; u64 file_hash_table_size = 0; - void VisitDirectory(Directory* dir, std::shared_ptr parent); + void VisitDirectory(Directory* dir, const std::shared_ptr& parent); void AddDirectory(std::shared_ptr ctx); void AddFile(std::shared_ptr ctx); diff --git a/src/core/horizon/filesystem/romfs/romfs.cpp b/src/core/horizon/filesystem/romfs/romfs.cpp index afea6b6a..7d451fc8 100644 --- a/src/core/horizon/filesystem/romfs/romfs.cpp +++ b/src/core/horizon/filesystem/romfs/romfs.cpp @@ -12,9 +12,8 @@ RomFS::RomFS(IFile* file) { // Header const auto header = stream->Read
(); - ASSERT_THROWING(header.header_size == sizeof(Header), Filesystem, - Error::InvalidHeaderSize, - "Invalid romFS header size 0x{:x}", header.header_size); + ASSERT(header.header_size == sizeof(Header), Filesystem, + "Invalid romFS header size 0x{:x}", header.header_size); // Content Parser parser(stream, new FileView(file, header.data_offset), @@ -30,8 +29,8 @@ RomFS::RomFS(IFile* file) { ASSERT(res == FsResult::Success, Filesystem, "Failed to get root romFS directory: {}", res); - auto root_dir = dynamic_cast(root); - ASSERT(root_dir != nullptr, Filesystem, "Root entry is not a directory"); + ASSERT(root->IsDirectory(), Filesystem, "Root entry is not a directory"); + auto root_dir = static_cast(root); for (const auto& [name, entry] : root_dir->GetEntries()) { res = AddEntry(name, entry); @@ -56,7 +55,7 @@ SparseFile* RomFS::Build() { u64 size = 0; for (const auto& chunk : chunks) size = std::max(size, chunk.offset + chunk.file->GetSize()); - SparseFile* file = new SparseFile(chunks, size); + auto file = new SparseFile(chunks, size); return file; } diff --git a/src/core/horizon/filesystem/romfs/romfs.hpp b/src/core/horizon/filesystem/romfs/romfs.hpp index 49af7224..708311d6 100644 --- a/src/core/horizon/filesystem/romfs/romfs.hpp +++ b/src/core/horizon/filesystem/romfs/romfs.hpp @@ -7,13 +7,9 @@ namespace hydra::horizon::filesystem::romfs { class RomFS final : public Directory { public: - enum class Error { - InvalidHeaderSize, - }; - RomFS(IFile* file); RomFS(const Directory& dir); - ~RomFS() override {} + ~RomFS() override = default; SparseFile* Build(); }; diff --git a/src/core/horizon/filesystem/sparse_file.hpp b/src/core/horizon/filesystem/sparse_file.hpp index 19b896df..d2fe1c04 100644 --- a/src/core/horizon/filesystem/sparse_file.hpp +++ b/src/core/horizon/filesystem/sparse_file.hpp @@ -14,10 +14,10 @@ class SparseFile : public IFile { SparseFile(std::span entries_, u64 size_) : size{size_} { // Sort the entries by offset entries.assign(entries_.begin(), entries_.end()); - std::sort(entries.begin(), entries.end(), - [](const SparseFileEntry& a, const SparseFileEntry& b) { - return a.offset < b.offset; - }); + std::ranges::sort( + entries, [](const SparseFileEntry& a, const SparseFileEntry& b) { + return a.offset < b.offset; + }); // TODO: revisit this idea /* @@ -81,12 +81,13 @@ class SparseFile : public IFile { } io::IStream* Open(FileOpenFlags flags) override { - std::vector streams; + std::vector streams; streams.reserve(entries.size()); for (const auto& entry : entries) { streams.push_back( - {Range(entry.offset, entry.offset + entry.file->GetSize()), - entry.file->Open(flags)}); + {.range = + Range(entry.offset, entry.offset + entry.file->GetSize()), + .stream = entry.file->Open(flags)}); } return new io::OwnedSparseStream(std::move(streams), size); diff --git a/src/core/horizon/kernel/applet_resource.hpp b/src/core/horizon/kernel/applet_resource.hpp index e11fd003..3938dc08 100644 --- a/src/core/horizon/kernel/applet_resource.hpp +++ b/src/core/horizon/kernel/applet_resource.hpp @@ -11,81 +11,68 @@ using AppletResourceUserId = u64; constexpr AppletResourceUserId ARUID_BEGIN = 0xa000000000000000ull; constexpr usize MAX_APPLET_RESOURCES = 0x20; -enum class ToAruidError { - InvalidIndex, -}; inline AppletResourceUserId ToAruid(usize index) { - ASSERT_THROWING_DEBUG(index < MAX_APPLET_RESOURCES, Kernel, - ToAruidError::InvalidIndex, "Invalid index {:#x}", - index); + ASSERT_DEBUG(index < MAX_APPLET_RESOURCES, Kernel, "Invalid index {:#x}", + index); return ARUID_BEGIN + index; } -enum class ToIndexError { - InvalidAruid, -}; inline usize ToIndex(AppletResourceUserId aruid) { - ASSERT_THROWING_DEBUG( - aruid >= ARUID_BEGIN && aruid < ARUID_BEGIN + MAX_APPLET_RESOURCES, - Kernel, ToIndexError::InvalidAruid, "Invalid aruid {:#x}", aruid); + ASSERT_DEBUG(aruid >= ARUID_BEGIN && + aruid < ARUID_BEGIN + MAX_APPLET_RESOURCES, + Kernel, "Invalid aruid {:#x}", aruid); return aruid - ARUID_BEGIN; } template class AppletResourcePool { - typedef std::array, MAX_APPLET_RESOURCES> ResourceArray; + using ResourceArray = std::array, MAX_APPLET_RESOURCES>; public: - enum class Error { - InvalidAruid, - AruidAlreadyTaken, - }; - AppletResourcePool(System& system_) : system{system_} {} - typename ResourceArray::iterator begin() { return resources.begin(); } + ResourceArray::iterator begin() { return resources.begin(); } - typename ResourceArray::const_iterator begin() const { + ResourceArray::const_iterator begin() const { return resources.begin(); } - typename ResourceArray::const_iterator cbegin() const { return begin(); } + ResourceArray::const_iterator cbegin() const { return begin(); } - typename ResourceArray::iterator end() { return resources.end(); } + ResourceArray::iterator end() { return resources.end(); } - typename ResourceArray::const_iterator end() const { + ResourceArray::const_iterator end() const { return resources.end(); } - typename ResourceArray::const_iterator cend() const { return end(); } + ResourceArray::const_iterator cend() const { return end(); } T& CreateResource(kernel::AppletResourceUserId aruid) { auto& resource = GetResourceOpt(aruid); - ASSERT_THROWING_DEBUG(!resource.has_value(), Kernel, - Error::AruidAlreadyTaken, - "Aruid {:#x} already taken", aruid); + ASSERT_DEBUG(!resource.has_value(), Kernel, "Aruid {:#x} already taken", + aruid); resource.emplace(system); return *resource; } void DestroyResource(kernel::AppletResourceUserId aruid) { auto& resource = GetResourceOpt(aruid); - ASSERT_THROWING_DEBUG(resource.has_value(), Kernel, Error::InvalidAruid, - "Invalid aruid {:#x}", aruid); + ASSERT_DEBUG(resource.has_value(), Kernel, "Invalid aruid {:#x}", + aruid); resource = std::nullopt; } T& GetResource(kernel::AppletResourceUserId aruid) { auto& resource = GetResourceOpt(aruid); - ASSERT_THROWING_DEBUG(resource.has_value(), Kernel, Error::InvalidAruid, - "Invalid aruid {:#x}", aruid); + ASSERT_DEBUG(resource.has_value(), Kernel, "Invalid aruid {:#x}", + aruid); return *resource; } const T& GetResource(kernel::AppletResourceUserId aruid) const { auto& resource = GetResourceOpt(aruid); - ASSERT_THROWING_DEBUG(resource.has_value(), Kernel, Error::InvalidAruid, - "Invalid aruid {:#x}", aruid); + ASSERT_DEBUG(resource.has_value(), Kernel, "Invalid aruid {:#x}", + aruid); return *resource; } diff --git a/src/core/horizon/kernel/applet_state.cpp b/src/core/horizon/kernel/applet_state.cpp index 012378a9..e04f27c0 100644 --- a/src/core/horizon/kernel/applet_state.cpp +++ b/src/core/horizon/kernel/applet_state.cpp @@ -15,13 +15,13 @@ AppletState::~AppletState() { } void AppletState::SendMessage(AppletMessage msg) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); SendMessageImpl(msg); } void AppletState::SetFocusState(AppletFocusState focus_state_) { { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); SendMessageImpl(AppletMessage::FocusStateChanged); if (focus_state_ == AppletFocusState::InFocus) SendMessageImpl(AppletMessage::ChangeIntoForeground); @@ -30,12 +30,12 @@ void AppletState::SetFocusState(AppletFocusState focus_state_) { } void AppletState::PushPreselectedUser(uuid_t user_id) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); user_ids.push(user_id); } AppletMessage AppletState::ReceiveMessage() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); if (msg_queue.empty()) { return AppletMessage::None; } @@ -50,8 +50,9 @@ AppletMessage AppletState::ReceiveMessage() { return msg; } -std::span AppletState::PopLaunchParameter(const LaunchParameterKind kind) { - std::lock_guard lock(mutex); +std::vector +AppletState::PopLaunchParameter(const LaunchParameterKind kind) { + std::scoped_lock lock(mutex); switch (kind) { case LaunchParameterKind::PreselectedUser: { if (user_ids.empty()) { @@ -62,12 +63,15 @@ std::span AppletState::PopLaunchParameter(const LaunchParameterKind kind) { const uuid_t user_id = user_ids.top(); user_ids.pop(); - return {reinterpret_cast(new AccountHeader{ - .magic = 0xc79497ca, - .unk_x4 = 1, - .user_id = user_id, - }), - sizeof(AccountHeader)}; + AccountHeader res{ + .magic = 0xc79497ca, + .unk_x4 = 1, + .user_id = user_id, + }; + + std::vector bytes(sizeof(AccountHeader)); + std::memcpy(bytes.data(), &res, sizeof(AccountHeader)); + return bytes; } default: LOG_NOT_IMPLEMENTED(Horizon, "Launch parameter {}", kind); diff --git a/src/core/horizon/kernel/applet_state.hpp b/src/core/horizon/kernel/applet_state.hpp index 22d49deb..94f5a4fa 100644 --- a/src/core/horizon/kernel/applet_state.hpp +++ b/src/core/horizon/kernel/applet_state.hpp @@ -13,9 +13,9 @@ class Kernel; #pragma pack(push, 1) struct AccountHeader { u32 magic; - aligned unk_x4; + Aligned unk_x4; uuid_t user_id; - u8 unk_x18[0x70]; // Unused + std::array unk_x18; // Unused }; #pragma pack(pop) @@ -37,7 +37,7 @@ class AppletState { AppletMessage ReceiveMessage(); AppletFocusState GetFocusState() { return focus_state; } bool IsExitLocked() { return exit_locked; } - std::span PopLaunchParameter(const LaunchParameterKind kind); + std::vector PopLaunchParameter(const LaunchParameterKind kind); private: Kernel& kernel; diff --git a/src/core/horizon/kernel/auto_object.hpp b/src/core/horizon/kernel/auto_object.hpp index 5e0da1b4..9bfc42f8 100644 --- a/src/core/horizon/kernel/auto_object.hpp +++ b/src/core/horizon/kernel/auto_object.hpp @@ -4,11 +4,32 @@ namespace hydra::horizon::kernel { +enum class AutoObjectTypeId { + ClientPort, + ClientSession, + Port, + ServerPort, + ServerSession, + Session, + CodeMemory, + Event, // TODO: ReadableEvent and WritableEvent + Process, + SharedMemory, + Thread, + TransferMemory, +}; + class AutoObject { public: - AutoObject(const std::string_view debug_name_ = "AutoObject") - : debug_name{fmt::format("{} {}", debug_name_, + AutoObject(AutoObjectTypeId type_id_, + const std::string_view debug_name_ = "AutoObject") noexcept + : type_id{type_id_}, + debug_name{fmt::format("{} {}", debug_name_, reinterpret_cast(this))} {} + virtual ~AutoObject() noexcept = default; + + MAKE_NON_COPYABLE(AutoObject); + MAKE_NON_MOVABLE(AutoObject); void Retain() { ref_count.fetch_add(1, std::memory_order_relaxed); } @@ -24,15 +45,31 @@ class AutoObject { return false; } - std::string_view GetDebugName() const { return debug_name; } + template + bool IsOfType() const + requires std::is_base_of_v + { + return type_id == T::TYPE_ID; + } - protected: - virtual ~AutoObject() {} + std::string_view GetDebugName() const { return debug_name; } private: + AutoObjectTypeId type_id; std::string debug_name; std::atomic ref_count{1}; + + public: + GETTER(type_id, GetTypeId); }; } // namespace hydra::horizon::kernel + +ENABLE_ENUM_FORMATTING(hydra::horizon::kernel::AutoObjectTypeId, ClientPort, + "client port", ClientSession, "client session", Port, + "port", ServerPort, "server port", ServerSession, + "server session", Session, "session", CodeMemory, + "code memory", Event, "event", Process, "process", + SharedMemory, "shared memory", Thread, "thread", + TransferMemory, "transfer memory") diff --git a/src/core/horizon/kernel/code_memory.hpp b/src/core/horizon/kernel/code_memory.hpp index 51952936..a0200363 100644 --- a/src/core/horizon/kernel/code_memory.hpp +++ b/src/core/horizon/kernel/code_memory.hpp @@ -7,9 +7,11 @@ namespace hydra::horizon::kernel { // TODO: does this inherit from AutoObject? class CodeMemory : public AutoObject { public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::CodeMemory; + CodeMemory(vaddr_t addr_, u64 size_, - const std::string_view debug_name = "CodeMemory") - : AutoObject(debug_name), addr{addr_}, size{size_} {} + std::string_view debug_name = "CodeMemory") + : AutoObject(TYPE_ID, debug_name), addr{addr_}, size{size_} {} private: vaddr_t addr; diff --git a/src/core/horizon/kernel/const.hpp b/src/core/horizon/kernel/const.hpp index a0e81fa9..d5a556d1 100644 --- a/src/core/horizon/kernel/const.hpp +++ b/src/core/horizon/kernel/const.hpp @@ -281,7 +281,7 @@ enum class Error { NotDebugged = 520, }; -typedef u32 result_t; +using result_t = u32; #define MAKE_RESULT(module, description) \ (((static_cast(::hydra::horizon::kernel::Module::module) & 0x1ff)) | \ @@ -359,9 +359,9 @@ struct MemoryInfo { u64 addr; u64 size; MemoryState state; - u32 ipc_ref_count; // TODO: what - u32 device_ref_count; // TODO: what - u32 padding = 0; + u32 ipc_ref_count; + u32 device_ref_count; + u32 _padding = 0; }; enum class BreakReasonType { @@ -379,10 +379,9 @@ struct BreakReason { BreakReasonType type; bool notification_only; - BreakReason(u64 reg) { - notification_only = reg & 0x80000000; - type = static_cast(reg & 0x7FFFFFFF); - } + BreakReason(u64 reg) + : type{static_cast(reg & 0x7FFFFFFF)}, + notification_only{static_cast(reg & 0x80000000)} {} }; // From https://github.com/switchbrew/libnx @@ -456,14 +455,14 @@ union FpuRegister { }; struct ThreadContext { - CpuRegister cpu_gprs[29]; + std::array cpu_gprs; u64 fp; u64 lr; u64 sp; CpuRegister pc; u32 psr; - FpuRegister fpu_gprs[32]; + std::array fpu_gprs; u32 fpcr; u32 fpsr; @@ -535,7 +534,7 @@ enum class LaunchParameterKind : u32 { Unknown0 = 3, }; -typedef u32 UserId; +using UserId = u32; enum class CodeMemoryOperation { MapOwner = 0, diff --git a/src/core/horizon/kernel/event.hpp b/src/core/horizon/kernel/event.hpp index 5a366092..d833e4f4 100644 --- a/src/core/horizon/kernel/event.hpp +++ b/src/core/horizon/kernel/event.hpp @@ -6,7 +6,11 @@ namespace hydra::horizon::kernel { // TODO: ReadableEvent and WritableEvent class Event : public SynchronizationObject { - using SynchronizationObject::SynchronizationObject; + public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::Event; + + Event(bool signalled = false, std::string_view debug_name = "Event") + : SynchronizationObject(TYPE_ID, signalled, debug_name) {} }; } // namespace hydra::horizon::kernel diff --git a/src/core/horizon/kernel/guest_thread.cpp b/src/core/horizon/kernel/guest_thread.cpp index 50fd9ee7..cb40efff 100644 --- a/src/core/horizon/kernel/guest_thread.cpp +++ b/src/core/horizon/kernel/guest_thread.cpp @@ -12,7 +12,7 @@ namespace hydra::horizon::kernel { GuestThread::GuestThread(System& system_, Process* process, vaddr_t stack_top_addr_, i32 priority, - const std::string_view debug_name) + std::string_view debug_name) : IThread(process, priority, debug_name), system{system_}, stack_top_addr{stack_top_addr_} { tls_mem = process->CreateTlsMemory(tls_addr); @@ -27,20 +27,20 @@ void GuestThread::Run() { ASSERT(entry_point != invalid(), Kernel, "Invalid entry point"); thread = system.GetCpu().CreateThread( system.GetWallClock(), process->GetMmu(), - {[this](hw::tegra_x1::cpu::IThread* hw_thread, u64 id) { + {.svc_handler=[this](hw::tegra_x1::cpu::IThread* hw_thread, u64 id) { system.GetOS().GetKernel().SupervisorCall(process, this, hw_thread, id); }, - [this]() { + .stop_requested=[this]() { ProcessMessages(); return GetState() == ThreadState::Stopping; }, - [this]() { + .supervisor_pause=[this]() { SupervisorPause(); DEBUGGER_MANAGER_INSTANCE.GetDebugger(process) .NotifySupervisorPaused(this, debugger::Signal::SigTrap); }, - [this]() { + .breakpoint_hit=[this]() { DEBUGGER_MANAGER_INSTANCE.GetDebugger(process).BreakpointHit(this); }}, tls_mem, tls_addr); diff --git a/src/core/horizon/kernel/guest_thread.hpp b/src/core/horizon/kernel/guest_thread.hpp index 3baee98c..8a7014dd 100644 --- a/src/core/horizon/kernel/guest_thread.hpp +++ b/src/core/horizon/kernel/guest_thread.hpp @@ -16,8 +16,7 @@ namespace hydra::horizon::kernel { class GuestThread : public IThread { public: GuestThread(System& system_, Process* process, vaddr_t stack_top_addr_, - i32 priority, - const std::string_view debug_name = "Guest thread"); + i32 priority, std::string_view debug_name = "Guest thread"); ~GuestThread() override; void SetEntryPoint(vaddr_t entry_point_) { entry_point = entry_point_; } diff --git a/src/core/horizon/kernel/hipc/client_port.hpp b/src/core/horizon/kernel/hipc/client_port.hpp index b3e5a31a..f79d4fe8 100644 --- a/src/core/horizon/kernel/hipc/client_port.hpp +++ b/src/core/horizon/kernel/hipc/client_port.hpp @@ -9,8 +9,10 @@ class ClientSession; class ClientPort : public SynchronizationObject { public: - ClientPort(const std::string_view debug_name = "Client port") - : SynchronizationObject(true, debug_name) {} + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::ClientPort; + + ClientPort(std::string_view debug_name = "Client port") + : SynchronizationObject(TYPE_ID, true, debug_name) {} ClientSession* Connect(); diff --git a/src/core/horizon/kernel/hipc/client_session.hpp b/src/core/horizon/kernel/hipc/client_session.hpp index c8f29379..ac9e7337 100644 --- a/src/core/horizon/kernel/hipc/client_session.hpp +++ b/src/core/horizon/kernel/hipc/client_session.hpp @@ -9,8 +9,10 @@ class Session; // TODO: should maintain a reference to the parent session class ClientSession : public AutoObject { public: - ClientSession(const std::string_view debug_name = "Client session") - : AutoObject(debug_name) {} + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::ClientSession; + + ClientSession(std::string_view debug_name = "Client session") + : AutoObject(TYPE_ID, debug_name) {} ~ClientSession() override; void OnServerClose() { server_open = false; } diff --git a/src/core/horizon/kernel/hipc/cmif.hpp b/src/core/horizon/kernel/hipc/cmif.hpp index 4faaf0e9..04e60c19 100644 --- a/src/core/horizon/kernel/hipc/cmif.hpp +++ b/src/core/horizon/kernel/hipc/cmif.hpp @@ -83,8 +83,8 @@ inline void write_domain_out_header(io::MemoryStream& stream) { } template -inline T* align_data_start(T* data_start) { - return align_ptr(data_start, 0x10); // align to 16 bytes +inline T* AlignDataStart(T* data_start) { + return AlignPtr(data_start, 0x10); // align to 16 bytes } } // namespace hydra::horizon::kernel::hipc::cmif diff --git a/src/core/horizon/kernel/hipc/const.hpp b/src/core/horizon/kernel/hipc/const.hpp index df8e5e4f..40d27d72 100644 --- a/src/core/horizon/kernel/hipc/const.hpp +++ b/src/core/horizon/kernel/hipc/const.hpp @@ -51,7 +51,7 @@ struct Header { u32 recv_static_mode : 4; u32 padding : 6; u32 recv_list_offset : 11; // Unused. - bool has_special_header : 1; + u32 has_special_header : 1; }; // From https://github.com/switchbrew/libnx @@ -106,58 +106,59 @@ struct SpecialHeader { // From https://github.com/switchbrew/libnx inline Request calc_request_layout(Metadata meta, void* base) { // Copy handles - handle_id_t* copy_handles = NULL; - if (meta.num_copy_handles) { + handle_id_t* copy_handles = nullptr; + if (meta.num_copy_handles != 0) { copy_handles = reinterpret_cast(base); base = copy_handles + meta.num_copy_handles; } // Move handles - handle_id_t* move_handles = NULL; - if (meta.num_move_handles) { + handle_id_t* move_handles = nullptr; + if (meta.num_move_handles != 0) { move_handles = reinterpret_cast(base); base = move_handles + meta.num_move_handles; } // Send statics - StaticDescriptor* send_statics = NULL; - if (meta.num_send_statics) { + StaticDescriptor* send_statics = nullptr; + if (meta.num_send_statics != 0) { send_statics = reinterpret_cast(base); base = send_statics + meta.num_send_statics; } // Send buffers - BufferDescriptor* send_buffers = NULL; - if (meta.num_send_buffers) { + BufferDescriptor* send_buffers = nullptr; + if (meta.num_send_buffers != 0) { send_buffers = reinterpret_cast(base); base = send_buffers + meta.num_send_buffers; } // Recv buffers - BufferDescriptor* recv_buffers = NULL; - if (meta.num_recv_buffers) { + BufferDescriptor* recv_buffers = nullptr; + if (meta.num_recv_buffers != 0) { recv_buffers = reinterpret_cast(base); base = recv_buffers + meta.num_recv_buffers; } // Exch buffers - BufferDescriptor* exch_buffers = NULL; - if (meta.num_exch_buffers) { + BufferDescriptor* exch_buffers = nullptr; + if (meta.num_exch_buffers != 0) { exch_buffers = reinterpret_cast(base); base = exch_buffers + meta.num_exch_buffers; } // Data words - u32* data_words = NULL; - if (meta.num_data_words) { + u32* data_words = nullptr; + if (meta.num_data_words != 0) { data_words = reinterpret_cast(base); base = data_words + meta.num_data_words; } // Recv list - RecvListEntry* recv_list = NULL; - if (meta.num_recv_statics) + RecvListEntry* recv_list = nullptr; + if (meta.num_recv_statics != 0) { recv_list = reinterpret_cast(base); + } return Request{ .send_statics = send_statics, @@ -180,7 +181,7 @@ inline ParsedRequest parse_request(void* base) { u64 pid = 0; // Parse recv static mode - if (hdr.recv_static_mode) { + if (hdr.recv_static_mode != 0u) { if (hdr.recv_static_mode == 2u) num_recv_statics = HIPC_AUTO_RECV_STATIC; else if (hdr.recv_static_mode > 2u) @@ -222,9 +223,10 @@ inline ParsedRequest parse_request(void* base) { inline Request make_request(void* base, Metadata meta) { // Write message header - bool has_special_header = - meta.send_pid || meta.num_copy_handles || meta.num_move_handles; - Header* hdr = reinterpret_cast(base); + bool has_special_header = (meta.send_pid != 0u) || + (meta.num_copy_handles != 0u) || + (meta.num_move_handles != 0u); + auto* hdr = reinterpret_cast(base); base = hdr + 1; *hdr = Header{ .type = meta.type, @@ -234,26 +236,26 @@ inline Request make_request(void* base, Metadata meta) { .num_exch_buffers = meta.num_exch_buffers, .num_data_words = meta.num_data_words, .recv_static_mode = - meta.num_recv_statics + (meta.num_recv_statics != 0u) ? (meta.num_recv_statics != HIPC_AUTO_RECV_STATIC ? 2u + meta.num_recv_statics : 2u) : 0u, .padding = 0, .recv_list_offset = 0, - .has_special_header = has_special_header, + .has_special_header = static_cast(has_special_header), }; // Write special header if (has_special_header) { - SpecialHeader* sphdr = reinterpret_cast(base); + auto sphdr = reinterpret_cast(base); base = sphdr + 1; *sphdr = SpecialHeader{ .send_pid = meta.send_pid, .num_copy_handles = meta.num_copy_handles, .num_move_handles = meta.num_move_handles, }; - if (meta.send_pid) + if (meta.send_pid != 0u) base = reinterpret_cast(base) + sizeof(u64); } @@ -279,7 +281,8 @@ u8* get_list_entry_ptr(const hw::tegra_x1::cpu::IMmu* mmu, u8* ptr = get_##buffer_or_static##_ptr( \ mmu, hipc_in.data.type##_##buffer_or_static##s[i], size); \ type##_##buffer_or_static##s_streams.push_back( \ - ptr ? std::make_optional(std::span(ptr, size)) \ + ptr != nullptr \ + ? std::make_optional(std::span(ptr, size)) \ : std::nullopt); \ } @@ -326,7 +329,8 @@ struct Streams { u8* ptr = get_list_entry_ptr(mmu, hipc_in.data.recv_list[i], size); // TODO: should we continue or push std::nullopt in case of nullptr? recv_list_streams.push_back( - ptr ? std::make_optional(std::span(ptr, size)) + ptr != nullptr + ? std::make_optional(std::span(ptr, size)) : std::nullopt); } CREATE_BUFFER_STREAMS(recv); diff --git a/src/core/horizon/kernel/hipc/port.cpp b/src/core/horizon/kernel/hipc/port.cpp index 84545586..8644f97f 100644 --- a/src/core/horizon/kernel/hipc/port.cpp +++ b/src/core/horizon/kernel/hipc/port.cpp @@ -5,9 +5,9 @@ namespace hydra::horizon::kernel::hipc { Port::Port(ServerPort* server_side_, ClientPort* client_side_, - const std::string_view debug_name) - : AutoObject(debug_name), server_side{server_side_}, client_side{ - client_side_} { + std::string_view debug_name) + : AutoObject(TYPE_ID, debug_name), server_side{server_side_}, + client_side{client_side_} { client_side->SetParent(this); } diff --git a/src/core/horizon/kernel/hipc/port.hpp b/src/core/horizon/kernel/hipc/port.hpp index bb7d372b..1d873945 100644 --- a/src/core/horizon/kernel/hipc/port.hpp +++ b/src/core/horizon/kernel/hipc/port.hpp @@ -10,8 +10,10 @@ class ClientPort; // TODO: implement same lifetime management logic as sessions class Port : public AutoObject { public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::Port; + Port(ServerPort* server_side_, ClientPort* client_side_, - const std::string_view debug_name = "Port"); + std::string_view debug_name = "Port"); private: ServerPort* server_side; diff --git a/src/core/horizon/kernel/hipc/server_port.cpp b/src/core/horizon/kernel/hipc/server_port.cpp index 3b961079..d79a01c7 100644 --- a/src/core/horizon/kernel/hipc/server_port.cpp +++ b/src/core/horizon/kernel/hipc/server_port.cpp @@ -3,7 +3,7 @@ namespace hydra::horizon::kernel::hipc { ServerSession* ServerPort::AcceptSession() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); ASSERT_DEBUG(!incomming_sessions.empty(), Kernel, "No incomming sessions"); const auto session = incomming_sessions.front(); incomming_sessions.pop(); @@ -16,7 +16,7 @@ ServerSession* ServerPort::AcceptSession() { } void ServerPort::ConnectSession(ServerSession* session) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); incomming_sessions.push(session); // Signal incomming session diff --git a/src/core/horizon/kernel/hipc/server_port.hpp b/src/core/horizon/kernel/hipc/server_port.hpp index b8ee50d6..c278896d 100644 --- a/src/core/horizon/kernel/hipc/server_port.hpp +++ b/src/core/horizon/kernel/hipc/server_port.hpp @@ -8,8 +8,10 @@ class ServerSession; class ServerPort : public SynchronizationObject { public: - ServerPort(const std::string_view debug_name = "Server port") - : SynchronizationObject(false, debug_name) {} + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::ServerPort; + + ServerPort(std::string_view debug_name = "Server port") + : SynchronizationObject(TYPE_ID, false, debug_name) {} // Server ServerSession* AcceptSession(); diff --git a/src/core/horizon/kernel/hipc/server_session.cpp b/src/core/horizon/kernel/hipc/server_session.cpp index a7f87399..4f0fa2cc 100644 --- a/src/core/horizon/kernel/hipc/server_session.cpp +++ b/src/core/horizon/kernel/hipc/server_session.cpp @@ -16,7 +16,7 @@ ServerSession::~ServerSession() { } void ServerSession::OnClientClose() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); client_open = false; // Signal the server that client has closed @@ -24,7 +24,7 @@ void ServerSession::OnClientClose() { } void ServerSession::Receive(IThread* crnt_thread) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); ASSERT_DEBUG(!requests.empty(), Kernel, "No requests"); active_request = requests.front(); requests.pop(); @@ -40,7 +40,7 @@ void ServerSession::Receive(IThread* crnt_thread) { } void ServerSession::Reply(uptr ptr) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); // Copy the message to client TLS memcpy(reinterpret_cast(active_request->client_thread->GetTlsPtr()), @@ -54,8 +54,8 @@ void ServerSession::Reply(uptr ptr) { void ServerSession::EnqueueRequest(Process* client_process, IThread* client_thread, uptr ptr) { - std::lock_guard lock(mutex); - requests.push({client_process, client_thread, ptr}); + std::scoped_lock lock(mutex); + requests.push({.client_process=client_process, .client_thread=client_thread, .ptr=ptr}); // Signal the server to process the request Signal(); diff --git a/src/core/horizon/kernel/hipc/server_session.hpp b/src/core/horizon/kernel/hipc/server_session.hpp index e9b1e7c7..74245398 100644 --- a/src/core/horizon/kernel/hipc/server_session.hpp +++ b/src/core/horizon/kernel/hipc/server_session.hpp @@ -20,14 +20,16 @@ struct SessionRequest { // TODO: should maintain a reference to the parent session class ServerSession : public SynchronizationObject { public: - ServerSession(const std::string_view debug_name = "Server session") - : SynchronizationObject(false, debug_name) {} + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::ServerSession; + + ServerSession(std::string_view debug_name = "Server session") + : SynchronizationObject(TYPE_ID, false, debug_name) {} ~ServerSession() override; void OnClientClose(); bool IsClientOpen() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); return client_open; } @@ -36,13 +38,13 @@ class ServerSession : public SynchronizationObject { void Reply(uptr ptr); bool HasRequests() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); return !requests.empty(); } // HACK kernel::Process* GetActiveRequestClientProcess() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); return active_request->client_process; } diff --git a/src/core/horizon/kernel/hipc/service_manager.hpp b/src/core/horizon/kernel/hipc/service_manager.hpp index 6981d9c0..8b294349 100644 --- a/src/core/horizon/kernel/hipc/service_manager.hpp +++ b/src/core/horizon/kernel/hipc/service_manager.hpp @@ -10,19 +10,19 @@ template class ServiceManager { public: ~ServiceManager() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); for (auto& [_, port] : ports) port->Release(); } void RegisterPort(const Key& port_name, ClientPort* client_port) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); client_port->Retain(); ports.insert({port_name, client_port}); } void UnregisterPort(const Key& port_name) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); auto it = ports.find(port_name); ASSERT(it != ports.end(), Kernel, "Port not registered"); it->second->Release(); @@ -30,7 +30,7 @@ class ServiceManager { } ClientPort* GetPort(const Key& port_name) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); auto it = ports.find(port_name); if (it == ports.end()) return nullptr; diff --git a/src/core/horizon/kernel/hipc/session.cpp b/src/core/horizon/kernel/hipc/session.cpp index ac0a9373..29888d79 100644 --- a/src/core/horizon/kernel/hipc/session.cpp +++ b/src/core/horizon/kernel/hipc/session.cpp @@ -8,22 +8,22 @@ namespace hydra::horizon::kernel::hipc { Session::Session(ServerSession* server_side_, ClientSession* client_side_, - const std::string_view debug_name) - : AutoObject(debug_name), server_side{server_side_}, client_side{ - client_side_} { + std::string_view debug_name) + : AutoObject(TYPE_ID, debug_name), server_side{server_side_}, + client_side{client_side_} { server_side->SetParent(this); client_side->SetParent(this); } void Session::OnServerClose() { server_side = nullptr; - if (client_side) + if (client_side != nullptr) client_side->OnServerClose(); } void Session::OnClientClose() { client_side = nullptr; - if (server_side) + if (server_side != nullptr) server_side->OnClientClose(); } diff --git a/src/core/horizon/kernel/hipc/session.hpp b/src/core/horizon/kernel/hipc/session.hpp index 84545494..a1b0c369 100644 --- a/src/core/horizon/kernel/hipc/session.hpp +++ b/src/core/horizon/kernel/hipc/session.hpp @@ -13,8 +13,10 @@ class ClientSession; class Session : public AutoObject { public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::Session; + Session(ServerSession* server_side_, ClientSession* client_side_, - const std::string_view debug_name = "Session"); + std::string_view debug_name = "Session"); void OnServerClose(); void OnClientClose(); diff --git a/src/core/horizon/kernel/host_thread.hpp b/src/core/horizon/kernel/host_thread.hpp index d512abe1..0598fb21 100644 --- a/src/core/horizon/kernel/host_thread.hpp +++ b/src/core/horizon/kernel/host_thread.hpp @@ -4,17 +4,19 @@ namespace hydra::horizon::kernel { -typedef std::function should_stop_fn_t; -typedef std::function run_callback_fn_t; +using should_stop_fn_t = std::function; +using run_callback_fn_t = std::function; class HostThread : public IThread { public: HostThread(Process* process, i32 priority, run_callback_fn_t run_callback_, - const std::string_view debug_name = "Thread") - : IThread(process, priority, debug_name), run_callback{run_callback_} {} - ~HostThread() override { delete[] tls; } + std::string_view debug_name = "Thread") + : IThread(process, priority, debug_name), + run_callback{std::move(run_callback_)}, tls(TLS_SIZE) {} - uptr GetTlsPtr() const override { return reinterpret_cast(tls); } + uptr GetTlsPtr() const override { + return reinterpret_cast(tls.data()); + } protected: void Run() override; @@ -22,7 +24,7 @@ class HostThread : public IThread { private: run_callback_fn_t run_callback; - u8* tls = new u8[TLS_SIZE]; // TODO: stack allocate + std::vector tls; // TODO: why cannot std::array be used? }; } // namespace hydra::horizon::kernel diff --git a/src/core/horizon/kernel/kernel.cpp b/src/core/horizon/kernel/kernel.cpp index b6b93d2b..be49782f 100644 --- a/src/core/horizon/kernel/kernel.cpp +++ b/src/core/horizon/kernel/kernel.cpp @@ -62,10 +62,10 @@ void Kernel::SupervisorCall(Process* crnt_process, IThread* crnt_thread, break; case 0x8: { IThread* thread = nullptr; - state.r[0] = - CreateThread(crnt_process, state.r[1], state.r[2], state.r[3], - std::bit_cast(u32(state.r[4])), - std::bit_cast(u32(state.r[5])), thread); + state.r[0] = CreateThread( + crnt_process, state.r[1], state.r[2], state.r[3], + std::bit_cast(static_cast(state.r[4])), + std::bit_cast(static_cast(state.r[5])), thread); state.r[1] = crnt_process->AddHandleNoRetain(thread); break; } @@ -361,21 +361,9 @@ result_t Kernel::SetHeapSize(Process* crnt_process, u64 size, uptr& out_base) { if ((size % HEAP_MEM_ALIGNMENT) != 0) return MAKE_RESULT(Svc, Error::InvalidSize); // TODO: correct? - // TODO: handle this more cleanly? - auto& heap_mem = crnt_process->GetHeapMemory(); - if (!heap_mem) { - heap_mem = system.GetCpu().AllocateMemory(size); - crnt_process->GetMmu()->Map(HEAP_REGION.GetBegin(), heap_mem, - {MemoryType::Normal_1_0_0, - MemoryAttribute::None, - MemoryPermission::ReadWrite}); - } else { - crnt_process->GetMmu()->ResizeHeap(heap_mem, HEAP_REGION.GetBegin(), - size); - } + crnt_process->ResizeHeap(size); out_base = HEAP_REGION.GetBegin(); - return RESULT_SUCCESS; } @@ -588,8 +576,8 @@ result_t Kernel::MapSharedMemory(Process* crnt_process, SharedMemory* shmem, "0x{:08x}, perm: {})", shmem->GetDebugName(), addr, size, perm); - shmem->MapToRange(crnt_process->GetMmu(), Range(addr, uptr(addr + size)), - perm); + shmem->MapToRange(crnt_process->GetMmu(), + Range(addr, static_cast(addr + size)), perm); return RESULT_SUCCESS; } @@ -622,7 +610,7 @@ result_t Kernel::CreateTransferMemory(uptr addr, u64 size, result_t Kernel::CloseHandle(Process* crnt_process, handle_id_t handle_id) { auto obj = crnt_process->GetHandle(handle_id); - if (!obj) { + if (obj == nullptr) { LOG_WARN(Kernel, "CloseHandle called (INVALID_HANDLE)"); return MAKE_RESULT(Svc, Error::InvalidHandle); } @@ -635,7 +623,7 @@ result_t Kernel::CloseHandle(Process* crnt_process, handle_id_t handle_id) { // TODO: can only be ReadableEvent or Process? result_t Kernel::ResetSignal(SynchronizationObject* sync_obj) { - if (!sync_obj) { + if (sync_obj == nullptr) { LOG_WARN(Kernel, "ResetSignal called (INVALID_HANDLE)"); // HACK return RESULT_SUCCESS; // MAKE_RESULT(Svc, Error::InvalidHandle); @@ -659,8 +647,8 @@ Kernel::WaitSynchronization(IThread* crnt_thread, "{})", sync_objs.size(), timeout); - for (u32 i = 0; i < sync_objs.size(); i++) { - if (!sync_objs[i]) { + for (auto& sync_obj : sync_objs) { + if (sync_obj == nullptr) { LOG_WARN(Kernel, "Invalid sync object"); // HACK: Celeste gets stuck in an infinite WaitSynchronization // loop if an error is returned @@ -701,7 +689,7 @@ Kernel::WaitSynchronization(IThread* crnt_thread, // Find the handle index out_signalled_index = 0; - if (signalled_obj) { + if (signalled_obj != nullptr) { for (u32 i = 0; i < sync_objs.size(); i++) { if (sync_objs[i] == signalled_obj) { out_signalled_index = i; @@ -818,7 +806,7 @@ result_t Kernel::WaitProcessWideKeyAtomic(Process* crnt_process, // Mutex auto owner = GetMutexOwner( crnt_process, static_cast(crnt_thread->mutex_wait_addr)); - if (owner) + if (owner != nullptr) owner->RemoveMutexWaiter(crnt_thread); } @@ -837,7 +825,7 @@ result_t Kernel::SignalProcessWideKey(Process* crnt_process, uptr addr, // TODO: sort by priority for (auto thread_node = cond_var_waiters.GetHead(); - thread_node && count > 0;) { + (thread_node != nullptr) && count > 0;) { const auto thread = thread_node->Get(); if (thread->cond_var_wait_addr == addr) { thread->cond_var_wait_addr = 0x0; @@ -863,7 +851,7 @@ result_t Kernel::ConnectToNamedPort(const std::string_view name, LOG_DEBUG(Kernel, "ConnectToNamedPort called (name: {})", name); auto port = service_manager.GetPort(std::string(name)); - if (!port) { + if (port == nullptr) { LOG_ERROR(Kernel, "Failed to connect to port \"{}\"", name); return MAKE_RESULT(Svc, Error::NotFound); } @@ -875,7 +863,7 @@ result_t Kernel::ConnectToNamedPort(const std::string_view name, result_t Kernel::SendSyncRequest(Process* crnt_process, IThread* crnt_thread, hipc::ClientSession* client_session) { - if (!client_session) { + if (client_session == nullptr) { LOG_WARN(Kernel, "SendSyncRequest called (INVALID_HANDLE)"); return MAKE_RESULT(Svc, Error::InvalidHandle); } @@ -916,7 +904,7 @@ result_t Kernel::GetThreadId(IThread* thread, u64& out_thread_id) { LOG_FUNC_STUBBED(Services); // HACK - out_thread_id = u64(thread); + out_thread_id = std::bit_cast(thread); return RESULT_SUCCESS; } @@ -928,7 +916,7 @@ result_t Kernel::Break(BreakReason reason, uptr buffer_ptr, u64 buffer_size) { reason.type, buffer_ptr, buffer_size); // TODO: this should be sent to the debugger instead of being logged - if (buffer_ptr) { + if (buffer_ptr != 0u) { if (buffer_size == sizeof(u32)) { const u32 result = *reinterpret_cast(buffer_ptr); const auto module = GET_RESULT_MODULE(result); @@ -992,7 +980,7 @@ result_t Kernel::GetInfo(Process* crnt_process, InfoType info_type, return RESULT_SUCCESS; case InfoType::TotalMemorySize: // TODO: what should this be? - out_info = 3u * 1024u * 1024u * 1024u; + out_info = 3ull * 1024ull * 1024ull * 1024ull; return RESULT_SUCCESS; case InfoType::UsedMemorySize: { // TODO: correct? @@ -1003,12 +991,12 @@ result_t Kernel::GetInfo(Process* crnt_process, InfoType info_type, size += executable_mem->GetSize(); out_info = size; */ - out_info = 4u * 1024u * 1024u; + out_info = 4ull * 1024ull * 1024ull; return RESULT_SUCCESS; } case InfoType::DebuggerAttached: // TODO: make this configurable - out_info = true; + out_info = static_cast(true); return RESULT_SUCCESS; case InfoType::RandomEntropy: ASSERT_DEBUG(info_sub_type < crnt_process->GetRandomEntropy().size(), @@ -1034,7 +1022,7 @@ result_t Kernel::GetInfo(Process* crnt_process, InfoType info_type, case InfoType::UsedSystemResourceSize: LOG_NOT_IMPLEMENTED(Kernel, "UsedSystemResourceSize"); // HACK - out_info = 64 * 1024; + out_info = 64ull * 1024ull; return RESULT_SUCCESS; case InfoType::ProgramId: out_info = crnt_process->GetTitleID(); @@ -1047,7 +1035,7 @@ result_t Kernel::GetInfo(Process* crnt_process, InfoType info_type, case InfoType::TotalNonSystemMemorySize: LOG_NOT_IMPLEMENTED(Kernel, "TotalNonSystemMemorySize"); // HACK - out_info = 2u * 1024u * 1024u * 1024u; + out_info = 2ull * 1024ull * 1024ull * 1024ull; return RESULT_SUCCESS; case InfoType::UsedNonSystemMemorySize: LOG_NOT_IMPLEMENTED(Kernel, "UsedNonSystemMemorySize"); @@ -1056,7 +1044,7 @@ result_t Kernel::GetInfo(Process* crnt_process, InfoType info_type, return RESULT_SUCCESS; case InfoType::IsApplication: // TODO: don't always return true - out_info = true; + out_info = static_cast(true); return RESULT_SUCCESS; case InfoType::AliasRegionExtraSize: LOG_NOT_IMPLEMENTED(Kernel, "AliasRegionExtraSize"); @@ -1087,8 +1075,9 @@ result_t Kernel::MapPhysicalMemory(Process* crnt_process, vaddr_t addr, auto mem = system.GetCpu().AllocateMemory(size); // TODO: keep track of the memory crnt_process->GetMmu()->Map(addr, mem, - {MemoryType::Alias, MemoryAttribute::None, - MemoryPermission::ReadWrite}); + {.type = MemoryType::Alias, + .attr = MemoryAttribute::None, + .perm = MemoryPermission::ReadWrite}); return RESULT_SUCCESS; } @@ -1255,7 +1244,7 @@ result_t Kernel::ReplyAndReceive(IThread* crnt_thread, LOG_DEBUG(Kernel, "ReplyAndReceive called (count: {}, timeout: {})", sync_objs.size(), timeout); - if (reply_target_session) { + if (reply_target_session != nullptr) { // Reply reply_target_session->Reply(crnt_thread->GetTlsPtr()); } @@ -1267,7 +1256,8 @@ result_t Kernel::ReplyAndReceive(IThread* crnt_thread, return res; auto sync_obj = sync_objs[static_cast(out_signalled_index)]; - if (auto server_session = dynamic_cast(sync_obj)) { + if (sync_obj->IsOfType()) { + auto server_session = static_cast(sync_obj); if (server_session->IsClientOpen()) { // Receive server_session->Receive(crnt_thread); @@ -1419,7 +1409,7 @@ void Kernel::UnlockMutex(IThread* thread, uptr mutex_addr) { u32 waiter_count; auto new_owner = thread->RelinquishMutex(mutex_addr, waiter_count); - if (!new_owner) { + if (new_owner == nullptr) { atomic_store(mutex, 0u); return; } diff --git a/src/core/horizon/kernel/kernel.hpp b/src/core/horizon/kernel/kernel.hpp index ac40d443..948ac1e2 100644 --- a/src/core/horizon/kernel/kernel.hpp +++ b/src/core/horizon/kernel/kernel.hpp @@ -37,9 +37,6 @@ class Kernel { void SupervisorCall(Process* crnt_process, IThread* crnt_thread, hw::tegra_x1::cpu::IThread* guest_thread, u64 id); - enum class AllocateAppletResourceUserIdError { - OutOfIds, - }; AppletResourceUserId AllocateAppletResourceUserId() { for (u32 i = 0; i < MAX_APPLET_RESOURCES; i++) { auto& is_free = free_applet_resource_user_ids[i]; @@ -49,17 +46,13 @@ class Kernel { } } - throw AllocateAppletResourceUserIdError::OutOfIds; + LOG_FATAL(Kernel, "Out of applet resource user IDs"); } - enum class ReleaseAppletResourceUserIdError { - InvalidAruid, - }; void ReleaseAppletResourceUserId(AppletResourceUserId aruid) { const auto index = ToIndex(aruid); - ASSERT_THROWING(!free_applet_resource_user_ids[index], Kernel, - ReleaseAppletResourceUserIdError::InvalidAruid, - "Invalid aruid {:#x}", aruid); + ASSERT(!free_applet_resource_user_ids[index], Kernel, + "Invalid aruid {:#x}", aruid); free_applet_resource_user_ids[index] = true; } @@ -98,7 +91,7 @@ class Kernel { result_t CloseHandle(Process* crnt_process, handle_id_t handle_id); result_t ResetSignal(SynchronizationObject* sync_object); result_t WaitSynchronization(IThread* crnt_thread, - std::span sync_objects, + std::span sync_objs, i64 timeout, u32& out_signalled_index); result_t CancelSynchronization(IThread* thread); result_t ArbitrateLock(IThread* crnt_thread, IThread* owner_thread, @@ -173,8 +166,8 @@ class Kernel { true}; // Helpers - void TryAcquireMutex(Process* crnt_process, IThread* thread); - void UnlockMutex(IThread* thread, uptr mutex_addr); + static void TryAcquireMutex(Process* crnt_process, IThread* thread); + static void UnlockMutex(IThread* thread, uptr mutex_addr); public: REF_GETTER(process_manager, GetProcessManager); diff --git a/src/core/horizon/kernel/process.cpp b/src/core/horizon/kernel/process.cpp index 5c2de0f4..dd71705f 100644 --- a/src/core/horizon/kernel/process.cpp +++ b/src/core/horizon/kernel/process.cpp @@ -10,10 +10,9 @@ namespace hydra::horizon::kernel { -Process::Process(System& system_, const std::string_view debug_name) - : SynchronizationObject(false, debug_name), system{system_}, - mmu{system.GetCpu().CreateMmu(system)}, gmmu{new hw::tegra_x1::gpu::GMmu( - mmu)}, +Process::Process(System& system_, std::string_view debug_name) + : SynchronizationObject(TYPE_ID, false, debug_name), system{system_}, + mmu{system.GetCpu().CreateMmu(system)}, gmmu(mmu.get()), applet_state(system.GetOS().GetKernel()) { // TODO: use title ID and name as debugger name? DEBUGGER_MANAGER_INSTANCE.AttachDebugger( @@ -38,8 +37,9 @@ uptr Process::CreateMemory(Range region, u64 size, MemoryType type, ASSERT(out_base != 0x0, Kernel, "Failed to find free memory"); auto mem = system.GetCpu().AllocateMemory(size); - mmu->Map(out_base, mem, {type, MemoryAttribute::None, perm}); - executable_mems.push_back(mem); + mmu->Map(out_base, mem, + {.type = type, .attr = MemoryAttribute::None, .perm = perm}); + executable_mems.emplace_back(mem); return mem->GetPtr(); } @@ -70,8 +70,9 @@ uptr Process::CreateExecutableMemory(const std::string_view module_name, // Debug DEBUGGER_MANAGER_INSTANCE.GetDebugger(this).GetModuleTable().RegisterSymbol( - {std::string(module_name), - Range(out_base, out_base + code_set.size)}); + {.name = std::string(module_name), + .guest_mem_range = + Range(out_base, out_base + code_set.size)}); return ptr; } @@ -80,8 +81,9 @@ hw::tegra_x1::cpu::IMemory* Process::CreateTlsMemory(vaddr_t& base) { auto mem = system.GetCpu().AllocateMemory(TLS_SIZE); base = tls_mem_base; mmu->Map(base, mem, - {MemoryType::ThreadLocal, MemoryAttribute::None, - MemoryPermission::ReadWrite}); + {.type = MemoryType::ThreadLocal, + .attr = MemoryAttribute::None, + .perm = MemoryPermission::ReadWrite}); tls_mem_base += TLS_SIZE; return mem; @@ -91,10 +93,26 @@ void Process::CreateStackMemory(u64 stack_size) { // main_thread = new GuestThread(this, STACK_REGION.begin + stack_size - // 0x10, priority); auto handle_id = AddHandle(main_thread); - main_thread_stack_mem = system.GetCpu().AllocateMemory(stack_size); - mmu->Map(STACK_REGION.GetBegin(), main_thread_stack_mem, - {MemoryType::Stack, MemoryAttribute::None, - MemoryPermission::ReadWrite}); + main_thread_stack_mem.reset(system.GetCpu().AllocateMemory(stack_size)); + mmu->Map(STACK_REGION.GetBegin(), main_thread_stack_mem.get(), + {.type = MemoryType::Stack, + .attr = MemoryAttribute::None, + .perm = MemoryPermission::ReadWrite}); +} + +void Process::ResizeHeap(u64 size) { + if (heap_mem == nullptr) { + heap_mem.reset(system.GetCpu().AllocateMemory(size)); + } else { + mmu->Unmap(Range::FromSize(HEAP_REGION.GetBegin(), + heap_mem->GetSize())); + heap_mem->Resize(size); + } + + mmu->Map(HEAP_REGION.GetBegin(), heap_mem.get(), + {.type = MemoryType::Normal_1_0_0, + .attr = MemoryAttribute::None, + .perm = MemoryPermission::ReadWrite}); } void Process::Start() { @@ -106,7 +124,7 @@ void Process::Start() { } void Process::Stop() { - std::lock_guard lock(thread_mutex); + std::scoped_lock lock(thread_mutex); for (auto thread : threads) thread->Stop(); @@ -115,7 +133,7 @@ void Process::Stop() { } void Process::SupervisorPause() { - std::lock_guard lock(thread_mutex); + std::scoped_lock lock(thread_mutex); for (auto thread : threads) thread->SupervisorPause(); @@ -124,7 +142,7 @@ void Process::SupervisorPause() { } void Process::SupervisorResume() { - std::lock_guard lock(thread_mutex); + std::scoped_lock lock(thread_mutex); for (auto thread : threads) thread->SupervisorResume(); @@ -133,23 +151,12 @@ void Process::SupervisorResume() { } void Process::CleanUp() { - // Heap memory - if (heap_mem) { - delete heap_mem; - heap_mem = nullptr; - } - - // Executable memories - for (auto mem : executable_mems) - delete mem; executable_mems.clear(); - - // Main thread stack memory - if (main_thread_stack_mem) - delete main_thread_stack_mem; + main_thread_stack_mem = nullptr; + heap_mem = nullptr; // Main thread - if (main_thread) { + if (main_thread != nullptr) { main_thread->Release(); main_thread = nullptr; } diff --git a/src/core/horizon/kernel/process.hpp b/src/core/horizon/kernel/process.hpp index f03ee2db..11f8d2c3 100644 --- a/src/core/horizon/kernel/process.hpp +++ b/src/core/horizon/kernel/process.hpp @@ -4,6 +4,7 @@ #include "core/horizon/kernel/synchronization_object.hpp" #include "core/horizon/kernel/thread.hpp" #include "core/hw/tegra_x1/cpu/memory.hpp" +#include "core/hw/tegra_x1/gpu/gmmu.hpp" // TODO: remove dependency #include "core/horizon/kernel/guest_thread.hpp" @@ -12,10 +13,6 @@ namespace hydra::hw::tegra_x1::cpu { class IMmu; } // namespace hydra::hw::tegra_x1::cpu -namespace hydra::hw::tegra_x1::gpu { -class GMmu; -} // namespace hydra::hw::tegra_x1::gpu - namespace hydra::horizon::kernel { enum class ProcessState { @@ -38,7 +35,9 @@ struct CodeSet { class Process : public SynchronizationObject { public: - Process(System& system_, const std::string_view debug_name = "Process"); + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::Process; + + Process(System& system_, std::string_view debug_name = "Process"); ~Process() override; // Memory @@ -48,6 +47,7 @@ class Process : public SynchronizationObject { CodeSet code_set, vaddr_t& out_base); hw::tegra_x1::cpu::IMemory* CreateTlsMemory(vaddr_t& base); void CreateStackMemory(u64 stack_size); + void ResizeHeap(u64 size); // Thread handle_id_t SetMainThread(GuestThread* thread) { @@ -56,13 +56,12 @@ class Process : public SynchronizationObject { } void RegisterThread(IThread* thread) { - std::lock_guard lock(thread_mutex); + std::scoped_lock lock(thread_mutex); threads.push_back(thread); } void UnregisterThread(IThread* thread) { - std::lock_guard lock(thread_mutex); - threads.erase(std::remove(threads.begin(), threads.end(), thread), - threads.end()); + std::scoped_lock lock(thread_mutex); + std::erase(threads, thread); // Signal if (threads.empty()) @@ -76,7 +75,7 @@ class Process : public SynchronizationObject { void SupervisorResume(); bool IsRunning() { - std::lock_guard lock(thread_mutex); + std::scoped_lock lock(thread_mutex); return !threads.empty(); } @@ -87,7 +86,7 @@ class Process : public SynchronizationObject { // Handles template T* GetHandle(handle_id_t handle_id) { - static_assert(std::is_base_of::value, + static_assert(std::is_base_of_v, "T must be derived from AutoObject"); if (handle_id == INVALID_HANDLE_ID) @@ -105,25 +104,22 @@ class Process : public SynchronizationObject { obj = handle_pool.Get(handle_id); } - auto cast_obj = dynamic_cast(obj); - ASSERT_DEBUG(cast_obj != nullptr, Kernel, "Invalid handle type"); - - return cast_obj; + return static_cast(obj); } handle_id_t AddHandleNoRetain(AutoObject* obj) { - if (!obj) [[unlikely]] + if (obj == nullptr) [[unlikely]] return INVALID_HANDLE_ID; - return handle_pool.Add(obj); + return handle_pool.Insert(obj); } handle_id_t AddHandle(AutoObject* obj) { - if (!obj) [[unlikely]] + if (obj == nullptr) [[unlikely]] return INVALID_HANDLE_ID; obj->Retain(); - return handle_pool.Add(obj); + return handle_pool.Insert(obj); } void FreeHandle(handle_id_t handle_id) { @@ -135,11 +131,14 @@ class Process : public SynchronizationObject { handle_pool.Free(handle_id); } + hw::tegra_x1::cpu::IMmu* GetMmu() const { return mmu.get(); } + hw::tegra_x1::cpu::IMemory* GetHeapMemory() const { return heap_mem.get(); } + private: System& system; - hw::tegra_x1::cpu::IMmu* mmu; - hw::tegra_x1::gpu::GMmu* gmmu; + std::unique_ptr mmu; + hw::tegra_x1::gpu::GMmu gmmu; AppletState applet_state; @@ -150,9 +149,9 @@ class Process : public SynchronizationObject { std::array random_entropy; // Memory - hw::tegra_x1::cpu::IMemory* heap_mem{nullptr}; - std::vector executable_mems; - hw::tegra_x1::cpu::IMemory* main_thread_stack_mem{nullptr}; + std::vector> executable_mems; + std::unique_ptr main_thread_stack_mem; + std::unique_ptr heap_mem; vaddr_t tls_mem_base{TLS_REGION.GetBegin()}; @@ -172,14 +171,12 @@ class Process : public SynchronizationObject { void SignalStateChange(ProcessState new_state); public: - GETTER(mmu, GetMmu); - GETTER(gmmu, GetGMmu); + REF_GETTER(gmmu, GetGMmu); REF_GETTER(applet_state, GetAppletState); GETTER_AND_SETTER(title_id, GetTitleID, SetTitleID); GETTER_AND_SETTER(system_resource_size, GetSystemResourceSize, SetSystemResourceSize); CONST_REF_GETTER(random_entropy, GetRandomEntropy); - REF_GETTER(heap_mem, GetHeapMemory); GETTER(main_thread, GetMainThread); }; diff --git a/src/core/horizon/kernel/process_manager.cpp b/src/core/horizon/kernel/process_manager.cpp index 873314ef..ba1d9bb3 100644 --- a/src/core/horizon/kernel/process_manager.cpp +++ b/src/core/horizon/kernel/process_manager.cpp @@ -17,23 +17,22 @@ ProcessManager::~ProcessManager() { } Process* ProcessManager::CreateProcess(const std::string_view name) { - std::lock_guard lock(mutex); - Process* process = new Process(system, name); + std::scoped_lock lock(mutex); + auto process = new Process(system, name); processes.push_back(process); return process; } void ProcessManager::DestroyProcess(Process* process) { - std::lock_guard lock(mutex); - processes.erase(std::remove(processes.begin(), processes.end(), process), - processes.end()); + std::scoped_lock lock(mutex); + std::erase(processes, process); ASSERT(process->Release(), Kernel, "Attempting to destroy {} which has active references", process->GetDebugName()); } bool ProcessManager::HasRunningProcesses() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); for (auto process : processes) { if (process->IsRunning()) return true; diff --git a/src/core/horizon/kernel/shared_memory.cpp b/src/core/horizon/kernel/shared_memory.cpp index 4392fd3e..40eadb7f 100644 --- a/src/core/horizon/kernel/shared_memory.cpp +++ b/src/core/horizon/kernel/shared_memory.cpp @@ -5,11 +5,9 @@ namespace hydra::horizon::kernel { SharedMemory::SharedMemory(hw::tegra_x1::cpu::ICpu& cpu, u64 size, - const std::string_view debug_name) - : AutoObject(debug_name) { - memory = cpu.AllocateMemory(size); - - // Clear + std::string_view debug_name) + : AutoObject(TYPE_ID, debug_name), memory{cpu.AllocateMemory(size)} { + // Clear memory memset(reinterpret_cast(GetPtr()), 0, size); } @@ -18,7 +16,9 @@ SharedMemory::~SharedMemory() { delete memory; } void SharedMemory::MapToRange(hw::tegra_x1::cpu::IMmu* mmu, const Range range, MemoryPermission perm) { mmu->Map(range.GetBegin(), memory, - {MemoryType::Shared, MemoryAttribute::None, perm}); + {.type = MemoryType::Shared, + .attr = MemoryAttribute::None, + .perm = perm}); } uptr SharedMemory::GetPtr() const { return memory->GetPtr(); } diff --git a/src/core/horizon/kernel/shared_memory.hpp b/src/core/horizon/kernel/shared_memory.hpp index 24d552af..69a27b91 100644 --- a/src/core/horizon/kernel/shared_memory.hpp +++ b/src/core/horizon/kernel/shared_memory.hpp @@ -13,8 +13,10 @@ namespace hydra::horizon::kernel { class SharedMemory : public AutoObject { public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::SharedMemory; + SharedMemory(hw::tegra_x1::cpu::ICpu& cpu, u64 size, - const std::string_view debug_name = "SharedMemory"); + std::string_view debug_name = "SharedMemory"); ~SharedMemory() override; void MapToRange(hw::tegra_x1::cpu::IMmu* mmu, const Range range_, diff --git a/src/core/horizon/kernel/synchronization_object.cpp b/src/core/horizon/kernel/synchronization_object.cpp index da2eb56a..2e1c35a4 100644 --- a/src/core/horizon/kernel/synchronization_object.cpp +++ b/src/core/horizon/kernel/synchronization_object.cpp @@ -5,7 +5,7 @@ namespace hydra::horizon::kernel { void SynchronizationObject::AddWaitingThread(IThread* thread) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); if (signalled) thread->Resume(this); else @@ -13,12 +13,12 @@ void SynchronizationObject::AddWaitingThread(IThread* thread) { } void SynchronizationObject::RemoveWaitingThread(IThread* thread) { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); waiting_threads.Remove(thread); } -void SynchronizationObject::AddSignalCallback(signal_callback_fn_t callback) { - std::lock_guard lock(mutex); +void SynchronizationObject::AddSignalCallback(const signal_callback_fn_t& callback) { + std::scoped_lock lock(mutex); if (signalled) callback(); else @@ -26,7 +26,7 @@ void SynchronizationObject::AddSignalCallback(signal_callback_fn_t callback) { } void SynchronizationObject::Signal() { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); if (signalled) return; diff --git a/src/core/horizon/kernel/synchronization_object.hpp b/src/core/horizon/kernel/synchronization_object.hpp index d999b983..00a5907f 100644 --- a/src/core/horizon/kernel/synchronization_object.hpp +++ b/src/core/horizon/kernel/synchronization_object.hpp @@ -6,18 +6,17 @@ namespace hydra::horizon::kernel { class IThread; -typedef std::function signal_callback_fn_t; +using signal_callback_fn_t = std::function; class SynchronizationObject : public AutoObject { public: - SynchronizationObject( - bool signalled_ = false, - const std::string_view debug_name = "SynchronizationObject") - : AutoObject(debug_name), signalled{signalled_} {} + SynchronizationObject(AutoObjectTypeId type_id, bool signalled_ = false, + std::string_view debug_name = "SynchronizationObject") + : AutoObject(type_id, debug_name), signalled{signalled_} {} void AddWaitingThread(IThread* thread); void RemoveWaitingThread(IThread* thread); - void AddSignalCallback(signal_callback_fn_t callback); + void AddSignalCallback(const signal_callback_fn_t& callback); void Signal(); bool Clear(); diff --git a/src/core/horizon/kernel/thread.cpp b/src/core/horizon/kernel/thread.cpp index cb9fc891..5d192c98 100644 --- a/src/core/horizon/kernel/thread.cpp +++ b/src/core/horizon/kernel/thread.cpp @@ -5,17 +5,14 @@ namespace hydra::horizon::kernel { -IThread::~IThread() { - if (thread) { - // Request stop - state = ThreadState::Stopping; - thread->join(); - delete thread; +IThread::~IThread() noexcept { + if (!IsStoppingOrStopped()) { + Stop(); } } void IThread::Start() { - thread = new std::thread([&]() { + thread = std::jthread([&]() { tls_current_thread = this; GET_CURRENT_PROCESS_DEBUGGER().RegisterThisThread(GetDebugName()); @@ -64,7 +61,7 @@ bool IThread::ProcessMessages(i64 pause_timeout_ns) { } void IThread::SendMessage(ThreadMessage msg) { - std::lock_guard lock(msg_mutex); + std::scoped_lock lock(msg_mutex); msg_queue.push(msg); msg_cv.notify_all(); // TODO: notify one? } @@ -110,17 +107,17 @@ bool IThread::ProcessMessagesImpl() { } void IThread::AddMutexWaiter(IThread* waiter) { - std::lock_guard lock(mutex_wait_mutex); + std::scoped_lock lock(mutex_wait_mutex); mutex_wait_list.AddLast(waiter); } void IThread::RemoveMutexWaiter(IThread* waiter) { - std::lock_guard lock(mutex_wait_mutex); + std::scoped_lock lock(mutex_wait_mutex); mutex_wait_list.Remove(waiter); } IThread* IThread::RelinquishMutex(uptr mutex_addr, u32& out_waiter_count) { - std::lock_guard lock(mutex_wait_mutex); + std::scoped_lock lock(mutex_wait_mutex); // Find a new owner IThread* new_owner = nullptr; @@ -134,7 +131,7 @@ IThread* IThread::RelinquishMutex(uptr mutex_addr, u32& out_waiter_count) { } waiter_node = mutex_wait_list.Remove(waiter_node); - if (new_owner) { + if (new_owner != nullptr) { new_owner->AddMutexWaiter(waiter); out_waiter_count++; } else { diff --git a/src/core/horizon/kernel/thread.hpp b/src/core/horizon/kernel/thread.hpp index 7811d109..706355cc 100644 --- a/src/core/horizon/kernel/thread.hpp +++ b/src/core/horizon/kernel/thread.hpp @@ -41,11 +41,13 @@ class IThread : public SynchronizationObject { friend class Kernel; public: + static constexpr AutoObjectTypeId TYPE_ID = AutoObjectTypeId::Thread; + IThread(Process* process_, i32 priority_, - const std::string_view debug_name = "Thread") - : SynchronizationObject(false, debug_name), process{process_}, + std::string_view debug_name = "Thread") noexcept + : SynchronizationObject(TYPE_ID, false, debug_name), process{process_}, priority{priority_} {} - virtual ~IThread() override; + ~IThread() noexcept override; void Start(); @@ -97,6 +99,10 @@ class IThread : public SynchronizationObject { return true; } + bool IsStoppingOrStopped() const { + return state == ThreadState::Stopping || state == ThreadState::Stopped; + } + virtual uptr GetTlsPtr() const = 0; protected: @@ -119,8 +125,6 @@ class IThread : public SynchronizationObject { private: i32 priority; - std::thread* thread{nullptr}; - ThreadState state{ThreadState::Created}; // TODO: atomic? std::mutex msg_mutex; @@ -139,6 +143,8 @@ class IThread : public SynchronizationObject { bool guest_pause{false}; std::optional sync_info{std::nullopt}; + std::jthread thread; + // Helpers // Messages diff --git a/src/core/horizon/kernel/transfer_memory.hpp b/src/core/horizon/kernel/transfer_memory.hpp index 09b0833d..df738045 100644 --- a/src/core/horizon/kernel/transfer_memory.hpp +++ b/src/core/horizon/kernel/transfer_memory.hpp @@ -6,9 +6,13 @@ namespace hydra::horizon::kernel { class TransferMemory : public AutoObject { public: + static constexpr AutoObjectTypeId TYPE_ID = + AutoObjectTypeId::TransferMemory; + TransferMemory(vaddr_t addr_, u64 size_, MemoryPermission perm_, - const std::string_view debug_name = "TransferMemory") - : AutoObject(debug_name), addr{addr_}, size{size_}, perm{perm_} {} + std::string_view debug_name = "TransferMemory") + : AutoObject(TYPE_ID, debug_name), addr{addr_}, size{size_}, + perm{perm_} {} private: vaddr_t addr; diff --git a/src/core/horizon/loader/homebrew_loader.cpp b/src/core/horizon/loader/homebrew_loader.cpp index 7313ceb0..fe6d66fd 100644 --- a/src/core/horizon/loader/homebrew_loader.cpp +++ b/src/core/horizon/loader/homebrew_loader.cpp @@ -154,8 +154,8 @@ class HomebrewThread : public kernel::GuestThread { ADD_ENTRY(t, IsMandatory, value0, value1) // Entries - ConfigEntry* entry = reinterpret_cast( - executable_ptr + config_offset); + auto entry = reinterpret_cast(executable_ptr + + config_offset); ADD_ENTRY_OPTIONAL(MainThreadHandle, self_handle, 0); ADD_ENTRY_OPTIONAL(ProcessHandle, self_process_handle, 0); @@ -245,7 +245,7 @@ void HomebrewLoader::LoadProcess(System& system, kernel::Process* process) { const auto nacp = stream->Read(); std::string title_name = nacp.GetApplicationTitle(SystemLanguage::AmericanEnglish).name; - std::replace(title_name.begin(), title_name.end(), ' ', '_'); + std::ranges::replace(title_name, ' ', '_'); delete stream; diff --git a/src/core/horizon/loader/homebrew_loader.hpp b/src/core/horizon/loader/homebrew_loader.hpp index ce91b09e..b1aa6c61 100644 --- a/src/core/horizon/loader/homebrew_loader.hpp +++ b/src/core/horizon/loader/homebrew_loader.hpp @@ -8,7 +8,7 @@ class System; namespace hydra::horizon::loader { -class HomebrewLoader : public LoaderBase { +class HomebrewLoader : public ILoader { public: HomebrewLoader(filesystem::IFile* file_); diff --git a/src/core/horizon/loader/loader_base.cpp b/src/core/horizon/loader/loader.cpp similarity index 63% rename from src/core/horizon/loader/loader_base.cpp rename to src/core/horizon/loader/loader.cpp index aee89d1d..7c5fe949 100644 --- a/src/core/horizon/loader/loader_base.cpp +++ b/src/core/horizon/loader/loader.cpp @@ -1,4 +1,4 @@ -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" #include @@ -24,12 +24,13 @@ uchar4* LoadImage(filesystem::IFile* file, u32& out_width, u32& out_height) { delete stream; - i32 w, h; + i32 w; + i32 h; i32 comp; auto data = reinterpret_cast(stbi_load_from_memory( raw_data.data(), static_cast(raw_data.size()), &w, &h, &comp, STBI_rgb_alpha)); - if (!data) { + if (data == nullptr) { LOG_ERROR(Loader, "Failed to load image"); return nullptr; } @@ -49,13 +50,15 @@ uchar4* LoadGIF(filesystem::IFile* file, delete stream; - i32 w, h, f; + i32 w; + i32 h; + i32 f; i32 comp; i32* delays_ms; auto data = reinterpret_cast(stbi_load_gif_from_memory( raw_data.data(), static_cast(raw_data.size()), &delays_ms, &w, &h, &f, &comp, STBI_rgb_alpha)); - if (!data) { + if (data == nullptr) { LOG_ERROR(Loader, "Failed to load GIF"); return nullptr; } @@ -66,7 +69,7 @@ uchar4* LoadGIF(filesystem::IFile* file, out_delays.reserve(static_cast(out_frame_count)); for (u32 i = 0; i < out_frame_count; i++) - out_delays.push_back(std::chrono::milliseconds(delays_ms[i])); + out_delays.emplace_back(delays_ms[i]); free(delays_ms); return data; @@ -74,65 +77,63 @@ uchar4* LoadGIF(filesystem::IFile* file, } // namespace -LoaderBase* LoaderBase::CreateFromPath(std::string_view path, - plugins::Manager* plugin_manager) { +std::optional +ILoader::CreateFromPath(std::string_view path, + std::optional plugin_manager_opt) { while (path.back() == '/') { path.remove_suffix(1); } // Check if the path exists - ASSERT_THROWING(std::filesystem::exists(path), Loader, - CreateFromPathError::DoesNotExist, - "Path \"{}\" does not exist", path); + if (!std::filesystem::exists(path)) + return std::nullopt; // Create loader - const auto ext = std::string_view(path).substr(path.find_last_of(".")); - horizon::loader::LoaderBase* loader{nullptr}; + const auto ext = std::string_view(path).substr(path.find_last_of('.')); if (ext == ".nx") { + if (!std::filesystem::is_directory(path)) + return std::nullopt; const auto dir = new horizon::filesystem::Directory(path); - loader = new horizon::loader::NxLoader(*dir); + return new horizon::loader::NxLoader(*dir); } else { + if (!std::filesystem::is_regular_file(path)) + return std::nullopt; const auto file = new horizon::filesystem::DiskFile(path); if (ext == ".nro") { // Assumes that all NROs are Homebrew - loader = new horizon::loader::HomebrewLoader(file); + return new horizon::loader::HomebrewLoader(file); } else if (ext == ".nso") { - loader = new horizon::loader::NsoLoader(file); + return new horizon::loader::NsoLoader(file); } else if (ext == ".nca") { - loader = new horizon::loader::NcaLoader(file); + return new horizon::loader::NcaLoader(file); } else { // Check if we need to create a temporary plugin manager - bool has_plugin_manager = (plugin_manager != nullptr); - if (!has_plugin_manager) - plugin_manager = new plugins::Manager(); + std::unique_ptr tmp_plugin_manager; + if (!plugin_manager_opt) + tmp_plugin_manager = std::make_unique(); + auto& plugin_manager = + (plugin_manager_opt ? *plugin_manager_opt.value() + : *tmp_plugin_manager); // First, check if any of the loader plugins supports this format - auto plugin = plugin_manager->FindPluginForFormat(ext.substr(1)); - ASSERT_THROWING( - plugin, Loader, CreateFromPathError::UnsupportedExtension, - "Unsupported extension \"{}\" (path: \"{}\")", ext, path); + auto plugin = plugin_manager.FindPluginForFormat(ext.substr(1)); + if (plugin == nullptr) + return std::nullopt; - loader = plugin->Load(path); - - if (!has_plugin_manager) - delete plugin_manager; + return plugin->Load(path); } } - - return loader; } -horizon::services::ns::ApplicationControlProperty* LoaderBase::LoadNacp() { - if (!nacp_file) +horizon::services::ns::ApplicationControlProperty* ILoader::LoadNacp() { + if (nacp_file == nullptr) return nullptr; auto stream = nacp_file->Open(filesystem::FileOpenFlags::Read); - ASSERT_THROWING( - stream->GetSize() == - sizeof(horizon::services::ns::ApplicationControlProperty), - Loader, LoadNacpError::InvalidSize, "Invalid NACP file size 0x{:x}", - stream->GetSize()); + ASSERT(stream->GetSize() == + sizeof(horizon::services::ns::ApplicationControlProperty), + Loader, "Invalid NACP file size 0x{:x}", stream->GetSize()); auto nacp = new horizon::services::ns::ApplicationControlProperty(); stream->ReadToRef(*nacp); @@ -141,38 +142,38 @@ horizon::services::ns::ApplicationControlProperty* LoaderBase::LoadNacp() { return nacp; } -uchar4* LoaderBase::LoadIcon(u32& out_width, u32& out_height) { - if (!icon_file) +uchar4* ILoader::LoadIcon(u32& out_width, u32& out_height) { + if (icon_file == nullptr) return nullptr; return LoadImage(icon_file, out_width, out_height); } -uchar4* LoaderBase::LoadNintendoLogo(u32& out_width, u32& out_height) { - if (!nintendo_logo_file) +uchar4* ILoader::LoadNintendoLogo(u32& out_width, u32& out_height) { + if (nintendo_logo_file == nullptr) return nullptr; return LoadImage(nintendo_logo_file, out_width, out_height); } uchar4* -LoaderBase::LoadStartupMovie(std::vector& out_delays, - u32& out_width, u32& out_height, - u32& out_frame_count) { - if (!startup_movie_file) +ILoader::LoadStartupMovie(std::vector& out_delays, + u32& out_width, u32& out_height, + u32& out_frame_count) { + if (startup_movie_file == nullptr) return nullptr; return LoadGIF(startup_movie_file, out_delays, out_width, out_height, out_frame_count); } -void LoaderBase::ExtractExeFs(std::string_view path) const { +void ILoader::ExtractExeFs(std::string_view path) const { ASSERT(exefs_dir != nullptr, Loader, "No exeFS"); LOG_INFO(Loader, "Exporting exeFS to \"{}\"", path); exefs_dir->Save(path); } -void LoaderBase::ExtractRomFs(std::string_view path) const { +void ILoader::ExtractRomFs(std::string_view path) const { ASSERT(romfs_entry != nullptr, Loader, "No romFS"); LOG_INFO(Loader, "Exporting romFS to \"{}\"", path); if (romfs_entry->IsDirectory()) { @@ -184,7 +185,7 @@ void LoaderBase::ExtractRomFs(std::string_view path) const { } } -void LoaderBase::ExtractIcon(std::string_view path) const { +void ILoader::ExtractIcon(std::string_view path) const { ASSERT(icon_file != nullptr, Loader, "No icon"); LOG_INFO(Loader, "Exporting icon to \"{}\"", path); icon_file->Save(path); diff --git a/src/core/horizon/loader/loader_base.hpp b/src/core/horizon/loader/loader.hpp similarity index 81% rename from src/core/horizon/loader/loader_base.hpp rename to src/core/horizon/loader/loader.hpp index 1ea5c32e..3f15b3e3 100644 --- a/src/core/horizon/loader/loader_base.hpp +++ b/src/core/horizon/loader/loader.hpp @@ -18,25 +18,23 @@ namespace plugins { class Manager; } -class LoaderBase { +class ILoader { public: - enum class CreateFromPathError { - DoesNotExist, - UnsupportedExtension, - }; - static LoaderBase* - CreateFromPath(std::string_view path, - plugins::Manager* plugin_manager = nullptr); + static std::optional CreateFromPath( + std::string_view path, + std::optional plugin_manager_opt = std::nullopt); - virtual ~LoaderBase() = default; + ILoader() noexcept = default; + virtual ~ILoader() noexcept = default; + + MAKE_NON_COPYABLE(ILoader); + MAKE_DEFAULT_MOVABLE(ILoader); virtual u64 GetTitleID() const { return invalid(); } virtual void LoadProcess(System& system, kernel::Process* process) = 0; - enum class LoadNacpError { - InvalidSize, - }; horizon::services::ns::ApplicationControlProperty* LoadNacp(); + // TODO: return a vector uchar4* LoadIcon(u32& out_width, u32& out_height); uchar4* LoadNintendoLogo(u32& out_width, u32& out_height); uchar4* LoadStartupMovie(std::vector& out_delays, diff --git a/src/core/horizon/loader/nca_loader.cpp b/src/core/horizon/loader/nca_loader.cpp index b4e66b38..bfac201a 100644 --- a/src/core/horizon/loader/nca_loader.cpp +++ b/src/core/horizon/loader/nca_loader.cpp @@ -11,8 +11,8 @@ namespace hydra::horizon::loader { -NcaLoader::NcaLoader(const filesystem::ContentArchive& content_archive_) - : content_archive{content_archive_} { +NcaLoader::NcaLoader(filesystem::ContentArchive content_archive_) + : content_archive{std::move(content_archive_)} { // Nintendo logo auto res = content_archive.GetFile(NINTENDO_LOGO_PATH, nintendo_logo_file); if (res != filesystem::FsResult::Success) @@ -42,9 +42,8 @@ NcaLoader::NcaLoader(const filesystem::ContentArchive& content_archive_) delete stream; - ASSERT_THROWING(meta.magic == make_magic4('M', 'E', 'T', 'A'), Loader, - Error::InvalidNpdmMagic, "Invalid NPDM meta magic 0x{:08x}", - meta.magic); + ASSERT(meta.magic == make_magic4('M', 'E', 'T', 'A'), Loader, + "Invalid NPDM meta magic 0x{:08x}", meta.magic); // TODO: support 32-bit games if (!any(meta.flags & NpdmFlags::Is64BitInstruction)) { @@ -92,7 +91,7 @@ void NcaLoader::LoadProcess(System& system, kernel::Process* process) { } void NcaLoader::LoadCode(System& system, kernel::Process* process, - filesystem::Directory* dir) { + filesystem::Directory* dir) const { // HACK: if rtld is not present, use main as the entry point std::string entry_point = "rtld"; filesystem::IEntry* e; @@ -100,8 +99,8 @@ void NcaLoader::LoadCode(System& system, kernel::Process* process, entry_point = "main"; for (const auto& [filename, entry] : dir->GetEntries()) { - auto file = dynamic_cast(entry); - ASSERT(file, Loader, "Code entry is not a file"); + ASSERT(entry->IsFile(), Loader, "Code entry is not a file"); + auto file = static_cast(entry); if (filename == "main.npdm") { // Do nothing } else { diff --git a/src/core/horizon/loader/nca_loader.hpp b/src/core/horizon/loader/nca_loader.hpp index b6b78876..46f024a8 100644 --- a/src/core/horizon/loader/nca_loader.hpp +++ b/src/core/horizon/loader/nca_loader.hpp @@ -1,7 +1,7 @@ #pragma once #include "core/horizon/filesystem/content_archive.hpp" -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" namespace hydra { class System; @@ -9,15 +9,11 @@ class System; namespace hydra::horizon::loader { -class NcaLoader : public LoaderBase { +class NcaLoader : public ILoader { public: - enum class Error { - InvalidNpdmMagic, - }; - NcaLoader(filesystem::IFile* file) - : NcaLoader(std::move(filesystem::ContentArchive(file))) {} - NcaLoader(const filesystem::ContentArchive& content_archive_); + : NcaLoader(filesystem::ContentArchive(file)) {} + NcaLoader(filesystem::ContentArchive content_archive_); u64 GetTitleID() const override { return content_archive.GetTitleID(); } @@ -36,7 +32,7 @@ class NcaLoader : public LoaderBase { // Helpers void LoadCode(System& system, kernel::Process* process, - filesystem::Directory* dir); + filesystem::Directory* dir) const; }; } // namespace hydra::horizon::loader diff --git a/src/core/horizon/loader/nro_loader.cpp b/src/core/horizon/loader/nro_loader.cpp index 25de6675..ec1c16ce 100644 --- a/src/core/horizon/loader/nro_loader.cpp +++ b/src/core/horizon/loader/nro_loader.cpp @@ -50,9 +50,8 @@ NroLoader::NroLoader(filesystem::IFile* file_, const bool is_entry_point_) const auto header = stream->Read(); // Validate - ASSERT_THROWING(header.magic == make_magic4('N', 'R', 'O', '0'), Loader, - Error::InvalidMagic, "Invalid NRO magic \"{}\"", - header.magic); + ASSERT(header.magic == make_magic4('N', 'R', 'O', '0'), Loader, + "Invalid NRO magic \"{}\"", header.magic); size = header.size; sections[0] = header.GetSection(NroSectionType::Text); @@ -70,10 +69,10 @@ void NroLoader::LoadProcess(System& system, kernel::Process* process) { // Create executable memory // TODO: is the size correct? const auto set = kernel::CodeSet{ - GetExecutableSize() + 0x1000, // HACK: one extra page - Range::FromSize(sections[0].offset, sections[0].size), - Range::FromSize(sections[1].offset, sections[1].size), - Range::FromSize(sections[2].offset, sections[2].size)}; + .size=GetExecutableSize() + 0x1000, // HACK: one extra page + .code=Range::FromSize(sections[0].offset, sections[0].size), + .ro_data=Range::FromSize(sections[1].offset, sections[1].size), + .data=Range::FromSize(sections[2].offset, sections[2].size)}; // TODO: module name executable_ptr = process->CreateExecutableMemory("main.nro", set, executable_base); diff --git a/src/core/horizon/loader/nro_loader.hpp b/src/core/horizon/loader/nro_loader.hpp index c7db5ba6..957f3785 100644 --- a/src/core/horizon/loader/nro_loader.hpp +++ b/src/core/horizon/loader/nro_loader.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" namespace hydra::horizon::loader { @@ -9,12 +9,8 @@ struct NroSection { u32 size; }; -class NroLoader : public LoaderBase { +class NroLoader : public ILoader { public: - enum class Error { - InvalidMagic, - }; - NroLoader(filesystem::IFile* file_, const bool is_entry_point_); void LoadProcess(System& system, kernel::Process* process) override; diff --git a/src/core/horizon/loader/nso_loader.cpp b/src/core/horizon/loader/nso_loader.cpp index d7b4f37d..7e73c000 100644 --- a/src/core/horizon/loader/nso_loader.cpp +++ b/src/core/horizon/loader/nso_loader.cpp @@ -1,10 +1,10 @@ #include "core/horizon/loader/nso_loader.hpp" -#include "common/elf.h" #include "common/lz4.hpp" #include "core/debugger/debugger_manager.hpp" #include "core/horizon/kernel/kernel.hpp" #include "core/horizon/kernel/process.hpp" +#include "elf.h" namespace hydra::horizon::loader { @@ -91,25 +91,28 @@ NsoLoader::NsoLoader(filesystem::IFile* file_, const std::string_view name_, // Header const auto header = stream->Read(); - ASSERT_THROWING(header.magic == make_magic4('N', 'S', 'O', '0'), Loader, - Error::InvalidMagic, "Invalid NSO magic"); + ASSERT(header.magic == make_magic4('N', 'S', 'O', '0'), Loader, + "Invalid NSO magic"); text_offset = header.text.memory_offset; // Segments - segments[0] = {header.text, header.text_file_size, - any(header.flags & NsoFlags::TextCompressed)}; - segments[1] = {header.ro, header.ro_file_size, - any(header.flags & NsoFlags::RoCompressed)}; - segments[2] = {header.data, header.data_file_size, - any(header.flags & NsoFlags::DataCompressed)}; + segments[0] = {.seg = header.text, + .file_size = header.text_file_size, + .compressed = any(header.flags & NsoFlags::TextCompressed)}; + segments[1] = {.seg = header.ro, + .file_size = header.ro_file_size, + .compressed = any(header.flags & NsoFlags::RoCompressed)}; + segments[2] = {.seg = header.data, + .file_size = header.data_file_size, + .compressed = any(header.flags & NsoFlags::DataCompressed)}; segments[2].seg.size += header.bss_size; // Determine executable memory size - for (u32 i = 0; i < 3; i++) { + for (const auto& segment : segments) { executable_size = std::max( - executable_size, static_cast(segments[i].seg.memory_offset + - segments[i].seg.size)); + executable_size, + static_cast(segment.seg.memory_offset + segment.seg.size)); } LOG_DEBUG(Loader, "NSO: 0x{:08x} + 0x{:08x}, 0x{:08x} + 0x{:08x}, 0x{:08x} + " @@ -135,21 +138,20 @@ void NsoLoader::LoadProcess(System& system, kernel::Process* process) { auto stream = file->Open(filesystem::FileOpenFlags::Read); // Create executable memory - const auto set = - kernel::CodeSet{executable_size, - Range::FromSize(segments[0].seg.memory_offset, - segments[0].seg.size), - Range::FromSize(segments[1].seg.memory_offset, - segments[1].seg.size), - Range::FromSize(segments[2].seg.memory_offset, - segments[2].seg.size)}; + const auto set = kernel::CodeSet{ + .size = executable_size, + .code = Range::FromSize(segments[0].seg.memory_offset, + segments[0].seg.size), + .ro_data = Range::FromSize(segments[1].seg.memory_offset, + segments[1].seg.size), + .data = Range::FromSize(segments[2].seg.memory_offset, + segments[2].seg.size)}; vaddr_t base; auto ptr = process->CreateExecutableMemory(name, set, base); LOG_DEBUG(Loader, "Base: 0x{:08x}, size: 0x{:08x}", base, executable_size); // Segments - for (u32 i = 0; i < 3; i++) { - const auto& segment = segments[i]; + for (const auto& segment : segments) { read_segment(stream, ptr, segment.seg, segment.file_size, segment.compressed); } @@ -207,10 +209,10 @@ void NsoLoader::LoadProcess(System& system, kernel::Process* process) { if (symbol.st_shndx != 0) { DEBUGGER_MANAGER_INSTANCE.GetDebugger(process) .GetFunctionTable() - .RegisterSymbol( - {demangle(std::string(symbol_name)), - Range(base + symbol.st_value, - base + symbol.st_value + symbol.st_size)}); + .RegisterSymbol({.name = demangle(std::string(symbol_name)), + .guest_mem_range = Range( + base + symbol.st_value, + base + symbol.st_value + symbol.st_size)}); } } diff --git a/src/core/horizon/loader/nso_loader.hpp b/src/core/horizon/loader/nso_loader.hpp index 016c376f..b72b2ec1 100644 --- a/src/core/horizon/loader/nso_loader.hpp +++ b/src/core/horizon/loader/nso_loader.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" namespace hydra::horizon::loader { @@ -10,12 +10,8 @@ struct Segment { u32 size; }; -class NsoLoader : public LoaderBase { +class NsoLoader : public ILoader { public: - enum class Error { - InvalidMagic, - }; - NsoLoader(filesystem::IFile* file_, const std::string_view name_ = "main", const bool is_entry_point_ = true); diff --git a/src/core/horizon/loader/nsp_loader.cpp b/src/core/horizon/loader/nsp_loader.cpp index 60faf4d0..30e52512 100644 --- a/src/core/horizon/loader/nsp_loader.cpp +++ b/src/core/horizon/loader/nsp_loader.cpp @@ -2,29 +2,8 @@ namespace hydra::horizon::loader { -NspLoader::NspLoader(const filesystem::PartitionFilesystem& pfs_) : pfs(pfs_) { - /* - // TODO: ticket file - - // NCAs - // HACK: find the largest one - struct { - filesystem::IFile* file; - u64 size; - } largest_entry{nullptr, 0}; - for (const auto& [filename, entry] : pfs.GetEntries()) { - auto file = dynamic_cast(entry); - if (!file) - continue; - - if (file->GetSize() > largest_entry.size) - largest_entry = {file, file->GetSize()}; - } - - // TODO: check for encryption - program_nca_loader = new NcaLoader(largest_entry.file); - */ - +NspLoader::NspLoader(filesystem::PartitionFilesystem pfs_) + : pfs(std::move(pfs_)) { filesystem::IFile* main_file; const auto res = pfs.GetFile("main", main_file); if (res != filesystem::FsResult::Success) { diff --git a/src/core/horizon/loader/nsp_loader.hpp b/src/core/horizon/loader/nsp_loader.hpp index a6706646..d1d5f8d7 100644 --- a/src/core/horizon/loader/nsp_loader.hpp +++ b/src/core/horizon/loader/nsp_loader.hpp @@ -1,31 +1,28 @@ #pragma once #include "core/horizon/filesystem/partition_filesystem.hpp" -// #include "core/horizon/loader/nca_loader.hpp" #include "core/horizon/loader/nso_loader.hpp" namespace hydra::horizon::loader { -class NspLoader : public LoaderBase { +// HACK: assumes Homebrew NSP +class NspLoader : public ILoader { public: NspLoader(filesystem::IFile* file) - : NspLoader(std::move( - *filesystem::PartitionFilesystem().Initialize(file))) {} - NspLoader(const filesystem::PartitionFilesystem& pfs_); + : NspLoader( + *filesystem::PartitionFilesystem().Initialize(file)) {} + NspLoader(filesystem::PartitionFilesystem pfs_); - u64 GetTitleID() const override { - return invalid(); // program_nca_loader->GetTitleID(); - } + u64 GetTitleID() const override { return invalid(); } void LoadProcess(System& system, kernel::Process* process) override { - /*program_nca_loader*/ nso_loader->LoadProcess(system, process); + nso_loader->LoadProcess(system, process); } private: filesystem::PartitionFilesystem pfs; NsoLoader* nso_loader{nullptr}; - // NcaLoader* program_nca_loader{nullptr}; }; } // namespace hydra::horizon::loader diff --git a/src/core/horizon/loader/nx_loader.cpp b/src/core/horizon/loader/nx_loader.cpp index 3c8c5e39..6ed25eeb 100644 --- a/src/core/horizon/loader/nx_loader.cpp +++ b/src/core/horizon/loader/nx_loader.cpp @@ -111,9 +111,8 @@ void NxLoader::ParseNpdm() { delete stream; - ASSERT_THROWING(meta.magic == make_magic4('M', 'E', 'T', 'A'), Loader, - Error::InvalidNpdmMagic, "Invalid NPDM meta magic 0x{:08x}", - meta.magic); + ASSERT(meta.magic == make_magic4('M', 'E', 'T', 'A'), Loader, + "Invalid NPDM meta magic 0x{:08x}", meta.magic); // TODO: support 32-bit games if (!any(meta.flags & NpdmFlags::Is64BitInstruction)) { @@ -208,7 +207,7 @@ void NxLoader::FindIcon() { } void NxLoader::LoadCode(System& system, kernel::Process* process, - filesystem::Directory* exefs_dir) { + filesystem::Directory* exefs_dir) const { // HACK: if rtld is not present, use main as the entry point std::string entry_point = "rtld"; filesystem::IEntry* e; @@ -216,8 +215,8 @@ void NxLoader::LoadCode(System& system, kernel::Process* process, entry_point = "main"; for (const auto& [filename, entry] : exefs_dir->GetEntries()) { - auto file = dynamic_cast(entry); - ASSERT(file, Loader, "Code entry is not a file"); + ASSERT(entry->IsFile(), Loader, "Code entry is not a file"); + auto file = static_cast(entry); if (filename == "main.npdm") { // Do nothing } else { diff --git a/src/core/horizon/loader/nx_loader.hpp b/src/core/horizon/loader/nx_loader.hpp index 132d7b2b..eb91bbb5 100644 --- a/src/core/horizon/loader/nx_loader.hpp +++ b/src/core/horizon/loader/nx_loader.hpp @@ -1,7 +1,7 @@ #pragma once #include "core/horizon/filesystem/directory.hpp" -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" namespace hydra { class System; @@ -9,12 +9,8 @@ class System; namespace hydra::horizon::loader { -class NxLoader : public LoaderBase { +class NxLoader : public ILoader { public: - enum class Error { - InvalidNpdmMagic, - }; - NxLoader(const filesystem::Directory& dir_); u64 GetTitleID() const override { return title_id; } @@ -39,7 +35,7 @@ class NxLoader : public LoaderBase { void ParseNpdm(); void FindIcon(); void LoadCode(System& system, kernel::Process* process, - filesystem::Directory* exefs_dir); + filesystem::Directory* exefs_dir) const; }; } // namespace hydra::horizon::loader diff --git a/src/core/horizon/loader/plugins/api.hpp b/src/core/horizon/loader/plugins/api.hpp index e6e49ffd..71ae0c97 100644 --- a/src/core/horizon/loader/plugins/api.hpp +++ b/src/core/horizon/loader/plugins/api.hpp @@ -49,7 +49,7 @@ struct Slice { } }; -typedef u32 (*GetApiVersionFnT)(); +using GetApiVersionFnT = u32 (*)(); enum class QueryType : u32 { Name = 0, @@ -77,7 +77,7 @@ struct OptionConfig { }; }; -typedef Slice (*QueryFnT)(QueryType); +using QueryFnT = Slice (*)(QueryType); enum class CreateContextResult : u32 { Success = 0, @@ -90,12 +90,12 @@ struct Option { Slice value; }; -typedef ReturnValue (*CreateContextFnT)( +using CreateContextFnT = ReturnValue (*)( Slice); -typedef u32 (*DestroyContextFnT)(void*); +using DestroyContextFnT = u32 (*)(void*); -typedef void (*add_file)(void*, filesystem::Directory*, Slice, +using add_file = void (*)(void*, filesystem::Directory*, Slice, void*); enum class CreateLoaderFromFileResult : u32 { @@ -104,21 +104,21 @@ enum class CreateLoaderFromFileResult : u32 { UnsupportedFile = 2, }; -typedef ReturnValue ( - *CreateLoaderFromFileFnT)(void*, void*, add_file, void*, Slice); +using CreateLoaderFromFileFnT = ReturnValue ( + *)(void*, void*, add_file, void*, Slice); -typedef void (*LoaderDestroyFnT)(void*); +using LoaderDestroyFnT = void (*)(void*); -typedef void (*FileDestroyFnT)(void*); -typedef void* (*FileOpenFnT)(void*); -typedef u64 (*FileGetSizeFnT)(void*); +using FileDestroyFnT = void (*)(void*); +using FileOpenFnT = void* (*)(void*); +using FileGetSizeFnT = u64 (*)(void*); -typedef void (*StreamDestroyFnT)(void*); -typedef u64 (*StreamGetSeekFnT)(void*); -typedef void (*StreamSeekToFnT)(void*, u64); -typedef void (*StreamSeekByFnT)(void*, u64); -typedef u64 (*StreamGetSizeFnT)(void*); -typedef void (*StreamReadRawFnT)(void*, Slice); +using StreamDestroyFnT = void (*)(void*); +using StreamGetSeekFnT = u64 (*)(void*); +using StreamSeekToFnT = void (*)(void*, u64); +using StreamSeekByFnT = void (*)(void*, u64); +using StreamGetSizeFnT = u64 (*)(void*); +using StreamReadRawFnT = void (*)(void*, Slice); } // namespace hydra::horizon::loader::plugins::api diff --git a/src/core/horizon/loader/plugins/manager.cpp b/src/core/horizon/loader/plugins/manager.cpp index a860efee..6f368df0 100644 --- a/src/core/horizon/loader/plugins/manager.cpp +++ b/src/core/horizon/loader/plugins/manager.cpp @@ -17,21 +17,17 @@ void Manager::Refresh() { continue; } - try { - plugins.emplace_back(plugin_config.path, plugin_config.options); - } catch (Plugin::Error err) { - // TODO: error popup? - } catch (Plugin::ContextError err) { - // TODO: error popup? - } + (void)Plugin::Create(plugin_config.path, plugin_config.options) + .transform([this](Plugin plugin) { + plugins.emplace_back(std::move(plugin)); + }); } } Plugin* Manager::FindPluginForFormat(std::string_view format) { for (auto& plugin : plugins) { - if (std::find(plugin.supported_formats.begin(), - plugin.supported_formats.end(), - format) != plugin.supported_formats.end()) + if (std::ranges::find(plugin.supported_formats, format) != + plugin.supported_formats.end()) return &plugin; } diff --git a/src/core/horizon/loader/plugins/plugin.cpp b/src/core/horizon/loader/plugins/plugin.cpp index 8707b00e..b6917d19 100644 --- a/src/core/horizon/loader/plugins/plugin.cpp +++ b/src/core/horizon/loader/plugins/plugin.cpp @@ -49,7 +49,7 @@ class Loader : public NxLoader { public: Loader(Plugin& extension_, void* handle_, const filesystem::Directory& dir) : NxLoader(dir), plugin{extension_}, handle{handle_} {} - ~Loader() { + ~Loader() override { // HACK (void)plugin; (void)handle; @@ -73,56 +73,63 @@ void AddFile(void* plugin, filesystem::Directory* dir, } // namespace -Plugin::Plugin(const std::string& path) { - library = dlopen(path.data(), RTLD_LAZY); - ASSERT_THROWING(library, Loader, Error::LoadFailed, - "Failed to load plugin at path {}: {}", path, dlerror()); +std::expected Plugin::Create(const std::string& path) { + Plugin plugin; + + plugin.library = dlopen(path.data(), RTLD_LAZY); + if (plugin.library == nullptr) + return std::unexpected(Error::LoadFailed); // Functions - get_api_version = - LoadFunction(); - query = LoadFunction(); - create_context = - LoadFunction(); - destroy_context = - LoadFunction(); - create_loader_from_file = LoadFunction(); - loader_destroy = - LoadFunction(); - file_destroy = - LoadFunction(); - file_open = LoadFunction(); - file_get_size = - LoadFunction(); - stream_destroy = - LoadFunction(); - stream_get_seek = - LoadFunction(); - stream_seek_to = - LoadFunction(); - stream_seek_by = - LoadFunction(); - stream_get_size = - LoadFunction(); - stream_read_raw = - LoadFunction(); + plugin.get_api_version = plugin.LoadFunction(); + plugin.query = plugin.LoadFunction(); + plugin.create_context = plugin.LoadFunction(); + plugin.destroy_context = plugin.LoadFunction(); + plugin.create_loader_from_file = + plugin.LoadFunction(); + plugin.loader_destroy = plugin.LoadFunction(); + plugin.file_destroy = + plugin.LoadFunction(); + plugin.file_open = + plugin.LoadFunction(); + plugin.file_get_size = + plugin.LoadFunction(); + plugin.stream_destroy = plugin.LoadFunction(); + plugin.stream_get_seek = plugin.LoadFunction(); + plugin.stream_seek_to = + plugin + .LoadFunction(); + plugin.stream_seek_by = + plugin + .LoadFunction(); + plugin.stream_get_size = plugin.LoadFunction(); + plugin.stream_read_raw = plugin.LoadFunction(); // API version - ASSERT_THROWING(GetApiVersion() == 1, Loader, Error::InvalidApiVersion, - "Invalid API version"); + if (plugin.GetApiVersion() != 1) + return std::unexpected(Error::UnsupportedApiVersion); // Info - name = QueryString(api::QueryType::Name); - display_version = QueryString(api::QueryType::DisplayVersion); - supported_formats = split( - QueryString(api::QueryType::SupportedFormats), ','); - const auto api_option_configs_buffer = Query(api::QueryType::OptionConfigs); + plugin.name = plugin.QueryString(api::QueryType::Name); + plugin.display_version = plugin.QueryString(api::QueryType::DisplayVersion); + plugin.supported_formats = Split( + plugin.QueryString(api::QueryType::SupportedFormats), ','); + const auto api_option_configs_buffer = + plugin.Query(api::QueryType::OptionConfigs); const auto api_option_configs = std::span(reinterpret_cast( api_option_configs_buffer.data()), api_option_configs_buffer.size() / sizeof(api::OptionConfig)); - option_configs.reserve(api_option_configs.size()); + plugin.option_configs.reserve(api_option_configs.size()); for (const auto& api_config : api_option_configs) { OptionConfig config{ .name = std::string_view(api_config.name), @@ -133,51 +140,62 @@ Plugin::Plugin(const std::string& path) { switch (api_config.type) { case api::OptionType::Enumeration: - config.enum_value_names = split( + config.enum_value_names = Split( std::string_view(api_config.enum_value_names), ','); break; case api::OptionType::Path: - config.path_content_types = split( + config.path_content_types = Split( std::string_view(api_config.path_content_types), ','); break; default: break; } - option_configs.emplace_back(std::move(config)); + plugin.option_configs.emplace_back(std::move(config)); } LOG_INFO(Loader, "Loaded plugin \"{}\" (version: {}, formats: {}) at path \"{}\"", - name, display_version, supported_formats, path); -} + plugin.name, plugin.display_version, plugin.supported_formats, + path); -Plugin::Plugin(const std::string& path, - const std::map& options) - : Plugin(path) { - // Verify that all required options are present - for (const auto& config : option_configs) { - if (config.is_required) { - ASSERT_THROWING(options.contains(std::string(config.name)), Loader, - ContextError::InvalidOptions, - "Missing option \"{}\"", config.name); - } - } + return std::move(plugin); +} - // Create context - CreateContext(options); +std::expected +Plugin::Create(const std::string& path, + const std::map& options) { + return Create(path).and_then( + [=](Plugin plugin) -> std::expected { + // Verify that all required options are present + for (const auto& config : plugin.option_configs) { + if (config.is_required) { + if (!options.contains(std::string(config.name))) + return std::unexpected(Error::InvalidOptions); + } + } + + // Create context + ASSIGN_OR_RETURN_ERROR(plugin.context, + plugin.CreateContext(options)); + + return plugin; + }); } Plugin::~Plugin() { - if (context) + if (context != nullptr) DestroyContext(); - dlclose(library); + if (library != nullptr) + dlclose(library); } -NxLoader* Plugin::Load(std::string_view path) { +std::optional Plugin::Load(std::string_view path) { const auto root_dir = new filesystem::Directory(); - const auto handle = CreateLoaderFromFile(root_dir, path); - return new Loader(*this, handle, *root_dir); + return CreateLoaderFromFile(root_dir, path) + .transform([root_dir, this](void* handle) { + return new Loader(*this, handle, *root_dir); + }); } u64 Plugin::GetApiVersion() { return get_api_version(); } @@ -186,11 +204,11 @@ std::span Plugin::Query(api::QueryType what) { return query(what); } std::string_view Plugin::QueryString(api::QueryType what) { const auto buffer = Query(what); - return std::string_view(reinterpret_cast(buffer.data()), - buffer.size()); + return {reinterpret_cast(buffer.data()), buffer.size()}; } -void Plugin::CreateContext(const std::map& options) { +std::expected +Plugin::CreateContext(const std::map& options) { std::vector options_vec; options_vec.reserve(options.size()); for (const auto& [key, value] : options) { @@ -200,23 +218,21 @@ void Plugin::CreateContext(const std::map& options) { } const auto ret = create_context(api::Slice(std::span(options_vec))); - ASSERT_THROWING(ret.res == api::CreateContextResult::Success, Loader, - ContextError::CreationFailed, - "Failed to create context ({})", ret.res); + if (ret.res != api::CreateContextResult::Success || ret.value == nullptr) + return std::unexpected(Error::ContextCreationFailed); - context = ret.value; - ASSERT_THROWING(context, Loader, ContextError::CreationFailed, - "Failed to create context"); + return ret.value; } void Plugin::DestroyContext() { destroy_context(context); } -void* Plugin::CreateLoaderFromFile(filesystem::Directory* root_dir, - std::string_view path) { +std::optional +Plugin::CreateLoaderFromFile(filesystem::Directory* root_dir, + std::string_view path) { const auto ret = create_loader_from_file(context, this, AddFile, root_dir, api::Slice(std::span(path))); if (ret.res != api::CreateLoaderFromFileResult::Success) { - throw ret.res; + return std::nullopt; } return ret.value; diff --git a/src/core/horizon/loader/plugins/plugin.hpp b/src/core/horizon/loader/plugins/plugin.hpp index f5d73a61..b2502bbd 100644 --- a/src/core/horizon/loader/plugins/plugin.hpp +++ b/src/core/horizon/loader/plugins/plugin.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "core/horizon/loader/plugins/api.hpp" @@ -34,30 +35,49 @@ class Plugin { public: enum class Error { LoadFailed, - InvalidApiVersion, - }; - enum class ContextError { + UnsupportedApiVersion, InvalidOptions, - CreationFailed, + ContextCreationFailed, }; // HACK: need to accept const std::string& instead of std::string_view, as - // dlopen need a null-terminated string - Plugin(const std::string& path); - Plugin(const std::string& path, + // dlopen needs a null-terminated string + static std::expected Create(const std::string& path); + static std::expected + Create(const std::string& path, const std::map& options); + + Plugin() = default; ~Plugin(); - NxLoader* Load(std::string_view path); + MAKE_NON_COPYABLE(Plugin); + MAKE_MOVABLE(Plugin, library, std::exchange(other.library, nullptr), + get_api_version, other.get_api_version, query, other.query, + create_context, other.create_context, destroy_context, + other.destroy_context, create_loader_from_file, + other.create_loader_from_file, loader_destroy, + other.loader_destroy, file_destroy, other.file_destroy, + file_open, other.file_open, file_get_size, other.file_get_size, + stream_destroy, other.stream_destroy, stream_get_seek, + other.stream_get_seek, stream_seek_to, other.stream_seek_to, + stream_seek_by, other.stream_seek_by, stream_get_size, + other.stream_get_size, stream_read_raw, other.stream_read_raw, + name, other.name, display_version, other.display_version, + supported_formats, std::move(other.supported_formats), + option_configs, std::move(other.option_configs), context, + std::exchange(other.context, nullptr)); + + std::optional Load(std::string_view path); // API u64 GetApiVersion(); std::span Query(api::QueryType what); std::string_view QueryString(api::QueryType what); - void CreateContext(const std::map& options); + std::expected + CreateContext(const std::map& options); void DestroyContext(); - void* CreateLoaderFromFile(filesystem::Directory* root_dir, - std::string_view path); + std::optional CreateLoaderFromFile(filesystem::Directory* root_dir, + std::string_view path); void LoaderDestroy(void* loader); void FileDestroy(void* file); void* FileOpen(void* file); @@ -70,7 +90,7 @@ class Plugin { void StreamReadRaw(void* stream, std::span buffer); private: - void* library; + void* library{nullptr}; // Functions api::GetApiVersionFnT get_api_version; @@ -99,13 +119,9 @@ class Plugin { void* context{nullptr}; // Helpers - enum class GetFunctionError { - SymbolNotFound, - }; - template T LoadFunction() { - std::string_view symbol_name; + std::string symbol_name; switch (api_func) { case api::Function::GetApiVersion: symbol_name = "hydra_ext_get_api_version"; @@ -154,10 +170,9 @@ class Plugin { break; } - const auto func = dlsym(library, symbol_name.data()); - ASSERT_THROWING(func != nullptr, Loader, - GetFunctionError::SymbolNotFound, - "Failed to load symbol \"{}\"", symbol_name); + const auto func = dlsym(library, symbol_name.c_str()); + ASSERT(func != nullptr, Loader, "Failed to load symbol \"{}\"", + symbol_name); return reinterpret_cast(func); } diff --git a/src/core/horizon/os.cpp b/src/core/horizon/os.cpp index 06afa656..04c58a44 100644 --- a/src/core/horizon/os.cpp +++ b/src/core/horizon/os.cpp @@ -90,7 +90,7 @@ void RegisterServiceToPort(services::Server* server, if constexpr (std::is_same_v) debug_name = port_name; else - debug_name = u64_to_str(port_name); + debug_name = U64AsString(port_name); // Session auto server_port = new kernel::hipc::ServerPort( @@ -101,7 +101,7 @@ void RegisterServiceToPort(services::Server* server, fmt::format("\"{}\" port", debug_name)); // Register server side - server->RegisterPort(server_port, service_creator); + server->RegisterPort(server_port, std::move(service_creator)); // Register client side service_manager.RegisterPort(port_name, client_port); @@ -109,16 +109,16 @@ void RegisterServiceToPort(services::Server* server, uint2 RoundUpToNearestStandardResolution(uint2 surface_resolution) { // TODO: constexpr - static uint2 standard_resolutions[] = { - {1280, 720}, {1920, 1080}, {2560, 1440}, {3840, 2160}, {7680, 4320}}; - for (u32 i = 0; i < sizeof_array(standard_resolutions); i++) { - const auto& resolution = standard_resolutions[i]; + constexpr std::array standard_resolutions = { + uint2({1280, 720}), uint2({1920, 1080}), uint2({2560, 1440}), + uint2({3840, 2160}), uint2({7680, 4320})}; + for (auto resolution : standard_resolutions) { if (surface_resolution.x() <= resolution.x() && surface_resolution.y() <= resolution.y()) return resolution; } - return standard_resolutions[sizeof_array(standard_resolutions) - 1]; + return standard_resolutions.back(); } } // namespace diff --git a/src/core/horizon/os.hpp b/src/core/horizon/os.hpp index 5dd2ea7c..3f02803c 100644 --- a/src/core/horizon/os.hpp +++ b/src/core/horizon/os.hpp @@ -16,10 +16,6 @@ class ICore; namespace hydra::horizon { -namespace services::am { -class LibraryAppletController; -} - namespace ui { class IHandler; } @@ -33,6 +29,18 @@ class OS { void SetSurfaceResolution(uint2 resolution); uint2 GetDisplayResolution() const; + services::am::internal::LibraryAppletController& + GetLibraryAppletSelfController() { + return *library_applet_self_controller; + } + + void SetLibraryAppletSelfController( + services::am::internal::LibraryAppletController + library_applet_self_controller_) { + library_applet_self_controller = + std::move(library_applet_self_controller_); + } + private: System& system; @@ -52,8 +60,8 @@ class OS { services::timesrv::internal::TimeManager time_manager; services::irsensor::internal::IrSensorManager ir_sensor_manager; - services::am::internal::LibraryAppletController* - library_applet_self_controller{nullptr}; + std::optional + library_applet_self_controller; // Display uint2 surface_resolution; @@ -68,9 +76,6 @@ class OS { REF_GETTER(shared_font_manager, GetSharedFontManager); REF_GETTER(time_manager, GetTimeManager); REF_GETTER(ir_sensor_manager, GetIrSensorManager); - GETTER_AND_SETTER(library_applet_self_controller, - GetLibraryAppletSelfController, - SetLibraryAppletSelfController); }; } // namespace hydra::horizon diff --git a/src/core/horizon/services/account/internal/user.hpp b/src/core/horizon/services/account/internal/user.hpp index 8045261a..d6ce2198 100644 --- a/src/core/horizon/services/account/internal/user.hpp +++ b/src/core/horizon/services/account/internal/user.hpp @@ -42,9 +42,8 @@ class User { }; void SetNickname(const std::string_view nickname) { - ASSERT_THROWING(nickname.size() < NICKNAME_SIZE, Services, - SetNicknameError::SizeTooLarge, - "Nickname size ({}) too big", nickname.size()); + ASSERT(nickname.size() < NICKNAME_SIZE, Services, + "Nickname size ({}) too big", nickname.size()); std::memcpy(base.nickname, nickname.data(), nickname.size()); base.nickname[nickname.size()] = '\0'; NotifyEdit(); diff --git a/src/core/horizon/services/account/internal/user_manager.cpp b/src/core/horizon/services/account/internal/user_manager.cpp index 710e6997..d4ec16f3 100644 --- a/src/core/horizon/services/account/internal/user_manager.cpp +++ b/src/core/horizon/services/account/internal/user_manager.cpp @@ -28,8 +28,8 @@ struct HusrHeader { constexpr u64 AVATAR_UNCOMPRESSED_IMAGE_SIZE = 0x40000; constexpr u32 AVATAR_IMAGE_DIMENSIONS = 256; -static void jpg_to_memory(void* context, void* data, int len) { - std::vector* jpg_image = static_cast*>(context); +void jpg_to_memory(void* context, void* data, int len) { + auto jpg_image = static_cast*>(context); u8* jpg = static_cast(data); jpg_image->insert(jpg_image->end(), jpg, jpg + len); } @@ -95,9 +95,9 @@ uuid_t UserManager::CreateUser() { void UserManager::LoadSystemAvatars(filesystem::Filesystem& fs) { // Default avatar const auto default_image_path = - get_bundle_resource_path("default_avatar_image.png"); + GetBundleResourcePath("default_avatar_image.png"); avatars[DEFAULT_AVATAR_IMAGE_PATH] = { - new filesystem::DiskFile(default_image_path)}; + .file = new filesystem::DiskFile(default_image_path)}; // NCA filesystem::IFile* file; @@ -133,7 +133,7 @@ void UserManager::LoadSystemAvatars(filesystem::Filesystem& fs) { for (const auto& [name, entry] : character_dir->GetEntries()) { if (name.ends_with(".szs")) avatars[fmt::format(SYSTEM_AVATARS_PATH "/{}", name)] = { - static_cast(entry)}; + .file = static_cast(entry)}; } } @@ -144,8 +144,8 @@ const std::vector& UserManager::LoadAvatarImage(std::string_view path, if (it == avatars.end()) { if (path[0] != '$') { it = avatars - .insert( - {std::string(path), {new filesystem::DiskFile(path)}}) + .insert({std::string(path), + {.file = new filesystem::DiskFile(path)}}) .first; } else { LOG_WARN( @@ -242,23 +242,24 @@ void UserManager::Deserialize(uuid_t user_id) { const auto header = stream.Read(); // Validate - ASSERT_THROWING( - header.magic == HUSR_MAGIC, Horizon, Error::InvalidHusrMagic, - "Invalid HUSR magic 0x{:08x} for user {:032x}", header.magic, user_id); + ASSERT(header.magic == HUSR_MAGIC, Horizon, + "Invalid HUSR magic 0x{:08x} for user {:032x}", header.magic, + user_id); if (header.version < 2) { LOG_WARN(Horizon, "Unsupported HUSR version {} for user {:032x}, skipping", header.version, user_id); return; } - ASSERT_THROWING(header.version == CURRENT_HUSR_VERSION, Horizon, - Error::InvalidHusrVersion, - "Invalid HUSR version {} for user {:032x}", header.version, - user_id); - ASSERT_THROWING(header.header_size == sizeof(HusrHeader), Horizon, - Error::InvalidHusrHeaderSize, - "Invalid HUSR header size 0x{:x} for user {:032x}", - header.header_size, user_id); + if (header.version > CURRENT_HUSR_VERSION) { + LOG_WARN(Horizon, + "Unsupported HUSR version {} for user {:032x}, skipping", + header.version, user_id); + return; + } + ASSERT(header.header_size == sizeof(HusrHeader), Horizon, + "Invalid HUSR header size 0x{:x} for user {:032x}", + header.header_size, user_id); // Data const auto base = stream.Read(); @@ -292,9 +293,7 @@ void UserManager::PreloadAvatar(Avatar& avatar, bool is_compressed) { #define YAZ0_ASSERT(expr) \ { \ const auto res = expr; \ - ASSERT_THROWING(res == YAZ0_OK, Services, \ - PreloadAvatarError::LoadImageFailed, \ - #expr " failed: {}", res); \ + ASSERT(res == YAZ0_OK, Services, #expr " failed: {}", res); \ } Yaz0Stream* yaz0; YAZ0_ASSERT(yaz0Init(&yaz0)); @@ -310,23 +309,23 @@ void UserManager::PreloadAvatar(Avatar& avatar, bool is_compressed) { avatar.dimensions = AVATAR_IMAGE_DIMENSIONS; } else { // Load with STB image - i32 width, height; + i32 width; + i32 height; auto pixels = stbi_load_from_memory(raw.data(), static_cast(raw.size()), &width, &height, nullptr, 4); - if (!pixels) { + if (pixels == nullptr) { LOG_ERROR(Services, "Failed to load avatar image"); return; } // TODO: crop the image if the dimensions don't match - ASSERT_THROWING(width == height, Services, - PreloadAvatarError::ImageNotASquare, - "Avatar image is not a square ({}x{})", width, height); + ASSERT(width == height, Services, + "Avatar image is not a square ({}x{})", width, height); avatar.dimensions = static_cast(width); // TODO: avoid intermediate copy - u64 size = avatar.dimensions * avatar.dimensions * 4; + u64 size = static_cast(avatar.dimensions * avatar.dimensions * 4); avatar.data.resize(size); std::memcpy(avatar.data.data(), pixels, size); stbi_image_free(pixels); diff --git a/src/core/horizon/services/account/internal/user_manager.hpp b/src/core/horizon/services/account/internal/user_manager.hpp index 540ee6ae..7fa56b81 100644 --- a/src/core/horizon/services/account/internal/user_manager.hpp +++ b/src/core/horizon/services/account/internal/user_manager.hpp @@ -7,18 +7,12 @@ namespace hydra::horizon::services::account::internal { struct Avatar { filesystem::IFile* file; - std::vector data{}; + std::vector data; u32 dimensions{0}; }; class UserManager { public: - enum class Error { - InvalidHusrMagic, - InvalidHusrVersion, - InvalidHusrHeaderSize, - }; - UserManager(); ~UserManager() { Flush(); } @@ -76,7 +70,7 @@ class UserManager { LoadImageFailed, ImageNotASquare, }; - void PreloadAvatar(Avatar& avatar, bool is_compressed); + static void PreloadAvatar(Avatar& avatar, bool is_compressed); public: CONST_REF_GETTER(avatars, GetAvatars); diff --git a/src/core/horizon/services/am/application_functions.cpp b/src/core/horizon/services/am/application_functions.cpp index 9585b5e4..e98f4f73 100644 --- a/src/core/horizon/services/am/application_functions.cpp +++ b/src/core/horizon/services/am/application_functions.cpp @@ -20,11 +20,11 @@ IApplicationFunctions::PopLaunchParameter(kernel::Process* process, kernel::LaunchParameterKind kind) { LOG_DEBUG(Services, "Kind: {}", kind); - const auto data = process->GetAppletState().PopLaunchParameter(kind); + auto data = process->GetAppletState().PopLaunchParameter(kind); if (data.empty()) return MAKE_RESULT(Am, 1); // TODO: result code - AddService(*ctx, new IStorage(data)); + AddService(*ctx, new IStorage(std::move(data))); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/internal/library_applet_controller.hpp b/src/core/horizon/services/am/internal/library_applet_controller.hpp index 1b2469c5..9e7d8ec9 100644 --- a/src/core/horizon/services/am/internal/library_applet_controller.hpp +++ b/src/core/horizon/services/am/internal/library_applet_controller.hpp @@ -8,11 +8,15 @@ namespace hydra::horizon::services::am::internal { class StorageQueue { public: - ~StorageQueue() { + StorageQueue() noexcept = default; + ~StorageQueue() noexcept { for (auto data : queue) data->Release(); } + MAKE_NON_COPYABLE(StorageQueue); + MAKE_DEFAULT_MOVABLE(StorageQueue); + void PushData(IStorage* data) { data->Retain(); queue.push_back(data); @@ -32,13 +36,16 @@ class StorageQueue { class LibraryAppletController { public: - LibraryAppletController(const LibraryAppletMode mode_) - : mode{mode_}, state_changed_event{new kernel::Event( - false, "Library applet state changed event")}, - interactive_in_data_event{new kernel::Event( - false, "Library applet interactive in data event")}, - interactive_out_data_event{new kernel::Event( - false, "Library applet interactive out data event")} {} + LibraryAppletController(const LibraryAppletMode mode_) noexcept + : mode{mode_}, state_changed_event(std::make_unique( + false, "Library applet state changed event")), + interactive_in_data_event(std::make_unique( + false, "Library applet interactive in data event")), + interactive_out_data_event(std::make_unique( + false, "Library applet interactive out data event")) {} + + MAKE_NON_COPYABLE(LibraryAppletController); + MAKE_DEFAULT_MOVABLE(LibraryAppletController); // Data @@ -65,23 +72,23 @@ class LibraryAppletController { IStorage* PopInteractiveOutData() { return interactive_out_data.PopData(); } // Events - kernel::Event* GetStateChangedEvent() { return state_changed_event; } + kernel::Event& GetStateChangedEvent() { return *state_changed_event; } - kernel::Event* GetInteractiveInDataEvent() { - return interactive_in_data_event; + kernel::Event& GetInteractiveInDataEvent() { + return *interactive_in_data_event; } - kernel::Event* GetInteractiveOutDataEvent() { - return interactive_out_data_event; + kernel::Event& GetInteractiveOutDataEvent() { + return *interactive_out_data_event; } private: // TODO: use [[maybe_unused]] LibraryAppletMode mode; - kernel::Event* state_changed_event; - kernel::Event* interactive_in_data_event; - kernel::Event* interactive_out_data_event; + std::unique_ptr state_changed_event; + std::unique_ptr interactive_in_data_event; + std::unique_ptr interactive_out_data_event; StorageQueue in_data; StorageQueue out_data; diff --git a/src/core/horizon/services/am/library_applet_accessor.cpp b/src/core/horizon/services/am/library_applet_accessor.cpp index e72a1a3b..523ec46c 100644 --- a/src/core/horizon/services/am/library_applet_accessor.cpp +++ b/src/core/horizon/services/am/library_applet_accessor.cpp @@ -42,7 +42,7 @@ ILibraryAppletAccessor::~ILibraryAppletAccessor() { delete applet; } result_t ILibraryAppletAccessor::GetAppletStateChangedEvent( kernel::Process* process, OutHandle out_handle) { - out_handle = process->AddHandle(controller.GetStateChangedEvent()); + out_handle = process->AddHandle(&controller.GetStateChangedEvent()); return RESULT_SUCCESS; } @@ -54,9 +54,7 @@ result_t ILibraryAppletAccessor::Start(System* system) { result_t ILibraryAppletAccessor::GetResult() { return applet->GetResult(); } result_t ILibraryAppletAccessor::PushInData(IService* storage_) { - auto storage = dynamic_cast(storage_); - ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); - + auto storage = static_cast(storage_); controller.PushInData(storage); return RESULT_SUCCESS; } @@ -67,9 +65,7 @@ result_t ILibraryAppletAccessor::PopOutData(RequestContext* ctx) { } result_t ILibraryAppletAccessor::PushInteractiveInData(IService* storage_) { - auto storage = dynamic_cast(storage_); - ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); - + auto storage = static_cast(storage_); controller.PushInteractiveInData(storage); return RESULT_SUCCESS; } @@ -81,7 +77,7 @@ result_t ILibraryAppletAccessor::PopInteractiveOutData(RequestContext* ctx) { result_t ILibraryAppletAccessor::GetPopInteractiveOutDataEvent( kernel::Process* process, OutHandle out_handle) { - out_handle = process->AddHandle(controller.GetInteractiveOutDataEvent()); + out_handle = process->AddHandle(&controller.GetInteractiveOutDataEvent()); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/library_applet_accessor.hpp b/src/core/horizon/services/am/library_applet_accessor.hpp index b9295e11..7b58ca58 100644 --- a/src/core/horizon/services/am/library_applet_accessor.hpp +++ b/src/core/horizon/services/am/library_applet_accessor.hpp @@ -15,7 +15,7 @@ class IStorage; class ILibraryAppletAccessor : public IService { public: ILibraryAppletAccessor(const AppletId id, const LibraryAppletMode mode); - ~ILibraryAppletAccessor(); + ~ILibraryAppletAccessor() override; protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, diff --git a/src/core/horizon/services/am/library_applet_creator.cpp b/src/core/horizon/services/am/library_applet_creator.cpp index 805772a4..8705680f 100644 --- a/src/core/horizon/services/am/library_applet_creator.cpp +++ b/src/core/horizon/services/am/library_applet_creator.cpp @@ -21,8 +21,7 @@ result_t ILibraryAppletCreator::CreateLibraryApplet(RequestContext* ctx, result_t ILibraryAppletCreator::CreateStorage(RequestContext* ctx, i64 size) { LOG_DEBUG(Services, "Size: {}", size); - const auto ptr = reinterpret_cast(malloc(static_cast(size))); - AddService(*ctx, new IStorage(std::span{ptr, static_cast(size)})); + AddService(*ctx, new IStorage(std::vector(static_cast(size)))); return RESULT_SUCCESS; } @@ -34,7 +33,8 @@ result_t ILibraryAppletCreator::CreateTransferMemoryStorage( auto tmem = process->GetHandle(tmem_handle); const auto ptr = reinterpret_cast(process->GetMmu()->UnmapAddr(tmem->GetAddress())); - AddService(*ctx, new IStorage(std::span{ptr, static_cast(size)})); + std::vector data(ptr, ptr + static_cast(size)); + AddService(*ctx, new IStorage(std::move(data))); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/library_applet_self_accessor.cpp b/src/core/horizon/services/am/library_applet_self_accessor.cpp index cca68c58..4f432831 100644 --- a/src/core/horizon/services/am/library_applet_self_accessor.cpp +++ b/src/core/horizon/services/am/library_applet_self_accessor.cpp @@ -17,32 +17,28 @@ DEFINE_SERVICE_COMMAND_TABLE(ILibraryAppletSelfAccessor, 0, PopInData, 1, result_t ILibraryAppletSelfAccessor::PopInData(RequestContext* ctx, System* system) { - AddService(*ctx, CONTROLLER->PopInData()->Retain()); + AddService(*ctx, CONTROLLER.PopInData()->Retain()); return RESULT_SUCCESS; } result_t ILibraryAppletSelfAccessor::PushOutData(System* system, IService* storage_) { - auto storage = dynamic_cast(storage_); - ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); - - CONTROLLER->PushOutData(storage); + auto storage = static_cast(storage_); + CONTROLLER.PushOutData(storage); return RESULT_SUCCESS; } result_t ILibraryAppletSelfAccessor::PopInteractiveInData(RequestContext* ctx, System* system) { - AddService(*ctx, CONTROLLER->PopInteractiveInData()->Retain()); + AddService(*ctx, CONTROLLER.PopInteractiveInData()->Retain()); return RESULT_SUCCESS; } result_t ILibraryAppletSelfAccessor::PushInteractiveOutData(System* system, IService* storage_) { - auto storage = dynamic_cast(storage_); - ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); - - CONTROLLER->PushInteractiveOutData(storage); + auto storage = static_cast(storage_); + CONTROLLER.PushInteractiveOutData(storage); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/session.hpp b/src/core/horizon/services/am/session.hpp index d2f8cc2b..f01611a1 100644 --- a/src/core/horizon/services/am/session.hpp +++ b/src/core/horizon/services/am/session.hpp @@ -8,8 +8,6 @@ enum class PerformanceMode : i32 { Invalid = -1, Normal = 0, Boost = 1, - - Count, }; class ISession : public IService { @@ -18,7 +16,7 @@ class ISession : public IService { u32 id) override; private: - u32 performance_configs[static_cast(PerformanceMode::Count)] = { + std::array performance_configs = { 0x20004, 0x92220007}; // TODO: what should this be? // Commands diff --git a/src/core/horizon/services/am/storage.hpp b/src/core/horizon/services/am/storage.hpp index ff1dc21d..2db14cad 100644 --- a/src/core/horizon/services/am/storage.hpp +++ b/src/core/horizon/services/am/storage.hpp @@ -6,24 +6,22 @@ namespace hydra::horizon::services::am { class IStorage : public IService { public: - IStorage(std::span data_) : data{data_} {} + IStorage(std::vector data_) : data{std::move(data_)} {} template - IStorage(T* ptr) : data(reinterpret_cast(ptr), sizeof(T)) {} - - ~IStorage() override { - // TODO: uncomment - // free(data.data()); + IStorage(const T& data_) { + data.resize(sizeof(T)); + std::memcpy(data.data(), &data_, sizeof(T)); } - std::span GetData() const { return data; } + std::span GetData() { return data; } protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, u32 id) override; private: - std::span data; + std::vector data; // Commands result_t Open(RequestContext* ctx); diff --git a/src/core/horizon/services/am/storage_accessor.cpp b/src/core/horizon/services/am/storage_accessor.cpp index 2c336013..f42ade92 100644 --- a/src/core/horizon/services/am/storage_accessor.cpp +++ b/src/core/horizon/services/am/storage_accessor.cpp @@ -17,7 +17,7 @@ result_t IStorageAccessor::Write(i64 offset, const u64 size = data.size() - static_cast(offset); const auto span = buffer.stream->ReadSpan(size); - std::copy(span.begin(), span.end(), data.data() + offset); + std::ranges::copy(span, data.data() + offset); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/audio/audio_device.cpp b/src/core/horizon/services/audio/audio_device.cpp index b128030c..86110268 100644 --- a/src/core/horizon/services/audio/audio_device.cpp +++ b/src/core/horizon/services/audio/audio_device.cpp @@ -77,8 +77,8 @@ result_t IAudioDevice::GetActiveAudioDeviceNameAuto( return GetActiveAudioDeviceNameImpl(out_buffer.stream); } -result_t IAudioDevice::ListAudioDeviceNameImpl(i32* out_count, - io::MemoryStream* out_stream) { +result_t IAudioDevice::ListAudioDeviceNameImpl( + i32* out_count, std::optional out_stream) { LOG_FUNC_STUBBED(Services); // HACK @@ -87,9 +87,8 @@ result_t IAudioDevice::ListAudioDeviceNameImpl(i32* out_count, return RESULT_SUCCESS; } -result_t -IAudioDevice::SetAudioDeviceOutputVolumeImpl(f32 volume, - io::MemoryStream* in_name_stream) { +result_t IAudioDevice::SetAudioDeviceOutputVolumeImpl( + f32 volume, std::optional in_name_stream) { const auto device_name_raw = in_name_stream->ReadPtr(); const std::string device_name(device_name_raw->name); LOG_FUNC_WITH_ARGS_STUBBED(Services, "name: {}, volume: {}", device_name, @@ -98,9 +97,8 @@ IAudioDevice::SetAudioDeviceOutputVolumeImpl(f32 volume, return RESULT_SUCCESS; } -result_t -IAudioDevice::GetAudioDeviceOutputVolumeImpl(io::MemoryStream* in_name_stream, - f32* out_volume) { +result_t IAudioDevice::GetAudioDeviceOutputVolumeImpl( + std::optional in_name_stream, f32* out_volume) { const auto device_name_raw = in_name_stream->ReadPtr(); const std::string device_name(device_name_raw->name); LOG_FUNC_WITH_ARGS_STUBBED(Services, "name: {}", device_name); @@ -110,8 +108,8 @@ IAudioDevice::GetAudioDeviceOutputVolumeImpl(io::MemoryStream* in_name_stream, return RESULT_SUCCESS; } -result_t -IAudioDevice::GetActiveAudioDeviceNameImpl(io::MemoryStream* out_stream) { +result_t IAudioDevice::GetActiveAudioDeviceNameImpl( + std::optional out_stream) { LOG_FUNC_STUBBED(Services); // HACK diff --git a/src/core/horizon/services/audio/audio_device.hpp b/src/core/horizon/services/audio/audio_device.hpp index 861adb1b..42c7da83 100644 --- a/src/core/horizon/services/audio/audio_device.hpp +++ b/src/core/horizon/services/audio/audio_device.hpp @@ -46,13 +46,15 @@ class IAudioDevice : public IService { GetActiveAudioDeviceNameAuto(OutBuffer out_buffer); // Impl - result_t ListAudioDeviceNameImpl(i32* out_count, - io::MemoryStream* out_stream); - result_t SetAudioDeviceOutputVolumeImpl(f32 volume, - io::MemoryStream* in_name_stream); - result_t GetAudioDeviceOutputVolumeImpl(io::MemoryStream* in_name_stream, - f32* out_volume); - result_t GetActiveAudioDeviceNameImpl(io::MemoryStream* out_stream); + result_t + ListAudioDeviceNameImpl(i32* out_count, + std::optional out_stream); + result_t SetAudioDeviceOutputVolumeImpl( + f32 volume, std::optional in_name_stream); + result_t GetAudioDeviceOutputVolumeImpl( + std::optional in_name_stream, f32* out_volume); + result_t + GetActiveAudioDeviceNameImpl(std::optional out_stream); }; } // namespace hydra::horizon::services::audio diff --git a/src/core/horizon/services/audio/audio_out.cpp b/src/core/horizon/services/audio/audio_out.cpp index ca8a4b0b..352b8b75 100644 --- a/src/core/horizon/services/audio/audio_out.cpp +++ b/src/core/horizon/services/audio/audio_out.cpp @@ -75,10 +75,9 @@ result_t IAudioOut::GetReleasedAudioOutBuffersAuto( return GetReleasedAudioOutBuffersImpl(out_count, out_buffers_buffer.stream); } -result_t -IAudioOut::AppendAudioOutBufferImpl(kernel::Process* process, - u64 buffer_client_ptr, - io::MemoryStream* in_buffer_stream) { +result_t IAudioOut::AppendAudioOutBufferImpl( + kernel::Process* process, u64 buffer_client_ptr, + std::optional in_buffer_stream) { const auto buffer = in_buffer_stream->Read(); // TODO: correct? const auto ptr = reinterpret_cast( @@ -90,7 +89,7 @@ IAudioOut::AppendAudioOutBufferImpl(kernel::Process* process, } result_t IAudioOut::GetReleasedAudioOutBuffersImpl( - u32* out_count, io::MemoryStream* out_buffers_stream) { + u32* out_count, std::optional out_buffers_stream) { std::unique_lock lock(buffer_mutex); *out_count = static_cast(released_buffers.size()); diff --git a/src/core/horizon/services/audio/audio_out.hpp b/src/core/horizon/services/audio/audio_out.hpp index 427daac5..0c3d6c40 100644 --- a/src/core/horizon/services/audio/audio_out.hpp +++ b/src/core/horizon/services/audio/audio_out.hpp @@ -52,12 +52,11 @@ class IAudioOut : public IService { u32* out_count, OutBuffer out_buffers_buffer); // Impl - result_t AppendAudioOutBufferImpl(kernel::Process* process, - u64 buffer_client_ptr, - io::MemoryStream* in_buffer_stream); result_t - GetReleasedAudioOutBuffersImpl(u32* out_count, - io::MemoryStream* out_buffers_stream); + AppendAudioOutBufferImpl(kernel::Process* process, u64 buffer_client_ptr, + std::optional in_buffer_stream); + result_t GetReleasedAudioOutBuffersImpl( + u32* out_count, std::optional out_buffers_stream); }; } // namespace hydra::horizon::services::audio diff --git a/src/core/horizon/services/audio/audio_out_manager.cpp b/src/core/horizon/services/audio/audio_out_manager.cpp index c0f74f8d..89e74273 100644 --- a/src/core/horizon/services/audio/audio_out_manager.cpp +++ b/src/core/horizon/services/audio/audio_out_manager.cpp @@ -44,8 +44,8 @@ result_t IAudioOutManager::OpenAudioOutAuto( out_device_name_buffer.stream); } -result_t IAudioOutManager::ListAudioOutsImpl(u32* out_count, - io::MemoryStream* out_stream) { +result_t IAudioOutManager::ListAudioOutsImpl( + u32* out_count, std::optional out_stream) { (void)out_stream; LOG_FUNC_STUBBED(Services); @@ -57,9 +57,9 @@ result_t IAudioOutManager::ListAudioOutsImpl(u32* out_count, result_t IAudioOutManager::OpenAudioOutImpl( RequestContext* ctx, u32 sample_rate, u16 channel_count, u64 aruid, - io::MemoryStream* in_device_name_stream, u32* out_sample_rate, + std::optional in_device_name_stream, u32* out_sample_rate, u32* out_channel_count, PcmFormat* out_format, AudioOutState* out_state, - io::MemoryStream* out_device_name_stream) { + std::optional out_device_name_stream) { (void)aruid; [[maybe_unused]] const auto device_name_in = diff --git a/src/core/horizon/services/audio/audio_out_manager.hpp b/src/core/horizon/services/audio/audio_out_manager.hpp index 44fa4464..488e7af0 100644 --- a/src/core/horizon/services/audio/audio_out_manager.hpp +++ b/src/core/horizon/services/audio/audio_out_manager.hpp @@ -33,13 +33,15 @@ class IAudioOutManager : public IService { OutBuffer out_device_name_buffer); // Impl - result_t ListAudioOutsImpl(u32* out_count, io::MemoryStream* out_stream); - result_t OpenAudioOutImpl(RequestContext* ctx, u32 sample_rate, - u16 channel_count, u64 aruid, - io::MemoryStream* in_device_name_stream, - u32* out_sample_rate, u32* out_channel_count, - PcmFormat* out_format, AudioOutState* out_state, - io::MemoryStream* out_device_name_stream); + result_t ListAudioOutsImpl(u32* out_count, + std::optional out_stream); + result_t + OpenAudioOutImpl(RequestContext* ctx, u32 sample_rate, u16 channel_count, + u64 aruid, + std::optional in_device_name_stream, + u32* out_sample_rate, u32* out_channel_count, + PcmFormat* out_format, AudioOutState* out_state, + std::optional out_device_name_stream); }; } // namespace hydra::horizon::services::audio diff --git a/src/core/horizon/services/audio/audio_renderer.cpp b/src/core/horizon/services/audio/audio_renderer.cpp index 1ed9419d..a681c007 100644 --- a/src/core/horizon/services/audio/audio_renderer.cpp +++ b/src/core/horizon/services/audio/audio_renderer.cpp @@ -7,6 +7,7 @@ namespace hydra::horizon::services::audio { namespace { +#pragma pack(push, 1) struct UpdateDataHeader { u32 revision; u32 behavior_size; @@ -21,7 +22,7 @@ struct UpdateDataHeader { u32 render_info_size; u32 _reserved[4]; u32 total_size; -} PACKED; +}; enum class MemPoolState : u32 { Invalid, @@ -38,12 +39,12 @@ struct MemPoolInfoIn { u64 size; MemPoolState state; u32 _padding[3]; -} PACKED; +}; struct MemPoolInfoOut { MemPoolState new_state; u32 _padding[3]; -} PACKED; +}; enum class VoicePlayState : u8 { Started = 0, @@ -56,7 +57,7 @@ struct BiquadFilter { u8 _padding; i16 numerator[3]; i16 denominator[2]; -} PACKED; +}; struct WaveBuffer { vaddr_t address; @@ -70,7 +71,7 @@ struct WaveBuffer { vaddr_t context_addr; u64 context_sz; u64 _padding2; -} PACKED; +}; struct VoiceInfoIn { u32 id; @@ -97,7 +98,7 @@ struct VoiceInfoIn { WaveBuffer wave_buffers[4]; u32 channel_ids[6]; u8 _padding3[24]; -} PACKED; +}; enum class EffectState : u8 { Enabled = 3, @@ -107,35 +108,36 @@ enum class EffectState : u8 { struct EffectInfoOutV1 { EffectState state; u8 _reserved[15]; -} PACKED; +}; struct SinkInfoOut { u32 last_written_offset; u32 _padding; u64 _reserved[3]; -} PACKED; +}; struct ErrorInfo { result_t result; u32 _padding; u64 extra_error_info; -} PACKED; +}; struct BehaviorInfoOut { ErrorInfo error_infos[10]; u32 error_info_count; u32 _reserved[3]; -} PACKED; +}; struct RenderInfoOut { u64 elapsed_frame_count; u64 _reserved; -} PACKED; +}; struct PerformanceInfoOut { u32 history_size; u32 _reserved[3]; -} PACKED; +}; +#pragma pack(pop) } // namespace @@ -203,9 +205,10 @@ result_t IAudioRenderer::RequestUpdateAuto( out_perf_buffer.stream); } -result_t IAudioRenderer::RequestUpdateImpl(io::MemoryStream* in_stream, - io::MemoryStream* out_stream, - io::MemoryStream* out_perf_stream) { +result_t IAudioRenderer::RequestUpdateImpl( + std::optional in_stream, + std::optional out_stream, + std::optional out_perf_stream) { ONCE(LOG_FUNC_STUBBED(Services)); // Header diff --git a/src/core/horizon/services/audio/audio_renderer.hpp b/src/core/horizon/services/audio/audio_renderer.hpp index 6b0e650b..613d3382 100644 --- a/src/core/horizon/services/audio/audio_renderer.hpp +++ b/src/core/horizon/services/audio/audio_renderer.hpp @@ -47,9 +47,9 @@ class IAudioRenderer : public IService { OutBuffer out_perf_buffer); // Impl - result_t RequestUpdateImpl(io::MemoryStream* in_stream, - io::MemoryStream* out_stream, - io::MemoryStream* out_perf_stream); + result_t RequestUpdateImpl(std::optional in_stream, + std::optional out_stream, + std::optional out_perf_stream); }; } // namespace hydra::horizon::services::audio diff --git a/src/core/horizon/services/audio/audio_renderer_manager.cpp b/src/core/horizon/services/audio/audio_renderer_manager.cpp index 3ea0f6fd..08f05c28 100644 --- a/src/core/horizon/services/audio/audio_renderer_manager.cpp +++ b/src/core/horizon/services/audio/audio_renderer_manager.cpp @@ -10,7 +10,7 @@ DEFINE_SERVICE_COMMAND_TABLE(IAudioRendererManager, 0, OpenAudioRenderer, 1, GetAudioDeviceServiceWithRevisionInfo) result_t IAudioRendererManager::OpenAudioRenderer( - RequestContext* ctx, aligned params, + RequestContext* ctx, Aligned params, u64 work_buffer_size, u64 aruid) { (void)aruid; @@ -25,13 +25,13 @@ IAudioRendererManager::GetWorkBufferSize(AudioRendererParameters params, LOG_FUNC_STUBBED(Services); u64 buffer_sz = align(4 * params.mix_buffer_count, 0x40u); - buffer_sz += params.submix_count * 1024; - buffer_sz += 0x940 * (params.submix_count + 1); - buffer_sz += 0x3F0 * params.voice_count; + buffer_sz += static_cast(params.submix_count * 1024); + buffer_sz += static_cast(0x940 * (params.submix_count + 1)); + buffer_sz += static_cast(0x3F0 * params.voice_count); buffer_sz += align(8 * (params.submix_count + 1), 0x10u); buffer_sz += align(8 * params.voice_count, 0x10u); - buffer_sz += align((0x3C0 * (params.sink_count + params.submix_count) + - 4 * params.sample_count) * + buffer_sz += align(((0x3C0 * (params.sink_count + params.submix_count)) + + (4 * params.sample_count)) * (params.mix_buffer_count + 6), 0x40u); @@ -39,8 +39,8 @@ IAudioRendererManager::GetWorkBufferSize(AudioRendererParameters params, params.revision)) { u32 count = params.submix_count + 1; u64 node_count = align(count, 0x40u); - u64 node_state_buffer_sz = 4 * (node_count * node_count) + - 0xC * node_count + 2 * (node_count / 8); + u64 node_state_buffer_sz = (4 * (node_count * node_count)) + + (0xC * node_count) + (2 * (node_count / 8)); u64 edge_matrix_buffer_sz = 0; node_count = align(count * count, 0x40u); if (node_count >> 31 != 0) { @@ -52,26 +52,29 @@ IAudioRendererManager::GetWorkBufferSize(AudioRendererParameters params, align(node_state_buffer_sz + edge_matrix_buffer_sz, 0x10ull); } - buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50; + buffer_sz += + (0x20 * (params.effect_count + (4 * params.voice_count))) + 0x50; if (IsAudioRendererFeatureSupported(AudioFeature::Splitter, params.revision)) { - buffer_sz += 0xE0 * params._unknown_x2c; - buffer_sz += 0x20 * params.splitter_count; + buffer_sz += static_cast(0xE0 * params._unknown_x2c); + buffer_sz += static_cast(0x20 * params.splitter_count); buffer_sz += align(4 * params._unknown_x2c, 0x10u); } - buffer_sz = align(buffer_sz, 0x40ull) + 0x170 * params.sink_count; - u64 output_sz = buffer_sz + 0x280 * params.sink_count + - 0x4B0 * params.effect_count + + buffer_sz = align(buffer_sz, 0x40ull) + + (static_cast(0x170 * params.sink_count)); + u64 output_sz = buffer_sz + (static_cast(0x280 * params.sink_count)) + + (static_cast(0x4B0 * params.effect_count)) + ((params.voice_count * 256) | 0x40); if (params.unknown_x1c >= 1) { - output_sz = align(((16 * params.sink_count + 16 * params.effect_count + - 16 * params.voice_count + 16) + - 0x658) * - (params.unknown_x1c + 1) + - 0xc0, - 0x40u) + - output_sz; + output_sz = + align(((((16 * params.sink_count) + (16 * params.effect_count) + + (16 * params.voice_count) + 16) + + 0x658) * + (params.unknown_x1c + 1)) + + 0xc0, + 0x40u) + + output_sz; } output_sz = align(output_sz + 0x1807e, 0x1000ull); diff --git a/src/core/horizon/services/audio/audio_renderer_manager.hpp b/src/core/horizon/services/audio/audio_renderer_manager.hpp index 2a7e462e..65635584 100644 --- a/src/core/horizon/services/audio/audio_renderer_manager.hpp +++ b/src/core/horizon/services/audio/audio_renderer_manager.hpp @@ -13,7 +13,7 @@ class IAudioRendererManager : public IService { private: // Commands result_t OpenAudioRenderer(RequestContext* ctx, - aligned params, + Aligned params, u64 work_buffer_size, u64 aruid); result_t GetWorkBufferSize(AudioRendererParameters params, u64* out_size); result_t GetAudioDeviceService(RequestContext* ctx, u64 aruid); diff --git a/src/core/horizon/services/codec/hardware_opus_decoder.cpp b/src/core/horizon/services/codec/hardware_opus_decoder.cpp index 1f134d69..555b43aa 100644 --- a/src/core/horizon/services/codec/hardware_opus_decoder.cpp +++ b/src/core/horizon/services/codec/hardware_opus_decoder.cpp @@ -14,8 +14,9 @@ result_t IHardwareOpusDecoder::DecodeInterleavedOld( } result_t IHardwareOpusDecoder::DecodeInterleavedImpl( - io::MemoryStream* in_opus_stream, i32* out_decoded_data_size, - i32* out_decoded_sample_count, io::MemoryStream* out_pcm_stream) { + std::optional in_opus_stream, i32* out_decoded_data_size, + i32* out_decoded_sample_count, + std::optional out_pcm_stream) { (void)in_opus_stream; (void)out_pcm_stream; ONCE(LOG_FUNC_STUBBED(Services)); diff --git a/src/core/horizon/services/codec/hardware_opus_decoder.hpp b/src/core/horizon/services/codec/hardware_opus_decoder.hpp index 437e4214..d7d00340 100644 --- a/src/core/horizon/services/codec/hardware_opus_decoder.hpp +++ b/src/core/horizon/services/codec/hardware_opus_decoder.hpp @@ -18,10 +18,11 @@ class IHardwareOpusDecoder : public IService { OutBuffer out_pcm_buffer); // Impl - result_t DecodeInterleavedImpl(io::MemoryStream* in_opus_stream, - i32* out_decoded_data_size, - i32* out_decoded_sample_count, - io::MemoryStream* out_pcm_stream); + result_t + DecodeInterleavedImpl(std::optional in_opus_stream, + i32* out_decoded_data_size, + i32* out_decoded_sample_count, + std::optional out_pcm_stream); }; } // namespace hydra::horizon::services::codec diff --git a/src/core/horizon/services/const.hpp b/src/core/horizon/services/const.hpp index d3c4f400..aa955655 100644 --- a/src/core/horizon/services/const.hpp +++ b/src/core/horizon/services/const.hpp @@ -1,5 +1,6 @@ #pragma once +#include "core/horizon/kernel/hipc/client_session.hpp" #include "core/horizon/services/service.hpp" #define SERVICE_COMMAND_CASE(service, id, func) \ @@ -49,12 +50,13 @@ class InBuffer { public: static constexpr BufferAttr attr = attr_; - io::MemoryStream* stream; + std::optional stream; - InBuffer() : stream{nullptr} {} - InBuffer(io::MemoryStream* stream_) : stream{stream_} {} + InBuffer() : stream{std::nullopt} {} + InBuffer(std::optional stream_) + : stream{std::move(stream_)} {} - bool IsValid() const { return stream != nullptr; } + bool IsValid() const { return stream.has_value(); } }; template @@ -62,12 +64,13 @@ class OutBuffer { public: static constexpr BufferAttr attr = attr_; - io::MemoryStream* stream; + std::optional stream; - OutBuffer() : stream{nullptr} {} - OutBuffer(io::MemoryStream* stream_) : stream{stream_} {} + OutBuffer() : stream{std::nullopt} {} + OutBuffer(std::optional stream_) + : stream{std::move(stream_)} {} - bool IsValid() const { return stream != nullptr; } + bool IsValid() const { return stream.has_value(); } }; enum class HandleAttr { @@ -99,7 +102,10 @@ class OutHandle { operator handle_id_t&() { return *handle_id; } - void operator=(handle_id_t other) { *handle_id = other; } + OutHandle& operator=(handle_id_t other) { + *handle_id = other; + return *this; + } private: handle_id_t* handle_id; @@ -227,22 +233,20 @@ void read_arg(RequestContext& context, Class& instance, arg_index + 1>(context, instance, args); return; } else if constexpr (traits::type == ArgumentType::InBuffer) { - io::MemoryStream* stream = nullptr; + std::optional stream; if constexpr (Arg::attr == BufferAttr::AutoSelect) { if (in_buffer_index < context.streams.send_buffers_streams.size()) - stream = unwrap_or_null( - context.streams.send_buffers_streams[in_buffer_index]); + stream = + context.streams.send_buffers_streams[in_buffer_index]; if (!stream && in_buffer_index < context.streams.send_statics_streams.size()) - stream = unwrap_or_null( - context.streams.send_statics_streams[in_buffer_index]); + stream = + context.streams.send_statics_streams[in_buffer_index]; } else if constexpr (Arg::attr == BufferAttr::MapAlias) { - stream = unwrap_or_null( - context.streams.send_buffers_streams[in_buffer_index]); + stream = context.streams.send_buffers_streams[in_buffer_index]; } else if constexpr (Arg::attr == BufferAttr::HipcPointer) { - stream = unwrap_or_null( - context.streams.send_statics_streams[in_buffer_index]); + stream = context.streams.send_statics_streams[in_buffer_index]; } else { LOG_FATAL(Services, "Invalid in buffer args"); } @@ -254,22 +258,20 @@ void read_arg(RequestContext& context, Class& instance, out_buffer_index, arg_index + 1>(context, instance, args); return; } else if constexpr (traits::type == ArgumentType::OutBuffer) { - io::MemoryStream* stream = nullptr; + std::optional stream; if constexpr (Arg::attr == BufferAttr::AutoSelect) { if (out_buffer_index < context.streams.recv_buffers_streams.size()) - stream = unwrap_or_null( - context.streams.recv_buffers_streams[out_buffer_index]); + stream = + context.streams.recv_buffers_streams[out_buffer_index]; if (!stream && out_buffer_index < context.streams.recv_list_streams.size()) - stream = unwrap_or_null( - context.streams.recv_list_streams[out_buffer_index]); + stream = + context.streams.recv_list_streams[out_buffer_index]; } else if constexpr (Arg::attr == BufferAttr::MapAlias) { - stream = unwrap_or_null( - context.streams.recv_buffers_streams[out_buffer_index]); + stream = context.streams.recv_buffers_streams[out_buffer_index]; } else if constexpr (Arg::attr == BufferAttr::HipcPointer) { - stream = unwrap_or_null( - context.streams.recv_list_streams[out_buffer_index]); + stream = context.streams.recv_list_streams[out_buffer_index]; } else { LOG_FATAL(Services, "Invalid out buffer args"); } @@ -322,8 +324,7 @@ void read_arg(RequestContext& context, Class& instance, "Objects stream is null"); auto service_handle_id = context.streams.in_objects_stream->Read(); - arg = dynamic_cast( - instance.GetService(context, service_handle_id)); + arg = instance.GetService(context, service_handle_id); ASSERT_DEBUG(arg, Services, "Invalid service"); // Next @@ -347,7 +348,7 @@ void read_arg(RequestContext& context, Class& instance, template result_t invoke_command_with_args(RequestContext& context, Class& instance, result_t (MethodClass::*func)(Args...), - std::index_sequence) { + std::index_sequence /*unused*/) { using traits = function_traits; auto args = std::tuple::type...>(); diff --git a/src/core/horizon/services/fssrv/directory.cpp b/src/core/horizon/services/fssrv/directory.cpp index b582c594..33dd24f5 100644 --- a/src/core/horizon/services/fssrv/directory.cpp +++ b/src/core/horizon/services/fssrv/directory.cpp @@ -37,7 +37,7 @@ result_t IDirectory::Read(u64* out_entry_count, if (i < entry_index) continue; - if (!entry) + if (entry == nullptr) continue; // Filter diff --git a/src/core/horizon/services/fssrv/file.cpp b/src/core/horizon/services/fssrv/file.cpp index 662432bc..a700db51 100644 --- a/src/core/horizon/services/fssrv/file.cpp +++ b/src/core/horizon/services/fssrv/file.cpp @@ -14,7 +14,7 @@ IFile::IFile(filesystem::IFile* file_, filesystem::FileOpenFlags flags) IFile::~IFile() { delete stream; } // TODO: option -result_t IFile::Read(aligned option, u64 offset, u64 size, +result_t IFile::Read(Aligned option, u64 offset, u64 size, u64* out_written_size, OutBuffer out_buffer) { (void)option; @@ -36,7 +36,7 @@ result_t IFile::Read(aligned option, u64 offset, u64 size, } // TODO: option -result_t IFile::Write(aligned option, u64 offset, u64 size, +result_t IFile::Write(Aligned option, u64 offset, u64 size, InBuffer in_buffer) { (void)option; diff --git a/src/core/horizon/services/fssrv/file.hpp b/src/core/horizon/services/fssrv/file.hpp index cf770e4f..fcedbba3 100644 --- a/src/core/horizon/services/fssrv/file.hpp +++ b/src/core/horizon/services/fssrv/file.hpp @@ -11,22 +11,21 @@ class IFile : public IService { ~IFile() override; private: + filesystem::IFile* file; + io::IStream* stream; + result_t RequestImpl([[maybe_unused]] RequestContext& context, u32 id) override; // Commands - result_t Read(aligned option, u64 offset, u64 size, + result_t Read(Aligned option, u64 offset, u64 size, u64* out_written_size, OutBuffer out_buffer); - result_t Write(aligned option, u64 offset, u64 size, + result_t Write(Aligned option, u64 offset, u64 size, InBuffer in_buffer); result_t Flush(); result_t SetSize(u64 size); result_t GetSize(u64* out_size); - - private: - filesystem::IFile* file; - io::IStream* stream; }; } // namespace hydra::horizon::services::fssrv diff --git a/src/core/horizon/services/fssrv/filesystem.cpp b/src/core/horizon/services/fssrv/filesystem.cpp index 2570d7f1..6905d653 100644 --- a/src/core/horizon/services/fssrv/filesystem.cpp +++ b/src/core/horizon/services/fssrv/filesystem.cpp @@ -17,7 +17,7 @@ DEFINE_SERVICE_COMMAND_TABLE(IFileSystem, 0, CreateFile, 1, DeleteFile, 2, GetTotalSpaceSize, 14, GetFileTimeStampRaw) #define READ_PATH_IMPL(path_var, debug_name) \ - const auto path_var = \ + [[maybe_unused]] const auto path_var = \ mount + \ std::string( \ in_##path_var##_buffer.stream->ReadNullTerminatedString()); \ @@ -40,9 +40,9 @@ IFileSystem::CreateFile(System* system, CreateOption flags, u64 size, const auto res = system->GetOS().GetFilesystem().CreateFile( path, size, true); // TODO: should create_intermediate be true? - if (res == filesystem::FsResult::AlreadyExists) + if (res == filesystem::FsResult::AlreadyExists) { LOG_WARN(Services, "File \"{}\" already exists", path); - else + } else ASSERT(res == filesystem::FsResult::Success, Services, "Failed to create file \"{}\": {}", path, res); @@ -70,9 +70,9 @@ IFileSystem::CreateDirectory(System* system, const auto res = system->GetOS().GetFilesystem().CreateDirectory( path, true); // TODO: should create_intermediate be true? - if (res == filesystem::FsResult::AlreadyExists) + if (res == filesystem::FsResult::AlreadyExists) { LOG_WARN(Services, "Directory \"{}\" already exists", path); - else + } else ASSERT(res == filesystem::FsResult::Success, Services, "Failed to create directory \"{}\": {}", path, res); diff --git a/src/core/horizon/services/fssrv/filesystem_proxy.cpp b/src/core/horizon/services/fssrv/filesystem_proxy.cpp index 00a1e074..558ddfbc 100644 --- a/src/core/horizon/services/fssrv/filesystem_proxy.cpp +++ b/src/core/horizon/services/fssrv/filesystem_proxy.cpp @@ -114,7 +114,7 @@ result_t IFileSystemProxy::CreateSaveDataFileSystem( } result_t IFileSystemProxy::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( - aligned space_id, u64 save_id, + Aligned space_id, u64 save_id, OutBuffer out_buffer) { LOG_FUNC_WITH_ARGS_STUBBED(Services, "space ID: {}, save ID: {}", space_id, save_id); @@ -129,14 +129,14 @@ result_t IFileSystemProxy::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( result_t IFileSystemProxy::OpenSaveDataFileSystem( RequestContext* ctx, System* system, kernel::Process* process, - aligned space_id, SaveDataAttribute attr) { + Aligned space_id, SaveDataAttribute attr) { return OpenSaveDataFileSystemImpl(ctx, system, process, space_id, attr, false); } result_t IFileSystemProxy::OpenReadOnlySaveDataFileSystem( RequestContext* ctx, System* system, kernel::Process* process, - aligned space_id, SaveDataAttribute attr) { + Aligned space_id, SaveDataAttribute attr) { return OpenSaveDataFileSystemImpl(ctx, system, process, space_id, attr, true); } @@ -178,7 +178,7 @@ result_t IFileSystemProxy::OpenDataStorageByProgramId(RequestContext* ctx, result_t IFileSystemProxy::OpenDataStorageByDataId(RequestContext* ctx, System* system, - aligned storage_id, + Aligned storage_id, u64 data_id) { LOG_FUNC_NOT_IMPLEMENTED(Services); diff --git a/src/core/horizon/services/fssrv/filesystem_proxy.hpp b/src/core/horizon/services/fssrv/filesystem_proxy.hpp index 49f8f1f9..648a4f4e 100644 --- a/src/core/horizon/services/fssrv/filesystem_proxy.hpp +++ b/src/core/horizon/services/fssrv/filesystem_proxy.hpp @@ -18,7 +18,7 @@ enum class FileSystemProxyType { RegisteredUpdate, }; -enum BisPartitionId : u32 { +enum class BisPartitionId : u32 { BootPartition1Root = 0, BootPartition2Root = 10, @@ -122,15 +122,15 @@ class IFileSystemProxy : public IService { SaveDataCreationInfo creation_info, SaveDataMetaInfo meta_info); result_t ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( - aligned space_id, u64 save_id, + Aligned space_id, u64 save_id, OutBuffer out_buffer); result_t OpenSaveDataFileSystem(RequestContext* ctx, System* system, kernel::Process* process, - aligned space_id, + Aligned space_id, SaveDataAttribute attr); result_t OpenReadOnlySaveDataFileSystem( RequestContext* ctx, System* system, kernel::Process* process, - aligned space_id, SaveDataAttribute attr); + Aligned space_id, SaveDataAttribute attr); result_t OpenSaveDataInfoReaderBySaveDataSpaceId(RequestContext* ctx, SaveDataSpaceId space_id); result_t OpenDataStorageByCurrentProcess(RequestContext* ctx, @@ -139,7 +139,7 @@ class IFileSystemProxy : public IService { result_t OpenDataStorageByProgramId(RequestContext* ctx, System* system, u64 program_id); result_t OpenDataStorageByDataId(RequestContext* ctx, System* system, - aligned storage_id, + Aligned storage_id, u64 data_id); result_t OpenPatchDataStorageByCurrentProcess(RequestContext* ctx, System* system); diff --git a/src/core/horizon/services/hid/applet_resource.hpp b/src/core/horizon/services/hid/applet_resource.hpp index db63cfa2..03b8c71d 100644 --- a/src/core/horizon/services/hid/applet_resource.hpp +++ b/src/core/horizon/services/hid/applet_resource.hpp @@ -12,7 +12,7 @@ class AppletResource; class IAppletResource : public IService { public: IAppletResource(System& system_, kernel::AppletResourceUserId aruid_); - ~IAppletResource(); + ~IAppletResource() override; protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, diff --git a/src/core/horizon/services/hid/const.hpp b/src/core/horizon/services/hid/const.hpp index 2d21ebeb..f85f397e 100644 --- a/src/core/horizon/services/hid/const.hpp +++ b/src/core/horizon/services/hid/const.hpp @@ -622,3 +622,11 @@ ENABLE_ENUM_FORMATTING(hydra::horizon::services::hid::NpadIdType, No1, "Number 4", No5, "Number 5", No6, "Number 6", No7, "Number 7", No8, "Number 8", Other, "Other", Handheld, "Handheld") + +ENABLE_ENUM_FLAGS_FORMATTING(hydra::horizon::services::hid::NpadStyleSet, + FullKey, "full key", Handheld, "handheld", JoyDual, + "joy dual", JoyLeft, "joy left", JoyRight, + "joy right", Gc, "GC", Palma, "palma", Lark, + "lark", HandheldLark, "handheld lark", Lucia, + "lucia", Lagon, "lagon", Lager, "lager", SystemExt, + "system ext", System, "system") diff --git a/src/core/horizon/services/hid/hid_server.cpp b/src/core/horizon/services/hid/hid_server.cpp index 3f8d7a94..0d7dceca 100644 --- a/src/core/horizon/services/hid/hid_server.cpp +++ b/src/core/horizon/services/hid/hid_server.cpp @@ -34,7 +34,7 @@ result_t IHidServer::CreateAppletResource(RequestContext* ctx, result_t IHidServer::SetSupportedNpadStyleSet(System* system, - aligned style_set, + Aligned style_set, kernel::AppletResourceUserId aruid) { APPLET_RESOURCE(aruid).SetSupportedStyleSet(style_set); return RESULT_SUCCESS; @@ -67,7 +67,7 @@ result_t IHidServer::ActivateNpad(System* system, } result_t IHidServer::AcquireNpadStyleSetUpdateEventHandle( - System* system, kernel::Process* process, aligned type, + System* system, kernel::Process* process, Aligned type, kernel::AppletResourceUserId aruid, u64 event_ptr, OutHandle out_handle) { (void)event_ptr; @@ -85,7 +85,7 @@ result_t IHidServer::AcquireNpadStyleSetUpdateEventHandle( return RESULT_SUCCESS; } -result_t IHidServer::DisconnectNpad(System* system, aligned type, +result_t IHidServer::DisconnectNpad(System* system, Aligned type, kernel::AppletResourceUserId aruid) { APPLET_RESOURCE(aruid).DisconnectNpad(internal::ToNpadIndex(type)); return RESULT_SUCCESS; @@ -135,7 +135,7 @@ result_t IHidServer::GetPlayerLedPattern(NpadIdType npad_id_type, result_t IHidServer::ActivateNpadWithRevision(System* system, - aligned revision, + Aligned revision, kernel::AppletResourceUserId aruid) { LOG_DEBUG(Services, "Revision: {}", revision); APPLET_RESOURCE(aruid).ActivateNpads(revision); @@ -151,7 +151,7 @@ result_t IHidServer::SetNpadJoyHoldType(System* system, result_t IHidServer::GetNpadJoyHoldType(System* system, kernel::AppletResourceUserId aruid, - aligned* out_type) { + Aligned* out_type) { out_type->ZeroOutPadding(); *out_type = APPLET_RESOURCE(aruid).GetJoyHoldType(); return RESULT_SUCCESS; diff --git a/src/core/horizon/services/hid/hid_server.hpp b/src/core/horizon/services/hid/hid_server.hpp index 33bf766e..15b6c784 100644 --- a/src/core/horizon/services/hid/hid_server.hpp +++ b/src/core/horizon/services/hid/hid_server.hpp @@ -38,7 +38,7 @@ class IHidServer : public IService { STUB_REQUEST_COMMAND(SetGyroscopeZeroDriftMode); STUB_REQUEST_COMMAND(ActivateGesture); result_t SetSupportedNpadStyleSet(System* system, - aligned style_set, + Aligned style_set, kernel::AppletResourceUserId aruid); result_t GetSupportedNpadStyleSet(System* system, kernel::AppletResourceUserId aruid, @@ -48,14 +48,14 @@ class IHidServer : public IService { InBuffer in_types_buffer); result_t ActivateNpad(System* system, kernel::AppletResourceUserId aruid); result_t AcquireNpadStyleSetUpdateEventHandle( - System* system, kernel::Process* process, aligned type, + System* system, kernel::Process* process, Aligned type, kernel::AppletResourceUserId aruid, u64 event_ptr, OutHandle out_handle); - result_t DisconnectNpad(System* system, aligned type, + result_t DisconnectNpad(System* system, Aligned type, kernel::AppletResourceUserId aruid); result_t GetPlayerLedPattern(NpadIdType npad_id_type, u64* out_pattern); result_t ActivateNpadWithRevision(System* system, - aligned revision, + Aligned revision, kernel::AppletResourceUserId aruid); // TODO: PID descriptor result_t SetNpadJoyHoldType(System* system, @@ -64,7 +64,7 @@ class IHidServer : public IService { // TODO: PID descriptor result_t GetNpadJoyHoldType(System* system, kernel::AppletResourceUserId aruid, - aligned* out_type); + Aligned* out_type); STUB_REQUEST_COMMAND(SetNpadJoyAssignmentModeSingleByDefault); STUB_REQUEST_COMMAND(SetNpadJoyAssignmentModeDual); STUB_REQUEST_COMMAND(SetNpadHandheldActivationMode); diff --git a/src/core/horizon/services/hid/internal/applet_resource.hpp b/src/core/horizon/services/hid/internal/applet_resource.hpp index 5ab9ef03..9eaf7fd5 100644 --- a/src/core/horizon/services/hid/internal/applet_resource.hpp +++ b/src/core/horizon/services/hid/internal/applet_resource.hpp @@ -61,7 +61,7 @@ class AppletResource { std::array npads; // Helpers - inline bool ShouldAcceptInput() const { return active && input_enabled; } + bool ShouldAcceptInput() const { return active && input_enabled; } public: GETTER(shared_mem, GetSharedMemory); diff --git a/src/core/horizon/services/hid/internal/npad.cpp b/src/core/horizon/services/hid/internal/npad.cpp index 5ec176d5..46e8e525 100644 --- a/src/core/horizon/services/hid/internal/npad.cpp +++ b/src/core/horizon/services/hid/internal/npad.cpp @@ -128,7 +128,7 @@ void Npad::Setup(NpadStyleSet style_set) { state.applet_footer_ui_type = AppletFooterUiType::None; break; default: - throw Error::InvalidStyleSet; + LOG_FATAL(Services, "Unsupported style set {}", style_set); } } diff --git a/src/core/horizon/services/hid/internal/npad.hpp b/src/core/horizon/services/hid/internal/npad.hpp index 6a015209..4b3fabeb 100644 --- a/src/core/horizon/services/hid/internal/npad.hpp +++ b/src/core/horizon/services/hid/internal/npad.hpp @@ -12,10 +12,6 @@ namespace hydra::horizon::services::hid::internal { class Npad { public: - enum class Error { - InvalidStyleSet, - }; - Npad(NpadInternalState& state_); ~Npad(); diff --git a/src/core/horizon/services/hid/internal/shared_memory.hpp b/src/core/horizon/services/hid/internal/shared_memory.hpp index be0d927b..1c35e835 100644 --- a/src/core/horizon/services/hid/internal/shared_memory.hpp +++ b/src/core/horizon/services/hid/internal/shared_memory.hpp @@ -7,16 +7,17 @@ namespace hydra::horizon::services::hid::internal { template struct RingLifo { public: - enum class Error { - NoStorage, - }; - void Clear() { atomic_store(&index, 0ull); atomic_store(&count, 0ull); } - T& GetCurrentStorage() { return GetCurrentAtomicStorage().data; } + std::optional GetCurrentStorage() { + return GetCurrentAtomicStorage().transform( + [](AtomicStorage* atomic_storage) { + return &atomic_storage->data; + }); + } void Write(const T& data) { const auto next_index = (ReadIndex() + 1) % max_entries; @@ -32,12 +33,11 @@ struct RingLifo { void WriteNext(const T& data) { // HACK: const cast - try { - const_cast(data).sampling_number = - GetCurrentStorage().sampling_number + 1; - } catch (Error error) { - const_cast(data).sampling_number = 0; - } + const_cast(data).sampling_number = + GetCurrentStorage() + .transform( + [](T* storage) { return storage->sampling_number + 1; }) + .value_or(0); Write(data); } @@ -66,12 +66,11 @@ struct RingLifo { u64 ReadIndex() { return atomic_load(&index); } u64 ReadCount() { return atomic_load(&count); } - AtomicStorage& GetCurrentAtomicStorage() { + std::optional GetCurrentAtomicStorage() { const auto count_ = std::min(ReadCount(), 1ull); // TODO: why limit to 1? - if (count_ == 0) { - throw Error::NoStorage; // TODO: what to do? - } + if (count_ == 0) + return std::nullopt; auto index_ = ReadIndex(); const auto storage_index = @@ -79,7 +78,7 @@ struct RingLifo { auto& storage = storages[storage_index]; // TODO: verify sampling numbers - return storage; + return &storage; } }; diff --git a/src/core/horizon/services/hosbinder/hos_binder_driver.cpp b/src/core/horizon/services/hosbinder/hos_binder_driver.cpp index 7ef1315d..0c6eb201 100644 --- a/src/core/horizon/services/hosbinder/hos_binder_driver.cpp +++ b/src/core/horizon/services/hosbinder/hos_binder_driver.cpp @@ -127,14 +127,14 @@ result_t IHOSBinderDriver::TransactParcelAuto( } // TODO: flags -void IHOSBinderDriver::TransactParcelImpl(System& system, i32 binder_id, - TransactCode code, u32 flags, - io::MemoryStream* in_stream, - io::MemoryStream* out_stream) { +void IHOSBinderDriver::TransactParcelImpl( + System& system, i32 binder_id, TransactCode code, u32 flags, + std::optional in_stream, + std::optional out_stream) { (void)flags; - ParcelReader parcel_reader(in_stream); - ParcelWriter parcel_writer(out_stream); + ParcelReader parcel_reader(in_stream.value()); + ParcelWriter parcel_writer(out_stream.value()); // Binder auto& binder = system.GetOS().GetDisplayDriver().GetBinder( @@ -243,7 +243,7 @@ void IHOSBinderDriver::TransactParcelImpl(System& system, i32 binder_id, // Input buffer auto buffer = parcel_reader.ReadStrongPointer(); - if (!buffer) { + if (buffer == nullptr) { LOG_ERROR(Services, "No graphic buffer"); break; } diff --git a/src/core/horizon/services/hosbinder/hos_binder_driver.hpp b/src/core/horizon/services/hosbinder/hos_binder_driver.hpp index c575a7fc..456d67cf 100644 --- a/src/core/horizon/services/hosbinder/hos_binder_driver.hpp +++ b/src/core/horizon/services/hosbinder/hos_binder_driver.hpp @@ -54,8 +54,9 @@ class IHOSBinderDriver : public IService { OutBuffer out_parcel_buffer); void TransactParcelImpl(System& system, i32 binder_id, TransactCode code, - u32 flags, io::MemoryStream* in_stream, - io::MemoryStream* out_stream); + u32 flags, + std::optional in_stream, + std::optional out_stream); }; } // namespace hydra::horizon::services::hosbinder diff --git a/src/core/horizon/services/hosbinder/parcel.hpp b/src/core/horizon/services/hosbinder/parcel.hpp index e7bc3221..9b9a7e23 100644 --- a/src/core/horizon/services/hosbinder/parcel.hpp +++ b/src/core/horizon/services/hosbinder/parcel.hpp @@ -25,18 +25,18 @@ struct ParcelFlattenedBinder { class ParcelReader { public: - ParcelReader(io::MemoryStream* stream_) : stream{stream_} { + ParcelReader(io::MemoryStream stream_) : stream{std::move(stream_)} { auto header = Read(); - stream->SeekTo(header.data_offset); + stream.SeekTo(header.data_offset); } template - const std::span ReadSpan(usize count) { - const auto span = stream->ReadSpan(count); + std::span ReadSpan(usize count) { + const auto span = stream.ReadSpan(count); // Align usize size = count * sizeof(T); - stream->SeekBy(align(size, static_cast(4)) - size); + stream.SeekBy(align(size, static_cast(4)) - size); return span; } @@ -75,7 +75,7 @@ class ParcelReader { // TODO: check this std::string ReadString16() { - usize length = static_cast(Read()); + auto length = static_cast(Read()); auto data = ReadSpan(length + 1); std::string str(length, '\0'); @@ -94,13 +94,13 @@ class ParcelReader { } private: - io::MemoryStream* stream; + io::MemoryStream stream; }; class ParcelWriter { public: - ParcelWriter(io::MemoryStream* stream_) : stream{stream_} { - header = stream->WriteReturningPtr({ + ParcelWriter(io::MemoryStream stream_) : stream{std::move(stream_)} { + header = stream.WriteReturningPtr({ .data_size = 0x0, .data_offset = sizeof(ParcelHeader), .objects_size = 0x0, @@ -110,11 +110,11 @@ class ParcelWriter { void Finish() { header->data_size = - static_cast(stream->GetSeek() - header->data_offset); + static_cast(stream.GetSeek() - header->data_offset); header->objects_size = static_cast(objects.size() * sizeof(u32)); header->objects_offset = header->data_offset + header->data_size; - stream->SeekTo(header->objects_offset); - stream->WriteSpan(std::span(objects)); + stream.SeekTo(header->objects_offset); + stream.WriteSpan(std::span(objects)); } template @@ -131,11 +131,11 @@ class ParcelWriter { template std::span WriteReturningSpan(usize count) { - auto span = stream->WriteReturningSpan(count); + auto span = stream.WriteReturningSpan(count); // Align usize size = count * sizeof(T); - stream->SeekBy(align(size, static_cast(4)) - size); + stream.SeekBy(align(size, static_cast(4)) - size); return span; } @@ -176,7 +176,7 @@ class ParcelWriter { // TODO: check this void WriteString16(const std::string_view str) { - ASSERT_DEBUG(str.size() != 0, Services, "Invalid string size"); + ASSERT_DEBUG(!str.empty(), Services, "Invalid string size"); Write(static_cast(str.size())); auto span = WriteReturningSpan(str.size() + 1); @@ -195,7 +195,7 @@ class ParcelWriter { } private: - io::MemoryStream* stream; + io::MemoryStream stream; ParcelHeader* header; std::vector objects; diff --git a/src/core/horizon/services/lm/logger.cpp b/src/core/horizon/services/lm/logger.cpp index 64e10ec2..ac96c37f 100644 --- a/src/core/horizon/services/lm/logger.cpp +++ b/src/core/horizon/services/lm/logger.cpp @@ -47,14 +47,14 @@ enum class LogDataChunkKey { }; // From Ryujinx -bool TryReadUleb128(io::MemoryStream* stream, u32& result) { +bool TryReadUleb128(io::MemoryStream& stream, u32& result) { result = 0; int count = 0; u8 encoded; do { // TODO: check if enough space - encoded = stream->Read(); + encoded = stream.Read(); result += static_cast(encoded & 0x7F) << (7 * count); @@ -81,15 +81,16 @@ namespace hydra::horizon::services::lm { DEFINE_SERVICE_COMMAND_TABLE(ILogger, 0, Log) result_t ILogger::Log(InBuffer buffer) { - auto stream = buffer.stream; - const auto header = stream->Read(); + ASSIGN_OR_RETURN_VALUE(auto stream, buffer.stream, + RESULT_SUCCESS); // TODO: return error on failure? + const auto header = stream.Read(); // From Ryujinx [[maybe_unused]] bool is_head_packet = any(header.flags & PacketFlags::Head); bool is_tail_packet = any(header.flags & PacketFlags::Tail); - while (stream->GetSeek() - sizeof(LogPacketHeader) < + while (stream.GetSeek() - sizeof(LogPacketHeader) < header.payload_size) { // TODO: correct? u32 key; u32 size; @@ -97,7 +98,7 @@ result_t ILogger::Log(InBuffer buffer) { return MAKE_RESULT( Svc, kernel::Error::InvalidCombination); // TODO: module - const auto data = stream->ReadSpan(size); + const auto data = stream.ReadSpan(size); #define GET_DATA(type) *reinterpret_cast(data.data()) #define GET_STRING() \ @@ -105,7 +106,7 @@ result_t ILogger::Log(InBuffer buffer) { switch (static_cast(key)) { case LogDataChunkKey::Begin: - stream->SeekBy(size); + stream.SeekBy(size); continue; case LogDataChunkKey::End: break; @@ -137,7 +138,7 @@ result_t ILogger::Log(InBuffer buffer) { packet.time = GET_DATA(u64); break; case LogDataChunkKey::ProcessName: - LOG_NOT_IMPLEMENTED(Services, "ProcessName"); + packet.process = GET_STRING(); break; } @@ -154,6 +155,9 @@ result_t ILogger::Log(InBuffer buffer) { packet.program_name, packet.filename, packet.line, packet.function, packet.module); } + if (!packet.process.empty()) { + msg += fmt::format("- Process: {}\n", packet.process); + } if (!packet.thread.empty()) { msg += fmt::format("- Thread: {}\n", packet.thread); } diff --git a/src/core/horizon/services/lm/logger.hpp b/src/core/horizon/services/lm/logger.hpp index b7c1c725..6f513ebd 100644 --- a/src/core/horizon/services/lm/logger.hpp +++ b/src/core/horizon/services/lm/logger.hpp @@ -10,6 +10,7 @@ struct Packet { std::string filename; std::string function; std::string module; + std::string process; std::string thread; u64 drop_count{0}; u64 time{0}; diff --git a/src/core/horizon/services/nifm/request.cpp b/src/core/horizon/services/nifm/request.cpp index 4a6f1f8a..3f75b1fb 100644 --- a/src/core/horizon/services/nifm/request.cpp +++ b/src/core/horizon/services/nifm/request.cpp @@ -10,8 +10,9 @@ DEFINE_SERVICE_COMMAND_TABLE(IRequest, 0, GetRequestState, 1, GetResult, 2, SetConnectionConfirmationOption) IRequest::IRequest() - : events{new kernel::Event(false, "IRequest system event 0"), - new kernel::Event(false, "IRequest system event 1")} {} + : events{ + std::make_unique(false, "IRequest system event 0"), + std::make_unique(false, "IRequest system event 1")} {} result_t IRequest::GetRequestState(RequestState* out_state) { LOG_FUNC_STUBBED(Services); @@ -25,8 +26,8 @@ result_t IRequest::GetRequestState(RequestState* out_state) { result_t IRequest::GetSystemEventReadableHandles( kernel::Process* process, OutHandle out_handle0, OutHandle out_handle1) { - out_handle0 = process->AddHandle(events[0]); - out_handle1 = process->AddHandle(events[1]); + out_handle0 = process->AddHandle(events[0].get()); + out_handle1 = process->AddHandle(events[1].get()); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/nifm/request.hpp b/src/core/horizon/services/nifm/request.hpp index fab84017..b693ff18 100644 --- a/src/core/horizon/services/nifm/request.hpp +++ b/src/core/horizon/services/nifm/request.hpp @@ -31,7 +31,7 @@ class IRequest : public IService { u32 id) override; private: - kernel::Event* events[2]; + std::array, 2> events; // Commands result_t GetRequestState(RequestState* out_state); diff --git a/src/core/horizon/services/ns/const.cpp b/src/core/horizon/services/ns/const.cpp index 27774c99..7f2728b1 100644 --- a/src/core/horizon/services/ns/const.cpp +++ b/src/core/horizon/services/ns/const.cpp @@ -13,9 +13,9 @@ ApplicationControlProperty::GetApplicationTitle(SystemLanguage lang) const { return titles[index]; // Otherwise just return the first valid title - for (u32 i = 0; i < sizeof_array(titles); i++) { - if (titles[i].IsValid()) - return titles[i]; + for (const auto& title : titles) { + if (title.IsValid()) + return title; } // Fallback to the first title diff --git a/src/core/horizon/services/ns/const.hpp b/src/core/horizon/services/ns/const.hpp index a86776e4..814704e3 100644 --- a/src/core/horizon/services/ns/const.hpp +++ b/src/core/horizon/services/ns/const.hpp @@ -32,10 +32,10 @@ struct NeighborDetectionClientConfiguration { NeighborDetectionGroupConfiguration receivable_group_configurations[0x10]; }; -typedef struct { +struct JitConfiguration { u64 flags; u64 memory_size; -} JitConfiguration; +}; // TODO: adjust this according to switchbrew struct ApplicationControlProperty { diff --git a/src/core/horizon/services/nvdrv/const.hpp b/src/core/horizon/services/nvdrv/const.hpp index 28b8ffd2..19b5f2d2 100644 --- a/src/core/horizon/services/nvdrv/const.hpp +++ b/src/core/horizon/services/nvdrv/const.hpp @@ -5,22 +5,22 @@ namespace hydra::horizon::services::nvdrv { enum class NvResult : u32 { - Success, - NotImplemented, - NotSupported, - NotInitialized, - BadParameter, - Timeout, - InsufficientMemory, - ReadOnlyAttribute, - InvalidState, - InvalidAddress, - InvalidSize, - BadValue, - AlreadyAllocated, - Busy, - ResourceError, - CountMismatch, + Success = 0, + NotImplemented = 1, + NotSupported = 2, + NotInitialized = 3, + BadParameter = 4, + Timeout = 5, + InsufficientMemory = 6, + ReadOnlyAttribute = 7, + InvalidState = 8, + InvalidAddress = 9, + InvalidSize = 10, + BadValue = 11, + AlreadyAllocated = 12, + Busy = 13, + ResourceError = 14, + CountMismatch = 15, SharedMemoryTooSmall = 0x1000, FileOperationFailed = 0x30003, DirectoryOperationFailed = 0x30004, diff --git a/src/core/horizon/services/nvdrv/ioctl/channel_base.cpp b/src/core/horizon/services/nvdrv/ioctl/channel_base.cpp index 6c1c6881..494ffc42 100644 --- a/src/core/horizon/services/nvdrv/ioctl/channel_base.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/channel_base.cpp @@ -45,7 +45,7 @@ NvResult ChannelBase::SetSubmitTimeout(u32 timeout) { NvResult ChannelBase::MapCmdBuffer(u32 num_handles, [[maybe_unused]] u32 _reserved_x4, - aligned is_compressed, + Aligned is_compressed, const MapCmdBufferHandle* handles) { std::span handle_span(handles, num_handles); LOG_FUNC_WITH_ARGS_STUBBED(Services, "is compressed: {}, handles: [{}]", @@ -55,7 +55,7 @@ NvResult ChannelBase::MapCmdBuffer(u32 num_handles, NvResult ChannelBase::UnmapCmdBuffer(u32 num_handles, [[maybe_unused]] u32 _reserved_x4, - aligned is_compressed, + Aligned is_compressed, const UnmapCmdBufferHandle* handles) { std::span handle_span(handles, num_handles); LOG_FUNC_WITH_ARGS_STUBBED(Services, "is compressed: {}, handles: [{}]", diff --git a/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp b/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp index 314090e3..5c1c4450 100644 --- a/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp @@ -30,10 +30,10 @@ class ChannelBase : public FdBase { NvResult GetWaitBase(u32 module_id, u32* out_value); NvResult SetSubmitTimeout(u32 timeout); NvResult MapCmdBuffer(u32 num_handles, [[maybe_unused]] u32 _reserved_x4, - aligned is_compressed, + Aligned is_compressed, const MapCmdBufferHandle* handles); NvResult UnmapCmdBuffer(u32 num_handles, [[maybe_unused]] u32 _reserved_x4, - aligned is_compressed, + Aligned is_compressed, const UnmapCmdBufferHandle* handles); NvResult SetUserData(u64 data); NvResult GetUserData(u64* out_data); diff --git a/src/core/horizon/services/nvdrv/ioctl/const.hpp b/src/core/horizon/services/nvdrv/ioctl/const.hpp index 668d3c10..b8be2da8 100644 --- a/src/core/horizon/services/nvdrv/ioctl/const.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/const.hpp @@ -54,10 +54,10 @@ namespace hydra::horizon::services::nvdrv::ioctl { struct IoctlContext { System& system; kernel::Process* process; - io::MemoryStream* in_stream; - io::MemoryStream* in_buffer_stream; - io::MemoryStream* out_stream; - io::MemoryStream* out_buffer_stream; + std::optional in_stream; + std::optional in_buffer_stream; + std::optional out_stream; + std::optional out_buffer_stream; }; template @@ -67,7 +67,10 @@ struct InOut { Out* out; operator In() const { return in; } - void operator=(const Out& other) { *out = other; } + InOut& operator=(const Out& other) { + *out = other; + return *this; + } In Get() const { return in; } }; @@ -77,7 +80,10 @@ struct InOutSingle { T* data; operator T() const { return *data; } - void operator=(const T& other) { *data = other; } + InOutSingle& operator=(const T& other) { + *data = other; + return *this; + } T Get() const { return *data; } }; @@ -213,7 +219,8 @@ void read_arg(IoctlContext& context, CommandArguments& args) { arg = context.in_stream->ReadPtr(); // Next - static_assert(arg_index == std::tuple_size_v - 1, + static_assert(arg_index == + std::tuple_size_v < CommandArguments > -1, "InArray must be the last argument"); return; } @@ -223,7 +230,7 @@ void read_arg(IoctlContext& context, CommandArguments& args) { template NvResult invoke_command_with_args(IoctlContext& context, Class& instance, NvResult (Class::*func)(Args...), - std::index_sequence) { + std::index_sequence /*unused*/) { using traits = function_traits; auto args = std::tuple::type...>(); diff --git a/src/core/horizon/services/nvdrv/ioctl/fd_base.hpp b/src/core/horizon/services/nvdrv/ioctl/fd_base.hpp index 0951edc5..f9dcecd8 100644 --- a/src/core/horizon/services/nvdrv/ioctl/fd_base.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/fd_base.hpp @@ -10,7 +10,7 @@ namespace hydra::horizon::services::nvdrv::ioctl { class FdBase { public: - virtual ~FdBase() {} + virtual ~FdBase() noexcept = default; virtual NvResult Ioctl(IoctlContext& context, u32 type, u32 nr) = 0; virtual NvResult Ioctl2([[maybe_unused]] IoctlContext& context, u32 type, diff --git a/src/core/horizon/services/nvdrv/ioctl/nvdisp_ctrl.hpp b/src/core/horizon/services/nvdrv/ioctl/nvdisp_ctrl.hpp index e7375f77..acb77b20 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvdisp_ctrl.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvdisp_ctrl.hpp @@ -6,7 +6,8 @@ namespace hydra::horizon::services::nvdrv::ioctl { class NvDispCtrl : public FdBase { public: - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; private: // Ioctls diff --git a/src/core/horizon/services/nvdrv/ioctl/nvdisp_disp.hpp b/src/core/horizon/services/nvdrv/ioctl/nvdisp_disp.hpp index ed1073d6..02fa7a57 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvdisp_disp.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvdisp_disp.hpp @@ -8,7 +8,8 @@ class NvDispDisp : public FdBase { public: NvDispDisp(u32 display_index_) : display_index{display_index_} {} - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; private: u32 display_index; diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp index eca57827..617b37ee 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp @@ -23,13 +23,13 @@ NvResult NvHostAsGpu::BindChannel(u32 fd_id) { NvResult NvHostAsGpu::AllocSpace(kernel::Process* process, u32 pages, u32 page_size, - aligned flags, + Aligned flags, InOut align_and_offset) { uptr gpu_addr = invalid(); if (any(flags & AllocSpaceFlags::FixedOffset)) gpu_addr = align_and_offset; // TODO: is it really align? - align_and_offset = process->GetGMmu()->AllocatePrivateAddressSpace( + align_and_offset = process->GetGMmu().AllocatePrivateAddressSpace( static_cast(pages) * static_cast(page_size), gpu_addr); return NvResult::Success; } @@ -73,7 +73,7 @@ NvResult NvHostAsGpu::MapBufferEX(System* system, kernel::Process* process, if (any(flags & MapBufferFlags::FixedOffset)) addr = inout_addr; - inout_addr = process->GetGMmu()->MapBufferToAddressSpace( + inout_addr = process->GetGMmu().MapBufferToAddressSpace( Range::FromSize(map.addr + buffer_offset, size), addr); return NvResult::Success; } @@ -108,7 +108,7 @@ NvResult NvHostAsGpu::AllocAsEX(kernel::Process* process, u32 big_page_size, // TODO: why does nouveau pass 0x0 for all of these? // TODO: what is split for? - process->GetGMmu()->AllocatePrivateAddressSpace( + process->GetGMmu().AllocatePrivateAddressSpace( va_range_end - va_range_start, va_range_start); return NvResult::Success; } diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp index 59f87058..b2e7d65a 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp @@ -49,7 +49,7 @@ class NvHostAsGpu : public FdBase { // Ioctls NvResult BindChannel(u32 fd_id); NvResult AllocSpace(kernel::Process* process, u32 pages, u32 page_size, - aligned flags, + Aligned flags, InOut align_and_offset); NvResult FreeSpace(vaddr_t offset, u32 pages, u32 page_size); NvResult UnmapBuffer(gpu_vaddr_t addr); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.cpp index 77b18b8c..fbf25739 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.cpp @@ -15,7 +15,7 @@ DEFINE_IOCTL_TABLE(NvHostCtrl, NvResult NvHostCtrl::QueryEvent(u32 event_id_u32, kernel::Event*& out_event) { u32 slot; u32 syncpoint_id; - if (extract_bits(event_id_u32, 28, 1)) { // New format + if (extract_bits(event_id_u32, 28, 1) != 0u) { // New format slot = extract_bits(event_id_u32, 0, 16); syncpoint_id = extract_bits(event_id_u32, 16, 12); } else { // Old format @@ -92,7 +92,7 @@ NvResult NvHostCtrl::SyncptAllocEvent(u32 slot) { // Check if event is already allocated // TODO: correct? - if (event.event) + if (event.event != nullptr) event.event->Release(); event.event = new kernel::Event(false, fmt::format("NvHostEvent {}", slot)); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.hpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.hpp index 999b1c34..bc73ab33 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl.hpp @@ -11,7 +11,8 @@ struct NvHostEvent { class NvHostCtrl : public FdBase { public: - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; NvResult QueryEvent(u32 event_id_u32, kernel::Event*& out_event) override; private: diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp index d8d34f59..c9187e90 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp @@ -47,7 +47,7 @@ NvResult NvHostGpu::SubmitGpfifo( (void)gpfifo; system->GetGpu().GetPfifo().SubmitEntries( - *process->GetGMmu(), + process->GetGMmu(), std::span(entries, num_entries), inout_flags_and_detailed_error); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp b/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp index ecf8e058..a43aa3c0 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp @@ -23,7 +23,7 @@ NvResult NvMap::FromId(u32 id, handle_id_t* out_handle_id) { // TODO: heap mask, kind NvResult NvMap::Alloc(System* system, handle_id_t handle_id, u32 heap_mask, u32 flags, InOutSingle inout_alignment, - aligned kind, gpu_vaddr_t addr) { + Aligned kind, gpu_vaddr_t addr) { (void)heap_mask; (void)kind; @@ -33,7 +33,7 @@ NvResult NvMap::Alloc(System* system, handle_id_t handle_id, u32 heap_mask, return NvResult::Success; } -NvResult NvMap::Free(System* system, aligned handle_id, +NvResult NvMap::Free(System* system, Aligned handle_id, gpu_vaddr_t* out_addr, u64* out_size, u32* out_flags) { auto map = system->GetGpu().GetMap(handle_id); system->GetGpu().FreeMap(handle_id); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp b/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp index b63acd93..9f6bcd3b 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp @@ -24,8 +24,8 @@ class NvMap : public FdBase { NvResult FromId(u32 id, handle_id_t* out_handle_id); NvResult Alloc(System* system, handle_id_t handle_id, u32 heap_mask, u32 flags, InOutSingle inout_alignment, - aligned kind, gpu_vaddr_t addr); - NvResult Free(System* system, aligned handle_id, + Aligned kind, gpu_vaddr_t addr); + NvResult Free(System* system, Aligned handle_id, gpu_vaddr_t* out_addr, u64* out_size, u32* out_flags); NvResult Param(System* system, handle_id_t handle_id, NvMapParamType type, u32* out_value); diff --git a/src/core/horizon/services/nvdrv/nvdrv_services.cpp b/src/core/horizon/services/nvdrv/nvdrv_services.cpp index 6ac0b972..e02cdaea 100644 --- a/src/core/horizon/services/nvdrv/nvdrv_services.cpp +++ b/src/core/horizon/services/nvdrv/nvdrv_services.cpp @@ -69,8 +69,8 @@ result_t INvDrvServices::Ioctl(System* system, kernel::Process* process, NvResult* out_result, OutBuffer out_buffer) { return IoctlImpl(&ioctl::FdBase::Ioctl, *system, process, fd_id, code, - in_buffer.stream, nullptr, out_buffer.stream, nullptr, - out_result); + in_buffer.stream, std::nullopt, out_buffer.stream, + std::nullopt, out_result); } result_t INvDrvServices::Close(u32 fd_id, u32* out_err) { @@ -123,7 +123,7 @@ result_t INvDrvServices::Ioctl2(System* system, kernel::Process* process, OutBuffer out_buffer) { return IoctlImpl(&ioctl::FdBase::Ioctl2, *system, process, fd_id, code, in_buffer1.stream, in_buffer2.stream, out_buffer.stream, - nullptr, out_result); + std::nullopt, out_result); } result_t INvDrvServices::Ioctl3(System* system, kernel::Process* process, @@ -133,7 +133,7 @@ result_t INvDrvServices::Ioctl3(System* system, kernel::Process* process, OutBuffer out_buffer1, OutBuffer out_buffer2) { return IoctlImpl(&ioctl::FdBase::Ioctl3, *system, process, fd_id, code, - in_buffer.stream, nullptr, out_buffer1.stream, + in_buffer.stream, std::nullopt, out_buffer1.stream, out_buffer2.stream, out_result); } @@ -141,9 +141,10 @@ result_t INvDrvServices::IoctlImpl( NvResult (ioctl::FdBase::*func)(ioctl::IoctlContext& context, u32 type, u32 nr), System& system, kernel::Process* process, handle_id_t fd_id, u32 code, - io::MemoryStream* in_stream, io::MemoryStream* in_buffer_stream, - io::MemoryStream* out_stream, io::MemoryStream* out_buffer_stream, - NvResult* out_result) { + std::optional in_stream, + std::optional in_buffer_stream, + std::optional out_stream, + std::optional out_buffer_stream, NvResult* out_result) { auto fd = fd_pool.Get(fd_id); // Dispatch @@ -151,8 +152,12 @@ result_t INvDrvServices::IoctlImpl( u32 nr = code & 0xff; ioctl::IoctlContext context{ - system, process, in_stream, - in_buffer_stream, out_stream, out_buffer_stream, + .system = system, + .process = process, + .in_stream = std::move(in_stream), + .in_buffer_stream = std::move(in_buffer_stream), + .out_stream = std::move(out_stream), + .out_buffer_stream = std::move(out_buffer_stream), }; NvResult result = (fd->*func)(context, type, nr); diff --git a/src/core/horizon/services/nvdrv/nvdrv_services.hpp b/src/core/horizon/services/nvdrv/nvdrv_services.hpp index cfbbef59..51bfd885 100644 --- a/src/core/horizon/services/nvdrv/nvdrv_services.hpp +++ b/src/core/horizon/services/nvdrv/nvdrv_services.hpp @@ -50,9 +50,11 @@ class INvDrvServices : public IService { IoctlImpl(NvResult (ioctl::FdBase::*func)(ioctl::IoctlContext& context, u32 type, u32 nr), System& system, kernel::Process* process, handle_id_t fd_id, - u32 code, io::MemoryStream* in_stream, - io::MemoryStream* in_buffer_stream, io::MemoryStream* out_stream, - io::MemoryStream* out_buffer_stream, NvResult* out_result); + u32 code, std::optional in_stream, + std::optional in_buffer_stream, + std::optional out_stream, + std::optional out_buffer_stream, + NvResult* out_result); }; } // namespace hydra::horizon::services::nvdrv diff --git a/src/core/horizon/services/pl/const.hpp b/src/core/horizon/services/pl/const.hpp index 06b638a0..3df2ccc3 100644 --- a/src/core/horizon/services/pl/const.hpp +++ b/src/core/horizon/services/pl/const.hpp @@ -9,8 +9,6 @@ enum class SharedFontType : u32 { ChineseTraditional = 3, Korean = 4, NintendoExtended = 5, - - Total, }; ENABLE_ENUM_ARITHMETIC_OPERATORS(SharedFontType) diff --git a/src/core/horizon/services/pl/internal/shared_font_manager.cpp b/src/core/horizon/services/pl/internal/shared_font_manager.cpp index a7a06298..d589527d 100644 --- a/src/core/horizon/services/pl/internal/shared_font_manager.cpp +++ b/src/core/horizon/services/pl/internal/shared_font_manager.cpp @@ -19,9 +19,8 @@ struct SharedFontName { }; #define SHARED_FONT_ENTRY(type, name, filename) \ - [static_cast(SharedFontType::type)] = SharedFontName { \ - name, filename ".bfttf" \ - } + [static_cast(SharedFontType::type)] = \ + SharedFontName{name, filename ".bfttf"} constexpr SharedFontName shared_font_names[] = { SHARED_FONT_ENTRY(JapanUsEurope, "FontStandard", "nintendo_udsg-r_std_003"), @@ -108,14 +107,14 @@ SharedFontManager::SharedFontManager(System& system_) SharedFontManager::~SharedFontManager() { delete shared_memory; } void SharedFontManager::LoadFonts() { - for (SharedFontType type = SharedFontType(0); type < SharedFontType::Total; - type++) + for (auto type = SharedFontType::JapanUsEurope; + type <= SharedFontType::NintendoExtended; type++) LoadFont(type); } void SharedFontManager::LoadFont(const SharedFontType type) { auto file = GetSharedFontFile(system.GetOS().GetFilesystem(), type); - if (!file) + if (file == nullptr) return; // Load @@ -131,7 +130,7 @@ void SharedFontManager::LoadFont(const SharedFontType type) { return; // Set state - auto& state = states[u32(type)]; + auto& state = states[static_cast(type)]; state.shared_memory_offset = shared_memory_offset; state.size = file->GetSize(); shared_memory_offset += file->GetSize(); diff --git a/src/core/horizon/services/pl/internal/shared_font_manager.hpp b/src/core/horizon/services/pl/internal/shared_font_manager.hpp index 995a1ebb..1475e405 100644 --- a/src/core/horizon/services/pl/internal/shared_font_manager.hpp +++ b/src/core/horizon/services/pl/internal/shared_font_manager.hpp @@ -24,7 +24,7 @@ class SharedFontManager { kernel::SharedMemory* shared_memory; u32 shared_memory_offset{0}; - FontState states[u32(SharedFontType::Total)]{}; + FontState states[6]{}; // Helpers void LoadFont(const SharedFontType type); @@ -32,7 +32,7 @@ class SharedFontManager { public: GETTER(shared_memory, GetSharedMemory); const FontState& GetState(SharedFontType type) const { - return states[u32(type)]; + return states[static_cast(type)]; } }; diff --git a/src/core/horizon/services/pl/shared_font_manager.cpp b/src/core/horizon/services/pl/shared_font_manager.cpp index 180b2aff..89b6ffbe 100644 --- a/src/core/horizon/services/pl/shared_font_manager.cpp +++ b/src/core/horizon/services/pl/shared_font_manager.cpp @@ -55,7 +55,7 @@ result_t ISharedFontManager::GetSharedFontInOrderOfPriority( // TODO: sort by priority (void)language_code; for (SharedFontType type = SharedFontType::JapanUsEurope; - type < SharedFontType::Total; type++) { + type <= SharedFontType::NintendoExtended; type++) { const auto& state = system->GetOS().GetSharedFontManager().GetState(type); out_types_buffer.stream->Write(type); @@ -75,9 +75,10 @@ result_t ISharedFontManager::GetSharedFontInOrderOfPriorityForSystem( OutBuffer out_offsets_buffer, OutBuffer out_sizes_buffer) { // TODO: how is this different from GetSharedFontInOrderOfPriority? - return GetSharedFontInOrderOfPriority(system, language_code, out_loaded, - out_count, out_types_buffer, - out_offsets_buffer, out_sizes_buffer); + return GetSharedFontInOrderOfPriority( + system, language_code, out_loaded, out_count, + std::move(out_types_buffer), std::move(out_offsets_buffer), + std::move(out_sizes_buffer)); } } // namespace hydra::horizon::services::pl diff --git a/src/core/horizon/services/server.cpp b/src/core/horizon/services/server.cpp index 3577fea8..1abc9b54 100644 --- a/src/core/horizon/services/server.cpp +++ b/src/core/horizon/services/server.cpp @@ -1,7 +1,6 @@ #include "core/horizon/services/server.hpp" #include "core/horizon/kernel/hipc/server_port.hpp" -#include "core/horizon/kernel/hipc/service_manager.hpp" #include "core/system.hpp" namespace hydra::horizon::services { @@ -11,23 +10,21 @@ void Server::Start() { // TODO: process // Thread - thread = new kernel::HostThread( + thread.emplace( nullptr, 0x20, - [this](kernel::should_stop_fn_t should_stop) { MainLoop(should_stop); }, + [this](const kernel::should_stop_fn_t& should_stop) { + MainLoop(should_stop); + }, "Service server thread"); thread->Start(); } -void Server::Stop() { - thread->Stop(); - delete thread; - thread = nullptr; -} +void Server::Stop() { thread = std::nullopt; } void Server::RegisterPort(kernel::hipc::ServerPort* port, create_service_fn_t service_creator) { ports.push_back(port); - port_service_creators.insert({port, service_creator}); + port_service_creators.insert({port, std::move(service_creator)}); } void Server::RegisterSession(kernel::hipc::ServerSession* session, @@ -36,7 +33,7 @@ void Server::RegisterSession(kernel::hipc::ServerSession* session, session_services.insert({session, service}); } -void Server::MainLoop(kernel::should_stop_fn_t should_stop) { +void Server::MainLoop(const kernel::should_stop_fn_t& should_stop) { kernel::hipc::ServerSession* reply_target_session = nullptr; while (true) { // Wait for incoming requests @@ -48,8 +45,8 @@ void Server::MainLoop(kernel::should_stop_fn_t should_stop) { u32 signalled_index; const auto res = system.GetOS().GetKernel().ReplyAndReceive( - thread, sync_objs, reply_target_session, kernel::INFINITE_TIMEOUT, - signalled_index); + &thread.value(), sync_objs, reply_target_session, + kernel::INFINITE_TIMEOUT, signalled_index); switch (res) { case RESULT_SUCCESS: { if (signalled_index < ports.size()) { @@ -93,7 +90,7 @@ void Server::MainLoop(kernel::should_stop_fn_t should_stop) { // Handle all requests while (session->HasRequests()) { - session->Receive(thread); + session->Receive(&thread.value()); service->HandleRequest(system, session->GetActiveRequestClientProcess(), thread->GetTlsPtr()); diff --git a/src/core/horizon/services/server.hpp b/src/core/horizon/services/server.hpp index 6c8e4834..320c2b1a 100644 --- a/src/core/horizon/services/server.hpp +++ b/src/core/horizon/services/server.hpp @@ -1,8 +1,6 @@ #pragma once -#include "core/horizon/kernel/hipc/client_session.hpp" #include "core/horizon/kernel/hipc/server_session.hpp" -#include "core/horizon/kernel/hipc/service_manager.hpp" #include "core/horizon/kernel/hipc/session.hpp" #include "core/horizon/kernel/host_thread.hpp" #include "core/horizon/services/service.hpp" @@ -18,13 +16,16 @@ class ServerSession; namespace hydra::horizon::services { -typedef std::function create_service_fn_t; +using create_service_fn_t = std::function; class Server { public: Server(System& system_) : system{system_} {} ~Server() { Stop(); } + MAKE_NON_COPYABLE(Server); + MAKE_NON_MOVABLE(Server); + void Start(); void Stop(); @@ -40,7 +41,7 @@ class Server { private: System& system; - kernel::HostThread* thread{nullptr}; + std::optional thread; std::map port_service_creators; @@ -49,10 +50,7 @@ class Server { std::vector ports; std::vector sessions; - void MainLoop(kernel::should_stop_fn_t should_stop); - - public: - GETTER(thread, GetThread); + void MainLoop(const kernel::should_stop_fn_t& should_stop); }; } // namespace hydra::horizon::services diff --git a/src/core/horizon/services/service.cpp b/src/core/horizon/services/service.cpp index e3164653..73ae84ac 100644 --- a/src/core/horizon/services/service.cpp +++ b/src/core/horizon/services/service.cpp @@ -9,11 +9,6 @@ namespace hydra::horizon::services { -IService::~IService() { - if (subservice_pool) - delete subservice_pool; -} - void IService::HandleRequest(System& system, kernel::Process* caller_process, uptr ptr) { // HIPC header @@ -24,7 +19,7 @@ void IService::HandleRequest(System& system, kernel::Process* caller_process, (command_type >= kernel::hipc::cmif::CommandType::TipcCommandRegion); if (!is_tipc) hipc_in.data.data_words = - kernel::hipc::cmif::align_data_start(hipc_in.data.data_words); + kernel::hipc::cmif::AlignDataStart(hipc_in.data.data_words); // Scratch memory u8 scratch_buffer[0x200]; @@ -38,9 +33,9 @@ void IService::HandleRequest(System& system, kernel::Process* caller_process, scratch_buffer_copy_handles, scratch_buffer_move_handles); RequestContext context{ - system, - caller_process, - streams, + .system = system, + .process = caller_process, + .streams = streams, }; // Dispatch @@ -103,14 +98,14 @@ void IService::HandleRequest(System& system, kernel::Process* caller_process, kernel::hipc::make_request(reinterpret_cast(ptr), meta); if (!is_tipc) response.data_words = - kernel::hipc::cmif::align_data_start(response.data_words); + kernel::hipc::cmif::AlignDataStart(response.data_words); u8* data_start = reinterpret_cast(response.data_words); if (command_type < kernel::hipc::cmif::CommandType::TipcCommandRegion) // TODO: is this // really how it // works? - data_start = align_ptr(data_start, 0x10); + data_start = AlignPtr(data_start, 0x10); WRITE_ARRAY(out_stream, data_start); if (streams.out_objects_stream.GetSeek() != 0) { memcpy(data_start + GET_ARRAY_SIZE(out_stream) * sizeof(u32), @@ -178,9 +173,8 @@ void IService::Request(RequestContext& context) { auto objects = context.streams.in_stream.GetPtr() + context.streams.in_stream.GetSeek() + cmif_in.data_size; - context.streams.in_objects_stream = io::MemoryStream( - std::span(reinterpret_cast(objects), - cmif_in.num_in_objects * sizeof(handle_id_t))); + context.streams.in_objects_stream.emplace(std::span( + objects, cmif_in.num_in_objects * sizeof(handle_id_t))); } kernel::hipc::cmif::write_domain_out_header(context.streams.out_stream); @@ -229,7 +223,7 @@ void IService::Control(RequestContext& context) { switch (command) { case kernel::hipc::cmif::ControlCommandType::ConvertCurrentObjectToDomain: { is_domain = true; - subservice_pool = new DynamicPool(); + subservice_pool.emplace(); const auto handle_id = AddSubservice(this->Retain()); context.streams.out_stream.Write(handle_id); *result = RESULT_SUCCESS; @@ -244,7 +238,7 @@ void IService::Control(RequestContext& context) { context.streams.out_stream.Write( 0x8000); // The highest known pointer buffer // size (used by nvservices) - // *result = RESULT_SUCCESS; + *result = RESULT_SUCCESS; break; case kernel::hipc::cmif::ControlCommandType::CloneCurrentObjectEx: // TODO: u32 tag diff --git a/src/core/horizon/services/service.hpp b/src/core/horizon/services/service.hpp index b578bd20..fb6c4469 100644 --- a/src/core/horizon/services/service.hpp +++ b/src/core/horizon/services/service.hpp @@ -25,6 +25,11 @@ struct RequestContext { class IService { public: + IService() noexcept = default; + virtual ~IService() noexcept = default; + + MAKE_NON_COPYABLE(IService); + void HandleRequest(System& system, kernel::Process* caller_process, uptr ptr); @@ -42,15 +47,13 @@ class IService { } protected: - virtual ~IService(); - virtual result_t RequestImpl(RequestContext& context, u32 id) = 0; u32 AddSubservice(IService* service) { - if (!service) + if (service == nullptr) return INVALID_HANDLE_ID; - return parent->subservice_pool->Add(service); + return parent->subservice_pool->Insert(service); } void FreeSubservice(handle_id_t handle_id) { @@ -70,7 +73,7 @@ class IService { // Domain bool is_domain{false}; IService* parent{this}; - DynamicPool* subservice_pool{nullptr}; + std::optional> subservice_pool; void Close(); void Request(RequestContext& context); diff --git a/src/core/horizon/services/settings/system_settings_server.cpp b/src/core/horizon/services/settings/system_settings_server.cpp index ead38acb..9c3902a9 100644 --- a/src/core/horizon/services/settings/system_settings_server.cpp +++ b/src/core/horizon/services/settings/system_settings_server.cpp @@ -42,7 +42,7 @@ result_t ISystemSettingsServer::GetSettingsItemValueSize( auto name = in_name_buffer.stream->ReadNullTerminatedString(); auto item_key = in_item_key_buffer.stream->ReadNullTerminatedString(); const auto* value = GetSettingsValue(name, item_key); - if (!value) { + if (value == nullptr) { // TODO: error return RESULT_SUCCESS; } @@ -69,7 +69,7 @@ result_t ISystemSettingsServer::GetSettingsItemValue( auto name = in_name_buffer.stream->ReadNullTerminatedString(); auto item_key = in_item_key_buffer.stream->ReadNullTerminatedString(); const auto* value = GetSettingsValue(name, item_key); - if (!value) { + if (value == nullptr) { // TODO: error return RESULT_SUCCESS; } @@ -111,7 +111,7 @@ result_t ISystemSettingsServer::GetTvSettings(TvSettings* out_settings) { result_t ISystemSettingsServer::GetDebugModeFlag(bool* out_flag) { auto value = GetSettingsValue("settings_debug", "is_debug_mode_enabled"); - if (!value) { + if (value == nullptr) { *out_flag = true; return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/sm/user_interface.cpp b/src/core/horizon/services/sm/user_interface.cpp index 17b3226b..1b48b05a 100644 --- a/src/core/horizon/services/sm/user_interface.cpp +++ b/src/core/horizon/services/sm/user_interface.cpp @@ -16,11 +16,11 @@ result_t IUserInterface::GetServiceHandle(System* system, kernel::Process* process, u64 name, OutHandle out_handle) { - LOG_DEBUG(Services, "Service name: \"{}\"", u64_to_str(name)); + LOG_DEBUG(Services, "Service name: \"{}\"", U64AsString(name)); auto client_port = system->GetOS().GetServiceManager().GetPort(name); - if (!client_port) { - LOG_WARN(Services, "Unknown service name \"{}\"", u64_to_str(name)); + if (client_port == nullptr) { + LOG_WARN(Services, "Unknown service name \"{}\"", U64AsString(name)); return MAKE_RESULT(Svc, kernel::Error::NotFound); // TODO: module } @@ -40,10 +40,10 @@ IUserInterface::RegisterService(System* system, kernel::Process* process, (void)is_light; (void)max_sessions; - LOG_DEBUG(Services, "Service name: \"{}\"", u64_to_str(name)); + LOG_DEBUG(Services, "Service name: \"{}\"", U64AsString(name)); // Debug - std::string debug_name = u64_to_str(name); + std::string debug_name = U64AsString(name); // Session auto server_port = new kernel::hipc::ServerPort( @@ -64,7 +64,7 @@ IUserInterface::RegisterService(System* system, kernel::Process* process, result_t IUserInterface::AtmosphereHasService(System* system, u64 name, bool* out_has_service) { - LOG_DEBUG(Services, "Service name: \"{}\"", u64_to_str(name)); + LOG_DEBUG(Services, "Service name: \"{}\"", U64AsString(name)); auto client_port = system->GetOS().GetServiceManager().GetPort(name); *out_has_service = (client_port != nullptr); @@ -73,7 +73,7 @@ result_t IUserInterface::AtmosphereHasService(System* system, u64 name, result_t IUserInterface::AtmosphereWaitService(u64 name) { // TODO: does this wait for the service to start? - LOG_FUNC_WITH_ARGS_STUBBED(Services, "name: {}", u64_to_str(name)); + LOG_FUNC_WITH_ARGS_STUBBED(Services, "name: {}", U64AsString(name)); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/ssl/sf/ssl_service.cpp b/src/core/horizon/services/ssl/sf/ssl_service.cpp index e7aced6c..171b1eb9 100644 --- a/src/core/horizon/services/ssl/sf/ssl_service.cpp +++ b/src/core/horizon/services/ssl/sf/ssl_service.cpp @@ -8,7 +8,7 @@ DEFINE_SERVICE_COMMAND_TABLE(ISslService, 0, CreateContext, 5, SetInterfaceVersion) result_t ISslService::CreateContext(RequestContext* ctx, - aligned version, + Aligned version, u64 pid_placeholder) { (void)pid_placeholder; diff --git a/src/core/horizon/services/ssl/sf/ssl_service.hpp b/src/core/horizon/services/ssl/sf/ssl_service.hpp index 3db596bf..58143a11 100644 --- a/src/core/horizon/services/ssl/sf/ssl_service.hpp +++ b/src/core/horizon/services/ssl/sf/ssl_service.hpp @@ -12,7 +12,7 @@ class ISslService : public IService { private: // Commands - result_t CreateContext(RequestContext* ctx, aligned version, + result_t CreateContext(RequestContext* ctx, Aligned version, u64 pid_placeholder); result_t SetInterfaceVersion(SystemVersion version); }; diff --git a/src/core/horizon/services/timesrv/internal/time_zone_manager.cpp b/src/core/horizon/services/timesrv/internal/time_zone_manager.cpp index 0496f661..ece1609e 100644 --- a/src/core/horizon/services/timesrv/internal/time_zone_manager.cpp +++ b/src/core/horizon/services/timesrv/internal/time_zone_manager.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/timesrv/internal/time_zone_manager.hpp" -#include "date/tz.h" +#include #include "core/horizon/filesystem/content_archive.hpp" #include "core/horizon/filesystem/file.hpp" @@ -44,7 +44,7 @@ TimeZoneManager::TimeZoneManager(filesystem::Filesystem& filesystem_) const auto stream = list_file->Open(filesystem::FileOpenFlags::Read); char buffer[256]; u32 str_size = 0; - while (stream->GetRemainingSize()) { + while (stream->GetRemainingSize() != 0u) { const auto c = stream->Read(); switch (c) { case '\n': { diff --git a/src/core/horizon/services/timesrv/internal/tzif.cpp b/src/core/horizon/services/timesrv/internal/tzif.cpp index 1b296f80..86bf3960 100644 --- a/src/core/horizon/services/timesrv/internal/tzif.cpp +++ b/src/core/horizon/services/timesrv/internal/tzif.cpp @@ -23,7 +23,7 @@ struct TzifHeader { }; template -static T Decode(T value) { +T Decode(T value) { if constexpr (std::endian::native == std::endian::little) { return std::byteswap(value); } else { @@ -31,11 +31,9 @@ static T Decode(T value) { } } -static bool DifferByRepeat(i64 t1, i64 t0) { - return (t1 - t0) == SECONDS_PER_REPEAT; -} +bool DifferByRepeat(i64 t1, i64 t0) { return (t1 - t0) == SECONDS_PER_REPEAT; } -static bool TimeTypeEquals(const TimeZoneRule& rule, u8 a_index, u8 b_index) { +bool TimeTypeEquals(const TimeZoneRule& rule, u8 a_index, u8 b_index) { if (a_index < 0 || a_index >= rule.type_count || b_index < 0 || b_index >= rule.type_count) { return false; @@ -56,10 +54,9 @@ static bool TimeTypeEquals(const TimeZoneRule& rule, u8 a_index, u8 b_index) { // From Ryujinx void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { - TzifHeader header = stream->Read(); - ASSERT_THROWING(header.magic == make_magic4('T', 'Z', 'i', 'f'), Services, - ParseTimeZoneBinaryError::InvalidMagic, - "Invalid TZif magic {:#x}", header.magic); + const auto header = stream->Read(); + ASSERT(header.magic == make_magic4('T', 'Z', 'i', 'f'), Services, + "Invalid TZif magic {:#x}", header.magic); u32 data_size = static_cast(stream->GetRemainingSize()); @@ -70,19 +67,17 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { u32 type_count = Decode(header.type_count); u32 char_count = Decode(header.char_count); - ASSERT_THROWING(leap_count < TimeZoneRule::MAX_LEAP_COUNT && - type_count < TimeZoneRule::MAX_TYPE_COUNT && - time_count < TimeZoneRule::MAX_TIME_COUNT && - char_count < TimeZoneRule::MAX_CHAR_COUNT && - (ttis_std_count == type_count || ttis_std_count == 0) && - (ttis_gmt_count == type_count || ttis_gmt_count == 0), - Services, ParseTimeZoneBinaryError::InvalidBinary, - "Invalid header parameters"); - ASSERT_THROWING((time_count * sizeof(u64) + time_count + type_count * 6 + - char_count + leap_count * (sizeof(u64) + 4) + - ttis_std_count + ttis_gmt_count) <= data_size, - Services, ParseTimeZoneBinaryError::InsufficientDataSize, - "Insufficient data size"); + ASSERT(leap_count < TimeZoneRule::MAX_LEAP_COUNT && + type_count < TimeZoneRule::MAX_TYPE_COUNT && + time_count < TimeZoneRule::MAX_TIME_COUNT && + char_count < TimeZoneRule::MAX_CHAR_COUNT && + (ttis_std_count == type_count || ttis_std_count == 0) && + (ttis_gmt_count == type_count || ttis_gmt_count == 0), + Services, "Invalid header parameters"); + ASSERT((time_count * sizeof(u64) + time_count + type_count * 6 + + char_count + leap_count * (sizeof(u64) + 4) + ttis_std_count + + ttis_gmt_count) <= data_size, + Services, "Insufficient data size"); out_rule.time_count = time_count; out_rule.type_count = type_count; @@ -95,10 +90,8 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { out_rule.type_indices[i] = 1; if (time_count != 0 && at <= out_rule.ats[time_count - 1]) { - ASSERT_THROWING(at >= out_rule.ats[time_count - 1], Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid at ({} < {})", at, - out_rule.ats[time_count - 1]); + ASSERT(at >= out_rule.ats[time_count - 1], Services, + "Invalid at ({} < {})", at, out_rule.ats[time_count - 1]); out_rule.type_indices[i - 1] = 0; time_count--; @@ -110,10 +103,9 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { time_count = 0; for (u32 i = 0; i < out_rule.time_count; i++) { const auto type_index = stream->Read(); - ASSERT_THROWING(type_index < out_rule.type_count, Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid type index ({} >= {})", type_index, - out_rule.type_count); + ASSERT(type_index < out_rule.type_count, Services, + "Invalid type index ({} >= {})", type_index, + out_rule.type_count); if (out_rule.type_indices[i] != 0) out_rule.type_indices[time_count++] = type_index; @@ -126,18 +118,14 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { type_info.gmt_offset = Decode(stream->Read()); const auto is_day_saving_time = stream->Read(); - ASSERT_THROWING(is_day_saving_time < 2, Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid is day saving time boolean {}", - is_day_saving_time); + ASSERT(is_day_saving_time < 2, Services, + "Invalid is day saving time boolean {}", is_day_saving_time); type_info.is_day_saving_time = (is_day_saving_time != 0); u32 abbreviation_list_index = stream->Read(); - ASSERT_THROWING(abbreviation_list_index < TimeZoneRule::MAX_CHAR_COUNT, - Services, ParseTimeZoneBinaryError::InvalidBinary, - "Invalid abbreviation list index {}", - abbreviation_list_index); + ASSERT(abbreviation_list_index < TimeZoneRule::MAX_CHAR_COUNT, Services, + "Invalid abbreviation list index {}", abbreviation_list_index); type_info.abbreviation_list_index = abbreviation_list_index; } @@ -150,10 +138,9 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { out_rule.type_infos[i].is_standard_time_daylight = false; } else { const auto is_standard_time_daylight = stream->Read(); - ASSERT_THROWING(is_standard_time_daylight < 2, Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid is standard time daylight boolean {}", - is_standard_time_daylight); + ASSERT(is_standard_time_daylight < 2, Services, + "Invalid is standard time daylight boolean {}", + is_standard_time_daylight); out_rule.type_infos[i].is_standard_time_daylight = (is_standard_time_daylight != 0); @@ -165,18 +152,15 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { out_rule.type_infos[i].is_gmt = false; } else { const auto is_gmt = stream->Read(); - ASSERT_THROWING(is_gmt < 2, Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid is GMT boolean {}", is_gmt); + ASSERT(is_gmt < 2, Services, "Invalid is GMT boolean {}", is_gmt); out_rule.type_infos[i].is_gmt = (is_gmt != 0); } } u32 name_len = static_cast(stream->GetRemainingSize()); - ASSERT_THROWING(name_len <= (TimeZoneRule::MAX_NAME_LEN + 1), Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid name length {}", name_len); + ASSERT(name_len <= (TimeZoneRule::MAX_NAME_LEN + 1), Services, + "Invalid name length {}", name_len); char tmp_name[TimeZoneRule::MAX_NAME_LEN + 1]; stream->ReadToSpan(std::span(tmp_name, name_len)); @@ -192,9 +176,7 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { LOG_NOT_IMPLEMENTED(Services, "Time zone name parsing"); } - ASSERT_THROWING(out_rule.type_count > 0, Services, - ParseTimeZoneBinaryError::InvalidBinary, - "Invalid type count"); + ASSERT(out_rule.type_count > 0, Services, "Invalid type count"); if (out_rule.time_count > 1) { for (u32 i = 1; i < out_rule.time_count; i++) { @@ -248,7 +230,7 @@ void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule) { } } - out_rule.default_type = static_cast(default_type); + out_rule.default_type = default_type; } else { out_rule.default_type = 0; } diff --git a/src/core/horizon/services/timesrv/internal/tzif.hpp b/src/core/horizon/services/timesrv/internal/tzif.hpp index a21fdf0f..57ba3b48 100644 --- a/src/core/horizon/services/timesrv/internal/tzif.hpp +++ b/src/core/horizon/services/timesrv/internal/tzif.hpp @@ -4,12 +4,6 @@ namespace hydra::horizon::services::timesrv::internal { -enum class ParseTimeZoneBinaryError { - InvalidMagic, - InvalidBinary, - InsufficientDataSize, -}; - void ParseTimeZoneBinary(io::IStream* stream, TimeZoneRule& out_rule); } // namespace hydra::horizon::services::timesrv::internal diff --git a/src/core/horizon/services/timesrv/time_zone_service.cpp b/src/core/horizon/services/timesrv/time_zone_service.cpp index 2ce4f859..91ca746c 100644 --- a/src/core/horizon/services/timesrv/time_zone_service.cpp +++ b/src/core/horizon/services/timesrv/time_zone_service.cpp @@ -117,7 +117,7 @@ result_t ITimeZoneService::ToCalendarTimeImpl( static_cast((std::chrono::sys_days{ymd} - std::chrono::sys_days{ymd.year() / 1 / 0}) .count()), - .timezone_name = ToU64String(tz_name), + .timezone_name = StringAsU64(tz_name), .dst = info.is_day_saving_time ? 1u : 0u, .seconds_rel_to_utc = info.gmt_offset, }; diff --git a/src/core/horizon/services/usb/hs/client_root_session.cpp b/src/core/horizon/services/usb/hs/client_root_session.cpp index 7bd7edac..19bd4bed 100644 --- a/src/core/horizon/services/usb/hs/client_root_session.cpp +++ b/src/core/horizon/services/usb/hs/client_root_session.cpp @@ -21,7 +21,7 @@ result_t IClientRootSession::BindClientProcess() { } result_t IClientRootSession::CreateInterfaceAvailableEvent( - kernel::Process* process, aligned index, DeviceFilter device_filter, + kernel::Process* process, Aligned index, DeviceFilter device_filter, OutHandle out_handle) { LOG_FUNC_WITH_ARGS_STUBBED(Services, "index: {}, device filter: {}", index, device_filter); diff --git a/src/core/horizon/services/usb/hs/client_root_session.hpp b/src/core/horizon/services/usb/hs/client_root_session.hpp index 9a6c54eb..059a8e78 100644 --- a/src/core/horizon/services/usb/hs/client_root_session.hpp +++ b/src/core/horizon/services/usb/hs/client_root_session.hpp @@ -38,7 +38,7 @@ class IClientRootSession : public IService { // Commands result_t BindClientProcess(); // 2.0.0+ result_t CreateInterfaceAvailableEvent( - kernel::Process* process, aligned index, + kernel::Process* process, Aligned index, DeviceFilter device_filter, OutHandle out_handle); result_t GetInterfaceStateChangeEvent(kernel::Process* process, diff --git a/src/core/horizon/services/visrv/application_display_service.cpp b/src/core/horizon/services/visrv/application_display_service.cpp index cde683bc..30d25f42 100644 --- a/src/core/horizon/services/visrv/application_display_service.cpp +++ b/src/core/horizon/services/visrv/application_display_service.cpp @@ -37,8 +37,8 @@ result_t IApplicationDisplayService::GetRelayService(RequestContext* ctx, const auto name = "dispdrv"_u64; auto client_port = system->GetOS().GetServiceManager().GetPort(name); - if (!client_port) { - LOG_WARN(Services, "Unknown service name \"{}\"", u64_to_str(name)); + if (client_port == nullptr) { + LOG_WARN(Services, "Unknown service name \"{}\"", U64AsString(name)); return MAKE_RESULT(Svc, kernel::Error::NotFound); // TODO: module } @@ -140,7 +140,7 @@ result_t IApplicationDisplayService::OpenLayer( layer.Open(); // Parcel - hosbinder::ParcelWriter parcel_writer(parcel_buffer.stream); + hosbinder::ParcelWriter parcel_writer(parcel_buffer.stream.value()); parcel_writer.WriteObject(layer.GetBinderID(), "dispdrv"_u64); parcel_writer.Finish(); @@ -155,7 +155,7 @@ result_t IApplicationDisplayService::CloseLayer(System* system, u64 layer_id) { } result_t IApplicationDisplayService::CreateStrayLayer( - System* system, kernel::Process* process, aligned flags, + System* system, kernel::Process* process, Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { return CreateStrayLayerImpl(*system, process, flags, display_id, diff --git a/src/core/horizon/services/visrv/application_display_service.hpp b/src/core/horizon/services/visrv/application_display_service.hpp index aea812d3..84a5330e 100644 --- a/src/core/horizon/services/visrv/application_display_service.hpp +++ b/src/core/horizon/services/visrv/application_display_service.hpp @@ -17,7 +17,6 @@ class IApplicationDisplayService : public DisplayServiceBase { result_t RequestImpl([[maybe_unused]] RequestContext& context, u32 id) override; - protected: // Commands result_t GetRelayService(RequestContext* ctx, System* system); result_t GetSystemDisplayService(RequestContext* ctx); @@ -38,7 +37,7 @@ class IApplicationDisplayService : public DisplayServiceBase { result_t CloseLayer(System* system, u64 layer_id); result_t CreateStrayLayer(System* system, kernel::Process* process, - aligned flags, u64 display_id, u64* out_layer_id, + Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); result_t DestroyStrayLayer(System* system, u64 layer_id); diff --git a/src/core/horizon/services/visrv/display_service_base.cpp b/src/core/horizon/services/visrv/display_service_base.cpp index cec35884..6641d750 100644 --- a/src/core/horizon/services/visrv/display_service_base.cpp +++ b/src/core/horizon/services/visrv/display_service_base.cpp @@ -8,7 +8,7 @@ namespace hydra::horizon::services::visrv { result_t DisplayServiceBase::CreateStrayLayerImpl( System& system, kernel::Process* process, u32 flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, - io::MemoryStream* out_parcel_stream) { + std::optional out_parcel_stream) { (void)flags; (void)display_id; @@ -20,7 +20,7 @@ result_t DisplayServiceBase::CreateStrayLayerImpl( system.GetOS().GetDisplayDriver().CreateLayer(process, binder_id); // Parcel - hosbinder::ParcelWriter parcel_writer(out_parcel_stream); + hosbinder::ParcelWriter parcel_writer(out_parcel_stream.value()); parcel_writer.WriteObject(binder_id, "dispdrv"_u64); parcel_writer.Finish(); diff --git a/src/core/horizon/services/visrv/display_service_base.hpp b/src/core/horizon/services/visrv/display_service_base.hpp index cc704d9b..17869511 100644 --- a/src/core/horizon/services/visrv/display_service_base.hpp +++ b/src/core/horizon/services/visrv/display_service_base.hpp @@ -7,10 +7,11 @@ namespace hydra::horizon::services::visrv { class DisplayServiceBase : public IService { protected: - result_t CreateStrayLayerImpl(System& system, kernel::Process* process, - u32 flags, u64 display_id, u64* out_layer_id, - u64* out_native_window_size, - io::MemoryStream* out_parcel_stream); + result_t + CreateStrayLayerImpl(System& system, kernel::Process* process, u32 flags, + u64 display_id, u64* out_layer_id, + u64* out_native_window_size, + std::optional out_parcel_stream); result_t SetLayerVisibilityImpl(u64 layer_id, bool visible); }; diff --git a/src/core/horizon/services/visrv/manager_display_service.cpp b/src/core/horizon/services/visrv/manager_display_service.cpp index 9df48e41..b83d56a1 100644 --- a/src/core/horizon/services/visrv/manager_display_service.cpp +++ b/src/core/horizon/services/visrv/manager_display_service.cpp @@ -11,7 +11,7 @@ DEFINE_SERVICE_COMMAND_TABLE(IManagerDisplayService, 2010, CreateManagedLayer, // TODO: flags, display ID result_t IManagerDisplayService::CreateManagedLayer(System* system, kernel::Process* process, - aligned flags, + Aligned flags, u64 display_id, u64 aruid, u64* out_layer_id) { (void)flags; @@ -35,7 +35,7 @@ result_t IManagerDisplayService::DestroyManagedLayer(System* system, } result_t IManagerDisplayService::CreateStrayLayer( - System* system, kernel::Process* process, aligned flags, + System* system, kernel::Process* process, Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { return CreateStrayLayerImpl(*system, process, flags, display_id, diff --git a/src/core/horizon/services/visrv/manager_display_service.hpp b/src/core/horizon/services/visrv/manager_display_service.hpp index 16ddf533..0c5318cb 100644 --- a/src/core/horizon/services/visrv/manager_display_service.hpp +++ b/src/core/horizon/services/visrv/manager_display_service.hpp @@ -12,12 +12,12 @@ class IManagerDisplayService : public DisplayServiceBase { private: // Commands result_t CreateManagedLayer(System* system, kernel::Process* process, - aligned flags, u64 display_id, + Aligned flags, u64 display_id, u64 aruid, u64* out_layer_id); result_t DestroyManagedLayer(System* system, u64 layer_id); result_t CreateStrayLayer(System* system, kernel::Process* process, - aligned flags, u64 display_id, u64* out_layer_id, + Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); result_t AddToLayerStack(u32 stack, u64 layer_id); diff --git a/src/core/horizon/services/visrv/system_display_service.cpp b/src/core/horizon/services/visrv/system_display_service.cpp index adb9c109..9ac1a4f8 100644 --- a/src/core/horizon/services/visrv/system_display_service.cpp +++ b/src/core/horizon/services/visrv/system_display_service.cpp @@ -32,7 +32,7 @@ result_t ISystemDisplayService::SetLayerSize(System* system, u64 layer_id, system->GetOS() .GetDisplayDriver() .GetLayer(static_cast(layer_id)) - .SetSize({u32(width), u32(height)}); + .SetSize({static_cast(width), static_cast(height)}); return RESULT_SUCCESS; } @@ -45,7 +45,7 @@ result_t ISystemDisplayService::SetLayerZ(System* system, u64 layer_id, i64 z) { } result_t ISystemDisplayService::CreateStrayLayer( - System* system, kernel::Process* process, aligned flags, + System* system, kernel::Process* process, Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { return CreateStrayLayerImpl(*system, process, flags, display_id, diff --git a/src/core/horizon/services/visrv/system_display_service.hpp b/src/core/horizon/services/visrv/system_display_service.hpp index f7763230..f95dc1a6 100644 --- a/src/core/horizon/services/visrv/system_display_service.hpp +++ b/src/core/horizon/services/visrv/system_display_service.hpp @@ -17,7 +17,7 @@ class ISystemDisplayService : public DisplayServiceBase { result_t SetLayerZ(System* system, u64 layer_id, i64 z); result_t CreateStrayLayer(System* system, kernel::Process* process, - aligned flags, u64 display_id, u64* out_layer_id, + Aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); result_t SetLayerVisibility(u64 layer_id, bool visible); diff --git a/src/core/hw/generic_mmu.hpp b/src/core/hw/generic_mmu.hpp index a708dcde..506ebc28 100644 --- a/src/core/hw/generic_mmu.hpp +++ b/src/core/hw/generic_mmu.hpp @@ -7,6 +7,11 @@ namespace hydra::hw { // TODO: get rid of this bs template class GenericMmu { + friend Subclass; + + private: + GenericMmu() noexcept = default; + public: void Map(uptr base, Impl impl) { mapped_ranges[base] = impl; diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/memory.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/memory.hpp index 35f576f2..9781077e 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/memory.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/memory.hpp @@ -22,7 +22,7 @@ class Memory : public IMemory { // Helpers void Allocate() { ptr = reinterpret_cast(malloc(GetSize())); } - void Free() { free(reinterpret_cast(ptr)); } + void Free() const { free(reinterpret_cast(ptr)); } }; } // namespace hydra::hw::tegra_x1::cpu::dynarmic diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.cpp b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.cpp index c6083e5a..1801218b 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.cpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.cpp @@ -55,23 +55,6 @@ void Mmu::Protect(Range range, } } -void Mmu::ResizeHeap(IMemory* heap_mem, vaddr_t va, u64 size) { - auto mem_impl = static_cast(heap_mem); - - mem_impl->Resize(size); - - auto memory_ptr = mem_impl->GetPtr(); - - u64 va_page = va / GUEST_PAGE_SIZE; - u64 size_page = size / GUEST_PAGE_SIZE; - u64 va_page_end = va_page + size_page; - for (u64 page = va_page; page < va_page_end; ++page) { - auto page_ptr = memory_ptr + ((page - va_page) * GUEST_PAGE_SIZE); - pages[page] = page_ptr; - states[page] = states[va_page]; - } -} - uptr Mmu::UnmapAddr(vaddr_t va) const { auto page = va / GUEST_PAGE_SIZE; auto page_offset = va % GUEST_PAGE_SIZE; diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp index 6f028764..37d00461 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp @@ -19,8 +19,6 @@ class Mmu : public IMmu { void Protect(Range range, horizon::kernel::MemoryPermission perm) override; - void ResizeHeap(IMemory* heap_mem, vaddr_t va, u64 size) override; - uptr UnmapAddr(vaddr_t va) const override; MemoryRegion QueryRegion(vaddr_t va) const override; void SetMemoryAttribute(Range range, diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp b/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp index e1061f50..8d30e297 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp @@ -28,8 +28,7 @@ static Dynarmic::ExclusiveMonitor Thread::Thread(WallClock& wall_clock, IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, vaddr_t tls_mem_base) - : IThread(wall_clock, mmu, callbacks, tls_mem) { - tpidrro_el0 = tls_mem_base; + : IThread(wall_clock, mmu, callbacks, tls_mem), tpidrro_el0{tls_mem_base} { // TODO: tpidr_el0? // Create JIT @@ -56,7 +55,7 @@ Thread::Thread(WallClock& wall_clock, IMmu* mmu, config.enable_cycle_counting = false; // Code cache size - config.code_cache_size = 128 * 1024 * 1024; // 128_MiB; + config.code_cache_size = static_cast(128 * 1024 * 1024); // 128_MiB; // TODO: make this configurable // config.optimizations = Dyn::no_optimizations; @@ -112,17 +111,17 @@ void Thread::MemoryWrite128(u64 addr, Dynarmic::A64::Vector value) { MMU->Write(addr, value); } -bool Thread::MemoryWriteExclusive8(u64 addr, u8 value, u8) { +bool Thread::MemoryWriteExclusive8(u64 addr, u8 value, u8 /*unused*/) { MMU->WriteExclusive(addr, value); return true; } -bool Thread::MemoryWriteExclusive16(u64 addr, u16 value, u16) { +bool Thread::MemoryWriteExclusive16(u64 addr, u16 value, u16 /*unused*/) { MMU->WriteExclusive(addr, value); return true; } -bool Thread::MemoryWriteExclusive32(u64 addr, u32 value, u32) { +bool Thread::MemoryWriteExclusive32(u64 addr, u32 value, u32 /*unused*/) { MMU->WriteExclusive(addr, value); return true; } diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp index ea5468a3..d3fabd81 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp @@ -62,9 +62,9 @@ class Thread final : public IThread, private Dynarmic::A64::UserCallbacks { void MemoryWrite64(u64 addr, u64 value) override; void MemoryWrite128(u64 addr, Dynarmic::A64::Vector value) override; - bool MemoryWriteExclusive8(u64 addr, u8 value, u8) override; - bool MemoryWriteExclusive16(u64 addr, u16 value, u16) override; - bool MemoryWriteExclusive32(u64 addr, u32 value, u32) override; + bool MemoryWriteExclusive8(u64 addr, u8 value, u8 /*unused*/) override; + bool MemoryWriteExclusive16(u64 addr, u16 value, u16 /*unused*/) override; + bool MemoryWriteExclusive32(u64 addr, u32 value, u32 /*unused*/) override; bool MemoryWriteExclusive64(u64 addr, u64 value, u64 expected) override; bool MemoryWriteExclusive128(u64 addr, Dynarmic::A64::Vector value, Dynarmic::A64::Vector expected) override; diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp index bc292fe5..456a5e0a 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp @@ -53,18 +53,12 @@ enum class ApFlags : u64 { constexpr u64 AP_FLAGS_MASK = (1ull << PNX_SHIFT) | (1ull << UXN_SHIFT) | (3ull << AP_SHIFT); -enum class AllocateVmMemoryError { - AllocationFailed, -}; - inline uptr AllocateVmMemory(u64 size) { ASSERT_ALIGNMENT(size, APPLE_PAGE_SIZE, Hypervisor, "size") void* ptr; const auto res = posix_memalign(&ptr, APPLE_PAGE_SIZE, size); - ASSERT_THROWING(res == 0, Hypervisor, - AllocateVmMemoryError::AllocationFailed, - "Failed to allocate memory: {:#x}", res); + ASSERT(res == 0, Hypervisor, "Failed to allocate memory: {:#x}", res); return reinterpret_cast(ptr); } diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp index 33ec6c6b..85e047b9 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp @@ -54,9 +54,9 @@ Cpu::Cpu() // Kernel memory kernel_page_table.Map( 0x0, Range::FromSize(kernel_mem.GetPtr(), KERNEL_MEM_SIZE), - {horizon::kernel::MemoryType::Kernel, - horizon::kernel::MemoryAttribute::None, - horizon::kernel::MemoryPermission::Execute}, + {.type = horizon::kernel::MemoryType::Kernel, + .attr = horizon::kernel::MemoryAttribute::None, + .perm = horizon::kernel::MemoryPermission::Execute}, ApFlags::UserNoneKernelReadExecute); for (u64 offset = 0; offset < 0x780; offset += 0x80) { @@ -86,8 +86,6 @@ Cpu::Cpu() .supports_synchronous_single_step = false}; } -Cpu::~Cpu() {} - IMmu* Cpu::CreateMmu(System& system) { return new Mmu(system); } IThread* Cpu::CreateThread(WallClock& wall_clock, IMmu* mmu, diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp index 8c7c2172..f7e9eb90 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp @@ -15,7 +15,6 @@ class IMmu; namespace hydra::hw::tegra_x1::cpu::hypervisor { class Mmu; -class Thread; class VirtualMachine { public: @@ -26,7 +25,7 @@ class VirtualMachine { class Cpu : public ICpu { public: Cpu(); - ~Cpu(); + ~Cpu() noexcept override = default; IMmu* CreateMmu(System& system) override; IThread* CreateThread(WallClock& wall_clock, IMmu* mmu, diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp index a2321957..712d88d6 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp @@ -50,7 +50,7 @@ inline ApFlags ToApFlags(horizon::kernel::MemoryPermission perm) { } // TODO: this is a horrible way to handle this -static bool page_table_regions[16] = {false}; +bool page_table_regions[16] = {false}; paddr_t FindFreePageTableRegion() { for (u32 i = 0; i < 16; i++) { @@ -127,16 +127,6 @@ void Mmu::Protect(Range range, user_page_table.SetMemoryPermission(range, perm, ToApFlags(perm)); } -// TODO: just improve this... -void Mmu::ResizeHeap(IMemory* heap_mem, vaddr_t va, u64 size) { - (void)heap_mem; - - const auto region = user_page_table.QueryRegion(va); - paddr_t pa = region.UnmapAddr(va); - user_page_table.Map(va, Range::FromSize(pa, size), region.state, - ToApFlags(region.state.perm)); -} - uptr Mmu::UnmapAddr(vaddr_t va) const { return user_page_table.UnmapAddr(va); } MemoryRegion Mmu::QueryRegion(vaddr_t va) const { diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp index 633f22f7..82da90f7 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp @@ -21,8 +21,6 @@ class Mmu : public IMmu { void Protect(Range range, horizon::kernel::MemoryPermission perm) override; - void ResizeHeap(IMemory* heap_mem, vaddr_t va, u64 size) override; - uptr UnmapAddr(vaddr_t va) const override; MemoryRegion QueryRegion(vaddr_t va) const override; void SetMemoryAttribute(Range range, diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp index 1a781fbc..1a50583b 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp @@ -37,7 +37,7 @@ void PageAllocator::Allocate(usize page_count) { HV_ASSERT_SUCCESS( hv_vm_map(reinterpret_cast(ptr), pa, size, HV_MEMORY_READ)); - allocations.push_back({ptr, page_count}); + allocations.push_back({.ptr = ptr, .page_count = page_count}); } } // namespace hydra::hw::tegra_x1::cpu::hypervisor diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/page_table.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/page_table.cpp index 037b1f17..b4be522e 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/page_table.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/page_table.cpp @@ -3,27 +3,19 @@ #include "common/type_aliases.hpp" #include "core/debugger/debugger_manager.hpp" -#define PTE_TYPE_MASK 0x3ull -#define PTE_BLOCK(level) ((level == 2 ? 3ull : 1ull) << 0) -#define PTE_TABLE (3ull << 0) // For level 0 and 1 descriptors -#define PTE_AF (1ull << 10) // Access Flag -#define PTE_RW (1ull << 6) // Read write -#define PTE_INNER_SHEREABLE (3ull << 8) // TODO: wht - -/* -#define USER_RANGE_MEM_BASE 0x01000000 -#define USER_RANGE_MEM_SIZE 0x1000000 - -#define KERNEL_RANGE_MEM_BASE 0x04000000 -#define KERNEL_RANGE_MEM_SIZE 0x1000000 -*/ - namespace hydra::hw::tegra_x1::cpu::hypervisor { namespace { constexpr u64 ENTRY_ADDR_MASK = 0x0000fffffffff000; // TODO: correct? +constexpr u64 PTE_TYPE_MASK = 0x3ull; +constexpr u64 GetPteBlock(u64 level) { return (level == 2 ? 3ull : 1ull) << 0; } +constexpr u64 PTE_TABLE = 3ull << 0; // For level 0 and 1 descriptors +constexpr u64 PTE_AF = 1ull << 10; // Access Flag +// constexpr u64 PTE_RW = 1ull << 6; // Read write +constexpr u64 PTE_INNER_SHEREABLE = 3ull << 8; + } // namespace PageTableLevel::PageTableLevel(u32 level_, const Page page_, @@ -31,7 +23,7 @@ PageTableLevel::PageTableLevel(u32 level_, const Page page_, : level{level_}, page{page_}, base_va{base_va_} { u64* table = reinterpret_cast(page.ptr); for (u32 i = 0; i < ENTRY_COUNT; i++) { - table[i] = 0x0; // 0x200000000 | PTE_BLOCK(level); + table[i] = 0x0; // 0x200000000 | GetPteBlock(level); } } @@ -39,7 +31,7 @@ PageTableLevel& PageTableLevel::GetNext(PageAllocator& allocator, u32 index) { ASSERT_DEBUG(level < 2, Hypervisor, "Level 2 is the last level"); auto& next = next_levels[index].level; - if (!next) { + if (next == nullptr) { next = new PageTableLevel(level + 1, allocator.GetNextPage(), base_va + index * GetBlockSize()); GetEntry(index) = next->page.pa | PTE_TABLE; @@ -66,6 +58,7 @@ void PageTable::Map(vaddr_t va, Range range, } void PageTable::Unmap(Range range) { + (void)this; LOG_FUNC_WITH_ARGS_NOT_IMPLEMENTED(Hypervisor, "range: {:#x}", range); } @@ -87,7 +80,7 @@ PageRegion PageTable::QueryRegion(vaddr_t va) const { u32 index = top_level.VaToIndex(va); auto* level = &top_level; u64 entry = top_level.GetEntry(index); - while ((entry & PTE_TYPE_MASK) != PTE_BLOCK(level->GetLevel())) { + while ((entry & PTE_TYPE_MASK) != GetPteBlock(level->GetLevel())) { if ((entry & PTE_TYPE_MASK) != PTE_TABLE) return FREE_MEMORY(va & ~(level->GetBlockSize() - 1), level->GetBlockSize()); @@ -215,7 +208,7 @@ void PageTable::MapLevelNext(PageTableLevel& level, vaddr_t va, paddr_t pa, u32 index = level.VaToIndex(va); // TODO: uncomment if (/*size == level.GetBlockSize()*/ level.GetLevel() == 2) { - level.GetEntry(index) = pa | PTE_BLOCK(level.GetLevel()) | PTE_AF | + level.GetEntry(index) = pa | GetPteBlock(level.GetLevel()) | PTE_AF | PTE_INNER_SHEREABLE | static_cast(ap_flags); level.GetLevelState(index) = state; @@ -227,15 +220,15 @@ void PageTable::MapLevelNext(PageTableLevel& level, vaddr_t va, paddr_t pa, void PageTable::IterateRange( Range range, - std::function, u64, const horizon::kernel::MemoryState&, - PageFlags)> + const std::function, u64, + const horizon::kernel::MemoryState&, PageFlags)>& callback) const { for (u64 page = range.GetBegin() / GUEST_PAGE_SIZE; page < range.GetEnd() / GUEST_PAGE_SIZE; ++page) { u32 index = top_level.VaToIndex(page * GUEST_PAGE_SIZE); auto* level = &top_level; u64 entry = top_level.GetEntry(index); - while ((entry & PTE_TYPE_MASK) != PTE_BLOCK(level->GetLevel())) { + while ((entry & PTE_TYPE_MASK) != GetPteBlock(level->GetLevel())) { if ((entry & PTE_TYPE_MASK) != PTE_TABLE) break; @@ -257,15 +250,15 @@ void PageTable::IterateRange( // TODO: this should subdivide the table if necessary void PageTable::ModifyRange( Range range, - std::function, u64&, horizon::kernel::MemoryState&, - PageFlags&)> + const std::function, u64&, + horizon::kernel::MemoryState&, PageFlags&)>& callback) { for (u64 page = range.GetBegin() / GUEST_PAGE_SIZE; page < range.GetEnd() / GUEST_PAGE_SIZE; ++page) { u32 index = top_level.VaToIndex(page * GUEST_PAGE_SIZE); auto* level = &top_level; u64 entry = top_level.GetEntry(index); - while ((entry & PTE_TYPE_MASK) != PTE_BLOCK(level->GetLevel())) { + while ((entry & PTE_TYPE_MASK) != GetPteBlock(level->GetLevel())) { if ((entry & PTE_TYPE_MASK) != PTE_TABLE) break; diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/page_table.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/page_table.hpp index 52889737..37d8b7c3 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/page_table.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/page_table.hpp @@ -34,16 +34,11 @@ struct PageTableLevel { return static_cast((va - base_va) >> GET_BLOCK_SHIFT(level)); } - u64& GetEntry(u32 index) { + u64& GetEntry(u32 index) const { u64* table = reinterpret_cast(page.ptr); return table[index]; } - const u64& GetEntry(u32 index) const { - const u64* table = reinterpret_cast(page.ptr); - return table[index]; - } - PageTableLevel* GetNextNoNew(u32 index) { ASSERT_DEBUG(level < 2, Hypervisor, "Level 2 is the last level"); return next_levels[index].level; @@ -134,16 +129,15 @@ class PageTable { const horizon::kernel::MemoryState state, ApFlags ap_flags); - void IterateRange( - Range range, - std::function, u64, - const horizon::kernel::MemoryState&, PageFlags)> - callback) const; void - ModifyRange(Range range, - std::function, u64&, - horizon::kernel::MemoryState&, PageFlags&)> - callback); + IterateRange(Range range, + const std::function, u64, + const horizon::kernel::MemoryState&, + PageFlags)>& callback) const; + void ModifyRange(Range range, + const std::function, u64&, + horizon::kernel::MemoryState&, + PageFlags&)>& callback); }; } // namespace hydra::hw::tegra_x1::cpu::hypervisor diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp index 3826cc43..a35616fa 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp @@ -21,7 +21,7 @@ constexpr u32 MDSCR_EL1_MDE = (1u << 15); constexpr u32 DBGBCR_E = (1u << 0); // Enable bit constexpr u32 DBGBCR_BAS = (0xfu << 5); // Byte address select -constexpr u64 INTERRUPT_TIME = 16 * 1000 * 1000; // 16ms +constexpr u64 INTERRUPT_TIME = 16ull * 1000ull * 1000ull; // 16ms enum class ExceptionClass { Unknown = 0b000000, @@ -102,7 +102,7 @@ Thread::Thread(WallClock& wall_clock, Cpu& cpu_, IMmu* mmu, vaddr_t tls_mem_base) : IThread(wall_clock, mmu, callbacks, tls_mem), cpu{cpu_} { // Create - HV_ASSERT_SUCCESS(hv_vcpu_create(&vcpu, &exit, NULL)); + HV_ASSERT_SUCCESS(hv_vcpu_create(&vcpu, &exit, nullptr)); // TODO: find out what this does SetReg(HV_REG_CPSR, 0x3c0); @@ -355,7 +355,7 @@ void Thread::InstructionTrap(u32 esr) { } void Thread::ProcessMessages() { - std::lock_guard lock(msg_mutex); + std::scoped_lock lock(msg_mutex); while (!msg_queue.empty()) { auto message = msg_queue.front(); msg_queue.pop(); diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp index 380237b2..2c63df14 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp @@ -54,14 +54,14 @@ class Thread : public IThread { // Debug void InsertBreakpoint(vaddr_t addr) override { - SendMessage({ThreadMessageType::InsertBreakpoint, - {.insert_breakpoint = {addr}}}); + SendMessage({.type=ThreadMessageType::InsertBreakpoint, + .payload={.insert_breakpoint = {addr}}}); } void RemoveBreakpoint(vaddr_t addr) override { - SendMessage({ThreadMessageType::RemoveBreakpoint, - {.remove_breakpoint = {addr}}}); + SendMessage({.type=ThreadMessageType::RemoveBreakpoint, + .payload={.remove_breakpoint = {addr}}}); } - void SingleStep() override { SendMessage({ThreadMessageType::SingleStep}); } + void SingleStep() override { SendMessage({.type=ThreadMessageType::SingleStep}); } private: Cpu& cpu; @@ -93,7 +93,7 @@ class Thread : public IThread { return value; } - void SetReg(hv_reg_t reg, u64 value) { + void SetReg(hv_reg_t reg, u64 value) const { HV_ASSERT_SUCCESS(hv_vcpu_set_reg(vcpu, reg, value)); } @@ -107,7 +107,7 @@ class Thread : public IThread { return std::bit_cast(value); } - void SetSimdFpReg(u8 reg, u128 value) { + void SetSimdFpReg(u8 reg, u128 value) const { // TODO: correct? HV_ASSERT_SUCCESS(hv_vcpu_set_simd_fp_reg( vcpu, static_cast(HV_SIMD_FP_REG_Q0 + reg), @@ -121,13 +121,13 @@ class Thread : public IThread { return value; } - void SetSysReg(hv_sys_reg_t reg, u64 value) { + void SetSysReg(hv_sys_reg_t reg, u64 value) const { HV_ASSERT_SUCCESS(hv_vcpu_set_sys_reg(vcpu, reg, value)); } // Messages void SendMessage(const ThreadMessage& message) { - std::lock_guard lock(msg_mutex); + std::scoped_lock lock(msg_mutex); msg_queue.push(message); } diff --git a/src/core/hw/tegra_x1/cpu/memory.hpp b/src/core/hw/tegra_x1/cpu/memory.hpp index 3f8b3f91..308b6bbc 100644 --- a/src/core/hw/tegra_x1/cpu/memory.hpp +++ b/src/core/hw/tegra_x1/cpu/memory.hpp @@ -9,6 +9,9 @@ class IMemory { IMemory(u64 size_) : size{align(size_, GUEST_PAGE_SIZE)} {} virtual ~IMemory() = default; + MAKE_NON_COPYABLE(IMemory); + MAKE_NON_MOVABLE(IMemory); + // The memory needs to be unmapped before resizing void Resize(u64 new_size) { size = new_size; diff --git a/src/core/hw/tegra_x1/cpu/mmu.cpp b/src/core/hw/tegra_x1/cpu/mmu.cpp index d8cf49cc..9aea32a6 100644 --- a/src/core/hw/tegra_x1/cpu/mmu.cpp +++ b/src/core/hw/tegra_x1/cpu/mmu.cpp @@ -79,7 +79,7 @@ bool IMmu::TrackWrite(Range range) { Range::FromSize(ptr, aligned_range.GetSize())); { - std::lock_guard lock(write_tracking_mutex); + std::scoped_lock lock(write_tracking_mutex); tracked_pages.push_back(aligned_range); } @@ -87,7 +87,7 @@ bool IMmu::TrackWrite(Range range) { } void IMmu::FlushTrackedPages() { - std::lock_guard lock(write_tracking_mutex); + std::scoped_lock lock(write_tracking_mutex); for (const auto& range : tracked_pages) ResumeWriteTracking(range); tracked_pages.clear(); diff --git a/src/core/hw/tegra_x1/cpu/mmu.hpp b/src/core/hw/tegra_x1/cpu/mmu.hpp index d32eba8f..8dff6bc2 100644 --- a/src/core/hw/tegra_x1/cpu/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/mmu.hpp @@ -36,9 +36,6 @@ class IMmu { virtual void Protect(Range range, horizon::kernel::MemoryPermission perm) = 0; - virtual void ResizeHeap(IMemory* heap_mem, vaddr_t va, - u64 size) = 0; // TODO: remove this - virtual uptr UnmapAddr(vaddr_t va) const = 0; virtual MemoryRegion QueryRegion(vaddr_t va) const = 0; virtual void SetMemoryAttribute(Range range, diff --git a/src/core/hw/tegra_x1/cpu/thread.cpp b/src/core/hw/tegra_x1/cpu/thread.cpp index 804ef764..85980cfa 100644 --- a/src/core/hw/tegra_x1/cpu/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/thread.cpp @@ -4,7 +4,7 @@ namespace hydra::hw::tegra_x1::cpu { -void IThread::GetStackTrace(stack_frame_callback_fn_t callback) { +void IThread::GetStackTrace(const stack_frame_callback_fn_t& callback) { u64 fp = state.fp; u64 lr = state.lr; diff --git a/src/core/hw/tegra_x1/cpu/thread.hpp b/src/core/hw/tegra_x1/cpu/thread.hpp index c39ac210..d2144312 100644 --- a/src/core/hw/tegra_x1/cpu/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/thread.hpp @@ -19,7 +19,7 @@ struct ThreadCallbacks { std::function breakpoint_hit; }; -typedef std::function stack_frame_callback_fn_t; +using stack_frame_callback_fn_t = std::function; struct ThreadState { u64 r[29]; @@ -35,11 +35,11 @@ struct ThreadState { class IThread { public: - IThread(WallClock& wall_clock_, IMmu* mmu_, - const ThreadCallbacks& callbacks_, IMemory* tls_mem_) - : wall_clock{wall_clock_}, mmu{mmu_}, callbacks{callbacks_}, + IThread(WallClock& wall_clock_, IMmu* mmu_, ThreadCallbacks callbacks_, + IMemory* tls_mem_) + : wall_clock{wall_clock_}, mmu{mmu_}, callbacks{std::move(callbacks_)}, tls_mem{tls_mem_} {} - virtual ~IThread() {} + virtual ~IThread() noexcept = default; virtual void Run() = 0; @@ -47,7 +47,7 @@ class IThread { NotifyMemoryChanged([[maybe_unused]] Range mem_range) {} // Debug - void GetStackTrace(stack_frame_callback_fn_t callback); + void GetStackTrace(const stack_frame_callback_fn_t& callback); virtual void InsertBreakpoint(vaddr_t addr) = 0; virtual void RemoveBreakpoint(vaddr_t addr) = 0; diff --git a/src/core/hw/tegra_x1/gpu/const.hpp b/src/core/hw/tegra_x1/gpu/const.hpp index 0dcb0f4d..559c5b5e 100644 --- a/src/core/hw/tegra_x1/gpu/const.hpp +++ b/src/core/hw/tegra_x1/gpu/const.hpp @@ -251,7 +251,6 @@ enum class NvKind : u32 { Invalid = 0xff, }; -// TODO: why do some formats have "_" in them? enum class NvColorFormat : u64 { Unspecified = 0x0000000000UL, NonColor8 = 0x0009200408UL, @@ -531,25 +530,25 @@ enum class ImageFormat : u32 { Z24S8 = 0x29, X8Z24 = 0x2A, S8Z24 = 0x2B, - X4V4Z24__COV4R4V = 0x2C, - X4V4Z24__COV8R8V = 0x2D, - V8Z24__COV4R12V = 0x2E, + X4V4Z24_COV4R4V = 0x2C, + X4V4Z24_COV8R8V = 0x2D, + V8Z24_COV4R12V = 0x2E, ZF32 = 0x2F, ZF32_X24S8 = 0x30, - X8Z24_X20V4S8__COV4R4V = 0x31, - X8Z24_X20V4S8__COV8R8V = 0x32, - ZF32_X20V4X8__COV4R4V = 0x33, - ZF32_X20V4X8__COV8R8V = 0x34, - ZF32_X20V4S8__COV4R4V = 0x35, - ZF32_X20V4S8__COV8R8V = 0x36, - X8Z24_X16V8S8__COV4R12V = 0x37, - ZF32_X16V8X8__COV4R12V = 0x38, - ZF32_X16V8S8__COV4R12V = 0x39, + X8Z24_X20V4S8_COV4R4V = 0x31, + X8Z24_X20V4S8_COV8R8V = 0x32, + ZF32_X20V4X8_COV4R4V = 0x33, + ZF32_X20V4X8_COV8R8V = 0x34, + ZF32_X20V4S8_COV4R4V = 0x35, + ZF32_X20V4S8_COV8R8V = 0x36, + X8Z24_X16V8S8_COV4R12V = 0x37, + ZF32_X16V8X8_COV4R12V = 0x38, + ZF32_X16V8S8_COV4R12V = 0x39, Z16 = 0x3A, - V8Z24__COV8R24V = 0x3B, - X8Z24_X16V8S8__COV8R24V = 0x3C, - ZF32_X16V8X8__COV8R24V = 0x3D, - ZF32_X16V8S8__COV8R24V = 0x3E, + V8Z24_COV8R24V = 0x3B, + X8Z24_X16V8S8_COV8R24V = 0x3C, + ZF32_X16V8X8_COV8R24V = 0x3D, + ZF32_X16V8S8_COV8R24V = 0x3E, ASTC_2D_4X4 = 0x40, ASTC_2D_5X5 = 0x41, ASTC_2D_6X6 = 0x42, @@ -682,6 +681,7 @@ enum class DepthSurfaceFormat : u32 { Z32S8C8X16Float = 0x1F, }; +#pragma pack(push, 1) struct NvSurface { u32 width; u32 height; @@ -698,7 +698,7 @@ struct NvSurface { u64 flags; u64 size; u32 unk[6]; // compression related -} PACKED; +}; struct NvGraphicsBuffer { i32 unk0; // -1 @@ -718,7 +718,8 @@ struct NvGraphicsBuffer { u64 unused; // official sw writes a pointer to bookkeeping data here, but // it's otherwise completely unused/overwritten during // marshalling -} PACKED; +}; +#pragma pack(pop) struct Fence { u32 id; @@ -1000,17 +1001,17 @@ ENABLE_ENUM_FORMATTING( E5BGR9_SHAREDEXP, "e5bgr9_sharedexp", B10GR11Float, "b10gr11float", GBGR8, "gbgr8", BGRG8, "bgrg8", DXT1, "dxt1", DXT23, "dxt23", DXT45, "dxt45", DXN1, "dxn1", DXN2, "dxn2", Z24S8, "z24s8", X8Z24, "x8z24", S8Z24, "s8z24", - X4V4Z24__COV4R4V, "x4v4z24__cov4r4v", X4V4Z24__COV8R8V, "x4v4z24__cov8r8v", - V8Z24__COV4R12V, "v8z24__cov4r12v", ZF32, "zf32", ZF32_X24S8, "zf32_x24s8", - X8Z24_X20V4S8__COV4R4V, "x8z24_x20v4s8__cov4r4v", X8Z24_X20V4S8__COV8R8V, - "x8z24_x20v4s8__cov8r8v", ZF32_X20V4X8__COV4R4V, "zf32_x20v4x8__cov4r4v", - ZF32_X20V4X8__COV8R8V, "zf32_x20v4x8__cov8r8v", ZF32_X20V4S8__COV4R4V, - "zf32_x20v4s8__cov4r4v", ZF32_X20V4S8__COV8R8V, "zf32_x20v4s8__cov8r8v", - X8Z24_X16V8S8__COV4R12V, "x8z24_x16v8s8__cov4r12v", ZF32_X16V8X8__COV4R12V, - "zf32_x16v8x8__cov4r12v", ZF32_X16V8S8__COV4R12V, "zf32_x16v8s8__cov4r12v", - Z16, "z16", V8Z24__COV8R24V, "v8z24__cov8r24v", X8Z24_X16V8S8__COV8R24V, - "x8z24_x16v8s8__cov8r24v", ZF32_X16V8X8__COV8R24V, "zf32_x16v8x8__cov8r24v", - ZF32_X16V8S8__COV8R24V, "zf32_x16v8s8__cov8r24v", ASTC_2D_4X4, + X4V4Z24_COV4R4V, "x4v4z24__cov4r4v", X4V4Z24_COV8R8V, "x4v4z24__cov8r8v", + V8Z24_COV4R12V, "v8z24__cov4r12v", ZF32, "zf32", ZF32_X24S8, "zf32_x24s8", + X8Z24_X20V4S8_COV4R4V, "x8z24_x20v4s8__cov4r4v", X8Z24_X20V4S8_COV8R8V, + "x8z24_x20v4s8__cov8r8v", ZF32_X20V4X8_COV4R4V, "zf32_x20v4x8__cov4r4v", + ZF32_X20V4X8_COV8R8V, "zf32_x20v4x8__cov8r8v", ZF32_X20V4S8_COV4R4V, + "zf32_x20v4s8__cov4r4v", ZF32_X20V4S8_COV8R8V, "zf32_x20v4s8__cov8r8v", + X8Z24_X16V8S8_COV4R12V, "x8z24_x16v8s8__cov4r12v", ZF32_X16V8X8_COV4R12V, + "zf32_x16v8x8__cov4r12v", ZF32_X16V8S8_COV4R12V, "zf32_x16v8s8__cov4r12v", + Z16, "z16", V8Z24_COV8R24V, "v8z24__cov8r24v", X8Z24_X16V8S8_COV8R24V, + "x8z24_x16v8s8__cov8r24v", ZF32_X16V8X8_COV8R24V, "zf32_x16v8x8__cov8r24v", + ZF32_X16V8S8_COV8R24V, "zf32_x16v8s8__cov8r24v", ASTC_2D_4X4, "astc_2d_4x4", ASTC_2D_5X5, "astc_2d_5x5", ASTC_2D_6X6, "astc_2d_6x6", ASTC_2D_8X8, "astc_2d_8x8", ASTC_2D_10X10, "astc_2d_10x10", ASTC_2D_12X12, "astc_2d_12x12", ASTC_2D_5X4, "astc_2d_5x4", ASTC_2D_6X5, "astc_2d_6x5", diff --git a/src/core/hw/tegra_x1/gpu/engines/2d.hpp b/src/core/hw/tegra_x1/gpu/engines/2d.hpp index db97b3ee..b67b3d5a 100644 --- a/src/core/hw/tegra_x1/gpu/engines/2d.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/2d.hpp @@ -36,7 +36,7 @@ struct FixedPoint { u32 integer; explicit operator f64() const { - return f64(integer) + f64(fractional) / f64(1llu << 32llu); + return static_cast(integer) + (static_cast(fractional) / static_cast(1llu << 32llu)); } }; diff --git a/src/core/hw/tegra_x1/gpu/engines/3d.cpp b/src/core/hw/tegra_x1/gpu/engines/3d.cpp index 7483c1e2..0db22115 100644 --- a/src/core/hw/tegra_x1/gpu/engines/3d.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/3d.cpp @@ -58,7 +58,7 @@ constexpr u32 D3D11_BLEND_OP_MAX = 5; renderer::BlendOperation get_blend_operation(u32 blend_op) { switch (blend_op) { - // GL + // GL case GL_MIN: return renderer::BlendOperation::Min; case GL_MAX: @@ -120,7 +120,7 @@ constexpr u32 D3D11_BLEND_FACTOR_INV_SRC1_ALPHA = 19; constexpr u32 GL_BLEND_FACTOR_BIT = 0x4000; renderer::BlendFactor get_blend_factor(u32 blend_factor) { - if (blend_factor & GL_BLEND_FACTOR_BIT) { // GL + if ((blend_factor & GL_BLEND_FACTOR_BIT) != 0u) { // GL u32 gl_blend_factor = blend_factor & ~GL_BLEND_FACTOR_BIT; switch (gl_blend_factor) { case GL_ZERO: @@ -226,8 +226,8 @@ ThreeD::ThreeD(Gpu& gpu_) : gpu{gpu_}, macro_driver{CreateMacroDriver(*this)} { // Viewports // TODO: correct? - for (u32 i = 0; i < VIEWPORT_COUNT; i++) { - regs.viewport_transforms[i].swizzle = { + for (auto& viewport_transform : regs.viewport_transforms) { + viewport_transform.swizzle = { .x = ViewportSwizzle::PositiveX, .y = ViewportSwizzle::PositiveY, .z = ViewportSwizzle::PositiveZ, @@ -237,8 +237,8 @@ ThreeD::ThreeD(Gpu& gpu_) : gpu{gpu_}, macro_driver{CreateMacroDriver(*this)} { // Color write masks // TODO: correct? - for (u32 i = 0; i < COLOR_TARGET_COUNT; i++) - regs.color_write_masks[i] = ColorWriteMask::All; + for (auto& color_write_mask : regs.color_write_masks) + color_write_mask = ColorWriteMask::All; // HACK regs.shader_programs[static_cast(ShaderStage::VertexB)].config.enable = @@ -284,7 +284,7 @@ void ThreeD::DrawVertexArray(const u32 index, u32 count) { auto primitive_type = regs.begin.primitive_type; renderer::BufferView index_buffer; { - std::lock_guard buffer_cache_lock( + std::scoped_lock buffer_cache_lock( gpu.GetRenderer().GetBufferCache().GetMutex()); if (!DrawInternal()) return; @@ -297,7 +297,7 @@ void ThreeD::DrawVertexArray(const u32 index, u32 count) { index_type, primitive_type, count); } - if (index_buffer.GetBase()) { + if (index_buffer.GetBase() != nullptr) { // Bind index buffer gpu.GetRenderer().BindIndexBuffer(index_buffer, index_type); @@ -323,7 +323,7 @@ void ThreeD::DrawVertexElements(const u32 index, u32 count) { auto primitive_type = regs.begin.primitive_type; renderer::BufferView index_buffer; { - std::lock_guard buffer_cache_lock( + std::scoped_lock buffer_cache_lock( gpu.GetRenderer().GetBufferCache().GetMutex()); if (!DrawInternal()) return; @@ -372,7 +372,7 @@ void ThreeD::ClearBuffer(const u32 index, const ClearBufferData data) { // Regular clear { - std::lock_guard texture_cache_lock( + std::scoped_lock texture_cache_lock( gpu.GetRenderer().GetTextureCache().GetMutex()); gpu.GetRenderer().BindRenderPass(GetRenderPass()); } @@ -432,7 +432,7 @@ void ThreeD::BindGroup(const u32 index, const u32 data) { break; case 0x4: { const auto buffer_index = extract_bits(data, 4, 5); - bool valid = data & 0x1; + bool valid = (data & 0x1) != 0u; if (valid) { const uptr const_buffer_gpu_ptr = tls_crnt_gmmu->UnmapAddr(regs.const_buffer_selector); @@ -483,7 +483,8 @@ ThreeD::GetColorTargetTexture(u32 render_target_index) const { // Width and stride const bool is_linear = render_target.tile_mode.is_linear; - u32 width, stride; + u32 width; + u32 stride; if (is_linear) { width = render_target.width_or_stride / renderer::get_texture_format_bpp(format); @@ -547,8 +548,9 @@ renderer::RenderPassBase* ThreeD::GetRenderPass() const { // Depth stencil target descriptor.depth_stencil_target = { - .texture = (regs.depth_target_enabled ? GetDepthStencilTargetTexture() - : nullptr), + .texture = + ((regs.depth_target_enabled != 0u) ? GetDepthStencilTargetTexture() + : nullptr), }; return gpu.GetRenderer().GetRenderPassCache().Find(descriptor); @@ -568,16 +570,16 @@ renderer::Viewport ThreeD::GetViewport(u32 index) { // Swizzle // TODO: check for viewport swizzle support - if (transform.swizzle.x == engines::ViewportSwizzle::NegativeX) + if (transform.swizzle.x == engines::ViewportSwizzle::NegativeX) { scale_x = -scale_x; - else + } else ASSERT_DEBUG(transform.swizzle.x == engines::ViewportSwizzle::PositiveX, Engines, "Unsupported X viewport swizzle {}", transform.swizzle.x); - if (transform.swizzle.y == engines::ViewportSwizzle::NegativeY) + if (transform.swizzle.y == engines::ViewportSwizzle::NegativeY) { scale_y = -scale_y; - else + } else ASSERT_DEBUG(transform.swizzle.y == engines::ViewportSwizzle::PositiveY, Engines, "Unsupported Y viewport swizzle {}", @@ -623,7 +625,7 @@ renderer::Viewport ThreeD::GetViewport(u32 index) { renderer::Scissor ThreeD::GetScissor(u32 index) { const auto& scissor = regs.scissors[index]; - if (scissor.enabled) { + if (scissor.enabled != 0u) { return renderer::Scissor( uint2({scissor.horizontal.min, scissor.vertical.min}), uint2({static_cast(scissor.horizontal.max - @@ -636,7 +638,7 @@ renderer::Scissor ThreeD::GetScissor(u32 index) { } renderer::ShaderBase* ThreeD::GetShaderUnchecked(ShaderStage stage) const { - return active_shaders[u32(to_renderer_shader_type(stage))]; + return active_shaders[static_cast(to_renderer_shader_type(stage))]; } renderer::ShaderBase* ThreeD::GetShader(ShaderStage stage) { @@ -668,7 +670,8 @@ renderer::ShaderBase* ThreeD::GetShader(ShaderStage stage) { renderer::to_color_data_type(regs.color_targets[i].format); } - auto& active_shader = active_shaders[u32(to_renderer_shader_type(stage))]; + auto& active_shader = + active_shaders[static_cast(to_renderer_shader_type(stage))]; active_shader = gpu.GetRenderer().GetShaderCache().Find(descriptor); return active_shader; @@ -679,9 +682,9 @@ renderer::PipelineBase* ThreeD::GetPipeline() { // Shaders // TODO: add all shaders - descriptor.shaders[u32(renderer::ShaderType::Vertex)] = + descriptor.shaders[static_cast(renderer::ShaderType::Vertex)] = GetShader(ShaderStage::VertexB); - descriptor.shaders[u32(renderer::ShaderType::Fragment)] = + descriptor.shaders[static_cast(renderer::ShaderType::Fragment)] = GetShader(ShaderStage::Fragment); // Vertex state @@ -730,7 +733,7 @@ renderer::PipelineBase* ThreeD::GetPipeline() { color_target.blend_enabled = static_cast(regs.color_blend_enabled[i]); if (color_target.blend_enabled) { - if (regs.independent_blend_enabled) { + if (regs.independent_blend_enabled != 0u) { const auto& blend_state = regs.independent_blend_state[i]; color_target.rgb_op = get_blend_operation(blend_state.rgb_op); color_target.src_rgb_factor = @@ -767,14 +770,15 @@ renderer::BufferView ThreeD::GetVertexBuffer(u32 vertex_array_index) const { const auto& vertex_array = regs.vertex_arrays[vertex_array_index]; // HACK - if (u64(vertex_array.addr) == 0x0) { + if (static_cast(vertex_array.addr) == 0x0) { ONCE(LOG_ERROR(Engines, "Invalid vertex buffer")); - return renderer::BufferView(); + return {}; } const auto ptr = tls_crnt_gmmu->UnmapAddr(vertex_array.addr); - const auto size = u64(regs.vertex_array_limits[vertex_array_index]) + 1 - - u64(vertex_array.addr); + const auto size = + static_cast(regs.vertex_array_limits[vertex_array_index]) + 1 - + static_cast(vertex_array.addr); return gpu.GetRenderer().GetBufferCache().Get( tls_crnt_command_buffer, Range::FromSize(ptr, size)); } @@ -893,7 +897,7 @@ void ThreeD::ConfigureShaderStage( // TODO: storage buffers // Textures - if (tex_header_pool && tex_sampler_pool) { + if ((tex_header_pool != nullptr) && (tex_sampler_pool != nullptr)) { gpu.GetRenderer().UnbindTextures(shader_type); auto tex_const_buffer = reinterpret_cast( bound_const_buffers[stage_index] @@ -913,7 +917,7 @@ void ThreeD::ConfigureShaderStage( const auto& tsc = tex_sampler_pool[sampler_handle]; const auto sampler = GetSampler(tsc); - if (texture && sampler) + if ((texture != nullptr) && (sampler != nullptr)) gpu.GetRenderer().BindTexture(texture, sampler, shader_type, renderer_index); } @@ -921,7 +925,7 @@ void ThreeD::ConfigureShaderStage( } bool ThreeD::DrawInternal() { - std::lock_guard texture_cache_lock( + std::scoped_lock texture_cache_lock( gpu.GetRenderer().GetTextureCache().GetMutex()); // Flush tracked pages @@ -937,8 +941,8 @@ bool ThreeD::DrawInternal() { gpu.GetRenderer().BindRenderPass(GetRenderPass()); gpu.GetRenderer().BindPipeline(GetPipeline()); - gpu.GetRenderer().SetDepthTestEnabled(regs.depth_test_enabled); - gpu.GetRenderer().SetDepthWriteEnabled(regs.depth_write_enabled); + gpu.GetRenderer().SetDepthTestEnabled(regs.depth_test_enabled != 0u); + gpu.GetRenderer().SetDepthWriteEnabled(regs.depth_write_enabled != 0u); gpu.GetRenderer().SetDepthCompareOp(regs.depth_compare_op); for (u32 i = 0; i < VIEWPORT_COUNT; i++) { diff --git a/src/core/hw/tegra_x1/gpu/engines/3d.hpp b/src/core/hw/tegra_x1/gpu/engines/3d.hpp index 7049675d..282e0d53 100644 --- a/src/core/hw/tegra_x1/gpu/engines/3d.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/3d.hpp @@ -523,7 +523,7 @@ struct Regs3D { u32 padding1; u32 num_registers; u32 padding2[0xc]; - } shader_programs[u32(ShaderStage::Count)]; + } shader_programs[static_cast(ShaderStage::Count)]; u32 padding_0x860[0x80]; @@ -544,7 +544,7 @@ struct Regs3D { // 0xd00 u32 mme_scratch[0x80]; -} PACKED; +}; class ThreeD : public EngineWithRegsBase, public InlineBase { public: diff --git a/src/core/hw/tegra_x1/gpu/engines/const.hpp b/src/core/hw/tegra_x1/gpu/engines/const.hpp index 57093ae1..9d893c5f 100644 --- a/src/core/hw/tegra_x1/gpu/engines/const.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/const.hpp @@ -8,7 +8,7 @@ struct Iova { u32 hi; u32 lo; - operator u64() const { return u64(hi) << 32 | u64(lo); } + operator u64() const { return static_cast(hi) << 32 | static_cast(lo); } }; enum class Winding : u32 { diff --git a/src/core/hw/tegra_x1/gpu/engines/copy.cpp b/src/core/hw/tegra_x1/gpu/engines/copy.cpp index c229859b..05bccc76 100644 --- a/src/core/hw/tegra_x1/gpu/engines/copy.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/copy.cpp @@ -41,8 +41,10 @@ void Copy::LaunchDMA(const u32 index, const LaunchDMAData data) { if (data.src_memory_layout == MemoryLayout::Pitch) { if (data.dst_memory_layout == MemoryLayout::Pitch) { for (u32 i = 0; i < regs.line_count; i++) - memcpy(reinterpret_cast(dst_ptr + regs.stride_out * i), - reinterpret_cast(src_ptr + regs.stride_in * i), + memcpy(reinterpret_cast( + dst_ptr + static_cast(regs.stride_out * i)), + reinterpret_cast( + src_ptr + static_cast(regs.stride_in * i)), regs.stride_in); } else { // TODO: is slice stride correct? @@ -93,7 +95,8 @@ void Copy::LaunchDMA(const u32 index, const LaunchDMAData data) { align(regs.dst.depth, 1u << static_cast(get_block_size_log2( regs.dst.block_size.depth))); gpu.GetRenderer().InvalidateMemory( - Range::FromSize(dst_ptr, slices * rows * stride), + Range::FromSize(dst_ptr, + static_cast(slices * rows * stride)), renderer::MemoryInvalidationScope::TextureCache); } } diff --git a/src/core/hw/tegra_x1/gpu/engines/copy.hpp b/src/core/hw/tegra_x1/gpu/engines/copy.hpp index 4fb5da96..34e99698 100644 --- a/src/core/hw/tegra_x1/gpu/engines/copy.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/copy.hpp @@ -31,14 +31,14 @@ enum class InterruptType : u32 { }; enum class SemaphoreReduction : u32 { - Imin, - Imax, - Ixor, - Iand, - Ior, - Iadd, - Inc, - Dec, + Imin = 0, + Imax = 1, + Ixor = 2, + Iand = 3, + Ior = 4, + Iadd = 5, + Inc = 6, + Dec = 7, Fadd = 10, }; diff --git a/src/core/hw/tegra_x1/gpu/engines/engine_base.hpp b/src/core/hw/tegra_x1/gpu/engines/engine_base.hpp index e41f7c44..fbdf6573 100644 --- a/src/core/hw/tegra_x1/gpu/engines/engine_base.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/engine_base.hpp @@ -29,27 +29,20 @@ namespace hydra::hw::tegra_x1::gpu::engines { class EngineBase { public: - enum class Error { - InvalidRegister, - MacrosNotSupported, - }; - virtual ~EngineBase() = default; virtual void Method(u32 method, u32 arg) = 0; virtual void FlushMacro() { - LOG_ERROR(Engines, "This engine does not support macros"); - throw Error::MacrosNotSupported; + LOG_FATAL(Engines, "This engine does not support macros"); } protected: virtual void Macro(u32 method, u32 arg) { - LOG_ERROR(Engines, + LOG_FATAL(Engines, "This engine does not support macros (method: 0x{:08x}, arg: " "0x{:08x})", method, arg); - throw Error::MacrosNotSupported; } }; @@ -59,8 +52,8 @@ class EngineWithRegsBase : public EngineBase { #define REG_COUNT (sizeof(RegsT) / sizeof(u32)) u32 GetReg(u32 reg) const { - ASSERT_THROWING_DEBUG(reg < REG_COUNT, Engines, Error::InvalidRegister, - "Invalid register 0x{:08x}", reg); + ASSERT_DEBUG(reg < REG_COUNT, Engines, "Invalid register 0x{:08x}", + reg); return regs_raw[reg]; } @@ -71,8 +64,7 @@ class EngineWithRegsBase : public EngineBase { }; void WriteReg(u32 reg, u32 value) { - ASSERT_THROWING_DEBUG(reg < REG_COUNT, Engines, Error::InvalidRegister, - "Invalid reg 0x{:08x}", reg); + ASSERT_DEBUG(reg < REG_COUNT, Engines, "Invalid reg 0x{:08x}", reg); LOG_DEBUG(Engines, "Writing to reg 0x{:03x} (value: 0x{:08x})", reg, value); regs_raw[reg] = value; diff --git a/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp b/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp index a1033f3f..bcfd8b59 100644 --- a/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp @@ -10,6 +10,7 @@ namespace hydra::hw::tegra_x1::gpu::engines { void InlineBase::LaunchDMAImpl(Gpu& gpu, RegsInline& regs, const u32 index, const u32 data) { + (void)this; LOG_FUNC_WITH_ARGS_STUBBED(Engines, "index: {}, data: {:#x}", index, data); } @@ -18,7 +19,7 @@ void InlineBase::LoadInlineDataImpl(Gpu& gpu, RegsInline& regs, const u32 index, inline_data.push_back(data); // TODO: correct? if (inline_data.size() * sizeof(u32) == - regs.line_length_in * regs.line_count) { + static_cast(regs.line_length_in * regs.line_count)) { // Flush // TODO: determine what type of copy this is based on launch DMA args diff --git a/src/core/hw/tegra_x1/gpu/gmmu.hpp b/src/core/hw/tegra_x1/gpu/gmmu.hpp index 18da9a58..731cdbf4 100644 --- a/src/core/hw/tegra_x1/gpu/gmmu.hpp +++ b/src/core/hw/tegra_x1/gpu/gmmu.hpp @@ -19,7 +19,7 @@ class GMmu : public GenericMmu { public: GMmu(cpu::IMmu* mmu_) : mmu{mmu_} {} - u64 ImplGetSize(const AddressSpace& as) const { return as.size; } + static u64 ImplGetSize(const AddressSpace& as) { return as.size; } AddressSpace& UnmapAddrToAddressSpace(uptr gpu_addr) { uptr base; diff --git a/src/core/hw/tegra_x1/gpu/gpu.cpp b/src/core/hw/tegra_x1/gpu/gpu.cpp index 710abd31..f0a8977d 100644 --- a/src/core/hw/tegra_x1/gpu/gpu.cpp +++ b/src/core/hw/tegra_x1/gpu/gpu.cpp @@ -79,13 +79,17 @@ void Gpu::SubchannelMethod(u32 subchannel, u32 method, u32 arg) { return; } - GetEngineAtSubchannel(subchannel)->Method(method, arg); + const auto engine = GetEngineAtSubchannel(subchannel); + if (!engine) + LOG_FATAL(Gpu, "Invalid subchannel {}", subchannel); + + (*engine)->Method(method, arg); } renderer::ITextureView* Gpu::GetTexture(renderer::ICommandBuffer* command_buffer, cpu::IMmu* mmu, const NvGraphicsBuffer& buff) { - std::lock_guard texture_cache_lock(renderer->GetTextureCache().GetMutex()); + std::scoped_lock texture_cache_lock(renderer->GetTextureCache().GetMutex()); const auto& plane = buff.planes[0]; diff --git a/src/core/hw/tegra_x1/gpu/gpu.hpp b/src/core/hw/tegra_x1/gpu/gpu.hpp index 11b832d9..de501551 100644 --- a/src/core/hw/tegra_x1/gpu/gpu.hpp +++ b/src/core/hw/tegra_x1/gpu/gpu.hpp @@ -64,27 +64,20 @@ class Gpu { } // Engines - enum class GetEngineAtSubchannelError { - InvalidSubchannel, - NoEngineBound, - }; - engines::EngineBase* GetEngineAtSubchannel(u32 subchannel) { - ASSERT_THROWING_DEBUG(subchannel <= SUBCHANNEL_COUNT, Gpu, - GetEngineAtSubchannelError::InvalidSubchannel, - "Invalid subchannel {}", subchannel); - - auto engine = subchannels[subchannel]; - ASSERT_THROWING_DEBUG( - engine, Gpu, GetEngineAtSubchannelError::NoEngineBound, - "Subchannel {} does not have a bound engine", subchannel); - - return engine; + std::optional GetEngineAtSubchannel(u32 subchannel) { + if (subchannel > SUBCHANNEL_COUNT) + return std::nullopt; + return subchannels[subchannel]; } void SubchannelMethod(u32 subchannel, u32 method, u32 arg); void SubchannelFlushMacro(u32 subchannel) { - GetEngineAtSubchannel(subchannel)->FlushMacro(); + const auto engine = GetEngineAtSubchannel(subchannel); + if (!engine) + LOG_FATAL(Gpu, "Invalid subchannel {}", subchannel); + + (*engine)->FlushMacro(); } // Texture @@ -94,7 +87,7 @@ class Gpu { // Getters Pfifo& GetPfifo() { return pfifo; } - renderer::IRenderer& GetRenderer() const { return *renderer.get(); } + renderer::IRenderer& GetRenderer() const { return *renderer; } private: // Pfifo @@ -106,7 +99,7 @@ class Gpu { engines::Inline inline_engine; engines::TwoD two_d_engine; engines::Copy copy_engine; - engines::EngineBase* subchannels[SUBCHANNEL_COUNT] = {nullptr}; + std::optional subchannels[SUBCHANNEL_COUNT] = {}; // Renderer std::unique_ptr renderer; diff --git a/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp b/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp index ded23df8..24b253e6 100644 --- a/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp +++ b/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp @@ -48,7 +48,7 @@ bool DriverBase::ParseInstruction(u32 pc) { #define GET_SIZE(shift) GET_DATA_U32(shift, 5) // Operation - Operation op = static_cast(instruction & 0x7); + const auto op = static_cast(instruction & 0x7); u32 value; bool branched = false; switch (op) { @@ -107,15 +107,14 @@ bool DriverBase::ParseInstruction(u32 pc) { // result_t operation if (op != Operation::Branch) { - ResultOperation result_op = - static_cast(GET_DATA_U32(4, 3)); + const auto result_op = static_cast(GET_DATA_U32(4, 3)); u8 rD = GET_REG(8); InstResult(result_op, rD, value); } // Check if exit // TODO: why is this so weird? - if (instruction & EXIT_BIT && !branched) + if ((instruction & EXIT_BIT) != 0u && !branched) exit_after = pc + 1; return pc == exit_after; diff --git a/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.cpp b/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.cpp index 8843b466..042a072b 100644 --- a/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.cpp +++ b/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.cpp @@ -30,22 +30,22 @@ u32 Driver::InstAlu(AluOperation op, u8 rA, u8 rB) { switch (op) { case AluOperation::Add: { i32 result = valueA + valueB; - carry = result < valueA; + carry = static_cast(result < valueA); RET(result); } case AluOperation::AddWithCarry: { i32 result = valueA + valueB + carry; - carry = result < valueA; + carry = static_cast(result < valueA); RET(result); } case AluOperation::Subtract: { i32 result = valueA - valueB; - carry = result < 0; + carry = static_cast(result < 0); RET(result); } case AluOperation::SubtractWithBorrow: { i32 result = valueA - valueB - carry; - carry = result < 0; + carry = static_cast(result < 0); RET(result); } case AluOperation::Xor: diff --git a/src/core/hw/tegra_x1/gpu/memory_util.cpp b/src/core/hw/tegra_x1/gpu/memory_util.cpp index 93e55c2c..bd2297c7 100644 --- a/src/core/hw/tegra_x1/gpu/memory_util.cpp +++ b/src/core/hw/tegra_x1/gpu/memory_util.cpp @@ -44,7 +44,7 @@ uint2 UnswizzleGobCoords(u32 index) { void ConvertBlockLinearToLinear(u32 stride, u32 rows, u32 depth, u32 block_height_gobs_log2, u32 block_depth_gobs_log2, const u8* in_data, - WriteGobFn write_fn) { + const WriteGobFn& write_fn) { const auto layout = GetMemoryLayout( stride, rows, depth, block_height_gobs_log2, block_depth_gobs_log2); u32 gob_index = 0; @@ -106,8 +106,8 @@ void ConvertBlockLinearToLinear(u32 src_stride, u32 dst_stride, void ConvertLinearToBlockLinear(u32 stride, u32 rows, u32 depth, u32 block_height_gobs_log2, - u32 block_depth_gobs_log2, ReadGobFn read_fn, - u8* out_data) { + u32 block_depth_gobs_log2, + const ReadGobFn& read_fn, u8* out_data) { const auto layout = GetMemoryLayout( stride, rows, depth, block_height_gobs_log2, block_depth_gobs_log2); u32 gob_index = 0; diff --git a/src/core/hw/tegra_x1/gpu/memory_util.hpp b/src/core/hw/tegra_x1/gpu/memory_util.hpp index b8664d0b..4e29ce14 100644 --- a/src/core/hw/tegra_x1/gpu/memory_util.hpp +++ b/src/core/hw/tegra_x1/gpu/memory_util.hpp @@ -13,15 +13,15 @@ constexpr u32 GOB_HEIGHT = 1 << GOB_HEIGHT_LOG2; constexpr u32 GOB_SIZE = 512; -typedef std::function - ReadGobFn; -typedef std::function - WriteGobFn; +using ReadGobFn = + std::function; +using WriteGobFn = + std::function; void ConvertBlockLinearToLinear(u32 stride, u32 rows, u32 depth, u32 block_height_gobs_log2, u32 block_depth_gobs_log2, const u8* in_data, - WriteGobFn write_fn); + const WriteGobFn& write_fn); void ConvertBlockLinearToLinear(u32 src_stride, u32 dst_stride, u32 dst_slice_stride, u32 rows, u32 depth, u32 block_height_gobs_log2, @@ -30,7 +30,7 @@ void ConvertBlockLinearToLinear(u32 src_stride, u32 dst_stride, void ConvertLinearToBlockLinear(u32 stride, u32 rows, u32 depth, u32 block_height_gobs_log2, - u32 block_depth_gobs_log2, ReadGobFn read_fn, + u32 block_depth_gobs_log2, const ReadGobFn& read_fn, u8* out_data); void ConvertLinearToBlockLinear(u32 src_stride, u32 src_slice_stride, u32 dst_stride, u32 rows, u32 depth, diff --git a/src/core/hw/tegra_x1/gpu/pfifo.cpp b/src/core/hw/tegra_x1/gpu/pfifo.cpp index aa46ec24..df7ebbdd 100644 --- a/src/core/hw/tegra_x1/gpu/pfifo.cpp +++ b/src/core/hw/tegra_x1/gpu/pfifo.cpp @@ -82,7 +82,7 @@ void Pfifo::SubmitEntries(GMmu& gmmu, std::span entries, LOG_DEBUG(Gpu, "Flags: {}", flags); { - std::lock_guard lock(mutex); + std::scoped_lock lock(mutex); entry_lists.emplace( gmmu, std::vector(entries.begin(), entries.end()), flags); @@ -140,14 +140,8 @@ void Pfifo::SubmitEntry(const GpfifoEntry entry) { uptr end = gpu_addr + entry.size * sizeof(u32); while (gpu_addr < end) { - try { - if (!SubmitCommand(gpu_addr)) - break; - } catch (Gpu::GetEngineAtSubchannelError error) { + if (!SubmitCommand(gpu_addr)) break; - } catch (engines::EngineBase::Error error) { - break; - } } } diff --git a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp index d1a93fc7..6b994c0f 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp @@ -12,7 +12,7 @@ BufferCache::~BufferCache() { BufferView BufferCache::Get(ICommandBuffer* command_buffer, Range range) { auto& entry = Find(range); - if (entry.buffer) { + if (entry.buffer != nullptr) { // Check for memory invalidation if (entry.invalidation_range.has_value() && entry.invalidation_range->Intersects(range)) { @@ -29,8 +29,8 @@ BufferView BufferCache::Get(ICommandBuffer* command_buffer, Range range) { UpdateRange(command_buffer, entry, entry.range); } - return BufferView(entry.buffer, range.GetBegin() - entry.range.GetBegin(), - range.GetSize()); + return {entry.buffer, range.GetBegin() - entry.range.GetBegin(), + range.GetSize()}; } void BufferCache::InvalidateMemory(Range range) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp index b150128e..e12638fa 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp @@ -14,7 +14,7 @@ class IRenderer; struct BufferEntry { BufferBase* buffer{nullptr}; Range range; - std::optional> invalidation_range{}; + std::optional> invalidation_range; bool inline_copy{false}; // TODO: implement }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/const.cpp b/src/core/hw/tegra_x1/gpu/renderer/const.cpp index b6b85827..48b8355b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/const.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/const.cpp @@ -384,8 +384,8 @@ u32 GetTextureFormatSliceStride(const TextureFormat format, u32 width, u32 get_texture_format_bpp(const TextureFormat format) { const auto& info = GetTextureFormatInfo(format); - if (info.block_width != 1 || info.block_height != 1) - throw GetTextureFormatBppError::UnsupportedFormatForBpp; + ASSERT_DEBUG(info.block_width == 1 && info.block_height == 1, Gpu, + "BPP not supported for format {}", format); return info.bytes_per_block; } diff --git a/src/core/hw/tegra_x1/gpu/renderer/const.hpp b/src/core/hw/tegra_x1/gpu/renderer/const.hpp index 62085212..b9944ccb 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/const.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/const.hpp @@ -176,11 +176,6 @@ TextureFormat to_texture_format(const ImageFormatWord image_format_word, TextureFormat to_texture_format(ColorSurfaceFormat color_surface_format); TextureFormat to_texture_format(DepthSurfaceFormat depth_surface_format); -enum class GetTextureFormatBppError { - InvalidFormat, - UnsupportedFormatForBpp, -}; - u32 GetTextureFormatStride(const TextureFormat format, u32 width); u32 GetTextureFormatRows(const TextureFormat format, u32 height); u32 GetTextureFormatSliceStride(const TextureFormat format, u32 width, @@ -249,8 +244,8 @@ struct TextureDescriptor { depth{depth_}, level_count{level_count_}, layer_count{layer_count_}, block_width_gobs_log2{block_width_gobs_log2_}, block_height_gobs_log2{block_height_gobs_log2_}, - block_depth_gobs_log2{block_depth_gobs_log2_}, layer_size{ - layer_size_} { + block_depth_gobs_log2{block_depth_gobs_log2_}, + layer_size{layer_size_} { CalculateSize(); } @@ -373,7 +368,7 @@ struct Viewport { f32 depth_far; }; -typedef UIntRect2D Scissor; +using Scissor = UIntRect2D; enum class ShaderType { Vertex, @@ -389,8 +384,8 @@ struct ResourceMapping { // TODO: images ResourceMapping() { - for (u32 i = 0; i < CONST_BUFFER_BINDING_COUNT; i++) - uniform_buffers[i] = invalid(); + for (auto& uniform_buffer : uniform_buffers) + uniform_buffer = invalid(); // TODO: storage buffers // TODO: images } @@ -428,7 +423,7 @@ struct ColorTargetState { }; struct PipelineDescriptor { - ShaderBase* shaders[usize(ShaderType::Count)]; + ShaderBase* shaders[static_cast(ShaderType::Count)]; VertexState vertex_state; ColorTargetState color_target_states[COLOR_TARGET_COUNT]; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp index e7dce840..5974eb82 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp @@ -139,25 +139,26 @@ BufferView IndexCache::Decode(ICommandBuffer* command_buffer, PRIMITIVE_TYPE_SWITCH(GET_PARAMS, GET_PARAMS_U8_INDEX) switch (out_count) { - case 0 ... 0xff: + case 0u ... 0xffu: // TODO: check for u8 support out_type = engines::IndexType::UInt16; break; - case 0x100 ... 0xffff: + case 0x100u ... 0xffffu: out_type = engines::IndexType::UInt16; break; - case 0x10000 ... 0xffffffff: + case 0x10000u ... 0xffffffffu: out_type = engines::IndexType::UInt32; break; } const auto hash = Hash(descriptor); auto& index_buffer = cache[hash]; - if (index_buffer) + if (index_buffer != nullptr) return index_buffer; const auto index_size = get_index_type_size(out_type); - index_buffer = renderer.AllocateTemporaryBuffer(out_count * index_size); + index_buffer = renderer.AllocateTemporaryBuffer( + static_cast(out_count * index_size)); uptr in_ptr = 0x0; if (descriptor.mem_range) in_ptr = descriptor.mem_range->GetBegin(); @@ -178,7 +179,7 @@ BufferView IndexCache::Decode(ICommandBuffer* command_buffer, PRIMITIVE_TYPE_SWITCH(DECODE_MACRO_AUTO, DECODE_MACRO_AUTO_U8_INDEX) } - return BufferView(index_buffer); + return {index_buffer}; } // namespace hydra::hw::tegra_x1::gpu::renderer u32 IndexCache::Hash(const IndexDescriptor& descriptor) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp index 6984c5c5..a3688b16 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp @@ -25,7 +25,7 @@ class IndexCache { engines::IndexType& out_type, engines::PrimitiveType& out_primitive_type, u32& out_count); - u32 Hash(const IndexDescriptor& descriptor); + static u32 Hash(const IndexDescriptor& descriptor); private: IRenderer& renderer; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp index 3279df1a..8d8ff27c 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp @@ -99,7 +99,7 @@ BlitPipelineCache::Create(const BlitPipelineDescriptor& descriptor) { NS::Error* error; auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create blit pipeline: {}", error->localizedDescription()->utf8String()); return nullptr; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp index cc71ae54..dc99c62d 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp @@ -6,9 +6,9 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Buffer::Buffer(MTL::Device* device, u64 size) : BufferBase(size) { - buffer = device->newBuffer(size, MTL::ResourceStorageModePrivate); -} +Buffer::Buffer(MTL::Device* device, u64 size) + : BufferBase(size), + buffer{device->newBuffer(size, MTL::ResourceStorageModePrivate)} {} Buffer::Buffer(MTL::Buffer* buffer_) : BufferBase(buffer_->allocatedSize()), buffer{buffer_} {} diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp index 96ed6998..2e55be3b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp @@ -73,13 +73,13 @@ MTL::RenderPipelineState* ClearColorPipelineCache::Create( color_attachment->setPixelFormat(descriptor.pixel_format); MTL::ColorWriteMask mask = MTL::ColorWriteMaskNone; - if (descriptor.mask & BIT(0)) + if ((descriptor.mask & BIT(0)) != 0u) mask |= MTL::ColorWriteMaskRed; - if (descriptor.mask & BIT(1)) + if ((descriptor.mask & BIT(1)) != 0u) mask |= MTL::ColorWriteMaskGreen; - if (descriptor.mask & BIT(2)) + if ((descriptor.mask & BIT(2)) != 0u) mask |= MTL::ColorWriteMaskBlue; - if (descriptor.mask & BIT(3)) + if ((descriptor.mask & BIT(3)) != 0u) mask |= MTL::ColorWriteMaskAlpha; color_attachment->setWriteMask(mask); @@ -87,7 +87,7 @@ MTL::RenderPipelineState* ClearColorPipelineCache::Create( NS::Error* error; auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create clear color pipeline: {}", error->localizedDescription()->utf8String()); return nullptr; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp index 7c2c1a53..d36efaeb 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp @@ -21,9 +21,9 @@ class ClearColorPipelineCache MTL::RenderPipelineState* Create(const ClearColorPipelineDescriptor& descriptor); void Update([[maybe_unused]] MTL::RenderPipelineState* pipeline) {} - u32 Hash(const ClearColorPipelineDescriptor& descriptor); + static u32 Hash(const ClearColorPipelineDescriptor& descriptor); - void DestroyElement(MTL::RenderPipelineState* pipeline); + static void DestroyElement(MTL::RenderPipelineState* pipeline); private: MTL::Device* device; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp index 548162b8..8c111f04 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp @@ -56,7 +56,7 @@ ClearDepthPipelineCache::Create(MTL::PixelFormat pixel_format) { NS::Error* error; auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create clear depth pipeline: {}", error->localizedDescription()->utf8String()); return nullptr; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp index b4c3b236..515bad91 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp @@ -14,9 +14,9 @@ class ClearDepthPipelineCache MTL::RenderPipelineState* Create(MTL::PixelFormat pixel_format); void Update([[maybe_unused]] MTL::RenderPipelineState* pipeline) {} - u32 Hash(MTL::PixelFormat pixel_format); + static u32 Hash(MTL::PixelFormat pixel_format); - void DestroyElement(MTL::RenderPipelineState* pipeline); + static void DestroyElement(MTL::RenderPipelineState* pipeline); private: MTL::Device* device; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/const.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/const.hpp index 212852df..e8c3c162 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/const.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/const.hpp @@ -61,7 +61,7 @@ inline MTL::Library* CreateLibraryFromSource(MTL::Device* device, // TODO: don't construct a new string? MTL::Library* library = device->newLibrary(ToNSString(std::string(source)), nullptr, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(Gpu, "Failed to create library: {}", error->localizedDescription()->utf8String()); // TODO: don't log? diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp index 7b2304c5..fba57940 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp @@ -22,9 +22,9 @@ class DepthStencilStateCache MTL::DepthStencilState* Create(const DepthStencilStateDescriptor& descriptor); void Update([[maybe_unused]] MTL::DepthStencilState* depth_stencil_state) {} - u32 Hash(const DepthStencilStateDescriptor& descriptor); + static u32 Hash(const DepthStencilStateDescriptor& descriptor); - void DestroyElement(MTL::DepthStencilState* depth_stencil_state); + static void DestroyElement(MTL::DepthStencilState* depth_stencil_state); private: MTL::Device* device; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp index d75bac07..fb58a058 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp @@ -12,10 +12,10 @@ Pipeline::Pipeline(MTL::Device* device, const PipelineDescriptor& descriptor) MTL::RenderPipelineDescriptor::alloc()->init(); // Shaders - const auto vertex_shader = - static_cast(descriptor.shaders[u32(ShaderType::Vertex)]); - const auto fragment_shader = - static_cast(descriptor.shaders[u32(ShaderType::Fragment)]); + const auto vertex_shader = static_cast( + descriptor.shaders[static_cast(ShaderType::Vertex)]); + const auto fragment_shader = static_cast( + descriptor.shaders[static_cast(ShaderType::Fragment)]); pipeline_descriptor->setVertexFunction(vertex_shader->GetFunction()); pipeline_descriptor->setFragmentFunction(fragment_shader->GetFunction()); @@ -139,7 +139,7 @@ Pipeline::Pipeline(MTL::Device* device, const PipelineDescriptor& descriptor) NS::Error* error; pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); pipeline_descriptor->release(); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create pipeline: {}", error->localizedDescription()->utf8String()); error->release(); // TODO: release? diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/render_pass.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/render_pass.cpp index 89158c5f..b5ffef8c 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/render_pass.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/render_pass.cpp @@ -12,7 +12,7 @@ RenderPass::RenderPass(const RenderPassDescriptor& descriptor) // Color targets for (u32 i = 0; i < COLOR_TARGET_COUNT; i++) { const auto& color_target = descriptor.color_targets[i]; - if (!color_target.texture) + if (color_target.texture == nullptr) continue; auto color_attachment = @@ -34,7 +34,7 @@ RenderPass::RenderPass(const RenderPassDescriptor& descriptor) } // Depth stencil target - if (descriptor.depth_stencil_target.texture) { + if (descriptor.depth_stencil_target.texture != nullptr) { const auto& depth_stencil_target = descriptor.depth_stencil_target; const auto& format_info = to_mtl_pixel_format_info( depth_stencil_target.texture->GetDescriptor().format); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp index 111aa9a1..fa4c54ef 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp @@ -79,11 +79,11 @@ void Renderer::SetSurface(void* surface) { ISurfaceCompositor* Renderer::AcquireNextSurface() { // Drawable - if (!ca_layer) + if (ca_layer == nullptr) return nullptr; ca_drawable = ca_layer->nextDrawable(); - if (!ca_drawable) + if (ca_drawable == nullptr) return nullptr; return new SurfaceCompositor(*this, ca_drawable); @@ -143,10 +143,12 @@ void Renderer::BlitTexture(ICommandBuffer* command_buffer, ITextureView* src, // Draw encoder->setRenderPipelineState(blit_pipeline_cache.Find( - {src_impl->GetTexture()->pixelFormat(), false})); - encoder->setViewport(MTL::Viewport(f64(dst_origin.x()), f64(dst_origin.y()), - f64(dst_size.x()), f64(dst_size.y()), - 0.0, 1.0)); + {.pixel_format = src_impl->GetTexture()->pixelFormat(), + .transparent = false})); + encoder->setViewport(MTL::Viewport( + static_cast(dst_origin.x()), static_cast(dst_origin.y()), + static_cast(dst_size.x()), static_cast(dst_size.y()), 0.0, + 1.0)); encoder->setVertexBytes(&dst_layer, sizeof(dst_layer), 0); BlitParams params = { .src_offset = {static_cast(src_origin.x()) / @@ -159,12 +161,15 @@ void Renderer::BlitTexture(ICommandBuffer* command_buffer, ITextureView* src, static_cast(src_impl->GetTexture()->height())}), }; encoder->setFragmentBytes(¶ms, sizeof(params), 0); - encoder->setFragmentTexture(src_impl->GetTexture(), NS::UInteger(0)); + encoder->setFragmentTexture(src_impl->GetTexture(), + static_cast(0)); encoder->setFragmentSamplerState( - linear_sampler, NS::UInteger(0)); // TODO: use the correct sampler + linear_sampler, + static_cast(0)); // TODO: use the correct sampler - encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - NS::UInteger(3)); + encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, + static_cast(0), + static_cast(3)); } SamplerBase* Renderer::CreateSampler(const SamplerDescriptor& descriptor) { @@ -194,7 +199,7 @@ void Renderer::ClearColor(ICommandBuffer* command_buffer, u32 render_target_id, .texture); // HACK - if (!texture) { + if (texture == nullptr) { ONCE(LOG_WARN(MetalRenderer, "Invalid color target at index {}", render_target_id)); return; @@ -207,13 +212,15 @@ void Renderer::ClearColor(ICommandBuffer* command_buffer, u32 render_target_id, auto encoder = GetRenderCommandEncoder(command_buffer_impl); command_buffer_impl->SetRenderPipelineState(clear_color_pipeline_cache.Find( - {to_mtl_pixel_format(texture->GetDescriptor().format), render_target_id, - mask})); + {.pixel_format = to_mtl_pixel_format(texture->GetDescriptor().format), + .render_target_id = render_target_id, + .mask = mask})); // TODO: set viewport and scissor encoder->setVertexBytes(&render_target_id, sizeof(render_target_id), 0); encoder->setFragmentBytes(&color, sizeof(color), 0); - encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - NS::UInteger(3)); + encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, + static_cast(0), + static_cast(3)); } void Renderer::ClearDepth(ICommandBuffer* command_buffer, u32 layer, @@ -224,7 +231,7 @@ void Renderer::ClearDepth(ICommandBuffer* command_buffer, u32 layer, state.render_pass->GetDescriptor().depth_stencil_target.texture); // HACK - if (!texture) { + if (texture == nullptr) { ONCE(LOG_WARN(MetalRenderer, "Invalid depth target")); return; } @@ -247,10 +254,11 @@ void Renderer::ClearDepth(ICommandBuffer* command_buffer, u32 layer, struct { u32 layer_id; float value; - } params = {layer, value}; + } params = {.layer_id = layer, .value = value}; encoder->setVertexBytes(¶ms, sizeof(params), 0); - encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - NS::UInteger(3)); + encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, + static_cast(0), + static_cast(3)); } void Renderer::ClearStencil(ICommandBuffer* command_buffer, u32 layer, @@ -308,7 +316,7 @@ void Renderer::BindUniformBuffer(const BufferView& buffer, if (shader_type == ShaderType::Count) return; - state.uniform_buffers[u32(shader_type)][index] = buffer; + state.uniform_buffers[static_cast(shader_type)][index] = buffer; } void Renderer::BindTexture(ITextureView* texture, SamplerBase* sampler, @@ -317,8 +325,9 @@ void Renderer::BindTexture(ITextureView* texture, SamplerBase* sampler, if (shader_type == ShaderType::Count) return; - state.textures[u32(shader_type)][index] = { - static_cast(texture), static_cast(sampler)}; + state.textures[static_cast(shader_type)][index] = { + .texture_view = static_cast(texture), + .sampler = static_cast(sampler)}; } void Renderer::UnbindUniformBuffers(ShaderType shader_type) { @@ -326,7 +335,7 @@ void Renderer::UnbindUniformBuffers(ShaderType shader_type) { if (shader_type == ShaderType::Count) return; - state.uniform_buffers[u32(shader_type)] = {}; + state.uniform_buffers[static_cast(shader_type)] = {}; } void Renderer::UnbindTextures(ShaderType shader_type) { @@ -334,7 +343,7 @@ void Renderer::UnbindTextures(ShaderType shader_type) { if (shader_type == ShaderType::Count) return; - state.textures[u32(shader_type)] = {}; + state.textures[static_cast(shader_type)] = {}; } void Renderer::Draw(ICommandBuffer* command_buffer, @@ -388,12 +397,12 @@ void Renderer::DrawIndexed(ICommandBuffer* command_buffer, } MTL::RenderCommandEncoder* -Renderer::GetRenderCommandEncoder(CommandBuffer* command_buffer) { +Renderer::GetRenderCommandEncoder(CommandBuffer* command_buffer) const { return command_buffer->GetRenderCommandEncoder( state.render_pass->GetRenderPassDescriptor()); } -void Renderer::SetRenderPipelineState(CommandBuffer* command_buffer) { +void Renderer::SetRenderPipelineState(CommandBuffer* command_buffer) const { command_buffer->SetRenderPipelineState(state.pipeline->GetPipeline()); } @@ -413,7 +422,7 @@ void Renderer::SetVertexBuffer(CommandBuffer* command_buffer, u32 index) { "Invalid vertex buffer index {}", index); const auto buffer = state.vertex_buffers[index]; - if (!buffer.GetBase()) + if (buffer.GetBase() == nullptr) return; command_buffer->SetBuffer( @@ -430,7 +439,7 @@ void Renderer::SetUniformBuffer(CommandBuffer* command_buffer, const auto buffer = state.uniform_buffers[static_cast(shader_type)][index]; - if (!buffer.GetBase()) + if (buffer.GetBase() == nullptr) return; command_buffer->SetBuffer( @@ -440,11 +449,11 @@ void Renderer::SetUniformBuffer(CommandBuffer* command_buffer, void Renderer::SetTexture(CommandBuffer* command_buffer, ShaderType shader_type, u32 index) { - const auto texture = state.textures[u32(shader_type)][index]; - if (texture.texture_view) + const auto texture = state.textures[static_cast(shader_type)][index]; + if (texture.texture_view != nullptr) command_buffer->SetTexture(texture.texture_view->GetTexture(), shader_type, index); - if (texture.sampler) + if (texture.sampler != nullptr) command_buffer->SetSampler(texture.sampler->GetSampler(), shader_type, index); } @@ -492,7 +501,7 @@ void Renderer::BeginCapture() { NS::Error* error = nullptr; capture_manager->startCapture(desc, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to start GPU capture: {}", error->localizedDescription()->utf8String()); } @@ -503,8 +512,8 @@ void Renderer::EndCapture() { captureManager->stopCapture(); } -bool Renderer::CanDraw() { - if (!state.pipeline->GetPipeline()) { +bool Renderer::CanDraw() const { + if (state.pipeline->GetPipeline() == nullptr) { ONCE(LOG_WARN(MetalRenderer, "Pipeline not present, skipping draw")); return false; } diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp index a908630c..c2bb5d48 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp @@ -29,7 +29,7 @@ struct State { engines::CompareOp depth_compare_op; Viewport viewports[VIEWPORT_COUNT]; Scissor scissors[VIEWPORT_COUNT]; - BufferView index_buffer{}; + BufferView index_buffer; engines::IndexType index_type{engines::IndexType::None}; std::array vertex_buffers{}; std::array, @@ -124,10 +124,10 @@ class Renderer : public IRenderer { // Helpers MTL::RenderCommandEncoder* - GetRenderCommandEncoder(CommandBuffer* command_buffer); + GetRenderCommandEncoder(CommandBuffer* command_buffer) const; // Encoder state setting - void SetRenderPipelineState(CommandBuffer* command_buffer); + void SetRenderPipelineState(CommandBuffer* command_buffer) const; void SetDepthStencilState(CommandBuffer* command_buffer); void SetVertexBuffer(CommandBuffer* command_buffer, u32 index); void SetUniformBuffer(CommandBuffer* command_buffer, ShaderType shader_type, @@ -170,7 +170,7 @@ class Renderer : public IRenderer { // encoder_state corrupts the state // Helpers - bool CanDraw(); + bool CanDraw() const; void BindDrawState(CommandBuffer* command_buffer); public: diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp index f8486e02..eb7d482e 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp @@ -24,7 +24,7 @@ Shader::Shader(MTL::Device* device, const ShaderDescriptor& descriptor) NS::Error* error; library = device->newLibrary(ToNSString(source), options, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create Metal library: {}", error->localizedDescription()->utf8String()); error->release(); // TODO: autorelease @@ -42,7 +42,7 @@ Shader::Shader(MTL::Device* device, const ShaderDescriptor& descriptor) NS::Error* error; // TODO: options library = device->newLibrary(dispatch_data, &error); - if (error) { + if (error != nullptr) { LOG_ERROR(MetalRenderer, "Failed to create Metal library: {}", error->localizedDescription()->utf8String()); error->release(); // TODO: autorelease diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp index 82436512..83ecb5dc 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp @@ -36,12 +36,15 @@ void SurfaceCompositor::DrawTexture(ICommandBuffer* command_buffer, // Draw encoder->setRenderPipelineState(renderer.GetBlitPipelineCache().Find( - {drawable->texture()->pixelFormat(), transparent})); - encoder->setViewport(MTL::Viewport{static_cast(dst_rect.origin.x()), - static_cast(dst_rect.origin.y()), - static_cast(dst_rect.size.x()), - static_cast(dst_rect.size.y()), 0.0, - 1.0}); + {.pixel_format = drawable->texture()->pixelFormat(), + .transparent = transparent})); + encoder->setViewport( + MTL::Viewport{.originX = static_cast(dst_rect.origin.x()), + .originY = static_cast(dst_rect.origin.y()), + .width = static_cast(dst_rect.size.x()), + .height = static_cast(dst_rect.size.y()), + .znear = 0.0, + .zfar = 1.0}); u32 zero = 0; encoder->setVertexBytes(&zero, sizeof(zero), 0); @@ -59,11 +62,13 @@ void SurfaceCompositor::DrawTexture(ICommandBuffer* command_buffer, }; encoder->setFragmentBytes(¶ms, sizeof(params), 0); - encoder->setFragmentTexture(texture_impl->GetTexture(), NS::UInteger(0)); + encoder->setFragmentTexture(texture_impl->GetTexture(), + static_cast(0)); encoder->setFragmentSamplerState(renderer.GetLinearSampler(), - NS::UInteger(0)); - encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - NS::UInteger(3)); + static_cast(0)); + encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, + static_cast(0), + static_cast(3)); } void SurfaceCompositor::Present(ICommandBuffer* command_buffer) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/null/buffer.cpp b/src/core/hw/tegra_x1/gpu/renderer/null/buffer.cpp index 15e77cd6..64f710b9 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/null/buffer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/null/buffer.cpp @@ -4,7 +4,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::null { -Buffer::Buffer(u64 size) : BufferBase(size) { buffer = new u8[size]; } +Buffer::Buffer(u64 size) : BufferBase(size), buffer(new u8[size]) { } Buffer::~Buffer() { delete[] buffer; } void Buffer::CopyFrom([[maybe_unused]] ICommandBuffer* command_buffer, diff --git a/src/core/hw/tegra_x1/gpu/renderer/null/renderer.cpp b/src/core/hw/tegra_x1/gpu/renderer/null/renderer.cpp index 42d697c7..1d239acd 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/null/renderer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/null/renderer.cpp @@ -6,26 +6,26 @@ namespace hydra::hw::tegra_x1::gpu::renderer::null { -CommandBuffer::CommandBuffer() {} -CommandBuffer::~CommandBuffer() {} +CommandBuffer::CommandBuffer() = default; +CommandBuffer::~CommandBuffer() = default; Sampler::Sampler(const SamplerDescriptor& descriptor) : SamplerBase(descriptor) {} -Sampler::~Sampler() {} +Sampler::~Sampler() = default; RenderPass::RenderPass(const RenderPassDescriptor& descriptor) : RenderPassBase(descriptor) {} -RenderPass::~RenderPass() {} +RenderPass::~RenderPass() = default; Pipeline::Pipeline(const PipelineDescriptor& descriptor) : PipelineBase(descriptor) {} -Pipeline::~Pipeline() {} +Pipeline::~Pipeline() = default; Shader::Shader(const ShaderDescriptor& descriptor) : ShaderBase(descriptor) {} -Shader::~Shader() {} +Shader::~Shader() = default; -Renderer::Renderer() {} -Renderer::~Renderer() {} +Renderer::Renderer() = default; +Renderer::~Renderer() = default; void Renderer::SetSurface([[maybe_unused]] void* surface) {} @@ -140,4 +140,4 @@ void Renderer::DrawIndexed( void Renderer::BeginCapture() {} void Renderer::EndCapture() {} -} // namespace hydra::hw::tegra_x1::gpu::renderer::null \ No newline at end of file +} // namespace hydra::hw::tegra_x1::gpu::renderer::null diff --git a/src/core/hw/tegra_x1/gpu/renderer/null/surface_compositor.cpp b/src/core/hw/tegra_x1/gpu/renderer/null/surface_compositor.cpp index a4e67a30..3bdbef67 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/null/surface_compositor.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/null/surface_compositor.cpp @@ -2,8 +2,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::null { -SurfaceCompositor::SurfaceCompositor() {} -SurfaceCompositor::~SurfaceCompositor() {} +SurfaceCompositor::SurfaceCompositor() = default; +SurfaceCompositor::~SurfaceCompositor() = default; void SurfaceCompositor::DrawTexture( [[maybe_unused]] ICommandBuffer* command_buffer, diff --git a/src/core/hw/tegra_x1/gpu/renderer/null/texture.cpp b/src/core/hw/tegra_x1/gpu/renderer/null/texture.cpp index d9be7d8f..4789d017 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/null/texture.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/null/texture.cpp @@ -3,7 +3,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::null { Texture::Texture(const TextureDescriptor& descriptor) : ITexture(descriptor) {} -Texture::~Texture() {} +Texture::~Texture() = default; ITextureView* Texture::CreateView(const TextureViewDescriptor& view_descriptor) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp index f7ec8ddc..5a9f35db 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp @@ -20,9 +20,8 @@ u32 PipelineCache::Hash(const PipelineDescriptor& descriptor) { // Vertex state // Vertex attributes - for (u32 i = 0; i < VERTEX_ATTRIB_COUNT; i++) { - const auto& vertex_attrib_state = - descriptor.vertex_state.vertex_attrib_states[i]; + for (const auto& vertex_attrib_state : + descriptor.vertex_state.vertex_attrib_states) { hash.Add(vertex_attrib_state.buffer_id); // is_fixed is in vertex shader hash hash.Add(vertex_attrib_state.offset); @@ -31,8 +30,7 @@ u32 PipelineCache::Hash(const PipelineDescriptor& descriptor) { } // Vertex arrays - for (u32 i = 0; i < VERTEX_ARRAY_COUNT; i++) { - const auto& vertex_array = descriptor.vertex_state.vertex_arrays[i]; + for (const auto& vertex_array : descriptor.vertex_state.vertex_arrays) { hash.Add(vertex_array.enable); hash.Add(vertex_array.stride); hash.Add(vertex_array.is_per_instance); @@ -42,8 +40,7 @@ u32 PipelineCache::Hash(const PipelineDescriptor& descriptor) { // Color state // Color targets - for (u32 i = 0; i < COLOR_TARGET_COUNT; i++) { - const auto& color_target_state = descriptor.color_target_states[i]; + for (const auto& color_target_state : descriptor.color_target_states) { hash.Add(color_target_state.format); hash.Add(color_target_state.blend_enabled); if (color_target_state.blend_enabled) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp index a9edf3c6..18b91a90 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp @@ -16,9 +16,9 @@ class PipelineCache PipelineBase* Create(const PipelineDescriptor& descriptor); void Update([[maybe_unused]] PipelineBase* pipeline) {} - u32 Hash(const PipelineDescriptor& descriptor); + static u32 Hash(const PipelineDescriptor& descriptor); - void DestroyElement(PipelineBase* pipeline); + static void DestroyElement(PipelineBase* pipeline); private: IRenderer& renderer; diff --git a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp index 4dc9060b..67a86f07 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp @@ -15,8 +15,8 @@ u32 RenderPassCache::Hash(const RenderPassDescriptor& descriptor) { // TODO: improve this // TODO: also hash metadata about clears - for (u32 i = 0; i < COLOR_TARGET_COUNT; i++) - hash.Add(descriptor.color_targets[i].texture); + for (const auto& color_target : descriptor.color_targets) + hash.Add(color_target.texture); hash.Add(descriptor.depth_stencil_target.texture); return hash.ToHashCode(); diff --git a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp index 40ac3d23..a5a6ee85 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp @@ -16,9 +16,9 @@ class RenderPassCache RenderPassBase* Create(const RenderPassDescriptor& descriptor); void Update([[maybe_unused]] RenderPassBase* render_pass) {} - u32 Hash(const RenderPassDescriptor& descriptor); + static u32 Hash(const RenderPassDescriptor& descriptor); - void DestroyElement(RenderPassBase* render_pass); + static void DestroyElement(RenderPassBase* render_pass); private: IRenderer& renderer; diff --git a/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp b/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp index 34534865..5d459fee 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp @@ -46,7 +46,7 @@ class IRenderer { : buffer_cache(*this), texture_cache(*this), sampler_cache(*this), render_pass_cache(*this), shader_cache(*this), pipeline_cache(*this), index_cache(*this) {} - virtual ~IRenderer() {} + virtual ~IRenderer() = default; void InvalidateMemory( Range range, diff --git a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp index c46780af..649836e7 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp @@ -20,9 +20,9 @@ class SamplerCache SamplerBase* Create(const SamplerDescriptor& descriptor); void Update([[maybe_unused]] SamplerBase* sampler) {} - u32 Hash(const SamplerDescriptor& descriptor); + static u32 Hash(const SamplerDescriptor& descriptor); - void DestroyElement(SamplerBase* sampler); + static void DestroyElement(SamplerBase* sampler); private: IRenderer& renderer; diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_base.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_base.hpp index b232035f..ddf06ffd 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_base.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_base.hpp @@ -6,7 +6,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class ShaderBase { public: - ShaderBase(const ShaderDescriptor& descriptor_) : descriptor(descriptor_) {} + ShaderBase(ShaderDescriptor descriptor_) + : descriptor(std::move(descriptor_)) {} virtual ~ShaderBase() = default; // Getters diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp index 3f4edd82..a01e4a29 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp @@ -15,10 +15,10 @@ ShaderBase* ShaderCache::Create(const GuestShaderDescriptor& descriptor) { io::MemoryStream code_stream( std::span(reinterpret_cast(descriptor.code_ptr), 0x1000)); // TODO: size - shader_decomp::Decompiler decompiler; - decompiler.Decompile(code_stream, host_descriptor.type, descriptor.state, - host_descriptor.backend, host_descriptor.code, - host_descriptor.resource_mapping); + shader_decomp::Decompile(code_stream, host_descriptor.type, + descriptor.state, host_descriptor.backend, + host_descriptor.code, + host_descriptor.resource_mapping); return renderer.CreateShader(host_descriptor); } @@ -41,9 +41,8 @@ u32 ShaderCache::Hash(const GuestShaderDescriptor& descriptor) { // Vertex state if (descriptor.stage == engines::ShaderStage::VertexB) { - for (u32 i = 0; i < VERTEX_ATTRIB_COUNT; i++) { - const auto& vertex_attrib_state = - descriptor.state.vertex_attrib_states[i]; + for (const auto& vertex_attrib_state : + descriptor.state.vertex_attrib_states) { hash.Add(vertex_attrib_state.is_fixed); hash.Add(vertex_attrib_state.size); hash.Add(vertex_attrib_state.type); @@ -52,9 +51,8 @@ u32 ShaderCache::Hash(const GuestShaderDescriptor& descriptor) { // Color target data types if (descriptor.stage == engines::ShaderStage::Fragment) { - for (u32 i = 0; i < COLOR_TARGET_COUNT; i++) { - const auto color_target_data_type = - descriptor.state.color_target_data_types[i]; + for (const auto& color_target_data_type : + descriptor.state.color_target_data_types) { hash.Add(color_target_data_type); } } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp index 1b3b48b2..6b0edb5d 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp @@ -29,9 +29,9 @@ class ShaderCache ShaderBase* Create(const GuestShaderDescriptor& descriptor); void Update([[maybe_unused]] ShaderBase* shader) {} - u32 Hash(const GuestShaderDescriptor& descriptor); + static u32 Hash(const GuestShaderDescriptor& descriptor); - void DestroyElement(ShaderBase* shader); + static void DestroyElement(ShaderBase* shader); private: IRenderer& renderer; diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/cfg.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/cfg.hpp index e0c4a0bb..ce5d4612 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/cfg.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/cfg.hpp @@ -278,7 +278,7 @@ class CfgBuilder { // Helpers CfgBasicBlock* GetBlock(label_t label) { auto& block = blocks[label]; - if (!block) + if (block == nullptr) block = new CfgBasicBlock{.label = label}; return block; } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/memory_analyzer.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/memory_analyzer.cpp index 19b61962..62cd7dfc 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/memory_analyzer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/analyzer/memory_analyzer.cpp @@ -57,7 +57,7 @@ void MemoryAnalyzer::Analyze(const ir::Module& modul) { bool is_depth = any(flags & TextureSampleFlags::DepthCompare); HandleTextureAccess(const_buffer_index, - TextureInfo{type, is_depth}); + TextureInfo{.type=type, .is_depth=is_depth}); break; } case ir::Opcode::TextureGather: { @@ -65,7 +65,7 @@ void MemoryAnalyzer::Analyze(const ir::Module& modul) { instruction.GetOperand(0).GetRawValue(); // TODO: is_depth HandleTextureAccess(const_buffer_index, - TextureInfo{TextureType::_2D, false}); + TextureInfo{.type=TextureType::_2D, .is_depth=false}); break; } // TODO: TextureQueryDimension? diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/emitter.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/emitter.hpp index e93436d7..b29b03e6 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/emitter.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/emitter.hpp @@ -26,7 +26,7 @@ class Emitter { ResourceMapping& out_resource_mapping_) : context{context_}, memory_analyzer{memory_analyzer_}, state{state_}, out_code{out_code_}, out_resource_mapping{out_resource_mapping_} {} - virtual ~Emitter() {} + virtual ~Emitter() = default; void Emit(const ir::Module& modul); diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.cpp index 9cba72e4..b3566d1b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.cpp @@ -54,7 +54,7 @@ void LangEmitter::Finish() { // TODO: avoid copying out_code.resize(code_str.size()); - std::copy(code_str.begin(), code_str.end(), out_code.begin()); + std::ranges::copy(code_str, out_code.begin()); // Debug LOG_DEBUG(ShaderDecompiler, "decompiled: \"\n{}\"", code_str); @@ -160,9 +160,9 @@ void LangEmitter::EmitFunction(const ir::Function& func) { // Function // TODO: function name std::string name = "main"; - if (name == "main") + if (name == "main") { EmitMainPrototype(); - else + } else LOG_FATAL(ShaderDecompiler, "Custom functions not implemented (name: {})", name); diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.hpp index 9d189550..7a969d2f 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/emitter.hpp @@ -216,7 +216,7 @@ class LangEmitter : public Emitter { case ir::TypeKind::Scalar: { switch (type.GetScalarType()) { case ir::ScalarType::Bool: - return GetConstantStr(imm & 0x1); + return GetConstantStr((imm & 0x1) != 0u); case ir::ScalarType::U8: return GetConstantStr(imm & 0xff); case ir::ScalarType::U16: @@ -233,7 +233,7 @@ class LangEmitter : public Emitter { return GetConstantStr(std::bit_cast(imm)); case ir::ScalarType::F16: return fmt::format("as_type((u16)0x{:04x})", - u16(imm & 0xffff)); + static_cast(imm & 0xffff)); case ir::ScalarType::F32: return GetConstantStr(std::bit_cast(imm)); } @@ -245,7 +245,7 @@ class LangEmitter : public Emitter { } } - std::string GetLocalStr(local_t local) { + static std::string GetLocalStr(local_t local) { return fmt::format("local0x{:x}_{}", u32(local.label), local.id); } @@ -329,14 +329,14 @@ class LangEmitter : public Emitter { } } - char GetComponentStrFromIndex(u8 component_index) { + static char GetComponentStrFromIndex(u8 component_index) { ASSERT_DEBUG(component_index < 4, ShaderDecompiler, "Invalid component index {}", component_index); return "xyzw"[component_index]; } - const std::string GetTypeSuffixStr(ir::Type type) { + static std::string GetTypeSuffixStr(ir::Type type) { switch (type.GetKind()) { case ir::TypeKind::Scalar: { switch (type.GetScalarType()) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/msl/emitter.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/msl/emitter.hpp index 871084a8..d3758314 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/msl/emitter.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/msl/emitter.hpp @@ -61,7 +61,7 @@ class MslEmitter final : public LangEmitter { private: // Helpers - std::string GetSvStr(const Sv& sv); + static std::string GetSvStr(const Sv& sv); std::string GetSvQualifierStr(const Sv& sv, bool output); }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.cpp index 16a0b9e0..8a97300d 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.cpp @@ -2,7 +2,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp { -const SvAccess get_sv_access_from_addr(u64 addr) { +SvAccess get_sv_access_from_addr(u64 addr) { ASSERT_ALIGNMENT_DEBUG(addr, 4, ShaderDecompiler, "Address"); struct SvBase { @@ -11,10 +11,10 @@ const SvAccess get_sv_access_from_addr(u64 addr) { }; static constexpr SvBase bases[] = { - {SvSemantic::VertexID, SV_VERTEX_ID_BASE}, - {SvSemantic::InstanceID, SV_INSTANCE_ID_BASE}, - {SvSemantic::UserInOut, SV_USER_IN_OUT_BASE}, - {SvSemantic::Position, SV_POSITION_BASE}, + {.semantic=SvSemantic::VertexID, .base_addr=SV_VERTEX_ID_BASE}, + {.semantic=SvSemantic::InstanceID, .base_addr=SV_INSTANCE_ID_BASE}, + {.semantic=SvSemantic::UserInOut, .base_addr=SV_USER_IN_OUT_BASE}, + {.semantic=SvSemantic::Position, .base_addr=SV_POSITION_BASE}, }; for (const auto& base : bases) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.hpp index 4c60c922..24ed18b0 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/const.hpp @@ -5,7 +5,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp { -typedef u64 instruction_t; +using instruction_t = u64; STRONG_NUMBER_TYPEDEF(reg_t, u8); STRONG_NUMBER_TYPEDEF(pred_t, u8); STRONG_NUMBER_TYPEDEF(label_t, u32); @@ -100,7 +100,7 @@ struct SvAccess { : sv{sv_}, component_index{component_index_} {} }; -const SvAccess get_sv_access_from_addr(u64 addr); +SvAccess get_sv_access_from_addr(u64 addr); enum class TextureType { _1D, @@ -175,7 +175,7 @@ struct fmt::formatter if (reg == hydra::hw::tegra_x1::gpu::renderer::shader_decomp::RZ) return formatter::format("0", ctx); return formatter::format( - fmt::format("r{}", hydra::u8(reg)), ctx); + fmt::format("r{}", static_cast(reg)), ctx); } }; @@ -189,7 +189,7 @@ struct fmt::formatter if (pred == hydra::hw::tegra_x1::gpu::renderer::shader_decomp::PT) return formatter::format("true", ctx); return formatter::format( - fmt::format("p{}", hydra::u8(pred)), ctx); + fmt::format("p{}", static_cast(pred)), ctx); } }; @@ -202,7 +202,7 @@ struct fmt::formatter< const hydra::hw::tegra_x1::gpu::renderer::shader_decomp::label_t label, FormatContext& ctx) const { return formatter::format( - fmt::format("label0x{:x}", hydra::u32(label)), ctx); + fmt::format("label0x{:x}", static_cast(label)), ctx); } }; @@ -215,7 +215,9 @@ struct fmt::formatter< const hydra::hw::tegra_x1::gpu::renderer::shader_decomp::local_t local, FormatContext& ctx) const { return formatter::format( - fmt::format("%0x{:x}_{}", hydra::u32(local.label), local.id), ctx); + fmt::format("%0x{:x}_{}", static_cast(local.label), + local.id), + ctx); } }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/bitfield.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/bitfield.cpp index 916bd33f..17bbf729 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/bitfield.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/bitfield.cpp @@ -36,7 +36,8 @@ void EmitBfeC(DecoderContext& context, InstBfeC inst) { EmitBitfieldExtract( context, inst.base.pred, inst.base.pred_inv, inst.base.is_signed, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4))); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)))); } void EmitBfeI(DecoderContext& context, InstBfeI inst) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/conversion.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/conversion.cpp index 1ce74bf4..19545373 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/conversion.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/conversion.cpp @@ -179,8 +179,9 @@ void EmitF2fC(DecoderContext& context, InstF2fC inst) { EmitFloatToFloat( context, inst.base.pred, inst.base.pred_inv, inst.base.GetRoundMode(), inst.base.sat, inst.base.dst, inst.base.dst_fmt, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ToType(inst.base.src_fmt)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ToType(inst.base.src_fmt)), inst.base.abs, inst.base.neg); } @@ -204,8 +205,9 @@ void EmitF2iC(DecoderContext& context, InstF2iC inst) { EmitFloatToInt( context, inst.base.pred, inst.base.pred_inv, inst.base.round_mode, inst.base.dst, inst.base.GetDstFmt(), - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ToType(inst.base.src_fmt)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ToType(inst.base.src_fmt)), inst.base.abs, inst.base.neg); } @@ -230,8 +232,9 @@ void EmitI2iC(DecoderContext& context, InstI2iC inst) { EmitIntToInt( context, inst.base.pred, inst.base.pred_inv, inst.base.byte_sel, inst.base.sat, inst.base.dst, inst.base.GetDstFmt(), - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ToType(inst.base.GetSrcFmt())), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ToType(inst.base.GetSrcFmt())), inst.base.abs, inst.base.neg); } @@ -255,8 +258,9 @@ void EmitI2fC(DecoderContext& context, InstI2fC inst) { EmitIntToFloat( context, inst.base.pred, inst.base.pred_inv, inst.base.byte_sel, inst.base.dst, inst.base.dst_fmt, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ToType(inst.base.GetSrcFmt())), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ToType(inst.base.GetSrcFmt())), inst.base.abs, inst.base.neg); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.cpp index 604eeb26..895070ca 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.cpp @@ -24,7 +24,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp::decoder { void Decoder::Decode() { crnt_block = &blocks[0x0]; - while (crnt_block) { + while (crnt_block != nullptr) { ParseNextInstruction(); } } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.hpp index 3ae7e648..f14d4466 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/decoder.hpp @@ -33,7 +33,7 @@ class Decoder { void ParseNextInstruction(); // Helpers - void Jump(u32 target) { + void Jump(u32 target) const { context.code_stream->SeekTo(target * sizeof(instruction_t)); } u32 GetPC() const { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_arithmetic.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_arithmetic.cpp index a438e12b..dd30e27e 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_arithmetic.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_arithmetic.cpp @@ -100,8 +100,9 @@ void EmitFaddC(DecoderContext& context, InstFaddC inst) { EmitFadd( context, inst.base.pred, inst.base.pred_inv, inst.base.sat, inst.base.dst, inst.base.src_a, inst.base.abs_a, inst.base.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.abs_b, inst.base.neg_b); } @@ -130,8 +131,9 @@ void EmitFmulC(DecoderContext& context, InstFmulC inst) { EmitFmul( context, inst.base.pred, inst.base.pred_inv, inst.base.scale, inst.base.sat, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.neg_b); } @@ -161,8 +163,9 @@ void EmitFfmaRC(DecoderContext& context, InstFfmaRC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.sat, inst.base.dst, inst.base.src_a, false, ir::Value::Register(inst.src_b, ir::ScalarType::F32), inst.base.neg_b, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.neg_c); } @@ -170,8 +173,9 @@ void EmitFfmaC(DecoderContext& context, InstFfmaC inst) { EmitFfma( context, inst.base.pred, inst.base.pred_inv, inst.base.sat, inst.base.dst, inst.base.src_a, false, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.neg_b, ir::Value::Register(inst.src_c, ir::ScalarType::F32), inst.base.neg_c); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_comparison.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_comparison.cpp index ff7a0289..ef89437d 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_comparison.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_comparison.cpp @@ -78,8 +78,9 @@ void EmitFsetC(DecoderContext& context, InstFsetC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.op, inst.base.b_op, inst.base.dst, inst.base.src_a, inst.base.abs_a, inst.base.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.abs_b, inst.base.neg_b, inst.base.src_pred, inst.base.src_pred_inv, inst.base.b_float); } @@ -108,8 +109,9 @@ void EmitFsetpC(DecoderContext& context, InstFsetpC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.op, inst.base.b_op, inst.base.dst_pred, inst.base.dst_inv_pred, inst.base.src_a, inst.base.abs_a, inst.base.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.abs_b, inst.base.neg_b, inst.base.src_pred, inst.base.src_pred_inv); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_min_max.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_min_max.cpp index c2785bcc..1c3a7fdb 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_min_max.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/float_min_max.cpp @@ -41,8 +41,9 @@ void EmitFmnmxC(DecoderContext& context, InstFmnmxC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.dst, inst.base.src_pred, inst.base.src_pred_inv, inst.base.src_a, inst.base.abs_a, inst.base.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), inst.base.abs_b, inst.base.neg_b); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_arithmetic.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_arithmetic.cpp index ee39c0bb..cf9c6c87 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_arithmetic.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_arithmetic.cpp @@ -123,8 +123,9 @@ void EmitHadd2C(DecoderContext& context, InstHadd2C inst) { context, inst.base.pred, inst.base.pred_inv, inst.sat, inst.base.out_fmt, inst.base.dst, inst.base.src_a, inst.base.swizzle_a, inst.base.abs_a, inst.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::VectorType(ir::ScalarType::F16, 2)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::VectorType(ir::ScalarType::F16, 2)), inst.abs_b, inst.neg_b); } @@ -158,8 +159,9 @@ void EmitHmul2C(DecoderContext& context, InstHmul2C inst) { context, inst.base.pred, inst.base.pred_inv, inst.sat, inst.base.out_fmt, inst.base.dst, inst.base.src_a, inst.base.swizzle_a, inst.base.abs_a, inst.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::VectorType(ir::ScalarType::F16, 2)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::VectorType(ir::ScalarType::F16, 2)), inst.abs_b, false); } @@ -196,8 +198,9 @@ void EmitHfma2RC(DecoderContext& context, InstHfma2RC inst) { inst.base.out_fmt, inst.base.dst, inst.base.src_a, inst.base.swizzle_a, false, GetSwizzledHalf(context.builder, inst.swizzle_b, inst.src_b), inst.neg_b, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::VectorType(ir::ScalarType::F16, 2)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::VectorType(ir::ScalarType::F16, 2)), inst.neg_c); } @@ -206,8 +209,9 @@ void EmitHfma2C(DecoderContext& context, InstHfma2C inst) { context, inst.base.pred, inst.base.pred_inv, inst.sat, inst.base.out_fmt, inst.base.dst, inst.base.src_a, inst.base.swizzle_a, false, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::VectorType(ir::ScalarType::F16, 2)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::VectorType(ir::ScalarType::F16, 2)), inst.neg_b, GetSwizzledHalf(context.builder, inst.swizzle_c, inst.src_c), inst.neg_c); diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_comparison.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_comparison.cpp index c5400aa8..48c1e90b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_comparison.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/half_comparison.cpp @@ -57,8 +57,9 @@ void EmitHsetp2C(DecoderContext& context, InstHsetp2C inst) { context, inst.base.pred, inst.base.pred_inv, inst.op, inst.base.b_op, inst.h_and, inst.base.dst_pred, inst.base.dst_inv_pred, inst.base.src_a, inst.base.swizzle_a, inst.base.abs_a, inst.base.neg_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::VectorType(ir::ScalarType::F16, 2)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::VectorType(ir::ScalarType::F16, 2)), inst.abs_b, inst.neg_b, inst.base.src_pred, inst.base.src_pred_inv); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_arithmetic.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_arithmetic.cpp index c6f49f07..1d7ddf24 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_arithmetic.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_arithmetic.cpp @@ -133,8 +133,9 @@ void EmitIaddC(DecoderContext& context, InstIaddC inst) { EmitIadd( context, inst.base.pred, inst.base.pred_inv, inst.base.avg_mode, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::I32)); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::I32)); } void EmitIaddI(DecoderContext& context, InstIaddI inst) { @@ -159,8 +160,9 @@ void EmitIscaddC(DecoderContext& context, InstIscaddC inst) { EmitIscadd( context, inst.base.pred, inst.base.pred_inv, inst.base.avg_mode, inst.base.dst, inst.base.src_a, inst.base.shift, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::I32)); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::I32)); } void EmitIscaddI(DecoderContext& context, InstIscaddI inst) { @@ -195,17 +197,18 @@ void EmitXmadRC(DecoderContext& context, InstXmadRC inst) { ? ir::ScalarType::I32 : ir::ScalarType::U32), inst.hilo_b, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::U32)); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::U32)); } void EmitXmadC(DecoderContext& context, InstXmadC inst) { EmitXmad( context, inst.base.pred, inst.base.pred_inv, inst.cop, false, false, inst.base.dst, inst.base.src_a, inst.base.a_signed, inst.base.hilo_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - inst.base.b_signed ? ir::ScalarType::I32 - : ir::ScalarType::U32), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + inst.base.b_signed ? ir::ScalarType::I32 : ir::ScalarType::U32), inst.hilo_b, ir::Value::Register(inst.src_c, ir::ScalarType::U32)); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_comparison.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_comparison.cpp index 999aad63..d744e4fe 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_comparison.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_comparison.cpp @@ -94,8 +94,9 @@ void EmitIsetC(DecoderContext& context, InstIsetC inst) { EmitIntSet( context, inst.base.pred, inst.base.pred_inv, inst.base.op, inst.base.b_op, inst.base.is_signed, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - GetDataType(inst.base.is_signed)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + GetDataType(inst.base.is_signed)), inst.base.src_pred, inst.base.src_pred_inv, inst.base.b_float); } @@ -122,8 +123,9 @@ void EmitIsetpC(DecoderContext& context, InstIsetpC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.op, inst.base.b_op, inst.base.is_signed, inst.base.dst_pred, inst.base.dst_inv_pred, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - GetDataType(inst.base.is_signed)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)), + GetDataType(inst.base.is_signed)), inst.base.src_pred, inst.base.src_pred_inv); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_logical.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_logical.cpp index 33af9c3c..03ab1fa7 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_logical.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/integer_logical.cpp @@ -74,7 +74,8 @@ void EmitLopC(DecoderContext& context, InstLopC inst) { context, inst.base.pred, inst.base.pred_inv, inst.base.op, inst.base.pred_op, inst.base.dst, inst.base.dst_pred, inst.base.src_a, inst.base.inv_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4)), + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4))), inst.base.inv_b); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/move.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/move.cpp index d590dc3d..6947ab64 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/move.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/move.cpp @@ -38,9 +38,9 @@ void EmitMovR(DecoderContext& context, InstMovR inst) { } void EmitMovC(DecoderContext& context, InstMovC inst) { - EmitMove( - context, inst.base.pred, inst.base.pred_inv, inst.base.dst, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4))); + EmitMove(context, inst.base.pred, inst.base.pred_inv, inst.base.dst, + ir::Value::ConstMemory(CMem( + inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)))); } void EmitMovI(DecoderContext& context, InstMovI inst) { @@ -64,7 +64,8 @@ void EmitSelC(DecoderContext& context, InstSelC inst) { EmitSelect( context, inst.base.pred, inst.base.pred_inv, inst.base.dst, inst.base.src_pred, inst.base.src_pred_inv, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4))); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)))); } void EmitSelI(DecoderContext& context, InstSelI inst) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/multifunction.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/multifunction.cpp index 44d0893c..7f635487 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/multifunction.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/multifunction.cpp @@ -73,11 +73,11 @@ void EmitRroR(DecoderContext& context, InstRroR inst) { } void EmitRroC(DecoderContext& context, InstRroC inst) { - EmitRro( - context, inst.base.pred, inst.base.pred_inv, inst.base.dst, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4), - ir::ScalarType::F32), - inst.base.abs, inst.base.neg); + EmitRro(context, inst.base.pred, inst.base.pred_inv, inst.base.dst, + ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, + static_cast(inst.cbuf_offset * 4)), + ir::ScalarType::F32), + inst.base.abs, inst.base.neg); } void EmitRroI(DecoderContext& context, InstRroI inst) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/shift.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/shift.cpp index 1fbfcb21..b0c6da2b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/shift.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/shift.cpp @@ -39,7 +39,8 @@ void EmitShlC(DecoderContext& context, InstShlC inst) { EmitShiftLeft( context, inst.base.pred, inst.base.pred_inv, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4))); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)))); } void EmitShlI(DecoderContext& context, InstShlI inst) { @@ -58,7 +59,8 @@ void EmitShrC(DecoderContext& context, InstShrC inst) { EmitShiftRight( context, inst.base.pred, inst.base.pred_inv, inst.base.dst, inst.base.src_a, - ir::Value::ConstMemory(CMem(inst.cbuf_slot, RZ, inst.cbuf_offset * 4))); + ir::Value::ConstMemory( + CMem(inst.cbuf_slot, RZ, static_cast(inst.cbuf_offset * 4)))); } void EmitShrI(DecoderContext& context, InstShrI inst) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/texture.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/texture.cpp index f39e743f..6d6d1eee 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/texture.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decoder/texture.cpp @@ -16,7 +16,7 @@ void EmitTextureQuery(DecoderContext& context, pred_t pred, bool pred_inv, switch (query) { case TextureQuery::Dimensions: for (u32 i = 0, mask = write_mask; mask != 0x0; i++, mask >>= 1) { - if (mask & 1) { + if ((mask & 1) != 0u) { const auto res = context.builder.OpTextureQueryDimension(cbuf_index, i); context.builder.OpCopy( diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.cpp index 00b227b4..d4eb3cf9 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.cpp @@ -10,6 +10,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp { +#pragma pack(push, 1) struct ShaderHeader { // CommonWord0 u32 sph_type : 5; @@ -63,7 +64,7 @@ struct ShaderHeader { u16 omap_sysvals_c; u8 omap_fixed_fnc_tex[5]; u8 omap_extra; - } PACKED vtg; + } vtg; struct { u8 imap_generic_vector[32]; @@ -78,15 +79,15 @@ struct ShaderHeader { } ps; }; }; +#pragma pack(pop) -void Decompiler::Decompile(io::MemoryStream& code_stream, const ShaderType type, - const GuestShaderState& state, - ShaderBackend& out_backend, - std::vector& out_code, - ResourceMapping& out_resource_mapping) { +void Decompile(io::MemoryStream& code_stream, const ShaderType type, + const GuestShaderState& state, ShaderBackend& out_backend, + std::vector& out_code, + ResourceMapping& out_resource_mapping) { // Header // TODO: don't read in case of compute shaders - const ShaderHeader header = code_stream.Read(); + const auto header = code_stream.Read(); // HACK: just for testing ASSERT_DEBUG(header.version == 3, ShaderDecompiler, "Invalid shader version {}", header.version); @@ -106,29 +107,14 @@ void Decompiler::Decompile(io::MemoryStream& code_stream, const ShaderType type, } } -#define DUMP_SHADERS 0 -#if DUMP_SHADERS - { - auto tmp_stream = code_stream; - const auto code = tmp_stream.ReadSpanWhole(); - LOG_INFO(ShaderDecompiler, "Dumping shader 0x{}", - (void*)code_stream.GetPtr()); - std::ofstream out( - fmt::format("/Users/samuliak/Downloads/extracted/0x{}.bin", - (void*)code_stream.GetPtr()), - std::ios::binary); - - out.write(reinterpret_cast(code.data()), - static_cast(code.size())); - } -#endif - // Build IR ir::Module modul; { ir::Builder builder(modul); io::StreamView stream(&code_stream, code_stream.GetSeek()); - decoder::Decoder decoder({context, &stream, builder}); + decoder::Decoder decoder({.decomp_context = context, + .code_stream = &stream, + .builder = builder}); decoder.Decode(); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.hpp index c3b4ee9a..29f143f9 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/decompiler.hpp @@ -11,15 +11,9 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp { class ObserverBase; class BuilderBase; -class Decompiler final { - public: - Decompiler() = default; - ~Decompiler() = default; - - void Decompile(io::MemoryStream& code_stream, const ShaderType type, - const GuestShaderState& state, ShaderBackend& out_backend, - std::vector& out_code, - ResourceMapping& out_resource_mapping); -}; +void Decompile(io::MemoryStream& code_stream, const ShaderType type, + const GuestShaderState& state, ShaderBackend& out_backend, + std::vector& out_code, + ResourceMapping& out_resource_mapping); } // namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/block.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/block.hpp index 46a7d9da..4288d580 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/block.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/block.hpp @@ -15,7 +15,7 @@ class Block { } Value CreateLocal(Type type) { - return Value::Local(local_t{label, u32(instructions.size())}, type); + return Value::Local(local_t{.label=label, .id=static_cast(instructions.size())}, type); } private: diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/builder.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/builder.hpp index 26b951ae..fa223622 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/builder.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/builder.hpp @@ -339,6 +339,7 @@ class Builder { Value OpVectorConstruct(ScalarType element_type, const std::vector& elements) { std::vector operands; + operands.reserve(elements.size()); for (const auto& element : elements) operands.push_back(element); return AddInstruction( diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/module.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/module.hpp index 8d597f53..fcc883e4 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/module.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/module.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp::ir { class Module { public: // TODO: is validation needed? - void Validate() { LOG_FUNC_NOT_IMPLEMENTED(ShaderDecompiler); } + static void Validate() { LOG_FUNC_NOT_IMPLEMENTED(ShaderDecompiler); } Function& GetFunction(const std::string& name) { auto it = functions.find(name); diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.cpp index bb61ab87..3ad0cba2 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.cpp @@ -3,9 +3,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::shader_decomp::ir { ScalarType ScalarSignedEquivalent(ScalarType scalar) { - ASSERT_THROWING_DEBUG(ScalarIsUnsignedInteger(scalar), ShaderDecompiler, - TypeError::NotUnsigned, - "Type {} is not an unsigned integer", scalar); + ASSERT_DEBUG(ScalarIsUnsignedInteger(scalar), ShaderDecompiler, + "Type {} is not an unsigned integer", scalar); switch (scalar) { case ScalarType::U8: return ScalarType::I8; @@ -19,9 +18,8 @@ ScalarType ScalarSignedEquivalent(ScalarType scalar) { } ScalarType ScalarUnsignedEquivalent(ScalarType scalar) { - ASSERT_THROWING_DEBUG(ScalarIsSignedInteger(scalar), ShaderDecompiler, - TypeError::NotSigned, - "Type {} is not a signed integer", scalar); + ASSERT_DEBUG(ScalarIsSignedInteger(scalar), ShaderDecompiler, + "Type {} is not a signed integer", scalar); switch (scalar) { case ScalarType::I8: return ScalarType::U8; @@ -35,22 +33,21 @@ ScalarType ScalarUnsignedEquivalent(ScalarType scalar) { } ScalarType Type::GetScalarType() const { - ASSERT_THROWING_DEBUG(IsScalar(), ShaderDecompiler, TypeError::NotAScalar, - "Type {} is not a scalar", *this); + ASSERT_DEBUG(IsScalar(), ShaderDecompiler, "Type {} is not a scalar", + *this); return scalar; } VectorType Type::GetVectorType() const { - ASSERT_THROWING_DEBUG(IsVector(), ShaderDecompiler, TypeError::NotAVector, - "Type {} is not a vector", *this); + ASSERT_DEBUG(IsVector(), ShaderDecompiler, "Type {} is not a vector", + *this); return vector; } // Type creation Type Type::SignedEquivalent() const { - ASSERT_THROWING_DEBUG(IsInteger(), ShaderDecompiler, - TypeError::NotAnInteger, "Type {} is not an integer", - *this); + ASSERT_DEBUG(IsInteger(), ShaderDecompiler, "Type {} is not an integer", + *this); switch (kind) { case TypeKind::Scalar: return ScalarSignedEquivalent(scalar); @@ -62,9 +59,8 @@ Type Type::SignedEquivalent() const { } Type Type::UnsignedEquivalent() const { - ASSERT_THROWING_DEBUG(IsInteger(), ShaderDecompiler, - TypeError::NotAnInteger, "Type {} is not an integer", - *this); + ASSERT_DEBUG(IsInteger(), ShaderDecompiler, "Type {} is not an integer", + *this); switch (kind) { case TypeKind::Scalar: return ScalarUnsignedEquivalent(scalar); diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.hpp index c27c629b..456f402d 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/type.hpp @@ -23,16 +23,6 @@ enum class ScalarType { F32, }; -enum class TypeError { - NotAScalar, - NotAVector, - NotABoolean, - NotAnInteger, - NotAFloatingPoint, - NotSigned, - NotUnsigned, -}; - inline bool ScalarIsInteger(ScalarType scalar) { switch (scalar) { case ScalarType::U8: @@ -99,10 +89,10 @@ class VectorType { } bool IsFloatingPoint() const { return ScalarIsFloatingPoint(element_type); } VectorType SignedEquivalent() const { - return VectorType(ScalarSignedEquivalent(element_type), size); + return {ScalarSignedEquivalent(element_type), size}; } VectorType UnsignedEquivalent() const { - return VectorType(ScalarUnsignedEquivalent(element_type), size); + return {ScalarUnsignedEquivalent(element_type), size}; } private: @@ -120,10 +110,10 @@ class Type { Type(ScalarType scalar_) : kind{TypeKind::Scalar}, scalar{scalar_} {} Type(VectorType vector_) : kind{TypeKind::Vector}, vector{vector_} {} - static Type Undefined() { return Type(); } - static Type Scalar(ScalarType scalar) { return Type(scalar); } + static Type Undefined() { return {}; } + static Type Scalar(ScalarType scalar) { return {scalar}; } static Type Vector(ScalarType element_type, u8 size) { - return Type(VectorType(element_type, size)); + return {VectorType(element_type, size)}; } bool operator==(const Type& other) const { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/value.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/value.hpp index c877964e..2de65c04 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/value.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_decompiler/ir/value.hpp @@ -20,18 +20,19 @@ class Value { public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - static Value Undefined() { return Value{ValueKind::Undefined}; } + static Value Undefined() { return Value{.kind = ValueKind::Undefined}; } #pragma GCC diagnostic pop template static Value RawValue(const T raw_value) { - return Value{ValueKind::RawValue, + return Value{.kind = ValueKind::RawValue, .raw_value = static_cast(raw_value)}; } static Value Constant(const u32 constant, const ScalarType type) { - return Value{ValueKind::Constant, type, .constant = constant}; + return Value{ + .kind = ValueKind::Constant, .type = type, .constant = constant}; } static Value ConstantB(const bool constant) { - return Constant(constant, ScalarType::Bool); + return Constant(static_cast(constant), ScalarType::Bool); } static Value ConstantU(const u32 constant, const ScalarType type = ScalarType::U32) { @@ -67,24 +68,27 @@ class Value { static_assert(always_false::value, "Unsupported type"); } static Value Local(const local_t local, const Type type = ScalarType::U32) { - return Value{ValueKind::Local, type, .local = local}; + return Value{.kind = ValueKind::Local, .type = type, .local = local}; } static Value Register(const reg_t reg, const Type type = ScalarType::U32) { - return Value{ValueKind::Register, type, .reg = reg}; + return Value{.kind = ValueKind::Register, .type = type, .reg = reg}; } static Value Predicate(const pred_t pred) { - return Value{ValueKind::Predicate, ScalarType::Bool, .pred = pred}; + return Value{.kind = ValueKind::Predicate, + .type = ScalarType::Bool, + .pred = pred}; } static Value AttrMemory(const AMem& amem, const Type type = ScalarType::U32) { - return Value{ValueKind::AttrMemory, type, .amem = amem}; + return Value{.kind = ValueKind::AttrMemory, .type = type, .amem = amem}; } static Value ConstMemory(const CMem& cmem, const Type type = ScalarType::U32) { - return Value{ValueKind::ConstMemory, type, .cmem = cmem}; + return Value{ + .kind = ValueKind::ConstMemory, .type = type, .cmem = cmem}; } static Value Label(const label_t label) { - return Value{ValueKind::Label, .label = label}; + return Value{.kind = ValueKind::Label, .label = label}; } bool operator==(const Value& other) const { diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp index a119e882..8f6995f4 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp @@ -111,9 +111,9 @@ void TextureCache::MergeMemories(TextureMem& mem, TextureMem& other) { for (auto& [group_key, other_group] : other.cache) { auto group_opt = mem.cache.Find(group_key); auto& group = - (group_opt.has_value() ? **group_opt : mem.cache.Add(group_key)); + (group_opt.has_value() ? **group_opt : mem.cache.Insert(group_key)); for (auto& [storage_key, storage] : other_group.cache) { - group.cache.Add(storage_key, std::move(storage)); + group.cache.Insert(storage_key, std::move(storage)); } } } @@ -141,10 +141,7 @@ bool CalculateLevelAndLayer(const TextureDescriptor& base_descriptor, uptr ptr, } // Check if level is aligned - if (crnt_level_offset != level_offset) - return false; - - return true; + return crnt_level_offset == level_offset; } bool CalculateLevelAndLayer(const TextureDescriptor& base_descriptor, @@ -201,10 +198,7 @@ bool CalculateLevelAndSlice(const TextureDescriptor& base_descriptor, uptr ptr, out_slice = slice_offset / slice_size; // Check if slice is aligned - if (out_slice * slice_size != slice_offset) - return false; - - return true; + return out_slice * slice_size == slice_offset; } bool CalculateLevelAndSlice(const TextureDescriptor& base1_descriptor, @@ -239,8 +233,8 @@ TextureCache::AddToMemory(ICommandBuffer* command_buffer, TextureMem& mem, // Check if it is a new entry auto group_opt = mem.cache.Find(group_hash); if (!group_opt.has_value()) { - auto& group = mem.cache.Add(group_hash); - auto& storage = group.cache.Add(storage_hash); + auto& group = mem.cache.Insert(group_hash); + auto& storage = group.cache.Insert(storage_hash); return GetTexture(command_buffer, storage, mem, descriptor, view_descriptor, usage); } @@ -260,7 +254,8 @@ TextureCache::AddToMemory(ICommandBuffer* command_buffer, TextureMem& mem, const auto& other_descriptor = storage.base->GetDescriptor(); const auto other_range = other_descriptor.GetRange(); if (other_range.Contains(range)) { - u32 level, layer; + u32 level; + u32 layer; if (!CalculateLevelAndLayer(other_descriptor, descriptor, level, layer)) { LOG_DEBUG(Gpu, @@ -281,7 +276,7 @@ TextureCache::AddToMemory(ICommandBuffer* command_buffer, TextureMem& mem, auto new_descriptor = other_descriptor; new_descriptor.level_count = min_levels; auto& new_storage = - group.cache.Add(new_descriptor.GetStorageHash()); + group.cache.Insert(new_descriptor.GetStorageHash()); UpdateStorage(command_buffer, new_storage, mem, new_descriptor, usage); @@ -367,7 +362,7 @@ TextureCache::AddToMemory(ICommandBuffer* command_buffer, TextureMem& mem, new_descriptor.layer_count = layer_count; // Create a new storage - auto& storage = group.cache.Add(storage_hash); + auto& storage = group.cache.Insert(storage_hash); UpdateStorage(command_buffer, storage, mem, new_descriptor, usage); // Copy overlapping storages @@ -390,7 +385,7 @@ void TextureCache::UpdateStorage(ICommandBuffer* command_buffer, TextureStorage& storage, TextureMem& mem, const TextureDescriptor& descriptor, TextureUsage usage) { - if (!storage.base) { + if (storage.base == nullptr) { storage.base = renderer.CreateTexture(descriptor); DecodeTexture(command_buffer, storage); } @@ -405,7 +400,7 @@ TextureCache::GetTextureView(TextureStorage& storage, return **view_opt; auto view = storage.base->CreateView(view_descriptor); - storage.view_cache.Add(view_descriptor.GetHash(), view); + storage.view_cache.Insert(view_descriptor.GetHash(), view); return view; } @@ -500,7 +495,10 @@ void TextureCache::Synchronize2DWith2D(ICommandBuffer* command_buffer, const auto copy_range = descriptor.GetRange().ClampedTo(other_descriptor.GetRange()); - u32 level, layer, other_level, other_layer; + u32 level; + u32 layer; + u32 other_level; + u32 other_layer; if (!CalculateLevelAndLayer(descriptor, other_descriptor, copy_range.GetBegin(), level, layer, other_level, other_layer)) { @@ -526,7 +524,10 @@ void TextureCache::Synchronize3DWith3D(ICommandBuffer* command_buffer, const auto copy_range = descriptor.GetRange().ClampedTo(other_descriptor.GetRange()); - u32 level, slice, other_level, other_slice; + u32 level; + u32 slice; + u32 other_level; + u32 other_slice; if (!CalculateLevelAndSlice(descriptor, other_descriptor, copy_range.GetBegin(), level, slice, other_level, other_slice)) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp index b43c8c1d..ac693f05 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp @@ -13,13 +13,13 @@ class ITexture; class ITextureView; class IRenderer; -typedef std::chrono::steady_clock TextureCacheClock; -typedef TextureCacheClock::time_point TextureCacheTimePoint; +using TextureCacheClock = std::chrono::steady_clock; +using TextureCacheTimePoint = TextureCacheClock::time_point; struct TextureStorage { ITexture* base{nullptr}; SmallCache view_cache; - TextureCacheTimePoint update_timestamp{}; + TextureCacheTimePoint update_timestamp; void MarkUpdated() { update_timestamp = TextureCacheClock::now(); } }; @@ -39,9 +39,9 @@ struct TextureGroup { }; struct TextureMemInfo { - TextureCacheTimePoint modified_timestamp{}; - TextureCacheTimePoint read_timestamp{}; - TextureCacheTimePoint written_timestamp{}; + TextureCacheTimePoint modified_timestamp; + TextureCacheTimePoint read_timestamp; + TextureCacheTimePoint written_timestamp; void MarkModified() { modified_timestamp = TextureCacheClock::now(); } void MarkRead() { read_timestamp = TextureCacheClock::now(); } @@ -95,7 +95,7 @@ class TextureCache { std::mutex mutex; std::map entries; - void MergeMemories(TextureMem& mem, TextureMem& other); + static void MergeMemories(TextureMem& mem, TextureMem& other); ITextureView* AddToMemory(ICommandBuffer* command_buffer, TextureMem& mem, const TextureDescriptor& descriptor, const TextureViewDescriptor& view_descriptor, @@ -103,7 +103,7 @@ class TextureCache { void UpdateStorage(ICommandBuffer* command_buffer, TextureStorage& storage, TextureMem& mem, const TextureDescriptor& descriptor, TextureUsage usage); - ITextureView* GetTextureView(TextureStorage& storage, + static ITextureView* GetTextureView(TextureStorage& storage, const TextureViewDescriptor& view_descriptor); ITextureView* GetTextureView(ICommandBuffer* command_buffer, TextureStorage& storage, TextureMem& mem, @@ -118,15 +118,15 @@ class TextureCache { TextureMem& mem, TextureUsage usage); // Data synchronization - void Synchronize2DWith2D(ICommandBuffer* command_buffer, + static void Synchronize2DWith2D(ICommandBuffer* command_buffer, TextureStorage& storage, TextureStorage& other_storage); - void Synchronize3DWith3D(ICommandBuffer* command_buffer, + static void Synchronize3DWith3D(ICommandBuffer* command_buffer, TextureStorage& storage, TextureStorage& other_storage); // Helpers - u32 GetDataHash(const ITexture* texture); + static u32 GetDataHash(const ITexture* texture); void DecodeTexture(ICommandBuffer* command_buffer, TextureStorage& storage); // TODO: encode texture diff --git a/src/core/input/apple_gc/device_list.mm b/src/core/input/apple_gc/device_list.mm index 45b84f2e..5c800ea0 100644 --- a/src/core/input/apple_gc/device_list.mm +++ b/src/core/input/apple_gc/device_list.mm @@ -16,7 +16,7 @@ @interface DeviceListImpl : NSObject @implementation DeviceListImpl - (id)initWithParent:(DeviceList*)parent { - if (self = [super init]) { + if ((self = [super init]) != nullptr) { self.parent = parent; // Notifications @@ -44,7 +44,7 @@ - (id)initWithParent:(DeviceList*)parent { // Connected keyboards if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) { GCKeyboard* keyboard = [GCKeyboard coalescedKeyboard]; - if (keyboard) { + if (keyboard != nullptr) { self.parent->AddKeyboard(keyboard); } } @@ -64,24 +64,22 @@ - (void)dealloc { } - (void)controllerConnected:(NSNotification*)notification { - GCController* controller = - reinterpret_cast(notification.object); + auto controller = reinterpret_cast(notification.object); _parent->AddController(controller); } - (void)controllerDisconnected:(NSNotification*)notification { - GCController* controller = - reinterpret_cast(notification.object); + auto controller = reinterpret_cast(notification.object); _parent->RemoveController(controller); } - (void)keyboardConnected:(NSNotification*)notification { - GCKeyboard* keyboard = reinterpret_cast(notification.object); + auto keyboard = reinterpret_cast(notification.object); _parent->AddKeyboard(keyboard); } - (void)keyboardDisconnected:(NSNotification*)notification { - GCKeyboard* keyboard = reinterpret_cast(notification.object); + auto keyboard = reinterpret_cast(notification.object); _parent->RemoveKeyboard(keyboard); } @@ -97,9 +95,7 @@ - (void)keyboardDisconnected:(NSNotification*)notification { } // namespace -DeviceList::DeviceList() { - impl = [[DeviceListImpl alloc] initWithParent:this]; -} +DeviceList::DeviceList() : impl([[DeviceListImpl alloc] initWithParent:this]) {} DeviceList::~DeviceList() { [impl release]; } diff --git a/src/core/input/device.hpp b/src/core/input/device.hpp index f7a79fab..7ed5f7bb 100644 --- a/src/core/input/device.hpp +++ b/src/core/input/device.hpp @@ -6,7 +6,7 @@ namespace hydra::input { class IDevice { public: - virtual ~IDevice() {} + virtual ~IDevice() = default; virtual bool ActsAsController() const { return false; }; virtual bool ActsAsTouchScreen() const { return false; }; diff --git a/src/core/input/device_list.hpp b/src/core/input/device_list.hpp index e62db7f1..7b3671db 100644 --- a/src/core/input/device_list.hpp +++ b/src/core/input/device_list.hpp @@ -6,10 +6,11 @@ namespace hydra::input { class IDeviceList { public: - virtual ~IDeviceList() { - for (auto [name, device] : devices) - delete device; - } + IDeviceList() noexcept = default; + virtual ~IDeviceList() noexcept = default; + + MAKE_NON_COPYABLE(IDeviceList); + MAKE_NON_MOVABLE(IDeviceList); virtual void PumpEvents() {} @@ -24,7 +25,6 @@ class IDeviceList { std::scoped_lock lock(mutex); const auto it = devices.find(name); ASSERT(it != devices.end(), Input, "{} not connected", name); - delete it->second; devices.erase(it); LOG_INFO(Input, "Device disconnected: {}", name); } @@ -34,12 +34,12 @@ class IDeviceList { if (it == devices.end()) return nullptr; - return it->second; + return it->second.get(); } private: std::mutex mutex; - std::map> devices; + std::map, std::less<>> devices; public: REF_GETTER(mutex, GetMutex); diff --git a/src/core/input/device_manager.cpp b/src/core/input/device_manager.cpp index 4ba578f1..5f578c99 100644 --- a/src/core/input/device_manager.cpp +++ b/src/core/input/device_manager.cpp @@ -57,7 +57,7 @@ DeviceManager::PollNpad(horizon::services::hid::internal::NpadIndex index) { std::scoped_lock lock(device_list->GetMutex()); auto device = device_list->GetDevice(device_name); - if (!device) + if (device == nullptr) continue; // Buttons @@ -116,7 +116,7 @@ std::map DeviceManager::PollTouch() { const std::string device_name = "cursor"; auto device = device_list->GetDevice(device_name); - if (!device) + if (device == nullptr) return state; // Process touches @@ -139,7 +139,8 @@ std::map DeviceManager::PollTouch() { for (const auto [touch_id, finger_id] : active_touches) { ASSERT_DEBUG(finger_id != invalid(), Input, "Invalid finger ID"); - i32 x, y; + i32 x; + i32 y; device->GetTouchPosition(touch_id, x, y); // TODO: also clamp to guest screen size x = std::max(x, 0); @@ -156,7 +157,7 @@ std::map DeviceManager::PollTouch() { u32 DeviceManager::BeginTouch() { for (u32 i = 0; i < MAX_FINGER_COUNT; i++) { - if (available_finger_mask & (1 << i)) { + if ((available_finger_mask & (1 << i)) != 0) { available_finger_mask &= ~(1 << i); touch_count++; return i; diff --git a/src/core/input/profile.cpp b/src/core/input/profile.cpp index c886740c..20a473df 100644 --- a/src/core/input/profile.cpp +++ b/src/core/input/profile.cpp @@ -58,7 +58,7 @@ std::string ValueToString(DeviceType device_type, u32 value) { } std::optional ToCode(const std::string_view str) { - const auto slash_pos = str.find("/"); + const auto slash_pos = str.find('/'); if (slash_pos == std::string::npos) { LOG_ERROR(Input, "Invalid input code format: {}", str); return std::nullopt; @@ -86,21 +86,21 @@ std::optional ToCode(const std::string_view str) { AnalogStickAxis ToAnalogStickAxis(const std::string_view str) { // TODO: clean this up? if (str == "l_right") { - return {true, AnalogStickDirection::Right}; + return {.is_left = true, .direction = AnalogStickDirection::Right}; } else if (str == "l_left") { - return {true, AnalogStickDirection::Left}; + return {.is_left = true, .direction = AnalogStickDirection::Left}; } else if (str == "l_up") { - return {true, AnalogStickDirection::Up}; + return {.is_left = true, .direction = AnalogStickDirection::Up}; } else if (str == "l_down") { - return {true, AnalogStickDirection::Down}; + return {.is_left = true, .direction = AnalogStickDirection::Down}; } else if (str == "r_right") { - return {false, AnalogStickDirection::Right}; + return {.is_left = false, .direction = AnalogStickDirection::Right}; } else if (str == "r_left") { - return {false, AnalogStickDirection::Left}; + return {.is_left = false, .direction = AnalogStickDirection::Left}; } else if (str == "r_up") { - return {false, AnalogStickDirection::Up}; + return {.is_left = false, .direction = AnalogStickDirection::Up}; } else if (str == "r_down") { - return {false, AnalogStickDirection::Down}; + return {.is_left = false, .direction = AnalogStickDirection::Down}; } else { LOG_ERROR(Input, "Invalid analog stick axis \"{}\"", str); return {}; @@ -189,102 +189,111 @@ void Profile::LoadDefaults() { // Devices #ifdef PLATFORM_MACOS device_names = {"Generic Keyboard"}; -#elif defined(PLATFORM_IOS) +#elifdef PLATFORM_IOS device_names = {"Apple Touch Controller"}; #endif // Buttons button_mappings = { // Controller - {Code(DeviceType::Controller, ControllerInput::Plus), - horizon::services::hid::NpadButtons::Plus}, - {Code(DeviceType::Controller, ControllerInput::Minus), - horizon::services::hid::NpadButtons::Minus}, - {Code(DeviceType::Controller, ControllerInput::Left), - horizon::services::hid::NpadButtons::Left}, - {Code(DeviceType::Controller, ControllerInput::Right), - horizon::services::hid::NpadButtons::Right}, - {Code(DeviceType::Controller, ControllerInput::Up), - horizon::services::hid::NpadButtons::Up}, - {Code(DeviceType::Controller, ControllerInput::Down), - horizon::services::hid::NpadButtons::Down}, - {Code(DeviceType::Controller, ControllerInput::A), - horizon::services::hid::NpadButtons::A}, - {Code(DeviceType::Controller, ControllerInput::B), - horizon::services::hid::NpadButtons::B}, - {Code(DeviceType::Controller, ControllerInput::X), - horizon::services::hid::NpadButtons::X}, - {Code(DeviceType::Controller, ControllerInput::Y), - horizon::services::hid::NpadButtons::Y}, - {Code(DeviceType::Controller, ControllerInput::L), - horizon::services::hid::NpadButtons::L}, - {Code(DeviceType::Controller, ControllerInput::R), - horizon::services::hid::NpadButtons::R}, - {Code(DeviceType::Controller, ControllerInput::ZL), - horizon::services::hid::NpadButtons::ZL}, - {Code(DeviceType::Controller, ControllerInput::ZR), - horizon::services::hid::NpadButtons::ZR}, + {.code = Code(DeviceType::Controller, ControllerInput::Plus), + .npad_buttons = horizon::services::hid::NpadButtons::Plus}, + {.code = Code(DeviceType::Controller, ControllerInput::Minus), + .npad_buttons = horizon::services::hid::NpadButtons::Minus}, + {.code = Code(DeviceType::Controller, ControllerInput::Left), + .npad_buttons = horizon::services::hid::NpadButtons::Left}, + {.code = Code(DeviceType::Controller, ControllerInput::Right), + .npad_buttons = horizon::services::hid::NpadButtons::Right}, + {.code = Code(DeviceType::Controller, ControllerInput::Up), + .npad_buttons = horizon::services::hid::NpadButtons::Up}, + {.code = Code(DeviceType::Controller, ControllerInput::Down), + .npad_buttons = horizon::services::hid::NpadButtons::Down}, + {.code = Code(DeviceType::Controller, ControllerInput::A), + .npad_buttons = horizon::services::hid::NpadButtons::A}, + {.code = Code(DeviceType::Controller, ControllerInput::B), + .npad_buttons = horizon::services::hid::NpadButtons::B}, + {.code = Code(DeviceType::Controller, ControllerInput::X), + .npad_buttons = horizon::services::hid::NpadButtons::X}, + {.code = Code(DeviceType::Controller, ControllerInput::Y), + .npad_buttons = horizon::services::hid::NpadButtons::Y}, + {.code = Code(DeviceType::Controller, ControllerInput::L), + .npad_buttons = horizon::services::hid::NpadButtons::L}, + {.code = Code(DeviceType::Controller, ControllerInput::R), + .npad_buttons = horizon::services::hid::NpadButtons::R}, + {.code = Code(DeviceType::Controller, ControllerInput::ZL), + .npad_buttons = horizon::services::hid::NpadButtons::ZL}, + {.code = Code(DeviceType::Controller, ControllerInput::ZR), + .npad_buttons = horizon::services::hid::NpadButtons::ZR}, // Keyboard - {Code(DeviceType::Keyboard, Key::Enter), - horizon::services::hid::NpadButtons::Plus}, - {Code(DeviceType::Keyboard, Key::Tab), - horizon::services::hid::NpadButtons::Minus}, - {Code(DeviceType::Keyboard, Key::ArrowLeft), - horizon::services::hid::NpadButtons::Left}, - {Code(DeviceType::Keyboard, Key::ArrowRight), - horizon::services::hid::NpadButtons::Right}, - {Code(DeviceType::Keyboard, Key::ArrowUp), - horizon::services::hid::NpadButtons::Up}, - {Code(DeviceType::Keyboard, Key::ArrowDown), - horizon::services::hid::NpadButtons::Down}, - {Code(DeviceType::Keyboard, Key::L), - horizon::services::hid::NpadButtons::A}, - {Code(DeviceType::Keyboard, Key::K), - horizon::services::hid::NpadButtons::B}, - {Code(DeviceType::Keyboard, Key::I), - horizon::services::hid::NpadButtons::X}, - {Code(DeviceType::Keyboard, Key::J), - horizon::services::hid::NpadButtons::Y}, - {Code(DeviceType::Keyboard, Key::U), - horizon::services::hid::NpadButtons::L}, - {Code(DeviceType::Keyboard, Key::O), - horizon::services::hid::NpadButtons::R}, - {Code(DeviceType::Keyboard, Key::Y), - horizon::services::hid::NpadButtons::ZL}, - {Code(DeviceType::Keyboard, Key::P), - horizon::services::hid::NpadButtons::ZR}, + {.code = Code(DeviceType::Keyboard, Key::Enter), + .npad_buttons = horizon::services::hid::NpadButtons::Plus}, + {.code = Code(DeviceType::Keyboard, Key::Tab), + .npad_buttons = horizon::services::hid::NpadButtons::Minus}, + {.code = Code(DeviceType::Keyboard, Key::ArrowLeft), + .npad_buttons = horizon::services::hid::NpadButtons::Left}, + {.code = Code(DeviceType::Keyboard, Key::ArrowRight), + .npad_buttons = horizon::services::hid::NpadButtons::Right}, + {.code = Code(DeviceType::Keyboard, Key::ArrowUp), + .npad_buttons = horizon::services::hid::NpadButtons::Up}, + {.code = Code(DeviceType::Keyboard, Key::ArrowDown), + .npad_buttons = horizon::services::hid::NpadButtons::Down}, + {.code = Code(DeviceType::Keyboard, Key::L), + .npad_buttons = horizon::services::hid::NpadButtons::A}, + {.code = Code(DeviceType::Keyboard, Key::K), + .npad_buttons = horizon::services::hid::NpadButtons::B}, + {.code = Code(DeviceType::Keyboard, Key::I), + .npad_buttons = horizon::services::hid::NpadButtons::X}, + {.code = Code(DeviceType::Keyboard, Key::J), + .npad_buttons = horizon::services::hid::NpadButtons::Y}, + {.code = Code(DeviceType::Keyboard, Key::U), + .npad_buttons = horizon::services::hid::NpadButtons::L}, + {.code = Code(DeviceType::Keyboard, Key::O), + .npad_buttons = horizon::services::hid::NpadButtons::R}, + {.code = Code(DeviceType::Keyboard, Key::Y), + .npad_buttons = horizon::services::hid::NpadButtons::ZL}, + {.code = Code(DeviceType::Keyboard, Key::P), + .npad_buttons = horizon::services::hid::NpadButtons::ZR}, }; // Analog sticks analog_mappings = { // Controller - {Code(DeviceType::Controller, ControllerInput::StickLRight), - {true, AnalogStickDirection::Right}}, - {Code(DeviceType::Controller, ControllerInput::StickLLeft), - {true, AnalogStickDirection::Left}}, - {Code(DeviceType::Controller, ControllerInput::StickLUp), - {true, AnalogStickDirection::Up}}, - {Code(DeviceType::Controller, ControllerInput::StickLDown), - {true, AnalogStickDirection::Down}}, - {Code(DeviceType::Controller, ControllerInput::StickRRight), - {false, AnalogStickDirection::Right}}, - {Code(DeviceType::Controller, ControllerInput::StickRLeft), - {false, AnalogStickDirection::Left}}, - {Code(DeviceType::Controller, ControllerInput::StickRUp), - {false, AnalogStickDirection::Up}}, - {Code(DeviceType::Controller, ControllerInput::StickRDown), - {false, AnalogStickDirection::Down}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickLRight), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Right}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickLLeft), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Left}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickLUp), + .axis = {.is_left = true, .direction = AnalogStickDirection::Up}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickLDown), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Down}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickRRight), + .axis = {.is_left = false, + .direction = AnalogStickDirection::Right}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickRLeft), + .axis = {.is_left = false, + .direction = AnalogStickDirection::Left}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickRUp), + .axis = {.is_left = false, .direction = AnalogStickDirection::Up}}, + {.code = Code(DeviceType::Controller, ControllerInput::StickRDown), + .axis = {.is_left = false, + .direction = AnalogStickDirection::Down}}, // Keyboard - {Code(DeviceType::Keyboard, Key::D), - {true, AnalogStickDirection::Right}}, - {Code(DeviceType::Keyboard, Key::A), - {true, AnalogStickDirection::Left}}, - {Code(DeviceType::Keyboard, Key::W), - {true, AnalogStickDirection::Up}}, - {Code(DeviceType::Keyboard, Key::S), - {true, AnalogStickDirection::Down}}, + {.code = Code(DeviceType::Keyboard, Key::D), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Right}}, + {.code = Code(DeviceType::Keyboard, Key::A), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Left}}, + {.code = Code(DeviceType::Keyboard, Key::W), + .axis = {.is_left = true, .direction = AnalogStickDirection::Up}}, + {.code = Code(DeviceType::Keyboard, Key::S), + .axis = {.is_left = true, + .direction = AnalogStickDirection::Down}}, }; break; @@ -327,7 +336,7 @@ void Profile::Serialize() { auto& button = buttons[npad_buttons_str]; if (!has_entry) button = toml::array{}; - button.as_array().push_back(mapping.code); + button.as_array().emplace_back(mapping.code); } } @@ -340,7 +349,7 @@ void Profile::Serialize() { auto& axis = analog[axis_str]; if (!has_entry) axis = toml::array{}; - axis.as_array().push_back(mapping.code); + axis.as_array().emplace_back(mapping.code); } } @@ -381,7 +390,8 @@ void Profile::Deserialize() { if (!code) continue; - button_mappings.push_back({code.value(), button.value()}); + button_mappings.push_back( + {.code = code.value(), .npad_buttons = button.value()}); } } } @@ -396,7 +406,7 @@ void Profile::Deserialize() { if (!code) continue; - analog_mappings.push_back({code.value(), axis}); + analog_mappings.push_back({.code = code.value(), .axis = axis}); } } } diff --git a/src/core/input/sdl/controller.cpp b/src/core/input/sdl/controller.cpp index 9460249c..0312763f 100644 --- a/src/core/input/sdl/controller.cpp +++ b/src/core/input/sdl/controller.cpp @@ -22,9 +22,9 @@ bool Controller::IsPressedImpl(ControllerInput input) { BUTTON_CASE(L, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER) BUTTON_CASE(R, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER) case ControllerInput::ZL: - return SDL_GetGamepadAxis(handle, SDL_GAMEPAD_AXIS_LEFT_TRIGGER); + return SDL_GetGamepadAxis(handle, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) != 0; case ControllerInput::ZR: - return SDL_GetGamepadAxis(handle, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER); + return SDL_GetGamepadAxis(handle, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) != 0; BUTTON_CASE(Plus, SDL_GAMEPAD_BUTTON_START); BUTTON_CASE(Minus, SDL_GAMEPAD_BUTTON_BACK); BUTTON_CASE(Left, SDL_GAMEPAD_BUTTON_DPAD_LEFT); diff --git a/src/core/input/sdl/controller.hpp b/src/core/input/sdl/controller.hpp index 801385c5..4ed84b76 100644 --- a/src/core/input/sdl/controller.hpp +++ b/src/core/input/sdl/controller.hpp @@ -9,7 +9,7 @@ namespace hydra::input::sdl { class Controller : public IController { public: Controller(SDL_Gamepad* handle_) : handle{handle_} {} - ~Controller() { SDL_CloseGamepad(handle); } + ~Controller() override { SDL_CloseGamepad(handle); } protected: bool IsPressedImpl(ControllerInput input) override; diff --git a/src/core/input/sdl/device_list.cpp b/src/core/input/sdl/device_list.cpp index 51e728b9..457053dd 100644 --- a/src/core/input/sdl/device_list.cpp +++ b/src/core/input/sdl/device_list.cpp @@ -27,7 +27,7 @@ DeviceList::DeviceList() { // Get initial keyboards int kb_count = 0; SDL_KeyboardID* keyboards = SDL_GetKeyboards(&kb_count); - if (keyboards) { + if (keyboards != nullptr) { keyboard_count = static_cast(kb_count); if (keyboard_count > 0) ConnectGenericKeyboard(); @@ -40,7 +40,7 @@ DeviceList::DeviceList() { // Get initial gamepads int gp_count = 0; SDL_JoystickID* gamepads = SDL_GetGamepads(&gp_count); - if (gamepads) { + if (gamepads != nullptr) { for (int i = 0; i < gp_count; i++) ConnectController(gamepads[i]); @@ -96,7 +96,7 @@ void DeviceList::ConnectGenericKeyboard() { void DeviceList::ConnectController(SDL_JoystickID id) { SDL_Gamepad* gp = SDL_OpenGamepad(id); - if (gp) { + if (gp != nullptr) { std::string name = SDL_GetGamepadName(gp); AddDevice(name, new Controller(gp)); } else { diff --git a/src/core/input/sdl/keyboard.hpp b/src/core/input/sdl/keyboard.hpp index 4d5bcd48..c6829d39 100644 --- a/src/core/input/sdl/keyboard.hpp +++ b/src/core/input/sdl/keyboard.hpp @@ -6,7 +6,7 @@ namespace hydra::input::sdl { class Keyboard : public IKeyboard { public: - Keyboard() {} + Keyboard() = default; protected: bool IsPressedImpl(Key key) override; diff --git a/src/common/stb.cpp b/src/core/stb.cpp similarity index 100% rename from src/common/stb.cpp rename to src/core/stb.cpp diff --git a/src/core/system.cpp b/src/core/system.cpp index 57515744..55b42726 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -101,26 +101,23 @@ System::~System() { LOGGER_INSTANCE.SetOutput(LogOutput::StdOut); } -void System::LoadAndStart(horizon::loader::LoaderBase* loader) { +void System::LoadAndStart(horizon::loader::ILoader* loader) { // Process - ASSERT_THROWING(main_process == nullptr, Other, - LoadAndStartError::ProcessAlreadyExists, - "Process already exists"); + ASSERT(main_process == nullptr, Other, "Process already exists"); main_process = os.GetKernel().GetProcessManager().CreateProcess("Guest process"); loader->LoadProcess(*this, main_process); // Check for firmware applets - auto controller = - new horizon::services::am::internal::LibraryAppletController( - horizon::LibraryAppletMode::AllForeground); + horizon::services::am::internal::LibraryAppletController controller( + horizon::LibraryAppletMode::AllForeground); // TODO: correct? u64 system_tick; os.GetKernel().GetSystemTick(system_tick); switch (loader->GetTitleID()) { case 0x0100000000001003: { // controller // Common args - auto common_args = new horizon::applets::CommonArguments{ + horizon::applets::CommonArguments common_args{ .version = 1, .size = sizeof(horizon::applets::CommonArguments), .library_applet_api_version = 1, // TODO: correct? @@ -128,8 +125,7 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .play_startup_sound = false, // HACK .system_tick = system_tick, }; - controller->PushInData( - new horizon::services::am::IStorage(common_args)); + controller.PushInData(new horizon::services::am::IStorage(common_args)); // Arg horizon::applets::controller::SupportArg<4> arg{ @@ -144,7 +140,7 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { }; // Private arg - auto private_arg = new horizon::applets::controller::ArgPrivate{ + horizon::applets::controller::ArgPrivate private_arg{ .size = sizeof(horizon::applets::controller::ArgPrivate), .controller_support_arg_size = sizeof(arg), .flag0 = 0, @@ -155,18 +151,15 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .npad_joy_hold_type = horizon::services::hid::NpadJoyHoldType::Vertical, }; - controller->PushInData( - new horizon::services::am::IStorage(private_arg)); + controller.PushInData(new horizon::services::am::IStorage(private_arg)); - auto arg_ptr = reinterpret_cast(malloc(sizeof(arg))); - memcpy(arg_ptr, &arg, sizeof(arg)); - controller->PushInData(new horizon::services::am::IStorage(arg_ptr)); + controller.PushInData(new horizon::services::am::IStorage(arg)); break; } case 0x0100000000001005: { // error // Common args - auto common_args = new horizon::applets::CommonArguments{ + horizon::applets::CommonArguments common_args{ .version = 1, .size = sizeof(horizon::applets::CommonArguments), .library_applet_api_version = 1, // TODO: correct? @@ -174,20 +167,19 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .play_startup_sound = false, // HACK .system_tick = system_tick, }; - controller->PushInData( - new horizon::services::am::IStorage(common_args)); + controller.PushInData(new horizon::services::am::IStorage(common_args)); // Param common - auto param_common = new horizon::applets::error::ParamCommon{ + horizon::applets::error::ParamCommon param_common{ .type = horizon::applets::error::ErrorType::ApplicationError, .is_jump_enabled = false, }; - controller->PushInData( + controller.PushInData( new horizon::services::am::IStorage(param_common)); // Param for application error - auto param_for_application_error = - new horizon::applets::error::ParamForApplicationError{ + horizon::applets::error::ParamForApplicationError + param_for_application_error{ .version = 1, .error_code_number = MAKE_RESULT(Svc, 0), .language_code = horizon::ToLanguageCode( @@ -195,14 +187,14 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .dialog_message = "Dialog message", .fullscreen_message = "Fullscreen message", }; - controller->PushInData( + controller.PushInData( new horizon::services::am::IStorage(param_for_application_error)); break; } case 0x0100000000001008: { // swkbd // Common args - auto common_args = new horizon::applets::CommonArguments{ + horizon::applets::CommonArguments common_args{ .version = 1, .size = sizeof(horizon::applets::CommonArguments), .library_applet_api_version = 1, // TODO: correct? @@ -210,32 +202,30 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .play_startup_sound = false, // HACK .system_tick = system_tick, }; - controller->PushInData( - new horizon::services::am::IStorage(common_args)); + controller.PushInData(new horizon::services::am::IStorage(common_args)); // Config - auto config = - new horizon::applets::software_keyboard::KeyboardConfigCommon{ - .mode = horizon::applets::software_keyboard::KeyboardMode::Full, - // TODO: more - }; - controller->PushInData(new horizon::services::am::IStorage(config)); + horizon::applets::software_keyboard::KeyboardConfigCommon config{ + .mode = horizon::applets::software_keyboard::KeyboardMode::Full, + // TODO: more + }; + controller.PushInData(new horizon::services::am::IStorage(config)); break; } case 0x0100000000001009: { // miiEdit // Args - auto args = new horizon::applets::mii_edit::AppletInput{ + horizon::applets::mii_edit::AppletInput args{ ._unknown_x0 = 0x3, .mode = horizon::applets::mii_edit::AppletMode::ShowMiiEdit, }; - controller->PushInData(new horizon::services::am::IStorage(args)); + controller.PushInData(new horizon::services::am::IStorage(args)); break; } case 0x010000000000100d: { // photoViewer // Common args - auto common_args = new horizon::applets::CommonArguments{ + horizon::applets::CommonArguments common_args{ .version = 1, .size = sizeof(horizon::applets::CommonArguments), .library_applet_api_version = 1, // TODO: correct? @@ -243,13 +233,12 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { .play_startup_sound = false, // HACK .system_tick = system_tick, }; - controller->PushInData( - new horizon::services::am::IStorage(common_args)); + controller.PushInData(new horizon::services::am::IStorage(common_args)); // Arg auto arg = new horizon::applets::album::Arg{ horizon::applets::album::Arg::ShowAllAlbumFilesForHomeMenu}; - controller->PushInData(new horizon::services::am::IStorage(arg)); + controller.PushInData(new horizon::services::am::IStorage(arg)); break; } @@ -257,88 +246,95 @@ void System::LoadAndStart(horizon::loader::LoaderBase* loader) { break; } - os.SetLibraryAppletSelfController(controller); + os.SetLibraryAppletSelfController(std::move(controller)); // Loading screen assets - hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer = nullptr; - - { - u32 width, height; - if (auto data = loader->LoadNintendoLogo(width, height)) { - // Create texture - const u32 stride = width * 4; - const u32 size = height * stride; - const hw::tegra_x1::gpu::renderer::TextureDescriptor descriptor( - 0x0, hw::tegra_x1::gpu::renderer::TextureType::_2D, - hw::tegra_x1::gpu::renderer::TextureFormat::RGBA8Unorm, true, - stride, width, height, 1, 1, 1, 0x0, 0x0, 0x0); - const auto texture = gpu.GetRenderer().CreateTexture(descriptor); - - const auto view_descriptor = - hw::tegra_x1::gpu::renderer::TextureViewDescriptor( - descriptor.type, descriptor.format, Range(0, 1), - Range(0, 1)); - const auto texture_view = texture->CreateView(view_descriptor); - nintendo_logo = {texture, texture_view}; - - // Command buffer - command_buffer = gpu.GetRenderer().CreateCommandBuffer(); - - // Copy data - auto tmp_buffer = gpu.GetRenderer().AllocateTemporaryBuffer(size); - std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), data, - size); - free(data); - texture->CopyFrom(command_buffer, tmp_buffer); - gpu.GetRenderer().FreeTemporaryBuffer(tmp_buffer); - } - } { - u32 width, height; - u32 frame_count; - if (auto data = loader->LoadStartupMovie(startup_movie_delays, width, - height, frame_count)) { - const u32 stride = width * 4; - const u32 size = height * stride; - hw::tegra_x1::gpu::renderer::TextureDescriptor descriptor( - 0x0, hw::tegra_x1::gpu::renderer::TextureType::_2D, - hw::tegra_x1::gpu::renderer::TextureFormat::RGBA8Unorm, true, - stride, width, height, 1, 1, 1, 0x0, 0x0, 0x0); - const auto view_descriptor = - hw::tegra_x1::gpu::renderer::TextureViewDescriptor( - descriptor.type, descriptor.format, Range(0, 1), - Range(0, 1)); - startup_movie.reserve(frame_count); - - // Command buffer - if (!command_buffer) - command_buffer = gpu.GetRenderer().CreateCommandBuffer(); - - for (u32 i = 0; i < frame_count; i++) { + std::unique_ptr + command_buffer = nullptr; + + { + u32 width; + u32 height; + if (auto data = loader->LoadNintendoLogo(width, height)) { // Create texture + const u32 stride = width * 4; + const u32 size = height * stride; + const hw::tegra_x1::gpu::renderer::TextureDescriptor descriptor( + 0x0, hw::tegra_x1::gpu::renderer::TextureType::_2D, + hw::tegra_x1::gpu::renderer::TextureFormat::RGBA8Unorm, + true, stride, width, height, 1, 1, 1, 0x0, 0x0, 0x0); const auto texture = gpu.GetRenderer().CreateTexture(descriptor); + + const auto view_descriptor = + hw::tegra_x1::gpu::renderer::TextureViewDescriptor( + descriptor.type, descriptor.format, Range(0, 1), + Range(0, 1)); const auto texture_view = texture->CreateView(view_descriptor); + nintendo_logo = {.base = texture, .view = texture_view}; + + // Command buffer + command_buffer.reset(gpu.GetRenderer().CreateCommandBuffer()); // Copy data auto tmp_buffer = gpu.GetRenderer().AllocateTemporaryBuffer(size); - std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), - data + i * height * width, size); - texture->CopyFrom(command_buffer, tmp_buffer); + std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), data, + size); + free(data); + texture->CopyFrom(command_buffer.get(), tmp_buffer); gpu.GetRenderer().FreeTemporaryBuffer(tmp_buffer); - startup_movie.push_back({texture, texture_view}); } - free(data); + } + { + u32 width; + u32 height; + u32 frame_count; + if (auto data = loader->LoadStartupMovie( + startup_movie_delays, width, height, frame_count)) { + const u32 stride = width * 4; + const u32 size = height * stride; + hw::tegra_x1::gpu::renderer::TextureDescriptor descriptor( + 0x0, hw::tegra_x1::gpu::renderer::TextureType::_2D, + hw::tegra_x1::gpu::renderer::TextureFormat::RGBA8Unorm, + true, stride, width, height, 1, 1, 1, 0x0, 0x0, 0x0); + const auto view_descriptor = + hw::tegra_x1::gpu::renderer::TextureViewDescriptor( + descriptor.type, descriptor.format, Range(0, 1), + Range(0, 1)); + startup_movie.reserve(frame_count); + + // Command buffer + if (command_buffer == nullptr) + command_buffer.reset( + gpu.GetRenderer().CreateCommandBuffer()); + + for (u32 i = 0; i < frame_count; i++) { + // Create texture + const auto texture = + gpu.GetRenderer().CreateTexture(descriptor); + const auto texture_view = + texture->CreateView(view_descriptor); + + // Copy data + auto tmp_buffer = + gpu.GetRenderer().AllocateTemporaryBuffer(size); + std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), + data + i * height * width, size); + texture->CopyFrom(command_buffer.get(), tmp_buffer); + gpu.GetRenderer().FreeTemporaryBuffer(tmp_buffer); + startup_movie.push_back( + {.base = texture, .view = texture_view}); + } + free(data); - // Extend the last frame's time - startup_movie_delays.back() = 5s; + // Extend the last frame's time + startup_movie_delays.back() = 5s; + } } } - if (command_buffer) - delete command_buffer; - LOG_INFO(Other, "-------- Title info --------"); LOG_INFO(Other, "Title ID: {:016x}", loader->GetTitleID()); @@ -471,14 +467,14 @@ void System::ProgressFrame(u32 width, u32 height, // Acquire surface auto compositor = gpu.GetRenderer().AcquireNextSurface(); - if (!compositor) + if (compositor == nullptr) return; // Delta time { auto layer = os.GetDisplayDriver().GetFirstLayerForProcess(main_process); - if (layer) + if (layer != nullptr) accumulated_dt += layer->GetAccumulatedDT(); } @@ -560,7 +556,7 @@ void System::ProgressFrame(u32 width, u32 height, const auto now = clock_t::now(); const auto time_since_last_dt_averaging = now - last_dt_averaging_time; if (time_since_last_dt_averaging > 1s) { - if (bool(accumulated_dt)) + if (static_cast(accumulated_dt)) last_dt_average = static_cast(accumulated_dt); else last_dt_average = 0.f; @@ -583,7 +579,7 @@ void System::ProgressFrame(u32 width, u32 height, } bool System::IsRunning() const { - if (!main_process) + if (main_process == nullptr) return false; switch (main_process->GetState()) { @@ -597,14 +593,12 @@ bool System::IsRunning() const { void System::TakeScreenshot() { auto layer = os.GetDisplayDriver().GetFirstLayerForProcess(main_process); - if (!layer) + if (layer == nullptr) return; - auto texture = layer->GetPresentTexture(); - if (!texture) - return; + ASSIGN_OR_RETURN(auto texture, layer->GetPresentTexture()); - std::thread thread([=, this]() { + std::thread thread([layer, texture, this]() { // Get the image data auto rect = layer->GetSrcRect(); @@ -653,7 +647,7 @@ void System::CaptureGpuFrame() { void System::TryApplyPatch(horizon::kernel::Process* process, const std::string_view target_filename, - const std::filesystem::path path) { + const std::filesystem::path& path) { if (to_lower(path.filename().string()) != target_filename) return; diff --git a/src/core/system.hpp b/src/core/system.hpp index cdbbedc2..4936518b 100644 --- a/src/core/system.hpp +++ b/src/core/system.hpp @@ -6,7 +6,7 @@ #include "core/input/device_manager.hpp" namespace hydra::horizon::loader { -class LoaderBase; +class ILoader; } namespace hydra { @@ -27,11 +27,7 @@ class System { void SetSurface(void* surface) { gpu.GetRenderer().SetSurface(surface); } - enum class LoadAndStartError { - ProcessAlreadyExists, - }; - - void LoadAndStart(horizon::loader::LoaderBase* loader); + void LoadAndStart(horizon::loader::ILoader* loader); void RequestStop(); void ForceStop(); @@ -60,7 +56,7 @@ class System { horizon::OS os; // Loading screen assets - std::optional nintendo_logo{}; + std::optional nintendo_logo; std::vector startup_movie; // TODO: texture array? std::vector startup_movie_delays; clock_t::time_point next_startup_movie_frame_time; @@ -78,17 +74,17 @@ class System { clock_t::time_point last_dt_averaging_time{clock_t::now()}; // Helpers - void TryApplyPatch(horizon::kernel::Process* process, - const std::string_view target_filename, - const std::filesystem::path path); + static void TryApplyPatch(horizon::kernel::Process* process, + const std::string_view target_filename, + const std::filesystem::path& path); public: GETTER(ui_handler, GetUIHandler); REF_GETTER(wall_clock, GetWallClock); - hw::tegra_x1::cpu::ICpu& GetCpu() { return *cpu.get(); } + hw::tegra_x1::cpu::ICpu& GetCpu() { return *cpu; } REF_GETTER(gpu, GetGpu); REF_GETTER(input_device_manager, GetInputDeviceManager); - audio::ICore& GetAudioCore() { return *audio_core.get(); } + audio::ICore& GetAudioCore() { return *audio_core; } REF_GETTER(os, GetOS); }; diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 32cb09b6..32d084bc 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -20,7 +20,7 @@ if (FRONTEND STREQUAL "SDL3") sdl3/window.hpp ) - target_link_libraries(hydra PRIVATE hydra_warnings SDL3::SDL3 "-framework Cocoa") + target_link_libraries(hydra PRIVATE hydra_compile_options SDL3::SDL3 "-framework Cocoa") elseif (FRONTEND STREQUAL "SwiftUI") message(STATUS "Using SwiftUI frontend") diff --git a/src/frontend/sdl3/window.cpp b/src/frontend/sdl3/window.cpp index 4cb002c3..d941a675 100644 --- a/src/frontend/sdl3/window.cpp +++ b/src/frontend/sdl3/window.cpp @@ -1,6 +1,6 @@ #include "frontend/sdl3/window.hpp" -#include "core/horizon/loader/loader_base.hpp" +#include "core/horizon/loader/loader.hpp" #include "core/input/device_manager.hpp" namespace hydra::frontend::sdl3 { @@ -125,15 +125,19 @@ Window::ShowSoftwareKeyboard(const std::string& header_text, } void Window::BeginEmulation(const std::string& path) { + // Create loader + // TODO: support loading applets from firmware + // TODO: display error when loading fails + ASSIGN_OR_RETURN(auto loader, + horizon::loader::ILoader::CreateFromPath(path)); + // Connect cursor as a touch screen device system.GetInputDeviceManager().ConnectTouchScreenDevice("cursor", &cursor); + // Start system.SetSurface(SDL_GetRenderMetalLayer(renderer)); - // TODO: support loading applets from firmware - auto loader = horizon::loader::LoaderBase::CreateFromPath(path); system.LoadAndStart(loader); title_id = loader->GetTitleID(); - delete loader; } void Window::UpdateWindowTitle() {