User Tools

Site Tools


metroid:asm_hacks

ASM hacks

This page lists various asm hacks that can be applied to the game. Larger code listings should be placed on their own page.

Notes

These hacks are from various sources and may be intended for different assemblers or for different configurations of an assembler. If you use the patch, please give credit to the author!

Most hacks are applied to the game engine bank (bank 7). These will not work as-is with a ROM expanded by Editroid, which moves the game engine to bank $F. The offset needs to be adjusted accordingly. Add $20000 to file offsets to get the new game engine bank offset. Also, the expanded ROMs make use of previously unused ROM space that ASM hacks will commonly be placed in, so the ASM may need to be placed at a different address.

Tweaks

Small tweaks that can be made to change behavior of the game. Tweaks that apply to the game engine page (bank $7) need to be adjusted to bank $F for an expanded ROM). To get the file offset for the game engine bank, add $10010 to the address ($30010 for expanded ROMs). For level banks, subtract $8000 from the pointer, and add level bank offset (Brinstar = $4010, Norfair = $8010, Tourian = $C010, Kraid = $10010, Ridley = $14010).

Locations are specified as BANK:ADDRESS

Bomb fuse time
.PATCH 07:D663 
LDA #$?? ; Sets bomb timer (originally #$18)
Easy bomb jumping
.PATCH 0F:D15D ; (.PATCH 07:D15D for unexpanded ROMs)
LDA $0307 ; Allows Samus to drop bombs while in air more easily
Damage from enemies
;(Substitute appropriate level bank)
.PATCH ??:95CE
.db #$??   ; Damage to Samus caused by enemies - low byte (example .db #$80 results in loss of 8 energy when hurt by enemy)
.PATCH ??:95CF
.db #$??   ; Damage to Samus caused by enemies - high byte (typically #$00. example: .db #$85 would result in additional damage of 850 when hurt by enemy)

Hacks too large to be listed here are linked to below.

  • Wavy-Ice—Allows combination of wave and ice beams
  • Mini-map—Provides a minimal map display
  • Wall Jumping—Allows the player to wall jump like in Super Metroid.
  • Health Blocks—Adds tiles that heal or damage the player.

Change Starting Area

This patch changes the starting area. It works by replacing the normal “start-new-game” routine with a simpler one that acts as though the player entered a password to start in the desired level. One drawback of this method is that the player can still enter a blank password and begin in Brinstar.

    InitializeGame     = $92D4
    NewStartingArea = 1     ; 0 = Brinstar, 1 = Norfair, 2 = Kraid, 3 = Tourian, 4 = Ridley
    
    .PATCH 00:932B
       lda #NewStartingArea
       sta PasswordByte08
       jmp InitializeGame

Doorway Scrolling

This simple patch changes how doorways affect scrolling. Usually, a normal doorway tile, show in green with “Show Physics” in Editroid, toggles between horizontal and vertical scrolling (connects a horizontal and vertical room), and a horizontal-doorway tile, shown in yellow in Editroid, sets scrolling to horizontal (connects two horizontal rooms).

With this patch, a green (normal) doorway will always set scrolling to vertical and a yellow (horizontal) doorway will always set scrolling to horizontal.

    .PATCH 07:E237
    ;     (0F:E237 for expanded ROMs)
        LDA #$00

The patch can easily be applied with a hex editor. Go to offset $1E247 in the file ($3E247 for expanded ROMs) and change A4 57 to A0 00.

The patch can also be automatically put into a ROM using Editroid, just go to “Tools” and select “Doorway Scrolling Patch”.

More Doorway Tiles

In the original Metroid, there is only one tile that has doorways physics (two, actually: one for each doorway type). This makes for a very boring doorway. This patch increases the number of tiles with doorway physics to allow more variety in the doorways.

