Skip to content

TALK.DAT

ProgSys edited this page Sep 8, 2024 · 68 revisions

TALK.DAT is a container that holds Talk scripts, which are to the most part a linear scripting language designed for in-game conversations and menu options.

It is located at SUBDATA.DAT->START.DAT, START.DAT (needs to be decompressed first).

Original work has been done by Krisan Thyme by his Toolpack.

File structure

Header

Type Size Description
uInt 4 byte Number of scripts
uInt 4 byte Number of scripts again

For each script (32 byte):

Type Size Description
uInt 4 byte Start address (The header size is not counted, therefore is first value is 0)
uInt 4 byte The script id
uShort 2 byte DungeonId
uShort 2 byte Unknown Search Flag (mostly 0-2, 102-111)
uShort 2 byte Game state filter positive size (from 0-4)
uShort 2 byte Game state filter negative size (from 0-4)
uShort 2 byte Game state filter positive 0
uShort 2 byte Game state filter positive 1
uShort 2 byte Game state filter positive 2
uShort 2 byte Game state filter positive 3
uShort 2 byte Game state filter negative 0
uShort 2 byte Game state filter negative 1
uShort 2 byte Game state filter negative 2
uShort 2 byte Game state filter negative 3

To find the size of each talk script, subtract the start address of the next script from the start address of the current script.

How a script is chosen by the game

The game chooses a script based on a combination of ID, Dungeon ID, and some Unknown Flag. Afterwards the game checks the current state of the game (probably from the save file), but only if any are given, i.e the size is bigger 0. If these checks pass, then the script is chosen. Otherwise it searches until it finds one.

The positive filter tests if a bit is set, while the negative tests if a bit is not set. The first 3 bits of "game state filter" are used to create a bit mask for checking against a global game state, determined by the rest of the bits:

struct DisaGameStateFilter {
    unsigned short bitIndex: 3; //the bit that should be tested (same as x & 7)
    unsigned short index: 13; //the index of a gamestate (same as  x >> 3)
    inline unsigned short getIndex() const noexcept { return index; } 
    inline byte getMask() const noexcept { return 1 << bitIndex; }
};

const byte mask = gameStateFilter.getMask(); // Create a bit mask (0-7)
const byte state = (globalStateStartPtr)[gameStateFilter.getIndex()]; // Get the state to check
return (state & mask) != 0; // Positive: When true then script is valid
return (state & mask) == 0; // Negative: When true then script is valid

Known Flags

Name Index Bit Description
Skip Story 275 0 When set then the story at the beginning of a stage should be skipped

Scripts

Two script languages are used: TALK and SCRIPT. Each has its own unique commands, though some commands are shared between them. They serve different purposes in the game:

  • TALK: Manages dialogue and serves as an entry point to game levels.
  • SCRIPT: Handles a broader range of in-game functions and effects.

What TALK can do

  • Play dialog in the game
  • Show character images and animations
  • Opening menus like the area select, shop, assembly, etc
  • Execute scripts from SCRIPT.DAT

What TALK can not do

  • Controll the camera
  • Spawn units on map and play there animations (for cutscenes)
  • Control sounds and background musik

All other effects are achived with the scripts within SCRIPT.DAT.

Commands overview

Each command consists of a op code (byte) and a body with arguments.

