一般漢化版遊戲可能有專用的 BIOS,通常這些BIOS除了官方的BIOS程式外還會含有中文字型的程式碼在裡頭。但不同漢化的遊戲的 BIOS 可能是不可以通用的。當你用漢化版 A 的遊戲蓋過原版的 BIOS 時可能會造成漢化版 B 的遊戲中文就亂碼了。這篇文章就是要說明如何用 Batocera 的程式功能來解決這個問題。
Batocera scripts 在這篇官方的文章裡有一段是說明可在遊戲執行前先執行自定程式。而我們要作的就是根據遊戲的名稱如果需要變更 BIOS 就把專用的 BIOS 蓋過官方的 BIOS,等遊戲結束後再把官方的 BIOS 蓋過專用的 BIOS 。程式的流程就是這樣。
這邊我是用 PYTHON3 來作這個動作。由於每個人拿到的遊戲檔名可能不一樣,請自行修改一下程式上的檔名。為把官方的 BIOS 跟專用的 BIOS 依下方程式作相對應的命之後。把下方的程式存成 run_script.py 。copy 至 Batocera 的 /userdata/system/scripts 。再執行 chmod 755 /userdata/system/scripts/run_script.py 。這樣在遊戲執行的前跟後就會作相對應的 COPY 跟蓋過 BIOS 的動作。
#!/usr/bin/env python3
"""
游戏启动/停止时自动切换 BIOS 文件的脚本
用法: python3 run_script.py <event> <param2> <param3> <param4> <rom_path>
"""
import sys
import shutil
from pathlib import Path
# 常量定义
LOGFILE = Path("/tmp/scriptlog.txt")
BIOS_DIR = Path("/userdata/bios")
ROMS_DIR = Path("/userdata/roms")
# BIOS 配置映射
BIOS_CONFIG = {
# PC Engine CD 游戏
"/userdata/roms/pcenginecd/Tengai Makyou Fuun Kabuki Den CN.cue": {
"start": (BIOS_DIR / "syscard3.cn.pce", BIOS_DIR / "syscard3.pce"),
"stop": (BIOS_DIR / "syscard3.bak.pce", BIOS_DIR / "syscard3.pce")
},
"/userdata/roms/pcenginecd/Akumajou Dracula X Chi no Rondo CN.cue": {
"start": (BIOS_DIR / "syscard3.cn.pce", BIOS_DIR / "syscard3.pce"),
"stop": (BIOS_DIR / "syscard3.bak.pce", BIOS_DIR / "syscard3.pce")
},
"/userdata/roms/pcenginecd/Shiawase_Usagi_CN.cue": {
"start": (BIOS_DIR / "syscard3.cn.v2.pce", BIOS_DIR / "syscard3.pce"),
"stop": (BIOS_DIR / "syscard3.bak.pce", BIOS_DIR / "syscard3.pce")
},
"/userdata/roms/pcenginecd/HIMITSU_NO_HANAZONO(CN).cue": {
"start": (BIOS_DIR / "syscard3.cn.v2.pce", BIOS_DIR / "syscard3.pce"),
"stop": (BIOS_DIR / "syscard3.bak.pce", BIOS_DIR / "syscard3.pce")
},
# PC-FX 游戏
"/userdata/roms/pcenginecd/First Kiss Monogatari(CN).cue": {
"start": (BIOS_DIR / "pcfx(CN).rom", BIOS_DIR / "pcfx.rom"),
"stop": (BIOS_DIR / "pcfx.bak.rom", BIOS_DIR / "pcfx.rom")
},
"/userdata/roms/pcenginecd/Pia Carrot He Youkoso(CN).cue": {
"start": (BIOS_DIR / "pcfx(CN).rom", BIOS_DIR / "pcfx.rom"),
"stop": (BIOS_DIR / "pcfx.bak.rom", BIOS_DIR / "pcfx.rom")
},
# PSX 游戏
"/userdata/roms/psx/PoPoLoCrois_Monogatari_CN.cue": {
"start": (BIOS_DIR / "PoPoLoCrois_bios.BIN", BIOS_DIR / "psxonpsp660.bin"),
"stop": (BIOS_DIR / "psxonpsp660.bin.bak", BIOS_DIR / "psxonpsp660.bin")
},
"/userdata/roms/psx/Gensou Suiko Gaiden Vol. 1 - Harmonia no Kenshi(CHS).cue": {
"start": (BIOS_DIR / "GensouSuikoGaidenVol1_bios.bin", BIOS_DIR / "psxonpsp660.bin"),
"stop": (BIOS_DIR / "psxonpsp660.bin.bak", BIOS_DIR / "psxonpsp660.bin")
},
"/userdata/roms/psx/Gensou Suiko Gaiden Vol. 2 - Crystal Valley no Kettou(CHS).cue": {
"start": (BIOS_DIR / "GensouSuikoGaidenVol1_bios.bin", BIOS_DIR / "psxonpsp660.bin"),
"stop": (BIOS_DIR / "psxonpsp660.bin.bak", BIOS_DIR / "psxonpsp660.bin")
}
}
def log_message(message):
"""写入日志文件"""
try:
with open(LOGFILE, "a") as f:
f.write(f"{message}\n")
except Exception as e:
print(f"日志写入失败: {e}", file=sys.stderr)
def copy_bios(source, destination):
"""复制 BIOS 文件"""
try:
shutil.copy2(source, destination)
log_message(f"已复制: {source} -> {destination}")
return True
except Exception as e:
log_message(f"复制失败: {source} -> {destination}, 错误: {e}")
return False
def handle_game_start(rom_path):
"""处理游戏启动事件"""
log_message("START")
log_message(f"启动游戏: {rom_path}")
if rom_path in BIOS_CONFIG:
log_message("change bios")
source, dest = BIOS_CONFIG[rom_path]["start"]
copy_bios(source, dest)
else:
log_message("无需更换 BIOS")
def handle_game_stop(rom_path):
"""处理游戏停止事件"""
log_message("END")
log_message(f"停止游戏: {rom_path}")
if rom_path in BIOS_CONFIG:
log_message("restore bios")
source, dest = BIOS_CONFIG[rom_path]["stop"]
copy_bios(source, dest)
else:
log_message("无需恢复 BIOS")
def main():
"""主函数"""
if len(sys.argv) < 2:
print("用法: python3 run_script.py <event> [参数...]")
print("事件类型: gameStart, gameStop")
sys.exit(1)
event = sys.argv[1]
# 记录所有参数
log_message(" ".join(sys.argv))
# 获取 ROM 路径(第5个参数,索引为5)
rom_path = sys.argv[5] if len(sys.argv) > 5 else ""
if event == "gameStart":
handle_game_start(rom_path)
elif event == "gameStop":
handle_game_stop(rom_path)
else:
log_message(f"未知事件: {event}")
print(f"未知事件: {event}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()