Using file names on the title screen, along with a specific glitch, we encode code written in the save files using the Japanese text. The American version of the game does not contain the values to make this glitch possible, so the Japanese version (besides being preferable anyways due to shorter text) must be used.
There is a more detailed explanation below.
Note, there is a counter within the game that counts up in hexadecimal by 1, about every second. This glitch only works on certain values. My TAS was optimized without bearing this in mind, meaning the goal was to reach the chest fastest regardless of wait time/available stalling, as I wanted a fast result to the chest rather than utilizing this wait time to be slow. I land on value 6A, and wait until 6D, which is literally the best value to land on, as the previous value 64 is impossible to reach under the current circumstances, let alone any of the prior values.
Addresses on which my ACE will work (I end up on 6A and wait until 6D, giving us a nice margin for error without possible improvement of the TAS):
More detailed explanation written by a LADXRTA runner:
= Filenames =
In LADX, there are 3 possible files the player can use with each one allowing for 5 characters to create a name. This gives a total of 15
characters which can be used for arbitrary code execution. Each character used has a specific value associated with it, so the game knows
what characters consistute a filename. This is why the glitch does not work on the English versions of the game, as the associated values
you need for ACE are not all present in the English character set. The Japanese version has 75 characters to choose from, not including
the value for the blank space. The English version only has 52. The numerical values for the filenames are as follows:
1: 39 11 29 18 2C 2: 09 3E 01 32 32 3: 3E 3C 2F 32 32
These are all typeable in the Japanese version, but the English version only allows for lower and uppercase alpha characters. When
the values are manually entered onto the English version (via hacking), they read:
1. 8A(A* 2. AAA11 3. A;.11
- the value here is not alphanumeric, and I can't show it to you.
= Ingame Counter =
At the memory address FB47, a counter increments from 00 by 01 every second. It eventually reaches FF and stops. This counter is vital
to the success of ACE. Certain values will not work, regardless of the prior setup.
= The Chest =
Upon opening the chest in the Doghouse, the return address F4FF is called to retrieve the value for whatever should happen when the chest
opens. This isn't where it should check however, and the game then executes all instructions in order starting from F4FF. Eventually, the game
reaches the value FB47. Depending on what value from 00 to FF that is, the game will either harmlessly execute an instruction or crash. This is why
ACE seems inconsistent, however in reality is perfectly consistent assuming you always get a harmless value. After FB47, the game progresses to FB4E.
= ACE: Setting up the value=
ECH1:FB4E 01 39 11 ld bc,1139 <= loads 1139 into BC ECH1:FB51 29 add hl,hl <= adds HL to HL ECH1:FB52 18 2C jr FB80 <= jumps to FB80
Let's break this down, line by line.
ECH1:FB4E 01 39 11 ld bc,1139
This loads the value of 1139 into the register BC. Memory address FB4E correlates to Link's sword level, which is 01 when you first obtain the sword.
01 is the opcode for loading in the GB system, so it prepares a load instruction. The next values, are the first 2 values of filename 1. But why are they
here? When starting a game, the name of save 1 (39 11 29 18 2C) is copied to FB4F from FB80, as we can see here. This only happens on save 1, which
explains why ACE only works on the first file.
ECH1:FB51 29 add hl,hl
This instruction, "add hl,hl" adds the HL register to itself, doubling it. This will be relevant later
ECH1:FB52 18 2C jr FB80
This instruction "jr FB80" jumps the game to memory address FB80, where the first filename was copied from. This means the first file is executed
twice in ACE, however the values are shifted slightly as the value for Link's sword is no longer present. Here is the game now:
ECH1:FB80 39 add hl,sp <= adds the register SP to HL ECH1:FB81 11 29 18 ld de,1829 <=loads 1829 into DE ECH1:FB84 2C inc l <= increments register L by 1 ECH1:FB85 09 add hl,bc <= adds BC to HL.
Again, let's make this easier and break it down.
ECH1:FB80 39 add hl,sp
This adds the register SP to HL, which is all to prepare HL at the end.
ECH1:FB81 11 29 18 ld de,1829
This line is largely ignored, as it is only used to setup the copied version of the file 1. This line loads 1829 into the register DE.
ECH1:FB84 2C inc l
This line INCrements the register "L" by 1.
ECH1:FB85 09 add hl,bc
Finally, we add BC to HL. The register now has a value of FB96, which is the byte where the end cutscene is stored. All this section was dedicated
to changing the value of one register.
= ACE: Writing bytes =
Before, we only used values from the first file and the first character of file 2. Now, we are going to be using the files from every file.
ECH1:FB86 3E 01 ld a,01 <= load 01 into register A ECH1:FB88 32 ldd (hl),a <= load A into HL, decrement H1 by A ECH1:FB89 32 ldd (hl),a <= load A into HL, decrement H1 by A ECH1:FB8A 3E 3C ld a,3C <= loads 3C into register A ECH1:FB8C 2F cpl <= flips the bits of A, turning the value of 3C into C3 ECH1:FB8D 32 ldd (hl),a <= loads the value of register A into register HL, decrement HL by 1 ECH1:FB8E 32 ldd (hl),a <= loads the value of register A into register HL, decrement HL by 1 ECH1:FB93 C3 C3 01 jp 01c3 <= jumps to 01c3, returning us to the main loop
To make this infinitely more easy to understand, we'll again break it down. Our goal here is to modify the bytes of FB95 and FB96.
FB95 is the address of which cutscene, and FB96 is what part of the cutscene. We want to play cutscene 01, part 01
ECH1:FB86 3E 01 ld a,01
This loads the value of 01 into the register A, this will help us to change the value of the bytes.
ECH1:FB88 32 ldd (hl),a ECH1:FB89 32 ldd (hl),a
This line is repeated twice. ldd is the LoaD Decrease instruction. This line loads A (01) into HL (FB96), then HL is decremented by A, so 01.
FB96 now has a value of 01. This is repeated, so FB96 is decremented by 01, and now both FB95 and FB96 have the values of 01. We are ready to
warp to the credits. However, there is a slight issue. Currently, we are not in the main loop of the game, so none of this will occur until we do this.
ECH1:FB8A 3E 3C ld a,3C
This line loads the value of 3C into the register A. The instruction to jump to another address (jp) is C3. We need to execute an instruction with that
value. Luckily, the next line sorts this out for us.
ECH1:FB8C 2F cpl
This instruction, ComPLement, flips the bits of the register A. It flips the bits of A, so it flips 3C, which happens to equal C3. Now A is C3
ECH1:FB8D 32 ldd (hl),a ECH1:FB8E 32 ldd (hl),a
Another double line. We load A into HL, and decrement HL by 1. This means FB94 contains the value C3, this repeats and FB93 contains another
C3.
ECH1:FB93 C3 C3 01 jp 01c3
Now, the game contains exactly what we need. The value of C3 correlates to a jump instruction, which will return us to the main loop. We needed
to set the second C3 as otherwise we would have returned to 0101, which is not in the main loop. We jump to 01C3 and the game warps us to the credits.
CasualPokePlayer: Replaced movie with one with the correct cycle count; corrected branch label ("Arbitrary Code Execution" -> "game end glitch")
ThunderAxe31: Claiming for judging.
OtakuTAS: Adjusted game name to match other publications.
ThunderAxe31: Un-claiming.
CasualPokePlayer: Claiming for judging.
CasualPokePlayer: Rejecting as the author has been banned.