dtgreene: You may notice that that TAS encode includes a dump of part of RAM on the right side. If you skip to the point (about 6 minutes into the run) and look at the right side, you will notice that data (namely the information on where the Warp spell will send the player) starts filling up more and more of RAM until, during the fight, some other data gets overwritten.
rtcvb32: Watching it, it appears there it's missing the cleanup code that's usually present...
Let's see if i can explain. When you write functions you generally do the following
[code]
FunctionName:
Push Registers //onto stack
do work
Pop Registers //off stack
return
[/code]
which is fine, although it's possible a function doesn't clean/free up the stack properly. Then there's also calling the function, in C you push the variables onto the stack, so if we pushed Hello World, it would be:
[code]
push hellostring //pushes (char*) pointer
Call Print
add sp, sizeof(char *) //remove string pointer, if we wanted to preserve it we'd pop it instead.
hellostring: db "Hello World", 0
[/code]
So in the FF2 TAS, the add/pop used after calling the function to change the screen never got cleaned, lowering the stack/data until it's right where he wanted it.
I think the reason the cleanup code isn't there is that the game has to implement the Warp spell. Warp, when cast outside of combat, teleports you back a number of floors equal to the spell's level. As a result, the game has to remember every floor you have been on since you entered the dungeon, and it seems the game uses the stack to store that information.
In C, one can actually store a linked list on the stack, using code like the following:
void liststack(Node *node)
{
Node new;
new.next = node;
if (some_condition)
liststack(&new);
else
work_with_list(&new);
}
Note that the function does not actually return the pointer to the list. Instead, the list is sent to another function once constructed, and once the function returns, the linked list will be deallocated due to it being stored entirely in local variables. Also, note that the local variable is an actual Node, not a pointer to one. (Notice no malloc here.)
(This will work in C++, provided you change the name of the variable "new".)
The Chicken Scheme compiler actually does something like this; here is an article if you're interested:
http://www.more-magic.net/posts/internals-gc.html Incidentally, looking at the memory during the stairs portion of the TAS, I notice a pattern: 3A F2 CA 81 15 3A F2 CA 84 15, and then it repeats.