Change the values of NormalDoorwayTiles and HorizontalDoorwayTiles accordingly

    NormalDoorwayTiles     =  $A     ; (10)
    HorizontalDoorwayTiles =  $A     ; (10)
    
    .PATCH 07:E807
    ;      0F:E807 for expanded ROMs
        CMP #($A0 + NormalDoorwayTiles)
        BCC $E811
        CMP #($A0 + NormalDoorwayTiles + HorizontalDoorwayTiles)
        BCS $E813

Or, using a hex editor go to $1E817 ($3E817 in an expanded ROM), and change

C9 A0 F0 06 C9 A1 D0 04

to

C9 (A0 + normal doorway tiles) 90 06 C9 (A0 + normal doorway tiles + horizontal doorway tiles) B0 04

The normal doorway tiles will start at tile A0, and horizontal doorway tiles will come right after the normal doorway tiles. Since these tiles are already in use, you will need to re-arrange the tiles and fix the combos that use them.

Hide Enemies When In Door

By FurryKef. This hack causes enemies to disappear when the player enters a doorway, and to re-appear as Samus is entering the next room. The idea is to avoid the issue of enemies getting trapped in the doorway during screen transitions, and killing the hell out of the player. It also avoid the issue of enemies in the next room attacking the player before he has time to dodge the enemy.

The intended assembler is WLA. It is not clear whether this patch is intended for a normal or expanded ROM.

; Behavioral patch - enemies now freeze while moving through doors
; No more being hit by enemies while moving through 'em!
; This hooks into the start of UpdateEnemies in Dirty McDingus's code.
.bank 16 slot 1
.orga $F345
.section "freeze enemies patch" size 12 overwrite
    lda $56    ; Nonzero when traveling through door
    beq +
    rts        ; In door; don't update enemies
+  jsr FreezeEnemiesRestoration
    nop
    nop
    nop
    nop
.ends

; This section starts at AccessSavedGame and ends at the end
; of SavedDataTable
.orga $CA35
.section "patch scratch" size 191 overwrite
; Restores the behavior overwritten by "freeze enemies patch"
FreezeEnemiesRestoration:
    ldx #$50
-  jsr $F351  ; DoOneEnemy
    ldx $4B    ; PageIndex
    jsr $F1F4  ; Xminus16
    bne -
    rts
.ends

Bug Fix: Faulty Unmorph Event Collision Check

By Stinktier. In the original metroid engine, the code instructs the CPU to add a constant to the player objects' (samuses) y position offset every so often, before checking if it is possible to go one pixel up. This is samuses' upper line in her hit box. Unfortunately and possibly mistakenly, the engine happens to add this constant twice during the special occasion of checking if samus is able to break from her morph ball mode; once in the subroutine which is called when the 'up' button is pressed while in ball mode, and then again in the aforementioned standard procedure subroutine for checking upward collisions. This results in a glitch where you by un-morphing can stand and jump through certain solid objects, as the collision detection line is way past the solid object.

During gameplay of the original level design, this bug is perfectly concealed by the design choice of letting almost all 'blocks' (or combos, as they are called in Editroid) consist of 2×2 sets of 8x8px tiles with homogenous properties; they are all either 'solid' or 'air'. The few odd combos are placed where they don't provoke the bug, as you wouldn't roll under a 'mario pipe' or a 'volcano'. The bug fix is therefore necessary if (and only when) you make combos that consist of both 'air' tiles and 'solid' tiles. Having this option available is significantly expanding what is possible to do with the level design.

The actual bug fix is to eliminate the addition in the first subroutine, which is called exclusively during the unmorphing event and nowhere else.

  1. Find the relevant location in the ROM by searching for this string: 2DAD0103186908 - This string is unique and will be found regardless of vanilla/expanded ROM size or data block restructuring.
  2. Either a) replace 08 with 00 (which will tell the CPU to add a zero value), or b) replace 6908 with two 'no operation' instructions (6908 to EAEA). Either way the amount of 'empty' CPU cycles will be neglible, and the result the same.
  3. Save. Now your hack is able to handle half-solid, half-air combos properly under all circumstances.
metroid/asm_hacks.txt · Last modified: 2021/03/06 15:51 by flower