The video is commented with subtitles.
  • Emulator: BizHawk 1.7.4
  • Rom: Final Fantasy III (U) (V1.0)
  • Aims for fastest time
  • Contains soft resets
  • Abuses programming errors
  • Manipulates luck
Terra and her team are back to fight Kefka and save the world. This time, however, they didn't want to watch as Kefka uses the Statues to torn the world apart, so they skipped it directly to the final confrontation.
This tas is an improvement of the previously published tas by Erokky in 4:05:52.87 and the non-published tas by Catastrophe in 4:16:34.88 [dead link removed], thanks to an extreme use of the sketch glitch.
This is the lua script used to make our life much easier

Tricks

Preemptive manipulation

Getting preempitves/side attacks is the basics of many JRPG TASes. In this case, all the randomness at the start of a fight (preemptive, startup ATB, monster vigor) is determined based on the time the fight triggered. More precisely, the game uses the number of frames (range 1-60) within one second of the in-game timer as the RNG seed. As a consequence, there are 60 different battle configurations possible. The method to trigger preemptives/side attacks is simply to delay the beginning of the fight. This works well on the world map, but on towns/dungeons, there is a frame rule concerning movement: we can only start walking 1 every 4 frames. Because of this, we can only have access to 15 configurations out of the 60 ones. To be able to change this frame rule, there are several possibilities:
  • Go in and out of the menu. You can set the frame rule you want by delaying the exit of the menu by 1, 2 or 3 frames. This is however very costly if you don't have any menuing to do.
  • Delay the enter in the dungeon from the world map. This is only useful for the first fight in the dungeon.
  • Delay the end of a previous winning fight. Fights usually have at least an XP gain message. You can delay the confirmation of this message which will alter the frame rule. Because most fights are escaped, this has a limited application. It is very useful for the Minecart sequence for example.
  • Add lag frames during the previous fight. By entering the inventory and moving items, it can make the game lag, which will alter the frame rule after the fight. The most reproducible way to add 1 lag frame is to switch the weapon and the buckler. Switching them again may add another lag frame, but this is definitively not an exact science. This trick is used extensively through the whole run.

Desperation attack

Desperation attacks are rather secret and powerful attacks in ff6. Under specific conditions, the attack command has 1/16 chance of triggering a character specific technique dealing massive damage to one enemy. Those conditions are:
  • The character must be in the near fatal status, when HPs are lower than 1/8 of max HPs
  • The number of battle ticks must be over 768. In other words, we have to wait for about 25 seconds after the beginning of the fight.
  • The character must not be in the Muddle, Image, Clear or Zombie status
  • You can only cast one desperation attack per character per fight
  • Gau, Umaro and special characters don't have a desperation attack
The desperation attacks are magical attacks that ignore the defense of the enemy. So the amount of damage only depends on the level, the magic stats of the caster and the random variation. Strago and Relm desperation attacks are different, they kill instantly the target.

Message speed tricks

Escaping fights is usually faster to do when getting a preemptive or side attack. Sometimes, however, not all characters will run away immediately. The remaining characters will run away about two seconds after. This usually happens when the number of characters is higher than the number of enemies. In this case, there are two ways to get a faster run-away. The first solution is to get a front attack instead, and try to run away as soon as possible. This is used during Sabin scenario mainly, for the single Ghost fights. It saves about one second. The other solution is to set the Message Speed to 2 in the Options. In this case, all run-away during preemptives/side attacks will be perfect. The downside is of course that each battle message text box will be longer by about 16 frames. This includes the "Preemptive"/"Side attack" message and every command message. This is used twice in this run, during Mt Kolts and during Terra scenario, as there are many random fights and we control a team of three characters.

Run-away trick

The way the RNG works during fights is that you have a general counter stored in $BE which is used as an index in the random static array $C0FD00-$C0FDFF. Each time the game pulls a random number, it increases the RNG index by one. During the fight, when no action is playing, the RNG index increases by one unit per frame. When an action is starting, the game pulls several random numbers to compute the action random factors (random damage, miss, criticals, chance of giving status, etc.) and then the RNG index is frozen until the animation of the action ended. If several actions are queued, then the RNG index will just increase by the number of random numbers pulled between each action.
There are several ways to manipulate the RNG, which is very useful to get criticals, desperation attacks and to manipulate the enemies behavior. The first one is simply to delay an action so that the RNG index will be frozen at a different value, and subsequent actions will use different random numbers. However, this is only possible when no action was made before it (typically the first action of the fight). Sometimes, you want to cast actions as fast as possible to queue them before enemies actions. In that case, there is a very useful trick using the run-away (R+L).
The game checks about every two seconds (more often with the Haste status) if each character is running away. If it is the case, it pulls a random number between 1 and a character specific run-away constant (stored in $3D71, $3D73, $3D75, $3D77 for each character) and adds it to a counter (stored in $3D70, $3D72, $3D74, $3D76 for each character). If this counter gets over the run-away difficulty (usually 2 times the number of enemies) then the character will escape the fight. The important part here is that you can make the game pull random numbers, thus increasing the RNG index, even during action animations. Let's say the animation takes 4 seconds and you have 4 characters in your party. At the end of the animation, you can set the RNG index to 9 different values. This is also useful to try to cast the desperation attack as soon as possible after the time limitation is passed. This trick is not working for preemptive/side attack battles, as the run-away counters are not increasing.
If this tricks allows you to increase the RNG index during animations, you can also do the opposite. When no animation is played, you can freeze the RNG index by popping the "Can't run away" text box. This was used several times in the run.

Save/reset

