Skip to content

Commit eadd82d

Browse files
authored
Merge pull request #221 from RedShyGuy/release/3.0.0
Release/3.0.0
2 parents 9d50766 + 5c5db70 commit eadd82d

File tree

90 files changed

+8451
-4293
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+8451
-4293
lines changed

.github/workflows/c-cpp.yml

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches: ["master"]
66
pull_request:
77
branches: ["master"]
8+
workflow_dispatch:
89

910
jobs:
1011
build:
@@ -14,30 +15,27 @@ jobs:
1415
steps:
1516
- uses: actions/checkout@v4
1617

17-
- name: Download libctrpf
18-
run: |
19-
wget -O libctrpf.tar.bz2 "https://gitlab.com/-/project/35748837/uploads/8d2a3dc282f32b6a75d5f6abaeafe88f/libctrpf-0.8.0.tar.bz2"
20-
tar -xjf libctrpf.tar.bz2
21-
22-
- name: Install libctrpf
23-
run: |
24-
mkdir -p /opt/devkitpro/libctrpf/include
25-
mkdir -p /opt/devkitpro/libctrpf/lib
26-
cp -r include/* /opt/devkitpro/libctrpf/include/
27-
cp -r lib/* /opt/devkitpro/libctrpf/lib/
28-
2918
- name: Download 3gxtool
3019
run: |
3120
wget -O 3gxtool "https://gitlab.com/-/project/35893975/uploads/7cf27fcdc26921d9a6c5505c1e5bbcaa/3gxtool"
3221
chmod +x 3gxtool
3322
cp 3gxtool /opt/devkitpro/tools/bin/3gxtool
3423
35-
- name: Build Plugin
36-
run: make
24+
- name: Clone libctrpf (develop)
25+
run: |
26+
git clone --depth=1 --branch develop https://gitlab.com/thepixellizeross/ctrpluginframework.git libctrpf
27+
28+
- name: Build & Install libctrpf
29+
run: |
30+
cd libctrpf
31+
make
3732
3833
- name: Run Language Python Script
3934
run: python3 LanguageBinCreator/json_to_bin.py
4035

36+
- name: Build Plugin
37+
run: make
38+
4139
- name: Package Plugin
4240
run: |
4341
mkdir -p package/Vapecord/Data/
@@ -51,12 +49,18 @@ jobs:
5149
cp -r Files/snd/* package/luma/plugins/$folder/snd/
5250
done
5351
54-
- name: Upload Artifacts
52+
- name: Upload Package Artifact
5553
uses: actions/upload-artifact@v4
5654
with:
5755
name: Vapecord.Public
5856
path: package/
5957

58+
- name: Upload ELF Artifact
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: Vapecord.Public.elf
62+
path: Vapecord_Public.elf
63+
6064
- name: Check For Unused Text
6165
run: python3 CheckForUnusedText.py
6266

@@ -66,5 +70,9 @@ jobs:
6670
- name: Check If Text Is Translated
6771
run: python3 CheckIfTextIsTranslated.py
6872

73+
- name: Check For Unused Addresses
74+
run: python3 CheckForUnusedAddresses.py
75+
76+
6977

7078

.vscode/c_cpp_properties.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"databaseFilename": ""
2828
},
2929
"cStandard": "c11",
30-
"cppStandard": "gnu++20",
30+
"cppStandard": "c++11",
3131
"intelliSenseMode": "gcc-arm"
3232
}
3333
],

CheckForUnusedAddresses.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import os
2+
import re
3+
import sys
4+
from pathlib import Path
5+
6+
SCRIPT_DIR = Path(__file__).parent
7+
ADDRESSES_HEADER = SCRIPT_DIR / "Includes/Address/Addresses.hpp"
8+
9+
address_usage_pattern = re.compile(
10+
r"\bAddress(?:\s+\w+)?\s*\(\s*(0x[0-9A-Fa-f]+)\s*\)"
11+
)
12+
13+
array_pattern = re.compile(
14+
r"\{\s*(0x[0-9A-Fa-f]+)\s*,"
15+
)
16+
17+
18+
# --- comment stripping ---
19+
20+
def strip_block_comments(text: str) -> str:
21+
return re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL)
22+
23+
24+
def strip_all_comments(text: str) -> str:
25+
text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL)
26+
text = re.sub(r"//.*", "", text)
27+
return text
28+
29+
30+
# --- header scan ---
31+
32+
def collect_addresses_from_header():
33+
addresses = set()
34+
35+
if not ADDRESSES_HEADER.exists():
36+
print(f"ERROR: {ADDRESSES_HEADER} not found!")
37+
return addresses
38+
39+
with open(ADDRESSES_HEADER, "r", encoding="utf-8", errors="ignore") as f:
40+
content = strip_block_comments(f.read())
41+
42+
for match in array_pattern.finditer(content):
43+
addresses.add(match.group(1).lower())
44+
45+
return addresses
46+
47+
48+
# --- code scan ---
49+
50+
def collect_used_addresses():
51+
used = set()
52+
53+
for root, _, files in os.walk("."):
54+
for file in files:
55+
if not file.endswith((".cpp", ".hpp", ".h")):
56+
continue
57+
58+
path = Path(root) / file
59+
60+
if path.resolve() == ADDRESSES_HEADER.resolve():
61+
continue
62+
63+
with open(path, "r", encoding="utf-8", errors="ignore") as f:
64+
content = strip_all_comments(f.read())
65+
66+
for match in address_usage_pattern.finditer(content):
67+
used.add(match.group(1).lower())
68+
69+
return used
70+
71+
72+
# --- main ---
73+
74+
def main():
75+
print("Scanning for unused addresses...")
76+
77+
header_addresses = collect_addresses_from_header()
78+
used_addresses = collect_used_addresses()
79+
80+
unused = sorted(header_addresses - used_addresses)
81+
82+
print(f"Total in header: {len(header_addresses)}")
83+
print(f"Used in code: {len(used_addresses)}")
84+
print(f"Unused: {len(unused)}")
85+
86+
if unused:
87+
print("\nUnused addresses:")
88+
for addr in unused:
89+
print(f" {addr}")
90+
exit_code = 1
91+
else:
92+
print("\nNo unused addresses found!")
93+
exit_code = 0
94+
95+
sys.exit(exit_code)
96+
97+
98+
if __name__ == "__main__":
99+
main()
100+

CheckForUnusedText.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
11
import json
22
from pathlib import Path
33
import re
4+
import sys
45

56
# Config
67
PROJECT_ROOT = Path(__file__).parent
78
LANG_JSON_DIR = PROJECT_ROOT / "LanguageBinCreator" / "languages"
89

9-
# Regex: match anything inside get("...") or get('...')
10-
LANG_PATTERN = re.compile(r'Language::getInstance\(\)->get\(\s*["\'](.+?)["\']\s*\)')
10+
# Regex: match anything like TextID::KEY
11+
TEXTID_PATTERN = re.compile(r'TextID::([A-Z0-9_]+)')
1112

12-
# MenuFolderExtras
13-
MENUFOLDER_PATTERN = re.compile(r'MenuFolderExtras\(\s*["\'](.+?)["\']')
14-
15-
# MenuEntryExtras
16-
MENUENTRY_PATTERN = re.compile(r'MenuEntryExtras\((.*?)\)')
17-
18-
# HotkeyExtras
19-
HOTKEY_PATTERN = re.compile(r'HotkeyExtras\([^,]+,\s*["\'](.+?)["\']\s*\)')
20-
21-
# Scan code files for keys
13+
# Scan code files for enum keys
2214
keys_used = set()
2315

2416
for file_path in PROJECT_ROOT.rglob("*"):
@@ -29,16 +21,11 @@
2921
print(f"[WARNING] Could not read {file_path}: {e}")
3022
continue
3123

32-
matches = MENUFOLDER_PATTERN.findall(content) + \
33-
HOTKEY_PATTERN.findall(content) + \
34-
LANG_PATTERN.findall(content)
35-
24+
matches = TEXTID_PATTERN.findall(content)
3625
keys_used.update(matches)
3726

38-
params = MENUENTRY_PATTERN.findall(content)
39-
for param_str in params:
40-
string_keys = re.findall(r'["\'](.+?)["\']', param_str)
41-
keys_used.update(string_keys)
27+
# Ignore TextID::NONE
28+
keys_used.discard("NONE")
4229

4330
# Load all JSON entries
4431
json_files = list(LANG_JSON_DIR.glob("*.json"))
@@ -63,12 +50,15 @@
6350
# Print results
6451
if not unused_keys_report:
6552
print("All language keys in JSON files are used in the code!")
53+
exit_code = 0
6654
else:
6755
print(f"Unused language keys found ({sum(len(v) for v in unused_keys_report.values())}):")
6856
for json_name, keys in sorted(unused_keys_report.items()):
6957
print(f"\n{json_name} ({len(keys)} unused keys):")
7058
for key in sorted(keys):
7159
print(f" - {key}")
60+
exit_code = 1
7261

73-
print(f"\nTotal keys used in code: {len(keys_used)}")
62+
print(f"\nTotal TextID keys used in code: {len(keys_used)}")
7463
print(f"JSON files scanned: {len(json_files)}")
64+
sys.exit(exit_code)

CheckIfAddressesArePorted.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import re
3+
import sys
34
from pathlib import Path
45

56
# CONFIG
@@ -67,8 +68,12 @@ def main():
6768
print(f"\n{file}:")
6869
for line, val in entries:
6970
print(f" Line {line}: {val}")
71+
exit_code = 1
7072
else:
7173
print("\nAll Address-Entries are ported!")
74+
exit_code = 0
75+
76+
sys.exit(exit_code)
7277

7378
if __name__ == "__main__":
7479
main()

CheckIfTextIsTranslated.py

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
import json
22
from pathlib import Path
33
import re
4+
import sys
45

56
# Config
67
PROJECT_ROOT = Path(__file__).parent
78
LANG_JSON_DIR = PROJECT_ROOT / "LanguageBinCreator" / "languages"
9+
TEXTID_ENUM_FILE = PROJECT_ROOT.parent / "Includes" / "TextID.hpp"
810

9-
# Regex: match anything inside get("...") or get('...')
10-
LANG_PATTERN = re.compile(r'Language::getInstance\(\)->get\(\s*["\'](.+?)["\']\s*\)')
11+
# Regex: match anything like TextID::SOME_KEY
12+
TEXTID_PATTERN = re.compile(r'TextID::([A-Z0-9_]+)')
1113

12-
# MenuFolderExtras: first parameter
13-
MENUFOLDER_PATTERN = re.compile(r'MenuFolderExtras\(\s*["\'](.+?)["\']')
14-
15-
# MenuEntryExtras: last string parameter
16-
17-
MENUENTRY_PATTERN = re.compile(r'MenuEntryExtras\((.*?)\)')
18-
19-
# HotkeyExtras: second parameter
20-
HOTKEY_PATTERN = re.compile(r'HotkeyExtras\([^,]+,\s*["\'](.+?)["\']\s*\)')
21-
22-
# Scan code files for keys
14+
# Scan code files for enum keys
2315
keys_used = set()
2416

2517
for file_path in PROJECT_ROOT.rglob("*"):
@@ -28,20 +20,16 @@
2820
content = file_path.read_text(encoding="utf-8")
2921
except Exception as e:
3022
print(f"[WARNING] Could not read {file_path}: {e}")
23+
exit_code = 1
3124
continue
3225

33-
matches = MENUFOLDER_PATTERN.findall(content) + \
34-
HOTKEY_PATTERN.findall(content) + \
35-
LANG_PATTERN.findall(content)
36-
26+
matches = TEXTID_PATTERN.findall(content)
3727
keys_used.update(matches)
3828

39-
params = MENUENTRY_PATTERN.findall(content)
40-
for param_str in params:
41-
string_keys = re.findall(r'["\'](.+?)["\']', param_str)
42-
keys_used.update(string_keys)
29+
# Ignore NONE
30+
keys_used.discard("NONE")
4331

44-
# Load all JSON entries
32+
# Load all JSON entries (master_keys)
4533
json_files = list(LANG_JSON_DIR.glob("*.json"))
4634
json_entries_per_file = {}
4735

@@ -52,6 +40,7 @@
5240
json_entries_per_file[json_file.name] = entries
5341
except Exception as e:
5442
print(f"[WARNING] Could not parse {json_file}: {e}")
43+
exit_code = 1
5544

5645
# Check each key in every JSON
5746
missing_keys_report = {}
@@ -66,11 +55,14 @@
6655

6756
# Print results
6857
if not missing_keys_report:
69-
print("All language keys exist in every JSON file!")
58+
print("All TextID keys exist in every JSON file!")
59+
exit_code = 0
7060
else:
71-
print(f"Some language keys are missing in JSON files ({len(missing_keys_report)}):")
61+
print(f"Some TextID keys are missing in JSON files ({len(missing_keys_report)}):")
7262
for key, missing_files in sorted(missing_keys_report.items()):
7363
print(f" - {key} missing in: {', '.join(missing_files)}")
64+
exit_code = 1
7465

75-
print(f"\nTotal keys found in code: {len(keys_used)}")
66+
print(f"\nTotal TextID keys found in code: {len(keys_used)}")
7667
print(f"JSON files scanned: {len(json_files)}")
68+
sys.exit(exit_code)

0 commit comments

Comments
 (0)