Some Overworld Rocks Are Chests

No. Really. Some rocks on the overworld do, in fact, behave like chests. The caveat is that they only behave like chests for the hammer and guard search probes. What is going on?

Overworld collision

First, we need to understand how underworld collision works. In the underworld, one room is loaded at a time and its tilemap exists in its entirety in memory at $7E2000 through to $7E5FFF. Each tile is a 16-bit word with a 10-bit tile name that dictates its graphics. That 10-bit tile name is used to look up a tile type in a dynamic table stored in WRAM at $7EFE00 and then stored in a collision map held in memory at $7F2000 through to $7F3FFF.

The underworld's tilemap and collision loading is simple, because only two 64-by-64 maps are loaded at a time—the upper and lower layers. That works out to 4096 tiles—$1000 in hexadecimal—the exact size of each collision map buffer.

The overworld, however, loads 8 times as many tiles! The smaller overworld screens are already 64-by-64, and four of those are loaded at once, even when loading a small screen. To fit more information into the same amount of space, some form of compression is required.

Instead of storing tilemaps directly, overworld screens are built with metatiles of 2-by-2 tiles which we will call "map16 objects". On the overworld, the memory at $7E2000 is repurposed to hold 8128 of these objects. There are 3744 defined map16 objects stored in a table at $0F8000. Each entry consists of four 16-bit words which constitute the tilemap value of each of the tiles within the map16 object. This table is referenced whenever the overworld needs drawing or updating, or whenever Link, or a sprite, or whatever needs to handle collision.

So which of these definitions works as a chest?

None of them.

Another table

While it is true that the vast majority of things look deeper into a map16 object to obtain the tile or tiles it needs, there are exceptions to this:

Any interaction that manipulates the overworld, such as cutting bushes or grass, hammering a peg, or bonking a pile of rocks, has a map16 object ID hardcoded into the test logic. For example, the code below is how the shovel checks for diggability:

1BBDF4
CMP.w #$0034
; Grass
1BBDF7
BEQ .diggable
1BBDF9
CMP.w #$0071
; Grass with tufts ▀
1BBDFC
BEQ .diggable
1BBDFE
CMP.w #$0035
; Grass with tufts ▄
1BBE01
BEQ .diggable
1BBE03
CMP.w #$010D
; Grass with tufts ▟
1BBE06
BEQ .diggable
1BBE08
CMP.w #$010F
; Grass with tufts ▙
1BBE0B
BEQ .diggable
1BBE0D
CMP.w #$00E1
; Grass with tufts ▞ and flowers ▚
1BBE10
BEQ .diggable
1BBE12
CMP.w #$00E2
; Grass with tufts ▄ and flower ▘
1BBE15
BEQ .diggable
1BBE17
CMP.w #$00DA
; Grass with tufts █
1BBE1A
BEQ .diggable
1BBE1C
CMP.w #$00F8
; Grass with tufts ▜
1BBE1F
BEQ .diggable
1BBE21
CMP.w #$010E
; Grass with tufts ▛
1BBE24
BEQ .diggable

The other exception—and this is the oddball—is the routine ReadOverworldTileType, which uses the gigantic OverworldTileTypeTable at $1BF110. This table contains a single byte for every map16 object that dictates a behavior for the entire metatile.

Shooting sparrows with a cannon

First off, why do the manipulability checks not use this table? Bushes, rocks, and diggable ground, and actually every interaction that has a hardcoded check already has an existing tile interaction type. Except doors, but those could easily be given one! This could have been much cleaner and more expandable.

Next, why does this table exist? It is only used by two things: the hammer for spawning a splash, and search probes for detecting collision. This table embodies an extremely odd and heavy hitting solution to these problems. Search probes could use the existing overworld tile checks that every other sprite uses. They already use the same routines as everything else for underworld tiles. Why are they different here? As for the hammer, it'd be slightly less efficient, but there's no reason it can't just check 4 tiles at once for being water. Why does it need to check map16 objects specifically?

It wasn't a rock...

Map16 ID Image
$02BA
$02C0
$02F8
$02FA
$0309
$0310
$0502
$069E
$0D0E
$0D17
$0D21

For some reason, inside OverworldTileTypeTable, there are 11 map16 objects that are given the value of $5C, which corresponds to chest #4. Hammers then test this value for equality to $08 (deep water) and $09 (shallow water), and search probes use it to index a table at $0DB971, which in turn gives the value $00. Really, that value should be $01 for collision, or $02 for short collision, if we're being generous.

So, unfortunately, we can't actually open any chest rocks in the overworld, because they're never considered a chest in that context. But they really are considered chests by the hammer. It just means nothing; they might as well be a wall.

Why is the table like this? I have no clue. I'm not even going to try to guess. I also don't know if there are any other oddities. No other blatantly nonsense values exist in the table, but it could very well be the case that a handful of IDs are associated with something contradicting their graphics. There are just too many to check for me to care.

Haters will say this is AI.

The culprits

So what if you wanna hit your own chest rock? Well you can! I have gone ahead and annotated the chest rocks on every screen they appear. Enjoy!