During the game startup, some RNG values are initialised based on a value stored in SRAM. In details, after the introduction, the game increments the address $307FF1 (or $1FF1 in SRAM). Then, when you load a save slot or you start a new game, it adds 13 to $307FF1 and also stores this value into $1FA1 and $1FA4 (determines how many steps until next fight), $1FA2 and $1FA3 (determines which enemy formation will be fought), $1FA5 (determines which enemy formation pack will be fought on the Veldt) and $1F6D (determines the NPC behaviour, the Lete river encounter randomness, the fish randomness, etc.). The address $307FF1 is not contained in one of the 3 save slots, meaning that whatever slot you loaded, you will get the same randomness. During this run, we saved and reset the game twice to set all the encounter randomness to other values, which was useful to get the right fight at the right time.
Because we are supposed to make the TAS from a clear game state, address $307FF1 was never set before so the game is using an uninitialised value. BizHawk sets the entire SRAM memory as 0xFF, so this value was used as the seed of the encounter randomness. Moreover, the 2-byte integer $1F6E-$1F6F is also not initialised by the game. This value is the danger counter that increases at every step and is compared with a random number to determine if a battle occurs. This value is stored in the save slot, so you recover it when loading your save, but if you start a new game, the game will not initialise this value. In BizHawk, the RAM is filled with numbers that do not follow a specific pattern. The address $1F6E-$1F6F contains the integer 0xFDFB. This is a very high value, which explains why, in the TAS, a fight is triggered after one step in the Narshe cave.

Move across objects/event tiles

Simple clipping

Entering and exiting the menu at the right time allows you to move on the same tile as a moving guard. This is used during Locke scenario to skip Celes.

Simple party switch trick

During a few sequences in the game where you have multiple parties to manage, you can switch between parties using the Y button. If you press X to enter the menu and then Y during the fade-out, you will still switch to the next party and the menu will open for them. You can also press again Y during the fade-in before the menu opens to switch again to another party, and this can be iterated for as long as you want. During all that time, monsters on the field will move, but fights won't trigger if a monster gets close to you. This trick is used during the Kefka at Narshe sequence, to allow a monster to move close to you without triggering the fight, saving about 8 seconds.

Advanced party switch trick

A related trick can be used to go through a tile associated with an event without triggering it. To do that, press Y just before reaching the event tile and use the above trick (X then Y during the fade-out) to go back to the party with the menu opened. Then, change the leader of the party and close the menu. You are now able to move without triggering the event of the tile you were standing on. This trick was used to skip Inferno in Kefka's tower. This trick can be linked multiple times to disable continuous event tiles, which allowed us to move on a specific conveyor belt backwards, skipping another boss in the tower (Poltergeist).

Sketch glitch

In short

The sketch glitch is the major glitch used in this run. Missing the sketch command with Relm, for specific characteristics of the 28th spell of the first character, may induce a partial rewriting of your inventory, graphical glitches, freezing or even a softlock. This glitch is only available on the v1.0 version of the US rom.

How does it work?

During a successful sketch, the game will get which monster was sketched and look for the sprite of that monster in the memory. It will copy the sprite in the RAM and display a flipped version on the screen. When the sketch misses, the game will still do all the procedure except for the display. The origin of the problem is in function C2/F5D2:
...
C2/F5E1: A0 03 00     LDY #$0003
C2/F5E4: B1 76        LDA ($76),Y    (get the enemy slot)
C2/F5E6: 0A           ASL            (multiply by 2)
C2/F5E7: AA           TAX
C2/F5E8: C2 20        REP $20
C2/F5EA: BD 01 20     LDA $2001,X    (get the enemy id in this slot)
C2/F5ED: AA           TAX
C2/F5EE: 7B           TDC
C2/F5EF: E2 20        SEP $20
C2/F5F1: 22 D1 24 C1  JSL $C124D1    (load the enemy sprite)
...
During a successful sketch, instruction LDA ($76),Y loads the enemy slot number (between 0 and 5), and get the monster id by looking at the array $2001-$200C containing the id (16-bit integer) of the 6 monsters present in battle. However, when the sketch misses, instruction LDA ($76),Y loads 0xFF instead of the enemy slot number. So LDA $2001,X is wrongly fetching the 16-bit integer $20FF-$2100 as the enemy id. This address is in the middle of the battle spell table. $20FF contains information about the usability of the 28th spell of the first character (was used/available). $2100 contains the aiming byte of the 28th spell of the first character.
The function C1/24D1 and sub-functions are executed with an incorrect enemy id. The next problem arises in function C1/215F. This function loads the disposition of tiles in an enemy sprite. Indeed, tiles are stored in one dimension in the game memory, and it uses a mapping to place the tiles to build a two-dimensional sprite. The list of mappings for each enemy sprite is located starting $D2A820. This function loads the mapping corresponding to the enemy id and stores it in the array $822D-$824C. From this array, the game derives the height and the width of the enemy sprite in tile units. This is the critical portion of the function:
C1/21B8: A6 00        LDX $00
C1/21BA: C2 20        REP #$20       (set 16-bit accumulator)
...
C1/21BE: BD 2D 82     LDA $822D,X    (get mappings for this row of tiles of the bitmap)
C1/21C1: F0 0B        BEQ $21CE      (if none of the tiles in this row are set, branch)
...
C1/21C7: E8           INX 
C1/21C8: E8           INX 
C1/21C9: E0 20 00     CPX #$0020
C1/21CC: D0 F0        BNE $21BE      (loop for all 16 rows. When this loop exits,
                                      X will hold the # of rows in the image
                                      that have any valid tiles times 2.)
