Dam age is exactly what it sounds like: it's how old the building in South Hyrule is.
It is not to be confused with damage, which is how much health is taken away from Link or an enemy when sustaining a hit. There are a handful of routines that do some sort of damage handling. Who's hitting whom determines which calculation will be used. This explication covers what happens when you, the player, are the aggressor.
A few pieces of information are needed to know exactly how much damage is taken or what happens to an enemy when it is hit with something.
Damage class is derived from whatever is dealing the hit. It is used with the sprite's ID to check a lookup table for that sprite's damage subclass within the damage class. Finally, the damage class and subclass together are fed to another table for the final value.
That's all there is to understand the basics, but if the basics are all you're after, then you are clearly out of sync with my style of deep-dive learning. The rest of you should strap on your brain snorkels and continue reading, as we will submerge into the inner workings of each of these calculations to understand how they differ and how they all converge into a single routine.
Sprites don't just take damage out of nowhere. Specific routines need to be called. There are 3 main ways that sprites can take damage:
There are other, minor ways to deal damage to sprites, but we'll cover those after the main trilogy.
| Damage class | Subclass damage | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
| $0 | Boomerang | $00 | $01 | $20 | $FF | $FC | $FB | $00 | $00 |
| $1 | Sword 1 | $00 | $02 | $40 | $04 | $00 | $00 | $00 | $00 |
| $2 | Sword 2 | $00 | $04 | $40 | $02 | $03 | $00 | $00 | $00 |
| $3 | Sword 3 | $00 | $08 | $40 | $04 | $00 | $00 | $00 | $00 |
| $4 | Sword 4 | $00 | $10 | $40 | $08 | $00 | $00 | $00 | $00 |
| $5 | Sword 5 | $00 | $10 | $40 | $08 | $00 | $00 | $00 | $00 |
| $6 | Arrow | $00 | $04 | $40 | $10 | $00 | $00 | $00 | $00 |
| $7 | Hookshot | $00 | $FF | $40 | $FF | $FC | $FB | $00 | $00 |
| $8 | Bomb | $00 | $04 | $40 | $FF | $FC | $FB | $20 | $00 |
| $9 | Silver arrow | $00 | $64 | $18 | $64 | $00 | $00 | $00 | $00 |
| $A | Powder | $00 | $F9 | $FA | $FF | $64 | $00 | $00 | $00 |
| $B | Fire rod | $00 | $08 | $40 | $FD | $04 | $10 | $00 | $00 |
| $C | Ice rod | $00 | $08 | $40 | $FE | $04 | $00 | $00 | $00 |
| $D | Bombos | $00 | $10 | $40 | $FD | $00 | $00 | $00 | $00 |
| $E | Ether | $00 | $FE | $40 | $10 | $00 | $00 | $00 | $00 |
| $F | Quake | $00 | $20 | $40 | $FF | $00 | $00 | $00 | $FA |
There are 16 damage classes, each with 8 subclasses. These subclasses determine the damage or effect inflicted on a sprite. Subclass data is stored as a table in ROM at
| ID | Function |
|---|---|
| $F9 | Target becomes a faerie |
| $FA | Target becomes a blob |
| $FB | Target stunned for 32 frames |
| $FC | Target stunned for 128 frames |
| $FD | Target incinerated |
| $FE | Target becomes frozen |
| $FF | Target stunned for 255 frames |
The subclass that each sprite should look for in each damage class is in a table in WRAM at
The full table for each sprite, including how much damage that subclass results in, is documented here.
Honestly, I'm not sure why damage subclass is even a gameplay routine. All this data is static, so they could have easily precalculated every damage value as they were decompressing the subclass data and stuck that into WRAM.
Contrary to some's belief, there is no "insta-kill" damage. Anything that dies to a single hit just doesn't have enough health to survive the damage inflicted. Technically, the inceration damage just sets sprites to AI mode
I don't know about you, but when I hear "instant", I expect things to be done without delay. I don't see how sadistically roasting your victims alive until their 3rd degree burns kill them is "instant" by any stretch of the word.
You sicken me.
| Attack type |
Sword level | |||
|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |
| Slash/Dash | 1 | 2 | 3 | 4 |
| Spin attack | 2 | 3 | 4 | 5 |
| Poke attack | 1 | 1 | 2 | 3 |
Most people understand the sword's damage mechanics, but it's still worth looking at parts of this routine more indepth, just to understand how exactly the game knows what damage to do.
Sword and hammer damage require that the sprite in question calls
There are several types of sword damages that can be dealt, and most people are familiar with them, but here's exactly how the game sees it:
The damage application routine actually begins right after this. It's literally the next instruction. But before we look at it, we have other things to cover.
| Ancilla | Class | Ancilla | Class | |||
|---|---|---|---|---|---|---|
| $00 | Nothing | $6 | $22 | Item get | $1 | |
| $01 | Somaria missile | $1 | $23 | Poof | $1 | |
| $02 | Fire rod shot | $B | $24 | Overworld gravestone | $1 | |
| $03 | Unused | $0 | $25 | Unused | $1 | |
| $04 | Beam wall hit | $0 | $26 | Sword swing sparkle | $1 | |
| $05 | Boomerang | $0 | $27 | Duck | $1 | |
| $06 | Wall hit | $0 | $28 | Fairy pond toss item | $1 | |
| $07 | Bomb | $8 | $29 | Pendant/crystal/medallion item get | $1 | |
| $08 | Door debris | $0 | $2A | Spin attack sparkle | $1 | |
| $09 | Arrow | $6 | $2B | Spin attack sparkle | $1 | |
| $0A | Lodged arrow | $0 | $2C | Somaria block | $1 | |
| $0B | Ice shot | $C | $2D | Somaria block dying | $1 | |
| $0C | Sword beam | $1 | $2E | Somaria block exploding | $1 | |
| $0D | Max sword charge sparkle | $0 | $2F | Lamp flame | $B | |
| $0E | Unused | $0 | $30 | Byrna charge up spark | $0 | |
| $0F | Unused | $0 | $31 | Byrna spark | $1 | |
| $10 | Unused | $0 | $32 | Blast wall explosion | $1 | |
| $11 | Ice rod shot wall hit | $1 | $33 | Blast wall explosion | $1 | |
| $12 | Unused | $0 | $34 | Skull Woods fire | $1 | |
| $13 | Ice shot sparkle | $0 | $35 | Master Sword cutscene | $1 | |
| $14 | Unused | $0 | $36 | Flute from ground | $1 | |
| $15 | Splash | $0 | $37 | Flute spot debris | $1 | |
| $16 | Stars | $0 | $38 | Flute cutscene bird | $1 | |
| $17 | Dirt | $0 | $39 | Somaria platform poof | $BC | |
| $18 | Ether | $E | $3A | Super Bomb explosion | $F0 | |
| $19 | Bombos | $D | $3B | Sword up sparkle | $0E | |
| $1A | Powder | $0 | $3C | Sword charge sparkle | $10 | |
| $1B | Wall poke spark | $0 | $3D | Item splash | $01 | |
| $1C | Quake | $F | $3E | Crystal rising | $6B | |
| $1D | Bonk screen shake | $0 | $3F | Bush powder poof | $DA | |
| $1E | Dash dust | $0 | $40 | Smithy poof | $AA | |
| $1F | Hookshot | $7 | $41 | Waterfall splash | $BF | |
| $20 | Link's blanky | $1 | $42 | Upgrade rupees | $84 | |
| $21 | Link snoring | $1 | $43 | Ganon's Tower cutscene | $EC | |
Ancillae begin by using their ID to index a table of damage classes. This table has a couple of oddities. First off, there are a total of 68 ancillae, but the table only has 57 entries; the last 11 bleed into code. While it might make sense to only include data up to the highest ID that can do damage, that's not what this table does. The last ID that needs a damage class is entry 49, the cane of byrna spark.
Half of the default values here are
Lamp flames don't contain any routine for checking damage, but if they did, they would do the same damage as fire rod.
But I digress…
Once the damage class is determined, it is used to perform a couple more checks that determine the flow of the routine.
You'd think these would be simple, right? In a way, they are, but there's some curious logic I'd like to point out. As mentioned, a small handful of sprites explicitly call the routine
Every sprite thrown, regardless of what it is, is given an 8x8 hitbox, and that is matched against the hitbox of the target.
Then, for some reason, there's an explicit check for the target's sprite ID to see if it's
| Subtype | Thrown object | |
|---|---|---|
| Outdoors | Indoors | |
| 0 | Sign | Glitchy placeholder |
| 1 | Light rock | Skull pot |
| 2 | Light bush | World-based pot |
| 3 | Link's head | Link's head |
| 4 | Dark bush | Miscolored ceramic pot |
| 5 | Dark rock | Miscolored skull pot |
| 6 | Big light rock | Big light block |
| 7 | Dark light rock | Big miscolored block |
| 8+ | Invalid (glitchy) | Invalid (glitchy) |
The thrown sprite's ID is checked, specifically for
And what's with the subtypes for throwable objects? Isn't it kind of odd that everything is class 3 damage, except for one type of bush, and only when outdoors? And when I say that subtype 3 is Link's head, I mean it. With an unused ID, it would make a bit more sense to use that for bushes, so that indoors/outdoors isn't relevant. And why do dark bushes deal more damage? I have a feeling that these were written sometime after the thrown sprite damage routine, resulting in someone not fixing their damage class either. I think this thrown-object-specific damage class stuff would have worked better as a table.
The first minor class of damage to discuss is reflected energy balls. Unlike thrown sprites, these are super simple. They just load a value of
Ballz also makes the hefty assumption that Agahnim is always in slot
Spike damage requires a specific routine to be called as well, but, in this case, it's
Now that we've covered damage class calculation, we can finally examine the
This routine has a single parameter, which is a value used later for an iframe timer. Everything else in memory should already be set up for damage to occur.
First, 2 checks are performed: bit 6 of
Next, the sprite's ID and the calculated damage class are used to index the WRAM sprite damage table for the subclass. The subclass is combined with the damage class to index the table in ROM at
Now we begin individual checks to see if we're doing using a special damage class or direct damage. This is the point in the routine that Agahnim's energy shots enter from. The fairy (
Following that is a check to make sure that better damage is not being overwritten. If the damage we entered with is less than the damage already being dealt, then the sprite's current "damage taken" property is left alone. But that's all that's skipped. The rest of the routine still continues as normal. This allows for damage application to be extended, such as with doubling fire rod shots on Kholdstare's shell.
If the inflicted damage is 0, it continues, but otherwise, there's this weird segment of code. As far as I can tell, it's essentially useless, but this code appears to "shield" non-boss sprites from damage, and even revive them. If the damage class was powder and powder doesn't damage the sprite normally, then its iframe timer and damage taken property will be zeroed.
For some reason, powder is a bit special when it deals damage to sprites. It does use the same routine, but only part of it. When the routine is entered normally, the sprite's death is checked, and bit 7 is a flag that tells the ancilla to stop. This check is not performed at the point where magic powder enters the routine. This seems pretty useless; you don't really have time to use powder in most cases. The best place to see this is to get an enemy that takes damage from the boomerang (debirandos are good because they don't move) and throw behind it. Then right before the boomerang hits it on its return, sprinkle the target.
But let's continue with the routine when it's nonzero damage. More special damage classes are checked. First, freeze and long stun are checked together. Then there's the code that handles water bubble respawning. I'm not sure why it's here, but it is. Basically, it just sets the bubble back to alive and resets its AI. Enemy arrows also have their deflection code here.
The value we initially entered with is used for the iframe timer, the same one that controls how long damage flashing occurs for. Helmasaur King has a special check here to determine which sound to play, based on what phase he's on. Otherwise, the boss flag sprite property is checked to determine which OOF is heard.
And finally, the damage class is checked again to apply recoil. Forcing 0 recoil against the sprite if it's one of the medallion classes. This is how recoilless Agahnim hits happen. The damage class address is a single byte, and it's only updated when it needs to be. So if the last damage class used was a medallion, it will be checked when energy balls deal damage, because they jump in halfway through the routine, and don't need to use the address; it gets left alone, but checked later for recoil.
For non-medallion damage classes, 3 sprites have a special recoil timer:
For everything else, the recoil timer is set to 15 frames.