PSX Mode2/2352 disc geometry Confirmed
The disc you put in the PlayStation is where every texture, model, line of dialogue and note of music starts. Before any of those game-specific formats gets involved, the disc has its own plain geometry: a flat run of 2352-byte sectors, each carrying only 2048 bytes of real file content and 304 bytes of addressing and error-correction padding. Everything else on this site starts from that 2048-byte view.
At a glance
- Magic
- none - a 12-byte sync pattern opens every sector; files are found through ISO9660
- Where on disc
- the whole
.binimage; the Primary Volume Descriptor sits at LBA 16 - Stride
- 2352 bytes per sector, 2048 of them file content at byte 24
- Parser
crates/iso(raw.rssector reader,iso9660.rswalker,write.rsEDC/ECC re-encode,relayout.rs)- Confidence
- Confirmed - textbook CD-ROM XA / ECMA-130 geometry; every disc-gated test in the workspace reads through it
- Used by
- extraction pipeline, disc patcher, in-browser ROM patcher
Overview
A CD image (.bin) is a flat run of sectors addressed by LBA - the logical block address, a sector number counting from the start of the disc. "Mode2/2352" names the sector flavour PlayStation discs use: mode 2 of the CD-ROM XA standard, stored as full 2352-byte raw sectors rather than pre-stripped 2048-byte ones. Reading a file means knowing its start LBA and peeling the 2048 user-data bytes out of each sector.
Two things live on top of that geometry:
- ISO9660 - the standard CD filesystem that turns sector numbers into the 45 named files on the disc.
- Relayout - growing a file by whole sectors, which the official PAL discs did to fit longer translated dialogue and which a community language pack needs when its text does not fit in place.
Sector layout
Each sector is 2352 bytes. Only the 2048-byte slice in the middle is file content; the rest is the sync mark and address the drive uses to find the sector, a subheader (meaningful for streamed XA audio and video), and the error-detection and error-correction codes that let a scratched disc still read.
RawDisc::read_sector(lba) returns only the 2048-byte user-data slice at byte 24.| Bytes | Size | Field | Meaning |
|---|---|---|---|
0..12 | 12 | sync | Sync pattern 00 FF FF FF FF FF FF FF FF FF FF 00 |
12..16 | 4 | header | M:S:F address (BCD minutes:seconds:frames, lba + 150) + mode byte |
16..24 | 8 | subheader | file / channel / submode / coding (the XA streaming fields) |
24..2072 | 2048 | user data | the file content ISO9660 and every game format see |
2072..2352 | 280 | EDC + ECC | error detection + correction (Form 1 only; Form 2 XA audio sectors carry no ECC) |
RawDisc::read_sector(lba) returns just the user-data slice; read_user_data(lba, count, buf) reads a contiguous run.
const SECTOR_SIZE: usize = 2352;
const USER_DATA_OFFSET: usize = 24;
const USER_DATA_SIZE: usize = 2048;
ISO9660 walk
On top of the sector layer sits ISO9660, the standard CD filesystem - it turns "sector 16" into named files and directories. The layout is textbook:
- Primary Volume Descriptor at LBA 16.
- Root directory record at PVD offset 156.
- Each directory record begins with a length byte; records pad to even lengths.
The walker (crates/iso/src/iso9660.rs) is iterative and yields stable-sorted file paths. The Legend of Legaia (USA) disc produces 45 files:
CDNAME.TXT DMY.DAT PROT.DAT SCUS_942.54 SYSTEM.CNF
MOV/MV1.STR ... MV6.STR
XA/XA1.XA ... XA34.XA
| File | What it is | Page |
|---|---|---|
PROT.DAT | the main asset archive - nearly every texture, model, script, sound bank and code overlay is one of its 1233 numbered entries | PROT.DAT TOC |
SCUS_942.54 | the game's main executable (the resident half of the engine; the rest lives in overlays inside PROT.DAT) | Ghidra tooling |
CDNAME.TXT | a developer-left name map for the archive's entries | CDNAME map |
DMY.DAT | a sibling archive of developer test fixtures, no game content | DMY.DAT |
MOV/MV*.STR | the pre-rendered movies - PSX MDEC video in the Iki bitstream, not the common STRv2 layout; decoder crates/mdec | FMV table, cutscenes |
XA/XA*.XA | streamed voice and audio in standard CD-XA Mode 2 Form 2; crates/xa demuxes per (file_no, ch_no) straight off the raw sectors | XA audio |
History: the XA "non-standard interleave"
Early tooling reported a bespoke XA interleave. The interleave is the standard one; the apparent muxing scheme was damage from reading Form 2 sectors through a Form 1 (2048-byte) truncation. The demuxer reads raw 2352-byte sectors - see XA audio.
Full-ISO relayout
Growing a file by whole sectors - PROT.DAT, which the official PAL discs grew at mastering to fit longer localized dialogue - moves every file after it, so every on-disc reference to those files has to be rewritten. Legaia's disc makes this a small, well-bounded edit. Implementation: legaia_iso::relayout (generic ISO9660 + ECMA-130; embeds no game bytes).
The LBA reference graph
Two facts make the relayout safe (how we know):
PROT.DAT's internal TOC is PROT.DAT-relative, not absolute disc LBAs. Entry 0's TOC start LBA is identical on every region's disc even thoughPROT.DATsits at a different disc LBA per region. Growing an interior entry needs only an internal-TOC shift (PROT.DAT TOC), not a disc-wide cascade.- No file is located by a hardcoded absolute LBA in the executable. Every file is found by ISO9660 name lookup; no post-
PROT.DATfile's disc LBA appears as a literal in any USA or PAL executable.
When PROT.DAT grows by G sectors the cascade reduces to one rule: every ISO9660 LBA value > prot_lba gains +G; PROT.DAT's directory-record size gains +G*2048; the PVD volume-space size gains +G.
| Structure | Location | Edit |
|---|---|---|
| PVD volume space | LBA 16, off 80 (LE) + 84 (BE) | += G |
| Path table (LE @18 + BE @20, incl. optional copies @19/@21) | dir extents | extents > prot_lba += G |
| Directory records (root + every subdirectory extent) | rec off +2 LBA / +10 size | LBA > prot_lba += G; PROT.DAT size += G*2048 |
| PROT internal TOC | PROT.DAT byte 8+(j+2)*4 | entries after a grown one += cumulative G (PROT-relative) |
Subdirectory extents that live after PROT.DAT (MOV and XA on the retail disc) relocate too, so their self . record and file records are patched at the extent's new position.
Per-sector mechanics of a relocation
- Every sector after
PROT.DATmoves+G: its 12-byte sync + 4-byte header are rewritten so the stored MSF address isBCD(lba+150)for the new position. - Form 1 EDC/ECC are computed with the header treated as zero (
crates/iso/src/write.rs), so a pure relocation needs no EDC/ECC recompute - only the MSF header changes. Form 2 (XA) sectors carry no ECC. - EDC/ECC are recomputed only for sectors whose user data changes: the rebuilt
PROT.DATpayload, the PVD, path tables and the directory extents. - The PROT entry index space is preserved (no entries added or removed), so index-keyed same-size edits still resolve after a relayout.
Consumers: DiscPatcher::grow_prot_entries and the translate import --allow-relayout localization path (translation tooling).
How we know
| Evidence | Address / source | What it proves |
|---|---|---|
| ECMA-130 / CD-ROM XA | public standard | Sector geometry, EDC/ECC polynomial, MSF encoding |
PROT.DAT opener | FUN_8003E4E8 | The archive is found by ISO9660 name lookup, not by a hardcoded LBA |
| STR / XA path opener | SCUS path-open helper | Movies and audio are opened by path; no absolute LBA literal in any USA or PAL executable |
| USA vs PAL diff | SCES_019.44/.45/.46 | The PAL discs are a per-entry +1-sector relayout of the same structure; PROT TOC entry 0 is identical across regions (PROT-relative) |
| Disc-gated round trips | crates/iso, crates/patcher/tests/*_real.rs | Every rewritten sector stays EDC/ECC-valid; relayout preserves the entry index space |
Full page: docs/formats/disc.md.