Nihuya sebe
This commit is contained in:
223
FORMAT.md
Normal file
223
FORMAT.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user