Submission Text Full Submission Page
Bad Apple, for Tsuri Sensei.
As mentioned in my Any% submission, this game has ACE potential, but I initially dismissed it as being too slow to be useful for Any%.
However, that doesn't mean it can't be used to Bad Apple. After a ton of experimentation, I finally found a suitable ACE setup, which ended up being fast enough where it could beat Any% (a game end glitch submission will happen sometime later).

The Script Stack Overflow Glitch

This ACE exploit relies on a developer mistake. The game implements a scripting system, which appears to manage all of the game logic, from menus, to fishing, to even the credits. This scripting system has its own script stack. Somehow, the developers screwed up and did not properly pop this stack upon exiting the map screen, only when exiting the status menu is the script stack reset. This eventually just leads to a classic stack overflow within this script stack, which usually happens to cause execution to jump to the script stack itself at $D8BE.
This itself isn't particularly useful. The nearest controllable memory is a bit after the script stack at $D915, which is just a few bytes that changes depending on the last text printed. Generally, this just ends up hitting a reti (a byte that usually doesn't change), which proceeds to advance the script engine and execute more garbage script data, eventually reaching to $F00B. This leads to fairly static uncontrollable data which ends in a stop opcode, freezing the game. For a few NPC textboxes, the reti can be bypassed (either by it changing to some other byte or being eaten by a multi-byte opcode), but doing such just ends up also leading to a crash in the later bytes, not to mention SRAM ends up getting locked, preventing more useful data to be executed.
A saving grace comes in with various NPCs (well, mostly wild animals) which after talking to them, move out of the way. These plaster some bytes after the script stack for some reason, starting at $D8E0. The main prize in these bytes is it has a jr $xx opcode. What $xx is depends on the direction which the NPC was spoken to. For most directions, this is some number >=$80, i.e. negative, as such just creating an infinite loop. However, when speaking from below, $7A is used, leading to a forward jump to $D95F.
$D95F is in a middle of some giant buffer that changes depending on the last text. I assume it's some buffer storing text itself. Even better, the buffer isn't explicitly cleared out with new text data, instead it's simply overwritten until the new text data has been written. This can lead to a mixmatching of different text data to create some kind of payload, at least one which can redirect execution.
This payload ends up being created with only 2 NPCs. Some shop clerk is asked for advice(?), which is random. One specific advice is wanted in this case, so some delay is needed to get such. Next some fishing instructor(?) person is talked to, with No selected for getting info on how to fish(?). This ends up creating a payload with these vital instructions (with a bunch of other relatively harmless instructions surrounding such):
push af
inc sp
ret nz
These end up by sheer chance redirecting execution to $A158. This is extremely useful, as SRAM is where file names are stored, and it's normally unlocked (although the ACE exploit here has a tendency to lock SRAM due to the somewhat randomness of the instructions executed, the NPCs choosen happen to make instructions that do not do this). These file names give quite a few bytes to work with, under these ranges:
$01-$0E
$10-$1E
$20-$2E
$30-$3E
$40-$4E
$C0-$C5
$E9
$FF
This isn't many opcodes to choose from, and each name only has 4 bytes to choose from. Worse, getting to the next name will cause some other relatively uncontrollable bytes to be executed. Right after every name is $FF, corresponding to rst $38. This is fairly harmless in this game (as the rst vector is implemented with an actual function), but has the effect of increasing HL by A * 2. The limited number of bytes given here mean the only way the payload can loop is using jp hl (with $E9), as such HL needs to stay constant.
All of the other uncontrollable bytes are relatively harmless. By sheer chance, they end up being quite useful however. The opcodes end up setting D to whatever H is, and leave E alone. HL is also left alone here.
This leads to setting HL within the first name executed, in order to become the loop point. HL here would be after the first name executed and before the second name executed, and would remain constant with the second and third names being executed. As such, the first name is:
ld h,$28
add hl,hl
add hl,hl
$26 $28 $29 $29
The second name executed ends up just being a simple call to the game's joypad routine at $0625. Due to the $FF byte after the name, the fourth character of the name has to be one which eats that byte (in this case, ld b,xx, as it's $06, the same last byte in $0625 in little endian order). As such, the second name is:
call nz,$0625
ld b,$FF
$C4 $25 $06 $06
The third name executed can now simply write A to [DE] and increment E. After such, the code can loop with a jp hl. As such, the third name is:
ld [de],a
inc e
jp hl
$12 $1C $E9
Either an E or DE increment technically works here, in any case D is set to H anyways. As such, eventually the pointer loops backwards to the beginning of the 256 byte chunk, allowing the next payload be written without it being executed. Once the next payload is finished, a backwards jr can be written to jump to the next payload.
A minor issue here however is that the joypad function returns the newly pressed buttons in the A register, not the currently pressed buttons. Due to this, the first few bytes written are ones which clear the game's joypad state variable in $FF91. This luckily can be done while abiding by the newly pressed buttons limitation, using the following opcodes:
ld c,$91
nop
xor a
nop
ldh [c],a
$0E $91 $00 $AF $00 $E2
The next payload is a small payload which writes in the final payload as fast as it can. That next payload along with the final payload main payload is (mostly) the as ones in Red, with minor adjustments to deal with game specific details: https://tasvideos.org/9604S
Another minor detail to note is the save file name order isn't as you'd immediately expect. What gets executed first is the "active" save file, then the first save file, then the second save file, then finally the third save file. As such, the third save file is used for the run in order to make it the "active" save file, and ends up having the first name executed.
Actual movie is too big, what's submitted is a truncated movie, full movie can be found here: https://mega.nz/file/osdBhLBJ#_-TUWCHeQxLN8ZFPNUY3FD3QEDNeybT0KdJ7u5YMojI


TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 16286
Location: 127.0.0.1
Spikestuff
They/Them
Editor, Expert player (3002)
Joined: 10/12/2011
Posts: 6539
Location: The land down under.
Spikestuff wrote:
Honestly. Yeah it should start being distinguished that this is just "injecting Bad Apple!! into everything", since this is now the fifth TAS. I'll put a vote for "arbitrary code execution, Bad Apple!!", but also coming from me of all people this is just turning into "abuse, and boot into video". There's a lack of style and flare going on compared to what MrWint did 8 years ago (and the obsoleted movies), to what Masterjun did 10 years ago, to what Lord_Tom did 9 years ago, and what the original one that started the Bad Apple!! trend with what OnehundredthCoin did. I'm personally going to start voting Meh, and it'll probably start devolving into No votes from me if this "lack of substance" and flare continues.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
Former player
Joined: 6/30/2010
Posts: 1119
Location: Zurich, Switzerland
When I already know the answer of what the payload for the ACE is going to be, I'm watching these TASes purely with the mindset of wondering how the ACE is pulled off. This one was very short and the gameplay did not look particularly broken to someone like me that has never heard of this game. That was probably the most interesting aspect of this TAS for me, the fact that we didn't get to see these glitched textures and distorted sounds, just a seemingly smooth transition to the payload. But ultimately, it was still repetitive and I had no idea what was even happening, so a I can't give this more than a "meh".
Current project: Gex 3 any% Paused: Gex 64 any% There are no N64 emulators. Just SM64 emulators with hacky support for all the other games.
Glitcher
He/Him
Joined: 3/24/2007
Posts: 217
Location: London, U.K.
Bad Apple again? I'm bored already. Props for cracking the code, but I'm tired of players using Bad Apple over and over for an ACE run. Considering the category allows for virtually anything you can code into the game like the brilliant Pokémon Yellow ACE run, it baffles me that there's nothing more creative you can do with this besides repeating an overused music animation. Yawn.
reubensoda82
He/Him
Joined: 5/5/2025
Posts: 11
Location: Nebraska
Glitcher wrote:
Bad Apple again? I'm bored already. Props for cracking the code, but I'm tired of players using Bad Apple over and over for an ACE run. Considering the category allows for virtually anything you can code into the game like the brilliant Pokémon Yellow ACE run, it baffles me that there's nothing more creative you can do with this besides repeating an overused music animation. Yawn.
My thoughts exactly; that's a no vote from me.

1750768138