Chrono Cross Fieldscript Notes
General Information
Chrono Cross
"Fieldscript" is the name given to the set of commands that loads and controls the rooms and their contents. A fieldscript file has 0x80 bytes of header containing an array used to access the global variables from the local room, then a number of entries, then a pointer table(?). The script bloc starts just after that.
Per yaz0r: "script 0 [for a given entity] is the init script, script 1 is ran[sic] every frame, script 2 is used when interacting with the entity and script 3 is used when collisioning with the entity (mostly used for entity that trigger room change). Also Entity 0 is always the director, and the last is the debug entity present in nearly every room (entity 15 in my exemple). This is all guess work, but it seems to fit." (Note: there are some rooms where the debug entity is //not// actually the last one.)
Typically, a 16-bit parameter indicating an action target can be either an ordinary value (if the high bit is set—AND the parameter with 7FFF to get the actual value) or the contents of a variable (if the high bit is not set). Script offsets such as jump targets or subroutine locations are an exception: they are normal values and do not need to be ~ANDed.
"If it's a variable, the game computes the variable index like this:"
int idx = (value & 0x7FFF) >> 6; int localVariable = roomLocalTable[idx]; int globalVariableIdx = ((value & 0x7FFF) >> 1) & 0x1F
if(localVariable & (1 << globalVariableIdx)) // signed or not ? { return (UInt16)variableTables[globalVariableIdx]; } else { return (Int16)variableTables[globalVariableIdx]; })
Only some of the variables' purposes are known. All seem to be two bytes long:
Address | Name |
0x02 | ~ROOM_PARAM |
0x04 | ~MULTI_CHOICE_RESULT |
0x06 | ~MAP_ID |
0x08 | ~PREVIOUS_MAP_ID |
0x0C | ~PARTY_MEMBER_0 |
0x0E | ~PARTY_MEMBER_1 |
0x10 | ~PARTY_MEMBER_2 |
0x18 | ~DIGIT_ENTRY_RESULT |
0x2A | ~USED_KEY_ITEM |
0x32 | ~BATTLE_RESULT |
0x34 | ~DEBUG_MODE |
0x44 | ~CURRENT_FRAME |
0x4C | ~SAVE_RESULT |
>= 0x400 | (room variables) |
Single-byte Character Identifiers
Where a script command uses a single byte to identify the target character:
- Values less than 0x80 refer to the number of an entity in the current script space
- 0xFB is the current entity
- 0xFF is the current party leader
- 0xFE is the second party member
- 0xFD is the third party member
- Values between 0x80 and 0xF0 refer to the ~PCs in standard numbered order (0x80 = Serge, 0x81 = Kid, 0x82 = Guile, etc.)
Currently identified commands (Note: a lot of these are cribbed from yaz0r's code, which I //hope// I am decoding properly. Some codes, such as B8, are not mentioned in his decompiler, so I assume that no actual use of them in the game's script has ever been found.)
- 00 - Halt: Self-explanatory
- 01 XXYY - Goto: Jump to offset YYXX in the fieldscript
- 02 TTUU VVWW XX YYZZ - Conditional jump to ZZYY. The details are quite complex (see [1])
- 03 - Unknown
- 04 - Unknown
- 05 XXYY - Call subroutine at YYXX. Max stack depth is 4
- 06 - Dummy/no-op?
- 07 XX YY - Run a script belonging to the specified entity in asynchronous mode, where XX is the entity and YY, that of the script under that entity to be run
- 08 XX YY - Run a script belonging to the specified entity in "UNK" mode, where XX is the entity and YY, that of the script under that entity to be run
- 09 XX YY - Run a script belonging to the specified entity in blocking mode, where XX is the entity and YY, that of the script under that entity to be run. NOTE: This code currently causes softlocks when ePSXe is overclocked to 240% to enable 60 fps gameplay, with no known workaround.
- 0A - Update character
- 0B - Update character and stop
- 0C - No-op
- 0D - Return from sub routine
- 0E XXYY - Set up the ~YYXXth PC (YYXX is never a variable here)
- 0F XXYY - Load NPC model: Loads the ~YYXXth NPC model for this room for the current entity.
- 10 VVWW XXYY ZZ - Set variable WWVV to signed value YYXX (ZZ contains sign bits)
- 11 XXYY - Set variable YYXX to 1
- 12 XXYY - Set variable YYXX to 0
- 13 VVWW XXYY ZZ - Add signed value YYXX to variable WWVV (ZZ contains sign bits)
- 14 VVWW XXYY ZZ - Subtract signed value YYXX from variable WWVV (ZZ contains sign bits)
- 15 VVWW XXYY ZZ - bitwise-OR variable WWVV with value YYXX?
- 16 VVWW XXYY ZZ - bitwise-XOR variable WWVV with value YYXX?
- 17 XXYY - Increment variable YYXX by 1
- 18 XXYY - Decrement variable YYXX by 1
- 19 VVWW XXYY ZZ - AND variable WWVV with value YYXX (ZZ contains sign bits)
- 1A VVWW XXYY ZZ - OR variable WWVV with value YYXX (ZZ contains sign bits)
- 1B VVWW XXYY ZZ - XOR variable WWVV with value YYXX (ZZ contains sign bits)
- 1C VVWW XXYY - Shift variable WWVV left by YYXX bits
- 1D VVWW XXYY - Shift variable WWVV right by YYXX bits
- 1E XXYY - Set variable YYXX to random value
- 1F WWXX YYZZ - Set variable XXWW to random multiple of ZZYY
- 20 VVWW XXYY ZZ - Multiply variable WWVV by value YYXX (ZZ contains sign bits)
- 21 VVWW XXYY ZZ - Divide variable WWVV by value YYXX (ZZ contains sign bits)
- 22 TTUU VVWW XXYY ZZ - Compute sine and place result in variable UUTT, other arguments uncertain
- 23 TTUU VVWW XXYY ZZ - Compute cosine and place result in variable UUTT, other arguments uncertain
- 24 TTUU VVWW XXYY ZZ - Compute tangent and place result in variable UUTT, other arguments uncertain
- 25 TTUU VVWW XXYY ZZ - ~SET_POSITION_UNSIGNED
- 26 TTUU VVWW XXYY ZZ - ~SET_POSITION_SIGNED
- 27 XXYY - Unknown
- 28 XXYY - Unknown
- 29 XXYY - Unknown
- 2A XXYY ZZ - Unknown, ZZ is sign bits
- 2B XX - Enable controls
- 2C - Disable controls
- 2D XXYY - Wait for period YYXX (?measured in what? Seconds?)
- 2E XX - Turn current entity to face character XX
- 2F XX - Set rotation to XX for current entity (simple version)
- 30 XXYY - Set rotation to YYXX(?) for current entity (complex version)
- 31 XX YYZZ - Turn entity XX to face direction ZZYY
- 32 XX YYZZ - Unknown
- 33 XX YY - Turn entity XX to face entity YY(?)
- 34 XX - Set collidability of current entity to XX?
- 35 XX YY - Hide entity (one of XX, YY is the entity ID, the other is...flags?)
- 36 XX YY - Make hidden entity visible (one of XX, YY is the entity ID, the other is...flags?)
- 37 XX - Unknown
- 38 XX - Unknown
- 39 XX - Unknown
- 3A - Wait one frame
- 3B - Stop script execution
- 3C XXYY - Set current entity to perform animation YYXX
- 3D XX YYZZ - Set walk animation for entiy XX to animation ZZYY
- 3E XXYY - Unknown
- 3F 00 TT UUVV WWXX YYZZ - Have entity TT walk to position given by the other arguments.
- 3F 01 - Wait-walk
- 40 00 RR SSTT UUVV WWXX YYZZ - Have entity RR walk to position given by the other arguments.
- 40 01 - Wait-walk
- 41 XXYY - Set movement speed for current entity to YYXX
- 42 00 TT UUVV WWXX YY ZZ - Another walkto, arguments uncertain.
- 42 01 - Wait-walkto for 42 00
- 43 00 RR SSTT UUVV WWXX YYZZ - As 40 00?
- 43 01 - As 40 01?
- 44 VV WW XX YY ZZ - Unknown, WW may be a character ID
- 45 TT UU VVWW XX YY ZZ - This command makes the NPC run to current party leader when nearby [3]
- 46 01 - Wait for movement completion
- 46 VV WWXX YYZZ - Move entity (VV != 01, XXWW = direction, ZZYY = number of frames during which to move)
- 47 XX - Unknown
- 48 TT UUVV WWXX YYZZ - Get position of entity TT and store in variables VVUU, XXWW, ZZYY
- 49 XXYY - ~TARGET_ROTATION & 0xFFF
- 4A XX YYZZ - Get rotation of entity XX (and store in variable ZZYY?)
- 4B XXYY - Set variable controlling the debug menu to YYXX
- 4C PP QQRR SSTT UUVV WWXX YYZZ - Unknown, args may be one byte less than shown.
- 4D LL MMNN OOPP QQRR SSTT UUVV WWXX YYZZ - Unknown, args may be one byte less than shown.
- 4E WWXX YY ZZ - Compute distance between entities YY and ZZ and store in variable XXWW.
- 4F WW XX YY ZZ - Unknown
- 50 WWXX YYZZ - Jump to ZZYY if (input_key_variable AND XXWW)
- 51 WWXX YYZZ - Jump to ZZYY if (script_var_2 AND XXWW)
- 54 - Set script_var_2 to 0
- 55 XX YYZZ - Some sort of jump command, with ZZYY as target
- 56 XX YYZZ - Some sort of jump command, with ZZYY as target
- 59 - Unknown
- 5A WWXX YYZZ - Mapjump: Jump to room XXWW using map parameter ZZYY
- 5B XX - (Unconfirmed) Character Exchange, may have 9 bytes of additional parameters if (XX AND 3) = 2
- 5C XX - Jump move, , may have 9 bytes of additional parameters if (XX AND 3) = 2
- 5D 00 RR SS TT UU VV WW XX YY ZZ - Set camera position according to parameters (bytes-per-param uncertain)
- 5D XX - Set camera to predefined position XX? (XX > 0)
- 5E 00 XX YY - Point camera at entity identified by variable YYXX
- 5E XX - Point camera at entity XX (XX > 0)
- 5F XX - Override control of entity XX
- 60 XX - Clear override of control of entity XX
- 61 00 XX YYZZ - Have the camera follow character XX (ZZYY may be some sort of flags)
- 61 XX - Wait for the camera to reach the position suggested by a 61 00 call
- 62 QQRR SSTT UUVV WWXX YYZZ - Set up a dialogue window at screen coordinates RRQQ, TTSS, with width VVUU, height XXWW, and flagset ZZYY (ZZYY = 64 -> display portrait)
- 63 XXYY - Unknown
- 64 XXYY ZZ - Unknown
- 65 XXYY - Unknown
- 66 WW XXYY ZZ - Unknown
- 67 XXYY - Set shadow colour to match entry YYXX from the shading palette
- 68 QQRR SSTT UUVV WWXX YYZZ - Set screen RGB according to the arguments
- 69 WWXX YYZZ - If the value in variable XXWW is equal to that of the ~SCENARIO_FLAG variable, jump to ZZYY
- 6A WWXX YYZZ - If the value in variable XXWW is less than that of the ~SCENARIO_FLAG variable, jump to ZZYY
- 6B WWXX YYZZ - If the value in variable XXWW is not equal to that of the ~SCENARIO_FLAG variable, jump to ZZYY
- 6C XXYY - Set the value of the ~SCENARIO_FLAG variable to YYXX
- 6D XXYY - Copy the value of the ~SCENARIO_FLAG variable into variable YYXX
- 6E WWXX YYZZ - Swap the values of the variables XXWW and ZZYY (note: the parameters here cannot be variables themselves)
- 6F UUVV WWXX Y ZZ - Set variable XXWW to the ~ZZYYth element of the array (with 8-bit elements) at VVUU (only ZZYY can be a variable)
- 70 TTUU VVWW XXYY ZZ - Set variable WWVV to the ~YYXXth element of the array (with 16-bit elements) at UUTT
- 71 XXYY ZZ - Set the specified bit of a variable (to 1)
- 72 XXYY ZZ - Clear the specified bit of a variable (set to 0)
- 73 VVWW XX YYZZ - Jump to ZZYY if the specified variable bit is clear
- 74 WWXX YY ZZ - Unknown
- 75 WW XX YYZZ - Set up flag
- 76 WW XX YYZZ - Unknown
- 77 WW XX YYZZ - Unknown
- 78 WW XX YYZZ - Unknown
- 79 VV WWXX YYZZ - Some sort of jump to ZZYY
- 7A VV WWXX YYZZ - Some sort of jump to ZZYY
- 7B XXYY - Add character YYXX to party
- 7C - Execute script for character
- 7D XX - Remove character XX from party
- 7E XXYY - Play movie YYXX
- 7F - Wait for the end of a movie called with 7E
- 80 XXYY - Enable background layer YYXX (YYXX can be between 0 and 0x1F inclusive)
- 81 XXYY - Disable background layer YYXX (YYXX can be between 0 and 0x1F inclusive)
- 82 WW XX YYZZ - Scale character XX along screen axis WW (with proportion ZZYY?)
- 83 RRSS TTUU VVWW XXYY ZZ - Unknown (ZZ is sign bits for other arguments)
- 84 EEFF GGHH IIJJ KKLL MMNN OOPP QQ RRSS TTUU VVWW XX YY ZZ - Set up formation. (QQ is sign bits for previous arguments.)
- 85 - Go to a formation set up by 84
- 86 XX - Set camera to auto-follow entity XX (?)
- 87 UUVV WWXX YYZZ - Set underwater RGB to (VVUU, XXWW, ZZYY)
- 88 XXYY - Play song: Start playing song YYXX
- 89 WWXX YY ZZ - Unknown, YY and ZZ may not be used
- 8A - Wait until the current song is finished playing
- 8B WWXX YYZZ - Unknown
- 8C WWXX YYZZ - Define a rectangle of size (XXWW, ZZYY)
- 8D XX - Unknown
- 8E XX - Toggle rectangle collision
- 8F KKLL MMNN OOPP QQRR SSTT UUVV WWXX YYZZ - Background wave on
- 90 00 XXYY - Background wave off (no idea what the param is for)
- 90 XX - Background wave off (usually, XX = 03)
- 91 XX - Unknown
- 92 XX YYZZ - Unknown
- 93 XX - Unknown
- 94 WWXX YYZZ - Jump to offset ZZYY in the fieldscript if and only if character XXWW is //not// in the party.
- 95 WWXX YYZZ - Jump?
- 96 XXYY - Add character YYXX to roster
- 97 XXYY - Remove character YYXX from roster
- 98 WWXX YYZZ - Store the number of the slot character ZZYY occupies in the party in variable XXWW
- 99 WWXX YYZZ - Store the ID of the ~ZZYYth character in the party in variable XXWW
- 9A WWXX YYZZ - Unknown
- 9B VV WW XX YY ZZ - Unknown (effect-related?)
- 9C WW XX YY ZZ - Unknown
- 9D XX - Unknown
- 9E XXYY - Set Dialog Portrait: Set current dialogue portrait to number YYXX
- 9F - Clear current dialogue portrait
- A0 XX - Unknown (argument length may not be exact)
- A1 TT UUVV WWXX YYZZ - Set the RGB for character TT to (VVUU, XXWW, ZZYY)
- A2 XX YYZZ - Unknown
- A3 UUVV WWXX YYZZ - Initiate a battle. Similar to opcode C9, but probably for more normal battles where the enemies involved vary.
- A4 XXYY - Unknown
- A5 XXYY - Unknown
- A6 XX - Unknown
- A7 SSTT UUVV WWXX YYZZ - Unknown
- A8 XX YYZZ - Fade (screen? What are the parameters—to-light-level and time?)
- A9 XX YYZZ - Play animation: have character XX run through animation ZZYY
- AA XX YYZZ - Set axis rotation: Rotate character XX through (or to?) angle ZZYY
- AB WWXX YYZZ - Unknown
- AC XX YYZZ - (Unconfirmed) Seems to be transparency related. XX is the character affected.
- AD XX - Unknown
- AE XX - Unknown
- AF TTUU VVWW XX YYZZ - Unknown (XX is sign bits for preceding arguments)
- B0 XXYY ZZ - Set rotation(?) (ZZ is sign bits for the other operand)
- B1 XX - unknown
- B2 00 - Override follow?
- B2 01 XXYY - Override follow
- B3 XX YYZZ - Some sort of conditional jump. XX is a character ID, ZZYY is the jump target.
- B4 WWXX YYZZ - Jump to ZZYY if the party does //not// possess key item XXWW.
- B5 XXYY - Unknown
- B6 WW XX YY ZZ - Unknown
- B7 XXYY ZZ - Unknown (ZZ is sign bits)
- B9 TT UU VVWW XX YY ZZ - Unknown (parameter grouping uncertain)
- BB XX YYZZ - Item give/take: if XX is 0, item ZZYY will be added to the inventory; if XX is non-zero, the item will be taken away. By default, ZZYY refers to a normal item (forge material/weapon/armour/accessory). If bit 0x200 is set, the item will be an Element. If 0x400 is set, the item will be a key item.
- BC UU VV WW XX YYZZ - Check money: jump to ZZYY if party has (probably less than, since Cross seems to have a "jump on negative" policy) the specified quantity of money
- BD XX YYZZ - yaz0r labels this just as "MONEY"—it may be for giving the party money
- BE - Unknown
- BF WW XX YY ZZ - Unknown (parameter grouping uncertain)
- C0 XX - Free character XX's special animation slot
- C1 00 XX YYZZ - Load animation ZZYY for character XX
- C1 00 FF VV WWXX YY ZZ - Similar to the case where the third byte is not FF, but consumes an extra two bytes whose purpose, if any, is not known.
- C1 01 - Load animation 01 for the current entity? (yaz0r's code is very unclear)
- C2 SSTT UUVV WWXX YYZZ - Set layer opacity
- C3 WWXX YYZZ - Get camera position (most likely, read the camera coordinates and place them in the variables referenced by the parameters)
- C4 XX - Wait until character XX has completed its current animation (?)
- C5 UUVV WWXX YYZZ - Something related to sound [5]
- C6 00 WWXX YYZZ - Play sound effect
- C6 01 SSTT UUVV WWXX YYZZ - Play sound effect with a lot more parameters
- C7 XXYY - Unknown
- C8 NNOO PPQQ RRSS TTUU VV WWXX YYZZ - Unknown. VV is sign bits for the three preceding parameters.
- C9 UUVV WWXX YYZZ - Sets up a battle using battlescript VVUU and battlefield XXWW (Battlefields are numbered consecutively in CD file order, starting with 0000 for Lizard Rock). YYZZ are a set of bitflags: Bit 0x01: Keeps field music into battle, Bit 0x02: Battle is losable, Bit 0x04: Caused party to have Dragoon disguise after battle, Bit 0x10: No victory music, Bit 0x20: Music in battle stays after battle, Bit 0x40: Brink of Death music plays. (see also A3)
- CA - Unknown
- CB - Wait for previous rotation command to complete itself
- CC XX - Wait until character XX has finished rotating.
- CD WWXX YYZZ - Yet another mystery jump command with target ZZYY
- CE WWXX YYZZ - If the value of the ~SCENARIO_FLAG variable is less than(?) XXWW, jump to ZZYY
- CF XX YYZZ - Unknown
- D0 XXYY - Yet another jump to YYXX. If a condition applies, we don't know what it is.
- D1 XXYY - Loads model [4]
- D2 - Unknown
- D3 WW XX YY ZZ - Play effect
- D4 WWXX YYZZ - Play movie XXWW, allow player to skip it.
- D5 WWXX YYZZ - Set variable XXWW to contain the quantity of item ZZYY (in the party inventory?)
- D6 XX YYZZ - ~ATTACH_TO_CHARACTER (attach what?). XX is the character.
- D7 WW XX YY ZZ - Unknown
- D8 TT UUVV WWXX YYZZ - Jump to ZZYY based on an unknown condition. TT is a character.
- D9 WWXX YYZZ - Set up character model.
- DA - Wait until a character mode set (?typo for D9 (character mode//l// set)?) has completed.
- DB WWXX YYZZ - Set variable XXWW to the ID of character ZZYY
- DC WWXX YYZZ - Mapjump. Differences from 5A not yet identified.
- DD 00 XX YYZZ - Read a block of data (how much? And put it where?)
- DD XX - Wait for the preceding DD 00 XX command to complete itself.
- DF SSTT UUVV WW XXYY ZZ - Unknown (WW is sign bits for preceding arguments)
- E0 XXYY ZZ - Message: Display message YYXX from the corresponding dialogue file.
- E1 XY - Have player make a selection from the set of values between X and Y
- E2 - Wait until the player is finished with the dialogue box
- E3 WW XXYY ZZ - If character WW is in the party, have him say message YYXX from the corresponding dialogue file
- E4 WW XXYY ZZ - Similar to E3?
- E6 WWXX YYZZ - Appears to be a jump or subroutine call, target ZZYY
- E9 WWXX YYZZ - (Unconfirmed) Render (or test for?) the current dialogue frame
- FE 01 XX - Unknown
- FE 02 XXYY - Unknown
- FE 03 WWXX YY ZZ - Unknown
- FE 04 XX - Unknown
- FE 05 XXYY - Store YYXX in a specific script variable (scriptVar1)
- FE 06 XX - Unknown
- FE 07 XX - Unknown
- FE 09 XX YYZZ - Unknown (XX is a character)
- FE 0A XX YYZZ - Unknown (XX is a character)
- FE 0C XX YY - Force character YY to face direction XX
- FE 0D XXYY - Unknown
- FE 0E XXYY - Unknown
- FE 0F XX YYZZ - Unknown (XX is a character)
- FE 10 - Initiates a battle set up by code A3 or C9.
- FE 11 XXYY - Unknown
- FE 12 UUVV WWXX YYZZ - Unknown
- FE 14 XX - Unknown
- FE 15 XXYY - Unknown
- FE 17 XX - Unknown
- FE 18 XX - Unknown
- FE 19 XX - Unknown
- FE 1A - Unknown
- FE 1B XXYY - Set current (animation? viewport?) frame
- FE 1C - Update current frame
- FE 1D WWXX YYZZ - Unknown
- FE 21 UUVV WWXX YYZZ - Prepare to make the screen shake with an amplitude of VVUU horizontal, XXWW vertical, for a period of time ZZYY
- FE 22 UUVV WWXX YYZZ - Change SFX volume
- FE 25 XX - Unknown
- FE 29 XXYY - Unknown
- FE 2A XX - Unknown
- FE 2B XX YYZZ - Unknown
- FE 2C XX - Unknown
- FE 2D XXYY - Unknown
- FE 2F XX - Unknown
- FE 31 XX - Unknown (XX is a character ID)
- FE 32 - Unknown
- FE 33 XX - Unknown
- FE 34 PPQQ RRSS TTUU VVWW XXYY ZZ - Unknown. ZZ is sign bits for all previous arguments.
- FE 35 XXYY ZZ - Unknown. ZZ is sign bits for previous argument.
- FE 36 XXYY - Heal group (what's the parameter for?)
- FE 37 WWXX YYZZ - Unknown
- FE 38 VVWW XXYY ZZ - yaz0r labels this "optional life", without explanation. ZZ is sign bits for first argument.
- FE 3A VVWW XXYY ZZ - Unknown. ZZ is sign bits for first argument.
- FE 3D WWXX YYZZ - Cure status ailment. One of the arguments represents the ailment type: 1 for poison, 8 for burns, 16 for sprain, 32 for flu
- FE 3E WWXX YYZZ - Cure all status ailments.
- FE 3F - Unknown
- FE 40 XXYY - Unknown
- FE 41 XX - Unknown
- FE 42 XX - Unknown (yaz0r has a note here saying "save parameter to external array", but I don't know whether that's an indication of what this does or a coding TODO for his own software)
- FE 43 WWXX YYZZ - Unknown
- FE 44 - Draw sync
- FE 45 00 XX YY - Unknown (YY is a character ID)
- FE 45 VV WW XX YY ZZ - Unknown (XX is a character ID, VV > 0)
- FE 46 TTUU VVWW XXYY ZZ - Unknown (ZZ is sign bits for preceding arguments)
- FE 47 TTUU VVWW XXYY ZZ - Unknown (ZZ is sign bits for preceding arguments)
- FE 48 SSTT UUVV WWXX YYZZ - Unknown
- FE 49 VVWW XXYY ZZ - Unknown (ZZ is sign bits for preceding arguments)
- FE 4A XXYY - Naming screen: Brings up the rename screen for character YYXX
- FE 4B XX - Unknown
- FE 4C XX - Unknown (XX is a character ID)
- FE 52 XXYY - Unknown
- FE 53 VVWW XXYY ZZ - Set the angle of character ~ZZ's head to WWVV, YYXX
- FE 55 XX YY - Have one character look at another (it's unclear which parameter is the looker and which the target)
- FE 56 XX - Set character ~XX's head to its default position
- FE 59 - Unknown
- FE 5A XX - Unknown
- FE 5B - Character exchange: Brings up the character swap menu
- FE 5C WW XX YYZZ - Unknown (XX is a character ID)
- FE 5E XX YY - Element shop: Brings up Element shop YYXX
- FE 61 - Open the main menu
- FE 62 XX YYZZ - Set character XX's head speed to ZZYY
- FE 63 - Stop the script if a specific variable has been set(?)
- FE 64 XX YY - Unknown. YY is a character.
- FE 65 00 XX YYZZ - Change to disc XX
- FE 65 XX YY - Change to disc YY (XX > 0)
- FE 68 XXYY - Blacksmith: Brings up smith's shop YYXX
- FE 6B XX - Unknown
- FE 6D - Recover Stars to max [2]
- FE 6E XXYY - Sets variable YYXX to...something.
- FE 6F XX - Unknown
- FE 70 XX - Unknown (XX is a character ID)
- FE 71 XX - Use alternate portrait XX for speaker
- FE 73 WWXX YYZZ - Learn character limit (I wasn't able to determine what //kind// of limit (stat?), but ZZYY is the limit's identifier, so XXWW must be the character)
- FE 74 WWXX YYZZ - As FE 73
- FE 76 XXYY - Unknown
- FE 78 WWXX YYZZ - Stall the script until some condition or other (details unknown) is met
- FE 79 - As FE 73
- FE 7A XXYY - Add frame to collection (per yaz0r, that is. I have no idea what he meant.)
- FE 7B XXYY - Toggle character limit mode (between what and what?)
- FE 7E - Unknown
- FE 81 XX - Unknown
- FE 84 - Set up the rename screen
- FE 85 - Save the game
[1] Additional stuff about opcode 02: TTUU - First value/variable. VVWW - Second value/variable. YYZZ - Offset for a jump. XX divided into two parts. 0x00 means both parameters will be variables. 0x40 - only the first will be a variable (second - value). 0x80 - only the second will be a variable (first - value). Second part is a condition parameter: 0x00 - '==', 0x01 - '!=', 0x02 - '>', 0x03 - '<', 0x04 - '>=', 0x05 - '<=', 0x06 - '$', 0x07 - '!=', 0x08 - '|', 0x09 - '$', 0x0A - '~'.
[2] Additional stuff about FE 6D: If you look in the decompiled script, let's say
0425.room_023_arni_home_-_serge's_room.script.cpt 0x037E: HEAL_GROUP(249) 0x0382: opFE6D() 0x0384: CURE_ALL_STATUS_AILEMENT(249, 57)
It is always with the Heal Group/Cure Ailment function! It is possible to prevent the opFE6D() if you set it to 0C0C you will not recover star's when you go at the inn/serge's bed
[3] Additional stuff about this command: Changing it to the second or third party character doesn't change anything, but you can remove the command with no issue. To make my test, I always set all the value of a Command to 0C (No-op)
[4] Command D1 is Similar to 0F XX YY.
- D1 XXYY - Unknown
- 0F XXYY - Load NPC model: Loads the ~YYXXth NPC model for this room for the current entity.
Example: D1 04 80
Loads Model 04 for Current Entity, I think D1 is used when you have the same model loadedmultiple times in the room. D1 04 80 Loads the Googhoul's Model in 1358.room_334_fort_dragonia_another_-_west_maze.script.cpt. There's 2 Googhoul) - would need more testing/data to be 100% sure.
[5] I think command C5 is related to the Sound. C5 UUVV WWXX YYZZ - Unknown. In my example: C5 0A 80 7F 80 00 80; this put the "Wing's Flapping" sound effect on Ghoogool. The closer you get to the Ghoogool the Louder the sound is. (Not sure if it always set like this)
Some Examples
How the Game Randomizes the Title Screen Sequence
0x015C: var[0x040E] = rand() 0x015F: var[0x040E] &= 3 0x0165: IF_JUMP(var[0x040E] == 0x0000, 0x0175) 0x016D: opD3("tit0") 0x0172: JUMP(0x01A5) 0x0175: IF_JUMP(var[0x040E] == 0x0001, 0x0185) 0x017D: opD3("tit1") 0x0182: JUMP(0x01A5) 0x0185: IF_JUMP(var[0x040E] == 0x0002, 0x0195) 0x018D: opD3("tit2") 0x0192: JUMP(0x01A5) 0x0195: IF_JUMP(var[0x040E] == 0x0003, 0x01A5) 0x019D: opD3("tit3") 0x01A2: JUMP(0x01A5) 0x01A5: op59()
Decompiled script for the room 1745 of ~CD2 (the programmer room with Kid)
Kid is entity 13 in the script. The interesting part:
--------------------------- | Entity 13 script 1 --------------------------- 0x0241: var[0x0400] = rand()%6 0x0246: IF_JUMP(var[0x0400] == 0x0000, 0x025F) 0x024E: op42(0x00, -642, -99, var[0x00C0]) 0x0257: op42(0x01) 0x0259: WAIT(60) 0x025C: JUMP(0x02C9) 0x025F: IF_JUMP(var[0x0400] == 0x0001, 0x0278) 0x0267: op42(0x00, -627, -99, var[0x00C0]) 0x0270: op42(0x01) 0x0272: WAIT(40) 0x0275: JUMP(0x02C9) 0x0278: IF_JUMP(var[0x0400] == 0x0002, 0x0291) 0x0280: op42(0x00, -607, -99, var[0x00C0]) 0x0289: op42(0x01) 0x028B: WAIT(60) 0x028E: JUMP(0x02C9) 0x0291: IF_JUMP(var[0x0400] == 0x0003, 0x029F) 0x0299: WAIT(60) 0x029C: JUMP(0x02C9) 0x029F: IF_JUMP(var[0x0400] == 0x0004, 0x02AD) 0x02A7: SET_ANIMATION(9) 0x02AA: JUMP(0x02C9) 0x02AD: IF_JUMP(var[0x0400] == 0x0005, 0x02BB) 0x02B5: WAIT(90) 0x02B8: JUMP(0x02C9) 0x02BB: IF_JUMP(var[0x0400] == 0x0006, 0x02C9) 0x02C3: SET_ANIMATION(1) 0x02C6: JUMP(0x02C9) 0x02C9: STOP()
Basically, the code means:
var[0x0400] = rand() % 6 switch(var[0x0400]) { case 0: op42(0x00, -642, -99, var[0x00C0]) op42(0x01) wait(60) break;
case 1: op42(0x00, -627, -99, var[0x00C0]) op42(0x01) WAIT(40) break;
case 2: op42(0x00, -607, -99, var[0x00C0]) op42(0x01) WAIT(60) break;
case 3: WAIT(60) break;
case 4: SET_ANIMATION(9) break;
case 5: WAIT(90) break;
case 6: SET_ANIMATION(1) break;
Lucca's Letter to Kid
Apparently, if you let the game load Grobyc's model instead of the letter's, Luccia will hold mini Grobyc in her hand when you talk to her.
--------------------------- | Entity 25 script 4 --------------------------- 0x0B50: PLAY_SONG(21) // The Girl Who Stole the Stars 0x0B53: op8A() // wait something 0x0B54: op68(0, 0, 0, 60, 60) // screen fade or blink, not sure 0x0B5F: WAIT(60) 0x0B62: op62(165, 100, 0, 0, 820) 0x0B6D: DIALOG(0x0037, 0x00) // My dear Kid, How are you doing? 0x0B71: WAIT_DIALOG() 0x0B72: DIALOG(0x0038, 0x00) 0x0B76: WAIT_DIALOG() 0x0B77: DIALOG(0x0039, 0x00) 0x0B7B: WAIT_DIALOG() 0x0B7C: DIALOG(0x003A, 0x00) 0x0B80: WAIT_DIALOG() 0x0B81: DIALOG(0x003B, 0x00) 0x0B85: WAIT_DIALOG() 0x0B86: DIALOG(0x003C, 0x00) 0x0B8A: WAIT_DIALOG() 0x0B8B: DIALOG(0x003D, 0x00) 0x0B8F: WAIT_DIALOG() 0x0B90: DIALOG(0x003E, 0x00) 0x0B94: WAIT_DIALOG() 0x0B95: DIALOG(0x003F, 0x00) 0x0B99: WAIT_DIALOG() 0x0B9A: DIALOG(0x0040, 0x00) 0x0B9E: WAIT_DIALOG() 0x0B9F: DIALOG(0x0041, 0x00) 0x0BA3: WAIT_DIALOG() 0x0BA4: DIALOG(0x0042, 0x00) 0x0BA8: WAIT_DIALOG() 0x0BA9: WAIT(60) 0x0BAC: DIALOG(0x0043, 0x00) 0x0BB0: WAIT_DIALOG() 0x0BB1: DIALOG(0x0044, 0x00) 0x0BB5: WAIT_DIALOG() 0x0BB6: DIALOG(0x0045, 0x00) 0x0BBA: WAIT_DIALOG() 0x0BBB: DIALOG(0x0046, 0x00) 0x0BBF: WAIT_DIALOG() 0x0BC0: DIALOG(0x0047, 0x00) 0x0BC4: WAIT_DIALOG() 0x0BC5: DIALOG(0x0048, 0x00) 0x0BC9: WAIT_DIALOG() 0x0BCA: DIALOG(0x0049, 0x00) 0x0BCE: WAIT_DIALOG() 0x0BCF: DIALOG(0x004A, 0x00) 0x0BD3: WAIT_DIALOG() 0x0BD4: DIALOG(0x004B, 0x00) 0x0BD8: WAIT_DIALOG() 0x0BD9: WAIT(60) 0x0BDC: DIALOG(0x004C, 0x00) 0x0BE0: WAIT_DIALOG() 0x0BE1: WAIT(30) 0x0BE4: opFE1D(180, 0) 0x0BEA: op68(0, 0, 0, 0, 60) 0x0BF5: STOP()
Open-door animation of Home Forbidden Island
--------------------------- | Sub function 0x00B3 --------------------------- 0x00B3: DISABLE_CHARACTER_CONTROLS() 0x00B4: PLAY_SOUNDFX(290, 0) 0x00BA: DISABLE_BACKGROUND_LAYER(1) 0x00BD: ENABLE_BACKGROUND_LAYER(2) 0x00C0: WAIT(4) 0x00C3: DISABLE_BACKGROUND_LAYER(2) 0x00C6: SET_NEXT_ROOM("CD0-432-Forbidden Island Cabin (Another)", 0) 0x00CB: STOP_SCRIPT_EXEC()