9.1 KiB
Megami Ibunroku Persona — Event Script Format Documentation
Overview
The game stores event/dialogue scripts inside ADV\E0.BIN on the CD.
This file is a container holding 224 sub-files (individual event scripts).
1. CD Image (BIN/CUE)
- Format: MODE2/2352 (raw CD-ROM XA)
- Sector size: 2352 bytes
- User data offset: 24 bytes from sector start
- User data size: 2048 bytes per sector
The game uses internal file tables (not ISO9660) to locate files:
- FSECT (LBA 634): array of uint32_le, each entry = starting LBA of a game file
- FSIZE (LBA 623): array of uint32_le, each entry = size in bytes
- E0.BIN is at index 273 in both tables
2. E0 Container Format
┌─────────────────────────────────────────────┐
│ Pointer Table (variable length) │
│ uint16_le[N+1] pointers │
│ Terminated by 0x0000 │
├─────────────────────────────────────────────┤
│ Padding to 0x800 alignment │
├─────────────────────────────────────────────┤
│ Sub-file 0 (aligned to 0x800) │
├─────────────────────────────────────────────┤
│ Sub-file 1 (aligned to 0x800) │
├─────────────────────────────────────────────┤
│ ... │
├─────────────────────────────────────────────┤
│ Sub-file N-1 │
└─────────────────────────────────────────────┘
Pointer Table
| Offset | Type | Description |
|---|---|---|
| 0 | uint16_le | Pointer to sub-file 0 (in 0x800-byte units) |
| 2 | uint16_le | Pointer to sub-file 1 |
| ... | ... | ... |
| N*2 | uint16_le | End-of-data pointer (marks end of last sub-file) |
| (N+1)*2 | uint16_le | 0x0000 (terminator) |
- Original E0 has 225 entries (224 sub-files + 1 end marker)
- To get byte offset:
pointer_value * 0x800 - Sub-file N size:
(ptr[N+1] - ptr[N]) * 0x800
3. Event Script Sub-file Format
Each sub-file has:
┌─────────────────────────────────────────────┐
│ Sub-file Header (8 bytes typically) │
├─────────────────────────────────────────────┤
│ Script Data Section │
│ ├── Event Command Table (offsets 0x00-0x60+)│
│ ├── Script Bytecode │
│ ├── String Pointer Table │
│ ├── Text Data (strings) │
│ └── Trailing Data │
└─────────────────────────────────────────────┘
Sub-file Header
| Offset | Type | Value | Description |
|---|---|---|---|
| 0 | uint16_le | 8 | Header size in bytes |
| 2 | uint16_le | 0x8010 | Marker (always 10 80) |
| 4 | uint16_le | varies | (purpose TBD) |
| 6 | uint16_le | 0x8010 | Marker (always 10 80) |
Script Data Section
The data section starts immediately after the header (offset = hdr_size).
All offsets below are relative to the start of the data section.
Key Fields
| Offset | Type | Name | Description |
|---|---|---|---|
| 52 | uint16_le | ett | End of text table / start of text blob area |
| 96 | uint16_le | table_ptr | Offset to string pointer table within data |
If table_ptr == 0xFFFF, the sub-file has no dialogue strings.
String Pointer Table
Located at data[table_ptr]. Entries follow this pattern:
FF 55 00 00 [ptr_lo] [ptr_hi] 10 80
FF 55 00 00= prefix marker (4 bytes before the pointer)ptr_lo, ptr_hi= uint16_le offset within data section pointing to string start10 80= suffix marker
The table continues until a different pattern is encountered.
To find all strings, scan from table_ptr looking for FF 55 00 00 XX XX 10 80 sequences.
4. Text Encoding
Single-byte characters (0x01-0x7F)
Originally mapped to Japanese kana. Values 0x01-0x7F are indices into the font file.
| Range | Original Content |
|---|---|
| 0x01-0x2E | Hiragana (あ-ん) |
| 0x2F-0x5E | Katakana (ア-ン) |
| 0x5F-0x7F | Extended katakana + marks |
For Russian translation, these are remapped to Cyrillic:
| Range | Content |
|---|---|
| 0x01-0x42 | А-я (66 letters + Ё/ё) |
| 0x43 | Space |
Two-byte characters (0x80xx)
High byte 0x80+ triggers a two-byte read. The pair forms a code looked up in the TBL file.
Common punctuation codes:
| Code | Character |
|---|---|
| 80 A5 | . (period) |
| 80 CB | : (colon) |
| 80 CC | (JP space) |
| 80 D0 | ? (question) |
| 80 D1 | ! (exclaim) |
| 80 D5 | , (comma) |
| 80 E1 | - (dash) |
Control codes (0xFF xx)
| Code | Parameters | Name | Description |
|---|---|---|---|
| FF 00 | none | [ff00] | Unknown/NOP |
| FF 01 | none | (terminator) | End of string |
| FF 02 | none | [end] | End of dialogue sequence |
| FF 03 | none | [nl] | Newline |
| FF 04 | none | [clear] | Clear text box |
| FF 05 XX 00 | 1 byte + 00 | [wait=XX] | Pause for XX frames |
| FF 06 XX | 1 byte | [color=XX] | Set text color |
| FF 07 | none | [firstname] | Insert player's first name |
| FF 08 | none | [nickname] | Insert player's nickname |
| FF 09 | none | [ff09] | Unknown |
| FF 0A | none | [ff0a] | Unknown |
| FF 0B | none | [ff0b] | Unknown |
| FF 0C | none | [ff0c] | Unknown |
| FF 0D | none | [ff0d] | Unknown |
| FF 0E XX | 1 byte | [choice=XX] | Display choice menu (XX = menu ID) |
| FF 0F | none | [lastname] | Insert player's last name |
5. Font File
- Located at game file index 5 in FSECT/FSIZE
- Size: 65536 bytes
- Glyph size: 32 bytes each (16x16 pixels, 1bpp, 2 bytes per row)
- Glyph index N is at byte offset
N * 32 - Indices 0x01-0x7F correspond to single-byte text codes
- Indices 0x80+ correspond to two-byte text code second bytes (TBL lookup)
6. TBL File (Persona_jap.tbl)
Plain text, UTF-8, format: XXXX=char per line where XXXX is hex code.
Example:
8090=漢
80A5=。
80CB=:
80CC=
80D0=?
80D1=!
80D5=、
The hex code is the 2-byte value as it appears in the script (big-endian in the TBL, but stored little-endian in the binary when the injector tool writes it).
7. Workflow for Translation
- Unpack: Read ISO → extract E0 → parse pointer table → for each sub-file, parse strings
- Edit: Modify string text (respecting encoding constraints and control codes)
- Repack: Encode strings → rebuild sub-file (update string pointers) → rebuild E0 container → patch ISO
Constraints when editing:
- New text blob must fit within
sub-file_size - ettbytes (or sub-file must be resized) - String pointer table positions are fixed (they're part of the script bytecode)
- Only the text area (after
ett) is safe to resize - If sub-file grows, the E0 container must be relocated in the ISO
8. Statistics (Original Japanese Rev 1)
- E0 container: 1,828,864 bytes (893 sectors)
- Sub-files: 224
- Sub-file sizes: 6,144 - 34,816 bytes
- Total dialogue strings: ~2,500 across all sub-files
- Sub-files with no strings (table_ptr=0xFFFF): ~27