mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-04-16 22:02:31 -05:00
Compare commits
43 Commits
cbb86c7746
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4ce6df911 | ||
|
|
d0846ed78f | ||
|
|
07b4e55053 | ||
|
|
690e897ca7 | ||
|
|
7471c176c3 | ||
|
|
e72773e46d | ||
|
|
3c0c1cec02 | ||
|
|
faf4236463 | ||
|
|
1c0c502258 | ||
|
|
06c48e071a | ||
|
|
8f93ee2239 | ||
|
|
9ba8b02ff1 | ||
|
|
6fc2753f3e | ||
|
|
486b359c22 | ||
|
|
76a3543672 | ||
|
|
48d185dd7d | ||
|
|
6dbc3f510b | ||
|
|
97e26103f5 | ||
|
|
59d777a33d | ||
|
|
9ce4724fc4 | ||
|
|
7e46c23f3a | ||
|
|
6f22dd7738 | ||
|
|
c0e42ee4eb | ||
|
|
92b270c054 | ||
|
|
2f11542ed3 | ||
|
|
f9a612db4a | ||
|
|
812775f6b4 | ||
|
|
73ccb216f5 | ||
|
|
5ee81b30c6 | ||
|
|
b5eae226cd | ||
|
|
fd4606885e | ||
|
|
ded903ed7a | ||
|
|
077392bcd9 | ||
|
|
f4626ce3bd | ||
|
|
9e184f76fc | ||
|
|
fa0ed63718 | ||
|
|
c3fa55bd46 | ||
|
|
0401d058a1 | ||
|
|
95b7a9813c | ||
|
|
22829cfab9 | ||
|
|
2326306f2b | ||
|
|
28ecf19f2b | ||
|
|
91925120c9 |
BIN
.github/assets/banner-light.png
vendored
Normal file
BIN
.github/assets/banner-light.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 246 KiB |
BIN
.github/assets/banner.png
vendored
Normal file
BIN
.github/assets/banner.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
BIN
.github/assets/favicon.png
vendored
Normal file
BIN
.github/assets/favicon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
.github/assets/logo.png
vendored
Normal file
BIN
.github/assets/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
.github/assets/social-preview.png
vendored
Normal file
BIN
.github/assets/social-preview.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
36
.github/workflows/build.yml
vendored
36
.github/workflows/build.yml
vendored
@@ -58,16 +58,32 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p .cache/large
|
mkdir -p .cache/large
|
||||||
gh release download large-files -D .cache/large/ 2>/dev/null || true
|
gh release download large-files -D .cache/large/ 2>/dev/null || true
|
||||||
for f in .cache/large/*; do
|
python3 -c "
|
||||||
[ -f "$f" ] || continue
|
import hashlib, json, os, shutil
|
||||||
name=$(basename "$f")
|
db = json.load(open('database.json'))
|
||||||
target=$(grep "$name" .gitignore | head -1)
|
with open('.gitignore') as f:
|
||||||
if [ -n "$target" ] && [ ! -f "$target" ]; then
|
ignored = {l.strip() for l in f if l.strip().startswith('bios/')}
|
||||||
mkdir -p "$(dirname "$target")"
|
cache = '.cache/large'
|
||||||
cp "$f" "$target"
|
if not os.path.isdir(cache):
|
||||||
echo "Restored: $target"
|
exit(0)
|
||||||
fi
|
idx = {}
|
||||||
done
|
for fn in os.listdir(cache):
|
||||||
|
fp = os.path.join(cache, fn)
|
||||||
|
if os.path.isfile(fp):
|
||||||
|
h = hashlib.sha1(open(fp, 'rb').read()).hexdigest()
|
||||||
|
idx[h] = fp
|
||||||
|
restored = 0
|
||||||
|
for sha1, entry in db['files'].items():
|
||||||
|
path = entry['path']
|
||||||
|
if path in ignored and not os.path.exists(path):
|
||||||
|
src = idx.get(sha1)
|
||||||
|
if src:
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
shutil.copy2(src, path)
|
||||||
|
print(f'Restored: {path}')
|
||||||
|
restored += 1
|
||||||
|
print(f'Total: {restored} files restored')
|
||||||
|
"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
37
.github/workflows/deploy-site.yml
vendored
37
.github/workflows/deploy-site.yml
vendored
@@ -36,6 +36,43 @@ jobs:
|
|||||||
|
|
||||||
- run: pip install pyyaml mkdocs-material pymdown-extensions
|
- run: pip install pyyaml mkdocs-material pymdown-extensions
|
||||||
|
|
||||||
|
- name: Restore large files from release
|
||||||
|
run: |
|
||||||
|
mkdir -p .cache/large
|
||||||
|
gh release download large-files -D .cache/large/ 2>/dev/null || true
|
||||||
|
python3 -c "
|
||||||
|
import hashlib, json, os, shutil
|
||||||
|
db = json.load(open('database.json'))
|
||||||
|
with open('.gitignore') as f:
|
||||||
|
ignored = {l.strip() for l in f if l.strip().startswith('bios/')}
|
||||||
|
cache = '.cache/large'
|
||||||
|
if not os.path.isdir(cache):
|
||||||
|
exit(0)
|
||||||
|
idx = {}
|
||||||
|
for fn in os.listdir(cache):
|
||||||
|
fp = os.path.join(cache, fn)
|
||||||
|
if os.path.isfile(fp):
|
||||||
|
h = hashlib.sha1(open(fp, 'rb').read()).hexdigest()
|
||||||
|
idx[h] = fp
|
||||||
|
restored = 0
|
||||||
|
for sha1, entry in db['files'].items():
|
||||||
|
path = entry['path']
|
||||||
|
if path in ignored and not os.path.exists(path):
|
||||||
|
src = idx.get(sha1)
|
||||||
|
if src:
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
shutil.copy2(src, path)
|
||||||
|
print(f'Restored: {path}')
|
||||||
|
restored += 1
|
||||||
|
print(f'Total: {restored} files restored')
|
||||||
|
"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Refresh data directories
|
||||||
|
run: python scripts/refresh_data_dirs.py
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Generate site
|
- name: Generate site
|
||||||
run: |
|
run: |
|
||||||
python scripts/generate_site.py
|
python scripts/generate_site.py
|
||||||
|
|||||||
@@ -7,6 +7,16 @@
|
|||||||
3. Variants (alternate hashes): `bios/Manufacturer/Console/.variants/`
|
3. Variants (alternate hashes): `bios/Manufacturer/Console/.variants/`
|
||||||
4. Create a Pull Request - checksums are verified automatically
|
4. Create a Pull Request - checksums are verified automatically
|
||||||
|
|
||||||
|
## Add a new platform
|
||||||
|
|
||||||
|
1. Write a scraper in `scripts/scraper/`
|
||||||
|
2. Create the platform YAML in `platforms/`
|
||||||
|
3. Register in `platforms/_registry.yml`
|
||||||
|
4. Submit a Pull Request
|
||||||
|
|
||||||
|
Contributors who add platform support are credited in the README,
|
||||||
|
on the documentation site, and in the BIOS packs.
|
||||||
|
|
||||||
## File conventions
|
## File conventions
|
||||||
|
|
||||||
- Files >50 MB go in GitHub release assets (`large-files` release)
|
- Files >50 MB go in GitHub release assets (`large-files` release)
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -1,8 +1,10 @@
|
|||||||
# RetroBIOS
|
<p align="center">
|
||||||
|
<img src=".github/assets/banner.png" alt="RetroBIOS" width="400">
|
||||||
|
</p>
|
||||||
|
|
||||||
Complete BIOS and firmware packs for Batocera, BizHawk, EmuDeck, Lakka, Recalbox, RetroArch, RetroBat, RetroDECK, RetroPie, and RomM.
|
Complete BIOS and firmware packs for Batocera, BizHawk, EmuDeck, Lakka, Recalbox, RetroArch, RetroBat, RetroDECK, RetroPie, and RomM.
|
||||||
|
|
||||||
**7,295** verified files across **396** systems, ready to extract into your emulator's BIOS directory.
|
**7,302** verified files across **396** systems, ready to extract into your emulator's BIOS directory.
|
||||||
|
|
||||||
## Quick Install
|
## Quick Install
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ Each file is checked against the emulator's source code to match what the code a
|
|||||||
- **10 platforms** supported with platform-specific verification
|
- **10 platforms** supported with platform-specific verification
|
||||||
- **329 emulators** profiled from source (RetroArch cores + standalone)
|
- **329 emulators** profiled from source (RetroArch cores + standalone)
|
||||||
- **396 systems** covered (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
|
- **396 systems** covered (NES, SNES, PlayStation, Saturn, Dreamcast, ...)
|
||||||
- **7,295 files** verified with MD5, SHA1, CRC32 checksums
|
- **7,302 files** verified with MD5, SHA1, CRC32 checksums
|
||||||
- **8765 MB** total collection size
|
- **8765 MB** total collection size
|
||||||
|
|
||||||
## Supported systems
|
## Supported systems
|
||||||
@@ -122,6 +124,10 @@ To keep packs accurate, each file is checked against the emulator's source code.
|
|||||||
<a href="https://github.com/monster-penguin"><img src="https://avatars.githubusercontent.com/u/266009589?v=4" width="50" title="monster-penguin"></a>
|
<a href="https://github.com/monster-penguin"><img src="https://avatars.githubusercontent.com/u/266009589?v=4" width="50" title="monster-penguin"></a>
|
||||||
|
|
||||||
|
|
||||||
|
## Community tools
|
||||||
|
|
||||||
|
- [BIOS Preservation Tool](https://github.com/monster-penguin/BIOS-Preservation-Tool) by [monster-penguin](https://github.com/monster-penguin) - scan, verify, and stage your own BIOS collection using RetroBIOS hash metadata
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||||
@@ -130,4 +136,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|||||||
|
|
||||||
This repository provides BIOS files for personal backup and archival purposes.
|
This repository provides BIOS files for personal backup and archival purposes.
|
||||||
|
|
||||||
*Auto-generated on 2026-03-31T20:38:37Z*
|
*Auto-generated on 2026-04-03T12:59:52Z*
|
||||||
|
|||||||
BIN
bios/Dragon/Dragon/delta2.rom
Normal file
BIN
bios/Dragon/Dragon/delta2.rom
Normal file
Binary file not shown.
BIN
bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d
Normal file
BIN
bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d
Normal file
Binary file not shown.
BIN
bios/Other/NXEngine/nxengine/data/sprites.sif
Normal file
BIN
bios/Other/NXEngine/nxengine/data/sprites.sif
Normal file
Binary file not shown.
BIN
bios/Other/NXEngine/nxengine/tilekey.dat
Normal file
BIN
bios/Other/NXEngine/nxengine/tilekey.dat
Normal file
Binary file not shown.
BIN
bios/Sony/PlayStation/.variants/scph3000.bin.e38466a4
Normal file
BIN
bios/Sony/PlayStation/.variants/scph3000.bin.e38466a4
Normal file
Binary file not shown.
BIN
bios/Sony/PlayStation/.variants/scph3500.bin.ffa7f9a7
Normal file
BIN
bios/Sony/PlayStation/.variants/scph3500.bin.ffa7f9a7
Normal file
Binary file not shown.
BIN
bios/Texas Instruments/TI-99/Gram Kracker.ctg
Normal file
BIN
bios/Texas Instruments/TI-99/Gram Kracker.ctg
Normal file
Binary file not shown.
BIN
bios/Texas Instruments/TI-99/cf7+.ctg
Normal file
BIN
bios/Texas Instruments/TI-99/cf7+.ctg
Normal file
Binary file not shown.
BIN
bios/Texas Instruments/TI-99/ti-pcard.ctg
Normal file
BIN
bios/Texas Instruments/TI-99/ti-pcard.ctg
Normal file
Binary file not shown.
301
bios/sdlpal/desc.dat
Normal file
301
bios/sdlpal/desc.dat
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
本說明檔由 Eric-Chen 整理
|
||||||
|
http://hi.baidu.com/eric_chensoft
|
||||||
|
|
||||||
|
適用於 SDLPAL (http://sdlpal.codeplex.com)
|
||||||
|
|
||||||
|
3d(觀音符)=以觀音聖水書寫的靈符。*HP+150
|
||||||
|
3e(聖靈符)=具有女媧神強大靈力的符咒。*全體HP+300
|
||||||
|
3f(金剛符)=使用後如有金鐘鐵罩護身。*增加防禦七回合。
|
||||||
|
40(淨衣符)=具有祛病、驅邪的法力,*可解赤毒、屍毒、瘴毒。
|
||||||
|
41(靈心符)=具有寧神、驅邪的靈效,*可解瘋魔、妖縛、昏睡、封咒。
|
||||||
|
42(天師符)=茅山道士用來對付妖怪的符咒。
|
||||||
|
43(風靈符)=產生風系法術的符咒。
|
||||||
|
44(雷靈符)=產生雷系法術的符咒。
|
||||||
|
45(水靈符)=產生冰系法術的符咒。
|
||||||
|
46(火靈符)=產生火系法術的符咒。
|
||||||
|
47(土靈符)=產生土系法術的符咒。
|
||||||
|
48(舍利子)=得道高僧佛身火化後,*結成如珠狀的東西。*最大真氣值+3
|
||||||
|
49(玉菩提)=墨玉菩提樹的種籽。*最大真氣值+5
|
||||||
|
4a(銀杏子)=銀杏樹所結的白色核果。*最大體力值+3
|
||||||
|
4b(糯米)=糯稻的米,富於黏性,*可解屍毒。
|
||||||
|
4c(糯米糕)=糯米加麥芽、甜豆所煮的米糕,*可解屍毒。HP+25
|
||||||
|
4d(鹽巴)=取海水煎熬或曝曬而成,用來調*味,有時可解毒。
|
||||||
|
4e(茶葉蛋)=雞蛋水煮後,以茶葉入味。*便宜而好吃的食物。*HPMP+15
|
||||||
|
4f(雞蛋)=便宜而常見的食物。*HPMP+10
|
||||||
|
50(糖葫蘆)=以竹簽串李子,裹上麥芽糖,*形如葫蘆,故稱「糖葫蘆」。*HPMP+22
|
||||||
|
51(蠟燭)=用蠟製的點火照明的東西。
|
||||||
|
52(符紙)=泛黃的空白符紙。
|
||||||
|
53(檀香)=含有檀香料的一種香,點燃用以*薰衣、薰室內,驅逐惡氣。
|
||||||
|
54(大蒜)=具有除穢、祛病、護身等功能,*可以入藥。*戰鬥中服食避毒率+30%
|
||||||
|
56(酒)=以米加酒麴釀製而成,*可解赤毒。HPMP+15
|
||||||
|
57(雄黃)=天然產的礦物,塊狀、色黃,*可解赤毒。
|
||||||
|
58(雄黃酒)=一點點的雄黃,撒在酒中,*習俗在端午節喝這種酒;*可解赤毒、瘴毒。
|
||||||
|
59(九節菖蒲)=一種水草,葉子狹長如劍,*可解赤毒、屍毒、瘴毒、毒絲。
|
||||||
|
5a(驅魔香)=以大蒜、雄黃、艾草、檀香等混合*煉製而成,點燃後發出魔物厭惡*的氣味,使魔物不敢接近。
|
||||||
|
5b(十里香)=以生血、內藏、肉桂等煉製,*點燃後散發出吸引魔物的香味。
|
||||||
|
5c(水果)=養顏美容、幫助消化。*HPMP+20
|
||||||
|
5d(燒肉)=以炭火熏烤的醬汁豬肉。*HPMP+30
|
||||||
|
5e(醃肉)=用鹽巴醃漬的豬肉。*HP+85
|
||||||
|
5f(還魂香)=點燃後會散發奇異的香氣,*能牽引離體魂魄回歸軀體。*HP恢復10%
|
||||||
|
60(贖魂燈)=以蓮燈作法與鬼差交涉,*贖回死者魂魄。*HP恢復30%
|
||||||
|
61(孟婆湯)=消除死者罪孽業障,*使死者復活。*HP恢復50%
|
||||||
|
62(天香續命露)=以大量珍貴秘藥精煉而成,*具有肉白骨、藥死人之奇效。*HP恢復100%
|
||||||
|
63(止血草)=嚼碎後敷在傷口上,可迅速止血。*HP+50
|
||||||
|
64(行軍丹)=活血順氣的藥丸。*HP+100
|
||||||
|
65(金創藥)=上等刀傷藥,去腐生肌。*HP+200
|
||||||
|
66(蟠果)=西王母蟠桃園遺種,*籽小肉厚汁液香甜。*HP+450
|
||||||
|
67(紫菁玉蓉膏)=依宮廷秘方,采珍貴藥材煉製,*是療傷藥的極品。*HP+1000
|
||||||
|
68(鼠兒果)=產於山間野地,多為鼠類所食,*經人發現移種平地。*MP+36
|
||||||
|
69(還神丹)=寧神醒腦的藥丸。*MP+50
|
||||||
|
6a(龍涎草)=經蛟龍唾涎灌溉而生,*具有補中益氣之療效。*MP+110
|
||||||
|
6b(靈山仙芝)=寄生於枯木上的菌類,俗稱瑞草,*具有養氣培元之神效。*MP+260
|
||||||
|
6c(雪蓮子)=白玉雪蓮之蓮子,其形珠圓玉潤,*服食者真氣充盈,經脈通暢。*MP+400
|
||||||
|
6d(天仙玉露)=觀音菩薩淨瓶甘露水,*人間難求的仙界聖藥。*MP+700
|
||||||
|
6e(神仙茶)=神仙廣成子養生延壽之秘方。*HPMP+440
|
||||||
|
6f(靈葫仙丹)=修道隱士所煉丹藥。*HPMP+250
|
||||||
|
70(試煉果)=藥王神農氏嘗百草時,*最早發現的珍藥。*靈力最大值+3
|
||||||
|
71(女媧石)=女神媧皇煉石補天後,*所遺之五色石。*防禦最大值+3
|
||||||
|
72(八仙石)=八仙石洞中所采集之丹礦。*防禦最大值+2
|
||||||
|
73(蜂巢)=蜜蜂的窩,可以拿來丟敵人。
|
||||||
|
74(屍腐肉)=沾染屍毒的腐敗肉塊。*毒性: 屍毒
|
||||||
|
75(毒蛇卵)=煉蠱的材料。*毒性: 赤毒
|
||||||
|
76(毒蠍卵)=煉蠱的材料。*毒性: 赤毒
|
||||||
|
77(毒蟾卵)=煉蠱的材料。*毒性: 赤毒
|
||||||
|
78(蜘蛛卵)=煉蠱的材料。*毒性: 赤毒
|
||||||
|
79(蜈蚣卵)=煉蠱的材料。*毒性: 赤毒
|
||||||
|
7a(鶴頂紅)=七大毒蠱,中毒後每回合損血,*至死方休。*解藥: 血海棠 致命藥引: 孔雀膽
|
||||||
|
7b(孔雀膽)=七大毒蠱,中毒後每回合損血,*至死方休。*解藥: 金蠶蠱 致命藥引: 鶴頂紅
|
||||||
|
7c(血海棠)=七大毒蠱,中毒後每回合損血,*至死方休。*解藥: 斷腸草 致命藥引: 三屍蠱
|
||||||
|
7d(斷腸草)=七大毒蠱,中毒後每回合損血,*至死方休。*解藥: 三屍蠱 致命藥引: 金蠶蠱
|
||||||
|
7e(醍醐香)=紫葉小白花,散發濃鬱香氣,*聞到香氣,便如酒醉一般。*妖縛四回合。
|
||||||
|
7f(忘魂花)=青藍色小花,散發淡淡香氣,*聞到香氣,便會渾然忘我、*昏睡三回合。
|
||||||
|
80(紫罌粟)=服食者會產生幻覺,敵我不分。*瘋魔四回合。
|
||||||
|
81(鬼枯藤)=具毒性的黑褐色野生藤蔓,*可解赤毒、屍毒、瘴毒、毒絲。*HP-30
|
||||||
|
82(腹蛇涎)=腹蛇的毒涎。*毒性: 瘴毒
|
||||||
|
83(蜂王蜜)=蜜蜂所釀最好的蜜。*HPMP+150
|
||||||
|
84(雪蛤蟆)=生長於天山極寒之地,僅銅錢般大*小。武術最大值+2 防禦最大值+2*靈力最大值+2
|
||||||
|
85(赤蠍粉)=以整只赤尾蠍研磨成的粉末,*可使敵方全體中赤毒。
|
||||||
|
86(化屍水)=碰到傷口血水,便腐蝕潰爛,*受傷者沾染立斃。
|
||||||
|
87(迷魂香)=點燃蒙汗藥散發迷香,*可使敵人昏睡五回合。
|
||||||
|
88(九陰散)=服食前若已中毒,可補滿體力,*但無法解毒;*服食前若沒中毒,即刻斃命。
|
||||||
|
89(無影毒)=七大毒蠱,中毒後立即發作,*耗損一半體力。
|
||||||
|
8a(三屍蠱)=七大毒蠱;中毒後,潛伏片刻即*會發作,毒性非常猛烈。*解藥: 孔雀膽 致命藥引: 血海棠
|
||||||
|
8b(金蠶蠱)=七大毒蠱,中毒後每回合損血,*至死方休。*解藥: 鶴頂紅 致命藥引: 斷腸草
|
||||||
|
8c(幻蠱)=分泌的毒液會影響人的腦部,*使人敵我不分,*瘋魔五回合。
|
||||||
|
8d(隱蠱)=如帶刺甲蟲,將其身體捏破,*散發之煙霧可助我方隱匿形跡。*全體隱形三回合。
|
||||||
|
8e(冰蠶蠱)=以雪山冰洞內所產所冰蠶培養的*蠱蟲,可做為攻擊道具。
|
||||||
|
8f(火蠶蠱)=以麒麟炎洞內所產火蠶所培養的*蠱蟲,可做為攻擊道具。
|
||||||
|
90(食妖蟲)=寄生宿主吸取靈氣,九回合後,*可煉成靈蠱。
|
||||||
|
91(靈蠱)=以稀有藥物豢養的雌蠱。*全體MP+250
|
||||||
|
92(爆烈蠱)=預先將法力灌輸在蠱蟲體內,*投擲敵人產生強烈爆炸。
|
||||||
|
93(碧血蠶)=寄生宿主吸取血液,九回合後,*可煉成赤血蠶。
|
||||||
|
94(蠱)=巫師施法所需的材料。
|
||||||
|
95(赤血蠶)=吸血維生的毒蠱,*服食後體力完全恢復。
|
||||||
|
96(金蠶王)=蠱中之王,月夜散發金色磷光,*服食後可提升修行。
|
||||||
|
97(引路蜂)=跟隨引路蜂而行,*可回到迷宮起點。
|
||||||
|
98(傀儡蟲)=湘西雲貴巫師用以控制屍體,*可使死者繼續攻擊九回合。
|
||||||
|
99(梅花鏢)=形如梅花的暗器。*敵人HP-90
|
||||||
|
9a(袖裏劍)=暗藏在衣袖中的飛劍。*敵人HP-170
|
||||||
|
9b(透骨釘)=精鐵打造、三寸長的鐵針是*很鋒利的暗器。*敵人HP-250
|
||||||
|
9c(雷火珠)=填充火藥的鐵珠,投擲撞擊*後會爆裂傷人。*敵人HP-135
|
||||||
|
9d(毒龍砂)=以腹蛇毒煉製成的細砂,*可使敵方全體中瘴毒。*HP-55
|
||||||
|
9e(吸星鎖)=鐵製鋼抓,尾端系以靈蠱蠶絲,*可吸取敵人HP180
|
||||||
|
9f(纏魂絲)=千年蜘蛛的毒絲。*毒性: 毒絲
|
||||||
|
a0(捆仙繩)=施有咒術的粗麻繩,*可令妖怪動彈不得,*妖縛五回合。
|
||||||
|
a1(無影神針)=細如牛毛,傷人於無形。*敵人HP-400
|
||||||
|
a2(血玲瓏)=紅色鐵球,四周裝有鋒利刀片。*敵方全體HP-300
|
||||||
|
a3(長鞭)=生牛皮製的七尺軟鞭。*武術+20 身法+20
|
||||||
|
a4(九截鞭)=以鐵節鐵環組成的九節軟鞭。*武術+66 身法+33
|
||||||
|
a5(金蛇鞭)=以蛇皮絞以金絲編織成九尺軟鞭。*武術+99 身法+60
|
||||||
|
a6(木劍)=用木材雕刻的劍,小孩玩具。*武術+2 身法+3
|
||||||
|
a7(短刀)=一尺半長的鈍刀,可用來劈*砍木材。*武術+6 身法-5
|
||||||
|
a8(鐵劍)=一般鐵匠大量生產的劍,打造*得頗為粗劣。*武術+10 防禦+3
|
||||||
|
a9(大刀)=刀身寬而長,刃部鋒利,*背部厚重。*武術+16 防禦+1
|
||||||
|
aa(仙女劍)=一尺長的雙手劍,適合女子*使用,可發出兩次攻擊。*武術+8 防禦+5
|
||||||
|
ab(長劍)=一般鐵匠接受訂造的劍,*比鐵劍精致鋒利。*武術+25
|
||||||
|
ac(紅纓刀)=精鋼打造,背厚刃薄,*刀柄飾以紅色長穗。*武術+38
|
||||||
|
ad(越女劍)=劍身寬僅兩指,*專為女子打造。*武術+22 身法+8
|
||||||
|
ae(戒刀)=佛門中人練武所用之刀,*嚴禁傷生染血。*武術+55 防禦+5 靈力+10
|
||||||
|
af(玄鐵劍)=以珍貴的黑色鐵礦打造而成,*堅韌鋒利但極笨重。*武術+70 身法-20 靈力-15 防禦+9
|
||||||
|
b0(芙蓉刀)=百花派獨門兵器雙手彎刀,*可發出兩次攻擊。*武術+16 身法+8
|
||||||
|
b1(柳月刀)=細長鐵製雙刀,形如柳葉新月,*可發出兩次攻擊。*武術+28 身法+12 防禦+3
|
||||||
|
b2(青鋒劍)=名家精心打造的劍,輕薄鋒利。*武術+75 身法+15
|
||||||
|
b3(苗刀)=苗族戰士所慣用的佩刀。*武術+70 身法+32
|
||||||
|
b4(鳳鳴刀)=出鞘之聲有如鳳鳴,*故稱「鳳鳴刀」。武術+124*防禦+9 身法+32 靈力+16
|
||||||
|
b5(雙龍劍)=與一般劍長度相同的雙手劍,*可發出兩次攻擊。*武術+62 防禦+9 身法+9
|
||||||
|
b6(玉女劍)=鴛鴦雙劍中的雌劍,與金童劍為*一對。武術+100 靈力+15*身法+20 吉運+30
|
||||||
|
b7(金童劍)=鴛鴦雙劍中的雄劍,與玉女劍為*一對。武術+100 吉運+30*身法+20 靈力+15 防禦+3
|
||||||
|
b8(龍泉劍)=龍泉的水質非常適合造劍,*當地生產的劍叫龍泉劍。*武術+88 身法+20 吉運+22
|
||||||
|
b9(鬼牙刀)=苗刀的一種,刀尖倒鉤,*又稱「勾魂刀」。*武術+90 身法+26 吉運-9
|
||||||
|
ba(七星劍)=劍身鑲嵌七顆金黃寶石,可吸取北*斗七星之精氣。武術+120 靈力+50*身法+32 吉運+33 防禦+7
|
||||||
|
bb(玄冥寶刀)=可連續攻擊敵方全體兩次,*傳說是魔族的邪異兵器。*武術+98 身法+98 吉運+98
|
||||||
|
bc(巫月神刀)=苗族拜月教鎮教之寶。*武術+132 靈力+55 防禦+29*身法+45 吉運+36
|
||||||
|
bd(盤龍劍)=鑄劍宗師歐冶子所煉寶劍,劍身鑄*有青龍盤柱。武術+134 靈力+37*防禦+8 身法+40 吉運+32
|
||||||
|
be(太極劍)=道祖張陵之隨身配劍,天師仗以降*妖伏魔。武術+158 靈力+90*防禦+35 身法+50 吉運+33
|
||||||
|
bf(無塵劍)=上古神劍,指天天崩、劃地地裂。*武術+200 防禦+20 身法+77*吉運+33
|
||||||
|
c0(青蛇杖)=雕刻雙蛇纏繞的綠玉杖。*武術+50 靈力+62 防禦+6
|
||||||
|
c1(鬼頭杖)=苗族巫師役鬼煉蠱之法器,*頭顱中囚禁四十九條生魂。*武術+70 靈力+88 防禦+11
|
||||||
|
c2(冥蛇杖)=來自冥界之魔杖,號令群邪,*杖頭鑲嵌千年蛇王內丹。*武術+88 靈力+120 防禦+22
|
||||||
|
c3(天蛇杖)=女神媧皇煉化五色石所用法杖。*武術+100 靈力+150 防禦+33*吉運+36
|
||||||
|
c4(頭巾)=以剩餘布料縫製的頭巾。*防禦+1
|
||||||
|
c5(青絲巾)=青色的絲織髮帶。*防禦+2
|
||||||
|
c6(髮飾)=錫製的女子頭飾。*防禦+3
|
||||||
|
c7(銀釵)=純銀的髮釵。*防禦+5
|
||||||
|
c8(翠玉金釵)=鑲有綠翡翠的黃金髮釵。*防禦+9
|
||||||
|
c9(皮帽)=羊皮縫製的帽子,非常保暖。*防禦+4
|
||||||
|
ca(珍珠冠)=以珍珠縫綴的紅色錦冠。*防禦+13
|
||||||
|
cb(天師帽)=道士做法時所戴的帽子。*防禦+11 靈力+3
|
||||||
|
cc(紫金冠)=紫金冠以薄銅片鑄成,*外殼以紫飾金而成。*防禦+18
|
||||||
|
cd(天蠶絲帶)=以極珍貴的天蠶絲織成,*輕薄柔韌。*防禦+25 身法+8
|
||||||
|
ce(鳳凰羽毛)=金翅鳳凰腹部的銀色羽毛。*防禦+7 身法+24 吉運+9
|
||||||
|
cf(沖天冠)=天兵神將遺留的護頭金盔,*頂插雙雉尾羽。*防禦+28法+5 靈力+3 吉運+3
|
||||||
|
d0(布袍)=粗布縫製的交領長袖白袍。*防禦+3
|
||||||
|
d1(藤甲)=以荊藤編製的護甲。*防禦+7
|
||||||
|
d2(絲衣)=以蠶絲紡織而成,輕柔透氣。*防禦+3 身法+4
|
||||||
|
d3(鐵鎖衣)=以鐵環扣鎖製成的護甲。*防禦+13 身法-10
|
||||||
|
d4(夜行衣)=暗黑色的緊身衣靠,*便於隱匿夜色之中。*防禦+18 身法+12 吉運+12
|
||||||
|
d5(青銅甲)=青銅製的獸面紋胸護甲。*防禦+22 身法-13
|
||||||
|
d6(羅漢袍)=修行得道的和尚所穿的衣袍。*防禦+10 吉運+10 靈力+10
|
||||||
|
d7(鐵鱗甲)=以魚鱗形甲片編綴而成的鎧甲。*防禦+28 身法-4
|
||||||
|
d8(天師道袍)=天師道祖修行時所穿的法衣。*防禦+33 靈力+28
|
||||||
|
d9(精鐵戰甲)=以橢圓形的精鐵片編綴而成,*光亮照人,*又稱「光明鎧」。防禦+40 身法-7
|
||||||
|
da(金縷衣)=以金線穿玉片編製而成*又稱「金縷玉衣」。*防禦+7 身法-10
|
||||||
|
db(鬼針冑)=長滿倒刺的銅製盔甲。*防禦+55 武術+9
|
||||||
|
dc(天蠶寶衣)=以極珍貴的天蠶絲織成,*輕薄柔韌。*防禦+66
|
||||||
|
dd(青龍寶甲)=龍鱗編綴而成,世間絕頂*戰甲。*防禦+90
|
||||||
|
de(白虎之鎧)=以罕見的白虎皮製成的皮甲。*防禦+80
|
||||||
|
df(玄武戰袍)=以玄武的殼甲鍛造而成,*材質堅韌色黑而無光澤。*防禦+80
|
||||||
|
e0(朱雀戰衣)= 以南方火鳥的羽毛編織而成。*防禦+80
|
||||||
|
e1(披風)=無領對襟、無袖的披衣,*俗稱「斗篷」。*防禦+2
|
||||||
|
e2(護肩)=披於肩臂上的鎧甲,*又稱「掩膊」。*防禦+6
|
||||||
|
e3(武士披風)=將帥所穿有護肩軟甲的戰帔。*防禦+12
|
||||||
|
e4(護心鏡)=防護前胸要害的披甲,形如*銅鏡。防禦+20
|
||||||
|
e5(霓虹羽衣)=東海霓虹鳥的羽毛織成的*披肩。*防禦+18 身法+18 吉運+18
|
||||||
|
e6(菩提袈裟)=高等僧衣,又名「無垢衣」,*多為高僧與長老所穿。*防禦+31 靈力+16
|
||||||
|
e7(虎紋披風)=以整張千年白額虎虎皮製成,*毛皮呈黃色,帶黑色橫紋。*防禦+40
|
||||||
|
e8(鳳紋披風)=相傳為織女縫製的披風,*繡鳳織錦,光彩奪目。*防禦+52
|
||||||
|
e9(龍紋披風)=布面繡雙龍搶珠之彩紋,*有神龍護體之功效。*防禦+60
|
||||||
|
ea(聖靈披風)=巫后的遺物,潛藏神聖的力*量。防禦+66 靈力+30
|
||||||
|
eb(草鞋)=以藺草編織而成,十分便宜,*穿起來很輕便,適宜行走。*防禦+1
|
||||||
|
ec(木鞋)=以木材削製而成,鞋面刻有吉祥*圖案。*防禦+2
|
||||||
|
ed(布靴)=粗布縫製的長統靴。*防禦+3 身法+2
|
||||||
|
ee(繡花鞋)=以絲緞縫製,鞋面繡有龍頭鳳尾*花。*防禦+4
|
||||||
|
ef(鐵履)=鞋底夾縫鐵片,較普通布靴重。*防禦+6
|
||||||
|
f0(武僧靴)=羅漢僧練武所穿的布靴。*防禦+8 身法+6
|
||||||
|
f1(鹿皮靴)=鞋面以鹿皮毛縫製,質地輕柔,*行動可如鹿般迅捷。*防禦+11 身法+9
|
||||||
|
f2(疾風靴)=以薄如雲霧的蟬紗織成,*助穿者疾行如風。*防禦+14 身法+17
|
||||||
|
f3(蓮花靴)=飾以金蓮的長統繡花鞋。*防禦+18 身法+5
|
||||||
|
f4(虎皮靴)=取自東北虎的皮毛縫製。*防禦+21 身法+16
|
||||||
|
f5(龍鱗靴)=以龍鱗編綴而成。*防禦+25 身法+12
|
||||||
|
f6(步雲靴)=雲中子羽化登仙後,*所遺留之神靴。*防禦+28 身法+20
|
||||||
|
f7(魅影神靴)=妖魔附體,身如鬼魅。*防禦+32 身法+26
|
||||||
|
f8(香袋)=填充木屑、香粉的小布包,*常用來裝飾兼避邪的物品。*靈力+8 吉運+9 避毒率+20%
|
||||||
|
f9(護腕)=粗布縫製之腕部護套。*防禦+2
|
||||||
|
fa(鐵護腕)=精鋼打造之腕部護環。*防禦+5
|
||||||
|
fb(竹笛)=青竹削製之七孔橫笛。*吉運+18
|
||||||
|
fc(珍珠)=蚌類所生的球狀物,*是珍貴的裝飾品。*吉運+20
|
||||||
|
fd(玉鐲)=戴在手臂上的玉製環形首飾。*防禦+5 吉運+9
|
||||||
|
fe(唸珠)=佛教徒記數唸經咒或佛號次數的*計算珠。*靈力+5 防禦+5
|
||||||
|
ff(銀針)=用銀針刺肉,以痛楚喚醒神智,*可解妖縛、昏睡、瘋魔。HP-9
|
||||||
|
100(銅鏡)=青銅鑄造的照容用具。*防禦+6
|
||||||
|
101(八卦鏡)=用朱砂在鏡面畫八卦,*可借用自然界的靈氣。*靈力+8 防禦+8
|
||||||
|
102(幹坤鏡)=銅鏡背面鑄有太極乾坤圖,*可吸取天地陰陽靈氣。*靈力+14 防禦+14
|
||||||
|
103(豹牙手環)=收集花豹的利牙串成的手環。*防禦+9
|
||||||
|
104(聖靈珠)=女媧末族祖傳寶物,曆代聖魂歸依*之所。合體法術: 武神*靈力+128 防禦+15 避毒率+35%
|
||||||
|
105(金罡珠)=大羅金仙修煉千年的內丹。*防禦+90
|
||||||
|
106(五毒珠)=成精蟾怪的內丹,*佩戴後百毒不侵。
|
||||||
|
107(風靈珠)=女媧降伏風神後,禁制風神於內的*寶珠。合體法術: 風卷殘雲*避風率+50%
|
||||||
|
108(雷靈珠)=女媧降伏雷神後,禁制雷神於內的*寶珠。合體法術: 狂雷*避雷率+50%
|
||||||
|
109(水靈珠)=女媧降伏雪妖後,禁制雪妖於內的*寶珠。合體法術: 風雪冰天*避水率+50%
|
||||||
|
10a(火靈珠)=女媧降伏火神後,禁制火神於內的*寶珠。合體法術: 煉獄真火*避火率+50%
|
||||||
|
10b(土靈珠)=女媧降伏山神後,禁制山神於內的*寶珠。合體法術: 泰山壓頂*避土率+50% 可用於脫離洞窟
|
||||||
|
10c(煉蠱皿)=可將毒蛇卵、毒蠍卵、毒蟾卵、*蜘蛛卵、蜈蚣卵煉成蠱。
|
||||||
|
10d(壽葫蘆)=戰鬥中發出真氣補充持有者,*有提神振氣之奇效。*HPMP每回合+20
|
||||||
|
10e(紫金葫蘆)=收妖煉丹,需與靈葫咒配合。
|
||||||
|
10f(布包)=長安富商的行李。
|
||||||
|
110(桂花酒)=摻了水的酒。
|
||||||
|
111(紫金丹)=水月宮最珍貴的仙丹靈藥。
|
||||||
|
112(玉佛珠)=西方如來檀前的唸珠,經佛法薰陶*變化通靈。合體法術: 佛法無邊*靈力+88 防禦+18 避毒率+30%
|
||||||
|
113(金鳳凰蛋殼)=藥材。
|
||||||
|
114(火眼麒麟角)=藥材。
|
||||||
|
116(毒龍膽)=千年毒蛟的膽,以毒攻毒可解天下*所有的毒。*若沒中毒吃毒龍膽會斃命。
|
||||||
|
117(破天錘)=用來敲碎仙靈島石像的法寶。
|
||||||
|
118(包袱)=嬸嬸替逍遙收拾的行李。
|
||||||
|
119(銀杏果)=藥材。
|
||||||
|
11a(鯉魚)=藥材。
|
||||||
|
11b(鹿茸)=藥材。
|
||||||
|
11c(釣竿)=借來的,記得還!
|
||||||
|
11d(捕獸夾)=獵戶放置的捕鹿的道具。
|
||||||
|
11e(六神丹)=韓家藥鋪的祖傳婦女良藥。
|
||||||
|
11f(情書)=士兵委托的情書。
|
||||||
|
120(玉佩)=婢女委托的玉佩。
|
||||||
|
121(石鑰匙)=開啟隱龍窟後洞石門的鑰匙。
|
||||||
|
122(天書)=書中仙附身於書中。
|
||||||
|
123(香蕉)=誰喜歡吃香蕉?
|
||||||
|
124(鳳紋手絹)=某人交付的信物。
|
||||||
|
125(手卷)=李逍遙的父母親所留下的武功*秘笈。
|
||||||
|
126(蘆葦漂)=可載人漂浮水面的草席。
|
||||||
|
127(夢蛇)=女媧族的變身魔法,*能力大幅提升。
|
||||||
|
128(氣療術)=我方單人HP+75
|
||||||
|
129(觀音咒)=我方單人HP+150
|
||||||
|
12a(凝神歸元)=我方單人HP+220
|
||||||
|
12b(元靈歸心術)=我方單人HP+500
|
||||||
|
12c(五氣朝元)=我方全體HP+300
|
||||||
|
12d(還魂咒)=我方單人復活*HP恢復10%
|
||||||
|
12e(贖魂)=我方單人復活*HP恢復30%
|
||||||
|
12f(回夢)=敵方單人昏睡四回合。
|
||||||
|
130(奪魂)=吸取敵人魂魄,中者立斃。
|
||||||
|
131(鬼降)=敵方單人瘋魔四回合。
|
||||||
|
132(淨衣咒)=解赤毒、屍毒、瘴毒。
|
||||||
|
133(冰心訣)=解妖縛、昏睡、瘋魔、咒封。
|
||||||
|
134(靈血咒)=解赤毒、屍毒、瘴毒、毒絲、*麻痹、催眠、瘋魔、咒封。
|
||||||
|
135(金剛咒)=使用後如有金鐘鐵罩護身,*增加防禦七回合。
|
||||||
|
136(真元護體)=使用後如有鐵鎧金甲護體,*增加防禦九回合。
|
||||||
|
137(天罡戰氣)=七回合內,使用武器攻擊,*威力提升。
|
||||||
|
138(風咒)=風系初級法術,*攻擊敵方單人。
|
||||||
|
139(旋風咒)=風系中級法術,*攻擊敵方全體。
|
||||||
|
13a(風卷殘雲)=風系高級法術,*攻擊敵方全體。
|
||||||
|
13b(風神)=召喚風神,*最強的風系法術。
|
||||||
|
13c(雷咒)=雷系初級法術,*攻擊敵方單人。
|
||||||
|
13d(五雷咒)=雷系中級法術,*攻擊敵方全體。
|
||||||
|
13e(天雷破)=雷系高級法術,*攻擊敵方單人。
|
||||||
|
13f(狂雷)=雷系高級法術,*攻擊敵方全體。
|
||||||
|
140(雷神)=召喚雷神,*最強的雷系法術。
|
||||||
|
141(冰咒)=冰系初級法術,*攻擊敵方單人。
|
||||||
|
142(玄冰咒)=冰系中級法術,*攻擊敵方全體。
|
||||||
|
143(風雪冰天)=冰系高級法術,*攻擊敵方全體。
|
||||||
|
144(風雪冰天)=冰系高級法術,*攻擊敵方全體。
|
||||||
|
145(雪妖)=召喚雪妖,*最強的冰系法術。
|
||||||
|
147(炎咒)=火系初級法術,*攻擊敵方單人。
|
||||||
|
148(三昧真火)=火系中級法術,*攻擊敵方全體。
|
||||||
|
149(炎殺咒)=火系高級法術,*攻擊敵方單人。
|
||||||
|
14a(煉獄真火)=火系高級法術,*攻擊敵方全體。
|
||||||
|
14c(土咒)=土系初級法術,*攻擊敵方單人。
|
||||||
|
14d(飛岩術)=土系中級法術,*攻擊敵方全體。
|
||||||
|
14e(地裂天崩)=土系中級法術,*攻擊敵方全體。
|
||||||
|
14f(泰山壓頂)=土系高級法術,*攻擊敵方全體。
|
||||||
|
150(山神)=召喚山神,*最強的土系法術。
|
||||||
|
151(氣劍指)=蘇州林家的家傳武藝,*攻擊敵方全體。
|
||||||
|
154(一陽指)=聚勁食指,發出剛猛的氣芒,*攻擊敵方單人。
|
||||||
|
155(七訣劍氣)=以指代劍,發出裂地劍氣*攻擊敵方全體。
|
||||||
|
156(斬龍訣)=以雄渾氣勁橫掃群魔,*攻擊敵方全體。
|
||||||
|
158(銅錢鏢)=將金錢當做暗器,攻擊敵方*單人,一次使用五百文錢。
|
||||||
|
159(禦劍術)=蜀山派入門劍法,*攻擊敵方單人。
|
||||||
|
15a(萬劍訣)=劍芒如雨直落,*攻擊敵方全體。
|
||||||
|
15c(天劍)=人劍合一,身化利劍,*攻擊敵方全體。
|
||||||
|
15d(天師符法)=茅山道士用來對付妖怪*的符法,攻擊敵方單人。
|
||||||
|
15f(武神)=召喚武神,神刀斬魔。
|
||||||
|
160(三屍咒)=下蠱攻擊敵方單人,*有蠱時才能使用。
|
||||||
|
161(禦蜂術)=以笛音指揮毒蜂,*攻擊敵方全體。
|
||||||
|
162(萬蟻蝕象)=操縱食人毒蟻,*攻擊敵方單人。
|
||||||
|
16b(劍神)=召喚劍神,萬劍齊飛。
|
||||||
|
172(酒神)=召喚酒神,*用全身真氣爆發攻擊敵人。
|
||||||
|
174(萬蠱蝕天)=放蠱攻擊敵方全體,*有蠱時才能使用。
|
||||||
|
176(爆炸蠱)=預先將法力灌輸在蠱蟲體*內,投擲敵人產生強烈爆炸。
|
||||||
|
179(飛龍探雲手)=偷取敵人的物品或金錢。
|
||||||
|
180(靈葫咒)=當妖物體力低於四分之一時,*可將其收入紫金葫蘆中煉藥。
|
||||||
|
185(火神)=召喚火神,*最強的火系法術。
|
||||||
|
186(醉仙望月步)=五回合內,使用武器攻擊,*可連續出手兩次。
|
||||||
|
188(金蟬脫殼)=戰鬥中逃跑。
|
||||||
|
189(仙風雲體術)=身法暫時提升九回合。
|
||||||
|
18a(乾坤一擲)=使用金錢鏢攻擊敵方全體,*會耗損大量金錢。
|
||||||
7531
database.json
7531
database.json
File diff suppressed because it is too large
Load Diff
578
docs_assets/extra.css
Normal file
578
docs_assets/extra.css
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
/* RetroBIOS custom theme */
|
||||||
|
|
||||||
|
/* ── Color palette ── */
|
||||||
|
:root {
|
||||||
|
--rb-primary: #4a4e8a;
|
||||||
|
--rb-primary-light: #6366a0;
|
||||||
|
--rb-primary-dark: #363870;
|
||||||
|
--rb-accent: #e8594f;
|
||||||
|
--rb-success: #2e7d32;
|
||||||
|
--rb-warning: #f57c00;
|
||||||
|
--rb-danger: #c62828;
|
||||||
|
--rb-info: #1565c0;
|
||||||
|
--rb-muted: #78909c;
|
||||||
|
--rb-surface: #f5f6fa;
|
||||||
|
--rb-border: #e0e3eb;
|
||||||
|
--rb-text-secondary: #546e7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] {
|
||||||
|
--rb-surface: #1e1e2e;
|
||||||
|
--rb-border: #313244;
|
||||||
|
--rb-text-secondary: #a6adc8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Material theme overrides ── */
|
||||||
|
[data-md-color-scheme="default"] {
|
||||||
|
--md-primary-fg-color: var(--rb-primary);
|
||||||
|
--md-primary-fg-color--light: var(--rb-primary-light);
|
||||||
|
--md-primary-fg-color--dark: var(--rb-primary-dark);
|
||||||
|
--md-accent-fg-color: var(--rb-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] {
|
||||||
|
--md-primary-fg-color: var(--rb-primary-light);
|
||||||
|
--md-accent-fg-color: var(--rb-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Hero section (home page) ── */
|
||||||
|
.rb-hero {
|
||||||
|
background: linear-gradient(135deg, var(--rb-primary) 0%, var(--rb-primary-dark) 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 2.5rem 2rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-hero::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 300px;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, transparent 40%, rgba(255,255,255,0.04) 100%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-hero h1 {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: white !important;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-hero p {
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Stat cards ── */
|
||||||
|
.rb-stats {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stat {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stat:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stat .rb-stat-value {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--rb-primary);
|
||||||
|
line-height: 1.2;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] .rb-stat .rb-stat-value {
|
||||||
|
color: var(--rb-primary-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stat .rb-stat-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Progress bars (inline) ── */
|
||||||
|
.rb-progress {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-progress-bar {
|
||||||
|
flex: 1;
|
||||||
|
height: 6px;
|
||||||
|
background: var(--rb-border);
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-progress-fill[data-level="high"] { background: var(--rb-success); }
|
||||||
|
.rb-progress-fill[data-level="mid"] { background: var(--rb-warning); }
|
||||||
|
.rb-progress-fill[data-level="low"] { background: var(--rb-danger); }
|
||||||
|
|
||||||
|
.rb-progress-text {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 3.5em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Status badges ── */
|
||||||
|
.rb-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.15em 0.6em;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-badge-success { background: #e8f5e9; color: #1b5e20; }
|
||||||
|
.rb-badge-warning { background: #fff3e0; color: #e65100; }
|
||||||
|
.rb-badge-danger { background: #ffebee; color: #b71c1c; }
|
||||||
|
.rb-badge-info { background: #e3f2fd; color: #0d47a1; }
|
||||||
|
.rb-badge-muted { background: #eceff1; color: #455a64; }
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] .rb-badge-success { background: #1b5e20; color: #a5d6a7; }
|
||||||
|
[data-md-color-scheme="slate"] .rb-badge-warning { background: #e65100; color: #ffcc80; }
|
||||||
|
[data-md-color-scheme="slate"] .rb-badge-danger { background: #b71c1c; color: #ef9a9a; }
|
||||||
|
[data-md-color-scheme="slate"] .rb-badge-info { background: #0d47a1; color: #90caf9; }
|
||||||
|
[data-md-color-scheme="slate"] .rb-badge-muted { background: #37474f; color: #b0bec5; }
|
||||||
|
|
||||||
|
/* ── Tables ── */
|
||||||
|
.md-typeset table:not([class]) {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table:not([class]) th {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table:not([class]) td {
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
border-top: 1px solid var(--rb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table:not([class]) tbody tr:hover {
|
||||||
|
background: rgba(74, 78, 138, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] .md-typeset table:not([class]) tbody tr:hover {
|
||||||
|
background: rgba(99, 102, 160, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zebra striping */
|
||||||
|
.md-typeset table:not([class]) tbody tr:nth-child(even) {
|
||||||
|
background: rgba(0, 0, 0, 0.015);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-md-color-scheme="slate"] .md-typeset table:not([class]) tbody tr:nth-child(even) {
|
||||||
|
background: rgba(255, 255, 255, 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Platform cards (home page) ── */
|
||||||
|
.rb-platform-row td:first-child img {
|
||||||
|
vertical-align: middle;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Quick start grid ── */
|
||||||
|
.rb-quickstart {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-quickstart-item {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.8rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-quickstart-item code {
|
||||||
|
background: transparent;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--rb-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Section separators ── */
|
||||||
|
.rb-section {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
border-top: 1px solid var(--rb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Methodology steps ── */
|
||||||
|
.rb-methodology ol {
|
||||||
|
counter-reset: method-step;
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-methodology ol li {
|
||||||
|
counter-increment: method-step;
|
||||||
|
padding: 0.6rem 0 0.6rem 2.5rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-methodology ol li::before {
|
||||||
|
content: counter(method-step);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0.5rem;
|
||||||
|
width: 1.8rem;
|
||||||
|
height: 1.8rem;
|
||||||
|
background: var(--rb-primary);
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Classification badges (emulators) ── */
|
||||||
|
.rb-cls-official_port { border-left: 3px solid var(--rb-success); }
|
||||||
|
.rb-cls-community_fork { border-left: 3px solid var(--rb-info); }
|
||||||
|
.rb-cls-pure_libretro { border-left: 3px solid var(--rb-primary); }
|
||||||
|
.rb-cls-game_engine { border-left: 3px solid #7b1fa2; }
|
||||||
|
.rb-cls-enhanced_fork { border-left: 3px solid #00838f; }
|
||||||
|
.rb-cls-frozen_snapshot { border-left: 3px solid var(--rb-muted); }
|
||||||
|
.rb-cls-embedded_hle { border-left: 3px solid #4e342e; }
|
||||||
|
.rb-cls-launcher { border-left: 3px solid #37474f; }
|
||||||
|
|
||||||
|
/* ── Gap analysis priority markers ── */
|
||||||
|
.rb-gap-required {
|
||||||
|
color: var(--rb-danger);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-gap-optional {
|
||||||
|
color: var(--rb-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Scrollable table container improvements ── */
|
||||||
|
.md-typeset__scrollwrap {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Footer timestamp ── */
|
||||||
|
.rb-timestamp {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid var(--rb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Info card (platform/emulator metadata) ── */
|
||||||
|
.rb-info-card {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: 0.3rem 1.2rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-info-card dt {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-info-card dd {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── File entry cards (emulator detail) ── */
|
||||||
|
.rb-file-entry {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-entry-required {
|
||||||
|
border-left: 3px solid var(--rb-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-entry-optional {
|
||||||
|
border-left: 3px solid var(--rb-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-header code {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-entry ul {
|
||||||
|
margin: 0.3rem 0 0;
|
||||||
|
padding-left: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-file-entry li {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin: 0.15rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Hash display (truncated with tooltip) ── */
|
||||||
|
.rb-hash {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
cursor: help;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* System page file cards */
|
||||||
|
.rb-sys-file {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.8rem 1rem;
|
||||||
|
margin: 0.6rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-sys-file > p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-sys-file ul {
|
||||||
|
margin: 0.3rem 0 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-sys-file li {
|
||||||
|
margin: 0.1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emulator metadata card */
|
||||||
|
.rb-meta-card {
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.8rem 0;
|
||||||
|
margin: 1rem 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-meta-card table {
|
||||||
|
border: none !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-meta-card th {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-meta-card td:first-child {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--rb-text-secondary);
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 140px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-meta-card td {
|
||||||
|
border-top: 1px solid var(--rb-border) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-meta-card tr:first-child td {
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Platform detail: coverage bar ── */
|
||||||
|
.rb-coverage-bar {
|
||||||
|
background: var(--rb-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-coverage-fill {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--rb-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Emulator index: section accent ── */
|
||||||
|
.md-typeset h2 .rb-cls-dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 0.4rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-dot-official_port { background: var(--rb-success); }
|
||||||
|
.rb-dot-community_fork { background: var(--rb-info); }
|
||||||
|
.rb-dot-pure_libretro { background: var(--rb-primary); }
|
||||||
|
.rb-dot-game_engine { background: #7b1fa2; }
|
||||||
|
.rb-dot-enhanced_fork { background: #00838f; }
|
||||||
|
.rb-dot-frozen_snapshot { background: var(--rb-muted); }
|
||||||
|
.rb-dot-embedded_hle { background: #4e342e; }
|
||||||
|
.rb-dot-launcher { background: #37474f; }
|
||||||
|
.rb-dot-other { background: #9e9e9e; }
|
||||||
|
|
||||||
|
/* ── Cross-ref: classification in table ── */
|
||||||
|
.rb-cls-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0.1em 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--rb-surface);
|
||||||
|
border: 1px solid var(--rb-border);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Buttons ── */
|
||||||
|
.md-typeset .md-button {
|
||||||
|
border-radius: 6px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pack button in tables: smaller */
|
||||||
|
.md-typeset table .md-button {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 0.3em 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Hide permalink anchors in hero ── */
|
||||||
|
.rb-hero .headerlink {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Compact stat variant ── */
|
||||||
|
.rb-stats-compact {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stats-compact .rb-stat {
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stats-compact .rb-stat-value {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-stats-compact .rb-stat-label {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Responsive ── */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.rb-hero {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
.rb-hero h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
.rb-stats {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.rb-stat {
|
||||||
|
padding: 0.8rem;
|
||||||
|
}
|
||||||
|
.rb-stat .rb-stat-value {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
.rb-stat .rb-stat-label {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
.rb-file-entry {
|
||||||
|
padding: 0.7rem 0.8rem;
|
||||||
|
}
|
||||||
|
.rb-sys-file {
|
||||||
|
padding: 0.6rem 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.rb-stats {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
.rb-hero h1 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,10 +92,9 @@ files:
|
|||||||
note: "override_bios=1. Falls back to region BIOS if not found."
|
note: "override_bios=1. Falls back to region BIOS if not found."
|
||||||
|
|
||||||
- name: "ps1_rom.bin"
|
- name: "ps1_rom.bin"
|
||||||
description: "PS3 embedded PS1 BIOS (region-free override)"
|
description: "PS3 embedded PS1 BIOS, first 512KB extracted (region-free override)"
|
||||||
region: "Auto"
|
region: "Auto"
|
||||||
required: false
|
required: false
|
||||||
size: 524288
|
|
||||||
sha1: "c40146361eb8cf670b19fdc9759190257803cab7"
|
sha1: "c40146361eb8cf670b19fdc9759190257803cab7"
|
||||||
md5: "81bbe60ba7a3d1cea1d48c14cbcc647b"
|
md5: "81bbe60ba7a3d1cea1d48c14cbcc647b"
|
||||||
validation: [sha1]
|
validation: [sha1]
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0x66f334fe"
|
known_hash_adler32: "0x66f334fe"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP instruction ROM for LLE audio. Free replacement (v0.4) included"
|
note: "DSP instruction ROM for LLE audio. Free replacement (v0.4) included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:136, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:84-117"
|
source_ref: "Source/Core/Common/CommonPaths.h:136, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:84-117"
|
||||||
|
|
||||||
@@ -75,6 +76,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0xf3b93527"
|
known_hash_adler32: "0xf3b93527"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP coefficient ROM for LLE audio and HLE polyphase resampling. Free replacement included"
|
note: "DSP coefficient ROM for LLE audio and HLE polyphase resampling. Free replacement included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:137, Source/Core/Core/DSP/DSPCore.cpp:32-33, Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp:55-62"
|
source_ref: "Source/Core/Common/CommonPaths.h:137, Source/Core/Core/DSP/DSPCore.cpp:32-33, Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp:55-62"
|
||||||
|
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ files:
|
|||||||
- name: CARTS.CRC
|
- name: CARTS.CRC
|
||||||
required: false
|
required: false
|
||||||
bundled: false
|
bundled: false
|
||||||
|
unsourceable: "dead legacy code path, never created or distributed, replaced by CARTS.SHA"
|
||||||
note: "CRC database for cartridge identification and mapper detection. Tried first, before CARTS.SHA (fMSX/MSX.c:2697)."
|
note: "CRC database for cartridge identification and mapper detection. Tried first, before CARTS.SHA (fMSX/MSX.c:2697)."
|
||||||
|
|
||||||
- name: CARTS.SHA
|
- name: CARTS.SHA
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0x66f334fe"
|
known_hash_adler32: "0x66f334fe"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP instruction ROM for LLE audio. Free replacement included"
|
note: "DSP instruction ROM for LLE audio. Free replacement included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:112, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:142-150, Source/Core/Core/DSP/DSPCore.cpp:48,67"
|
source_ref: "Source/Core/Common/CommonPaths.h:112, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:142-150, Source/Core/Core/DSP/DSPCore.cpp:48,67"
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0xf3b93527"
|
known_hash_adler32: "0xf3b93527"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP coefficient ROM for LLE audio and HLE polyphase resampling. Free replacement included"
|
note: "DSP coefficient ROM for LLE audio and HLE polyphase resampling. Free replacement included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:113, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:143-153, Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp:43-72, Source/Core/Core/DSP/DSPCore.cpp:48,68"
|
source_ref: "Source/Core/Common/CommonPaths.h:113, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:143-153, Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp:43-72, Source/Core/Core/DSP/DSPCore.cpp:48,68"
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ files:
|
|||||||
path: "np2kai/gpib.rom"
|
path: "np2kai/gpib.rom"
|
||||||
size: 8192
|
size: 8192
|
||||||
required: false
|
required: false
|
||||||
|
unsourceable: "never publicly dumped, GP-IB emulation is stub code (source comment: not implemented)"
|
||||||
note: >
|
note: >
|
||||||
GP-IB interface BIOS ROM (8 KB). If missing, GP-IB emulation
|
GP-IB interface BIOS ROM (8 KB). If missing, GP-IB emulation
|
||||||
is disabled entirely.
|
is disabled entirely.
|
||||||
@@ -198,6 +199,8 @@ files:
|
|||||||
- name: "key.txt"
|
- name: "key.txt"
|
||||||
path: "np2kai/key.txt"
|
path: "np2kai/key.txt"
|
||||||
required: false
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
unsourceable: "user-created keyboard config, no default distributed in any NP2kai release"
|
||||||
note: >
|
note: >
|
||||||
Keyboard remapping configuration (text file). User-created file
|
Keyboard remapping configuration (text file). User-created file
|
||||||
for custom keyboard layout. The core uses built-in defaults if absent.
|
for custom keyboard layout. The core uses built-in defaults if absent.
|
||||||
|
|||||||
@@ -81,5 +81,6 @@ files:
|
|||||||
system: cave-story
|
system: cave-story
|
||||||
description: "Tile attribute lookup table (maps tile codes to collision/behavior attributes)"
|
description: "Tile attribute lookup table (maps tile codes to collision/behavior attributes)"
|
||||||
required: false
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
source_ref: "map.cpp:290-303 (loaded at init, hardcoded default if missing)"
|
source_ref: "map.cpp:290-303 (loaded at init, hardcoded default if missing)"
|
||||||
note: "Not part of the freeware distribution. Generated by the standalone NXEngine extraction tool. The libretro core has hardcoded defaults in map.cpp:30."
|
note: "Not part of the freeware distribution. Generated by the standalone NXEngine extraction tool. The libretro core has hardcoded defaults in map.cpp:30."
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0x66f334fe"
|
known_hash_adler32: "0x66f334fe"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP instruction ROM for LLE audio. Free replacement (v0.4) included"
|
note: "DSP instruction ROM for LLE audio. Free replacement (v0.4) included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:135, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:87-117"
|
source_ref: "Source/Core/Common/CommonPaths.h:135, Source/Core/Core/HW/DSPLLE/DSPLLE.cpp:87-117"
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ files:
|
|||||||
hle_fallback: true
|
hle_fallback: true
|
||||||
validation: [size]
|
validation: [size]
|
||||||
known_hash_adler32: "0xf3b93527"
|
known_hash_adler32: "0xf3b93527"
|
||||||
|
adler32_byteswap: true
|
||||||
note: "DSP coefficient ROM for LLE audio. Free replacement included"
|
note: "DSP coefficient ROM for LLE audio. Free replacement included"
|
||||||
source_ref: "Source/Core/Common/CommonPaths.h:136, Source/Core/Core/DSP/DSPCore.cpp:32-38"
|
source_ref: "Source/Core/Common/CommonPaths.h:136, Source/Core/Core/DSP/DSPCore.cpp:32-38"
|
||||||
|
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ files:
|
|||||||
- name: "WHDLoad.key"
|
- name: "WHDLoad.key"
|
||||||
system: commodore-amiga
|
system: commodore-amiga
|
||||||
required: false
|
required: false
|
||||||
|
unsourceable: "per-user signed registration key, never distributed generically, WHDLoad free since v18.2"
|
||||||
note: "WHDLoad license key. Copied to saves/WHDLoad/L/ for registered WHDLoad use."
|
note: "WHDLoad license key. Copied to saves/WHDLoad/L/ for registered WHDLoad use."
|
||||||
source_ref: "libretro/libretro-core.c:5985-5998"
|
source_ref: "libretro/libretro-core.c:5985-5998"
|
||||||
|
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ files:
|
|||||||
- name: "WHDLoad.key"
|
- name: "WHDLoad.key"
|
||||||
system: commodore-amiga
|
system: commodore-amiga
|
||||||
required: false
|
required: false
|
||||||
|
unsourceable: "per-user signed registration key, never distributed generically, WHDLoad free since v18.2"
|
||||||
note: "WHDLoad license key. Copied to saves/WHDLoad/L/ for registered WHDLoad use."
|
note: "WHDLoad license key. Copied to saves/WHDLoad/L/ for registered WHDLoad use."
|
||||||
source_ref: "libretro/libretro-core.c:5903-5916"
|
source_ref: "libretro/libretro-core.c:5903-5916"
|
||||||
|
|
||||||
|
|||||||
@@ -70,11 +70,12 @@ files:
|
|||||||
aliases: []
|
aliases: []
|
||||||
|
|
||||||
- name: "ps1_rom.bin"
|
- name: "ps1_rom.bin"
|
||||||
description: "PS3 (v5.0 06-23-03 A)"
|
description: "PS3 embedded PS1 BIOS (v5.0 06-23-03 A)"
|
||||||
region: "Auto"
|
region: "Auto"
|
||||||
required: false
|
required: false
|
||||||
md5: "81bbe60ba7a3d1cea1d48c14cbcc647b"
|
md5: "81bbe60ba7a3d1cea1d48c14cbcc647b"
|
||||||
size: 4089584
|
size: [524288, 4194304, 4089584]
|
||||||
validation: [size, md5]
|
validation: [size, md5]
|
||||||
source_ref: "src/core/bios.cpp:70"
|
note: "Accepts PS1 (512KB), PS2 (4MB), and PS3 (0x3E66F0) sizes. Only first 512KB used."
|
||||||
|
source_ref: "src/core/bios.h:9, src/core/bios.cpp:70,83"
|
||||||
aliases: []
|
aliases: []
|
||||||
|
|||||||
@@ -397,5 +397,6 @@ files:
|
|||||||
system: dragon64
|
system: dragon64
|
||||||
description: "Ikon Ultra Drive Dragonfly ROM 2.3"
|
description: "Ikon Ultra Drive Dragonfly ROM 2.3"
|
||||||
required: false
|
required: false
|
||||||
|
unsourceable: "not yet dumped, only v1.3 publicly available, XRoar support is experimental (#ifdef WANT_EXPERIMENTAL)"
|
||||||
source_ref: "xroar.c:715 (romlist ikon), ikon.c:151 (default @ikon)"
|
source_ref: "xroar.c:715 (romlist ikon), ikon.c:151 (default @ikon)"
|
||||||
note: "Experimental. Ikon Ultra Drive storage interface. Older version: dragonfly-1.3."
|
note: "Experimental. Ikon Ultra Drive storage interface. Older version: dragonfly-1.3."
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ files:
|
|||||||
|
|
||||||
- name: Custom.dat
|
- name: Custom.dat
|
||||||
path: zc210/sfx/Custom.dat
|
path: zc210/sfx/Custom.dat
|
||||||
|
category: game_data
|
||||||
description: user-provided custom SFX replacement
|
description: user-provided custom SFX replacement
|
||||||
required: false
|
required: false
|
||||||
|
unsourceable: "user placeholder slot, README says 'rename your own SFX dat file to this name'"
|
||||||
source_ref: "zelda.cpp:1193-1218, libretro.cpp:148"
|
source_ref: "zelda.cpp:1193-1218, libretro.cpp:148"
|
||||||
|
|||||||
46
install.ps1
46
install.ps1
@@ -101,4 +101,50 @@ foreach ($f in $toDownload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Standalone emulator copies
|
||||||
|
if ($manifest.standalone_copies) {
|
||||||
|
Write-Host "`nStandalone emulators:"
|
||||||
|
foreach ($entry in $manifest.standalone_copies) {
|
||||||
|
if ($entry.note) {
|
||||||
|
$detectPaths = @()
|
||||||
|
if ($entry.detect -and $entry.detect.windows) {
|
||||||
|
$detectPaths = $entry.detect.windows
|
||||||
|
}
|
||||||
|
foreach ($dp in $detectPaths) {
|
||||||
|
$expanded = [Environment]::ExpandEnvironmentVariables($dp)
|
||||||
|
if (Test-Path $expanded) {
|
||||||
|
Write-Host " $($entry.note)"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$sources = @()
|
||||||
|
if ($entry.pattern) {
|
||||||
|
$sources = Get-ChildItem -Path $biosPath -Filter $entry.pattern -File -ErrorAction SilentlyContinue
|
||||||
|
} elseif ($entry.file) {
|
||||||
|
$src = Join-Path $biosPath $entry.file
|
||||||
|
if (Test-Path $src) { $sources = @(Get-Item $src) }
|
||||||
|
}
|
||||||
|
if ($sources.Count -eq 0) { continue }
|
||||||
|
$targetDirs = @()
|
||||||
|
if ($entry.targets -and $entry.targets.windows) {
|
||||||
|
$targetDirs = $entry.targets.windows
|
||||||
|
}
|
||||||
|
foreach ($td in $targetDirs) {
|
||||||
|
$expanded = [Environment]::ExpandEnvironmentVariables($td)
|
||||||
|
if (-not (Test-Path $expanded)) { continue }
|
||||||
|
foreach ($s in $sources) {
|
||||||
|
$dest = Join-Path $expanded $s.Name
|
||||||
|
try {
|
||||||
|
Copy-Item $s.FullName $dest -Force
|
||||||
|
Write-Host " $($s.Name) -> $expanded"
|
||||||
|
} catch {
|
||||||
|
Write-Host " $($s.Name) -> $expanded FAILED" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "`nDone. $downloaded downloaded, $upToDate already up to date."
|
Write-Host "`nDone. $downloaded downloaded, $upToDate already up to date."
|
||||||
|
|||||||
49
install.py
49
install.py
@@ -192,9 +192,9 @@ def detect_platforms(os_type: str) -> list[tuple[str, Path]]:
|
|||||||
if retrodeck_cfg.exists():
|
if retrodeck_cfg.exists():
|
||||||
bios_path = _parse_bash_var(retrodeck_cfg, "rdhome")
|
bios_path = _parse_bash_var(retrodeck_cfg, "rdhome")
|
||||||
if bios_path:
|
if bios_path:
|
||||||
found.append(("retrodeck", Path(bios_path) / "bios"))
|
found.append(("retrodeck", Path(bios_path)))
|
||||||
else:
|
else:
|
||||||
found.append(("retrodeck", home / "retrodeck" / "bios"))
|
found.append(("retrodeck", home / "retrodeck"))
|
||||||
|
|
||||||
# RetroArch Flatpak
|
# RetroArch Flatpak
|
||||||
flatpak_cfg = home / ".var" / "app" / "org.libretro.RetroArch" / "config" / "retroarch" / "retroarch.cfg"
|
flatpak_cfg = home / ".var" / "app" / "org.libretro.RetroArch" / "config" / "retroarch" / "retroarch.cfg"
|
||||||
@@ -390,8 +390,16 @@ def do_standalone_copies(
|
|||||||
) -> tuple[int, int]:
|
) -> tuple[int, int]:
|
||||||
"""Copy BIOS files to standalone emulator directories.
|
"""Copy BIOS files to standalone emulator directories.
|
||||||
|
|
||||||
|
Supports:
|
||||||
|
- file: single file copy
|
||||||
|
- pattern: glob match (e.g. "scph*.bin")
|
||||||
|
- note: informational message when detect path exists
|
||||||
|
- WSL fallback to linux targets
|
||||||
|
|
||||||
Returns (copied_count, skipped_count).
|
Returns (copied_count, skipped_count).
|
||||||
"""
|
"""
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
copies = manifest.get("standalone_copies", [])
|
copies = manifest.get("standalone_copies", [])
|
||||||
if not copies:
|
if not copies:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
@@ -400,21 +408,48 @@ def do_standalone_copies(
|
|||||||
skipped = 0
|
skipped = 0
|
||||||
|
|
||||||
for entry in copies:
|
for entry in copies:
|
||||||
src = bios_path / entry["file"]
|
# Note entries: print message if emulator detected
|
||||||
if not src.exists():
|
if "note" in entry:
|
||||||
|
detect_paths = entry.get("detect", {}).get(os_type, [])
|
||||||
|
if not detect_paths and os_type == "wsl":
|
||||||
|
detect_paths = entry.get("detect", {}).get("linux", [])
|
||||||
|
for dp in detect_paths:
|
||||||
|
expanded = Path(os.path.expandvars(os.path.expanduser(dp)))
|
||||||
|
if expanded.is_dir():
|
||||||
|
print(f" {entry['note']}")
|
||||||
|
break
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Resolve source files
|
||||||
|
if "pattern" in entry:
|
||||||
|
sources = [
|
||||||
|
f for f in bios_path.rglob("*")
|
||||||
|
if fnmatch(f.name, entry["pattern"]) and f.is_file()
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
src = bios_path / entry["file"]
|
||||||
|
sources = [src] if src.exists() else []
|
||||||
|
|
||||||
|
if not sources:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Resolve target directories with WSL fallback
|
||||||
targets = entry.get("targets", {}).get(os_type, [])
|
targets = entry.get("targets", {}).get(os_type, [])
|
||||||
|
if not targets and os_type == "wsl":
|
||||||
|
targets = entry.get("targets", {}).get("linux", [])
|
||||||
|
|
||||||
for target_dir_str in targets:
|
for target_dir_str in targets:
|
||||||
target_dir = Path(os.path.expandvars(os.path.expanduser(target_dir_str)))
|
target_dir = Path(os.path.expandvars(os.path.expanduser(target_dir_str)))
|
||||||
if target_dir.is_dir():
|
if not target_dir.is_dir():
|
||||||
|
skipped += len(sources)
|
||||||
|
continue
|
||||||
|
for src in sources:
|
||||||
dest = target_dir / src.name
|
dest = target_dir / src.name
|
||||||
try:
|
try:
|
||||||
shutil.copy2(src, dest)
|
shutil.copy2(src, dest)
|
||||||
copied += 1
|
copied += 1
|
||||||
except OSError:
|
except OSError:
|
||||||
skipped += 1
|
skipped += 1
|
||||||
else:
|
|
||||||
skipped += 1
|
|
||||||
|
|
||||||
return copied, skipped
|
return copied, skipped
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "batocera",
|
"platform": "batocera",
|
||||||
"display_name": "Batocera",
|
"display_name": "Batocera",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:41:41Z",
|
"generated": "2026-04-03T09:43:11Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -14,9 +14,224 @@
|
|||||||
"bios_path": "/userdata/bios"
|
"bios_path": "/userdata/bios"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [
|
||||||
"total_files": 1540,
|
{
|
||||||
"total_size": 3891615271,
|
"file": "prod.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
|
"$HOME/.config/Ryujinx/system"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "title.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_files": 1547,
|
||||||
|
"total_size": 4371484317,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "panafz1.bin",
|
"dest": "panafz1.bin",
|
||||||
@@ -2904,6 +3119,15 @@
|
|||||||
"blueMSX"
|
"blueMSX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": [
|
||||||
|
"blueMSX"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
||||||
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
||||||
@@ -6148,6 +6372,39 @@
|
|||||||
"FinalBurn Neo"
|
"FinalBurn Neo"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "gamegenie.nes",
|
"dest": "gamegenie.nes",
|
||||||
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
||||||
@@ -8389,6 +8646,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "NMS8245SystemROM1.08.bin",
|
"dest": "NMS8245SystemROM1.08.bin",
|
||||||
"sha1": "cc57c1dcd7249ea9f8e2547244592e7d97308ed0",
|
"sha1": "cc57c1dcd7249ea9f8e2547244592e7d97308ed0",
|
||||||
@@ -10657,6 +10932,15 @@
|
|||||||
"XRoar"
|
"XRoar"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "delta2.rom",
|
||||||
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
|
"size": 8192,
|
||||||
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
|
"cores": [
|
||||||
|
"XRoar"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "cp450dsk.rom",
|
"dest": "cp450dsk.rom",
|
||||||
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "bizhawk",
|
"platform": "bizhawk",
|
||||||
"display_name": "BizHawk",
|
"display_name": "BizHawk",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:00:10Z",
|
"generated": "2026-04-02T13:52:21Z",
|
||||||
"base_destination": "Firmware",
|
"base_destination": "Firmware",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [],
|
||||||
"total_files": 527,
|
"total_files": 530,
|
||||||
"total_size": 2068127713,
|
"total_size": 2547895289,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "panafz1.bin",
|
"dest": "panafz1.bin",
|
||||||
@@ -1274,6 +1274,39 @@
|
|||||||
"FinalBurn Neo"
|
"FinalBurn Neo"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "sl31253.bin",
|
"dest": "sl31253.bin",
|
||||||
"sha1": "81193965a374d77b99b4743d317824b53c3e3c78",
|
"sha1": "81193965a374d77b99b4743d317824b53c3e3c78",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "emudeck",
|
"platform": "emudeck",
|
||||||
"display_name": "EmuDeck",
|
"display_name": "EmuDeck",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:41:53Z",
|
"generated": "2026-04-03T09:43:22Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -34,19 +34,211 @@
|
|||||||
"linux": [
|
"linux": [
|
||||||
"$HOME/.local/share/yuzu/keys",
|
"$HOME/.local/share/yuzu/keys",
|
||||||
"$HOME/.local/share/eden/keys",
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
"$HOME/.config/Ryujinx/system"
|
"$HOME/.config/Ryujinx/system"
|
||||||
],
|
],
|
||||||
"windows": [
|
"windows": [
|
||||||
"%APPDATA%\\yuzu\\keys",
|
"%APPDATA%\\yuzu\\keys",
|
||||||
"%APPDATA%\\eden\\keys"
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "aes_keys.txt",
|
"file": "title.keys",
|
||||||
"targets": {
|
"targets": {
|
||||||
"linux": [
|
"linux": [
|
||||||
"$HOME/Emulation/bios/citra/keys"
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "lakka",
|
"platform": "lakka",
|
||||||
"display_name": "Lakka",
|
"display_name": "Lakka",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:42:08Z",
|
"generated": "2026-04-02T13:52:45Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [],
|
||||||
"total_files": 1620,
|
"total_files": 1627,
|
||||||
"total_size": 5255358024,
|
"total_size": 5735234905,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "3do_arcade_saot.bin",
|
"dest": "3do_arcade_saot.bin",
|
||||||
@@ -3438,6 +3438,15 @@
|
|||||||
"blueMSX"
|
"blueMSX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": [
|
||||||
|
"blueMSX"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
||||||
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
||||||
@@ -5070,6 +5079,39 @@
|
|||||||
"storage": "release",
|
"storage": "release",
|
||||||
"release_asset": "vimana.zip"
|
"release_asset": "vimana.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "nes.pal",
|
"dest": "nes.pal",
|
||||||
"sha1": "37027d92e1015b82a7dc5c43e9f1649a961577ab",
|
"sha1": "37027d92e1015b82a7dc5c43e9f1649a961577ab",
|
||||||
@@ -7862,6 +7904,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "mda.rom",
|
"dest": "mda.rom",
|
||||||
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
||||||
@@ -9650,6 +9710,15 @@
|
|||||||
"SameBoy"
|
"SameBoy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "sdlpal/desc.dat",
|
||||||
|
"sha1": "8c20ff26ebfefbf9b050b67af8083704003595ba",
|
||||||
|
"size": 16027,
|
||||||
|
"repo_path": "bios/sdlpal/desc.dat",
|
||||||
|
"cores": [
|
||||||
|
"SDLPAL"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "SkyEmu/dmg_rom.bin",
|
"dest": "SkyEmu/dmg_rom.bin",
|
||||||
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "recalbox",
|
"platform": "recalbox",
|
||||||
"display_name": "Recalbox",
|
"display_name": "Recalbox",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:42:39Z",
|
"generated": "2026-04-03T09:44:06Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -14,9 +14,224 @@
|
|||||||
"bios_path": "/recalbox/share/bios"
|
"bios_path": "/recalbox/share/bios"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [
|
||||||
"total_files": 1097,
|
{
|
||||||
"total_size": 3500142330,
|
"file": "prod.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
|
"$HOME/.config/Ryujinx/system"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "title.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_files": 1107,
|
||||||
|
"total_size": 3980096655,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "3do/panafz1.bin",
|
"dest": "3do/panafz1.bin",
|
||||||
@@ -540,7 +755,7 @@
|
|||||||
"dest": "dragon/deltados.rom",
|
"dest": "dragon/deltados.rom",
|
||||||
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
"size": 8192,
|
"size": 8192,
|
||||||
"repo_path": "bios/Dragon/Dragon/deltados.rom",
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
"cores": null
|
"cores": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -851,6 +1066,13 @@
|
|||||||
"repo_path": "bios/Microsoft/MSX/MSX2EXT.ROM",
|
"repo_path": "bios/Microsoft/MSX/MSX2EXT.ROM",
|
||||||
"cores": null
|
"cores": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2P.rom",
|
"dest": "Machines/Shared Roms/MSX2P.rom",
|
||||||
"sha1": "e90f80a61d94c617850c415e12ad70ac41e66bb7",
|
"sha1": "e90f80a61d94c617850c415e12ad70ac41e66bb7",
|
||||||
@@ -3797,6 +4019,39 @@
|
|||||||
"FinalBurn Neo"
|
"FinalBurn Neo"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "gamegenie.nes",
|
"dest": "gamegenie.nes",
|
||||||
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
||||||
@@ -6452,6 +6707,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "64DD_IPL.bin",
|
"dest": "64DD_IPL.bin",
|
||||||
"sha1": "bf861922dcb78c316360e3e742f4f70ff63c9bc3",
|
"sha1": "bf861922dcb78c316360e3e742f4f70ff63c9bc3",
|
||||||
@@ -6821,6 +7094,33 @@
|
|||||||
"Stella 2023"
|
"Stella 2023"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Gram Kracker.ctg",
|
||||||
|
"sha1": "56dd520570cdcdd60dda2eedc8af1e02a781dcc5",
|
||||||
|
"size": 7587,
|
||||||
|
"repo_path": "bios/Texas Instruments/TI-99/Gram Kracker.ctg",
|
||||||
|
"cores": [
|
||||||
|
"ti99sim"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "ti-pcard.ctg",
|
||||||
|
"sha1": "c7bf5fcfea0502011dca76d12efcc242e23421b9",
|
||||||
|
"size": 71924,
|
||||||
|
"repo_path": "bios/Texas Instruments/TI-99/ti-pcard.ctg",
|
||||||
|
"cores": [
|
||||||
|
"ti99sim"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "cf7+.ctg",
|
||||||
|
"sha1": "698c638e1773244a6bf8a353c87d210047cce402",
|
||||||
|
"size": 5768,
|
||||||
|
"repo_path": "bios/Texas Instruments/TI-99/cf7+.ctg",
|
||||||
|
"cores": [
|
||||||
|
"ti99sim"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "JiffyDOS_SX-64.bin",
|
"dest": "JiffyDOS_SX-64.bin",
|
||||||
"sha1": "942c2150123dc30f40b3df6086132ef0a3c43948",
|
"sha1": "942c2150123dc30f40b3df6086132ef0a3c43948",
|
||||||
@@ -7046,6 +7346,15 @@
|
|||||||
"XRoar"
|
"XRoar"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "delta2.rom",
|
||||||
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
|
"size": 8192,
|
||||||
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
|
"cores": [
|
||||||
|
"XRoar"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "cp450dsk.rom",
|
"dest": "cp450dsk.rom",
|
||||||
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "retroarch",
|
"platform": "retroarch",
|
||||||
"display_name": "RetroArch",
|
"display_name": "RetroArch",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:42:08Z",
|
"generated": "2026-04-03T09:43:38Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -32,9 +32,224 @@
|
|||||||
"parse_key": "system_directory"
|
"parse_key": "system_directory"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [
|
||||||
"total_files": 1620,
|
{
|
||||||
"total_size": 5255358024,
|
"file": "prod.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
|
"$HOME/.config/Ryujinx/system"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "title.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_files": 1627,
|
||||||
|
"total_size": 5735234905,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "3do_arcade_saot.bin",
|
"dest": "3do_arcade_saot.bin",
|
||||||
@@ -3456,6 +3671,15 @@
|
|||||||
"blueMSX"
|
"blueMSX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": [
|
||||||
|
"blueMSX"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
||||||
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
||||||
@@ -5088,6 +5312,39 @@
|
|||||||
"storage": "release",
|
"storage": "release",
|
||||||
"release_asset": "vimana.zip"
|
"release_asset": "vimana.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "nes.pal",
|
"dest": "nes.pal",
|
||||||
"sha1": "37027d92e1015b82a7dc5c43e9f1649a961577ab",
|
"sha1": "37027d92e1015b82a7dc5c43e9f1649a961577ab",
|
||||||
@@ -7880,6 +8137,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "mda.rom",
|
"dest": "mda.rom",
|
||||||
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
||||||
@@ -9668,6 +9943,15 @@
|
|||||||
"SameBoy"
|
"SameBoy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "sdlpal/desc.dat",
|
||||||
|
"sha1": "8c20ff26ebfefbf9b050b67af8083704003595ba",
|
||||||
|
"size": 16027,
|
||||||
|
"repo_path": "bios/sdlpal/desc.dat",
|
||||||
|
"cores": [
|
||||||
|
"SDLPAL"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "SkyEmu/dmg_rom.bin",
|
"dest": "SkyEmu/dmg_rom.bin",
|
||||||
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "retrobat",
|
"platform": "retrobat",
|
||||||
"display_name": "RetroBat",
|
"display_name": "RetroBat",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:42:50Z",
|
"generated": "2026-04-03T09:44:16Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -13,9 +13,224 @@
|
|||||||
"path": "%USERPROFILE%\\RetroBat\\bios"
|
"path": "%USERPROFILE%\\RetroBat\\bios"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [
|
||||||
"total_files": 1162,
|
{
|
||||||
"total_size": 4297772175,
|
"file": "prod.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
|
"$HOME/.config/Ryujinx/system"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "title.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_files": 1169,
|
||||||
|
"total_size": 4777641221,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "panafz1.bin",
|
"dest": "panafz1.bin",
|
||||||
@@ -2525,6 +2740,15 @@
|
|||||||
"blueMSX"
|
"blueMSX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": [
|
||||||
|
"blueMSX"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
||||||
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
||||||
@@ -3968,6 +4192,39 @@
|
|||||||
"storage": "release",
|
"storage": "release",
|
||||||
"release_asset": "vimana.zip"
|
"release_asset": "vimana.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "gamegenie.nes",
|
"dest": "gamegenie.nes",
|
||||||
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
||||||
@@ -6191,6 +6448,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "panafz1j.bin",
|
"dest": "panafz1j.bin",
|
||||||
"sha1": "ec7ec62d60ec0459a14ed56ebc66761ef3c80efc",
|
"sha1": "ec7ec62d60ec0459a14ed56ebc66761ef3c80efc",
|
||||||
@@ -7439,6 +7714,15 @@
|
|||||||
"XRoar"
|
"XRoar"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "delta2.rom",
|
||||||
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
|
"size": 8192,
|
||||||
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
|
"cores": [
|
||||||
|
"XRoar"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "cp450dsk.rom",
|
"dest": "cp450dsk.rom",
|
||||||
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
||||||
|
|||||||
@@ -4,19 +4,234 @@
|
|||||||
"platform": "retrodeck",
|
"platform": "retrodeck",
|
||||||
"display_name": "RetroDECK",
|
"display_name": "RetroDECK",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:43:08Z",
|
"generated": "2026-04-03T09:44:33Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"method": "path_exists",
|
"method": "path_exists",
|
||||||
"path": "$HOME/.var/app/net.retrodeck.retrodeck",
|
"path": "$HOME/.var/app/net.retrodeck.retrodeck",
|
||||||
"bios_path": "$HOME/retrodeck/bios"
|
"bios_path": "$HOME/retrodeck"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [
|
||||||
"total_files": 3144,
|
{
|
||||||
"total_size": 5871582893,
|
"file": "prod.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys",
|
||||||
|
"$HOME/.config/Ryujinx/system"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys",
|
||||||
|
"%APPDATA%\\Ryujinx\\system"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys",
|
||||||
|
"$HOME/Library/Application Support/Ryujinx/system"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "title.keys",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/yuzu/keys",
|
||||||
|
"$HOME/.local/share/eden/keys",
|
||||||
|
"$HOME/.local/share/citron/keys",
|
||||||
|
"$HOME/.local/share/suyu/keys"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\yuzu\\keys",
|
||||||
|
"%APPDATA%\\eden\\keys",
|
||||||
|
"%APPDATA%\\citron\\keys",
|
||||||
|
"%APPDATA%\\suyu\\keys"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/yuzu/keys"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/aes_keys.txt",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "Citra/sysdata/boot9.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/azahar/sysdata"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Azahar\\sysdata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "scph*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/duckstation/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%LOCALAPPDATA%\\DuckStation\\bios",
|
||||||
|
"%USERPROFILE%\\Documents\\DuckStation\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/DuckStation/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "ps2-*.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/PCSX2/bios",
|
||||||
|
"$HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PCSX2\\bios"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PCSX2/bios"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.",
|
||||||
|
"detect": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/rpcs3"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\rpcs3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/USA/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/USA"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\USA"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/USA"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/EUR/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/EUR"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\EUR"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/EUR"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "GC/JAP/IPL.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu/GC/JAP"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator\\GC\\JAP"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin/GC/JAP"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_rom.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dsp_coef.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/dolphin-emu"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\Dolphin Emulator"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/Dolphin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "PPSSPP/ppge_atlas.zim",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.config/ppsspp/PSP/SYSTEM"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%USERPROFILE%\\Documents\\PPSSPP\\PSP\\SYSTEM"
|
||||||
|
],
|
||||||
|
"darwin": [
|
||||||
|
"$HOME/Library/Application Support/PPSSPP/PSP/SYSTEM"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_boot.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "dc/dc_nvmem.bin",
|
||||||
|
"targets": {
|
||||||
|
"linux": [
|
||||||
|
"$HOME/.local/share/flycast/data",
|
||||||
|
"$HOME/.var/app/org.flycast.Flycast/data/flycast"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"%APPDATA%\\flycast\\data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_files": 3153,
|
||||||
|
"total_size": 6351500734,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "bios/panafz1.bin",
|
"dest": "bios/panafz1.bin",
|
||||||
@@ -11082,7 +11297,7 @@
|
|||||||
"dest": "bios/deltados.rom",
|
"dest": "bios/deltados.rom",
|
||||||
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
"size": 8192,
|
"size": 8192,
|
||||||
"repo_path": "bios/Dragon/Dragon/deltados.rom",
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
"cores": null
|
"cores": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -11477,6 +11692,13 @@
|
|||||||
"repo_path": "bios/Microsoft/MSX/openmsx/yrw801.rom",
|
"repo_path": "bios/Microsoft/MSX/openmsx/yrw801.rom",
|
||||||
"cores": null
|
"cores": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "bios/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "bios/MSX2R2.ROM",
|
"dest": "bios/MSX2R2.ROM",
|
||||||
"sha1": "04990aa1c3a3fc7294ec884b81deaa89832df614",
|
"sha1": "04990aa1c3a3fc7294ec884b81deaa89832df614",
|
||||||
@@ -16290,6 +16512,39 @@
|
|||||||
"storage": "release",
|
"storage": "release",
|
||||||
"release_asset": "vimana.zip"
|
"release_asset": "vimana.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "gamegenie.nes",
|
"dest": "gamegenie.nes",
|
||||||
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
||||||
@@ -18256,6 +18511,24 @@
|
|||||||
"NXEngine"
|
"NXEngine"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/data/sprites.sif",
|
||||||
|
"sha1": "73acccee601b56a2b7f624b0227fa7e1d662ef4b",
|
||||||
|
"size": 59482,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/data/sprites.sif",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "nxengine/tilekey.dat",
|
||||||
|
"sha1": "74c14b15dbc2f36c81d2ad9cb65e2893298415da",
|
||||||
|
"size": 1028,
|
||||||
|
"repo_path": "bios/Other/NXEngine/nxengine/tilekey.dat",
|
||||||
|
"cores": [
|
||||||
|
"NXEngine"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "mda.rom",
|
"dest": "mda.rom",
|
||||||
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
"sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f",
|
||||||
@@ -20037,6 +20310,15 @@
|
|||||||
"SameBoy"
|
"SameBoy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "sdlpal/desc.dat",
|
||||||
|
"sha1": "8c20ff26ebfefbf9b050b67af8083704003595ba",
|
||||||
|
"size": 16027,
|
||||||
|
"repo_path": "bios/sdlpal/desc.dat",
|
||||||
|
"cores": [
|
||||||
|
"SDLPAL"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "SkyEmu/dmg_rom.bin",
|
"dest": "SkyEmu/dmg_rom.bin",
|
||||||
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
"sha1": "4ed31ec6b0b175bb109c0eb5fd3d193da823339f",
|
||||||
@@ -21733,6 +22015,15 @@
|
|||||||
"XRoar"
|
"XRoar"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "delta2.rom",
|
||||||
|
"sha1": "686ebb5f39dd4fc907a0b748867d0a022d2f1a60",
|
||||||
|
"size": 8192,
|
||||||
|
"repo_path": "bios/Dragon/Dragon/delta2.rom",
|
||||||
|
"cores": [
|
||||||
|
"XRoar"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "cp450dsk.rom",
|
"dest": "cp450dsk.rom",
|
||||||
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
"sha1": "827697fa5b755f5dc1efb054cdbbeb04e405405b",
|
||||||
@@ -22300,6 +22591,15 @@
|
|||||||
"blueMSX"
|
"blueMSX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "Machines/Shared Roms/MSX2J.rom",
|
||||||
|
"sha1": "0081ea0d25bc5cd8d70b60ad8cfdc7307812c0fd",
|
||||||
|
"size": 32768,
|
||||||
|
"repo_path": "bios/Microsoft/MSX/.variants/MSX2.ROM.0081ea0d",
|
||||||
|
"cores": [
|
||||||
|
"blueMSX"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
"dest": "Machines/Shared Roms/MSX2R2.ROM",
|
||||||
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
"sha1": "ebb7eb540a390509edfd36c84288ba85e63f2d1f",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"platform": "romm",
|
"platform": "romm",
|
||||||
"display_name": "RomM",
|
"display_name": "RomM",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"generated": "2026-04-01T14:43:09Z",
|
"generated": "2026-04-02T13:53:45Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standalone_copies": [],
|
"standalone_copies": [],
|
||||||
"total_files": 535,
|
"total_files": 538,
|
||||||
"total_size": 1076531155,
|
"total_size": 1556298731,
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"dest": "3do/3do_arcade_saot.bin",
|
"dest": "3do/3do_arcade_saot.bin",
|
||||||
@@ -2796,6 +2796,39 @@
|
|||||||
"ep128emu-core"
|
"ep128emu-core"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dest": "colecovision/fbneo/samples/donpachi.zip",
|
||||||
|
"sha1": "d380fb29287eb7fc9ff901a7653ad40785f7deb1",
|
||||||
|
"size": 208549253,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "donpachi.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "colecovision/fbneo/samples/sfz3mix.zip",
|
||||||
|
"sha1": "937cdc6ccf9de418b94d8b762aad36822f857ec9",
|
||||||
|
"size": 116329446,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "sfz3mix.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dest": "colecovision/fbneo/samples/twotiger.zip",
|
||||||
|
"sha1": "74399cc36d97e9f74b387b87900505ebbf260ca9",
|
||||||
|
"size": 154888877,
|
||||||
|
"repo_path": "",
|
||||||
|
"cores": [
|
||||||
|
"FinalBurn Neo"
|
||||||
|
],
|
||||||
|
"storage": "release",
|
||||||
|
"release_asset": "twotiger.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dest": "fds/gamegenie.nes",
|
"dest": "fds/gamegenie.nes",
|
||||||
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
"sha1": "f430a0d752a9fa0c7032db8131f9090d18f71779",
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ theme:
|
|||||||
icon: material/brightness-4
|
icon: material/brightness-4
|
||||||
name: Switch to auto
|
name: Switch to auto
|
||||||
font: false
|
font: false
|
||||||
|
logo: assets/images/logo.png
|
||||||
|
favicon: assets/images/favicon.png
|
||||||
|
icon:
|
||||||
|
logo: material/chip
|
||||||
features:
|
features:
|
||||||
- navigation.tabs
|
- navigation.tabs
|
||||||
- navigation.sections
|
- navigation.sections
|
||||||
@@ -29,6 +33,8 @@ theme:
|
|||||||
- search.highlight
|
- search.highlight
|
||||||
- content.tabs.link
|
- content.tabs.link
|
||||||
- toc.follow
|
- toc.follow
|
||||||
|
extra_css:
|
||||||
|
- stylesheets/extra.css
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- tables
|
- tables
|
||||||
- admonition
|
- admonition
|
||||||
@@ -48,6 +54,7 @@ plugins:
|
|||||||
- search
|
- search
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
|
- Which pack?: which-pack.md
|
||||||
- Platforms:
|
- Platforms:
|
||||||
- Overview: platforms/index.md
|
- Overview: platforms/index.md
|
||||||
- Batocera: platforms/batocera.md
|
- Batocera: platforms/batocera.md
|
||||||
@@ -134,6 +141,7 @@ nav:
|
|||||||
- VTech: systems/vtech.md
|
- VTech: systems/vtech.md
|
||||||
- Vircon: systems/vircon.md
|
- Vircon: systems/vircon.md
|
||||||
- ZC: systems/zc.md
|
- ZC: systems/zc.md
|
||||||
|
- sdlpal: systems/sdlpal.md
|
||||||
- Emulators:
|
- Emulators:
|
||||||
- Overview: emulators/index.md
|
- Overview: emulators/index.md
|
||||||
- Official ports (63):
|
- Official ports (63):
|
||||||
@@ -475,4 +483,5 @@ nav:
|
|||||||
- Adding a scraper: wiki/adding-a-scraper.md
|
- Adding a scraper: wiki/adding-a-scraper.md
|
||||||
- Testing guide: wiki/testing-guide.md
|
- Testing guide: wiki/testing-guide.md
|
||||||
- Release process: wiki/release-process.md
|
- Release process: wiki/release-process.md
|
||||||
|
- Community tools: wiki/community-tools.md
|
||||||
- Contributing: contributing.md
|
- Contributing: contributing.md
|
||||||
|
|||||||
@@ -150,22 +150,23 @@ data_directories:
|
|||||||
description: "SDLPAL Chinese Paladin game data (.mkf archives)"
|
description: "SDLPAL Chinese Paladin game data (.mkf archives)"
|
||||||
|
|
||||||
# ref: OpenTyrian2000 — system/opentyrian/tyrian/
|
# ref: OpenTyrian2000 — system/opentyrian/tyrian/
|
||||||
# Tyrian 2.1 freeware data (also on buildbot as OpenTyrian.zip)
|
# Tyrian 2.1 freeware data (buildbot URLs removed, sourced from release asset)
|
||||||
opentyrian:
|
opentyrian:
|
||||||
source_url: "https://buildbot.libretro.com/assets/system/OpenTyrian%20%28Game%20Data%29.zip"
|
source_url: "https://github.com/Abdess/retrobios/releases/download/large-files/opentyrian-data.zip"
|
||||||
source_type: zip
|
source_type: zip
|
||||||
for_platforms: [retroarch, lakka, retropie]
|
for_platforms: [retroarch, lakka, retropie]
|
||||||
local_cache: data/opentyrian
|
local_cache: data/opentyrian
|
||||||
description: "OpenTyrian Tyrian 2.1 freeware game data"
|
description: "OpenTyrian Tyrian 2.1 freeware game data"
|
||||||
|
|
||||||
# ref: syobonaction — system/syobonaction/
|
# ref: syobonaction — system/syobonaction/
|
||||||
# Freeware game data from OpenSyobonAction
|
# Freeware game data from OpenSyobonAction (BGM, res, SE directories)
|
||||||
syobonaction:
|
syobonaction:
|
||||||
source_url: "https://github.com/akemin-dayo/OpenSyobonAction"
|
source_url: "https://github.com/akemin-dayo/OpenSyobonAction/archive/refs/heads/{version}.tar.gz"
|
||||||
source_type: git_subtree
|
source_type: tarball
|
||||||
source_path: "res"
|
source_path: "OpenSyobonAction-master"
|
||||||
version: master
|
version: master
|
||||||
local_cache: data/syobonaction
|
local_cache: data/syobonaction
|
||||||
|
exclude: [DxLib.cpp, DxLib.h, icon.ico, joyconfig.h, loadg.cpp, main.cpp, main.h, Makefile, README_ja.md, README.md]
|
||||||
description: "Syobon Action (Cat Mario) game data (sprites, BGM, SE)"
|
description: "Syobon Action (Cat Mario) game data (sprites, BGM, SE)"
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
@@ -190,9 +191,10 @@ data_directories:
|
|||||||
# Not on buildbot — sourced from libretro repo
|
# Not on buildbot — sourced from libretro repo
|
||||||
# 532 files (tiles, fonts, databases, lua scripts, level descriptions)
|
# 532 files (tiles, fonts, databases, lua scripts, level descriptions)
|
||||||
stonesoup:
|
stonesoup:
|
||||||
source_url: "https://github.com/libretro/crawl-ref"
|
source_url: "https://github.com/libretro/crawl-ref/archive/refs/heads/{version}.tar.gz"
|
||||||
source_type: git_subtree
|
source_type: tarball
|
||||||
source_path: "crawl-ref/source/dat"
|
source_path: "crawl-ref-master/crawl-ref/source/dat"
|
||||||
|
version: master
|
||||||
local_cache: data/stonesoup
|
local_cache: data/stonesoup
|
||||||
description: "DCSS game data (tiles, fonts, databases, lua, level descriptions)"
|
description: "DCSS game data (tiles, fonts, databases, lua, level descriptions)"
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,144 @@ platforms:
|
|||||||
method: config_file
|
method: config_file
|
||||||
config: '%APPDATA%\RetroArch\retroarch.cfg'
|
config: '%APPDATA%\RetroArch\retroarch.cfg'
|
||||||
parse_key: system_directory
|
parse_key: system_directory
|
||||||
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
|
- file: prod.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
- $HOME/.config/Ryujinx/system
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
batocera:
|
batocera:
|
||||||
config: batocera.yml
|
config: batocera.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -256,6 +394,144 @@ platforms:
|
|||||||
method: file_exists
|
method: file_exists
|
||||||
file: /etc/batocera-version
|
file: /etc/batocera-version
|
||||||
bios_path: /userdata/bios
|
bios_path: /userdata/bios
|
||||||
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
|
- file: prod.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
- $HOME/.config/Ryujinx/system
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
recalbox:
|
recalbox:
|
||||||
config: recalbox.yml
|
config: recalbox.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -468,6 +744,144 @@ platforms:
|
|||||||
method: file_exists
|
method: file_exists
|
||||||
file: /usr/bin/recalbox-settings
|
file: /usr/bin/recalbox-settings
|
||||||
bios_path: /recalbox/share/bios
|
bios_path: /recalbox/share/bios
|
||||||
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
|
- file: prod.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
- $HOME/.config/Ryujinx/system
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
retrobat:
|
retrobat:
|
||||||
config: retrobat.yml
|
config: retrobat.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -653,6 +1067,144 @@ platforms:
|
|||||||
- os: windows
|
- os: windows
|
||||||
method: path_exists
|
method: path_exists
|
||||||
path: '%USERPROFILE%\RetroBat\bios'
|
path: '%USERPROFILE%\RetroBat\bios'
|
||||||
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
|
- file: prod.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
- $HOME/.config/Ryujinx/system
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
emudeck:
|
emudeck:
|
||||||
config: emudeck.yml
|
config: emudeck.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -681,19 +1233,143 @@ platforms:
|
|||||||
parse_key: $emulationPath
|
parse_key: $emulationPath
|
||||||
bios_subdir: bios
|
bios_subdir: bios
|
||||||
standalone_copies:
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
- file: prod.keys
|
- file: prod.keys
|
||||||
targets:
|
targets:
|
||||||
linux:
|
linux:
|
||||||
- $HOME/.local/share/yuzu/keys
|
- $HOME/.local/share/yuzu/keys
|
||||||
- $HOME/.local/share/eden/keys
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
- $HOME/.config/Ryujinx/system
|
- $HOME/.config/Ryujinx/system
|
||||||
windows:
|
windows:
|
||||||
- '%APPDATA%\yuzu\keys'
|
- '%APPDATA%\yuzu\keys'
|
||||||
- '%APPDATA%\eden\keys'
|
- '%APPDATA%\eden\keys'
|
||||||
- file: aes_keys.txt
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
targets:
|
targets:
|
||||||
linux:
|
linux:
|
||||||
- $HOME/Emulation/bios/citra/keys
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
lakka:
|
lakka:
|
||||||
config: lakka.yml
|
config: lakka.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -719,6 +1395,10 @@ platforms:
|
|||||||
source_format: github_component_manifests
|
source_format: github_component_manifests
|
||||||
hash_type: md5
|
hash_type: md5
|
||||||
schedule: monthly
|
schedule: monthly
|
||||||
|
contributed_by:
|
||||||
|
- username: monster-penguin
|
||||||
|
contribution: platform support
|
||||||
|
pr: 36
|
||||||
cores:
|
cores:
|
||||||
- azahar
|
- azahar
|
||||||
- cemu
|
- cemu
|
||||||
@@ -748,7 +1428,145 @@ platforms:
|
|||||||
- os: linux
|
- os: linux
|
||||||
method: path_exists
|
method: path_exists
|
||||||
path: $HOME/.var/app/net.retrodeck.retrodeck
|
path: $HOME/.var/app/net.retrodeck.retrodeck
|
||||||
bios_path: $HOME/retrodeck/bios
|
bios_path: $HOME/retrodeck
|
||||||
|
standalone_copies:
|
||||||
|
# Switch emulators (keys)
|
||||||
|
- file: prod.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
- $HOME/.config/Ryujinx/system
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
- '%APPDATA%\Ryujinx\system'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
- $HOME/Library/Application Support/Ryujinx/system
|
||||||
|
- file: title.keys
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/yuzu/keys
|
||||||
|
- $HOME/.local/share/eden/keys
|
||||||
|
- $HOME/.local/share/citron/keys
|
||||||
|
- $HOME/.local/share/suyu/keys
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\yuzu\keys'
|
||||||
|
- '%APPDATA%\eden\keys'
|
||||||
|
- '%APPDATA%\citron\keys'
|
||||||
|
- '%APPDATA%\suyu\keys'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/yuzu/keys
|
||||||
|
# 3DS emulators
|
||||||
|
- file: Citra/sysdata/aes_keys.txt
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
- file: Citra/sysdata/boot9.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/azahar/sysdata
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Azahar\sysdata'
|
||||||
|
# DuckStation (PS1)
|
||||||
|
- pattern: 'scph*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/duckstation/bios
|
||||||
|
windows:
|
||||||
|
- '%LOCALAPPDATA%\DuckStation\bios'
|
||||||
|
- '%USERPROFILE%\Documents\DuckStation\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/DuckStation/bios
|
||||||
|
# PCSX2 (PS2)
|
||||||
|
- pattern: 'ps2-*.bin'
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/PCSX2/bios
|
||||||
|
- $HOME/.var/app/net.pcsx2.PCSX2/config/PCSX2/bios
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PCSX2\bios'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PCSX2/bios
|
||||||
|
# RPCS3 (PS3) - needs menu install
|
||||||
|
- note: 'PS3 firmware (PS3UPDAT.PUP) found. Install via RPCS3 > File > Install Firmware.'
|
||||||
|
detect:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/rpcs3
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\rpcs3'
|
||||||
|
# Dolphin (GameCube)
|
||||||
|
- file: GC/USA/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/USA
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\USA'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/USA
|
||||||
|
- file: GC/EUR/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/EUR
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\EUR'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/EUR
|
||||||
|
- file: GC/JAP/IPL.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu/GC/JAP
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator\GC\JAP'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin/GC/JAP
|
||||||
|
- file: dsp_rom.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
- file: dsp_coef.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/dolphin-emu
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\Dolphin Emulator'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/Dolphin
|
||||||
|
# PPSSPP
|
||||||
|
- file: PPSSPP/ppge_atlas.zim
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.config/ppsspp/PSP/SYSTEM
|
||||||
|
windows:
|
||||||
|
- '%USERPROFILE%\Documents\PPSSPP\PSP\SYSTEM'
|
||||||
|
darwin:
|
||||||
|
- $HOME/Library/Application Support/PPSSPP/PSP/SYSTEM
|
||||||
|
# Flycast (Dreamcast)
|
||||||
|
- file: dc/dc_boot.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
|
- file: dc/dc_nvmem.bin
|
||||||
|
targets:
|
||||||
|
linux:
|
||||||
|
- $HOME/.local/share/flycast/data
|
||||||
|
- $HOME/.var/app/org.flycast.Flycast/data/flycast
|
||||||
|
windows:
|
||||||
|
- '%APPDATA%\flycast\data'
|
||||||
romm:
|
romm:
|
||||||
config: romm.yml
|
config: romm.yml
|
||||||
status: active
|
status: active
|
||||||
@@ -758,6 +1576,10 @@ platforms:
|
|||||||
source_format: json
|
source_format: json
|
||||||
hash_type: sha1
|
hash_type: sha1
|
||||||
schedule: monthly
|
schedule: monthly
|
||||||
|
contributed_by:
|
||||||
|
- username: PixNyb
|
||||||
|
contribution: platform support
|
||||||
|
pr: 37
|
||||||
inherits_from: emulatorjs
|
inherits_from: emulatorjs
|
||||||
target_scraper: null
|
target_scraper: null
|
||||||
target_source: null
|
target_source: null
|
||||||
|
|||||||
@@ -743,15 +743,13 @@ def group_identical_platforms(
|
|||||||
inherits[platform] = False
|
inherits[platform] = False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
base_dest = config.get("base_destination", "")
|
|
||||||
entries = []
|
entries = []
|
||||||
for sys_id, system in sorted(config.get("systems", {}).items()):
|
for sys_id, system in sorted(config.get("systems", {}).items()):
|
||||||
for fe in system.get("files", []):
|
for fe in system.get("files", []):
|
||||||
dest = fe.get("destination", fe.get("name", ""))
|
dest = fe.get("destination", fe.get("name", ""))
|
||||||
full_dest = f"{base_dest}/{dest}" if base_dest else dest
|
|
||||||
sha1 = fe.get("sha1", "")
|
sha1 = fe.get("sha1", "")
|
||||||
md5 = fe.get("md5", "")
|
md5 = fe.get("md5", "")
|
||||||
entries.append(f"{full_dest}|{sha1}|{md5}")
|
entries.append(f"{dest}|{sha1}|{md5}")
|
||||||
|
|
||||||
fp = hashlib.sha1("|".join(sorted(entries)).encode()).hexdigest()
|
fp = hashlib.sha1("|".join(sorted(entries)).encode()).hexdigest()
|
||||||
if target_cores_cache:
|
if target_cores_cache:
|
||||||
|
|||||||
@@ -103,32 +103,55 @@ def _build_supplemental_index(
|
|||||||
return names
|
return names
|
||||||
|
|
||||||
|
|
||||||
def _find_in_repo(
|
def _resolve_source(
|
||||||
fname: str,
|
fname: str,
|
||||||
by_name: dict[str, list],
|
by_name: dict[str, list],
|
||||||
by_name_lower: dict[str, str],
|
by_name_lower: dict[str, str],
|
||||||
data_names: set[str] | None = None,
|
data_names: set[str] | None = None,
|
||||||
) -> bool:
|
by_path_suffix: dict | None = None,
|
||||||
|
) -> str | None:
|
||||||
|
"""Return the source category for a file, or None if not found.
|
||||||
|
|
||||||
|
Returns ``"bios"`` (in database.json / bios/), ``"data"`` (in data/),
|
||||||
|
or ``None`` (not available anywhere).
|
||||||
|
"""
|
||||||
|
# bios/ via database.json by_name
|
||||||
if fname in by_name:
|
if fname in by_name:
|
||||||
return True
|
return "bios"
|
||||||
# For directory entries or paths, extract the meaningful basename
|
|
||||||
stripped = fname.rstrip("/")
|
stripped = fname.rstrip("/")
|
||||||
basename = stripped.rsplit("/", 1)[-1] if "/" in stripped else None
|
basename = stripped.rsplit("/", 1)[-1] if "/" in stripped else None
|
||||||
if basename and basename in by_name:
|
if basename and basename in by_name:
|
||||||
return True
|
return "bios"
|
||||||
key = fname.lower()
|
key = fname.lower()
|
||||||
if key in by_name_lower:
|
if key in by_name_lower:
|
||||||
return True
|
return "bios"
|
||||||
if basename:
|
if basename:
|
||||||
key = basename.lower()
|
if basename.lower() in by_name_lower:
|
||||||
if key in by_name_lower:
|
return "bios"
|
||||||
return True
|
# bios/ via by_path_suffix (regional variants)
|
||||||
|
if by_path_suffix and fname in by_path_suffix:
|
||||||
|
return "bios"
|
||||||
|
# data/ supplemental index
|
||||||
if data_names:
|
if data_names:
|
||||||
if fname in data_names or key in data_names:
|
if fname in data_names or key in data_names:
|
||||||
return True
|
return "data"
|
||||||
if basename and (basename in data_names or basename.lower() in data_names):
|
if basename and (basename in data_names or basename.lower() in data_names):
|
||||||
return True
|
return "data"
|
||||||
return False
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_archive_source(
|
||||||
|
archive_name: str,
|
||||||
|
by_name: dict[str, list],
|
||||||
|
by_name_lower: dict[str, str],
|
||||||
|
data_names: set[str] | None = None,
|
||||||
|
by_path_suffix: dict | None = None,
|
||||||
|
) -> str:
|
||||||
|
"""Resolve source for an archive (ZIP) name, returning a source category string."""
|
||||||
|
result = _resolve_source(
|
||||||
|
archive_name, by_name, by_name_lower, data_names, by_path_suffix,
|
||||||
|
)
|
||||||
|
return result if result is not None else "missing"
|
||||||
|
|
||||||
|
|
||||||
def cross_reference(
|
def cross_reference(
|
||||||
@@ -137,88 +160,184 @@ def cross_reference(
|
|||||||
db: dict,
|
db: dict,
|
||||||
platform_data_dirs: dict[str, set[str]] | None = None,
|
platform_data_dirs: dict[str, set[str]] | None = None,
|
||||||
data_names: set[str] | None = None,
|
data_names: set[str] | None = None,
|
||||||
|
all_declared: set[str] | None = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Compare emulator profiles against platform declarations.
|
"""Compare emulator profiles against platform declarations.
|
||||||
|
|
||||||
Returns a report with gaps (files emulators need but platforms don't list)
|
Returns a report with gaps (files emulators need but platforms don't list)
|
||||||
and coverage stats. Files covered by matching data_directories between
|
and coverage stats. Each gap entry carries a ``source`` field indicating
|
||||||
emulator profile and platform config are not reported as gaps.
|
where the file is available: ``"bios"`` (bios/ via database.json),
|
||||||
Checks both bios/ (via database) and data/ (via data_names index).
|
``"data"`` (data/ directory), ``"large_file"`` (GitHub release asset),
|
||||||
|
or ``"missing"`` (not available anywhere).
|
||||||
|
|
||||||
|
The boolean ``in_repo`` is derived: ``source != "missing"``.
|
||||||
|
|
||||||
|
When *all_declared* is provided (flat set of every filename declared by
|
||||||
|
any platform for any system), it is used for the ``in_platform`` check
|
||||||
|
instead of the per-system lookup. This is appropriate for the global
|
||||||
|
gap analysis page where "undeclared" means "no platform declares it at all".
|
||||||
"""
|
"""
|
||||||
platform_data_dirs = platform_data_dirs or {}
|
platform_data_dirs = platform_data_dirs or {}
|
||||||
by_name = db.get("indexes", {}).get("by_name", {})
|
by_name = db.get("indexes", {}).get("by_name", {})
|
||||||
by_name_lower = {k.lower(): k for k in by_name}
|
by_name_lower = {k.lower(): k for k in by_name}
|
||||||
|
by_md5 = db.get("indexes", {}).get("by_md5", {})
|
||||||
|
by_path_suffix = db.get("indexes", {}).get("by_path_suffix", {})
|
||||||
|
db_files = db.get("files", {})
|
||||||
report = {}
|
report = {}
|
||||||
|
|
||||||
for emu_name, profile in profiles.items():
|
for emu_name, profile in profiles.items():
|
||||||
emu_files = profile.get("files", [])
|
emu_files = profile.get("files", [])
|
||||||
systems = profile.get("systems", [])
|
systems = profile.get("systems", [])
|
||||||
|
|
||||||
platform_names = set()
|
# Skip filename-agnostic profiles (BIOS detected without fixed names)
|
||||||
for sys_id in systems:
|
if profile.get("bios_mode") == "agnostic":
|
||||||
platform_names.update(declared.get(sys_id, set()))
|
continue
|
||||||
|
|
||||||
|
if all_declared is not None:
|
||||||
|
platform_names = all_declared
|
||||||
|
else:
|
||||||
|
platform_names = set()
|
||||||
|
for sys_id in systems:
|
||||||
|
platform_names.update(declared.get(sys_id, set()))
|
||||||
|
|
||||||
gaps = []
|
gaps = []
|
||||||
covered = []
|
covered = []
|
||||||
by_md5 = db.get("indexes", {}).get("by_md5", {})
|
unsourceable_list: list[dict] = []
|
||||||
|
archive_gaps: dict[str, dict] = {}
|
||||||
|
seen_files: set[str] = set()
|
||||||
for f in emu_files:
|
for f in emu_files:
|
||||||
fname = f.get("name", "")
|
fname = f.get("name", "")
|
||||||
if not fname:
|
if not fname or fname in seen_files:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Collect unsourceable files separately (documented, not a gap)
|
||||||
|
unsourceable_reason = f.get("unsourceable", "")
|
||||||
|
if unsourceable_reason:
|
||||||
|
seen_files.add(fname)
|
||||||
|
unsourceable_list.append({
|
||||||
|
"name": fname,
|
||||||
|
"required": f.get("required", False),
|
||||||
|
"reason": unsourceable_reason,
|
||||||
|
"source_ref": f.get("source_ref", ""),
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip pattern placeholders (e.g., <bios>.bin, <user-selected>.bin)
|
# Skip pattern placeholders (e.g., <bios>.bin, <user-selected>.bin)
|
||||||
if "<" in fname or ">" in fname:
|
if "<" in fname or ">" in fname or "*" in fname:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip UI-imported files with explicit path: null (not resolvable by pack)
|
# Skip UI-imported files with explicit path: null (not resolvable by pack)
|
||||||
if "path" in f and f["path"] is None:
|
if "path" in f and f["path"] is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip release asset files (stored in GitHub releases, not bios/)
|
|
||||||
if f.get("storage") == "release":
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Skip standalone-only files
|
# Skip standalone-only files
|
||||||
file_mode = f.get("mode", "both")
|
file_mode = f.get("mode", "both")
|
||||||
if file_mode == "standalone":
|
if file_mode == "standalone":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Skip files loaded from non-system directories (save_dir, content_dir)
|
||||||
|
load_from = f.get("load_from", "")
|
||||||
|
if load_from and load_from != "system_dir":
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Skip filename-agnostic files (handled by agnostic scan)
|
||||||
|
if f.get("agnostic"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
archive = f.get("archive")
|
||||||
|
|
||||||
|
# Check platform declaration (by name or archive)
|
||||||
in_platform = fname in platform_names
|
in_platform = fname in platform_names
|
||||||
in_repo = _find_in_repo(fname, by_name, by_name_lower, data_names)
|
if not in_platform and archive:
|
||||||
if not in_repo:
|
in_platform = archive in platform_names
|
||||||
path_field = f.get("path", "")
|
|
||||||
if path_field and path_field != fname:
|
if in_platform:
|
||||||
in_repo = _find_in_repo(
|
seen_files.add(fname)
|
||||||
path_field, by_name, by_name_lower, data_names
|
covered.append({
|
||||||
|
"name": fname,
|
||||||
|
"required": f.get("required", False),
|
||||||
|
"in_platform": True,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
|
seen_files.add(fname)
|
||||||
|
|
||||||
|
# Group archived files by archive name
|
||||||
|
if archive:
|
||||||
|
if archive not in archive_gaps:
|
||||||
|
source = _resolve_archive_source(
|
||||||
|
archive, by_name, by_name_lower, data_names,
|
||||||
|
by_path_suffix,
|
||||||
)
|
)
|
||||||
# Try MD5 hash match (handles files that exist under different names)
|
archive_gaps[archive] = {
|
||||||
if not in_repo:
|
"name": archive,
|
||||||
md5_raw = f.get("md5", "")
|
"required": False,
|
||||||
if md5_raw:
|
"note": "",
|
||||||
for md5_val in md5_raw.split(","):
|
"source_ref": "",
|
||||||
md5_val = md5_val.strip().lower()
|
"in_platform": False,
|
||||||
if md5_val and by_md5.get(md5_val):
|
"in_repo": source != "missing",
|
||||||
in_repo = True
|
"source": source,
|
||||||
break
|
"archive": archive,
|
||||||
# Try SHA1 hash match
|
"archive_file_count": 0,
|
||||||
if not in_repo:
|
"archive_required_count": 0,
|
||||||
sha1 = f.get("sha1", "")
|
}
|
||||||
if sha1 and sha1 in db.get("files", {}):
|
entry = archive_gaps[archive]
|
||||||
in_repo = True
|
entry["archive_file_count"] += 1
|
||||||
|
if f.get("required", False):
|
||||||
|
entry["archive_required_count"] += 1
|
||||||
|
entry["required"] = True
|
||||||
|
if not entry["source_ref"] and f.get("source_ref"):
|
||||||
|
entry["source_ref"] = f["source_ref"]
|
||||||
|
continue
|
||||||
|
|
||||||
|
# --- resolve source provenance ---
|
||||||
|
storage = f.get("storage", "")
|
||||||
|
if storage in ("release", "large_file"):
|
||||||
|
source = "large_file"
|
||||||
|
else:
|
||||||
|
source = _resolve_source(
|
||||||
|
fname, by_name, by_name_lower, data_names, by_path_suffix
|
||||||
|
)
|
||||||
|
if source is None:
|
||||||
|
path_field = f.get("path", "")
|
||||||
|
if path_field and path_field != fname:
|
||||||
|
source = _resolve_source(
|
||||||
|
path_field, by_name, by_name_lower,
|
||||||
|
data_names, by_path_suffix,
|
||||||
|
)
|
||||||
|
# Try MD5 hash match
|
||||||
|
if source is None:
|
||||||
|
md5_raw = f.get("md5", "")
|
||||||
|
if md5_raw:
|
||||||
|
for md5_val in md5_raw.split(","):
|
||||||
|
md5_val = md5_val.strip().lower()
|
||||||
|
if md5_val and by_md5.get(md5_val):
|
||||||
|
source = "bios"
|
||||||
|
break
|
||||||
|
# Try SHA1 hash match
|
||||||
|
if source is None:
|
||||||
|
sha1 = f.get("sha1", "")
|
||||||
|
if sha1 and sha1 in db_files:
|
||||||
|
source = "bios"
|
||||||
|
if source is None:
|
||||||
|
source = "missing"
|
||||||
|
|
||||||
|
in_repo = source != "missing"
|
||||||
|
|
||||||
entry = {
|
entry = {
|
||||||
"name": fname,
|
"name": fname,
|
||||||
"required": f.get("required", False),
|
"required": f.get("required", False),
|
||||||
"note": f.get("note", ""),
|
"note": f.get("note", ""),
|
||||||
"source_ref": f.get("source_ref", ""),
|
"source_ref": f.get("source_ref", ""),
|
||||||
"in_platform": in_platform,
|
"in_platform": False,
|
||||||
"in_repo": in_repo,
|
"in_repo": in_repo,
|
||||||
|
"source": source,
|
||||||
}
|
}
|
||||||
|
gaps.append(entry)
|
||||||
|
|
||||||
if not in_platform:
|
# Append grouped archive gaps
|
||||||
gaps.append(entry)
|
for ag in sorted(archive_gaps.values(), key=lambda e: e["name"]):
|
||||||
else:
|
gaps.append(ag)
|
||||||
covered.append(entry)
|
|
||||||
|
|
||||||
report[emu_name] = {
|
report[emu_name] = {
|
||||||
"emulator": profile.get("emulator", emu_name),
|
"emulator": profile.get("emulator", emu_name),
|
||||||
@@ -227,8 +346,12 @@ def cross_reference(
|
|||||||
"platform_covered": len(covered),
|
"platform_covered": len(covered),
|
||||||
"gaps": len(gaps),
|
"gaps": len(gaps),
|
||||||
"gap_in_repo": sum(1 for g in gaps if g["in_repo"]),
|
"gap_in_repo": sum(1 for g in gaps if g["in_repo"]),
|
||||||
"gap_missing": sum(1 for g in gaps if not g["in_repo"]),
|
"gap_missing": sum(1 for g in gaps if g["source"] == "missing"),
|
||||||
|
"gap_bios": sum(1 for g in gaps if g["source"] == "bios"),
|
||||||
|
"gap_data": sum(1 for g in gaps if g["source"] == "data"),
|
||||||
|
"gap_large_file": sum(1 for g in gaps if g["source"] == "large_file"),
|
||||||
"gap_details": gaps,
|
"gap_details": gaps,
|
||||||
|
"unsourceable": unsourceable_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
return report
|
return report
|
||||||
@@ -240,15 +363,19 @@ def print_report(report: dict) -> None:
|
|||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
total_gaps = 0
|
total_gaps = 0
|
||||||
total_in_repo = 0
|
totals: dict[str, int] = {"bios": 0, "data": 0, "large_file": 0, "missing": 0}
|
||||||
total_missing = 0
|
|
||||||
|
|
||||||
for emu_name, data in sorted(report.items()):
|
for emu_name, data in sorted(report.items()):
|
||||||
gaps = data["gaps"]
|
gaps = data["gaps"]
|
||||||
if gaps == 0:
|
if gaps == 0:
|
||||||
status = "OK"
|
continue
|
||||||
else:
|
|
||||||
status = f"{data['gap_in_repo']} in repo, {data['gap_missing']} missing"
|
parts = []
|
||||||
|
for key in ("bios", "data", "large_file", "missing"):
|
||||||
|
count = data.get(f"gap_{key}", 0)
|
||||||
|
if count:
|
||||||
|
parts.append(f"{count} {key}")
|
||||||
|
status = ", ".join(parts) if parts else "OK"
|
||||||
|
|
||||||
print(f"\n{data['emulator']} ({', '.join(data['systems'])})")
|
print(f"\n{data['emulator']} ({', '.join(data['systems'])})")
|
||||||
print(
|
print(
|
||||||
@@ -256,23 +383,29 @@ def print_report(report: dict) -> None:
|
|||||||
f"{data['platform_covered']} declared by platforms, "
|
f"{data['platform_covered']} declared by platforms, "
|
||||||
f"{gaps} undeclared"
|
f"{gaps} undeclared"
|
||||||
)
|
)
|
||||||
|
print(f" Gaps: {status}")
|
||||||
|
|
||||||
if gaps > 0:
|
for g in data["gap_details"]:
|
||||||
print(f" Gaps: {status}")
|
req = "*" if g["required"] else " "
|
||||||
for g in data["gap_details"]:
|
src = g.get("source", "missing").upper()
|
||||||
req = "*" if g["required"] else " "
|
note = f" -- {g['note']}" if g["note"] else ""
|
||||||
loc = "repo" if g["in_repo"] else "MISSING"
|
archive_info = ""
|
||||||
note = f" -- {g['note']}" if g["note"] else ""
|
if g.get("archive"):
|
||||||
print(f" {req} {g['name']} [{loc}]{note}")
|
fc = g.get("archive_file_count", 0)
|
||||||
|
rc = g.get("archive_required_count", 0)
|
||||||
|
archive_info = f" ({fc} files, {rc} required)"
|
||||||
|
print(f" {req} {g['name']} [{src}]{archive_info}{note}")
|
||||||
|
|
||||||
total_gaps += gaps
|
total_gaps += gaps
|
||||||
total_in_repo += data["gap_in_repo"]
|
for key in totals:
|
||||||
total_missing += data["gap_missing"]
|
totals[key] += data.get(f"gap_{key}", 0)
|
||||||
|
|
||||||
print(f"\n{'=' * 60}")
|
print(f"\n{'=' * 60}")
|
||||||
print(f"Total: {total_gaps} undeclared files across all emulators")
|
print(f"Total: {total_gaps} undeclared files across all emulators")
|
||||||
print(f" {total_in_repo} already in repo (can be added to packs)")
|
available = totals["bios"] + totals["data"] + totals["large_file"]
|
||||||
print(f" {total_missing} missing from repo (need to be sourced)")
|
print(f" {available} available (bios: {totals['bios']}, data: {totals['data']}, "
|
||||||
|
f"large_file: {totals['large_file']})")
|
||||||
|
print(f" {totals['missing']} missing (need to be sourced)")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ def build_indexes(files: dict, aliases: dict) -> dict:
|
|||||||
by_md5 = {}
|
by_md5 = {}
|
||||||
by_name = {}
|
by_name = {}
|
||||||
by_crc32 = {}
|
by_crc32 = {}
|
||||||
|
by_sha256 = {}
|
||||||
by_path_suffix = {}
|
by_path_suffix = {}
|
||||||
|
|
||||||
for sha1, entry in files.items():
|
for sha1, entry in files.items():
|
||||||
@@ -179,6 +180,7 @@ def build_indexes(files: dict, aliases: dict) -> dict:
|
|||||||
by_name[name].append(sha1)
|
by_name[name].append(sha1)
|
||||||
|
|
||||||
by_crc32[entry["crc32"]] = sha1
|
by_crc32[entry["crc32"]] = sha1
|
||||||
|
by_sha256[entry["sha256"]] = sha1
|
||||||
|
|
||||||
# Path suffix index for regional variant resolution
|
# Path suffix index for regional variant resolution
|
||||||
suffix = _path_suffix(entry["path"])
|
suffix = _path_suffix(entry["path"])
|
||||||
@@ -208,6 +210,7 @@ def build_indexes(files: dict, aliases: dict) -> dict:
|
|||||||
"by_md5": by_md5,
|
"by_md5": by_md5,
|
||||||
"by_name": by_name,
|
"by_name": by_name,
|
||||||
"by_crc32": by_crc32,
|
"by_crc32": by_crc32,
|
||||||
|
"by_sha256": by_sha256,
|
||||||
"by_path_suffix": by_path_suffix,
|
"by_path_suffix": by_path_suffix,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,13 @@ def _register_path(dest: str, seen_files: set[str], seen_parents: set[str]) -> N
|
|||||||
seen_parents.add(parent)
|
seen_parents.add(parent)
|
||||||
|
|
||||||
|
|
||||||
|
def _flat(arcname: str, prefix: str, flatten: bool) -> str:
|
||||||
|
"""Strip base_destination prefix from ZIP arcname when flattening."""
|
||||||
|
if flatten and prefix and arcname.startswith(prefix + "/"):
|
||||||
|
return arcname[len(prefix) + 1:]
|
||||||
|
return arcname
|
||||||
|
|
||||||
|
|
||||||
def resolve_file(
|
def resolve_file(
|
||||||
file_entry: dict,
|
file_entry: dict,
|
||||||
db: dict,
|
db: dict,
|
||||||
@@ -758,6 +765,7 @@ def _build_readme(
|
|||||||
total_files: int,
|
total_files: int,
|
||||||
num_systems: int,
|
num_systems: int,
|
||||||
source: str = "full",
|
source: str = "full",
|
||||||
|
contributors: list[dict] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Build a personalized step-by-step README for each platform pack."""
|
"""Build a personalized step-by-step README for each platform pack."""
|
||||||
sep = "=" * 50
|
sep = "=" * 50
|
||||||
@@ -782,15 +790,14 @@ def _build_readme(
|
|||||||
" 1. Find your RetroArch system directory:\n"
|
" 1. Find your RetroArch system directory:\n"
|
||||||
" - RetroArch > Settings > Directory > System/BIOS\n"
|
" - RetroArch > Settings > Directory > System/BIOS\n"
|
||||||
" - Default: retroarch/system/\n"
|
" - Default: retroarch/system/\n"
|
||||||
' 2. Open the "system" folder from this archive\n'
|
" 2. Extract all files from this archive directly into your system directory\n"
|
||||||
" 3. Copy ALL contents into your system directory\n"
|
" 3. Overwrite if asked\n\n"
|
||||||
" 4. Overwrite if asked\n\n"
|
|
||||||
" Option C: Manual (handheld / SD card)\n"
|
" Option C: Manual (handheld / SD card)\n"
|
||||||
" -------------------------------------\n"
|
" -------------------------------------\n"
|
||||||
" Anbernic, Retroid, Miyoo, Trimui, etc.:\n"
|
" Anbernic, Retroid, Miyoo, Trimui, etc.:\n"
|
||||||
" 1. Connect your SD card to your PC\n"
|
" 1. Connect your SD card to your PC\n"
|
||||||
" 2. Find the BIOS folder (usually BIOS/ or system/)\n"
|
" 2. Find the BIOS folder (usually BIOS/ or system/)\n"
|
||||||
' 3. Copy ALL contents of "system" from this archive\n'
|
" 3. Extract all files from this archive directly into that folder\n"
|
||||||
" 4. Eject SD card and reboot your device\n\n"
|
" 4. Eject SD card and reboot your device\n\n"
|
||||||
" Common paths by device:\n"
|
" Common paths by device:\n"
|
||||||
" Anbernic (ArkOS/JELOS): BIOS/\n"
|
" Anbernic (ArkOS/JELOS): BIOS/\n"
|
||||||
@@ -809,14 +816,13 @@ def _build_readme(
|
|||||||
" 1. On your PC, open the Batocera network share:\n"
|
" 1. On your PC, open the Batocera network share:\n"
|
||||||
" - Windows: \\\\BATOCERA\\share\\bios\\\n"
|
" - Windows: \\\\BATOCERA\\share\\bios\\\n"
|
||||||
" - Mac/Linux: smb://batocera/share/bios/\n"
|
" - Mac/Linux: smb://batocera/share/bios/\n"
|
||||||
' 2. Open the "bios" folder from this archive\n'
|
" 2. Extract all files from this archive directly into the share\n"
|
||||||
" 3. Copy ALL contents into the share\n"
|
" 3. Overwrite if asked\n\n"
|
||||||
" 4. Overwrite if asked\n\n"
|
|
||||||
" Option C: Manual (SD card)\n"
|
" Option C: Manual (SD card)\n"
|
||||||
" --------------------------\n"
|
" --------------------------\n"
|
||||||
" 1. Put the SD card in your PC\n"
|
" 1. Put the SD card in your PC\n"
|
||||||
" 2. Navigate to /userdata/bios/ on the SHARE partition\n"
|
" 2. Navigate to /userdata/bios/ on the SHARE partition\n"
|
||||||
' 3. Copy ALL contents of "bios" from this archive\n\n'
|
" 3. Extract all files from this archive directly into that folder\n\n"
|
||||||
" NOTE: Dreamcast flash memory is named dc_nvmem.bin\n"
|
" NOTE: Dreamcast flash memory is named dc_nvmem.bin\n"
|
||||||
" (if your setup asks for dc_flash.bin, same file).\n\n"
|
" (if your setup asks for dc_flash.bin, same file).\n\n"
|
||||||
),
|
),
|
||||||
@@ -830,13 +836,12 @@ def _build_readme(
|
|||||||
" 1. On your PC, open the Recalbox network share:\n"
|
" 1. On your PC, open the Recalbox network share:\n"
|
||||||
" - Windows: \\\\RECALBOX\\share\\bios\\\n"
|
" - Windows: \\\\RECALBOX\\share\\bios\\\n"
|
||||||
" - Mac/Linux: smb://recalbox/share/bios/\n"
|
" - Mac/Linux: smb://recalbox/share/bios/\n"
|
||||||
' 2. Open the "bios" folder from this archive\n'
|
" 2. Extract all files from this archive directly into the share\n\n"
|
||||||
" 3. Copy ALL contents into the share\n\n"
|
|
||||||
" Option C: Manual (SD card)\n"
|
" Option C: Manual (SD card)\n"
|
||||||
" --------------------------\n"
|
" --------------------------\n"
|
||||||
" 1. Put the SD card in your PC\n"
|
" 1. Put the SD card in your PC\n"
|
||||||
" 2. Navigate to /recalbox/share/bios/\n"
|
" 2. Navigate to /recalbox/share/bios/\n"
|
||||||
' 3. Copy ALL contents of "bios" from this archive\n\n'
|
" 3. Extract all files from this archive directly into that folder\n\n"
|
||||||
),
|
),
|
||||||
"emudeck": (
|
"emudeck": (
|
||||||
"INSTALLATION GUIDE (Steam Deck / Linux)\n\n"
|
"INSTALLATION GUIDE (Steam Deck / Linux)\n\n"
|
||||||
@@ -850,8 +855,7 @@ def _build_readme(
|
|||||||
" ----------------\n"
|
" ----------------\n"
|
||||||
" 1. Open Dolphin file manager\n"
|
" 1. Open Dolphin file manager\n"
|
||||||
" 2. Navigate to ~/Emulation/bios/\n"
|
" 2. Navigate to ~/Emulation/bios/\n"
|
||||||
' 3. Open the "bios" folder from this archive\n'
|
" 3. Extract all files from this archive directly into ~/Emulation/bios/\n\n"
|
||||||
" 4. Copy ALL contents into ~/Emulation/bios/\n\n"
|
|
||||||
" STANDALONE EMULATORS (extra step)\n"
|
" STANDALONE EMULATORS (extra step)\n"
|
||||||
" Switch and 3DS emulators need keys in specific folders:\n"
|
" Switch and 3DS emulators need keys in specific folders:\n"
|
||||||
" prod.keys -> ~/.local/share/yuzu/keys/\n"
|
" prod.keys -> ~/.local/share/yuzu/keys/\n"
|
||||||
@@ -870,11 +874,8 @@ def _build_readme(
|
|||||||
" ----------------\n"
|
" ----------------\n"
|
||||||
" 1. Open Dolphin file manager\n"
|
" 1. Open Dolphin file manager\n"
|
||||||
" 2. Show hidden files (Ctrl+H)\n"
|
" 2. Show hidden files (Ctrl+H)\n"
|
||||||
" 3. Navigate to ~/retrodeck/\n"
|
" 3. Navigate to ~/retrodeck/bios/\n"
|
||||||
' 4. Open the "bios" folder from this archive\n'
|
" 4. Extract all files from this archive directly into ~/retrodeck/bios/\n\n"
|
||||||
" 5. Copy ALL contents into ~/retrodeck/bios/\n"
|
|
||||||
' 6. If the archive contains a "roms" folder, copy\n'
|
|
||||||
" its contents into ~/retrodeck/roms/\n\n"
|
|
||||||
" NOTE: RetroDECK uses its own BIOS checker. After\n"
|
" NOTE: RetroDECK uses its own BIOS checker. After\n"
|
||||||
" copying, open RetroDECK > Tools > BIOS Checker to\n"
|
" copying, open RetroDECK > Tools > BIOS Checker to\n"
|
||||||
" verify everything is detected.\n\n"
|
" verify everything is detected.\n\n"
|
||||||
@@ -890,9 +891,8 @@ def _build_readme(
|
|||||||
" 1. Open your RetroBat installation folder\n"
|
" 1. Open your RetroBat installation folder\n"
|
||||||
" 2. Navigate to the bios\\ subfolder\n"
|
" 2. Navigate to the bios\\ subfolder\n"
|
||||||
" (default: C:\\RetroBat\\bios\\)\n"
|
" (default: C:\\RetroBat\\bios\\)\n"
|
||||||
' 3. Open the "bios" folder from this archive\n'
|
" 3. Extract all files from this archive directly into your bios\\ folder\n"
|
||||||
" 4. Copy ALL contents into your bios\\ folder\n"
|
" 4. Overwrite if asked\n\n"
|
||||||
" 5. Overwrite if asked\n\n"
|
|
||||||
),
|
),
|
||||||
"bizhawk": (
|
"bizhawk": (
|
||||||
"INSTALLATION GUIDE\n\n"
|
"INSTALLATION GUIDE\n\n"
|
||||||
@@ -900,16 +900,15 @@ def _build_readme(
|
|||||||
" 2. Navigate to the Firmware subfolder:\n"
|
" 2. Navigate to the Firmware subfolder:\n"
|
||||||
" - Windows: BizHawk\\Firmware\\\n"
|
" - Windows: BizHawk\\Firmware\\\n"
|
||||||
" - Linux: ~/.config/BizHawk/Firmware/\n"
|
" - Linux: ~/.config/BizHawk/Firmware/\n"
|
||||||
' 3. Open the "Firmware" folder from this archive\n'
|
" 3. Extract all files from this archive directly into your Firmware folder\n"
|
||||||
" 4. Copy ALL contents into your Firmware folder\n"
|
" 4. In BizHawk: Config > Paths > Firmware should\n"
|
||||||
" 5. In BizHawk: Config > Paths > Firmware should\n"
|
|
||||||
" point to this folder\n\n"
|
" point to this folder\n\n"
|
||||||
),
|
),
|
||||||
"romm": (
|
"romm": (
|
||||||
"INSTALLATION GUIDE (RomM server)\n\n"
|
"INSTALLATION GUIDE (RomM server)\n\n"
|
||||||
" 1. Locate your RomM library folder\n"
|
" 1. Locate your RomM library folder\n"
|
||||||
" 2. Navigate to the bios/ subdirectory\n"
|
" 2. Navigate to the bios/ subdirectory\n"
|
||||||
' 3. Copy ALL contents of "bios" from this archive\n'
|
" 3. Extract all files from this archive directly into that folder\n"
|
||||||
" 4. Restart the RomM service to detect new files\n\n"
|
" 4. Restart the RomM service to detect new files\n\n"
|
||||||
),
|
),
|
||||||
"retropie": (
|
"retropie": (
|
||||||
@@ -917,7 +916,7 @@ def _build_readme(
|
|||||||
" Option A: Via network share\n"
|
" Option A: Via network share\n"
|
||||||
" --------------------------\n"
|
" --------------------------\n"
|
||||||
" 1. On your PC, open: \\\\RETROPIE\\bios\\\n"
|
" 1. On your PC, open: \\\\RETROPIE\\bios\\\n"
|
||||||
' 2. Copy ALL contents of "BIOS" from this archive\n\n'
|
" 2. Extract all files from this archive directly into that folder\n\n"
|
||||||
" Option B: Via SSH\n"
|
" Option B: Via SSH\n"
|
||||||
" -----------------\n"
|
" -----------------\n"
|
||||||
" 1. SSH into your Pi: ssh pi@retropie\n"
|
" 1. SSH into your Pi: ssh pi@retropie\n"
|
||||||
@@ -926,7 +925,7 @@ def _build_readme(
|
|||||||
" ---------------------\n"
|
" ---------------------\n"
|
||||||
" 1. Put the SD card in your PC\n"
|
" 1. Put the SD card in your PC\n"
|
||||||
" 2. Navigate to /home/pi/RetroPie/BIOS/\n"
|
" 2. Navigate to /home/pi/RetroPie/BIOS/\n"
|
||||||
' 3. Copy ALL contents of "BIOS" from this archive\n\n'
|
" 3. Extract all files from this archive directly into that folder\n\n"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,9 +936,8 @@ def _build_readme(
|
|||||||
platform_name,
|
platform_name,
|
||||||
(
|
(
|
||||||
f"INSTALLATION\n\n"
|
f"INSTALLATION\n\n"
|
||||||
f' 1. Open the "{base_dest or "files"}" folder in this archive\n'
|
f" 1. Extract all files from this archive directly into your BIOS directory\n"
|
||||||
f" 2. Copy ALL contents to your BIOS directory\n"
|
f" 2. Overwrite if asked\n\n"
|
||||||
f" 3. Overwrite if asked\n\n"
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -971,7 +969,15 @@ def _build_readme(
|
|||||||
" Independent of platform scraper accuracy.\n\n"
|
" Independent of platform scraper accuracy.\n\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
return header + source_info + guide + footer
|
credits = ""
|
||||||
|
if contributors:
|
||||||
|
credits = "\nCONTRIBUTORS\n\n"
|
||||||
|
for cb in contributors:
|
||||||
|
username = cb.get("username", "")
|
||||||
|
credits += f" @{username}\n"
|
||||||
|
credits += "\n"
|
||||||
|
|
||||||
|
return header + source_info + guide + credits + footer
|
||||||
|
|
||||||
|
|
||||||
def _build_agnostic_rename_readme(
|
def _build_agnostic_rename_readme(
|
||||||
@@ -1010,6 +1016,7 @@ def generate_pack(
|
|||||||
system_filter: list[str] | None = None,
|
system_filter: list[str] | None = None,
|
||||||
precomputed_extras: list[dict] | None = None,
|
precomputed_extras: list[dict] | None = None,
|
||||||
source: str = "full",
|
source: str = "full",
|
||||||
|
flatten: bool = True,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Generate a ZIP pack for a platform.
|
"""Generate a ZIP pack for a platform.
|
||||||
|
|
||||||
@@ -1145,7 +1152,7 @@ def generate_pack(
|
|||||||
f"{base_dest}/{instr_name}" if base_dest else instr_name
|
f"{base_dest}/{instr_name}" if base_dest else instr_name
|
||||||
)
|
)
|
||||||
zf.writestr(
|
zf.writestr(
|
||||||
instr_path,
|
_flat(instr_path, base_dest, flatten),
|
||||||
f"File needed: {file_entry['name']}\n\n{instructions}\n",
|
f"File needed: {file_entry['name']}\n\n{instructions}\n",
|
||||||
)
|
)
|
||||||
user_provided.append(file_entry["name"])
|
user_provided.append(file_entry["name"])
|
||||||
@@ -1171,9 +1178,9 @@ def generate_pack(
|
|||||||
if download_external(file_entry, tmp_path):
|
if download_external(file_entry, tmp_path):
|
||||||
extract = file_entry.get("extract", False)
|
extract = file_entry.get("extract", False)
|
||||||
if extract and tmp_path.endswith(".zip"):
|
if extract and tmp_path.endswith(".zip"):
|
||||||
_extract_zip_to_archive(tmp_path, full_dest, zf)
|
_extract_zip_to_archive(tmp_path, _flat(full_dest, base_dest, flatten), zf)
|
||||||
else:
|
else:
|
||||||
zf.write(tmp_path, full_dest)
|
zf.write(tmp_path, _flat(full_dest, base_dest, flatten))
|
||||||
seen_destinations.add(dedup_key)
|
seen_destinations.add(dedup_key)
|
||||||
_register_path(dedup_key, seen_destinations, seen_parents)
|
_register_path(dedup_key, seen_destinations, seen_parents)
|
||||||
if case_insensitive:
|
if case_insensitive:
|
||||||
@@ -1251,7 +1258,7 @@ def generate_pack(
|
|||||||
else readme_name
|
else readme_name
|
||||||
)
|
)
|
||||||
if readme_full not in seen_destinations:
|
if readme_full not in seen_destinations:
|
||||||
zf.writestr(readme_full, readme_text)
|
zf.writestr(_flat(readme_full, base_dest, flatten), readme_text)
|
||||||
seen_destinations.add(readme_full)
|
seen_destinations.add(readme_full)
|
||||||
status = "agnostic_fallback"
|
status = "agnostic_fallback"
|
||||||
# Fall through to normal packing below
|
# Fall through to normal packing below
|
||||||
@@ -1308,10 +1315,11 @@ def generate_pack(
|
|||||||
and validation_index
|
and validation_index
|
||||||
):
|
):
|
||||||
fname = file_entry.get("name", "")
|
fname = file_entry.get("name", "")
|
||||||
reason = check_file_validation(
|
check = check_file_validation(
|
||||||
local_path, fname, validation_index, bios_dir
|
local_path, fname, validation_index, bios_dir
|
||||||
)
|
)
|
||||||
if reason:
|
if check:
|
||||||
|
reason, emus_list = check
|
||||||
better = _find_candidate_satisfying_both(
|
better = _find_candidate_satisfying_both(
|
||||||
file_entry,
|
file_entry,
|
||||||
db,
|
db,
|
||||||
@@ -1322,8 +1330,7 @@ def generate_pack(
|
|||||||
if better:
|
if better:
|
||||||
local_path = better
|
local_path = better
|
||||||
else:
|
else:
|
||||||
ventry = validation_index.get(fname, {})
|
emus = ", ".join(emus_list)
|
||||||
emus = ", ".join(ventry.get("emulators", []))
|
|
||||||
file_reasons.setdefault(
|
file_reasons.setdefault(
|
||||||
dedup_key,
|
dedup_key,
|
||||||
f"{platform_display} says OK but {emus} says {reason}",
|
f"{platform_display} says OK but {emus} says {reason}",
|
||||||
@@ -1337,12 +1344,13 @@ def generate_pack(
|
|||||||
seen_lower.add(dedup_key.lower())
|
seen_lower.add(dedup_key.lower())
|
||||||
|
|
||||||
extract = file_entry.get("extract", False)
|
extract = file_entry.get("extract", False)
|
||||||
|
flat_dest = _flat(full_dest, base_dest, flatten)
|
||||||
if extract and local_path.endswith(".zip"):
|
if extract and local_path.endswith(".zip"):
|
||||||
_extract_zip_to_archive(local_path, full_dest, zf)
|
_extract_zip_to_archive(local_path, flat_dest, zf)
|
||||||
elif local_path.endswith(".zip"):
|
elif local_path.endswith(".zip"):
|
||||||
_normalize_zip_for_pack(local_path, full_dest, zf)
|
_normalize_zip_for_pack(local_path, flat_dest, zf)
|
||||||
else:
|
else:
|
||||||
zf.write(local_path, full_dest)
|
zf.write(local_path, flat_dest)
|
||||||
total_files += 1
|
total_files += 1
|
||||||
|
|
||||||
# Core requirements: files platform's cores need but YAML doesn't declare
|
# Core requirements: files platform's cores need but YAML doesn't declare
|
||||||
@@ -1428,10 +1436,11 @@ def generate_pack(
|
|||||||
if status in ("not_found", "external", "user_provided"):
|
if status in ("not_found", "external", "user_provided"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
flat_dest = _flat(full_dest, base_dest, flatten)
|
||||||
if local_path.endswith(".zip"):
|
if local_path.endswith(".zip"):
|
||||||
_normalize_zip_for_pack(local_path, full_dest, zf)
|
_normalize_zip_for_pack(local_path, flat_dest, zf)
|
||||||
else:
|
else:
|
||||||
zf.write(local_path, full_dest)
|
zf.write(local_path, flat_dest)
|
||||||
seen_destinations.add(full_dest)
|
seen_destinations.add(full_dest)
|
||||||
_register_path(full_dest, seen_destinations, seen_parents)
|
_register_path(full_dest, seen_destinations, seen_parents)
|
||||||
if case_insensitive:
|
if case_insensitive:
|
||||||
@@ -1477,14 +1486,20 @@ def generate_pack(
|
|||||||
_register_path(full, seen_destinations, seen_parents)
|
_register_path(full, seen_destinations, seen_parents)
|
||||||
if case_insensitive:
|
if case_insensitive:
|
||||||
seen_lower.add(full.lower())
|
seen_lower.add(full.lower())
|
||||||
zf.write(src, full)
|
zf.write(src, _flat(full, base_dest, flatten))
|
||||||
total_files += 1
|
total_files += 1
|
||||||
|
|
||||||
# README.txt for users -personalized step-by-step per platform
|
# README.txt for users -personalized step-by-step per platform
|
||||||
num_systems = len(pack_systems)
|
num_systems = len(pack_systems)
|
||||||
|
_registry_path = Path(platforms_dir) / "_registry.yml"
|
||||||
|
_pack_registry: dict = {}
|
||||||
|
if _registry_path.exists():
|
||||||
|
with open(_registry_path) as _rf:
|
||||||
|
_pack_registry = (yaml.safe_load(_rf) or {}).get("platforms", {})
|
||||||
readme_text = _build_readme(
|
readme_text = _build_readme(
|
||||||
platform_name, platform_display, base_dest, total_files, num_systems,
|
platform_name, platform_display, base_dest, total_files, num_systems,
|
||||||
source=source,
|
source=source,
|
||||||
|
contributors=_pack_registry.get(platform_name, {}).get("contributed_by", []),
|
||||||
)
|
)
|
||||||
zf.writestr("README.txt", readme_text)
|
zf.writestr("README.txt", readme_text)
|
||||||
|
|
||||||
@@ -2414,6 +2429,11 @@ def _run_verify_packs(args):
|
|||||||
with zipfile.ZipFile(zip_path) as zf:
|
with zipfile.ZipFile(zip_path) as zf:
|
||||||
zf.extractall(extract_dir)
|
zf.extractall(extract_dir)
|
||||||
|
|
||||||
|
# Auto-detect flat vs nested extraction
|
||||||
|
is_flat = bool(base_dest) and not os.path.isdir(
|
||||||
|
os.path.join(extract_dir, base_dest)
|
||||||
|
)
|
||||||
|
|
||||||
missing = []
|
missing = []
|
||||||
hash_fail = []
|
hash_fail = []
|
||||||
ok = 0
|
ok = 0
|
||||||
@@ -2424,7 +2444,7 @@ def _run_verify_packs(args):
|
|||||||
continue
|
continue
|
||||||
fp = (
|
fp = (
|
||||||
os.path.join(extract_dir, base_dest, dest)
|
os.path.join(extract_dir, base_dest, dest)
|
||||||
if base_dest
|
if base_dest and not is_flat
|
||||||
else os.path.join(extract_dir, dest)
|
else os.path.join(extract_dir, dest)
|
||||||
)
|
)
|
||||||
# Case-insensitive fallback
|
# Case-insensitive fallback
|
||||||
@@ -2595,9 +2615,11 @@ def _run_platform_packs(
|
|||||||
load_platform_config(p, args.platforms_dir).get("platform", p)
|
load_platform_config(p, args.platforms_dir).get("platform", p)
|
||||||
for p in group_platforms
|
for p in group_platforms
|
||||||
]
|
]
|
||||||
|
source_tag = {"platform": "_Platform", "truth": "_Truth"}.get(source, "")
|
||||||
|
req_tag = "_Required" if required_only else ""
|
||||||
combined = (
|
combined = (
|
||||||
"_".join(n.replace(" ", "") for n in all_names)
|
"_".join(n.replace(" ", "") for n in all_names)
|
||||||
+ f"{ver_tag}_BIOS_Pack.zip"
|
+ f"{ver_tag}{source_tag}{req_tag}_BIOS_Pack.zip"
|
||||||
)
|
)
|
||||||
new_path = os.path.join(os.path.dirname(zip_path), combined)
|
new_path = os.path.join(os.path.dirname(zip_path), combined)
|
||||||
if new_path != zip_path:
|
if new_path != zip_path:
|
||||||
@@ -3257,7 +3279,11 @@ def verify_pack(
|
|||||||
# Data directory: check against cached files
|
# Data directory: check against cached files
|
||||||
if status == "untracked" and _data_index:
|
if status == "untracked" and _data_index:
|
||||||
_bn = os.path.basename(name)
|
_bn = os.path.basename(name)
|
||||||
_pr = name[len("system/") :] if name.startswith("system/") else name
|
_pr = name
|
||||||
|
for _known_prefix in ("system/", "bios/", "BIOS/", "Firmware/"):
|
||||||
|
if name.startswith(_known_prefix):
|
||||||
|
_pr = name[len(_known_prefix):]
|
||||||
|
break
|
||||||
_cands = []
|
_cands = []
|
||||||
if _pr in _data_path_index:
|
if _pr in _data_path_index:
|
||||||
_cands.append(_data_path_index[_pr])
|
_cands.append(_data_path_index[_pr])
|
||||||
@@ -3424,6 +3450,13 @@ def verify_pack_against_platform(
|
|||||||
zip_set = set(zf.namelist())
|
zip_set = set(zf.namelist())
|
||||||
zip_lower = {n.lower(): n for n in zip_set}
|
zip_lower = {n.lower(): n for n in zip_set}
|
||||||
|
|
||||||
|
# Auto-detect flat vs nested ZIP
|
||||||
|
is_flat = bool(base_dest) and not any(
|
||||||
|
n.startswith(base_dest + "/")
|
||||||
|
for n in zip_set
|
||||||
|
if n not in ("README.txt", "manifest.json") and not n.endswith("/")
|
||||||
|
)
|
||||||
|
|
||||||
# Structural checks
|
# Structural checks
|
||||||
dupes = sum(1 for c in Counter(zf.namelist()).values() if c > 1)
|
dupes = sum(1 for c in Counter(zf.namelist()).values() if c > 1)
|
||||||
if dupes:
|
if dupes:
|
||||||
@@ -3453,7 +3486,7 @@ def verify_pack_against_platform(
|
|||||||
dest = fe.get("destination", fe.get("name", ""))
|
dest = fe.get("destination", fe.get("name", ""))
|
||||||
if not dest:
|
if not dest:
|
||||||
continue
|
continue
|
||||||
expected = f"{base_dest}/{dest}" if base_dest else dest
|
expected = f"{base_dest}/{dest}" if base_dest and not is_flat else dest
|
||||||
baseline_checked += 1
|
baseline_checked += 1
|
||||||
|
|
||||||
if expected in zip_set or expected.lower() in zip_lower:
|
if expected in zip_set or expected.lower() in zip_lower:
|
||||||
@@ -3480,7 +3513,7 @@ def verify_pack_against_platform(
|
|||||||
continue
|
continue
|
||||||
raw_dest = u.get("path") or u["name"]
|
raw_dest = u.get("path") or u["name"]
|
||||||
dest = f"{raw_dest}{u['name']}" if raw_dest.endswith("/") else raw_dest
|
dest = f"{raw_dest}{u['name']}" if raw_dest.endswith("/") else raw_dest
|
||||||
if extras_pfx:
|
if extras_pfx and not (is_flat and extras_pfx == base_dest):
|
||||||
if not dest.startswith(f"{extras_pfx}/"):
|
if not dest.startswith(f"{extras_pfx}/"):
|
||||||
full = f"{extras_pfx}/{dest}"
|
full = f"{extras_pfx}/{dest}"
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -143,7 +143,9 @@ def generate_readme(db: dict, platforms_dir: str) -> str:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
"# RetroBIOS",
|
'<p align="center">',
|
||||||
|
' <img src=".github/assets/banner.png" alt="RetroBIOS" width="400">',
|
||||||
|
"</p>",
|
||||||
"",
|
"",
|
||||||
f"Complete BIOS and firmware packs for "
|
f"Complete BIOS and firmware packs for "
|
||||||
f"{', '.join(c['platform'] for c in sorted(coverages.values(), key=lambda x: x[
|
f"{', '.join(c['platform'] for c in sorted(coverages.values(), key=lambda x: x[
|
||||||
@@ -349,6 +351,13 @@ def generate_readme(db: dict, platforms_dir: str) -> str:
|
|||||||
|
|
||||||
lines.extend(
|
lines.extend(
|
||||||
[
|
[
|
||||||
|
"",
|
||||||
|
"## Community tools",
|
||||||
|
"",
|
||||||
|
"- [BIOS Preservation Tool](https://github.com/monster-penguin/BIOS-Preservation-Tool)"
|
||||||
|
" by [monster-penguin](https://github.com/monster-penguin)"
|
||||||
|
" - scan, verify, and stage your own BIOS collection"
|
||||||
|
" using RetroBIOS hash metadata",
|
||||||
"",
|
"",
|
||||||
"## Contributing",
|
"## Contributing",
|
||||||
"",
|
"",
|
||||||
@@ -375,6 +384,16 @@ def generate_contributing() -> str:
|
|||||||
3. Variants (alternate hashes): `bios/Manufacturer/Console/.variants/`
|
3. Variants (alternate hashes): `bios/Manufacturer/Console/.variants/`
|
||||||
4. Create a Pull Request - checksums are verified automatically
|
4. Create a Pull Request - checksums are verified automatically
|
||||||
|
|
||||||
|
## Add a new platform
|
||||||
|
|
||||||
|
1. Write a scraper in `scripts/scraper/`
|
||||||
|
2. Create the platform YAML in `platforms/`
|
||||||
|
3. Register in `platforms/_registry.yml`
|
||||||
|
4. Submit a Pull Request
|
||||||
|
|
||||||
|
Contributors who add platform support are credited in the README,
|
||||||
|
on the documentation site, and in the BIOS packs.
|
||||||
|
|
||||||
## File conventions
|
## File conventions
|
||||||
|
|
||||||
- Files >50 MB go in GitHub release assets (`large-files` release)
|
- Files >50 MB go in GitHub release assets (`large-files` release)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Scraper for RetroDECK BIOS requirements.
|
"""Scraper for RetroDECK BIOS requirements.
|
||||||
|
|
||||||
|
Platform contributed by @monster-penguin (#36).
|
||||||
|
|
||||||
Source: https://github.com/RetroDECK/components
|
Source: https://github.com/RetroDECK/components
|
||||||
Format: component_manifest.json per component directory
|
Format: component_manifest.json per component directory
|
||||||
Hash: MD5 (primary), SHA256 for some entries (melonDS DSi)
|
Hash: MD5 (primary), SHA256 for some entries (melonDS DSi)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Scraper for RomM BIOS requirements.
|
"""Scraper for RomM BIOS requirements.
|
||||||
|
|
||||||
|
Platform contributed by @PixNyb (#37).
|
||||||
|
|
||||||
Source: https://github.com/rommapp/romm
|
Source: https://github.com/rommapp/romm
|
||||||
Format: JSON fixture mapping "slug:filename" to {size, crc, md5, sha1}
|
Format: JSON fixture mapping "slug:filename" to {size, crc, md5, sha1}
|
||||||
Hash: SHA1 primary (all four hashes available per entry)
|
Hash: SHA1 primary (all four hashes available per entry)
|
||||||
|
|||||||
@@ -15,6 +15,25 @@ from common import compute_hashes
|
|||||||
# verify.py cannot reproduce these -size checks still apply if combined.
|
# verify.py cannot reproduce these -size checks still apply if combined.
|
||||||
_CRYPTO_CHECKS = frozenset({"signature", "crypto"})
|
_CRYPTO_CHECKS = frozenset({"signature", "crypto"})
|
||||||
|
|
||||||
|
|
||||||
|
def _adler32_byteswapped(path: str) -> str:
|
||||||
|
"""Compute adler32 on 16-bit byte-swapped data.
|
||||||
|
|
||||||
|
Dolphin's DSP loader swaps every 16-bit word before hashing
|
||||||
|
(Common::swap16 in DSPLLE.cpp:LoadDSPRom). This reproduces that
|
||||||
|
transform so verify.py can match the expected adler32 values.
|
||||||
|
"""
|
||||||
|
import struct
|
||||||
|
import zlib
|
||||||
|
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
# Pad to even length if necessary
|
||||||
|
if len(data) % 2:
|
||||||
|
data += b"\x00"
|
||||||
|
swapped = struct.pack(f">{len(data) // 2}H", *struct.unpack(f"<{len(data) // 2}H", data))
|
||||||
|
return format(zlib.adler32(swapped) & 0xFFFFFFFF, "08x")
|
||||||
|
|
||||||
# All reproducible validation types.
|
# All reproducible validation types.
|
||||||
_HASH_CHECKS = frozenset({"crc32", "md5", "sha1", "adler32"})
|
_HASH_CHECKS = frozenset({"crc32", "md5", "sha1", "adler32"})
|
||||||
|
|
||||||
@@ -72,6 +91,7 @@ def _build_validation_index(profiles: dict) -> dict[str, dict]:
|
|||||||
"sha1": set(),
|
"sha1": set(),
|
||||||
"sha256": set(),
|
"sha256": set(),
|
||||||
"adler32": set(),
|
"adler32": set(),
|
||||||
|
"adler32_byteswap": False,
|
||||||
"crypto_only": set(),
|
"crypto_only": set(),
|
||||||
"emulators": set(),
|
"emulators": set(),
|
||||||
"per_emulator": {},
|
"per_emulator": {},
|
||||||
@@ -82,8 +102,12 @@ def _build_validation_index(profiles: dict) -> dict[str, dict]:
|
|||||||
index[fname]["crypto_only"].update(c for c in checks if c in _CRYPTO_CHECKS)
|
index[fname]["crypto_only"].update(c for c in checks if c in _CRYPTO_CHECKS)
|
||||||
# Size checks
|
# Size checks
|
||||||
if "size" in checks:
|
if "size" in checks:
|
||||||
if f.get("size") is not None:
|
raw_size = f.get("size")
|
||||||
index[fname]["sizes"].add(f["size"])
|
if raw_size is not None:
|
||||||
|
if isinstance(raw_size, list):
|
||||||
|
index[fname]["sizes"].update(raw_size)
|
||||||
|
else:
|
||||||
|
index[fname]["sizes"].add(raw_size)
|
||||||
if f.get("min_size") is not None:
|
if f.get("min_size") is not None:
|
||||||
cur = index[fname]["min_size"]
|
cur = index[fname]["min_size"]
|
||||||
index[fname]["min_size"] = (
|
index[fname]["min_size"] = (
|
||||||
@@ -120,6 +144,8 @@ def _build_validation_index(profiles: dict) -> dict[str, dict]:
|
|||||||
if norm.startswith("0x"):
|
if norm.startswith("0x"):
|
||||||
norm = norm[2:]
|
norm = norm[2:]
|
||||||
index[fname]["adler32"].add(norm)
|
index[fname]["adler32"].add(norm)
|
||||||
|
if f.get("adler32_byteswap"):
|
||||||
|
index[fname]["adler32_byteswap"] = True
|
||||||
# Per-emulator ground truth detail
|
# Per-emulator ground truth detail
|
||||||
expected: dict = {}
|
expected: dict = {}
|
||||||
if "size" in checks:
|
if "size" in checks:
|
||||||
@@ -182,35 +208,56 @@ def build_ground_truth(filename: str, validation_index: dict[str, dict]) -> list
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _emulators_for_check(
|
||||||
|
check_type: str, per_emulator: dict[str, dict],
|
||||||
|
) -> list[str]:
|
||||||
|
"""Return emulator names that validate a specific check type."""
|
||||||
|
result = []
|
||||||
|
for emu, detail in per_emulator.items():
|
||||||
|
emu_checks = detail.get("checks", [])
|
||||||
|
if check_type in emu_checks:
|
||||||
|
result.append(emu)
|
||||||
|
# adler32 is stored as known_hash, not always in validation list
|
||||||
|
if check_type == "adler32" and detail.get("expected", {}).get("adler32"):
|
||||||
|
if emu not in result:
|
||||||
|
result.append(emu)
|
||||||
|
return sorted(result)
|
||||||
|
|
||||||
|
|
||||||
def check_file_validation(
|
def check_file_validation(
|
||||||
local_path: str,
|
local_path: str,
|
||||||
filename: str,
|
filename: str,
|
||||||
validation_index: dict[str, dict],
|
validation_index: dict[str, dict],
|
||||||
bios_dir: str = "bios",
|
bios_dir: str = "bios",
|
||||||
) -> str | None:
|
) -> tuple[str, list[str]] | None:
|
||||||
"""Check emulator-level validation on a resolved file.
|
"""Check emulator-level validation on a resolved file.
|
||||||
|
|
||||||
Supports: size (exact/min/max), crc32, md5, sha1, adler32,
|
Supports: size (exact/min/max), crc32, md5, sha1, adler32,
|
||||||
signature (RSA-2048 PKCS1v15 SHA256), crypto (AES-128-CBC + SHA256).
|
signature (RSA-2048 PKCS1v15 SHA256), crypto (AES-128-CBC + SHA256).
|
||||||
|
|
||||||
Returns None if all checks pass or no validation applies.
|
Returns None if all checks pass or no validation applies.
|
||||||
Returns a reason string if a check fails.
|
Returns (reason, emulators) tuple on failure, where *emulators*
|
||||||
|
lists only those cores whose check actually failed.
|
||||||
"""
|
"""
|
||||||
entry = validation_index.get(filename)
|
entry = validation_index.get(filename)
|
||||||
if not entry:
|
if not entry:
|
||||||
return None
|
return None
|
||||||
checks = entry["checks"]
|
checks = entry["checks"]
|
||||||
|
pe = entry.get("per_emulator", {})
|
||||||
|
|
||||||
# Size checks -sizes is a set of accepted values
|
# Size checks -sizes is a set of accepted values
|
||||||
if "size" in checks:
|
if "size" in checks:
|
||||||
actual_size = os.path.getsize(local_path)
|
actual_size = os.path.getsize(local_path)
|
||||||
if entry["sizes"] and actual_size not in entry["sizes"]:
|
if entry["sizes"] and actual_size not in entry["sizes"]:
|
||||||
expected = ",".join(str(s) for s in sorted(entry["sizes"]))
|
expected = ",".join(str(s) for s in sorted(entry["sizes"]))
|
||||||
return f"size mismatch: got {actual_size}, accepted [{expected}]"
|
emus = _emulators_for_check("size", pe)
|
||||||
|
return f"size mismatch: got {actual_size}, accepted [{expected}]", emus
|
||||||
if entry["min_size"] is not None and actual_size < entry["min_size"]:
|
if entry["min_size"] is not None and actual_size < entry["min_size"]:
|
||||||
return f"size too small: min {entry['min_size']}, got {actual_size}"
|
emus = _emulators_for_check("size", pe)
|
||||||
|
return f"size too small: min {entry['min_size']}, got {actual_size}", emus
|
||||||
if entry["max_size"] is not None and actual_size > entry["max_size"]:
|
if entry["max_size"] is not None and actual_size > entry["max_size"]:
|
||||||
return f"size too large: max {entry['max_size']}, got {actual_size}"
|
emus = _emulators_for_check("size", pe)
|
||||||
|
return f"size too large: max {entry['max_size']}, got {actual_size}", emus
|
||||||
|
|
||||||
# Hash checks -compute once, reuse for all hash types.
|
# Hash checks -compute once, reuse for all hash types.
|
||||||
# Each hash field is a set of accepted values (multiple valid ROM versions).
|
# Each hash field is a set of accepted values (multiple valid ROM versions).
|
||||||
@@ -223,11 +270,23 @@ def check_file_validation(
|
|||||||
if hash_type in checks and entry[hash_type]:
|
if hash_type in checks and entry[hash_type]:
|
||||||
if hashes[hash_type].lower() not in entry[hash_type]:
|
if hashes[hash_type].lower() not in entry[hash_type]:
|
||||||
expected = ",".join(sorted(entry[hash_type]))
|
expected = ",".join(sorted(entry[hash_type]))
|
||||||
return f"{hash_type} mismatch: got {hashes[hash_type]}, accepted [{expected}]"
|
emus = _emulators_for_check(hash_type, pe)
|
||||||
|
return (
|
||||||
|
f"{hash_type} mismatch: got {hashes[hash_type]}, "
|
||||||
|
f"accepted [{expected}]",
|
||||||
|
emus,
|
||||||
|
)
|
||||||
if entry["adler32"]:
|
if entry["adler32"]:
|
||||||
if hashes["adler32"].lower() not in entry["adler32"]:
|
actual_adler = hashes["adler32"].lower()
|
||||||
|
if entry.get("adler32_byteswap"):
|
||||||
|
actual_adler = _adler32_byteswapped(local_path)
|
||||||
|
if actual_adler not in entry["adler32"]:
|
||||||
expected = ",".join(sorted(entry["adler32"]))
|
expected = ",".join(sorted(entry["adler32"]))
|
||||||
return f"adler32 mismatch: got 0x{hashes['adler32']}, accepted [{expected}]"
|
emus = _emulators_for_check("adler32", pe)
|
||||||
|
return (
|
||||||
|
f"adler32 mismatch: got 0x{actual_adler}, accepted [{expected}]",
|
||||||
|
emus,
|
||||||
|
)
|
||||||
|
|
||||||
# Signature/crypto checks (3DS RSA, AES)
|
# Signature/crypto checks (3DS RSA, AES)
|
||||||
if entry["crypto_only"]:
|
if entry["crypto_only"]:
|
||||||
@@ -235,7 +294,8 @@ def check_file_validation(
|
|||||||
|
|
||||||
crypto_reason = check_crypto_validation(local_path, filename, bios_dir)
|
crypto_reason = check_crypto_validation(local_path, filename, bios_dir)
|
||||||
if crypto_reason:
|
if crypto_reason:
|
||||||
return crypto_reason
|
emus = sorted(entry.get("emulators", []))
|
||||||
|
return crypto_reason, emus
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ def verify_entry_existence(
|
|||||||
file_entry: dict,
|
file_entry: dict,
|
||||||
local_path: str | None,
|
local_path: str | None,
|
||||||
validation_index: dict[str, dict] | None = None,
|
validation_index: dict[str, dict] | None = None,
|
||||||
|
db: dict | None = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""RetroArch verification: path_is_valid() -file exists = OK."""
|
"""RetroArch verification: path_is_valid() -file exists = OK."""
|
||||||
name = file_entry.get("name", "")
|
name = file_entry.get("name", "")
|
||||||
@@ -102,11 +103,21 @@ def verify_entry_existence(
|
|||||||
return {"name": name, "status": Status.MISSING, "required": required}
|
return {"name": name, "status": Status.MISSING, "required": required}
|
||||||
result = {"name": name, "status": Status.OK, "required": required}
|
result = {"name": name, "status": Status.OK, "required": required}
|
||||||
if validation_index:
|
if validation_index:
|
||||||
reason = check_file_validation(local_path, name, validation_index)
|
check = check_file_validation(local_path, name, validation_index)
|
||||||
if reason:
|
if check:
|
||||||
ventry = validation_index.get(name, {})
|
reason, emus_list = check
|
||||||
emus = ", ".join(ventry.get("emulators", []))
|
suppressed = False
|
||||||
result["discrepancy"] = f"file present (OK) but {emus} says {reason}"
|
if db:
|
||||||
|
better = _find_best_variant(
|
||||||
|
file_entry, db, local_path, validation_index,
|
||||||
|
)
|
||||||
|
if better:
|
||||||
|
suppressed = True
|
||||||
|
if not suppressed:
|
||||||
|
emus = ", ".join(emus_list)
|
||||||
|
result["discrepancy"] = (
|
||||||
|
f"file present (OK) but {emus} says {reason}"
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@@ -287,13 +298,23 @@ def _name_in_index(
|
|||||||
by_name: dict,
|
by_name: dict,
|
||||||
by_path_suffix: dict | None = None,
|
by_path_suffix: dict | None = None,
|
||||||
data_names: set[str] | None = None,
|
data_names: set[str] | None = None,
|
||||||
|
by_name_lower: dict[str, str] | None = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Check if a name is resolvable in the database indexes or data directories."""
|
"""Check if a name is resolvable in the database indexes or data directories."""
|
||||||
|
# Strip trailing slash for directory-type entries (e.g. nestopia/samples/foo/)
|
||||||
|
name = name.rstrip("/")
|
||||||
if name in by_name:
|
if name in by_name:
|
||||||
return True
|
return True
|
||||||
basename = name.rsplit("/", 1)[-1]
|
basename = name.rsplit("/", 1)[-1] if "/" in name else name
|
||||||
if basename != name and basename in by_name:
|
if basename != name and basename in by_name:
|
||||||
return True
|
return True
|
||||||
|
# Case-insensitive by_name lookup
|
||||||
|
if by_name_lower:
|
||||||
|
key = name.lower()
|
||||||
|
if key in by_name_lower:
|
||||||
|
return True
|
||||||
|
if basename != name and basename.lower() in by_name_lower:
|
||||||
|
return True
|
||||||
if by_path_suffix and name in by_path_suffix:
|
if by_path_suffix and name in by_path_suffix:
|
||||||
return True
|
return True
|
||||||
if data_names:
|
if data_names:
|
||||||
@@ -334,6 +355,7 @@ def find_undeclared_files(
|
|||||||
declared_dd.add(ref)
|
declared_dd.add(ref)
|
||||||
|
|
||||||
by_name = db.get("indexes", {}).get("by_name", {})
|
by_name = db.get("indexes", {}).get("by_name", {})
|
||||||
|
by_name_lower = {k.lower(): k for k in by_name}
|
||||||
by_path_suffix = db.get("indexes", {}).get("by_path_suffix", {})
|
by_path_suffix = db.get("indexes", {}).get("by_path_suffix", {})
|
||||||
profiles = (
|
profiles = (
|
||||||
emu_profiles
|
emu_profiles
|
||||||
@@ -367,6 +389,10 @@ def find_undeclared_files(
|
|||||||
fname = f.get("name", "")
|
fname = f.get("name", "")
|
||||||
if not fname or fname in seen_files:
|
if not fname or fname in seen_files:
|
||||||
continue
|
continue
|
||||||
|
# Skip unsourceable files (documented reason, not a gap)
|
||||||
|
if f.get("unsourceable"):
|
||||||
|
seen_files.add(fname)
|
||||||
|
continue
|
||||||
# Skip pattern placeholders (e.g., <user-selected>.bin)
|
# Skip pattern placeholders (e.g., <user-selected>.bin)
|
||||||
if "<" in fname or ">" in fname or "*" in fname:
|
if "<" in fname or ">" in fname or "*" in fname:
|
||||||
continue
|
continue
|
||||||
@@ -405,7 +431,8 @@ def find_undeclared_files(
|
|||||||
if archive:
|
if archive:
|
||||||
if archive not in archive_entries:
|
if archive not in archive_entries:
|
||||||
in_repo = _name_in_index(
|
in_repo = _name_in_index(
|
||||||
archive, by_name, by_path_suffix, data_names
|
archive, by_name, by_path_suffix, data_names,
|
||||||
|
by_name_lower,
|
||||||
)
|
)
|
||||||
archive_entries[archive] = {
|
archive_entries[archive] = {
|
||||||
"emulator": profile.get("emulator", emu_name),
|
"emulator": profile.get("emulator", emu_name),
|
||||||
@@ -436,11 +463,20 @@ def find_undeclared_files(
|
|||||||
else:
|
else:
|
||||||
dest = f.get("path") or fname
|
dest = f.get("path") or fname
|
||||||
|
|
||||||
# Resolution: try name, then path basename, then path_suffix
|
# Resolution: storage flag, then name, then path basename
|
||||||
in_repo = _name_in_index(fname, by_name, by_path_suffix, data_names)
|
storage = f.get("storage", "")
|
||||||
if not in_repo and dest != fname:
|
if storage in ("release", "large_file"):
|
||||||
path_base = dest.rsplit("/", 1)[-1]
|
in_repo = True
|
||||||
in_repo = _name_in_index(path_base, by_name, by_path_suffix, data_names)
|
else:
|
||||||
|
in_repo = _name_in_index(
|
||||||
|
fname, by_name, by_path_suffix, data_names, by_name_lower,
|
||||||
|
)
|
||||||
|
if not in_repo and dest != fname:
|
||||||
|
path_base = dest.rsplit("/", 1)[-1]
|
||||||
|
in_repo = _name_in_index(
|
||||||
|
path_base, by_name, by_path_suffix, data_names,
|
||||||
|
by_name_lower,
|
||||||
|
)
|
||||||
|
|
||||||
checks = _parse_validation(f.get("validation"))
|
checks = _parse_validation(f.get("validation"))
|
||||||
undeclared.append(
|
undeclared.append(
|
||||||
@@ -561,35 +597,82 @@ def _find_best_variant(
|
|||||||
current_path: str,
|
current_path: str,
|
||||||
validation_index: dict,
|
validation_index: dict,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Search for a repo file that passes both platform MD5 and emulator validation."""
|
"""Search for a repo file that passes emulator validation.
|
||||||
|
|
||||||
|
Two-pass search:
|
||||||
|
1. Hash lookup — use the emulator's expected hashes (sha1, md5, sha256,
|
||||||
|
crc32) to find candidates directly in the DB indexes. This finds
|
||||||
|
variants stored under different filenames (e.g. megacd2_v200_eu.bin
|
||||||
|
for bios_CD_E.bin).
|
||||||
|
2. Name lookup — check all files sharing the same name (aliases,
|
||||||
|
.variants/ with name-based suffixes).
|
||||||
|
|
||||||
|
If any candidate on disk passes ``check_file_validation``, the
|
||||||
|
discrepancy is suppressed — the repo has what the emulator needs.
|
||||||
|
"""
|
||||||
fname = file_entry.get("name", "")
|
fname = file_entry.get("name", "")
|
||||||
if not fname or fname not in validation_index:
|
if not fname or fname not in validation_index:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
md5_expected = file_entry.get("md5", "")
|
|
||||||
md5_set = (
|
|
||||||
{m.strip().lower() for m in md5_expected.split(",") if m.strip()}
|
|
||||||
if md5_expected
|
|
||||||
else set()
|
|
||||||
)
|
|
||||||
|
|
||||||
by_name = db.get("indexes", {}).get("by_name", {})
|
|
||||||
files_db = db.get("files", {})
|
files_db = db.get("files", {})
|
||||||
|
current_real = os.path.realpath(current_path)
|
||||||
|
seen_paths: set[str] = set()
|
||||||
|
|
||||||
for sha1 in by_name.get(fname, []):
|
def _try_candidate(sha1: str) -> str | None:
|
||||||
candidate = files_db.get(sha1, {})
|
candidate = files_db.get(sha1, {})
|
||||||
path = candidate.get("path", "")
|
path = candidate.get("path", "")
|
||||||
if (
|
if not path or not os.path.exists(path):
|
||||||
not path
|
return None
|
||||||
or not os.path.exists(path)
|
rp = os.path.realpath(path)
|
||||||
or os.path.realpath(path) == os.path.realpath(current_path)
|
if rp == current_real or rp in seen_paths:
|
||||||
):
|
return None
|
||||||
continue
|
seen_paths.add(rp)
|
||||||
if md5_set and candidate.get("md5", "").lower() not in md5_set:
|
if check_file_validation(path, fname, validation_index) is None:
|
||||||
continue
|
|
||||||
reason = check_file_validation(path, fname, validation_index)
|
|
||||||
if reason is None:
|
|
||||||
return path
|
return path
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Pass 1: hash-based lookup from emulator expected values
|
||||||
|
ventry = validation_index[fname]
|
||||||
|
indexes = db.get("indexes", {})
|
||||||
|
for hash_type, db_index_key in (
|
||||||
|
("sha1", None),
|
||||||
|
("md5", "by_md5"),
|
||||||
|
("crc32", "by_crc32"),
|
||||||
|
("sha256", "by_sha256"),
|
||||||
|
):
|
||||||
|
expected = ventry.get(hash_type)
|
||||||
|
if not expected:
|
||||||
|
continue
|
||||||
|
if db_index_key is None:
|
||||||
|
# SHA1 is the primary key of files_db
|
||||||
|
for h in expected:
|
||||||
|
if h in files_db:
|
||||||
|
result = _try_candidate(h)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
continue
|
||||||
|
db_index = indexes.get(db_index_key, {})
|
||||||
|
for h in expected:
|
||||||
|
entries = db_index.get(h)
|
||||||
|
if not entries:
|
||||||
|
continue
|
||||||
|
if isinstance(entries, list):
|
||||||
|
for sha1 in entries:
|
||||||
|
result = _try_candidate(sha1)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
elif isinstance(entries, str):
|
||||||
|
result = _try_candidate(entries)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Pass 2: name-based lookup (aliases, .variants/ with same filename)
|
||||||
|
by_name = db.get("indexes", {}).get("by_name", {})
|
||||||
|
for sha1 in by_name.get(fname, []):
|
||||||
|
result = _try_candidate(sha1)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -655,6 +738,7 @@ def verify_platform(
|
|||||||
file_entry,
|
file_entry,
|
||||||
local_path,
|
local_path,
|
||||||
validation_index,
|
validation_index,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
elif mode == "sha1":
|
elif mode == "sha1":
|
||||||
result = verify_entry_sha1(file_entry, local_path)
|
result = verify_entry_sha1(file_entry, local_path)
|
||||||
@@ -665,8 +749,11 @@ def verify_platform(
|
|||||||
# mismatches are reported as discrepancies, not failures.
|
# mismatches are reported as discrepancies, not failures.
|
||||||
if result["status"] == Status.OK and local_path and validation_index:
|
if result["status"] == Status.OK and local_path and validation_index:
|
||||||
fname = file_entry.get("name", "")
|
fname = file_entry.get("name", "")
|
||||||
reason = check_file_validation(local_path, fname, validation_index)
|
check = check_file_validation(
|
||||||
if reason:
|
local_path, fname, validation_index,
|
||||||
|
)
|
||||||
|
if check:
|
||||||
|
reason, emus_list = check
|
||||||
better = _find_best_variant(
|
better = _find_best_variant(
|
||||||
file_entry,
|
file_entry,
|
||||||
db,
|
db,
|
||||||
@@ -674,8 +761,7 @@ def verify_platform(
|
|||||||
validation_index,
|
validation_index,
|
||||||
)
|
)
|
||||||
if not better:
|
if not better:
|
||||||
ventry = validation_index.get(fname, {})
|
emus = ", ".join(emus_list)
|
||||||
emus = ", ".join(ventry.get("emulators", []))
|
|
||||||
result["discrepancy"] = (
|
result["discrepancy"] = (
|
||||||
f"{platform} says OK but {emus} says {reason}"
|
f"{platform} says OK but {emus} says {reason}"
|
||||||
)
|
)
|
||||||
@@ -1166,15 +1252,27 @@ def verify_emulator(
|
|||||||
result = {"name": name, "status": Status.MISSING, "required": required}
|
result = {"name": name, "status": Status.MISSING, "required": required}
|
||||||
else:
|
else:
|
||||||
# Apply emulator validation
|
# Apply emulator validation
|
||||||
reason = check_file_validation(local_path, name, validation_index)
|
check = check_file_validation(local_path, name, validation_index)
|
||||||
if reason:
|
if check:
|
||||||
result = {
|
reason, _emus = check
|
||||||
"name": name,
|
better = _find_best_variant(
|
||||||
"status": Status.UNTESTED,
|
file_entry, db, local_path, validation_index,
|
||||||
"required": required,
|
)
|
||||||
"path": local_path,
|
if better:
|
||||||
"reason": reason,
|
result = {
|
||||||
}
|
"name": name,
|
||||||
|
"status": Status.OK,
|
||||||
|
"required": required,
|
||||||
|
"path": better,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
result = {
|
||||||
|
"name": name,
|
||||||
|
"status": Status.UNTESTED,
|
||||||
|
"required": required,
|
||||||
|
"path": local_path,
|
||||||
|
"reason": reason,
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
result = {
|
result = {
|
||||||
"name": name,
|
"name": name,
|
||||||
|
|||||||
@@ -994,8 +994,10 @@ class TestE2E(unittest.TestCase):
|
|||||||
groups = group_identical_platforms(
|
groups = group_identical_platforms(
|
||||||
["test_existence", "test_inherited"], self.platforms_dir
|
["test_existence", "test_inherited"], self.platforms_dir
|
||||||
)
|
)
|
||||||
# Different base_destination ->separate groups
|
# With flat ZIPs, base_destination no longer separates groups
|
||||||
self.assertEqual(len(groups), 2)
|
# Platforms with same files (regardless of base_dest) are grouped
|
||||||
|
self.assertEqual(len(groups), 1)
|
||||||
|
self.assertEqual(len(groups[0][0]), 2)
|
||||||
|
|
||||||
def test_51_platform_grouping_same(self):
|
def test_51_platform_grouping_same(self):
|
||||||
# Create two identical platforms
|
# Create two identical platforms
|
||||||
@@ -1137,9 +1139,11 @@ class TestE2E(unittest.TestCase):
|
|||||||
profiles = load_emulator_profiles(self.emulators_dir)
|
profiles = load_emulator_profiles(self.emulators_dir)
|
||||||
index = _build_validation_index(profiles)
|
index = _build_validation_index(profiles)
|
||||||
path = self.files["present_opt.bin"]["path"]
|
path = self.files["present_opt.bin"]["path"]
|
||||||
reason = check_file_validation(path, "present_opt.bin", index)
|
result = check_file_validation(path, "present_opt.bin", index)
|
||||||
self.assertIsNotNone(reason)
|
self.assertIsNotNone(result)
|
||||||
|
reason, emus = result
|
||||||
self.assertIn("size mismatch", reason)
|
self.assertIn("size mismatch", reason)
|
||||||
|
self.assertIsInstance(emus, list)
|
||||||
|
|
||||||
def test_73_validation_crc32_pass(self):
|
def test_73_validation_crc32_pass(self):
|
||||||
"""File with correct CRC32 passes validation."""
|
"""File with correct CRC32 passes validation."""
|
||||||
@@ -1154,9 +1158,11 @@ class TestE2E(unittest.TestCase):
|
|||||||
profiles = load_emulator_profiles(self.emulators_dir)
|
profiles = load_emulator_profiles(self.emulators_dir)
|
||||||
index = _build_validation_index(profiles)
|
index = _build_validation_index(profiles)
|
||||||
path = self.files["no_md5.bin"]["path"]
|
path = self.files["no_md5.bin"]["path"]
|
||||||
reason = check_file_validation(path, "no_md5.bin", index)
|
result = check_file_validation(path, "no_md5.bin", index)
|
||||||
self.assertIsNotNone(reason)
|
self.assertIsNotNone(result)
|
||||||
|
reason, emus = result
|
||||||
self.assertIn("crc32 mismatch", reason)
|
self.assertIn("crc32 mismatch", reason)
|
||||||
|
self.assertIsInstance(emus, list)
|
||||||
|
|
||||||
def test_75_validation_applied_in_existence_mode(self):
|
def test_75_validation_applied_in_existence_mode(self):
|
||||||
"""Existence mode reports discrepancy when validation fails, keeps OK."""
|
"""Existence mode reports discrepancy when validation fails, keeps OK."""
|
||||||
@@ -1212,9 +1218,11 @@ class TestE2E(unittest.TestCase):
|
|||||||
profiles = load_emulator_profiles(self.emulators_dir)
|
profiles = load_emulator_profiles(self.emulators_dir)
|
||||||
index = _build_validation_index(profiles)
|
index = _build_validation_index(profiles)
|
||||||
path = self.files["alias_target.bin"]["path"]
|
path = self.files["alias_target.bin"]["path"]
|
||||||
reason = check_file_validation(path, "alias_target.bin", index)
|
result = check_file_validation(path, "alias_target.bin", index)
|
||||||
self.assertIsNotNone(reason)
|
self.assertIsNotNone(result)
|
||||||
|
reason, emus = result
|
||||||
self.assertIn("md5 mismatch", reason)
|
self.assertIn("md5 mismatch", reason)
|
||||||
|
self.assertIsInstance(emus, list)
|
||||||
|
|
||||||
def test_81_validation_index_has_md5_sha1(self):
|
def test_81_validation_index_has_md5_sha1(self):
|
||||||
"""Validation index stores md5 and sha1 when declared."""
|
"""Validation index stores md5 and sha1 when declared."""
|
||||||
@@ -3377,10 +3385,17 @@ class TestE2E(unittest.TestCase):
|
|||||||
registry_path,
|
registry_path,
|
||||||
emulators_dir=self.emulators_dir,
|
emulators_dir=self.emulators_dir,
|
||||||
)
|
)
|
||||||
|
# Detect flat vs nested ZIP to build expected paths
|
||||||
base = manifest.get("base_destination", "")
|
base = manifest.get("base_destination", "")
|
||||||
|
is_flat = bool(base) and not any(
|
||||||
|
n.startswith(base + "/") for n in zip_names
|
||||||
|
)
|
||||||
manifest_dests = set()
|
manifest_dests = set()
|
||||||
for f in manifest["files"]:
|
for f in manifest["files"]:
|
||||||
d = f"{base}/{f['dest']}" if base else f["dest"]
|
if base and not is_flat:
|
||||||
|
d = f"{base}/{f['dest']}"
|
||||||
|
else:
|
||||||
|
d = f["dest"]
|
||||||
manifest_dests.add(d)
|
manifest_dests.add(d)
|
||||||
|
|
||||||
self.assertEqual(manifest_dests, zip_names)
|
self.assertEqual(manifest_dests, zip_names)
|
||||||
|
|||||||
@@ -324,10 +324,13 @@ python scripts/pipeline.py --offline
|
|||||||
This executes in sequence:
|
This executes in sequence:
|
||||||
|
|
||||||
1. `generate_db.py` - rebuild `database.json` from `bios/`
|
1. `generate_db.py` - rebuild `database.json` from `bios/`
|
||||||
2. `refresh_data_dirs.py` - update data directories
|
2. `refresh_data_dirs.py` - update data directories (skipped with `--offline`)
|
||||||
3. `verify.py --all` - verify all platforms including the new one
|
3. `verify.py --all` - verify all platforms including the new one
|
||||||
4. `generate_pack.py --all` - build ZIP packs
|
4. `generate_pack.py --all` - build ZIP packs + install manifests
|
||||||
5. Consistency check - verify counts match between verify and pack
|
5. Consistency check - verify counts match between verify and pack
|
||||||
|
6. Pack integrity - extract ZIPs and verify hashes per platform mode
|
||||||
|
7. `generate_readme.py` - regenerate README
|
||||||
|
8. `generate_site.py` - regenerate documentation site
|
||||||
|
|
||||||
Check the output for:
|
Check the output for:
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Upstream sources Scrapers parse generate_db.py scans
|
|||||||
batocera-systems builds database.json
|
batocera-systems builds database.json
|
||||||
es_bios.xml (recalbox) (SHA1 primary key,
|
es_bios.xml (recalbox) (SHA1 primary key,
|
||||||
core-info .info files indexes: by_md5, by_name,
|
core-info .info files indexes: by_md5, by_name,
|
||||||
FirmwareDatabase.cs by_crc32, by_path_suffix)
|
FirmwareDatabase.cs by_crc32, by_sha256, by_path_suffix)
|
||||||
MAME/FBNeo source
|
MAME/FBNeo source
|
||||||
|
|
||||||
emulators/*.yml verify.py checks generate_pack.py resolves
|
emulators/*.yml verify.py checks generate_pack.py resolves
|
||||||
@@ -236,11 +236,11 @@ user's platform, filter files by hardware target, and download with SHA1 verific
|
|||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
5 test files, 249 tests total:
|
5 test files, 259 tests total:
|
||||||
|
|
||||||
| File | Tests | Coverage |
|
| File | Tests | Coverage |
|
||||||
|------|-------|----------|
|
|------|-------|----------|
|
||||||
| `test_e2e.py` | 186 | file resolution, verification, severity, cross-reference, aliases, inheritance, shared groups, data dirs, storage tiers, HLE, launchers, platform grouping, core resolution, target filtering, truth/diff, exporters |
|
| `test_e2e.py` | 196 | file resolution, verification, severity, cross-reference, aliases, inheritance, shared groups, data dirs, storage tiers, HLE, launchers, platform grouping, core resolution, target filtering, truth/diff, exporters |
|
||||||
| `test_pack_integrity.py` | 8 | extract ZIP packs to disk, verify paths + hashes per platform's native mode |
|
| `test_pack_integrity.py` | 8 | extract ZIP packs to disk, verify paths + hashes per platform's native mode |
|
||||||
| `test_mame_parser.py` | 22 | BIOS root set detection, ROM block parsing, macro expansion |
|
| `test_mame_parser.py` | 22 | BIOS root set detection, ROM block parsing, macro expansion |
|
||||||
| `test_fbneo_parser.py` | 16 | BIOS set detection, ROM info parsing |
|
| `test_fbneo_parser.py` | 16 | BIOS set detection, ROM info parsing |
|
||||||
@@ -254,7 +254,7 @@ python -m unittest tests.test_e2e -v
|
|||||||
|
|
||||||
| Workflow | File | Trigger | Role |
|
| Workflow | File | Trigger | Role |
|
||||||
|----------|------|---------|------|
|
|----------|------|---------|------|
|
||||||
| Build & Release | `build.yml` | `workflow_dispatch` (manual) | restore large files, build packs, create GitHub release |
|
| Build & Release | `build.yml` | push to main (bios/, platforms/) + manual | restore large files, build packs, create GitHub release |
|
||||||
| Deploy Site | `deploy-site.yml` | push to main (platforms, emulators, wiki, scripts) + manual | generate site, build with MkDocs, deploy to GitHub Pages |
|
| Deploy Site | `deploy-site.yml` | push to main (platforms, emulators, wiki, scripts) + manual | generate site, build with MkDocs, deploy to GitHub Pages |
|
||||||
| PR Validation | `validate.yml` | pull request on `bios/`/`platforms/` | validate BIOS hashes, schema check, run tests, auto-label PR |
|
| PR Validation | `validate.yml` | pull request on `bios/`/`platforms/` | validate BIOS hashes, schema check, run tests, auto-label PR |
|
||||||
| Weekly Sync | `watch.yml` | cron (Monday 6 AM UTC) + manual | scrape upstream sources, detect changes, create update PR |
|
| Weekly Sync | `watch.yml` | cron (Monday 6 AM UTC) + manual | scrape upstream sources, detect changes, create update PR |
|
||||||
|
|||||||
21
wiki/community-tools.md
Normal file
21
wiki/community-tools.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Community tools
|
||||||
|
|
||||||
|
Projects built on RetroBIOS data.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BIOS Preservation Tool
|
||||||
|
|
||||||
|
**Author:** [monster-penguin](https://github.com/monster-penguin)
|
||||||
|
**Repository:** [github.com/monster-penguin/BIOS-Preservation-Tool](https://github.com/monster-penguin/BIOS-Preservation-Tool)
|
||||||
|
**License:** MIT
|
||||||
|
|
||||||
|
A local tool for managing your own BIOS collection. Point it at your files, it verifies them against RetroBIOS platform YAMLs, stores them in a deduplicated database, and produces ready-to-use directories for each platform. Supports scanning directories, archives, and URLs.
|
||||||
|
|
||||||
|
See the project's [README](https://github.com/monster-penguin/BIOS-Preservation-Tool#readme) for setup and usage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! note "Add your project"
|
||||||
|
|
||||||
|
Open an issue with a link to your repository.
|
||||||
@@ -89,13 +89,15 @@ A hash is a fixed-length fingerprint computed from a file's contents. If even on
|
|||||||
| SHA1 | 40 hex chars | `10155d8d6e6e832d8ea1571511e40dfb15fede05` |
|
| SHA1 | 40 hex chars | `10155d8d6e6e832d8ea1571511e40dfb15fede05` |
|
||||||
| CRC32 | 8 hex chars | `2F468B96` |
|
| CRC32 | 8 hex chars | `2F468B96` |
|
||||||
|
|
||||||
Different platforms use different hash types for verification. Batocera uses MD5, RetroArch checks existence only, and RomM accepts any of the three.
|
Different platforms use different hash types for verification. Batocera uses MD5, RetroArch checks existence only, BizHawk uses SHA1, and RomM uses MD5.
|
||||||
|
|
||||||
## Why does my verification report say UNTESTED?
|
## Why does my verification report say UNTESTED?
|
||||||
|
|
||||||
UNTESTED means the file exists on disk but its hash was not confirmed against a known value. This happens on existence-mode platforms (RetroArch, Lakka, RetroPie) where the platform only checks that the file is present, without verifying its contents.
|
UNTESTED means the file exists on disk but its hash does not match the expected value. This happens on MD5/SHA1-mode platforms (Batocera, Recalbox, BizHawk, etc.) when the file is present but contains different data than what the platform declares.
|
||||||
|
|
||||||
The file may still be correct. Running `verify.py --emulator <core> --verbose` shows the emulator-level ground truth, which can confirm whether the file's hash matches what the source code expects.
|
On existence-mode platforms (RetroArch, Lakka, RetroPie), files are never UNTESTED because the platform only checks presence, not content. Those files show as OK if present.
|
||||||
|
|
||||||
|
Running `verify.py --emulator <core> --verbose` shows the emulator-level ground truth, which can confirm whether the file's hash matches what the source code expects.
|
||||||
|
|
||||||
## Can I use BIOS from one platform on another?
|
## Can I use BIOS from one platform on another?
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ Relative to the RetroBat installation directory (e.g., `C:\RetroBat\bios\`).
|
|||||||
### RetroDECK
|
### RetroDECK
|
||||||
|
|
||||||
```
|
```
|
||||||
~/.var/app/net.retrodeck.retrodeck/retrodeck/bios/
|
~/retrodeck/bios/
|
||||||
```
|
```
|
||||||
|
|
||||||
### EmuDeck
|
### EmuDeck
|
||||||
|
|||||||
@@ -28,12 +28,16 @@ If you just want to download BIOS packs, see the [home page](../index.md).
|
|||||||
|
|
||||||
See [contributing](../contributing.md) for submission guidelines.
|
See [contributing](../contributing.md) for submission guidelines.
|
||||||
|
|
||||||
|
## Community
|
||||||
|
|
||||||
|
- **[Community tools](community-tools.md)** - projects built on RetroBIOS data
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
|
|
||||||
- **BIOS** - firmware burned into console hardware, needed by emulators that rely on original boot code
|
- **BIOS** - firmware burned into console hardware, needed by emulators that rely on original boot code
|
||||||
- **firmware** - system software loaded by a console at boot; used interchangeably with BIOS in this project
|
- **firmware** - system software loaded by a console at boot; used interchangeably with BIOS in this project
|
||||||
- **HLE** - High-Level Emulation; software reimplementation of BIOS functions, avoids needing the original file
|
- **HLE** - High-Level Emulation; software reimplementation of BIOS functions, avoids needing the original file
|
||||||
- **hash** - fixed-length fingerprint of a file's contents; this project uses MD5, SHA1, SHA256, and CRC32
|
- **hash** - fixed-length fingerprint of a file's contents; this project uses MD5, SHA1, SHA256, CRC32, and Adler-32
|
||||||
- **platform** - a distribution that packages emulators (RetroArch, Batocera, Recalbox, EmuDeck, etc.)
|
- **platform** - a distribution that packages emulators (RetroArch, Batocera, Recalbox, EmuDeck, etc.)
|
||||||
- **core** - an emulator packaged as a libretro plugin, loaded by RetroArch or compatible frontends
|
- **core** - an emulator packaged as a libretro plugin, loaded by RetroArch or compatible frontends
|
||||||
- **profile** - a YAML file in `emulators/` documenting one core's BIOS requirements, verified against source code
|
- **profile** - a YAML file in `emulators/` documenting one core's BIOS requirements, verified against source code
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ even if documentation mentions it.
|
|||||||
|-------|----------|-------------|
|
|-------|----------|-------------|
|
||||||
| `emulator` | yes | display name |
|
| `emulator` | yes | display name |
|
||||||
| `type` | yes | `libretro`, `standalone`, `standalone + libretro`, `alias`, `launcher`, `game`, `utility`, `test` |
|
| `type` | yes | `libretro`, `standalone`, `standalone + libretro`, `alias`, `launcher`, `game`, `utility`, `test` |
|
||||||
| `core_classification` | no | `pure_libretro`, `official_port`, `community_fork`, `frozen_snapshot`, `enhanced_fork`, `game_engine`, `embedded_hle`, `alias`, `launcher` |
|
| `core_classification` | no | `pure_libretro`, `official_port`, `community_fork`, `frozen_snapshot`, `enhanced_fork`, `game_engine`, `embedded_hle`, `launcher`, `other` |
|
||||||
| `source` | yes | libretro core repository URL |
|
| `source` | yes | libretro core repository URL |
|
||||||
| `upstream` | no | original emulator repository URL |
|
| `upstream` | no | original emulator repository URL |
|
||||||
| `profiled_date` | yes | date of source analysis |
|
| `profiled_date` | yes | date of source analysis |
|
||||||
@@ -276,6 +276,7 @@ even if documentation mentions it.
|
|||||||
| `size` | expected size in bytes |
|
| `size` | expected size in bytes |
|
||||||
| `min_size`, `max_size` | size range when the code accepts a range |
|
| `min_size`, `max_size` | size range when the code accepts a range |
|
||||||
| `md5`, `sha1`, `crc32`, `sha256` | expected hashes from source code |
|
| `md5`, `sha1`, `crc32`, `sha256` | expected hashes from source code |
|
||||||
|
| `known_hash_adler32` | expected Adler-32 hash (used by Dolphin IPL files) |
|
||||||
| `validation` | checks the code performs: `size`, `crc32`, `md5`, `sha1`, `adler32`, `signature`, `crypto`. Can be a list or dict `{core: [...], upstream: [...]}` for divergent checks |
|
| `validation` | checks the code performs: `size`, `crc32`, `md5`, `sha1`, `adler32`, `signature`, `crypto`. Can be a list or dict `{core: [...], upstream: [...]}` for divergent checks |
|
||||||
| `aliases` | alternate filenames for the same file |
|
| `aliases` | alternate filenames for the same file |
|
||||||
| `mode` | `libretro`, `standalone`, or `both` |
|
| `mode` | `libretro`, `standalone`, or `both` |
|
||||||
@@ -288,4 +289,7 @@ even if documentation mentions it.
|
|||||||
| `note` | additional context |
|
| `note` | additional context |
|
||||||
| `contents` | structure of files inside a BIOS ZIP (`name`, `description`, `size`, `crc32`) |
|
| `contents` | structure of files inside a BIOS ZIP (`name`, `description`, `size`, `crc32`) |
|
||||||
| `storage` | `large_file` for files > 50 MB stored as release assets |
|
| `storage` | `large_file` for files > 50 MB stored as release assets |
|
||||||
|
| `agnostic` | true if any file under the system path within size constraints satisfies the requirement |
|
||||||
|
| `unsourceable` | reason why the file cannot be sourced (acknowledged gap) |
|
||||||
|
| `destination` | target path within the BIOS directory |
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Run everything in sequence:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/pipeline.py --offline # DB + verify + packs + manifests + integrity + readme + site
|
python scripts/pipeline.py --offline # DB + verify + packs + manifests + integrity + readme + site
|
||||||
python scripts/pipeline.py --offline --skip-packs # DB + verify only
|
python scripts/pipeline.py --offline --skip-packs # DB + verify + readme + site
|
||||||
python scripts/pipeline.py --offline --skip-docs # skip readme + site generation
|
python scripts/pipeline.py --offline --skip-docs # skip readme + site generation
|
||||||
python scripts/pipeline.py --offline --target switch # filter by hardware target
|
python scripts/pipeline.py --offline --target switch # filter by hardware target
|
||||||
python scripts/pipeline.py --offline --with-truth # include truth generation + diff
|
python scripts/pipeline.py --offline --with-truth # include truth generation + diff
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ cannot start games for that system at all.
|
|||||||
|
|
||||||
**Check if the hash matches:**
|
**Check if the hash matches:**
|
||||||
|
|
||||||
Look for `HASH_MISMATCH` in the verify output. This means the file exists but
|
Look for `untested` entries in the verify output. This means the file exists but
|
||||||
contains different data than expected. Common causes:
|
its hash does not match the expected value. Common causes:
|
||||||
|
|
||||||
- Wrong region (a PAL BIOS instead of NTSC, or vice versa)
|
- Wrong region (a PAL BIOS instead of NTSC, or vice versa)
|
||||||
- Wrong hardware revision (e.g. SCPH-5501 vs SCPH-1001 for PlayStation)
|
- Wrong hardware revision (e.g. SCPH-5501 vs SCPH-1001 for PlayStation)
|
||||||
@@ -72,13 +72,11 @@ filename from the emulator profile.
|
|||||||
|
|
||||||
## Hash mismatch / UNTESTED
|
## Hash mismatch / UNTESTED
|
||||||
|
|
||||||
`verify.py` reports `HASH_MISMATCH` or `UNTESTED` for a file.
|
`verify.py` reports `UNTESTED` for a file.
|
||||||
|
|
||||||
**HASH_MISMATCH:**
|
|
||||||
|
|
||||||
The file exists and was hashed, but the computed hash doesn't match any expected
|
The file exists and was hashed, but the computed hash doesn't match any expected
|
||||||
value. This means you have a different version of the file than what the platform
|
value. This means you have a different version of the file than what the platform
|
||||||
or emulator expects.
|
or emulator expects. The reason field shows the expected vs actual hash prefix.
|
||||||
|
|
||||||
To find the correct version, check the system page on the site. It lists every
|
To find the correct version, check the system page on the site. It lists every
|
||||||
known BIOS file with its expected MD5 and SHA1.
|
known BIOS file with its expected MD5 and SHA1.
|
||||||
@@ -147,10 +145,11 @@ How to read and interpret `verify.py` output.
|
|||||||
| Status | Meaning |
|
| Status | Meaning |
|
||||||
|--------|---------|
|
|--------|---------|
|
||||||
| `ok` | File present, hash matches (or existence check passed) |
|
| `ok` | File present, hash matches (or existence check passed) |
|
||||||
| `untested` | File present, hash not confirmed (existence-only platforms) |
|
| `untested` | File present, hash not confirmed against expected value |
|
||||||
| `missing` | File not found in the repository |
|
| `missing` | File not found in the repository |
|
||||||
| `hash_mismatch` | File found but hash doesn't match expected value |
|
|
||||||
| `size_mismatch` | File found but size doesn't match what the emulator expects |
|
Hash and size mismatches are reported as `untested` with a reason field
|
||||||
|
showing expected vs actual values (e.g., `expected abc123… got def456…`).
|
||||||
|
|
||||||
**Reading the output:**
|
**Reading the output:**
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ Recalbox uses three severity levels derived from two YAML fields (`mandatory` an
|
|||||||
|-----------|--------------------|--------|-------------------|
|
|-----------|--------------------|--------|-------------------|
|
||||||
| true | true | RED | CRITICAL |
|
| true | true | RED | CRITICAL |
|
||||||
| true | false | YELLOW | WARNING |
|
| true | false | YELLOW | WARNING |
|
||||||
| false | (any) | GREEN | INFO |
|
| false | (any) | GREEN | WARNING |
|
||||||
|
|
||||||
### checkInsideZip (Batocera zippedFile)
|
### checkInsideZip (Batocera zippedFile)
|
||||||
|
|
||||||
@@ -93,9 +93,10 @@ If the inner file is not found inside the ZIP, the status is UNTESTED with a rea
|
|||||||
|
|
||||||
### RomM verification
|
### RomM verification
|
||||||
|
|
||||||
RomM checks both file size and hash. It accepts any hash type (MD5, SHA1, or CRC32).
|
RomM uses MD5 verification (`verification_mode: md5`). The platform YAML stores
|
||||||
ZIP files are not opened; only the container is checked. `verify.py` replicates this
|
SHA1, MD5, and CRC32 for reference, but `verify.py` checks only the MD5 field,
|
||||||
by checking size first, then trying each available hash.
|
matching the platform's runtime behavior. ZIP files are not opened; only the
|
||||||
|
container is checked.
|
||||||
|
|
||||||
|
|
||||||
## SHA1 Mode
|
## SHA1 Mode
|
||||||
|
|||||||
Reference in New Issue
Block a user