PCSX2 GameDB(GameIndex.yaml)完全指南:游戏数据库格式、GameFix 与 GS 硬件修复配置详解
【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2
PCSX2(PlayStation 2 模拟器)内置一套名为 GameDB(游戏数据库)的机制:它以一份 YAML 文件(GameIndex.yaml)为核心,按游戏序列号(Serial)为数千款 PS2 游戏预置兼容性状态、EE/VU 浮点舍入与钳位模式、GameFix、SpeedHack、GS 硬件修复、记忆卡过滤与补丁(Patch)。本文以仓库中的官方文档 pcsx2/Docs/GameIndex.md 为主线,结合 GameDatabase.cpp / GameDatabase.h 源码与实际数据文件 bin/resources/GameIndex.yaml,完整讲解 GameDB 的 YAML 格式、每个配置项的取值范围与语义,并深入到加载、校验、应用修复的底层实现,帮助你理解"为什么某款游戏会自动套用特定修复"以及"如何为游戏新增一个正确的数据库条目"。
一、GameDB 是什么:数据库文件与源码入口
GameDB 在 PCSX2 中承担"按游戏自动调优"的职责。实际数据存放在资源目录下的 bin/resources/GameIndex.yaml(代码中以常量GAMEDB_YAML_FILE_NAME = "GameIndex.yaml"引用,见 GameDatabase.cpp),而解析与应用逻辑位于 pcsx2/GameDatabase.cpp 与 pcsx2/GameDatabase.h。
从源码结构看,加载流程为:ensureLoaded()(通过std::call_once保证只初始化一次)→initDatabase()读取并解析 YAML →findGame(serial)按小写序列号在s_game_db哈希表中查找条目(GameDatabase.cpp)。命中后,条目中的 GameFix、Round/Clamp 模式、SpeedHack、GS 硬件修复会通过GameEntry::applyGameFixes()与GameEntry::applyGSHardwareFixes()写入当前模拟配置(Pcsx2Config),并实时打印日志,例如:
GameDB: Changing EE/FPU roundmode to 0 [Nearest] GameDB: Enabled Gamefix: XGKickHack GameDB: Enabled GS Hardware Fix: halfPixelOffset to [mode=2]该机制的价值在于:普通用户无需了解每个游戏的底层问题,只要 GameDB 有条目,PCSX2 启动对应游戏时就会自动套用社区验证过的修复组合。
二、YAML 游戏条目格式:字段全解
官方文档给出了一个"带注释的、可定义单条游戏全部内容"的完整示例。以下完整继承该示例,并补充每个字段的实际语义:
SERIAL-12345: # !必填! 游戏序列号,游戏查找的唯一依据,不区分大小写 name: "A Sample Game" # !必填! 游戏名称 region: "NTSC-U" # !必填! 发行区域 compat: 0 # 兼容性等级,取值 0~6 roundModes: # 浮点舍入模式 eeRoundMode: 0 # EE(Emotion Engine)主处理器 FPU vuRoundMode: 3 # VU(Vector Unit,向量单元) clampModes: # 浮点钳位模式 eeClampMode: 0 vuClampMode: 3 # 出现在列表中的 GameFix 会被启用; # 如需临时禁用,请注释掉该行或直接删除。 gameFixes: - VuAddSubHack - FpuMulHack - FpuNegDivHack - XGKickHack - EETimingHack - SkipMPEGHack - OPHFlagHack - DMABusyHack - VIFFIFOHack - VIF1StallHack - GIFFIFOHack - GoemonTlbHack - IbitHack - FullVU0SyncHack - VUSyncHack - VUOverflowHack - SoftwareRendererFMVHack # gsHWFixes 的值约定为整数 gsHWFixes: mipmap: 1 preloadFrameData: 1 # speedHacks 的值约定为整数 speedHacks: mvuFlag: 0 InstantVU1: 0 mtvu: 0 eeCycleRate: 2 memcardFilters: - "SERIAL-123" - "SERIAL-456" # 可以定义多个补丁,但每个补丁通过 CRC 区分 patches: default: # 默认 CRC! content: |- # !必填! YAML 多行字符串块,保留换行符 comment=Sample Patch patch=1,EE,00000002,word,00000000 crc123: # 特定 CRC 的补丁 content: |- comment=Another Sample patch=1,EE,00000001,word,00000000提示:YAML 中字符串加不加引号均可,但
*等字符属于保留字符,必须用引号包裹。建议使用 YAML 检查工具(linter)避免歧义。
2.1 字段在源码中的解析对应关系
上述字段并非全部硬编码:parseAndInsert()(GameDatabase.cpp)逐项检查节点是否存在再写入GameEntry结构。值得注意的几个细节:
- name / name-sort / name-en:除
name外,name-sort(排序用名称,常用于日文假名排序)与name-en(ASCII 英文名)也是合法字段,解析代码分别读取node["name-sort"]与node["name-en"]。 - roundModes 子字段:支持
eeRoundMode、eeDivRoundMode(EE 除法专用舍入)、vuRoundMode、vu0RoundMode、vu1RoundMode。其中vuRoundMode会同时写入 VU0 与 VU1(GameDatabase.cpp)。 - clampModes 子字段:支持
eeClampMode、vuClampMode(同时作用于 VU0/VU1)、vu0ClampMode、vu1ClampMode。 - dynaPatches:解析代码还支持一种"动态补丁"(
pattern+replacement,按内存 offset/value 匹配二进制特征并替换),这是官方文档未展开但仓库已实现的扩展字段(GameDatabase.cpp)。
2.2 真实条目示例
从 bin/resources/GameIndex.yaml 中可以看到真实条目,例如《生化危机 枪下亡魂 4》(Gun Survivor 4)的配置,带注释说明了每个修复解决的问题:
CPCS-01005: name: "ガンサバイバー4 バイオハザード ヒーローズ ネバー ダイ WITH ガンコン2" name-en: "Gun Survivor 4 - BioHazard - Heroes Never Die [with GunCon2]" region: "NTSC-J" gsHWFixes: halfPixelOffset: 5 # 修复手电筒与模糊处的角色偏移、水线问题 roundSprite: 2 # 修复字体伪影 autoFlush: 1 # 修复光晕强度 nativeScaling: 2 # 修复后期处理而《怪物猎人 2》则展示了compat与clampModes的组合:
CPCS-01020: name: "モンスターハンター2 [DXハンターボックス]" name-en: "Monster Hunter 2 [DX Hunters Box]" region: "NTSC-J" compat: 5 clampModes: vuClampMode: 3 # 修复洞穴等场景中角色模型的照明问题 gsHWFixes: maximumBlendingLevel: 0 # 移除 GPU 上不必要的负载注意,真实文件中还会使用 YAML 锚点(&gran-turismo-3-gs-fixes/*gran-turismo-3-gs-fixes)让多个同系列版本共享同一组 GS 修复,减少重复。
三、大小写敏感性:序列号与 CRC 一律小写化
官方文档明确:
- 游戏序列号与 CRC 补丁当前不区分大小写,存储与查询统一使用小写表示;
- 但风格上强烈推荐大写,未来可能强制并迁移为全大写;
- YAML 本身区分大小写,允许存在仅大小写不同的重复序列号,此时会抛出校验错误,第一个条目生效。
示例:SLUS-123在 GameDB 中存储并查询为slus-123;大写十六进制 CRC23AF6876存储并查询为23af6876。
其余所有内容都可安全假定为大小写敏感的(例如 GameFix 名称)。
源码完全印证了这一点:initDatabase()在遍历根节点时执行StringUtil::toLower(...)后再插入s_game_db,并显式做重复检测——GameDB: Duplicate serial '{}' found in GameDB. Skipping, Serials are case-insensitive!(GameDatabase.cpp)。同理,findGame()查询时也执行StringUtil::toLower(serial)(GameDatabase.cpp)。补丁侧,patches解析时把default映射为 CRC0,其余键按十六进制解析,重复 CRC 会被跳过并提示CRCs are case-insensitive!(GameDatabase.cpp)。
四、兼容性等级(Compat)
compat字段取值为整数,表示该游戏在 PCSX2 上的兼容状态:
| 值 | 含义 |
|---|---|
0 | 兼容性未知(Unknown) |
1 | 无(Nothing,无法运行) |
2 | 仅到片头(Intro) |
3 | 仅到菜单(Menu) |
4 | 可进入游戏内(In-game) |
5 | 可玩(Playable) |
6 | 完美(Perfect) |
该枚举在 GameDatabase.h 中定义为enum class Compatibility { Unknown = 0, Nothing, Intro, Menu, InGame, Playable, Perfect },GameEntry::compatAsString()负责将其转换为可读字符串(GameDatabase.cpp),在游戏列表界面中显示。JSON Schema 也约束compat必须为0到6的整数(gamedb-schema.json)。
五、浮点舍入模式(Rounding Modes)
PS2 的浮点单元(EE 的 FPU/COP2 与 VU)支持四种舍入模式,GameDB 按数值指定:
| 值 | 模式 |
|---|---|
0 | Nearest(最近舍入,常见默认) |
1 | Negative Infinity(负无穷) |
2 | Positive Infinity(正无穷) |
3 | Chop (Zero)(向零截断) |
作用对象字段包括:
eeRoundMode:EE 的 FPU 协处理器与 COP2eeDivRoundMode:EE 的除法运算专用舍入模式vuRoundMode:VU(微模式下)通用舍入vu0RoundMode/vu1RoundMode:分别作用于 VU0 / VU1
源码印证:applyGameFixes()中舍入模式被映射为FPRoundMode枚举并写入config.Cpu.FPUFPCR、FPUDivFPCR、VU0FPCR、VU1FPCR(GameDatabase.cpp),名称表s_round_modes[] = {"Nearest", "NegativeInfinity", "PositiveInfinity", "Chop"}用于日志输出。同时,源码对越界值(如负数或超过枚举上限)会打印Invalid EE round mode并忽略该字段(GameDatabase.cpp)。真实条目示例:《玛娜传奇 学园的炼金术士们》通过eeRoundMode: 0修复跳跃问题。
六、浮点钳位模式(Clamping Modes)
钳位模式同样按数值指定,控制浮点溢出/下溢时的处理强度:
eeClampMode:EE 的 FPU 协处理器与 COP2vuClampMode:微模式下的 VU(同时作用于 VU0/VU1)vu0ClampMode/vu1ClampMode:分别作用于 VU0 / VU1
eeClampMode 取值
| 值 | 含义 |
|---|---|
0 | 完全禁用钳位 |
1 | 正常钳位(仅钳位结果) |
2 | 额外钳位 + 保留符号(钳位结果与操作数) |
3 | FPU 完全钳位 |
vuClampMode 取值
| 值 | 含义 |
|---|---|
0 | 完全禁用钳位 |
1 | 正常钳位(仅钳位结果) |
2 | 额外钳位(钳位结果与操作数) |
3 | 额外钳位 + 保留符号 |
源码印证:applyGameFixes()将 EE 钳位模式映射为三个开关——fpuOverflow(≥1)、fpuExtraOverflow(≥2)、fpuFullMode(≥3);VU0/VU1 同理映射为vuNOverflow、vuNExtraOverflow、vuNSignOverflow(GameDatabase.cpp)。这解释了数值递增的语义:等级越高,钳位越严格,模拟越准确但性能开销越大。真实条目示例:《怪物猎人 2》使用vuClampMode: 3修复角色模型照明异常。
七、GS 硬件修复(GS Hardware Fixes)
gsHWFixes是所有字段中最庞大的类别,官方文档按用途分为四组。约定记号:
[ ]= GameDB 中的取值{ }= GUI 选项( )= 默认值
源码侧,这些字段在 GameDatabase.h 中对应enum class GSHWFixId,在 GameDatabase.cpp 的s_gs_hw_fix_names[]中定义了与 YAML 键一一对应的名称表(该表与枚举数量通过static_assert强校验)。
7.1 Mipmap 相关
| 键 | 取值 | GUI | 默认 |
|---|---|---|---|
mipmap | 0/1 | Off / On | On(查 GameDB) |
trilinearFiltering | 0/1/2 | None / Trilinear / Trilinear Ultra | None (0) |
7.2 通用修复
| 键 | 取值 | GUI | 默认 |
|---|---|---|---|
beforeDraw | 带OI前缀的函数名(如OI_BurnoutGames) | 无(除非特定游戏 GSC) | Automatic(无值,查 GameDB) |
moveHandler | 带MV前缀的函数名(如MV_Ico) | 无(除非特定游戏 GSC) | Automatic(无值,查 GameDB) |
afterDraw | 带OO前缀的函数名 | 无(除非特定游戏 GSC) | Automatic(无值,查 GameDB) |
conservativeFramebuffer | 0/1 | Off / On | On (1) |
texturePreloading | 0/1/2 | None / Partial / Full Hash Cache | None (0) |
deinterlace | 0~9 | Automatic、Off、WeaveTFF、WeaveBFF、BobTFF、BobBFF、BlendTFF、BlendBFF、AdaptiveTFF、AdaptiveBFF | Automatic(无值,查 GameDB) |
说明:beforeDraw、moveHandler、afterDraw这类"函数式修复"在源码中以字符串形式解析,通过GSLookupBeforeDrawFunctionId()、GSLookupMoveHandlerFunctionId()、GSLookupGetSkipCountFunctionId()映射为函数 ID(GameDatabase.cpp),映射失败会打印Invalid GS HW Fix Value并跳过。
7.3 渲染器修复(Renderer Fixes)
| 键 | 取值 | GUI | 默认 |
|---|---|---|---|
accurateAlphaTest | 0/1 | Off / On | Off |
autoFlush | 0/1/2 | Disabled / Enabled (Sprites Only) / Enabled (All Primitives) | Off (0) |
partialTargetInvalidation | 0/1 | Off / On | Off (0) |
PCRTCOffsets | 0/1 | Off / On | Off (0) |
PCRTCOverscan | 0/1 | Off / On | Off (0) |
disableDepthSupport | 0/1 | Off / On | Off (0) |
disablePartialInvalidation | 0/1 | Off / On | Off (0) |
cpuFramebufferConversion | 0/1 | Off / On | Off (0) |
preloadFrameData | 0/1 | Off / On | Off (0) |
textureInsideRT | 0/1/2 | Disabled / Inside Targets / Merge Targets | Off (0) |
cpuCLUTRender | 0/1/2 | Disabled / Normal / Aggressive | Disabled (0) |
cpuSpriteRenderBW | 0~10 | Disabled, 1(64), 2(128), 3(192), 4(256), 5(320), 6(384), 7(448), 8(512), 9(576), 10(640) | Off (0) |
cpuSpriteRenderLevel | 0/1/2 | Sprites only / Sprites+Triangles / Blended Sprites/Triangles | Off(若cpuSpriteRenderBW非 Off 则为 'Sprites only')(0) |
estimateTextureRegion | 0/1 | Off / On | Off (0) |
drawBuffering | 0/1 | Off / On | Off (0) |
rewriteLargeSTCoords | 0/1 | Off / On | Off (0) |
getSkipCount | 带GSC前缀的函数名(如GSC_PolyphonyDigitalGames、GSC_UrbanReign) | 无(除非特定游戏 GSC) | Disabled (0) 除非有合法函数名 |
gpuPaletteConversion | 0/1 | Off / On | Off (0) |
gpuTargetCLUT | 0/1/2 | Disabled / Enabled (Exact Match) / Enabled (Check Inside Target) | Disabled (0) |
minimumBlendingLevel | 0~5 | Minimum / Basic / Medium / High / Full(Slow) / Maximum (Very Slow) | Automatic(无值,查 GameDB) |
maximumBlendingLevel | 0~5 | 同上 | Automatic(无值,查 GameDB) |
recommendedBlendingLevel | 0~5 | 同上 | Automatic(无值,查 GameDB) |
readTCOnClose | 0/1 | Off / On | Off (0)(GUI 第 3 标签页硬件修复第 4 个复选框) |
limit24BitDepth | 0/1/2 | Disabled / Prioritise Upper Bits / Prioritise Lower Bits | Off (0) |
recommendedAccurateAlphaTest | 0/1 | Disabled / Advise to use AAT | Off (0) |
recommendedHWAA1 | 0/1 | Disabled / Advise to use AA1 | Off (0) |
7.4 放大修复(Upscaling Fixes)
| 键 | 取值 | GUI | 默认 |
|---|---|---|---|
alignSprite | 0/1 | Off / On | Off (0) |
mergeSprite | 0/1 | Off / On | Off (0) |
forceEvenSpritePosition | 0/1 | Off / On | Off (0) |
bilinearUpscale | 0/1/2 | Automatic / Force Bilinear / Force Nearest | Automatic |
skipDrawStart | 0~10000 | 0-10000 | Off (0) |
skipDrawEnd | 0~10000 | 0-10000 | Off (0) |
halfPixelOffset | 0~5 | Off / Normal Vertex / Special (Texture) / Special (Texture Aggressive) / Align to Native / Align to Native with Texture Offsets | Off (0) |
nativeScaling | 0~4 | Off / Normal / Aggressive / Normal (Maintain Upscale) / Aggressive (Maintain Upscale) | Normal (0) |
nativePaletteDraw | 0/1 | Off / On | Off (0) |
roundSprite | 0/1/2 | Off / Half / Full | Off (0) |
7.5 应用规则与自动/手动冲突处理
applyGSHardwareFixes()(GameDatabase.cpp)揭示了重要的行为规则:
- 手动覆盖优先:如果用户在 GUI 中启用了"Manual GS hardware renderer fixes"(
config.ManualUserHacks),GameDB 中的"用户可调"修复(isUserHackHWFix返回 true 的项)会被跳过,并在 OSD 中列出被跳过的项;而deinterlace、mipmap、texturePreloading、trilinearFiltering、三个 Blending Level、PCRTCOffsets/Overscan、getSkipCount、beforeDraw、moveHandler属于非用户可调项(GameDatabase.cpp),始终按数据库应用。 - 推荐类修复只弹提示:
recommendedBlendingLevel、recommendedAccurateAlphaTest、recommendedHWAA1不会强制改配置,而是通过 OSD 消息提示用户"该游戏建议更高画质设置",例如《攻壳机动队 STAND ALONE COMPLEX 体验版》配置了recommendedBlendingLevel: 4(GameDatabase.cpp)。 - 越界防护与范围修正:每个值应用前都做范围检查(如
halfPixelOffset必须小于GSHalfPixelOffset::MaxCount);最后还会执行config.SkipDrawEnd = std::max(config.SkipDrawStart, config.SkipDrawEnd)修正异常的 skipDraw 区间(GameDatabase.cpp)。 - 软件渲染器旁路:当渲染器为 SW 时,推荐类 OSD 警告不显示(
is_sw_renderer判断)。
真实条目示例:《攻壳机动队 STAND ALONE COMPLEX 体验版》同时使用autoFlush: 1、estimateTextureRegion: 1、halfPixelOffset: 2、nativeScaling: 1、textureInsideRT: 1、recommendedBlendingLevel: 4修复后期效果与性能;《生化危机枪下亡魂 4》则用halfPixelOffset: 5+roundSprite: 2+autoFlush: 1+nativeScaling: 2组合。
八、Game Fixes(游戏修复)
Game Fix 是核心模拟层面的修复开关,名称大小写敏感。如果写错名称,启动时会出现校验错误,非法项会从该游戏的修复列表中被丢弃(源码在parseAndInsert()中逐项匹配GamefixOptions::GetGameFixName(),匹配失败打印Invalid gamefix: '{}' ... Dropping!,见 GameDatabase.cpp)。
官方文档列出的全部 GameFix 及其用途:
| 名称 | 用途/受影响游戏 |
|---|---|
FpuMulHack | 《宿命传说》系列:解决挂起(hanging)问题 |
SoftwareRendererFMVHack | 用于某些游戏中复杂的 FMV 渲染 |
SkipMPEGHack | 通过跳过视频/FMV 防止游戏挂起/冻结 |
GoemonTlbHack | 预加载 TLB,防止《大神》(Goemon)TLB miss |
EETimingHack | 通用时序修复,影响《数码恶魔传说》(Digital Devil Saga)、《SSX》等 |
InstantDMAHack | 解决缓存模拟问题,影响《Fire Pro Wrestling Z》等 |
OPHFlagHack | 影响《死神 刀锋战士》(Bleach Blade Battlers)、《光明力量 III》(Growlanser II and III)、《Wizardry》等 |
GIFFIFOHack | 修正渲染(会降低速度),影响《FIFA Street 2》等 |
DMABusyHack | 影响《玛娜传奇 1》(Mana Khemia 1)、《Metal Saga》、《Pilot Down Behind Enemy Lines》等 |
VIF1StallHack | 解决《SOCOM 2》HUD、《Spy Hunter》等游戏的挂起问题 |
VIFFIFOHack | 模拟 VIF1 FIFO 预读,影响《Test Drive Unlimited》、《Transformers》等 |
FullVU0SyncHack | 在每条 COP2 指令上强制紧密的 VU0 同步 |
IbitHack | 避免《疤面煞星》(Scarface: The World is Yours)、《Crash Tag Team Racing》等游戏中的持续重编译 |
VuAddSubHack | Tri-Ace 游戏:《星之海洋 3》、《凡人物语》(Radiata Stories)、《北欧女神 2》 |
VUOverflowHack | 检查可能的浮点溢出(《超人归来》Superman Returns) |
VUSyncHack | 确保 VU 与 EE 之间的同步以修复时序问题 |
XGKickHack | 为 VU XGKick 使用精确时序,影响《WRC》、《Erementar Gerad》、《Tennis Court Smash》等 |
BlitInternalFPSHack | 用替代方法计算内部 FPS,避免部分游戏的错误读数 |
应用逻辑:applyGameFixes()中每个存在于列表中的 GameFix 都会被启用(config.Gamefixes.Set(id, true)),并打印Enabled Gamefix: ...日志。特别地,GoemonTlbHack(内部名Fix_GoemonTlbMiss)启用时会额外调用vtlb_Alloc_Ppmap()分配页表,因为该 LUT 只为这一款游戏使用,平时不分配以节省约 4MB 内存(GameDatabase.cpp)——这是一个很好的"按需分配资源"的设计例证。
真实条目示例:《工作室系列》多个作品通过SoftwareRendererFMVHack修复 FMV 水平线/垂直线问题。
九、SpeedHacks(速度作弊)
speedHacks以键值对形式给出,值约定为整数(源码在 GameDatabase.cpp 中解析,非法项打印Invalid speedhack: '{}={}' ... Dropping!):
| 键 | 取值 | 说明 |
|---|---|---|
mvuFlag | 0/1 | 《块魂》(Katamari Damacy)在此开关启用时(默认启用)存在独特的加速 bug |
mtvu | 0/1 | T-bit 类游戏不喜欢 MTVU,部分游戏与 MTVU 不兼容 |
instantVU1 | 0/1 | 《啪啦啪啦啪 2》(PaRappa the Rapper 2)等游戏需要 VU1 同步,可用此参数强制同步 |
eeCycleRate | -3~3 | EE 周期率调节 |
应用时通过config.Speedhacks.Set(id, value)写入配置(GameDatabase.cpp)。源码注释特别说明:GameDB 中 speedhack 虽然以整数存储,但实际行为与布尔型 GameFix 类似。
十、记忆卡过滤覆盖(Memory Card Filter Override)
默认情况下,FolderMemoryCard(文件夹记忆卡)根据游戏序列号过滤存档:只加载文件夹名中包含该游戏序列号的存档。这对绝大多数游戏有效,但部分场景会失败,正是此覆盖项存在的意义:
- 多碟游戏:后续碟片经常复用前一碟的序列号;
- 存档跨游戏继承:例如允许从前作导入存档的游戏(服装/外观等外观要素、武器提前解锁等机制要素)。
此时通过memcardFilters指定一组额外的序列号字符串(YAML 字符串列表,如示例中的"SERIAL-123"/"SERIAL-456"),让这些序列号的存档也能被加载。文件型记忆卡(file memcards)不需要此机制,因为它们本身不向游戏隐藏序列号或外部日期。
源码中,memcardFilters以向量形式存储,运行时通过memcardFiltersAsString()转换为/分隔的字符串供上层使用(GameDatabase.cpp、GameDatabase.h)。
十一、补丁(Patches)
patches的结构为CRC -> content:
default键代表默认 CRC(源码解析为 CRC0,见 GameDatabase.cpp);- 运行中游戏的 CRC 对应的补丁优先于
default; - 同一 CRC 不能定义多个补丁,否则抛出校验错误(
Duplicate CRC ... Skipping, CRCs are case-insensitive!); - CRC 不区分大小写,但风格上推荐大写;
content使用 YAML 多行字符串块(|-),每一行对应传统*.pnach文件中的一行。
查找逻辑在GameEntry::findPatch(crc)中实现:先按精确 CRC 查找,找不到再回退到 CRC0(default),CRC 为 0 时直接返回空(GameDatabase.cpp)。
补丁内容示例(对应 pnach 格式):
patches: default: content: |- comment=Sample Patch patch=1,EE,00000002,word,00000000 crc123: content: |- comment=Another Sample patch=1,EE,00000001,word,00000000十二、编辑器工具:JSON Schema 与 VSCode 集成
仓库为 GameDB 格式提供了一份 JSON Schema:pcsx2/Docs/gamedb-schema.json,可用于校验文件合法性并辅助编写。Schema 中值得注意的约束(与本文前面内容相互印证):
- 顶层键(序列号)必须匹配
^[A-Z\d]+-[A-Z\d]+$(如SLUS-12345); region必须匹配^(?:NTSC-(?:B|C|E|HK|J|K|M|T|U).*|PAL-?(?:A|B|E|F|G|I|M|N|P|R|S|U)?.*|Other)$;compat限定为0~6整数;roundModes/clampModes的子字段全部限定0~3,且additionalProperties: false(防止拼写错误被静默忽略);gameFixes是唯一值数组(uniqueItems: true),枚举与第八章列表一致(gamedb-schema.json);gsHWFixes的每个键都声明了合法取值区间(如autoFlush0~2、mipmap0~2、textureInsideRT0~2、skipDrawStart/End等)。
VSCode 集成步骤:
- 安装 YAML 扩展(Red Hat 出品的
redhat.vscode-yaml); - 在 VSCode 设置中添加 schema 映射,将本地 schema 文件关联到 GameIndex.yaml:
"yaml.schemas": { "pcsx2/Docs/gamedb-schema.json": "**/GameIndex.yaml" }(若使用绝对路径,可将键替换为本机仓库中 gamedb-schema.json 的完整路径。)配置完成后,编辑GameIndex.yaml时即可获得补全、类型校验与非法值提示。
十三、从文件到生效:GameDB 的完整工作链路
综合源码,一条 GameDB 条目从磁盘到模拟器的完整链路如下,可作为排查"为什么某修复没生效"的参考:
- 加载:
ensureLoaded()通过std::call_once触发initDatabase(),读取EmuFolders::Resources/GameIndex.yaml并统计加载耗时(GameDB: N games on record (loaded in X.XXms),GameDatabase.cpp); - 解析与校验:
parseAndInsert()逐条解析,对 GameFix、SpeedHack、GS 硬件修复、补丁做有效性校验,非法项打印错误并丢弃;序列号统一小写化并查重; - 查询:
findGame(serial)小写化后查表返回GameEntry; - 应用核心修复:
applyGameFixes()根据用户设置决定是否自动应用——若用户关闭了自动 Game Fix(applyAuto=false),则跳过并打印Skipping ...警告; - 应用图形修复:
applyGSHardwareFixes()应用 GS 硬件修复,受ManualUserHacks开关、渲染器类型(SW/HW)影响,并在冲突时通过 OSD 提示用户; - 运行时:CRC 匹配的补丁通过
findPatch()生效;记忆卡过滤通过memcardFiltersAsString()影响 FolderMemoryCard 的存档可见性。
理解这一链路后,你就能明白:如果你在 GUI 中启用了"手动 GS 硬件修复",或关闭了自动 Game Fix,GameDB 中对应的自动修复就会被有意跳过——这不是 bug,而是设计上给予用户最高优先级的控制权。
结语
PCSX2 的 GameDB 用一份结构化的 YAML 文件,把数千款 PS2 游戏的兼容性调优经验沉淀为机器可读、可校验、可版本管理的配置资产。无论你是想在 bin/resources/GameIndex.yaml 中为某款游戏补充条目、通过 pcsx2/Docs/gamedb-schema.json 做本地校验,还是想深入 GameDatabase.cpp 理解修复的生效机制,本文梳理的字段语义、取值范围与源码调用链都能为你提供完整的地图。
【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考