The area of Mist is covered in a fog effect, which to this day feels impressive for an NES game.
The implementation of the effect is actually quite simple, and is composed of the following:
1. **Multiple types of fog tiles.**
These aren't part of an animation, but rather are different shading or configurations of the fog "particles" (the pixels making up the fog).
2. **Foreground placement.**
The tiles are placed in the foreground, appearing to overlap the player, enemies, and blocks.
3. **Fog generator.**
The Fog Generator is a block of code that computes some state (a fog state index and a fog tile index). The fog tile index ultimately maps to the lower byte of an address for a fog tile.
3. **Fog tile updates/animation.**
The fog tile index's computed lower byte of an address is paired with an upper byte (hard-coded as `$18`). This becomes a fog tile address.
This is then referenced by scheduling a [[PPU Buffer]] draw command: Rotate Sprite Right. This command takes a tile and shifts all pixels to the right one, creating the effect of fog moving to the right.
Through this simple effect, and good placement of different static and animating-capable fog tiles in the foreground and in the background, the game can create a really effective fog atmosphere.
# Addresses
Fog generation uses the following addresses in memory:
| Address | Name | Comment |
| ------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| $001D | Fog tile index (0..7) | Incremented by 2 every drawing tick.<br><br>Decremented by 1 every non-drawing tick.<br><br>When wrapped up to 0 during drawing, a new value will be computed based on a lookup table.<br><br>The value is multiplied by 16 (tile data size) to get a lower byte of the tile address. |
| $001E | Fog state index | When odd, fog animation occurs.<br><br>When even, the fog generator decrements until it hits 0, and then the fog index is incremented. |
Functions include:
| Address | Purpose |
| ------- | ---------------------------------------------------------- |
| $DFC5 | On-tick fog calculations and draw scheduling. |
| $DFDE | Fog drawing (schedules the rotate-right PPU draw command). |
# Algorithm
```c
static char fogTileIndex = 0;
static char fogStateIndex = 0;
static char FOG_START_TILE_INDEXES = [
0x18,
0x06,
0x30,
0x0C,
];
void onTick() {
/* Limit this to the Mist area, which has the tiles to animate. */
if (!inMist) {
return;
}
if ((fogStateIndex & 1) == 0) {
/* On odd indexes, rotate a fog tile right. */
updateFogTiles();
} else {
/* On even indexes, decrement the fog generator. */
fogTileIndex--;
if (fogTileIndex == 0) {
/* If that hits 0, increment the fog index. */
fogStateIndex++;
}
}
}
void updateFogTiles() {
rotateTileRight(
0x18, // Upper byte for address
fogGenerator * 16); // Lower byte for address
/* Increment the fog generator by 2, but cap from values 0..7. */
fogTileIndex = (fogTileIndex + 2) & 7;
if (fogTileIndex == 0) {
/* The fog generator wrapped. Increment the lookup index. */
fogStateIndex++;
/* Calculate new start position based on the index. */
fogTileIndex = FOG_START_TILE_INDEXES[(fogStateIndex / 2) & 3];
}
}
```