Files
persona-script-editor/FORMAT.md
2026-07-17 01:04:47 +03:00

9.1 KiB
Raw Blame History

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 start
  • 10 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

  1. Unpack: Read ISO → extract E0 → parse pointer table → for each sub-file, parse strings
  2. Edit: Modify string text (respecting encoding constraints and control codes)
  3. 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 - ett bytes (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