This page documents the known esoteric tricks of Battle of Olympus. We concentrate here on tricks that are mainly usable in a TAS.

### Climbing on non-existing stairs

Stub. TODO: Expand this section.
Press up+down while descending/ascending stairs, and depending on situation, you might start climbing non-existing stairs.
When you reach the bottom or the top of the screen, depending on situation, you may make the screen scroll immediately to the left or the right, even repeatedly, by attempting to walk. This may enable immense shortcuts in the game.

### Super fast horizontal motion.

#### How velocity works

Note that climbing has different mechanics. This explanation only applies to walking and jumping.
"Velocity" here refers to a variable, found in the memory address \$0053, which tells how much will be added to the hero's X position at every frame. Negative values mean leftwards motion, and positive values mean rightwards motion.
The high 4 bits refer to fullpixel motion, low 4 bits refer to subpixel motion. 2^4 is 16, thus divide the velocity by 16 to get the motion speed in pixels per frame. Examples:
• Velocity of +16 means moving to the right at 1.0 pix/frame
• Velocity of −24 means moving to the left at 1.5 pix/frame (24 ∕ 16 = 1.5)
When the hero enters the view from somewhere, his velocity starts from either +16 or −16, depending on whether he moves to the right, or to the left, respectively.
When the player holds down the Left button:
``` If velocity ≥ 0, velocity decreases by 2. (Meaning that the hero accelerates towards the left)
If velocity = −24, nothing happens.
If velocity < 0 and ≠ −24, velocity decreases by 1.
```
When the player holds down the Right button:
``` If velocity ≤ 0, velocity increases by 2.
If velocity = 24, nothing happens.
If velocity > 0 and ≠ 24, velocity increases by 1.
```
When the player holds down both Left and right:
``` If velocity = 15, the velocity is set to 16.
If velocity = 16, nothing happens.
If velocity ≠ 15 or 16, velocity increases by 2.
```
When the player does not hold either Left or Right, or is holding Down:
``` If the player is jumping, the velocity is preserved. Otherwise:
The velocity increases or decreases by 1 towards zero.
```
However, when the player is fighting:
``` The Left and Right keys do not affect at all, except to change the hero's facing.
If the player is jumping, the velocity is preserved. Otherwise, it is set to 0 immediately.
```
The velocity is a 8-bit signed integer variable, meaning that increasing +127 by 1 yields −128, and decreasing −128 by 1 yields +127.

#### The fastest way to move to the right

Hold Left+Right, until the velocity is 16. Then hold only Right for 1 frame (to get the velocity into 17), and then hold Left+Right again, until the velocity is 127. Do not hold Right after that, or the velocity will wrap into −128 (Right) or −127 (Left+Right).
If you do not press any key, the velocity will start decreasing towards zero. To prevent the velocity from decreasing, jump. During the jump, the velocity is preserved. If you cannot jump, let the velocity decrease to +126, then press Right once to restore it into +127, and keep alternating it between +126 and +127.

#### The fastest way to move to the left

If you hold Left, the maximum velocity you can get is −24. To achieve further speed, you must use the wrapping trick. Increase your velocity towards the right until it reaches +126 or +127, then let it wrap by letting it increase by 1 (Right) or 2 (Left+Right). At that point, the hero will suddenly zoom to the left.
To prevent the velocity from falling (technically, increasing) from −128 to −127, use the same technique as with when going to the right: jump, or alternate.
Note that the velocity works the same way even when the hero is facing an obstacle, so you can achieve the zipping speed to the left even by walking towards a wall on the right side.

#### To halt immediately from any velocity

If you are standing on the ground, fight, and the velocity will drop to 0 immediately. You can then jump immediately if you want to continue moving slowly. If you are jumping, you can only slow down by changing the velocity into either direction with Left / Right / Left+right.

### Bypassing the red bush in the Peloponnesos forest without burning it

#### Super speed

Gain super speed and jump over the bush.

#### Damage

Jump towards the bush, and turn to the right, before the collision. When the hero gets damage, he will be pushed to the left if you did it right.

### Bypassing the barrier in Crete

#### Damage

