Houlihan

As a change of pace from glitch explication, I want to dissect something that is not a glitch, but it's something everyone immediately labels as one. But it's not a glitch, nor is it necessarily the result of one. There are ways to use glitches to trigger the Houlihan warp, but that just means the code is doing its job. Instead, the Houlihan is an easter egg that's been built in as a failsafe, and it's one of the few general failsafes to exist.

Misconceptions

To start, I'd like to clear up the second biggest misconception, which is that triggering Houlihan is the result of a messed up camera. That's not exactly really true. The camera matters, but only indirectly. What really matters is your X-coordinate, Y-coordinate, and screen ID.

Screen ID

This is the easiest to explain. It's your screen's… ID… Basically "which screen are you on?" Except instead of saying "Oh, I'm in Kakariko.", it's the CPU reading address $8A and saying "Oh, you're on screen $0018."

Coordinates

Your coordinates together are used to calculate a location in Map16 (which, to keep it brief, is how overworld tiles are stored to keep them, their graphics, and their behaviors "easy" to control). This location is then used in part of the search for where the hole goes.

X-coordinate

This may sound silly, but your X-coordinate is easier to explain than your Y-coordinate. Why? Well, it's taken as what it is when you fall into the hole.

Y-coordinate

Your Y-coordinate is a little trickier. When you fall into a hole, your Y-coordinate is modified to be placed above the screen. Here's exactly how the routine goes, starting from when we're finally ready to warp:

  1. Reset ability to dash (I guess that routine has some stuff they needed…?)
  2. Set Link's falling status, turn Link invisible, and set his speed modifier to "fast".
  3. Subtract the V-scroll of the BG2 camera from Link's Y-coordinate and store it in scratch space.
  4. See if we're indoors or outdoors.

Hey! We're outdoors! Let's follow that branch!

  1. Do stuff that's exclusive to the underworld, because having a branches merged makes some sense, but saving every possible byte by using the same exact branch is important to save space. I could have done this a whole lot better.
  2. Take our coordinate-camera difference from earlier and add 16 to it, then put that new value in scratch space.
  3. Take Link's Y-coordinate and subtract from it the value from the previous step. Store that as the new Y-coordinate.
  4. See if we're indoors (we're not).
  5. See if we're on the broken bridge screen on Death Mountain (we're probably not).
  6. Call the routine Overworld_Hole.

So ya, the routine tries to put Link at the top of the screen for later stuff. Some of you may be screaming, "SO THEN IT'S THE CAMERA!", but it's not that direct. The vertical scroll of the camera matters only because it determines your Y-coordinate. The horizontal scroll of the camera is completely irrelevant.

Another subtlety that should be pointed out is that you may sometimes notice the camera jerk upwards after you've fallen into a hole. This happens after the Y-coordinate recalculation, so that's irrelevant as well.

The meat

Now that we know the variables used and how they're determined, let's take a look at the actual routine that finds our destination, Overworld_Hole:

  1. Do a bunch of garbage to our X- and Y- coordinates to find the map16 tile that Link is on (full details below).
  2. Do this loop 19 times:
    1. Compare Link's map16 coordinate to the value in the table.
    2. If it doesn't match, skip to next hole.
    3. Check the screen ID. If it matches, use that index for the hole.

    If the loop reaches -1, set the pit index to 19 (remember: 0-index), and put Link in the Light World.

  3. Use the index to set the entrance and exit the subroutine.

100% intended

So what exactly makes this not a glitch? A glitch is something that is not intended by the developers. But if you look at this code, it's pretty clearly intended. After all, they promised a Mr. Chris Houlihan his name would appear in the game. What better way to technically fulfill that promise than an obscure fail-safe room?

Putting my money where my mouth is

No seriously, this code is sloppy. Here's the vanilla code:

REP #$30
m=8 x=8 before this
LDA $1B
AND #$00FF
BEQ OVERWORLD_HOLE
LDA $00
PHA
SEP #$30

Seriously? Who knew 14 bytes could be so lame? Here's my better code, which uses space and time more efficiently:

LDA $1B
Load indoors/outdoors
BEQ OVERWORLD_HOLE
but further ahead than vanilla
PEI ($00)
Underused opcode that is totally AWESOME

Ya, that's it. 6 bytes. The branch in my code would be 6 bytes further (accounting for the stuff I removed), hitting the instruction REP #$20. X should be 16-bit though, so we need to change that to REP #$30. Same number of bytes though.

PEI is an underused and underrated instruction that pushes the 16-bit value in the address it holds to stack, regardless of the accumulator's or index register's current bit mode. In this case, it also makes way more sense than swapping bitmodes just to push to the stack, which also required a mask o—… Wait a second. No it didn't. Even if you wanted to do it this inefficient way, why would you set the accumulator to 16-bit and immediately load what's intended to be an 8-bit value? REP #$30 should have come after the LDA $1B. It wouldn't affect the Z flag, and it would have removed the need to mask the accumulator before the branch check.

Summary

When Link falls into a hole on the overworld, the destination is determined by both the current screen ID and his X- and Y-coordinates. As a small catch, before this even happens, Link's Y-coordinate is determined by the top of the camera. Although the camera can move after the Y-coordinate is recalculated, but before the destination is. So calling it camera-based is only about one-quarter correct.

Destinations are in a list, which is looked through for a match from the input parameters. If every item is looked at without finding a match, then the Houlihan Room is used as the target destination.

This is one of the few failsafes added to the game. No matter how you slice it, the game is doing exactly what the developers wanted it to do. And because it is possible to trigger the failsafe without doing any actual glitches, calling Houlihan a glitch is patently wrong.