From 5124b540279bc08d14da049a6d4180265f4a799a Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sat, 10 Jun 2023 01:42:35 -0700 Subject: [PATCH] Add `FourCC`/`_u32` helper function/literals Portable code for turning string-based four-character-codes like `"BLAH"_u32` into a 32-bit integer at compile-time. --- include/helpers.hpp | 22 ++++++++++++++++++++++ src/core/loader/ncch.cpp | 2 +- src/core/loader/ncsd.cpp | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/helpers.hpp b/include/helpers.hpp index ee1a1dac..25c2ef2d 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -141,6 +141,28 @@ constexpr size_t operator""_GB(unsigned long long int x) { return 1024_MB * x; } +// Utility user-literal/metaprogramming-type for turning four-character-codes +// into 32-bit integers at compile-time +// Ex: "BLAH"_u32, "HEAD"_u32, "END "_u32 +template +struct FourCC { + u32 value; + + constexpr FourCC(const char (&identifier)[N]) : value(0) { + static_assert(N == 5, "FourCC must be 4 characters"); + if constexpr (std::endian::native == std::endian::big) { + value = ((identifier[3] << 0) | (identifier[2] << 8) | (identifier[1] << 16) | (identifier[0] << 24)); + } else { + value = ((identifier[3] << 24) | (identifier[2] << 16) | (identifier[1] << 8) | (identifier[0] << 0)); + } + } +}; + +template +constexpr std::uint32_t operator""_u32() { + return code.value; +} + // useful macros // likely/unlikely #ifdef __GNUC__ diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index c3dd8d2e..6eb4506c 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -5,7 +5,7 @@ #include "memory.hpp" bool NCCH::loadFromHeader(u8* header, IOFile& file) { - if (header[0x100] != 'N' || header[0x101] != 'C' || header[0x102] != 'C' || header[0x103] != 'H') { + if (*(u32*)&header[0x100] != "NCCH"_u32) { printf("Invalid header on NCCH\n"); return false; } diff --git a/src/core/loader/ncsd.cpp b/src/core/loader/ncsd.cpp index bf93f490..cc311eba 100644 --- a/src/core/loader/ncsd.cpp +++ b/src/core/loader/ncsd.cpp @@ -17,7 +17,7 @@ std::optional Memory::loadNCSD(const std::filesystem::path& path) { return std::nullopt; } - if (magic[0] != 'N' || magic[1] != 'C' || magic[2] != 'S' || magic[3] != 'D') { + if (*(u32*)&magic[0] != "NCSD"_u32) { printf("NCSD with wrong magic value\n"); return std::nullopt; }