Normally, the barrier in Crete will instantly kill Orpheus unless he possesses the second fragment of love. But, when Orpheus is damaged by one of the flying one-eyed monsters in the room, he briefly becomes invincible. The invincibility time is long enough for Orpheus to slip through the barrier. This trick allows Orpheus to obtain the third fragment of love out of sequence, but, unfortunately, the path to Tartarus will not open unless he leaves Crete with all three fragments of love.

0053Velocity
0063X-axis position
0052X-axis subpixel
0067Y-axis position
006DOlives counter
006CBay leaves counter

### Item drop formula

Item drop calculations for bay leaves and olives are based off the games global RNG. When a player enters a new screen, there are 2 counters, 006C is the counter for bay leaves, 006D is the counter for olives, these get reset to '75' upon entering a new screen. Before a drop is calculated, the game takes the sum of these two counters, subtracts 50 and if the result is greater than 50, this table is used:
OffsetItem%
0-25%
1Bay leaf25%
2-25%
3Olive25%
If the result of subtracting 50 is less than or equal to 50, this table is used:
OffsetItem%
0-12.5%
1Bay leaf12.5%
2-12.5%
3Olive12.5%
4-12.5%
5-12.5%
6-12.5%
7-12.5%
After the game determines the drop table to use, it rolls the RNG to select the specific drop. The RNG value is then AND'd against 3 (if the first table is used), or 7 (if the 2nd table was used). The result determines the drop (e.g., if the result was 3, an olive drops; if 1, a bay leaf; etc.).
However, there is one more check to perform before an item finally drops. The game once again checks the respective counters (olive/bay leaf) to see if the counter has reached zero. If it has, no item drops. This means that there is a limit of 75 bay leaves and 75 olives per screen. And both of them dropping can affect the % of drops that can occur within the screen.

### RNG

The RNG is a linear-feedback shift register with 32 bits of state and 2 taps.
\$D7DD:18 CLC
\$D7DE:A5 DA LDA \$00DA
\$D7E0:29 48 AND #\$48
\$D7E2:F0 06 BEQ \$D7EA
\$D7E4:C9 48 CMP #\$48
\$D7E6:18 CLC
\$D7E7:F0 01 BEQ \$D7EA
\$D7E9:38 SEC
\$D7EA:26 DC ROL \$00DC
\$D7EC:26 DD ROL \$00DD
\$D7EE:26 DA ROL \$00DA
\$D7F0:26 DB ROL \$00DB
\$D7F2:A5 DA LDA \$00DA
The memory locations \$00DA, \$00DB, \$00DC, and \$00DD hold the state of the shift register. When the RNG function is called, two bits from \$00DA (corresponding to the mask 0x48) are tested. If the bits are equal, a 0 bit is shifted into the state; if they are unequal, a 1 bit is shifted in. This is done by either clearing (`CLC`) or setting (`SEC`) the carry flag before starting the shift. The new bit is shifted into \$00DC, which then shifts into \$00DD, then \$00DA, and finally \$00DB. (Note the non-consecutive order of memory addresses.) Finally, the function returns the value of \$00DA. (Not \$00DB, as you might expect.)
``````\$00DB       \$00DA       \$00DD       \$00DC
xxxxxxxx <- xxxxxxxx <- xxxxxxxx <- xxxxxxxx <-.
|  |                              |
'--+------------------------------'
``````
In C, the RNG function would look like this (with one 32-bit `state` variable taking the place of four 8-bit state variables in the original):
``````static uint32_t state = 0x00aa00aa; // Initialized at \$C02E in the ROM.
uint8_t rng(void)
{
// If both tap bits are 0 or both are 1, shift in a 0 bit.
// Otherwise, shift in a 1 bit.
uint32_t carry;
if ((state & 0x00480000) == 0x00000000 || (state & 0x00480000) == 0x00480000)
carry = 0;
else
carry = 1;
state = (state << 1) | carry;
// Return the second-to-last byte in the state, not the last byte.
return (uint8_t) (state >> 16);
}
``````
An odd feature is that the return value is the second-to-last byte in the register (\$00DA), not the last byte (\$00DB). Even though there are 32 bits of state variables, only 24 bits are really used. The only effect \$00DB could possibly have is affecting the CPU's carry flag; otherwise the function would return the same sequence of values if that part of the state were removed.
Despite having 32 (or 24) bits of state, the choice of taps leads to a period of only 32,767.

GameResources/NES/BattleOfOlympus last edited by Sand on 10/11/2023 7:10 PM