From fa32ad0780c284be6bd7ab762272cd9c44955c46 Mon Sep 17 00:00:00 2001 From: Filip Michalski Date: Fri, 30 Oct 2026 14:03:17 +0100 Subject: [PATCH 1/2] refactor(tools): use standard base64 for NID encoding --- tools/nid_names.py | 13 ++----------- tools/stubgen.py | 4 ++-- tools/tests/test_nid_names.py | 8 ++++++++ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/tools/nid_names.py b/tools/nid_names.py index 658b223f8f..37b4e5b4dd 100644 --- a/tools/nid_names.py +++ b/tools/nid_names.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import argparse +import base64 import hashlib import json import os @@ -15,7 +16,6 @@ DB_URL = ("https://raw.githubusercontent.com/zecoxao/sce_symbols" "/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv") DEFAULT_CACHE = Path(tempfile.gettempdir()) / "anyps5-nid-db" / "aerolib.csv" -CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" SUFFIX = bytes([0x51, 0x8D, 0x64, 0xA6, 0x35, 0xDE, 0xD8, 0xC1, 0xE6, 0xB0, 0x39, 0xB1, 0xC3, 0xE5, 0x52, 0x30]) CPP_TOKEN = re.compile( @@ -31,16 +31,7 @@ ASM_FUNCTION_MACROS = {"APS5_ASM_FUNCTION", "APS5_SIGNAL_ASM_FUNCTION"} def compute_nid(symbol): digest = hashlib.sha1(symbol.encode() + SUFFIX).digest() - rev = bytes(digest[7 - i] for i in range(8)) - out = [] - for i in range(0, 6, 3): - triple = (rev[i] << 16) | (rev[i + 1] << 8) | rev[i + 2] - out += [CHARSET[(triple >> 18) & 63], CHARSET[(triple >> 12) & 63], - CHARSET[(triple >> 6) & 63], CHARSET[triple & 63]] - tail = (rev[6] << 16) | (rev[7] << 8) - out += [CHARSET[(tail >> 18) & 63], CHARSET[(tail >> 12) & 63], - CHARSET[(tail >> 6) & 63]] - return "".join(out) + return base64.b64encode(digest[:8][::-1], altchars=b"+-").decode("ascii").rstrip("=") def strip_nid_postfix(name): diff --git a/tools/stubgen.py b/tools/stubgen.py index 8558fa9c13..34756c7a14 100644 --- a/tools/stubgen.py +++ b/tools/stubgen.py @@ -8,9 +8,9 @@ import tempfile from pathlib import Path try: - from tools.nid_names import CHARSET, SUFFIX, compute_nid + from tools.nid_names import SUFFIX, compute_nid except ImportError: - from nid_names import CHARSET, SUFFIX, compute_nid + from nid_names import SUFFIX, compute_nid def strip_nid_token(raw): diff --git a/tools/tests/test_nid_names.py b/tools/tests/test_nid_names.py index 4823be7801..a70495cfc6 100644 --- a/tools/tests/test_nid_names.py +++ b/tools/tests/test_nid_names.py @@ -16,6 +16,14 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import nid_names +class NidEncodingTests(unittest.TestCase): + def test_fixed_nid_vectors(self): + for name, expected in (("ACProcessMain", "mFq1M6vw-JM"), ("sceAmprUnknown00", "6OkOa1SOKuY"), + ("", "B4c6vzgC+Xc"), ("東京", "2GKwIE7lnRc")): + with self.subTest(name=name): + self.assertEqual(nid_names.compute_nid(name), expected) + + class DatabaseCacheTests(unittest.TestCase): @contextlib.contextmanager def database_server(self, payload): From 4b6df98d071a654175d45e81e7f9ba0bcea995bc Mon Sep 17 00:00:00 2001 From: Filip Michalski Date: Fri, 30 Oct 2026 14:04:42 +0100 Subject: [PATCH 2/2] refactor(tools): keep NID encoding edits independent --- tools/nid_names.py | 4 ++-- tools/tests/test_nid_names.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/nid_names.py b/tools/nid_names.py index 37b4e5b4dd..a6d7feff12 100644 --- a/tools/nid_names.py +++ b/tools/nid_names.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 import argparse -import base64 import hashlib import json import os @@ -8,6 +7,7 @@ import re import sys import tempfile import urllib.request +from base64 import b64encode from pathlib import Path ROOT = Path(__file__).resolve().parent.parent @@ -31,7 +31,7 @@ ASM_FUNCTION_MACROS = {"APS5_ASM_FUNCTION", "APS5_SIGNAL_ASM_FUNCTION"} def compute_nid(symbol): digest = hashlib.sha1(symbol.encode() + SUFFIX).digest() - return base64.b64encode(digest[:8][::-1], altchars=b"+-").decode("ascii").rstrip("=") + return b64encode(digest[:8][::-1], altchars=b"+-").decode("ascii").rstrip("=") def strip_nid_postfix(name): diff --git a/tools/tests/test_nid_names.py b/tools/tests/test_nid_names.py index a70495cfc6..b908f99aa5 100644 --- a/tools/tests/test_nid_names.py +++ b/tools/tests/test_nid_names.py @@ -16,14 +16,6 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import nid_names -class NidEncodingTests(unittest.TestCase): - def test_fixed_nid_vectors(self): - for name, expected in (("ACProcessMain", "mFq1M6vw-JM"), ("sceAmprUnknown00", "6OkOa1SOKuY"), - ("", "B4c6vzgC+Xc"), ("東京", "2GKwIE7lnRc")): - with self.subTest(name=name): - self.assertEqual(nid_names.compute_nid(name), expected) - - class DatabaseCacheTests(unittest.TestCase): @contextlib.contextmanager def database_server(self, payload): @@ -683,5 +675,13 @@ class SourceLocationTests(unittest.TestCase): nid_names.main(arguments) +class NidEncodingTests(unittest.TestCase): + def test_fixed_nid_vectors(self): + for name, expected in (("ACProcessMain", "mFq1M6vw-JM"), ("sceAmprUnknown00", "6OkOa1SOKuY"), + ("", "B4c6vzgC+Xc"), ("東京", "2GKwIE7lnRc")): + with self.subTest(name=name): + self.assertEqual(nid_names.compute_nid(name), expected) + + if __name__ == "__main__": unittest.main()