The game computes the height of the sprite as the number of valid (non-zero) tiles in the mapping. Keep in mind that if the enemy id is wrong, the mapping array will also be wrong. If this mapping array starts with the 0 value, the computed height of the enemy sprite will be zero.
Now, the most important function is function C1/22A5 which copies each tile of the enemy sprite from ROM to RAM, depending on the mapping array. This function is basically a double 'for' loop on the width and height of the enemy sprite. Then, a tile is copied for every bit set in the mapping array. Here is the portion of the code that decrements the sprite height and loops, at the end of the function:
C1/22D7: CE 53 82     DEC $8253    (decrement adjusted monster height/8, iow, its tile height)
C1/22DA: D0 C9        BNE $22A5    (loop if we haven't finished processing/copying
                                    all the rows of the monster's tiles.)
Notice that the game *first* decrements the height, and then checks if it's non-zero. What happens if the height is zero in the first place? The variable becomes 255, so the game will assume that the sprite has a tile height of 256! This is a very high value, the maximum tile height planned by the game is 16. This will lead to many more tile copies than normally, which will overwrite many other memory locations.

Which variables affect the outcome of the glitch?

As said earlier, the game will load the availability and the aiming of the 28th spell of the first character, and interpret them as the enemy id. During battle startup, the spell list of all character present in the battle is compressed and stored for each character. The compression is as followed: the whole spell list is placed in a table of three columns. If a row does not contain any spell known by a character present in the battle, that row is deleted. The remaining table is placed in the Magic menu for each character, with only their known spells. If we want to have a spell in the 28th slot, we have to learn at least 10 spells that will each one fill a different row. The route for the present TAS is to learn:
  • Cure (Lv1), Fire (Lv3), Antdot (Lv6) and Drain (Lv12) with Terra's natural magic
  • Sleep (10 AP), Mute (13 AP) and Slow (15 AP) with Siren
  • Bio (13 AP) and Break (20 AP) with Shoat
  • Muddle (15 AP) and Imp (20 AP) with Stray
Here is how the magic list looks like during a fight where all 10 spells are present. 10 rows are filled so that Break is placed at the 28th position.
Cure     Cure 2    Cure 3
Life     Life 2    Antdot
Remedy   Regen     Life 3
-
Scan     Slow      Rasp
Mute     Safe      Sleep
Muddle   Haste     Stop
Bserk    Float     Imp
Rflect   Shell     Vanish
Haste2   Slow2     Osmose
Warp     Quick     Dispel
-
Fire     Ice       Bolt
Poison   Drain     Fire 2
Ice 2    Bolt 2    Bio
Fire 3   Ice 3     Bolt 3
Break    Doom      Pearl
Flare    Demi      Quartr
X-Zone   Meteor    Ultima
Quake    W.Wind    Merton
-
Now that we know how to place a spell at the 28th position, we can focus on the characteristics of the spell that affect the sketch glitch. First, the aiming of the spell consists of an 8-bit integer where each bit has a different meaning:
  • Bit 0 = Cursor Moveable
  • Bit 1 = One Side Only
  • Bit 2 = Autoselect both parties
  • Bit 3 = Autoselect one party
  • Bit 4 = Auto Confirm
  • Bit 5 = Multiple Selection possible
  • Bit 6 = Cursor Start on Enemy
  • Bit 7 = Random selection among all enemies and allies
There are 13 different aiming bytes represented in this game:
  • 0x00 (Self): Warp
  • 0x01 (Allies or enemies, single): Safe, Haste, Bserk, Rflect, Shell, Vanish, Life, Life 2
  • 0x02 (Self): Quick
  • 0x03 (Allies, single target): Antdot, Remedy, Regen, Life 3
  • 0x04 (Allies and enemies, multi target): Quake, W Wind, Merton
  • 0x21 (Allies or enemies, single or multi target): Float, Cure, Cure 2, Cure 3
  • 0x29 (Allies or enemies, multi or single target): Haste 2
  • 0x41 (Enemies or allies, single target): Poison, Drain, Break, Doom, Pearl, Flare, Scan, Slow, Rasp, Mute, Sleep, Muddle, Stop, Imp, Osmose, Dispel
  • 0x43 (Enemies, single target): Demi
  • 0x61 (Enemies or allies, single or multi target): Fire, Ice, Bolt, Fire 2, Ice 2, Bolt 2, Bio, Fire 3, Ice 3, Bolt 3
  • 0x69 (Enemies or allies, multi or single target): Slow 2
  • 0x6A (Enemies, multi target): X-Zone
  • 0x6E (Enemies, multi target): Quartr, Meteor, Ultima
We used in this route the 0x41 aiming byte because it gives access to the shortest setups. The second characteristics is the availability of the spell. It is represented as a 8-bit integer, whose bit 7 is set if the spell is not available (grayed) or cleared if it is. When the game updates the availability of the spell (function C2/5763), the integer is shifted right and the new availability bit is stored in bit 7. At the beginning of the battle, the integer is initialised as 0xFF and the game updates the availability of every spell.
During the fight, the game calls this update function when:
  • The holder of the spell received a MP heal by an item. Items having the "Concerns MP" flag set are Tincture, Ether, X-Ether, Elixir, Megalixir, Sleeping Bag and Tent.
  • The holder of the spell consumes MP using the Magic, X-Magic, Esper or Lore commands. Spells costing 0 MP don't trigger the update.
  • The holder of the spell is imped or de-imped.
The game does not call the update function when:
  • The holder of the spell attacks with a weapon with the "critical MP" property (like the Rune Edge), thus reducing his MPs.
  • The holder gets the Mute status. In this case, the Magic command is disabled, not every individual spell, as opposed to the Imp status where every spell except Imp are disabled.
For example, if we want to place the integer 0x83 (or 0b10000011) in the availability byte, we can do the following:
  1. Start the fight with the 28th spell available (0x01111111)
  2. Use a Tincture on the first character (0x0011111)
  3. Use a second Tincture (0x00011111)
  4. Use a third Tincture (0x00001111)
  5. Use a fourth Tincture (0x00000111)
  6. Use Imp on the first character (0x10000011)
During a sketch, we saw that the game is using the mapping array $822D-$824C to determine if a tile must be copied from ROM to RAM. During a sketch glitch, however, as the sprite height is incorrectly set to 256, the corresponding mapping array will be $822D-$842C, overflowing the next portion of memory. Addresses from $824D to $8258 store local variables, but addresses starting $8259 store the offsets of each enemy position. These offsets depend on the formation mold. Every enemy formation is using a specific formation mold, which gives the coordinates and maximal dimension of every enemy. There are 13 different molds used in the game. Each formation mold will lead to overwriting different parts of memory during a sketch glitch.

Taking advantage of the sketch glitch

The main beneficial outcome of the sketch glitch is to erase part of your in-battle inventory ($2686-$2B85). At the end of the battle, the game loads the in-battle inventory into the general inventory ($1869-$1A68). Thus all items that appeared during the sketch glitch are kept. The in-battle inventory stores 5 bytes per item:
  • Byte 0: Item id
  • Byte 1: Item flags
    • 0x08: Is a shield
    • 0x10: Is a weapon
    • 0x20: Can be thrown
    • 0x40: Is a tool
    • 0x80: Not usable as an item in battle
  • Byte 2: Item targeting
    • 0x01: Cursor Moveable
    • 0x02: One Side Only
    • 0x04: Autoselect both parties
    • 0x08: Autoselect one party
    • 0x10: Auto Confirm
    • 0x20: Multiple selection possible
    • 0x40: Cursor Start on Enemy
    • 0x80: Random selection among all enemies and allies
  • Byte 3: Item quantity
  • Byte 4: Item equipability
    • 0x01: Onscreen character 0 can't equip item
    • 0x02: Onscreen character 1 can't equip item
    • 0x04: Onscreen character 2 can't equip item
    • 0x08: Onscreen character 3 can't equip item
Added to the fact that you have access to a bunch of new items, the sketch glitch also allows you to change the characteristics of an item without changing its type. Indeed, on some item slots, only part of the characteristics will be overwritten. Thanks to this, you are able to flag any item, leading to useful tricks like:
  • Flagging an item as a weapon or a shield and equip it during the fight. The item will be kept in your equipment after the fight. All special effects of the item will be operative even if the item is not in the right spot (e.g. a Moogle Charm in the right hand will still remove random encounters)
  • Flagging an item as usable in fight and use it
  • Duplicating an item by overwriting its quantity
The Japanese equip-anything glitch still applies here. This glitch, only possible in the Japanese version of the game, allows you to equip an item in an equipment slot if:
  1. you put that item in the 255th slot
  2. you don't have any item in your inventory that fits in that slot
  3. you select Optimize
In the US version of the game, the developers disabled the 255th slot, but a sketch glitch can still put an item in that slot. You can then move that item into an equipment slot by the same method.
The sketch glitch also overwrite the in-battle Magic menu. This menu starts at address $208E for the first character and contains 4 bytes for each spell:
  • Byte 0: Spell id
  • Byte 1: Spell availability
  • Byte 2: Aiming byte
  • Byte 3: Spell MP cost
We don't have as much freedom as the inventory, but a sketch glitch can give inaccessible magics. Magics are not only white/black/grey magics that we learn during the game, but also Espers, Skeans, SwdTechs, Blitz, Dances, Slots, Magitek, Lores, enemy attacks, desperation attacks and Interceptor attacks.
Also, for a few formation molds (2, 4 and 8), the sketch glitch overwrites the command list. This list is stored starting $202E and takes three bytes per command:
  • Byte 0: Command id
  • Byte 1: Command availability
  • Byte 2: Aiming byte
Unfortunately, those molds are known to freeze the game easily.
The consequences of the sketch glitch for each mold and spell setup can be generated from this lua script which outputs a spreadsheet.

Goggles glitch

If a character attacks with the Goggles item (which can be placed here thanks to the sketch glitch) and another character opens the Magic menu at the same time, the menu will show items from the inventory if scrolled up or down. If an item is used, the character will cast the magic whose id corresponds to the id of the item. For example, if a character uses the Antidote item (id 0xF2) in the glitched Magic menu, he will cast Cyan's desperation attack Back Blade (id 0xF2). In this run, we used the Goggles glitch with the items Black Belt (id 0xD5) and X-Potion (id 0xEA) to cast the magics Engulf (id 0xD5) and Bababreath (id 0xEA). Because Black Belt is not a usable item, a sketch glitch is needed to flag it as usable. The magic Bababreath is normally cast by the boss Phunbaba on the party, it removes the target from the battle. It also works when casting on an enemy. The magic Engulf is described below.

Engulf

There is an enemy in the game called Zone Eater in the World of Ruin who has the Engulf attack. This attack removes the target from the battle. If all the party is engulfed, the party is sent inside the Triangle Island cave, where the secret character Gogo can be recruited. Thanks to the sketch glitch, the Engulf magic can be cast by a character as soon as Relm is recruited, in the World of Balance. If cast by a character, the magic will auto-target an enemy, so Muddle is necessary to be able to cast it on a character. In that case, if the entire party is engulfed, it will be sent inside the Triangle Island cave. If the party exists the cave using the light exit on top (using a Warp Stone won't work), it will appear on the Triangle Island in the World of Ruin. The airship will have the same coordinates as where it was left. Because of this, the party will be stuck if the airship was not left on the island beforehand.

Unused tricks

Sleeping Bag

When you make an item usable in fight thanks to the sketch glitch, most items that were not supposed to be used will cast Fire. Some items, however, will have its own effect. When using a Sleeping Bag on someone, it will recover all his MPs with no item animation. Compared to a Tincture or an Elixir, the Sleeping Bag is about 100 frames faster to use. It could have been possible to use it instead of the Tincture in the run, but the required sketch glitch before being able to use the Sleeping Bag made this strat slower in the end.

Other glitched weapons

The sketch glitch can allow a character to equip as a weapon every item in the game. When a character attacks, the game loads the weapon graphics from $ECE400+8*id to $626B-$6272. Address $6270 (unknown purpose, launching flag?) varies between 0 and 4 for regular weapons. This address is used in the following code:
C1/C269:    AD7062      LDA $6270
C1/C26C:    297F        AND #$7F
C1/C26E:    0A          ASL A
C1/C26F:    AA          TAX 
C1/C270:    7C73C2      JMP ($C273,X)

Pointers to code

C1/C273:    86C2        (00)        
C1/C275:    99C2        (01)
C1/C277:    7DC2        (02)    
C1/C279:    12C3        (03)
C1/C27B:    73C3        (04)
For glitched weapons, however, address $6270 can take arbitrary values. So the above code will jump to a random place within C1 bank.

Tier change

With a sketch glitch against a formation mold 4, with a 0x41 aiming spell and 0xBF availability, the second command of the third character will be replaced with the command 32, which triggers the tier change during the Kefka fight. In this case, the tier change will load another enemy formation depending on the aiming of the command. The binary representation of the aiming value is the following two-bytes integer:
0 0 foe6 foe5 foe4 foe3 foe2 foe1 0 0 0 0 char4 char3 char2 char1
So we can load enemy formations with an id as high as 16143, knowing that formations are normally included between 0 and 575. This leads to aberrant formations.

Goggles glitch with other menus

The Goggles glitch was used in this run with the Magic menu. It can be used with many more menus, but this was not actually deeply tested:
  • SwdTech: Cyan will cast a magic whose id will be the id of the item + a constant (85). Indeed, the game indexed the SwdTechs starting 0, and adds a constant to get the corresponding magic id. For example, if you use the item Fire Shield (id 96) in the glitched SwdTech menu, Cyan will cast the magic Tek Laser (id 181 = 96 + 85). The magic seems to automatically target the enemy, even if the target was set to be on the party.
  • Blitz: We couldn't get it to work
  • Tools: Edgar will damage the enemy, and sprites will start to move in an odd way through the screen
  • Rage: Not tested, but we supposed that it would not have any effect, because there are 256 rages already
  • Slots: Setzer will cast a magic whose id is stored in the address $C24E4A + itemid. For example, if Setzer uses the Potion item (id 0xE9) in the glitched Slots menu, he will cast the magic whose id is stored in $C24F33 which is the desperation attack MoogleRush (id 0xFA).
  • Command: Instead of opening a sub-menu, we can change character by using X or Y. If done right, the command menu of the new character will be glitched as the item menu. This should allow us to cast any command.

Alternative wrong warps

There are at least three ways to do the Engulf wrong warp:
  • The Engulf spell can be written in the magic list using the sketch glitch
  • The Engulf spell can be cast using the Goggles glitch, by using the Black Belt item
  • When triggering the sketch glitch against formation mold 3, the variable ($3EBC) that stores if the whole party was engulfed is rewritten. For specific sketch glitch setups, this variable is rewritten to a value that indicates that the party was engulfed. The downside is that a sketch glitch against mold 3 is followed by a freeze of the game, which can take minutes. This is however the safest way to do the wrong warp for an unassisted speedrun.

Comparison

LocationPresent TASErokky TASDifferenceCumulative differenceCommentary
Introduction808380651818Emulator differences probably
Magitek Armor to Whelk185261721712911309A slightly different route. Also because of uninitialised RAM, we got an extra fight in the cave
Whelk fight2230121007-151294Closing the command window before the end of the fight saves a bit of time
Terra escape4443443973-833461We run away the two random fights
Marshal Lobo fight476184714314475
To Figaro Castle5386153491-105370
Figaro Castle770007660822392We waited more than 2 seconds for the Lete River manipulation, but only loosing 22 frames... maybe thanks to 1-letter names?
M-Tek fight7948879196-100292We got a Metal Kick instead of a Tek Laser
To the Cave8345683201-372551-letter names
Cave8847088027188443We made characters escape so Terra got the level up
South Figaro9077490214117560We bought a Goggles and set the Message Speed to 2
Mt Kolts100509101987-2038-1478Faster escaping thanks to the Message Speed 2 and no fight won
Vargas fight105318107004-208-1686Better Sabin ATB
Road to Returner's Hideout110166112006-154-1840Another fast escape
Returner's Hideout121114124203-1249-3089Better river manipulation
Lete river126839131640-1712-4801Didn't win the two mandatory fights
Ultros 1129450134126125-4676Slower fight due to underleveled Terra
Team splitting132320137081-85-4761Renaming
Locke Scenario136256153356-12339-17100Skipping Celes
TunnelArmor139253156372-19-17119
Terra scenario152729170285-437-17556Faster escaping thanks to the Message Speed 2
Doma191574211485-2355-19911One less Grunt during a fight, Battle Speed 1 for Leader
Phantom Train210362229993280-19631More solo Bomb :(
Rizopas22549624507453-19578Battle Speed 1, making more attacks from the enemies so more lag
Veldt246759271176-4839-24417No farming for Snare, but bad RNG
End of Sabin scenario256117281353-819-25236Perfect escape underwater
Narshe269312294999-451-25687Guard clip
Kefka271815297538-36-25723
Terra cutscene282969308794-102-25825Renaming
Road to Zozo2954183196491594-24231Save and Reset
Zozo302660327460-569-24800Solo Sabin
Dadaluma305371330239-68-24868
Road to the Opera3317103552251353-23515One extra fight on the way and more menuing
Opera372754396797-528-24043...I don't know
Rats373878397807114-23929Bad rat RNG
Ultros 2379291403410-190-24119
Airship cutscene39362941769454-24065Having Sabin and Edgar here costs time
Road to Vector39552041950184-23981Longer menuing
Before Ifrit404124428660-555-24536One less fight
Ifrit405779431504-1189-25725Ifrit escape trick
To Number 024411286437030-19-25744
Number 0244143054385151534-24210Old TAS used the Muddle/Phantom/Snare technique. We don't have Snare
Before Minecart425280449571-81-24291
Minecart432868457921-762-25053Better enemy formations by putting Sabin in the first slot
Number 128435748461410-609-25662
Before Cranes44059846623030-25632Lost time for ATB manipulation
Cranes442010467876-234-25866Didn't need to steal Debilitator
Esper World464383490296-47-25913
Narshe cutscene4726044965791938-23975Stop by on the Island to kill an Intangir
Cave to the Sealed Gate490097516111-2039-26014Less fights
Road to Vector499955526013-44-26058
Banquet530121560087-3908-29966Didn't go for the Charm Bangle
Road to Thamasa5548235834681321-28645Second save and reset
Fire House571283600354-426-29071Better Bomb placement
Flame Eater573908603178-199-29270Morph saves time
Road to Esper Cave586853616255-132-29402
Before Ultros5937636218631302-28100Won two fights for XP and MP
Ultros 3595989624204-115-28215
Rest of Esper Cave6064426331061551-26664First sketch glitch to get Flame Shields
Before Leo614754641425-7-26671
Leo619067647522-1784-28455Saved time with the Flame Shields
Rest of the cutscene644204672744-85-28540
Road to Kefka tower655568821759-137651-166191Wrong Warp
Road to Guardian671076844652-7385-173576Skip Inferno and Moogle Charms
Three Statues679348857351-4427-178003Well, only two Statues
Kefka cutscene688189867318-1126-179129Skip Terra cutscene
Kefka689323883418-14966-194095Thanks Bababreath
End69110488517227-194068

Known improvements

  • Based on the above comparison table, it could have been faster to set Battle Speed to 6 just after the Phantom Train before Rizopas. We think Rizopas appearance is delayed when actions are made during the fight. And having the Battle Speed set to 1 caused the enemies to attack more often.
  • Some fights in Doma Castle were not good, especially the Grunt and Cadet fight.
  • The RNG on Sabin scenario was very bad: we got 3 fights against a single Bomb during the Phantom train (costing 3 seconds) and we got the unescapable fight against Templars and Soldiers on the Veldt. The latter is dependent on an uninitialised value in the RAM, which is set arbitrary by the emulator. The former, however, may be avoided by swapping scenarios (putting Terra last).
  • We forgot that we would need the Magic command on many people during Kefka tower, and thus Espers equipped. We had to lose time by equipping them one by one during the tower, we could have equipped them during just before the Opera.
  • We unequipped Sprint Shoes from Locke at the end of his scenario, but he is taking a few steps after that is affected by the presence of Sprint Shoes. We could have taken the Sprint Shoes from Terra instead.
  • Rhizopas skip
  • Kefka Tower skip and Kefka fight skip

Special Thanks

  • masterZed for first documenting the sketch glitch. This was really useful to disassemble the glitch
  • amaurea for writing a very complete lua script. It still had a few bugs, but fixing them didn't take us a long time and it was heavily useful for producing the tas.
  • Tanooki Teabag for discovering the Goggles glitch
  • simon for helping with the tas and writing a program which outputs the optimal magic route for the sketch glitch
  • Yousei, Novalia Spirit, Mnrogar, Imzogelmo, Cless, assassin, Lenophis, Terii Senshi, abyssonym, and many other for all the work that has been done in the past 10 years for disassembling ff6 code
  • Lord J for concentrating all this information into a very useful program: ff6usME
  • Catastrophe for making the previous ff6 tas with sketch glitch route, which was useful to use for comparison. Also thanks for suggesting the ultimate spell: Bababreath, and the work for optimising the end game
  • LCC for his deep knowledge of the game, for finding a few tricks that was helpful in the tas.
  • Erokky for doing the previous tas and writing very valuable information in the submission text

Suggested screenshots


FractalFusion: Changed game name to "Final Fantasy VI" to match that of the current publication.

turska: Judging.

turska: Accepting for publication to Moons in a new "sketch glitch" branch.
Spikestuff: Publishing.


TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15629
Location: 127.0.0.1
Joined: 5/8/2010
Posts: 177
Location: Entropy
This run is bound to be great, having it played myself I can already see that it will be great by being only 3 hours long. Will cast my vote when I have time to watch it. Edit 1: Still haven't had time to watch this, days are to full. Edit 2: After finally finding time to watch this beast, there's nothing else than a Yes than can be given. Great work. It's been a few years since I last played this game so much memories.
Synahel
She/Her
Former player
Joined: 1/19/2011
Posts: 260
Location: France
Having watched the WIP closely, having seen the HUGE work Keylie and Kadmony have been through, this is my TAS of the year. Kudos to you two, it's amazing.
Editor, Skilled player (1824)
Joined: 8/25/2013
Posts: 1200
Fantastic TAS! Awesome to see FF6 finally get an update :3 Yes vote for sure on this one.
effort on the first draft means less effort on any draft thereafter - some loser
Player (13)
Joined: 6/17/2006
Posts: 510
As I have mentioned in the FF6 thread, I have a big issue with the softlock occurring near the end of the game. For me, this doesn't count as beating the game, falls in the "missing critical ending routines" criteria from the Judge Guidelines, and invalidates all the hard work that was put in this run in my eyes. I don't have anything against glitched endings in general (on the contrary), but I do have a problem with incomplete endings. It's like watching a really good movie that would suddenly cut one minute before the end of the story. As such, I am forced to vote No for entertainment, as I still feel betrayed, even one week after my original viewing, for watching a seemingly-amazing run that don't fulfill my most basic expectation. While I greatly appreciate the tricks and glitches showcased here and their technical explanations by themselves, it's all spoiled by that one issue which I can't overlook. P.S.: I know that the Dragon View TAS was published under similar conditions, but I believe it was a mistake to do so and is a bad precedent that should not be repeated.
Joined: 7/27/2014
Posts: 4
This run is amazing and it should be on the front page of TASVideos.
@oxydoreduction twitch.tv/oxydoreduction
Joined: 5/13/2009
Posts: 141
Wow. "Yes, please!" vote.
jaysmad
Other
Experienced player (933)
Joined: 12/1/2006
Posts: 629
Location: Mom's
YES STAR KUPO!!!!
Spikestuff
They/Them
Editor, Publisher, Expert player (2656)
Joined: 10/12/2011
Posts: 6449
Location: The land down under.
I love this, I love you, I love the length of this, I love how I didn't get bored. I love how I'm going to give it a YES Vote.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
Editor, Player (69)
Joined: 1/18/2008
Posts: 663
The latter is dependent on an uninitialised value in the RAM, which is set arbitrary by the emulator.
What? Since when? And even if this information were true, why would this not be manipulable?
true on twitch - lsnes windows builds 20230425 - the date this site is buried
Joined: 2/12/2008
Posts: 67
Location: San Francisco Bay Area, CA
Amazing. I was not bothered at all by the ending softlock, as the ending clearly began. (Anyway, because of the way the scripts work, apparently any TAS that skips the normal World of Ruin transition will trigger this softlock, and the entertainment that the skip provides outweighs the disadvantage of the softlock, at least to me.)
Joined: 1/17/2008
Posts: 133
Nightwatch wrote:
Amazing. I was not bothered at all by the ending softlock, as the ending clearly began. (Anyway, because of the way the scripts work, apparently any TAS that skips the normal World of Ruin transition will trigger this softlock, and the entertainment that the skip provides outweighs the disadvantage of the softlock, at least to me.)
As a not-FF-player, I will assume this softlock is - common knowledge - has been common knowledge for a long time - most/all of the FF speedrunning community considers it valid completion Otherwise, why on earth would the author's comments not even mention it?
Patashu
He/Him
Joined: 10/2/2005
Posts: 4045
In the east, RPG speedruns end at 'The End'. In the west, RPG speedruns end as soon as the credits BEGIN. So this is a valid TAS in the west but not in the east.
My Chiptune music, made in Famitracker: http://soundcloud.com/patashu My twitch. I stream mostly shmups & rhythm games http://twitch.tv/patashu My youtube, again shmups and rhythm games and misc stuff: http://youtube.com/user/patashu
Spikestuff
They/Them
Editor, Publisher, Expert player (2656)
Joined: 10/12/2011
Posts: 6449
Location: The land down under.
Patashu wrote:
In the east, RPG speedruns end at 'The End'. In the west, RPG speedruns end as soon as the credits BEGIN. So this is a valid TAS in the west but not in the east.
And considering that this was the west version, Congratulations.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
keylie
He/Him
Editor, Emulator Coder, Expert player (2845)
Joined: 3/17/2013
Posts: 392
True wrote:
The latter is dependent on an uninitialised value in the RAM, which is set arbitrary by the emulator.
What? Since when? And even if this information were true, why would this not be manipulable?
Maybe I wasn't clear. I will add a paragraph in the submission regarding this. For example, during the game, address $1FA1 stores the index in the random array regarding encounters triggering. When you power-on the console, the game loads the address $307FF1 (which is in the Save-RAM), add 0x0D to that value, stores again in $307FF1 and also in $1FA1. If you have never played the game before and the cartridge is brand new, the game will still load address $307FF1 even if the Save-RAM memory has never written to. When I said "arbitrary", I mean that the developers of BizHawk chose to put values in Save-RAM that are not all 0 but different values in different addresses.
Player (109)
Joined: 11/3/2014
Posts: 9
Although I generally prefer not to express myself more than necessary on the subject -having neither taste nor the will to do so- i would like to develop some additional points and recollections. I never played nor got interested specifically on FF6 until the middle of February. At this time, during a run of MV, i asked to myself "when does a character enter the memory of the game?". The only reasonable time being the time when the character is being named, I suggested to MV to try to semi-skip Celes. We tested it right away on a secondary stream -Synahel and other friends already being there at this point- and thanks to his knowledge we came to the now classical Locke's scenario strategy. In spite of the fact that this improvement was not essential, I still thought of it as a valuable and esthetic artifice of the run. This drove me to the will of looking more closely to the route. I then encountered the 'Let's play archive' dedicated to FF6 glitches, and my inspiration was stirred by the description on how it remains possible to glitch the game 'a la japonaise' -through the 255th slot- using the sketch glitch. I began some tests and ended up with an abstract route, which essentially delayed one of the most intricate problem : the magic route. The toying around thus swiftly turned into an empiric study of the game, and I discovered step by step through experience how the game deals with magic, not knowing that TASers had already unleashed those mechanics previously with their tools. I came up with the banal magic route going for the pseudo-mandatory Vanish magic, whose drawback -among many others- was to force an Intangir fight. I was not satisfied with it and i would have not accepted to release such rough route. At this time MV and Brandy were sometimes coming to my home and supported me, as i was exhausted struggling with all these datas. For some reason, I once saw a reverse Phantom strat and discovered right after that it was actually possible to Sketch Glitch using Muddle, in stead of Vanish. This detail is one of the most important features of the Sketch Route, since it allows more flexibility in the magic learning. I then went again for empiric research on the shortest path to slot 28, and came up with a really fast one, consisting mainly on naturally learned Terra magics, as well as Muddle-Imp, which are 'mandatory' to trigger the glitch. The game was then routed and learned in some weeks, with the other new improvements and circonvolutions I wrote in my notes. I then came to Kilaye and offered to work with him on a TAS. He was very busy at this time and couldn't get into it. Some weeks after -on the 28th of June, if i recall correctly- Kilaye came back to me and was now ready. The Skype conversation 'FF6 - constant brainstorm' was created and the 'French TASers', as people seem to call us, began to work. As i said here and there, more than 600 pages of conversation were needed to realize this TAS, and there has not been any line on which we didn't have the same point of view. At some point I was reluctant to starting TASing the begining of the game, fearing bad random encounter manipulation, but Kilaye decided that we should go in, even though the strategy was not settled. I would like to point out that Kilaye has been in charge of almost all the technical realization of the TAS. The admirable self-denial he demonstrated when solving all these micro-issues is impressing. Simon and myself offered a first Wrong Warp route, which had lots of subtle circonvolutions but was satisfying in terms of swiftness. Kilaye thought that this could be improved, and worked on another way to Warp, using subtle tricks such as Tier changes. He came up with an hypothetic new way to Warp and for some reason, as soon as he explained this to me, I asked him "... nevertheless, why don't we do 'this'?". The discussion dropped instantly and 'this' became the route of the TAS, which in fact remains in the same spirit as the first route, being slightly faster and much safer. One of the greatest personal satisfaction of all of this is that the final magic route of the TAS is actually the magic route i came up to empirically from the very begining. Simon has shown rigorously that this magic route is the fastest possible to Sketch Glitch. There are three points on which the TAS did not eventually satisfy me completely. First, I still have the faith in a warp to credits (Kilaye will probably say that it's really hard to remove things, once when they get into my mind :)). Hopefully there will be some oppportunities to do so, and we stay aware of this. Esthetically, i would also have loved to farm for Magic Points using Reverse Magicite to cast Phoenix and instant kill Undead ennemies three by three, but the banal strategy using Rods appeared to be a bit faster. Finally, I would have loved to finish the game escaping from Tier 1 using Engulf, stop the timer at the fadeout just as we do in the speedrun of the game and loop back to Zone Eater's belly, getting again to Kefka's tower and loop back again and again during tier 1. Unfortunately, we have proved that it is not possible to do so. As for the softlock during the ending, don't forget that this does not rely directly on memory corruption, nor on the way the final fight ends (indeed, the ends goes normally -even if you corrupt memory- as long as there is no Wrong Warp). Since the usual rule is to stop the timer at the last input, i don't really see in which way this is an issue. I would advise people who still feel roughly offended about it to look through a window, wait for a plane to appear in the sky and turn their head around sometimes to get the real ending. If people still feel deeply betrayed, the submission can be withdrawn. This TAS thus owes a lot to Kilaye's tremendous work, and my feelings and mind are bounded to all those who accompanied us during this journey as much as they could, notably Simon, Brandy, MV and Synahel. L.L. PS: hopefully, the 'French TASers' will run new projects in the future.
Joined: 9/1/2014
Posts: 58
I understand it being a speedrun, but this is definitely the most underwhelming final boss fight it could have had, sure it is interesting to show it can be done and is a lot faster than actually fighting it, but the final boss and ending are the "payoff" for sitting through it, which sort of makes 3 hours have pretty much no payoff at the end with that fight and the broken ending sequence. Entertainment wise it already showed any battle could be ended with barbabreath so I would have been happy to have some "time sacrificed for entertainment" type thing on Kefka and showcase some other fighting stuff instead.
Enjoys speedruns but hasn't actually tried making any yet.
Samsara
She/They
Senior Judge, Site Admin, Expert player (2241)
Joined: 11/13/2006
Posts: 2823
Location: Northern California
...What's the point of removing one of the defining moments of the run just so people can watch Kefka getting killed for the millionth time? This way is far more entertaining than any other way would be.
TASvideos Admin and acting Senior Judge 💙 Currently unable to dedicate a lot of time to the site, taking care of family. Now infrequently posting on Bluesky
warmCabin wrote:
You shouldn't need a degree in computer science to get into this hobby.
Editor
Joined: 11/3/2013
Posts: 506
Ragnarokia wrote:
I understand it being a speedrun, but this is definitely the most underwhelming final boss fight it could have had, sure it is interesting to show it can be done and is a lot faster than actually fighting it, but the final boss and ending are the "payoff" for sitting through it, which sort of makes 3 hours have pretty much no payoff at the end with that fight and the broken ending sequence. Entertainment wise it already showed any battle could be ended with barbabreath so I would have been happy to have some "time sacrificed for entertainment" type thing on Kefka and showcase some other fighting stuff instead.
Credits are the payoff for beating a game yourself. They are not the payoff for watching somebody else's speedrun any more than the credits of a film are the payoff for watching the film. There's no sense of personal achievement in watching somebody else's work, as impressive as that work may be.
Personman
Other
Joined: 4/20/2008
Posts: 465
Kadmony: I really enjoy your florid English style :) Thanks for sharing the development story, it was a good read.
PS: hopefully, the 'French TASers' will run new projects in the future.
:D Can't wait!
A warb degombs the brangy. Your gitch zanks and leils the warb.
AntyMew
It/Its
Encoder, Player (35)
Joined: 10/22/2014
Posts: 425
thatguy wrote:
There's no sense of personal achievement in watching somebody else's work, as impressive as that work may be.
That's what being proud of someone is :P Though missing the climax and ending of the game is pretty annoying either way, at least after having so much text put into the story.
Just a Mew! 〜 It/She ΘΔ 〜
Editor, Expert player (2480)
Joined: 4/8/2005
Posts: 1573
Location: Gone for a year, just for varietyyyyyyyyy!!
The ending was unconventional and entertaining. Here, have a big yes-vote for an amazing TAS. It should already be common knowledge that there is no universal definition for a true ending of a game in a TAS context. This run here is a complete TAS with an ending that cannot be defined in any "pre-TAS era" or "pre-ACE era" conceptions of game endings. I saw the final boss being defeated in an unconventional way. I also saw unconventional credits. It would be absurd to claim that this magnificent piece of digital art is not complete. It is what it is. And it is good. It is very good indeed.
Editor, Player (69)
Joined: 1/18/2008
Posts: 663
keylie wrote:
When I said "arbitrary", I mean that the developers of BizHawk chose to put values in Save-RAM that are not all 0 but different values in different addresses.
If this is true, this is absurd and is a bug. Has anyone else verified this run?
true on twitch - lsnes windows builds 20230425 - the date this site is buried
keylie
He/Him
Editor, Emulator Coder, Expert player (2845)
Joined: 3/17/2013
Posts: 392
True wrote:
keylie wrote:
When I said "arbitrary", I mean that the developers of BizHawk chose to put values in Save-RAM that are not all 0 but different values in different addresses.
If this is true, this is absurd and is a bug.
Sorry, I made a mistake. What I said applies for WRAM only. For SRAM, values are all 0xFF by default. I think the WRAM initialization is in this file at line 131:
for(int i=0;i<128*1024;i++) wram[i] = random(config.cpu.wram_init_value);
Spikestuff
They/Them
Editor, Publisher, Expert player (2656)
Joined: 10/12/2011
Posts: 6449
Location: The land down under.
A Suggested Screenshot a YouTuber suggested:
UpliftingAstra wrote:
3:24:32 Should be the screenshot for the submission. Sums it up perfectly
Just another one besides the 3 that you provided.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.