Movement and Acceleration
Whenever the Faxanadude starts moving, his speed is set to 192 subpixels per frame (spx/f) and incremented by 2spx/f to a maximum of 384spx/f. As long as the Faxanadude continues moving in a horizontal direction without missing a frame, acceleration continues. Turning around, as long as there is no intermediate non-walking frame, does not kill your acceleration. Jumping without Wing Boots being active also affords acceleration. For jumping with Wing Boots to provide acceleration, L or R must be pressed at each frame of the jump.
Movement is registered two frames before enemies appear on screen, and two frames before the Faxanadude lands from a jump without Wing Boots being active.
Speed is immediately set to the minimum value of 192spx/f if:
- Faxanadude starts climbing a ladder (and sometimes even if he misses).
- Faxanadude flies up or down with Wing Boots active.
- Faxanadude's Weapon connects with an enemy.
- The player presses B for any reason while Wing Boots are active.
- Faxanadude collides with an enemy (see Damage Boosting, below).
- Faxanadude stops moving for one frame.
- Faxanadude changes game areas (from Trunk to Mist, Mist to Trunk, Mist to Branch, or Branch to Mist).
Pressing B causes the Faxanadude to enter his attack animation. Nine frames later, the weapon is minimally extended and can deal damage. A few frames later, the weapon is maximally extended and can deal damage. On the final frame of attacking (where advancing the game causes the uppermost bit of the Player Behaviours to be set to 0), movement is again able to be registered, but it is also possible to activate items (DB) or throw Magic (UB) without starting a new attack. On the frame immediately following, it is impossible to start a new attack. On the frame following that, a new attack can be started.
Skipping the introduction
The introductory text crawl is actually a trigger that is one block wide and two blocks high, located at (48, 112) - (64, 144). As a result, it can be jumped over, saving 12.5 seconds with an optimized jump. This is demonstrated here
Many enemies in the game do not pay attention to RNG, and will simply move toward the player following a pre-defined path. This causes some enemies to jump at the Faxanadude, some to jump over the Faxanadude, and some to waddle slowly toward the Faxanadude.
Ladders as Platforms
The Wing Boots drastically change the way the game is played. While active, you can grab a ladder for one frame while moving horizontally (URA, ULA), release jump and up (R, L), and then jump (A) to quickly ascend. This is demonstrated here
The Wing Boots, Gloves, Ointment, and Hourglass all have set durations based on the Faxanadude's title, and these durations decrease as the Faxanadude's title advances. At Aspirant (the title earned at 1000 experience), the Wing Boots, Ointment, and Gloves (and probably Hourglass too) are set to last for 30 seconds. Each of these timers decrement when the frame counter, modulo 64, is equal to 63. The pause frame does register other input, the unpause frame does not, so a typical pause pattern might look like: URSA, --, S, URA to continue flying to the right.
Jumping Down Ladders
Lord Tom discovered a way to partially jump down a ladder. To make this work, you need at least a one-pixel ceiling above the Faxanadude. Then jump (toward the ladder you wish to fall through). Done correctly, you will notice that falling acceleration is applied to the Faxanadude even though rising acceleration was not, and on the last frame of acceleration, the Faxanadude will fall eight pixels further into the floor.
Enemies will push the Faxanadude in the direction they are facing when they hit the Faxanadude (or, when the Faxanadude hits them). The Faxanadude is shoved away at a rate of eight pixels per frame for three frames, and is given sixty frames of invincibility. These sixty frames cannot be extended through pausing. By hitting an enemy with a Weapon or a Magic on the same frame as the enemy collides with the Faxanadude, the enemy will be turned in the direction it was hit and Faxanadude will be sent in that direction as well. As with all other methods of stopping, the Faxanadude's movement speed will be reduced to its lowest value, 192 spx/f.
Useful Memory Addresses
|0x001A||Frame counter||Unsigned. Counts from 0 to 255, but when this number, modulo 64, is 63, timers are decremented.|
|0x009D||Player's X Subpixel|| |
|0x009E||Player's X Coordinate|| |
|0x00A1||Player's Y Coordinate|| |
|0x00A4||Player Behaviours||A bitmask containing useful information. The uppermost bit (bit 8) indicates that the Faxanadude is attacking. Bit 3 indicates that the Faxanadude in in front of a ladder. Bit 1 indicates that the Faxandude is jumping.|
|0x00A9||Player's Speed||16-bit little endian value. The first frame of new movement sets it to 192 and increments it to 194, and its maximum value is 384.|
|0x00AD||Player's Invulnerability Timer||Set to 60 whenever collision with an enemy occurs.|
|0x0431||Player's Full Health||How much health the Faxanadude has. Maximum is 80.|
|0x0432||Player's Fractional Health||This is stored but I don't know that it is actually used. Maybe if the Faxanadude has armour?|
|0x043A||Four-Item Counter||Counts up by one every time the Faxanadude enters a room with a hidden item, cycling back from 3 to 0. At 0x00A4 == 0, a hidden item will spawn when all enemies are killed.|
|0x039A||Player's Magic||How much magic the Faxanadude has.|
|0x00D7||Spring Rock Counter||Counts the number of sequential frames that the rock above the Spring has been pushed. At 96, the rock is pushed aside.|
|0x00DA||RNG Offset||Used to index into the ROM table at 0x8000 to give the actual RNG bits, incremented every time an enemy needs an RNG value and ignored otherwise.|
|0x0427||Ointment Counter||Can be extended by pausing around framecount % 64 == 63|
|0x0428||Glove Counter||Can be extended by pausing around framecount % 64 == 63|
|0x0429||Wing Boots Counter||Can be extended by pausing around framecount % 64 == 63|
|0x034B||Enemy 8's Health||Enemies do not die until their hit points are reduced below 0. Use 0x034A for enemy 7, and so on until enemy 1.|
|0x036B||Enemy 8's Phase Duration||The phase duration, phase counter, and phase timer variables dictate enemy movement and behaviours.|
|0x02EB||Enemy 8's Phase Counter||Those behaviours are defined on a per-enemy basis, but knowing when an enemy is about to decide to|
|0x02F3||Enemy 8's Phase Timer||do something new is helpful for your own decision making. 0x036A, 0x02EA, 0x2F2 are the values for enemy 7.|
|0x0343||Enemy 8's Magic Invincibility Timer||This is set to 4 whenever enemy 8 is hit by Deluge (and probably other Magic). 0x0342 for enemy 7.|
|0x0353||Enemy 8's Weapon Invincibility Timer||This is set to 8 whenever enemy 8 is hit by the Dagger (and probably other Weapons). 0x0352 for enemy 7.|
|0x02CC||Enemy 1's Sprite Number||Useful for looking into the SpriteSize table, which then is used for looking into the SpriteWidth and SpriteHeight tables. 02CD for enemy 2.|
|0xB4DF||The Sprite Sizes Table||0xB4DF + (the value in (0x02CC + enemy number - 1) ) = the memory address containing the offset into the SpriteWidth and SpriteHeight tables.|
|0xB4D1||The Sprite Widths Table||0xB4D1 + (the value in (0xB4DF + (the value in (0x02CC + enemy number - 1) ) ) )= the number of pixels wide that the sprite at enemy number is.|
|0xB4D8||The Sprite Heights Table||0xB4D8 + (the value in (0xB4DF + (the value in (0x02CC + enemy number - 1) ) ) ) = the number of pixels tall that the sprite at enemy number is.|