Name Op Code Arguments Arguments Size Description
Dialog 01 Display string in Shift JIS. x + 1 byte Display dialog
Confirm 02 None 0 byte Wait for user to press confirm to continue dialog
ConfirmClose 03 None 0 byte Like Confirm, however it will close the dialog box
CharLeft 04 Slot, seed and animation, modefier 2 + 2 + 1 byte Display image in slot at left.
Portrait 05 Character portrait Id 2 byte Character portrait to display
Voice 06 Id of dialog 2 byte Play character dialog
SpeechBubble 07 Bubble type, arrow position 1 + 1 byte The style of speech bubble.
NameLabel 08 uShort name id, Char label position 2 + 1 byte Display name lable
Set 09 Set a game state flag 2 byte Set a bit in game state
Clear 0A Clear a game state flag 2 byte Clear a bit in game state
Script 0B Id of script from SCRIPT.DAT 3 byte Exectue script form SCRIPT.DAT
Call 0C Id of talk script 3 byte Exectue another talk script
MenuStart 14 Number of entries, followed by string of first entry and it's bransh code 1 + x * y byte Defines the start of a menu.
MenuEntry 14 String of entry and it's bransh code x * y byte Defines consequent menu enries after MenuEntry.
ShowBox C9 char (Boolean) 1 byte Will open background box.
CharRight 18 Slot, seed and animation, modefier 2 + 2 + 1 byte Display image in slot at right.
CharMid 0E Slot, seed and animation, modefier 2 + 2 + 1 byte Display image in slot at center.
LoadImg 64 slot * 10000 + BUImageId 3 byte Load a BU** Image into a slot.
ConfirmAuto 65 delay, delayAlt, boolean to close the dialog box 2 + 2 + 1 byte Will automatically ConfirmClose or Confirm after given delay.
NOP FA char 1 byte Does nothing skipping a byte, used to skip 1 byte menu commands.
MenuEnd FD None 0 byte Marks the end of conversation selection.
Return FF None 0 byte Will terminate script.
Restart FE None 0 byte Restarts the script from the beginning. Usually used in connection with menus.

Commands detailed overview

Dialog

  • Op Code: 01
  • Construction: 01 XX XX 00
  • Arguments: Zero terminating string in Shift JIS.

Will open the dialog box and display the given string inside. The string can't be larger then 128 bytes (or the memory will bleed over), must be encoded in Shift_JIS and be terminated by a 0 byte. You can have up to 3 dialog commands, each indicating the row inside the text box. The text also will be animated, appearing letter by letter.

Confirm

  • Op Code: 02
  • Construction: 02
  • Arguments: None

Will pause and prompt the user to press continue between dialog lines. Usually used when the same character continues talking.

ConfirmClose

  • Op Code: 03
  • Construction: 03
  • Arguments: None

Will pause and prompt the user to press continue between dialog lines. But unlike Confirm this will close the dialog box on confirmation. This is usually used when a different character starts talking. Or when the SpeechBubble command is used to change the stlye of it to play a nice transition animation.

ConfirmAuto

  • Op Code: 65
  • Construction: 65 11 11 22 22 33
  • Arguments: delay, delay alternative (language), continue or confirm

Will pause, however it will not wait for user input, instead it will automatically trigger ConfirmClose (false) or Confirm (true) after a given delay depending on last boolean argument. Also user can't skip forward. There are two delay timers, the first is base. The second is used if not zero and a certain game state flag is set (probably language, so delay is in sync with the audio track). For example it is used in the cutscene where Laharl interrupts Vyers..

LoadImg

  • Op Code: 64
  • Construction: 64 00 00 00
  • Argument: slot * 10000 + BUImageId (3 byte)

Before an character image can be used it must be loaded into a slot so it can be refereced later. LoadImg takes one argument, which is a combination of the BU** image id, plus the slot times 10000: slot * 10000 + BUImageId. For example, 50103, will load BU0103.TX2 (angry Laharl) from DATA.DAT into slot 5. The total number of slots is 7. The image is loaded asynchronous. If you attempt to use an image from a slot that has not been fully loaded, the game will crash! Thus call script(0); to force the game to wait for the image to be loaded.

CharLeft/CharMid/CharRight

  • Op Code: 04/0E/18
  • Construction: 04/0E/18 00 11 11 22
  • Arguments: Slot Id (2 byte), Animation speed and type (speed * 100 + type)(2 byte), Modefier (1 byte)

Display image in slot at position defined and default orientation by op code. Image must have been fully loaded with LoadImg otherwise the game will crash.

The way the character image enters the frame is determined by the second argument, which is a combination of speed and type: speed * 100 + type. The type indicates the entry animation, while the speed determines the speed of this animation. Lower speed values mean slower animations, with 0 resulting in an instant appearance.

