Symphonic Rain:Technical Documentation
From TLWiki
Contents |
[edit] File Format: .kgo script
Note: This documentation may be out of sync with the actual interpretation. Use at your own risk.
=================================== KOGADO Kuroneko Team - .kgo script file format / Scene.tbl
== KOGADO KGO SCRIPT FILE FORMAT == Documented by RasqualTwilight
=================================== Revision: v.1.0-RC2 2007-10-09
= Introduction =
This document describes the files used in the adventure mode of games created by Kogado's Kuroneko-san Team.
Although efforts have been made to keep it accurate for the various covered
games, no warranty is made as for the exactitude of the present document.
= Document technical conventions =
#######################################################################
The structure definitions in this document use datatypes found in Win32 programming.
* Byte order is Little-endian unless specified otherwise
(datatypes beginning with BE are Big-Endian byte-ordered)
For instance,
0 1 2 3 4 5 6 7 8 9 A B C D E F
00 00 00 00 00 00 00 00 82 E6 82 EB 82 B5 82 A2
the value at offset 8 is 0xEB82E682 in LE order.
* a BYTE is an unsigned 8-bit variable (uint8)
a CHAR is an 8-bit variable (char) which represents a character, comprised between 0 and 255.
** A C-style string ("NUL-terminated string") is a
sequence of characters whose value is not 0, followed by a 00 byte.
* a WORD is an unsigned 16-bit variable (uint16). Ranges [0-65535] included.
* a DWORD is an unsigned 32-bit variable (uint32). Ranges [0-2^32-1] included.
It may also be used to represent a 32-bit memory address.
* [] indicate an array. Subscript indices start at 0. Array sizes are in decimal.
a CHAR[] may also be the notation for a C-style string type.
In particular cases, if the width is fixed, there may be no need to terminate the string with a NUL byte.
Anyway, the document will explicitly state which convention is used.
* numbers prefixed with a "0x" string are in hexadecimal base
See http://wiki.xentax.com/index.php/DGTEFF if you are unfamiliar with these terms.
#######################################################################
= .kgo File Format =
The .kgo files are so-called scripts, prepared in a special formatting that
define a succession of actions affecting the game as presented to the user,
such as displaying a message, playing an animation made of successive bitmaps,
branch based on choices, etc.
** Each script may contain zero, one or more scenes
** Each script defines at least one function. Functions are entrypoints.
** While each scene is associated to a function,
not all functions are accessed through a scene identifier.
In other words, a script may EXPORT a function solely for use in other scripts.
For instance, in Symphonic Rain, kgo0182.kgo defines no scene but exports SCR0182::Func_PassWord.
** Several scene identifiers may point to a single function.
It means there can be more scenes than functions in a script.
It is up to the game engine to select which scene will be selected
when starting in scenario mode.
For example, Symphonic Rain defines two start routes at the main screen:
the Al Fine and Da Capo modes.
However, in "Dear Pianissimo Refrain" (and maybe later versions),
the Scene-Function association is missing. It can be assumed that
they are linked in the order they appear respectively, although this
does not prevent having more functions than scenes.
The general structure of a .kgo script is:
* Kgo Header:
** Fixed Header
** Variable Header (Scene Descriptors)
* Functions Data
* Special Strings ("Dear Pianissimo Refrain" and higher)
* Message Table
== Header ==
The beginning of the file is made of a header which always has a fixed part
and may also contain a variable part.
As you may suppose, the game engine has undergone various improvements
over time. The latest version available at the time of this writing
is featured in "Dear Pianissimo" and "Dear Pianissimo Refrain" (Fortell 2.00),
hereafter referred to as "DP".
Games using the Fortell engine are
* AC Angelic Concert (2001-01-19)
* AS Angelic Serenade (2002-03-29)
* ASDVD Angelic Serenade umaretabakari no Love Song (2003-03-19) - with plug-ins
* SR Symphonic=Rain (2004-03-26)
* ACE Angelic Concert Encore (2004-12-03)
* SRTE Symphonic=Rain Treasure Edition (aisouban) (2005-06-24)
* ASN Angelic Serenade Rabbie aisouban (2005-12-22)
* DP Dear Pianissimo (2006-08-11)
* DPR Dear Pianissimo Refrain (2007-06-29)
The only engines being considered in this document are SR, SRTE, ACE (roughly the same)
and DP.
== Fixed Header ==
The size of the fixed part is as following:
* SR/SRTE/ACE: header 0x34 (52) bytes
* DP: header 0x40 (64) bytes
Here is a possible interpretation of the fixed header:
struct KgoScriptHeader // 0x34 or 0x40 bytes
{
[00] CHAR[4] GameTag; // e.g. "SR01" "AE01" "DP01" "DP20" actually unchecked by the program
[04] DWORD ScriptFilesize; // size of current script
// useful, because .kgo scripts are usually contained
// in a HyPack-compressed archive, e.g. script.pak)
[08] DWORD ScriptNumber; // current script's number
[0C] DWORD ?CRC?; // unknown
//» #ignored. Maybe used in earlier versions.
[10] DWORD KgoFixedHeaderSizeIgnored;
[14] DWORD KgoVariableHeaderSizeIgnored;
[18] DWORD SceneDescriptorsCountIgnored;
//»
[1C] DWORD KgoHeaderSize; // The .kgo header contains a fixed part plus an optional variable part
// #SR01, AE01: includes fixed part 0x34 (52) bytes
// #DP01,DP20: includes fixed part 0x40 (64) bytes
// if (KgoHeaderSize > fixed part size)
// @offset 0x34/0x40: array KgoSceneDescriptor[SceneDescriptorsCountIgnored]
// Note: also possible to rely on [10-1B] info to determine this size,
// however [10]+[14] is not necessarily aligned on a boundary thus may be != KgoHeaderSize
[20] DWORD KgoFunctionDataSize; // See "Format of Kgo Function Data" section below for details on this area
//» #ignored. Maybe used in earlier versions.
[24] DWORD KgoFunctionCountIgnored;
//»
//» #DP01: ignored. Use [34-3F] instead
// #DP20: used for non-dialogue text, such as scene names, maybe function calls (:: notation).
// Note that scripts that return to main menu generally have [2C] set to zero.
// The format of the region is documented below.
[28] DWORD TextOffset; // set if TextLength is not zero. Normally equals (HeaderSize + KgoFunctionDataSize)
[2C] DWORD TextLength; // May be zero. @offset: (TextOffset + TextLength) may be before EOF because of memory Alignment
[30] DWORD MessageEntriesCount; // Number of strings in message table
//»
// #SR01,AE01: fixed header ends here
//» #DP01,DP20: specific fields start here.
[34] DWORD TextSectionOffset; // Offset of Text Section
[38] DWORD TextSectionSize; // Section ends at last WORD-aligned '00' byte
[3C] DWORD MessageEntriesCount2;// Number of strings in ext message table
//»
};
== Variable Header (Scene Descriptors) ==
A single script may contain zero, one or several scenes.
This comes right after the fixed header, but can also be absent if the script defines no scene.
* Starts at file offset 0x34 or 0x40 depending on engine version.
* Check KgoScriptHeader::KgoHeaderSize and/or KgoScriptHeader::KgoVariableHeaderSizeIgnored
to know whether it is valid to read at this offset.
* If there are several functions in a script, the layout is:
FIXHEAD
VARHEAD << described here
DATA1
DATA2 etc. (one for each Func, not scene)
MSG
struct KgoSceneDescriptor // variable size
{
[00] WORD SizeOfSceneDescriptor;
//» #SR01,AE01: 0x20 (32) (offsetof(descriptor_i) == 0x34 + i * 0x20)
// #DP01,DP20: variable (because of memory alignment)
//» #SR01,AE01: Aligned block size necessary for scene name.
[02] WORD SceneNameAllocSize;
//» #DP01,DP20
[02] WORD ScriptNumber;
//»
//» #SR01,AE01: Script containing the scene
[04] WORD ScriptNumber;
//» #DP01,DP20: Always 0, ignored
[04] WORD ZeroFieldIgnored;
//»
//» #SR01,AE01
[06] WORD ?SomeSize?;
//» #DP01,DP20
[06] WORD SceneNameAllocSize;
//»
//» #DP20
[08] DWORD Ignored; // Offset is always function's (0x0A + KgoData::SceneFuncnameAllocSize)
//» #others
[08] DWORD OffsetInData; // Offset in the KgoData section of .kgo (bytecode offset)
//»
//» #DP20
[0C] WORD ?ZeroFieldIgnored?;
//»
[0C+x] DWORD SceneID; // ID defined in script header (a script may contain several scenes)
[10+x] DWORD SceneID2; // ditto
[14+x] CHAR SceneName[SceneNameAllocSize];
// NUL-terminated scene name.
// #DP01,DP20: Zero-padded to closest upper WORD boundary.
};
The scene ID's are used in the scene hashtable
(see section "Scene.tbl file format (HashTable)" for details)
The name of the first scene to be loaded in story mode is game-dependant.
In SRTE, it is either a01 (Al Fine) or t01 (Da Capo).
== Format of Kgo Function Data (KgoFunctionDataSize bytes) ==
Starts at file offset KgoScriptHeader::KgoHeaderSize and has
size KgoScriptHeader::KgoFunctionDataSize.
Repeated KgoScriptHeader::KgoFunctionCountIgnored times.
struct KgoData // variable size
{
//» #SR01,AE01
[00] DWORD SizeOfFuncData; // (=KgoFunctionDataSize if only one Func)
//» #DP01,DP20
[00] WORD SizeOfFuncData;
[02] WORD ZeroFieldIgnored;
//»
[04] WORD SceneFuncnameAllocSize;
//» #SR01,AE01
[06] WORD ZeroFieldIgnored; // Let extra = 2
//»
[06+extra] DWORD SceneDataSectionSize; // Section ends at last WORD-aligned '00' byte
[0A+extra] CHAR[SceneFuncnameAllocSize] SceneFuncname[SceneFuncnameAllocSize]; // NUL-terminated and Zero-padded Function name
[yy] CHAR[Remainder] SceneDataSectionBlob; // yy = 0A+extra+SceneFuncnameAllocSize; Remainder = SizeOfFuncData - yy;
};
[zz] CHAR[tt] PADDING; // Pads to next WORD boundary
=== Format of KgoData::SceneDataSectionBlob ===
The data block is made of a simple assembly-like language that could be disassembled into mnemonics
(human-readable virtual machine operations).
Each mnemonic is associated to a WORD value between 0 and a version-specific limit representing the command.
This language also defines an argument stack for passing values to called services.
For instance:
The 0x0 (00 00) command is NOP (No-Operation)
0x1 (01 00) command is PUSH: loads a DWORD onto the stack, that is to say is followed by a DWORD value.
0x72 (72 00) is AVGPAUSE and takes zero argument.
There are two types of mnemonics:
* Mnemonics that are "read-ahead", that is to say require to read more than just the WORD value.
They are a minority (in parenthesis, meaning of read-ahead value):
PUSH (DWORD:value), JMP (DWORD:offset), JF (DWORD:offset), JT (DWORD:offset), JMPPLUS (int32:offset)
** Here's an example stream pushing a value: 01 00 C0 03 00 00 = PUSH(3c0)
** Here's a JMP that serves no purpose: 05 00 06 00 00 00 = JMP(+6)
* Mnemonics that require zero, one or more arguments obtained from the argument stack
** For instance, 0x4B plays a voice file.
01 00 EB 03 00 00 = PUSH(3eb)
4B 00 = PlayVoice(Arg1)
and the DWORD 3eb is removed ("popped") from the stack.
The argument stack is augmented by instructions such as PUSH of course, but some called functions also
modify the stack after they are called. For instance, PUSHCMPGT takes 2 arguments (removes them) and
pushes a value on the stack depending of the result of the comparison. Another example is
AVGPLACESELECT, which takes no argument and repushes a value on the stack.
Arguments are pushed Left-To-Right when calling a function.
It can be seen with the AVGCHOICE mnemonic which takes 4 arguments (string references), but ignores
string references set to zero. For example, the used VM instructions coumd be:
PUSH "Choice #1" # Actually pushing a DWORD value, the assembler takes care of the string-to-integer translation
PUSH "Choice #2"
PUSH 0
PUSH 0
AVGCHOICE
And choice options are presented in this order on the game screen.
== Format of TextSection ==
The Text Section contains all strings used in the script. It can be:
* Scene identifiers ("bt03")
* Function identifiers ("SCR0183::Func_GrandEnd")
* Game scenario dialogue line
* Choice label
This section is simply an aggregation of String Blocks, with the following information
struct KgoStringBlock // variable size
{
[00] WORD StringBlockSize; // rounded to upper WORD boundary
[02] CHAR[StringBlockSize - 2] StringEntry; // Text, or scene name, NUL-terminated and zero-padded.
};
Those blocks are indexed by their order of appearance and may be displayed in the
scene using the appropriate functions.
Indexing starts at 1 (i.e. PUSH 1 refers to the first string block of the text section).
=== Format of Text [24] ("Special Strings") for DP20 ===
* Scene identifiers ("inter01")
* Function identifiers maybe ("SCR0183::Func_GrandEnd")
struct KgoSpecialStringBlock // variable size
{
[00] WORD SpecialStringBlockSize; // not rounded
[00] WORD Unknown; // always 3? - is not (SpecialStringBlockSize / 4)
[02] CHAR[StringBlockSize - 4] SpecialStringEntry; // Text, or scene name, NUL-terminated.
};
Indexing starts at 0.
= Scene.tbl file format (HashTable) =
This file references the game scenes, with information such as which
script file contains a given scene.
== Flat Organization ==
struct SceneTable // 0x8 or 0xC + variable size
{
//» #DP20
[00] CHAR[4] GameTag; // e.g. "DP20"
//»
[00+x] DWORD HashTableFilesize // Bytes
[04+x] DWORD HashTableCount; // Number of scene buckets
}
struct SceneBucket
{
[00] WORD SizeOfSceneBucket;
//» #SR01,AE01: scene name string length
[02] WORD ScenenameAllocSize;
//» #DP01,DP20: Script containing the scene
[02] WORD ScriptNumber;
//»
//» #SR01,AE01
[04] WORD ScriptNumber;
//» #DP01,DP20: Script containing the scene
[04] WORD ZeroIgnored;
//»
//» #SR01,AE01: ?Some Size?
[06] WORD ??;
//» #DP01,DP20
[06] WORD ScenenameAllocSize;
//»
//» #DP20
[08] DWORD Ignored; // Offset is always function's (0x0A + KgoData::SceneFuncnameAllocSize)
//» #others
[08] DWORD OffsetInData;
//»
//» #DP20
[0C] WORD ??;
//»
[0C+x] DWORD SceneID; // ID defined in .kgo script header (a script may contain several scenes)
[10+x] DWORD SceneID2; // ditto
[14+x] CHAR[xx] SceneName; // NUL-terminated scene name
// #SR01,AE01: SizeOfSceneBucket = 0x20 (32) bytes
// #DP01,DP20: SizeOfSceneBucket = variable
};
= Random Notes =
Let: g_offset = 16;
00424804 /$ 55 PUSH EBP
00424805 |. 8BEC MOV EBP, ESP
00424807 |. BA 02000000 MOV EDX, 2
0042480C |. 8B45 08 MOV EAX, [ARG.1] ; memory address of KgoData + offset
0042480F |. 66:8B00 MOV AX, WORD PTR [EAX]
00424812 |. 66:83F8 10 CMP AX, 10
00424816 |. 73 15 JNB SHORT SR_fixed.0042482D
00424818 |. 66:FFC8 DEC AX
0042481B |. 74 0B JE SHORT SR_fixed.00424828
0042481D |. 83C0 FE ADD EAX, -2
00424820 |. 66:83E8 04 SUB AX, 4
00424824 |. 72 02 JB SHORT SR_fixed.00424828
00424826 |. EB 05 JMP SHORT SR_fixed.0042482D
00424828 |> BA 06000000 MOV EDX, 6
0042482D |> 8BC2 MOV EAX, EDX
0042482F |. 5D POP EBP
00424830 \. C3 RETN
Load 3funcs(Cmd) = {
ESI = *(unsigned WORD*)(&Cmd) (Zero extend Cmd)
EDX = 3 * ESI
fn1 = (DWORD*)0x596090 + 4 *EDX
fn2 = (DWORD*)0x596094 + 4 *EDX
fn3 = (DWORD*)0x596098 + 4 *EDX
}
fn1 must be non-null (SRTE: roughly Cmd in [0-152] with some holes)
- SRTE/DP FadeMasks:
4 "FadeMask02_LucasR.bmp"
5 "FadeMask03_LucasL.bmp"
6 "FadeMask00_BlindR.bmp"
7 "FadeMask01_BlindL.bmp"
C Translate To Foreground effect
D Translate To Background effect
E Water effect
F Moving Light Source effect with "HaloBack.bmp"
10 "FadeMask04_Circle.bmp"
11 "FadeMask05_CircleR.bmp"
12 "FadeMask06_Clock.bmp"
13 "FadeMask07_Swirl.bmp"
14 "FadeMask08_Crystal.bmp"
15 "FadeMask09_StripesB.bmp"
16 "FadeMask10_StripesN.bmp"
17 "FadeMask11_Star.bmp"
18 "FadeMask12_Radiation.bmp"
19 "FadeMask13_RadiationR.bmp"
1A "FadeMask14_Windmill.bmp"
1B "FadeMask15_Naruto.bmp"
1C "FadeMask16_Noise.bmp"
[edit] File Format: .kgo script mnemonics
Note: This documentation may be out of sync with the actual interpretation. Use at your own risk.
| # | Args | Mnemonic | Description | Repush |
|---|---|---|---|---|
| 0 (0000h) | 0 | NOP | Do Nothing | 0 |
| 1 (0001h) | 0 | PUSH | Push a signed 4-byte integer on arg stack (read ahead) | 0 |
| 2 (0002h) | 1 | POP | Pop stacked(Arg1:Returned Value) | 0 |
| 3 (0003h) | 0 | JMP | Jump, set offset = offset + read-ahead-DWORD [offset points at 03 bytecode] (read ahead) | 0 |
| 4 (0004h) | 1 | JF | Jump if false(Arg1:bool), set offset = offset + read-ahead-DWORD [offset points at 04 bytecode] (read ahead) | 0 |
| 5 (0005h) | 1 | JT | Jump if true(Arg1:bool), set offset = offset + read-ahead-DWORD [offset points at 05 bytecode] (read ahead) | 0 |
| 6 (0006h) | 0 | JMPPLUS | Jump to another scene in same kgo, set offset = offset + read-ahead-DWORD (possibly negative) - Should land on scene start [offset points at 06 bytecode][SRTE:Unused] (read ahead)(Repush 1) | 1 |
| 7 (0007h) | 1 | CALLFUNC | CallFunction(Arg1:FuncIdStringIndex[0-0xFFFF]). Syntax of function identifier is SCRIPT::FuncName e.g. SCR0180::Func_b05_2 (Repush 1) | 1 |
| 8 (0008h) | 0 | PUSHEVAL | Push Last Play Evaluation (Repush 1) | 1 |
| 9 (0009h) | 2 | PUSHSWAPTWO | Swap two stacked arguments(Arg1, Arg2)[SRTE:Unused] (Repush 2) | 2 |
| 10 (000Ah) | 1 | PUSHEVALTWO | Push Last Play Evaluation, then push Arg1(Arg1)[SRTE:Unused] (Repush 2) | 2 |
| 11 (000Bh) | 3 | PUSHSWAPTWOTHREE | Swap two stacked arguments Arg2 and Arg3(Arg1, Arg2, Arg3) (Repush 3) | 3 |
| 14 (000Eh) | 1 | ENDSCRIPT | EndOfScript(Arg1=0). Provides fail-safe script termination. Pass Arg1 as 0 (NOP) due to instructions aligned on word boundaries. Should be the last instruction | 0 |
| 15 (000Fh) | 0 | ENDSCRIPT2 | EndOfScript2()[SRTE:Unused]. Provides fail-safe script termination. | 0 |
| 16 (0010h) | 1 | PUSHNOT | Replace stacked bool Arg1:bool by: repush (!Arg1) (Repush 1) | 1 |
| 19 (0013h) | 2 | PUSHMUL | Multiply (Arg1, Arg2), repush (Arg1 * Arg2) (Repush 1) | 1 |
| 20 (0014h) | 2 | PUSHIDIVZ | Integer Divide with SignedZeroCheck (Arg1, Arg2), repush (Arg2 ? Arg2 / Arg1 : Arg1 >= 0 ? 0 : -1) (Repush 1) | 1 |
| 21 (0015h) | 2 | PUSHIDIV | Integer Divide with ZeroCheck (Arg1, Arg2), repush (Arg2 ? Arg2 / Arg1 : 0) (Repush 1) | 1 |
| 22 (0016h) | 2 | PUSHADD | Add (Arg1, Arg2), repush (Arg1 + Arg2) (Repush 1) | 1 |
| 23 (0017h) | 2 | PUSHSUB | Substract (Arg1, Arg2), repush (Arg2 - Arg1) (Repush 1) | 1 |
| 24 (0018h) | 2 | PUSHCMPGT | Compare GreaterThan(Arg1,Arg2), repush (Arg1 > Arg2) (Repush 1) | 1 |
| 25 (0019h) | 2 | PUSHCMPGE | Compare GreaterOrEqual(Arg1,Arg2), repush (Arg1 >= Arg2) (Repush 1) | 1 |
| 26 (001Ah) | 2 | PUSHCMPLT | Compare LessThan(Arg1,Arg2), repush (Arg1 < Arg2) (Repush 1) | 1 |
| 27 (001Bh) | 2 | PUSHCMPLE | Compare LessOrEqual(Arg1,Arg2), repush (Arg1 <= Arg2) (Repush 1) | 1 |
| 28 (001Ch) | 2 | PUSHCMPEQ | Compare Equal(Arg1,Arg2), repush (Arg1 == Arg2) (Repush 1) | 1 |
| 29 (001Dh) | 2 | PUSHCMPNE | Compare NotEqual(Arg1,Arg2), repush (Arg1 != Arg2) (Repush 1) | 1 |
| 30 (001Eh) | 2 | PUSHAND | BooleanAnd(Arg1,Arg2), repush (Arg2 && Arg1) (Repush 1) | 1 |
| 31 (001Fh) | 2 | PUSHOR | BooleanOr(Arg1,Arg2), repush (Arg2 || Arg1) (Repush 1) | 1 |
| 32 (0020h) | 2 | SETFLAGVAR_MAYBE | Set FLAG Variable?(Arg1:bool,Arg2:[0-0x1FF]) | 0 |
| 33 (0021h) | 1 | PUSHFLAGVAR_MAYBE | Push FLAG Variable?(Arg1:[0-0x1FF], repush <bool>) (Repush 1) | 1 |
| 34 (0022h) | 2 | SETFLAGALT_MAYBE | Set Alt FLAG Variable?(Arg1:bool,Arg2:[0-0x3F]) | 0 |
| 35 (0023h) | 1 | PUSHFLAGALT_MAYBE | Push Alt FLAG Variable?(Arg1:[0-0x3F], repush <bool> FALSE if Arg1 off-range; X=(Arg1/8),Xin[0-7] Y=(Arg1%7) EDX=2^Y EAX=[005EEA40+X] 005EEA40:=00,00,00,00,00,00,20,83 EDX=EDXxorEAX repush (EDX!=0) (Repush 1) | 1 |
| 36 (0024h) | 2 | SETVARALT_MAYBE | Set Alt Variable?(Arg1,Arg2:[0-0x3F]) | 0 |
| 37 (0025h) | 1 | INCVARALT_MAYBE | Increment Alt Variable?(Arg1:[0-0x3F]) | 0 |
| 38 (0026h) | 1 | DECVARALT_MAYBE | Decrement Alt Variable?(Arg1:[0-0x3F]) | 0 |
| 39 (0027h) | 1 | PUSHVARALT_MAYBE | Push Alt Variable?(Arg1:[0-0x3F]) (Repush 1) | 1 |
| 40 (0028h) | 2 | OPCODE40 | Unresolved 40(Arg1, Arg2) | 0 |
| 41 (0029h) | 1 | PUSHSIGNBIT | Push Sign Bit(Arg1)[SRTE:Unused] (Repush 1) | 1 |
| 42 (002Ah) | 1 | ASSIGNEVAL | Assign Evaluation(Arg1:Evaluation[0-59]) | 0 |
| 43 (002Bh) | 0 | PUSHASSIGNEDEVAL | Push Assigned Evaluation (Repush 1) | 1 |
| 48 (0030h) | 1 | AVGSCENE | Set Scene(Arg1:SceneNameStringIndex[0-0xFFFF]) | 0 |
| 64 (0040h) | 1 | AVGMSG | MessageText(Arg1:StringIndex[0-0xFFFF]). If a text is already displayed, appends. | 0 |
| 65 (0041h) | 0 | AVGCRLF | Message Newline() | 0 |
| 66 (0042h) | 0 | AVGCLR | ClearMessagePanel() | 0 |
| 67 (0043h) | 0 | AVGOPEN | OpenMessagePanel() | 0 |
| 68 (0044h) | 0 | AVGCLOSE | CloseMessagePanel() | 0 |
| 69 (0045h) | 1 | AVGFORCESPD | ForceMessageSpeed(Arg1:[0-3000]) | 0 |
| 70 (0046h) | 1 | AVGVNMODE | SetVisualNovelMode(Arg1:bool) | 0 |
| 71 (0047h) | 2 | AVGVNPOS | SetVNModeTextPos(Arg1:TopBlankLinePadding[0-25], Arg2:LeftWhitespacePadding[0-15] | 0 |
| 72 (0048h) | 1 | AVGPAUSE | Pause Engine (Arg1:Time_ms) | 0 |
| 73 (0049h) | 0 | AVGNEXT | Prompt for user click() | 0 |
| 74 (004Ah) | 1 | AVGFORCENOSKIP | ForceUnskippableMessage(Arg1:bool) | 0 |
| 75 (004Bh) | 1 | AVGVOICE | PlayVoice(Arg1:Num "%06d.wav") ("Voice\srev%03d.pak") | 0 |
| 76 (004Ch) | 1 | AVGVOLUME | SetVolume(Arg1:[0-100]) | 0 |
| 77 (004Dh) | 2 | AVGVOICEPOS | SetVoicePosition(Arg1:Z, Arg2:X), Args are rounded to [-INF;-12]u[12;+INF] depending on sign. Args are expressed in hundreds of unit. | 0 |
| 78 (004Eh) | 2 | UNK_78 | Unresolved 78(Arg1:bool, Arg2:bool)[SRTE:Unused] | 0 |
| 79 (004Fh) | 1 | UNK_79 | Unresolved 79(Arg1:bool)[SRTE:Unused] | 0 |
| 80 (0050h) | 1 | UNK_80 | Unresolved 80(Arg1:[0-100]) | 0 |
| 81 (0051h) | 2 | UNK_81 | Unresolved 81(Arg1:bool, Arg2)[SRTE:Unused] | 0 |
| 82 (0052h) | 1 | UNK_82 | Unresolved 82(Arg1:bool)[SRTE:Unused] | 0 |
| 83 (0053h) | 1 | UNK_83 | Unresolved 83(Arg1:[0-100]), Same as UNK_80? | 0 |
| 84 (0054h) | 1 | AVGSE | PlaySpecialEffect(Arg1:Num "srse%03d.wav") | 0 |
| 85 (0055h) | 0 | AVGSESTOP | StopSpecialEffect() Stop currently playing non-looping SE, if applicable | 0 |
| 86 (0056h) | 1 | AVGSEVOLUME | SetSpecialEffectVolume(Arg1:[0-100]), Set volume for non-looping SE. | 0 |
| 87 (0057h) | 2 | AVGSEPOS | SetSpecialEffectPosition(Arg1:Z, Arg2:X) | 0 |
| 88 (0058h) | 2 | UNK_88 | Unresolved 88(Arg1:bool, Arg2)[SRTE:Unused] | 0 |
| 89 (0059h) | 1 | UNK_89 | Unresolved 89(Arg1:bool)[SRTE:Unused] | 0 |
| 90 (005Ah) | 1 | OPCODE90 | [Unreviewed](Arg1:[0-100]) | 0 |
| 91 (005Bh) | 2 | OPCODE91 | [Unreviewed](Arg1, Arg2) | 0 |
| 92 (005Ch) | 1 | UNK_92 | Unresolved 92(Arg1:BgAnimation) | 0 |
| 93 (005Dh) | 0 | UNK_93 | Unresolved 93() BgAnimation = 3E6 | 0 |
| 94 (005Eh) | 0 | UNK_94 | Unresolved 94() BgAnimation = 3E7 | 0 |
| 95 (005Fh) | 2 | UNK_95 | Unresolved 95(Arg1:[0-2], Arg2) | 0 |
| 96 (0060h) | 1 | UNK_96 | Unresolved 96(Arg1), like UNK_95 w/Arg2=-1 | 0 |
| 97 (0061h) | 1 | AVGFADE | FadeAnimation(Arg1:FadeMask) | 0 |
| 98 (0062h) | 2 | AVGBGFADE | FadeBgAnimation(Arg1:FadeMask, Arg2:OptionalTargetBgCGNum indirectly used in "srbg%03d.bmp", see AVGBGFADEINTO) | 0 |
| 99 (0063h) | 1 | AVGFADEWHITE | FadeToWhite(Arg1:FadeMask) | 0 |
| 100 (0064h) | 1 | AVGFADEBLACK | FadeToBlack(Arg1:FadeMask) | 0 |
| 101 (0065h) | 3 | AVGCHARONE | ShowOneChar(Arg1:FadeMode[0-2], Arg2:CharSlot[0=Center,1=Left,2=Right], Arg3:CGNum) | 0 |
| 102 (0066h) | 2 | UNK102 | Unresolved 102(Arg1:[0-2], Arg2:[0-2]) | 0 |
| 103 (0067h) | 0 | OPCODE103 | [Unreviewed]() | 0 |
| 104 (0068h) | 0 | UNK104 | Unresolved 104() | 0 |
| 105 (0069h) | 1 | OPCODE105 | [Unreviewed](Arg1) | 0 |
| 106 (006Ah) | 0 | OPCODE106 | [Unreviewed]() | 0 |
| 107 (006Bh) | 0 | OPCODE107 | [Unreviewed]() | 0 |
| 108 (006Ch) | 1 | AVGPLACE | ShowPlaceLabel(Arg1:Num "AvgPlace%02d.png") | 0 |
| 109 (006Dh) | 1 | OPCODE109 | [Unreviewed](Arg1) | 0 |
| 110 (006Eh) | 0 | OPCODE110 | [Unreviewed]() (Repush 1) | 1 |
| 111 (006Fh) | 0 | OPCODE111 | [Unreviewed]() (Repush 1) | 1 |
| 112 (0070h) | 0 | OPCODE112 | [Unreviewed]() (Repush 1) | 1 |
| 113 (0071h) | 0 | OPCODE113 | [Unreviewed]() (Repush 1) | 1 |
| 114 (0072h) | 1 | AVGBGFADEINTO | SetFadeBgInto(Arg1=?), specifies that next AVGBGANIM instruction will fade into a new Bg | 0 |
| 115 (0073h) | 0 | OPCODE115 | [Unreviewed]() (Repush 1) | 1 |
| 116 (0074h) | 0 | OPCODE116 | [Unreviewed]() (Repush 1) | 1 |
| 117 (0075h) | 0 | OPCODE117 | [Unreviewed]() (Repush 1) | 1 |
| 118 (0076h) | 1 | AVGBGEFFECT | SetBackgroundEffect(Arg1:EffectMode[0=Sunset,1=Gray,2=Gray+Rain,3=Gray+Snow,4=Sunset+OldFilm,5=Gray]) | 0 |
| 119 (0077h) | 0 | OPCODE119 | [Unreviewed]() (Repush 1) | 1 |
| 120 (0078h) | 4 | AVGCHOICE | Prompt Choice and Push Selected Entry(Arg1=0orStringIndex, Arg2=0orStringIndex, Arg3=StringIndex, Arg4=StringIndex), Pushed Value is Arg4 => 0, Arg3 => 1 etc. | 1 |
| 121 (0079h) | 0 | AVGNOTIFYLOADING | NotifyLoading() | 0 |
| 122 (007Ah) | 1 | OPCODE122 | [Unreviewed](Arg1) | 0 |
| 123 (007Bh) | 0 | OPCODE123 | [Unreviewed]() | 0 |
| 124 (007Ch) | 1 | AVGSONG | Loads a song in play mode and Set Last Evaluation (Arg1:HUNDREDS=EventNum;Event#.pak;UNITS=SongNum;e.g.SR##) (Repush 1) | 1 |
| 125 (007Dh) | 0 | OPCODE125 | [Unreviewed]() | 0 |
| 126 (007Eh) | 0 | OPCODE126 | [Unreviewed]() | 0 |
| 127 (007Fh) | 2 | OPCODE127 | [Unreviewed](Arg1:bool, Arg2:[0-9]) | 0 |
| 128 (0080h) | 0 | AVGPLACESELECT | SelectPlace() (Repush 1) | 1 |
| 129 (0081h) | 1 | OPCODE129 | [Unreviewed](Arg1) | 0 |
| 130 (0082h) | 1 | OPCODE130 | [Unreviewed](Arg1) | 0 |
| 131 (0083h) | 1 | OPCODE131 | [Unreviewed](Arg1:[0-100]) | 0 |
| 132 (0084h) | 0 | OPCODE132 | [Unreviewed]() | 0 |
| 133 (0085h) | 0 | OPCODE133 | [Unreviewed]() | 0 |
| 134 (0086h) | 1 | UNK134 | Unresolved 134(Arg1:bool) | 0 |
| 135 (0087h) | 1 | AVGMSGPANELVIS | SetMessagePanelVisibility(Arg1:bool) | 0 |
| 136 (0088h) | 1 | UNK136 | Unresolved 136(Arg1:bool) | 0 |
| 137 (0089h) | 1 | AVGMSGPANELTWOVIS | SetMessagePanel2Visibility(Arg1:bool) | 0 |
| 138 (008Ah) | 1 | AVGBGM | SetBackgroundMusic(Arg1;Num "Track%02d.bgm") | 0 |
| 139 (008Bh) | 0 | UNK139 | Unresolved 139() | 0 |
| 140 (008Ch) | 1 | UNK140 | Unresolved 140(Arg1) | 0 |
| 141 (008Dh) | 0 | OPCODE141 | [Unreviewed]() | 0 |
| 142 (008Eh) | 1 | AVGLOOPSE | SetLoopingSpecialEffect(Arg1:Num "srse%03d.wav") | 0 |
| 143 (008Fh) | 0 | UNK143 | Unresolved 143() | 0 |
| 144 (0090h) | 1 | UNK144 | Unresolved 144(Arg1:[1-14]) | 0 |
| 145 (0091h) | 1 | AVGMSGPANELX | MessagePanel::SetSizeX(Arg1:Num[0-0x100]) | 0 |
| 146 (0092h) | 0 | UNK146 | Unresolved 146() (Repush 1) | 1 |
| 147 (0093h) | 1 | OPCODE147 | [Unreviewed](Arg1:[0-3]) | 0 |
| 148 (0094h) | 0 | OPCODE148 | [Unreviewed]() (Repush 1) | 1 |
| 149 (0095h) | 1 | OPCODE149 | [Unreviewed](Arg1) | 0 |
| 150 (0096h) | 1 | OPCODE150 | [Unreviewed](Arg1) | 0 |
| 151 (0097h) | 1 | OPCODE151 | [Unreviewed](Arg1) | 0 |
| 152 (0098h) | 1 | OPCODE152 | [Unreviewed](Arg1) | 0 |
| 153 (0099h) | 1 | OPCODE153 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 154 (009Ah) | 1 | OPCODE154 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 155 (009Bh) | 0 | OPCODE155 | [Unreviewed]()[SRTE:Unsupported] | 0 |
| 156 (009Ch) | 0 | OPCODE156 | [Unreviewed]()[SRTE:Unsupported] | 0 |
| 157 (009Dh) | 1 | OPCODE157 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 158 (009Eh) | 0 | OPCODE158 | [Unreviewed]()[SRTE:Unsupported] | 0 |
| 159 (009Fh) | 1 | OPCODE159 | [Unreviewed](Arg1)[SRTE:Unsupported](Arg1:[>0] | 0 |
| 160 (00A0h) | 1 | OPCODE160 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 161 (00A1h) | 1 | OPCODE161 | [Unreviewed](Arg1)[SRTE:Unsupported] | 1 |
| 162 (00A2h) | 1 | OPCODE162 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 163 (00A3h) | 1 | OPCODE163 | [Unreviewed](Arg1)[SRTE:Unsupported] | 0 |
| 164 (00A4h) | 0 | OPCODE164 | [Unreviewed]()[SRTE:Unsupported][ACE:Unsupported] | 0 |