The game's cut-scene and menu rooms (offices, changing rooms, TV studio,
stadium concourse, ...) are pre-rendered images with 3D characters drawn
on top. A .zbf is the Z buffer that goes with one of those images:
the game loads it into GS depth memory so characters are hidden behind
the rendered furniture.
There are 140 of them, one per MRG in the main background sets
BG/BG_{CH,EN,FS,IP,IS,MN,OF,OR,RR,SP,TV}_nn.MRG, always named
BG_xx_nn_00.zbf with merge user ID 4 (see PAC_FORMAT.md).
The BG_OR2, BG_P2 and BG_PP MRGs have none.
python SRC/zbf.py info DAT checks them all; python SRC/zbf.py png DAT out/ writes each one as a greyscale PNG (white = near).
No header. Always 0xE0000 bytes:
| size | 512 × 448 pixels × 4 bytes |
| pixel | little-endian u32 depth |
| order | row-major, top-left first, linear (not GS-swizzled) |
512×448 is the game's frame buffer size, so the file is a screen-space depth image.
The colour image is CSE/BG_xx_nn_00.CSP (see
CSE_FORMAT.md; the name pattern
BG_%s_%02d_00.csp is in DLL/SIMPRG.REL). It holds an embedded SVR
(at 0x190 in BG_CH_00_00.CSP): a 512×512 8bpp texture. 110 of the
151 background CSPs carry their own palette (data format 0x6C). The
other 41 use an external one (0x64). 63 of the 140 MRGs carry a set of
32 palettes, BG_xx_nn_00.svp … BG_xx_nn_31.svp. BG_CH_00_00.svp
decodes BG_CH_00_00.CSP correctly. Which of the 32 the game picks isn't
known (below).
Scaled to 512×448, that texture lines up with the .zbf pixel for
pixel: every depth edge sits on the rendered furniture, plants and
window frames. So the background is drawn as a 512×512 texture squashed
onto the 448-line screen, and the Z buffer was rendered at screen
resolution.
- Larger = nearer. The floor at the bottom of the screen has the
highest values, and open windows/sky are 0. This matches the usual PS2
setup of
ZTST = GEQUALwith the buffer cleared to 0. - Only the low 24 bits count (PSMZ24). This is inferred from the data:
BG_MN_00_00.zbfis filled entirely with0x01000000. Read as Z24 that is 0 ("infinitely far"), so characters always draw over that menu background. Read as Z32 it would be nearer than anything in any other scene, which would hide the characters. Every other file stays below0x01000000. - Ranges vary by scene. Most peak at
0xC3B9(64 files) or0xD3EE(50). The RR, IP and TV rooms go up to0x2D4C1.
Confirmed (traced for the widescreen patch,
WIDESCREEN.md): SIMPRG.REL 0xfc3a8 takes
the depth file through CLoader::getBinary and sends it with
nnuLoadImagePS2 (0x1668f0) as a 512×448 PSMZ32 image (0x30) of
0xe0000 bytes straight into the Z buffer. Other scenes' depth buffers
go the same way (SIMPRG.REL 0x408a8, 0xcace4; CEDITPRG.REL 0x1db8, 0x6bb8), and CBackgroundManager clears the Z buffer with a
zero buffer of the same shape (SIMPRG.REL 0xfe8c0).
So the upload is a plain PSMZ32 transfer. That the Z buffer itself is
PSMZ24 with ZTST = GEQUAL still comes from the data alone (above):
the frame's own Z buffer format and depth test weren't traced.
- The frame's own Z buffer format and depth test (PSMZ24 and
ZTST = GEQUALcome from the data only). - The projection that maps scene depth to these values.
- Which of a room's 32 palettes the game picks, and when
(
BG_DIR.md).