For example, a value of 1002 means the image will slide from the right (2) to it's target position at a slow speed of 10.

Known animation types:

  • 0 - INSTANT
  • 1 - SLIDE_FROM_LEFT
  • 2 - SLIDE_FROM_RIGHT
  • 3 - SLIDE_FROM_LEFT_TO_CENTER
  • 4 - SLIDE_FROM_RIGHT_TO_CENTER
  • 5 - FADE_IN
  • 7 - SLIDE_FROM_BOTTOM
  • 9 - SLIDE_FROM_TOP
  • 11 - SLIDE_TO_LEFT
  • 13 - SLIDE_TO_ALMOST_LEFT

The Modefier is a bit mask, with only two bits. The fist will mirror the image vertically. The second will offset the image down.

SpeechBubble

  • Op Code: 07
  • Construction: 07 00 11
  • Arguments: Bubble type (1 byte), Arrow position (1 byte)

Defines the style and position of the arrow of the character that is speeking.

Bubble types:

  • 1: Normal
  • 2: Shouting
  • 3: Inner thought

The arrow position is defined from left to right with the corresponding values 1 to 4. Some bubble types don't support arrows.

NameLabel

  • Op Code: 08
  • Construction: 08 00 00 11
  • Arguments: Name Id (2 byte), Label position (1 byte)

Display a name tag at given position. The position is defined from left to right with the corresponding values 1 to 4. If Id is -1 or position is out of bounds then name tag will not be displayed.

Script

  • Op Code: 0B
  • Construction: 0B 00 00 00
  • Arguments: Script Id (3 byte)

Execute a script from SCRIPT.DAT. The script will run asynchronous. To wait for the script to finish call script with id 0: script(0);. A script from SCRIPT.DAT is used to control the camera, spawn cutscene characters, play sound effects and more.

Call

  • Op Code: 0C
  • Construction: 0C 00 00 00
  • Arguments: Talk script Id (3 byte)

Execute a script from TALK.DAT. This will completely stop the current script execution and start a new script. The game has not call stack, so after the called script finished, the game will not continue with the previous script! Also many settings done by other commands will be reset.

Menu

A menu is created using branching instructions, with MenuStart to begin the menu, including the first entry, and MenuEntry for each additional entry and branching path. MenuEnd indicates the end of the menu and where the code execution will continue after the menu is closed. Basically it functions like a switch case.

Example:

MenuStart(3, “First entry”);
//code for entry 1
MenuEntry(“Second entry”);
//code for entry 2
MenuEntry(“Third entry”);
//code for entry 3
MenuEnd();
//code after menu is closed

MenuStart

  • Op Code: 14
  • Construction: 14 NN 01 STRING 00 BRANSH_CODE…
  • Argument: Number of entries (1 byte).

MenuStart initializes the menu. The first argument specifies the total number of menu entries (including the initial entry and any MenuEntry entries). After this, there is a '01' byte, a null-terminated string for the first entry, and the branching code that will execute when this entry is selected. The string should not exceed 128 bytes and must be encoded in Shift-JIS.

It's now allowed to have sub menus directly, for that you must call another talk script inside the brash code.

(Note, the '01' is not the same as the Dialog command. In fact it's not even required in all cases, the game mainly use it to search for 0x1401.)

MenuStartLogic

MenuEntry

  • Op Code: 14
  • Construction: 14 01 STRING 00 BRANSH_CODE…
  • Argument: None.

MenuEntry adds additional entries to the menu after MenuStart is defined. The total number of MenuEntry instances should match the number specified in MenuStart minus one. Apart from not requiring an argument, it is constructed equally to MenuStart.

MenuEnd

  • Op Code: FD
  • Construction: FD
  • Argument: None.

Marks the end of the menu and the point where the code will continue after the menu is closed. Note this is solely a marker, if it where to be reached then it will be treated the same as return. Use NOP to skip it if needed.