summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2026-07-29 17:49:48 +1200
committerGitHub <noreply@github.com>2026-07-29 17:49:48 +1200
commitc863abc0d3b5d9f25a9b83bbdebd48bd29197617 (patch)
tree9e0ca4e5460e47a9cf46406bb818415194fbdb85
parent9b726fd56ba7fde6f81854ed048c5e3c75d0393c (diff)
parent55c015e6ac74b0ecce7f30b4aed499f02fa9c5bd (diff)
Merge pull request #14770 from JoshuaVandaele/gen-approved-hash
AchievementApprovedHash: Automatically generate hash using CMake
-rw-r--r--CMake/GenerateAchievementHash.cmake5
-rw-r--r--Source/Core/Common/Crypto/SHA1.cpp4
-rw-r--r--Source/Core/Common/Crypto/SHA1.h27
-rw-r--r--Source/Core/Core/AchievementApprovedHash.h13
-rw-r--r--Source/Core/Core/AchievementApprovedHash.h.in10
-rw-r--r--Source/Core/Core/CMakeLists.txt15
-rw-r--r--Source/UnitTests/Core/PatchAllowlistTest.cpp4
7 files changed, 56 insertions, 22 deletions
diff --git a/CMake/GenerateAchievementHash.cmake b/CMake/GenerateAchievementHash.cmake
new file mode 100644
index 0000000000..5f62e43f72
--- /dev/null
+++ b/CMake/GenerateAchievementHash.cmake
@@ -0,0 +1,5 @@
+# This file exists to be consumed via `add_custom_command`
+# so that file changes are picked up without needing a full reconfigure
+
+file(SHA1 ${JSON_FILE} ACHIEVEMENT_APPROVED_LIST_HASH)
+configure_file(${TEMPLATE_FILE} ${OUTPUT_FILE} @ONLY)
diff --git a/Source/Core/Common/Crypto/SHA1.cpp b/Source/Core/Common/Crypto/SHA1.cpp
index 44d5f9c3dd..bca90ec079 100644
--- a/Source/Core/Common/Crypto/SHA1.cpp
+++ b/Source/Core/Common/Crypto/SHA1.cpp
@@ -394,8 +394,4 @@ std::string DigestToString(const Digest& digest)
return fmt::format("{:02X}", fmt::join(digest, ""));
}
-std::string DigestToSource(const Digest& digest)
-{
- return fmt::format("{{0x{:02X}}}", fmt::join(digest, ", 0x"));
-}
} // namespace Common::SHA1
diff --git a/Source/Core/Common/Crypto/SHA1.h b/Source/Core/Common/Crypto/SHA1.h
index feb92f31fd..cbd287edd5 100644
--- a/Source/Core/Common/Crypto/SHA1.h
+++ b/Source/Core/Common/Crypto/SHA1.h
@@ -58,5 +58,30 @@ inline Digest CalculateDigest(const std::array<T, Size>& msg)
}
std::string DigestToString(const Digest& digest);
-std::string DigestToSource(const Digest& digest);
+
+constexpr Digest StringToDigest(std::string_view str)
+{
+ Digest digest{};
+ ASSERT(str.size() == digest.size() * 2);
+
+ for (size_t i = 0; i < str.size(); ++i)
+ {
+ const char c = str[i];
+ u8 quartet;
+ if (c >= '0' && c <= '9')
+ quartet = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ quartet = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ quartet = c - 'a' + 10;
+ else
+ ASSERT(false);
+
+ if (i % 2 == 0)
+ digest[i / 2] = quartet << 4;
+ else
+ digest[i / 2] |= quartet;
+ }
+ return digest;
+}
} // namespace Common::SHA1
diff --git a/Source/Core/Core/AchievementApprovedHash.h b/Source/Core/Core/AchievementApprovedHash.h
deleted file mode 100644
index d7962ebd3c..0000000000
--- a/Source/Core/Core/AchievementApprovedHash.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2026 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "Common/Crypto/SHA1.h"
-
-static constexpr std::string_view ACHIEVEMENT_APPROVED_LIST_FILENAME = "ApprovedInis.json";
-// After building tests, find the new hash with:
-// ./Binaries/Tests/tests --gtest_filter=PatchAllowlist.VerifyHashes
-static const inline Common::SHA1::Digest ACHIEVEMENT_APPROVED_LIST_HASH = {
- 0xE6, 0xCD, 0xD7, 0x85, 0x7A, 0xBA, 0x72, 0xEC, 0x34, 0x11,
- 0x2B, 0x16, 0xB1, 0x31, 0xD0, 0x0A, 0x0A, 0xD7, 0xFC, 0xCC};
diff --git a/Source/Core/Core/AchievementApprovedHash.h.in b/Source/Core/Core/AchievementApprovedHash.h.in
new file mode 100644
index 0000000000..ed1feaeea3
--- /dev/null
+++ b/Source/Core/Core/AchievementApprovedHash.h.in
@@ -0,0 +1,10 @@
+// Copyright 2026 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "Common/Crypto/SHA1.h"
+
+static constexpr std::string_view ACHIEVEMENT_APPROVED_LIST_FILENAME = "ApprovedInis.json";
+static constinit inline Common::SHA1::Digest ACHIEVEMENT_APPROVED_LIST_HASH =
+ Common::SHA1::StringToDigest("@ACHIEVEMENT_APPROVED_LIST_HASH@");
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 996b63e22b..56c8dba3de 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -1,5 +1,4 @@
add_library(core
- AchievementApprovedHash.h
AchievementManager.cpp
AchievementManager.h
ActionReplay.cpp
@@ -591,6 +590,20 @@ add_library(core
WiiUtils.h
)
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/AchievementApprovedHash.h
+ COMMAND ${CMAKE_COMMAND}
+ -DJSON_FILE=${CMAKE_SOURCE_DIR}/Data/Sys/ApprovedInis.json
+ -DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/AchievementApprovedHash.h.in
+ -DOUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/AchievementApprovedHash.h
+ -P ${CMAKE_SOURCE_DIR}/CMake/GenerateAchievementHash.cmake
+ DEPENDS ${CMAKE_SOURCE_DIR}/Data/Sys/ApprovedInis.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/AchievementApprovedHash.h.in
+ COMMENT "Generating AchievementApprovedHash.h"
+)
+
+target_sources(core PRIVATE AchievementApprovedHash.h)
+
if(_M_X86_64)
target_sources(core PRIVATE
DSP/Jit/x64/DSPEmitter.cpp
diff --git a/Source/UnitTests/Core/PatchAllowlistTest.cpp b/Source/UnitTests/Core/PatchAllowlistTest.cpp
index b7ac220f61..c689908277 100644
--- a/Source/UnitTests/Core/PatchAllowlistTest.cpp
+++ b/Source/UnitTests/Core/PatchAllowlistTest.cpp
@@ -131,9 +131,7 @@ TEST(PatchAllowlist, VerifyHashes)
if (digest != ACHIEVEMENT_APPROVED_LIST_HASH)
{
ADD_FAILURE() << "Approved list hash does not match the one in AchievementApprovedHash.h."
- << std::endl
- << "Please update ACHIEVEMENT_APPROVED_LIST_HASH to the following:" << std::endl
- << Common::SHA1::DigestToSource(digest);
+ << std::endl;
}
// Compare with old allowlist
std::string old_allowlist;