Skip to content

FINAL FANTASY XII THE ZODIAC AGE: LZ4 VBF blocks and Phyre programs in main; new profile - #2528

Open
gxt43 wants to merge 1 commit into
seedds:mainfrom
gxt43:ff12-tza
Open

gxt43 wants to merge 1 commit into
seedds:mainfrom
gxt43:ff12-tza

Conversation

@gxt43

@gxt43 gxt43 commented Nov 12, 2026

Copy link
Copy Markdown

What and why

FINAL FANTASY XII THE ZODIAC AGE (0100EB100AB42000) showed a black screen after the logos (music and input worked). Two split gaps left about half its shaders out of the map:

  • VBF blocks are raw LZ4. The SRYK archives match FFX/X-2's layout, but compressed blocks are raw LZ4 blocks, not zlib, so vbf.py stopped each archive at its first block (Error -3 ... incorrect header check (its shaders are left out)). vbf.read now decodes a block as zlib when it is one whole stream of the block's size and as raw LZ4 of exactly that size otherwise (vbf.block).
  • Phyre programs in main. main holds 23 PhyreEngine built-in programs as code area + control section pairs, unaligned and outside any RYHP container, which raw_shaders cannot attribute (7 red "no code area" lines; the unaligned ones were never examined). phyre_main runs the existing phyre_shaders on main for games whose files are Phyre's (.vbf / .phyre).

Shaders: 3,100 → 6,454. All 32 programs DM_NVN_SHDUMP saved before the fix are in the new map.

Also a new profile (depth_mode zero; dual_want.tsv with 20 dual-source pixel shaders, without which the cursor highlight, icons and cutscene backgrounds drew nothing), its note, games-table row, and the reference entry LZ4 blocks in FFXII's VBF archives and Phyre programs in main.

Checked

  • Tests: dm/gfx/tests/test_vbf.py (new LZ4 and Phyre-in-main cases), all dm/tools/tests/test_split_*, test_docs, test_game_profile; docs_symptoms.py --check.
  • Games run: FINAL FANTASY XII THE ZODIAC AGE 1.1.0, about 30 minutes: logos, title, menus with cursor highlight, dialogue with button icons, a battle, cutscenes; 30 fps, no not in the shader map and no no dual-source entry point lines.
  • Devices and OS: Apple M3 Max, macOS 27.3.
  • Not run: iPhone; scripts/regress.py. phyre_main also runs for FFX/X-2 (it has .vbf files); its main was not checked for such pairs, as I don't have that game.

Docs

  • The finding is in its game note and its docs/reference/shaders.md entry, and python3 dm/tools/docs_symptoms.py was run
  • A chain tool changed: n/a (vbf.py and shader_split.py are split tools, not chain tools)
  • No game files, keys or data extracted from a game in the change or the attachments

Open, in the game note: one texture with a blue stripe (seen once); [RED] BeginRecording re-entered about once a frame, with no visible effect.

… the shader split reads FFXII's VBF archives, whose blocks are raw LZ4, and PhyreEngine's built-in programs in main

Every frame was black after the logos while music played and the game took input. The split logged "[RED] FFXII_TZA.vbf: error: Error -3 while decompressing data: incorrect header check (its shaders are left out)" (the same for FFXII_TZA_PATCH.vbf) and seven "main control section @...: no code area" lines and found 3,100 shaders, 3,028 of them in main's GLSLC outputs; the run printed "[RED] shader ... is not in the shader map" for 27 keys in the first minute and "program has no vertex shader". The SRYK archives have FFX/X-2's layout, but their compressed blocks are raw LZ4 blocks (no frame, no size prefix; gamedata/nxgamesetting.ini's block opens with the token f6 90 and then "Language="), so vbf.py's zlib stopped each archive at its first compressed block. And main holds 23 of PhyreEngine's built-in programs in Phyre's own form, the code area right before its control section, unaligned, 9 bytes between pairs, with no RYHP container; nothing points at them in a form raw_shaders follows, so the aligned ones were left out with a red line and the unaligned ones never looked at.

vbf.read now takes a block that is one whole zlib stream of the block's size as before and any other compressed block as a raw LZ4 block of exactly that size (vbf.block); a block that is neither stops the member with an error. shader_split.py's phyre_main runs the existing phyre_shaders (same header, length and stage checks) on main for a game whose files are Phyre's (a .vbf archive or a .phyre effect), before raw_shaders, which then leaves those control sections alone. The split now finds 6,454 shaders (5,999 pixel, 371 vertex, 84 geometry; 3,051 from main, 3,403 from the archives and loose files); all 32 programs DM_NVN_SHDUMP saved up to the first cutscene are among them (25 in the archives, 7 in main).

New profile dm/games/0100EB100AB42000 from the provisional one, with depth_mode zero (the game sets near = 0, so the bundled pipeline archive was built for the wrong depth mode) and dual_want.tsv: 20 pixel shaders blend with their output 1 as the second source, and without the dual-source entry point the menu cursor's highlight, button and character icons and most cutscene backgrounds drew nothing (listed with DM_NVN_DUAL_WANT over menus, dialogue, a cutscene and a battle). Its note and games-table row; a reference entry (LZ4 blocks in FFXII's VBF archives and Phyre programs in main).

Checked: test_vbf.py (new cases: LZ4 beside zlib blocks, a block that is neither, Phyre pairs in a main-like blob read only for a Phyre game and then not reported by raw_shaders), all test_split_*, test_docs, test_game_profile. On an M3 Max: logos, title, menus, dialogue, a battle and cutscenes at 30 fps, no shader missing from the map and no dual-source red line. Not run: the iPhone, regress.py; FFX/X-2's main was not checked for such pairs (phyre_main runs for it too). Open: one texture with a blue stripe, once; "[RED] BeginRecording re-entered" about once a frame, with no visible effect.
@github-actions github-actions Bot added nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) packing Building an IPA or a Mac app: the NSP script, extraction, the shader split, the packers docs Documentation game: 0100EB100AB42000 A game new game Adds a game profile that main does not have yet labels Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation game: 0100EB100AB42000 A game new game Adds a game profile that main does not have yet nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) packing Building an IPA or a Mac app: the NSP script, extraction, the shader split, the packers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant