The Great Metroid Construction Collaboration Hunt - Post your resources here!

Started by Zhs2, July 20, 2009, 07:55:03 PM

Previous topic - Next topic

Fe

Indexed Item Sounds

Yet another ASM patch that lets you change item pickup sounds. This one operates on item indexes though, and has a few more features. You can choose to have fanfare for an item (such as a major upgrade) and the message box will last the normal 6 seconds, or if you choose a sound effect it will be 30 frames. Also, it can optionally override the value provided for the first expansion item of a certain type you pick up (so that your first missile has fanfare, and the rest can be quick sound effects).

Should be compatible with pretty much any hack unless you moved fundamental PLM routines, but if you messed with PLM instructions then the fanfare override might not work.

Fe

Equipment Screen Time/Percentage



Pretty self explanatory. I took some extra time to touch things up though, AND there's a version that's compatible with DC's map patch.
Scyzer's endingtotals.asm is completely contained in this patch (should be safe to patch this over that as well). I fixed her arithmetic for
calculating decimal places, and now it can accurately calculate 2 decimal places with any number of total items in the hack (as long as it's
less than 256).

Removes reserve tank functionality in the equipment screen, for now. If people are interested I could definitely add a compact reserves
display.

Please let me know if there are any issues  :^_^:

And please read the README  :wink:

albert v.

#1152
Nice Song for Futuristic looking hacks, or racing hacks like grand prix for example :p

5CC9 Long

Plus adding a new song collection from Kraid' area,
all the songs from kraid's theme I've made so far, i'm not working with music at the moment, but i had these ready from long ago so here you go!

Also added a custom arrangement from Red brinstar
If you want to use the source file just let me know, this is one of the first songs I've made.

Please ask for password if you want to use the resource files  :^_^:


PHOSPHOTiDYL

I made a list of how many doorz there are per room for easy level swapping.;------------------------------;;------------------------------;
;//.....[8doorz]h
79d19
;------------------------------;;------------------------------;
;//.....[7doorz]
792fd
7acb3
7caf6
;------------------------------;;------------------------------;
;//.....[6doorz]
793fe
7d5a7
;------------------------------;;------------------------------;
;//.....[5doorz]
796ba
7a253
7a923
7ad5e
7cfc9
7d0b9
;------------------------------;;------------------------------;
;//.....[4doorz]
791f8
799bd
7a815
7aa82
7ab07
7ae74
7b3a5
7cefb ;//[maridiatube]
7d017
7d21c
7d340
7d646
7d913
;------------------------------;;------------------------------;
;//.....[3doorz]
7948c
79cb3
79e52
79f11
7a011
7a408
7a471
7a4da
7a56b
7a8b9
7a98d ;//[crocomire]
7adad
7aedf
7af72
7afce
7b4ad
7b510
7b585
7b6c1
7b6ee
7c98e ;//[walktorizo]
7ca52
7cbd5
7cc6f
7cf80
7d1a3
7d48e
7d72a
7ddf3
;------------------------------;;------------------------------;
;//.....[2doorz]
792b3
79461
794fd
79552
7957d
795a8
795d4
795ff
7965b
7968f
7975c
79879
798e2
7990d
79969
799f9
79a44
79b5b
79b9d
79bc8
79c5e
79d9c
79dc7 ;//[sporespawn]
79e11
79f64
79fba
79fe5
7a0a4
7a130
7a1ad
7a293
7a2f7
7a3dd
7a521
7a59f ;//[kraid]
7a5ed
7a6a1
7a75d
7a788
7a7b3
7a865
7a8f8
7aa0e
7aa41
7ab64
7ab8f
7abd2
7ac00
7ac2b
7ac83
7acf0
7ae07
7ae32
7aeb4
7af14
7afa3
7affb
7b026
7b07a
7b106
7b139
7b167
7b1e5
7b283 ;//[goldtorizo]
7b2da
7b32e ;//[ridley]
7b37a
7b40a
7b457
7b482
7b4e5
7b55a
7b5d5
7b62b ;//[ninjapiratez]
7b656
7ca08
7cb8b
7cd5c
7ce40
7cf54
7d08a
7d104
7d16d
7d1dd
7d252
7d27e
7d2d9
7d387
7d408 ;//[maridiaexpress]
7d433
7d461
7d4c2
7d5ec
7d617
7d69a
7d78f
7d7e4
7d81a
7d898
7d8c5 ;//[shaktool]
7d95e ;//[botwoon]
7d9fe
7da2b
7da60 ;//[draygon]
7dae1
7db31
7db7d
7dbcd
7dc19
7dc65
7dcb1 ;//[giantmetroid]
7dcff
7ddc4
7de7a
7dea7
7dede
7df8d ;//[ceres]
7dfd7 ;//[ceres]
7e021 ;//[ceres]
7e06b ;//[ceres]
;------------------------------;;------------------------------;
;//.....[1doorz]
793aa
793d5
79804 ;//[bombtorizo]
79994
79a90
79c07
79c35
79c89
7a051
7a07b
7a0d2
7a107
7a15b
7a184
7a1d8
7a201
7a22a
7a2ce
7a37c
7a3ae
7a447
7a4b1
7a618
7a641
7a6e2
7a70b
7a734
7a890
7a9e5
7aab5
7aade
7ab3b
7ac5a
7ad1b
7adde
7b051
7b0b4
7b0dd
7b192
7b1bb
7b305
7b3e1 ;//[unused]
7b698
7b741
7caae
7cc27
7cccb
7cd13 ;//[phantoon]
7cda8
7cdf1
7ce8a
7ced2
7d055
7d13b
7d2aa
7d3b6
7d3df
7d4ef
7d51e
7d54d
7d57a
7d6d0
7d6fd
7d765
7d845
7d86e
7d9aa
7d9d4
7dd2e
7dd58 ;//[motherbrain]
7de23
7de4d
7df1b
7e0b5 ;//[ceresridley]
;------------------------------;;------------------------------;
;//.....[elevatorz top]
794cc ;//[crateria]
7962a ;//[crateria]
797b5 ;//[crateria]
79938 ;//[crateria]
7a66a ;//[crateria]
7a6a1 ;//[brinstar]
7af3f ;//[norfair]
;------------------------------;;------------------------------;
;//.....[elevatorz bot]
79ad9 ;//[brinstar]
79e9f ;//[brinstar]
7a322 ;//[brinstar]
7a7de ;//[norfair]
7b236 ;//[norfair]
7d30b ;//[maridia]
7daae ;//[tourian]
7df45 ;//[ceres]
;------------------------------;;------------------------------;


albert v.

Updated Song: Goron City Song from The Legend of Zelda Ocarina Of Time, I tried to make it sound just like the original.
609F LONG
+
New Song: Windmill from The Legend of Zelda, this still has some minimum panning issues but sound great so far.
+
Stone Tower song From Majora's mask, I'm trying to make it sound just like the original, although I had to do some modifications and remove a few instruments in order to fit into the Super Metroid Spc Engine
59AB LONG!

If you ever want to learn about making music for Super Metroid, you can DM me on Discord: Albert V#5864 And I'll be happy to help.

BigDomino

Hello everyone,

Here are three patches that I have been working on for some time.
These features are intended to integrate my hack, but I thought they might be of interest to other people, so I decided to share them.

For more information, see the videos and descriptions below.

SPOTLIGHT ON SAMUS :

VIDEO

[spoiler=ASM + Description][code];------------------------------------------------------------------------------------------------------------------------------------------------------------   *
;                                                            |
; Spotlight effect on Samus ASM  [Filename: Spotlight v.1.00.asm] (version 1.00 ; september 2020)                        |
; =============================                                                   |
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
;                                                            |
; Description:                                                         |
; - This patch create a new FX1 type which darkens the room where it is apllied.                              |
; - In such a room, Samus appear surounded by a glowing luminous halo.                                    |
; - When she moves, the halo is shifted in the direction of displacement.                                 |
;                                                            |
; Warning:                                                         |
; - The patch replace the original FX1 Fog effect. Don't apply this patch if you plan to use fog in your hack !                     |
;                                                            |
; How to install ?:                                                      |
; - Read info, control free space usage and apply the patch "Subroutine_Array_v.1.00.asm" prior to this patch, but ...                  |
;   "Subroutine array" is a prerequisite for several patches by BigDomino. It should only be applied ONCE to your hack and never again !          |
;   If you alrerady have applied "Subroutine array" for another BigDomino patch, it's done ! Go to the next step.                  |
;   Don't apply it again since it would reset some pointers, making older patches ineffectives.                           |
; - Control free space usage for this patch (see below).                                       |
; - Apply this ASM patch to your unheadered ROM.                                          |
; - Done.                                                         |
;                                                            |
; How to use in a room ? (Smile 2.5):                                                |
; - In a room with FX1 valid pointer, open the FX1 editor and choose: 0C - Fog.                                 |
; - Set palette blend value to 06, 0C, 12 or 18 (-> the higher, the darker).                                 |
; - Uncheck all options in "Palette FX" tab.                                             |
; - In the "A/B" tab, set the "A" parameter to 28 & "B" parameter to 30.                                 |
; - Done.                                                         |
;                                                            |
; Limitation, regarding enemy sprites:                                                |
; - When enemies are used in a room with the halo effect, they should use palette line 0007 (ie: in the bottom right corner of the "Species editor",       |
;   see the column next to enemy ID and double-clic to edit).                                       |
;   Due to SNES limitation, only the enemies whose color palette is assigned to palette line index 7 of CGRAM are correctly affected by the halo effect ;   |
;   Those whose palette is assigned to another palette line (ie: 0001 ; 0002 or 0003) are left unaffected (ie: They are not darkened at all).         |
;   In that case, the enemies' sprites will appears much brighter than they should, in total contrast with the dark room all around...            |
;                                                            |
;   So, for rooms where only one type of enemy is needed, there is no problem : use palette line 0007.                        |
;   In the other hand, if more than one type of enemy is needed, a possible workaround is to assign all enemies to palette line 0007 in the species editor.   |
;   In that case, all enemies will share the specific color palette of the enemy located at the very bottom of the list (nice & unusual effect are possible).   |
;   NB: In a previously designed room, since the order in this list is decisive, don't hesitate to remove all enemies ID by double-clicking them,      |
;   then, re-add each species in the desired order, by double-clicking in the enemy list in the top-left corner.                  |
;                                                            |
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
; Free space usage:                                                      |
; - Free space used by this patch can be set at the user's will (but within the same respectives banks) ; The default ranges are:            |
;                                                            |
;  LoROM $88:EE32 to $88:F21A (inclusive) ie PC $04:6E32 to $04:721A (inclusive). [lenght: $ 3E9 bytes]                        |
;  LoROM $B8:B7A0 to $B8:B7CB (inclusive) ie PC $1C:37A0 to $1C:37CB (inclusive). [lenght: $  2C bytes]                        |
;                                                            |
; - If there is data in your ROM at these places, you need to relocate the code of this ASM before applying (see below).               |
;                                                            |
;                                                            |
; Data modification / Pointer redirection:                                             |
; - Some data are changed at the folowing ranges in the ROM:                                       |
;                                                            |
;  LoROM $88:8235 to $88:823D (inclusive) ie PC $04:0235 to $04:023D (inclusive). [lenght: $   8 bytes]                        |
;  LoROM $88:825A to $88:8261 (inclusive) ie PC $04:025A to $04:0261 (inclusive). [lenght: $   8 bytes]                        |
;  LoROM $88:827F to $88:8286 (inclusive) ie PC $04:027F to $04:0286 (inclusive). [lenght: $   8 bytes]                        |
;  LoROM $88:806E to $88:806F (inclusive) ie PC $04:006E to $04:006F (inclusive). [lenght: $   2 bytes]                        |
;  LoROM $88:DB48 to $88:DB5D (inclusive) ie PC $04:5B48 to $04:5B5D (inclusive). [lenght: $  16 bytes]                        |
;  LoROM $89:AA08 to $89:AA17 (inclusive) ie PC $04:AA08 to $04:AA1F (inclusive). [lenght: $  18 bytes]                        |
;  LoROM $8A:A940 to $8A:B17F (inclusive) ie PC $05:2940 to $05:317F (inclusive). [lenght: $ 840 bytes]                        |
;  LoROM $9A:B800 to $9A:B81F (inclusive) ie PC $0D:3800 to $0D:381F (inclusive). [lenght: $  20 bytes]                      |
;  LoROM $9A:B900 to $9A:B95F (inclusive) ie PC $0D:3900 to $0D:395F (inclusive). [lenght: $  60 bytes]                      |
;  LoROM $9A:B980 to $9A:BADF (inclusive) ie PC $0D:3980 to $0D:3ADF (inclusive). [lenght: $ 160 bytes]                      |
;                                                            |
; - If you have already used these addresses to create HiJack point or other stuff for your hack, you shouldn't apply this patch.            |
;                                                            |
;                                                            |
; RAM usage:                                                         |
; - This patch use several free RAM addresses:                                             |
;                                                            |
;  RAM $7E:FA12 to $7E:FA12 (inclusive). [lenght: $ 2 bytes]                                       |
;  RAM $7E:FA14 to $7E:FA14 (inclusive). [lenght: $ 2 bytes]                                       |
;  RAM $7E:FA16 to $7E:FA16 (inclusive). [lenght: $ 2 bytes]                                       |
;  RAM $7E:FA18 to $7E:FA18 (inclusive). [lenght: $ 2 bytes]                                       |
;  RAM $7E:FA1A to $7E:FA1A (inclusive). [lenght: $ 2 bytes]                                       |
;  RAM $7E:FA20 to $7E:FA21 (inclusive). [lenght: $ 2 bytes]                                       |   
;  RAM $7E:FA22 to $7E:FA23 (inclusive). [lenght: $ 2 bytes]                                       |   
;                                                            |
; - If another patch/code who use the same addresses is intended to run at the same time than this patch in a room, you need to change the addresses above to   |
;   other unused one (there is plenty : for example, from 7E:FA24 to 7E:FFFF).                                 |
;                                                            |
;                                                            |
; Credit:                                                         |
; - PJ_Boy for his documentation - specifically his RAM map and the disassembly of bank $88 - and for writing the code of the subroutine that disables parts      |
;   of BG3 via window 1 mask.                                                   |
; - Bruce Clark (65C816 Opcodes at http://www.6502.org/tutorials/65c816opcodes.html).                              |   
;                                                            |
;                                                            |
; Patch Created by BigDomino.                                                   |
;                                                            |
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *

lorom

            ; Defines addresses :
            ; ===================
!OnScreenX         = $12   ; Horizontal coordinate of Samus on-screen.
!windowBg3Mask        = $61   ; Window BG3/BG4 mask settings.
!window1Left          = $63   ; Window 1 left position.
!window1Right         = $64   ; Window 1 right position.
!winAreaSubscrDis     = $6D   ; Window area subscreen disable.
!ColMathRegB         = $71   ; Next gameplay colour math control register B.
!BackdropBlue         = $74   ; Value 1 for colour math subscreen backdrop colour (used for Blue).
!BackdropGreen         = $75   ; Value 2 for colour math subscreen backdrop colour (used for Green).
!BackdropRed         = $76   ; Value 3 for colour math subscreen backdrop colour (used for Red).
!PlayerInput         = $8B   ; Controller 1 input.
!FrameCounter         = $05B8   ; Frame counter (incl. lag frames).
!layer1X              = $0911   ; Layer 1 X position.
!layer1Y              = $0915   ; Layer 1 Y position.
!GameState         = $0998   ; Game state.
!samusX               = $0AF6   ; Samus X position.
!samusY               = $0AFA   ; Samus Y position.
!PBlendCol1         = $C032   ; Color, copied straight to CGRAM (from palette blend color n°1).
!PBlendCol2         = $C034   ; Color, copied straight to CGRAM (from palette blend color n°2).
!PBlendCol3         = $C036   ; Color, copied straight to CGRAM (from palette blend color n°3).
!PBlendCol1Tar         = $C232   ; Target color (from palette blend color n°1).
!PBlendCol2Tar         = $C234   ; Target color (from palette blend color n°2).
!PBlendCol3Tar         = $C236   ; Target color (from palette blend color n°3).
!bg3X                 = $7ECADC   ; BG3 X position.
!bg3Y                 = $7ECADE   ; BG3 Y position.
!RAM_Y_Shift          = $7EFA12   ; Custom RAM address to store halo vertical shift value.                             [!]
!RAM_X_Shift          = $7EFA14   ; Custom RAM address to store halo horizontal shift value.                             [!]
!ColorFlag         = $FA16   ; Custom RAM address for the "color-saved" flag. (#$1234 = set ; #$0000 = clear).                      [!]
!OriginalColor         = $FA18   ; Custom RAM address to store palette blend color 2 value, as a reference.                        [!]
!DarkerColor         = $FA1A   ; Custom RAM address to store palette blend color 2 value darkened, as a reference.                      [!]
!PBOccuredFlag        = $7EFA20   ; Custom RAM address for the flag set when a power bomb explosion animation has occured. (#$0001 = set ; #$0000 = clear)     [!]
!RestartAfterPB       = $7EFA22   ; Custom RAM address to store the value of the frame counter where a PB explosion has occured.                   [!]
            ;
            ; Defines constants :
            ; ===================
            ;
!spotlightRadius      = #$0040   ; Radius of the halo ; BG3 will be amputated, right and left, beyond this distance.
!Shift_positive       = #$0020   ; Max value the halo can be shifted in the UP/RIGHT direction. [min. 0000 ; max. 0040]                    [!]
!Shift_negative       = #$FFE0   ; Max value the halo can be shifted in the DOWN/LEFT direction.   [min. FFC0 ; max. 0000]                      [!]
            ;
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
            ;
org $89AA08         ; Set new palette blend entries N°06, 0C, 12 & 18 with 1+3 colors for the halo :
            ; ==============================================================================
            ; (Each palette overlap with previous palette by one color, as long as color 0 is hardcoded to be always transparent)
            ;
            ;           - Blue  Green  Red    B G R
; Standard dark room (06) :   ; ________________________________   _____
;   dw #%????????????????   ; Color 0 : #% ? ????? ????? ????? = ? ? ? : outside area  -> use transparency, then do a strong subtraction via backdrop color.
   dw #%0000010000100001   ; Color 1 : #% 0 00001 00001 00001 = 1 1 1 : center        -> very low subtraction.
   dw #%0001000010000100   ; Color 2 : #% 0 00100 00100 00100 = 4 4 4 : external ring -> medium subtraction.
   dw #%0000100001000010   ; Color 3 : #% 0 00010 00010 00010 = 2 2 2 : internal ring -> low subtraction.
            ;
; Medium dark room (0C) :   ; ________________________________   _____
;   dw #%????????????????   ; Color 0 : #% ? ????? ????? ????? = ? ? ? : outside area  -> use transparency, then do a strong subtraction via backdrop color.
   dw #%0000010000100001   ; Color 1 : #% 0 00001 00001 00001 = 1 1 1 : center        -> very low subtraction.
   dw #%0001100011000110   ; Color 2 : #% 0 00110 00110 00110 = 6 6 6 : external ring -> medium subtraction.
   dw #%0000110001100011   ; Color 3 : #% 0 00011 00011 00011 = 3 3 3 : internal ring -> low subtraction.
            ;
; Very dark room (12) :      ; ________________________________   _____
;   dw #%????????????????   ; Color 0 : #% ? ????? ????? ????? = ? ? ? : outside area  -> use transparency, then do a strong subtraction via backdrop color.
   dw #%0000010000100001   ; Color 1 : #% 0 00001 00001 00001 = 1 1 1 : center        -> very low subtraction.
   dw #%0010000100001000   ; Color 2 : #% 0 01000 01000 01000 = 8 8 8 : external ring -> medium subtraction.
   dw #%0001000010000100   ; Color 3 : #% 0 00100 00100 00100 = 4 4 4 : internal ring -> low subtraction.
            ;
; Extremely dark room (18) :   ; ________________________________   _____
;   dw #%????????????????   ; Color 0 : #% ? ????? ????? ????? = ? ? ? : outside area  -> use transparency, then do a strong subtraction via backdrop color.
   dw #%0000010000100001   ; Color 1 : #% 0 00001 00001 00001 = 1 1 1 : center        -> very low subtraction.
   dw #%0010110101101011   ; Color 2 : #% 0 01011 01011 01011 = B B B : external ring -> medium subtraction.
   dw #%0001100011000110   ; Color 3 : #% 0 00110 00110 00110 = 6 6 6 : internal ring -> low subtraction.
            ;
            ;
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
            ;
org $88806E         ; Repoint layer blending configuration #$30 :
            ; ===========================================
   dw LAYER_BLENDING   ; Now point to the routine that set window 1 mask, set color math register, calculate halo glowing effect and backdrop color.
            ;
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
            ;
org $88DB48         ; Halo effect position / animation routine : (hijack the original fog scrolling routine)
            ; ==========================================
   PHP          ; Push Processor Statut register to the stack. Always 1 byte copied to the stack.
   PHD         ; Push Direct Page register to the stack. Always 2 bytes copied to the stack.
   REP #$30      ; Set Accumulator, X and Y index register size to 16 bit (original size is already saved).
   PHA : PHX : PHY      ; Push full Accumulator, X and Y register to the stack. 2 bytes if A, X and Y register are in 16 bit mode.
            ;
   JSR CHECK_PLAYER_INPUT   ; Jump to subroutine that calculate animation of the halo according to input.
   JSR BG3_X_SCROLL   ; Jump to subroutine that handle layer 3 and windows mask position.
            ;
   REP #$30      ; Set Accumulator, X and Y register size to 16 bit.
   PLY : PLX : PLA      ; Pull next tree 2-bytes value from stack toward Y, X register and Accumulator.
   PLD         ; Pull next 2-bytes value from stack toward Direct Page register.
   PLP         ; Pull next 2-bytes value from stack toward Processor Statut register.
            ;
   PLB         ; Pull next 2-bytes value from stack toward Data Bank register (NB: pushed before hijack point).
            ;
   RTL         ; Return from subroutine long.
            ;
;   fillto $88DB8A, $FF   ; Fill remaining unused instruction with FF FF FF ... (for the sake of clarity) Uncomment if your assembler know this command.    [!]
            ;
            ;
            ; Warn if writing past end of original routine :
   warnpc $88DB8A      ; ==============================================
            ;
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
            ;
org $88EE32              ; Check free space in your ROM at this address ! Code should remain in bank $88.                    [!]
            ;
            ;---------------------------------------------------------------------------------------------------------------------------   *
            ;
BG3_X_SCROLL:         ; Write BG3 position, store on-screen X position of Samus in $12 :
            ; ================================================================
   LDA !samusY      ; Load Samus Y position, in pixel, from top border.
   SEC : SBC !layer1Y   ; Subtract layer 1 Y position.
   CLC : ADC #$0080   ; Shift layer3 position of 80 pixels down to match Samus hitbox center
   EOR #$FFFF : INC A   ; Reverse direction of the animation by changing the sign.
   CLC : ADC !RAM_Y_Shift   ; Add vertical shift value according to current player inputs.
            ;
            ; BG3 vertical position need to be limited to prevent the halo to appear at the other side of the screen (-> occure on elevator) :
   CMP #$FE98      ; Compare with the minimum value below which the halo start to loop near the ceilling :
   BCC +         ; If BG3 position is less than #$FE98, branch +...
   CMP #$FF67+1      ; Compare with the maximum value above which the halo start to loop near the floor :
   BCS ++         ; If BG3 position is greater than #$FF67 (ie: greater or equal than FF68), branch ++...
   BRA +++         ; but if value is between FE98 & FF67 (inclusive), go to the final step to store the calculated value as the new BG3 Y position.
+   LDA #$FE98      ; ...block minimal value in accumulator and...
   BRA +++         ; ...go to final step to store the value as BG3 Y position.
++   LDA #$FF67      ; ...block maximal value in accumulator and...
+++   STA !bg3Y      ; ...store as BG3 Y position.
            ;
   LDA !samusX      ; Load Samus X position, in pixel, from left border.
   SEC : SBC !layer1X   ; Subtract layer 1 X position.
   STA !OnScreenX      ; Save on-screen position of Samus.
   CLC : ADC #$0080   ; Shift layer3 position of 80 pixels to the right to match Samus hitbox center.
   CLC : ADC !RAM_X_Shift   ; Add horizontal shift value according to current player inputs.
   EOR #$FFFF : INC A   ; Reverse direction of the animation by changing the sign.
   STA !bg3X      ; Store as BG3 X position.
            ;
            ;----------------------------------------------------------------------------------------------------------------------------   *
            ;
            ; Window 1 left position = max(0, Samus' X position on screen - spotlight radius +/- halo shift value) :
            ; ======================================================================================================
   LDA !OnScreenX      ; Load on-screen position of Samus.
            ;
   SEC         ;
   SBC !spotlightRadius   ; Subtract radius of the halo, in pixel.
   CLC         ;
   ADC !RAM_X_Shift   ; Add horizontal shift value according to current player inputs.
            ;
   CMP #$00FF      ; Compare halo left border current X position with 00FF.
   BCC +         ; If less than 00FF (0000 to 00FE) halo is in normal range. Avoid next instruction.
            ;
   LDA #$0000      ; If equal or greater than 00FF (00FF to FFFF), halo shifted beyond left border (causing overflow). Load 0000 coordinate instead. 
+            ;
   SEP #$20      ; Set Accumulator size to 8 bit.
   STA !window1Left   ; Store low byte of accumulator to window 1 left border RAM address.
            ;
            ;----------------------------------------------------------------------------------------------------------------------------   *
            ;
            ; Window 1 right position = min(255, Samus' X position on screen + spotlight radius +/- halo shift va

BigDomino

SHINESPARK-RESTART :

VIDEO

[spoiler=ASM+Description][code];------------------------------------------------------------------------------------------------------------------------------------------------------------   *
;                                                            |
; SHINESPARK-RESTART MAIN CODE ASM  [Filename: Shinespark-Restart_Main_Code_v.1.00.asm] (version 1.00 ; September 2019)                  |
; ================================                                                |
;                                                            |
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
;                                                            |
; Description:                                                         |
; - During an horizontal super-jump (aka: shinespark), this patch made Samus able to crouch on any ascending slope, thus being ready to do another      |
;   super-jump in any direction (Nota: This feature was previously seen in Metroid Zero Mission / Metroid Fusion and works the same way as in these games).   |
; - This patch handle the main code of the "Shinespark restart" feature. Two other patches need to be apllied to implement the pick-up PLM that grant the   |
;   ability to restart shinespark as described above.                                          |
; - Once the PLM is collected, the upgrade is effective and cannot be desactivated anymore.                           |
;                                                            |
; Warning:                                                         |
; - This patch use free space at different places of the ROM. Be sure to check the "Free space usage" section before applying.               |
;                                                            |
; How to install ?:                                                      |
; - Read info, control free space usage and apply the patch "Subroutine_Array_v.1.00.asm" prior to this patch, but ...                  |
;   "Subroutine array" is a prerequisite for several patches by BigDomino. It should only be applied ONCE to your hack and never again !          |
;   If you alrerady have applied "Subroutine array" for another BigDomino patch, it's done ! Go to the next step.                  |
;   Don't apply it again since it would reset some pointers, making older patches ineffectives.                           |
; - Control free space usage for the present patch (see below).                                       |
; - Apply this ASM patch (Shinespark-Restart_Main_Code_v.1.00.asm).                                    |
; - Read info, control free space usage and apply the patch "Shinespark-Restart_Item_PLM_v.1.00.asm".                        |
; - Read info, control free space usage and apply the patch "Shinespark-Restart_Message-Box_v.1.00.asm".                     |
; - Done.                                                         |
;                                                            |
; How to use in a room ? (Smile 2.5):                                                |
; - Put item PLM F170 in a room (ie: the better would be a room accesible only once speed booster item had been collected).               |
; - Set the slopes in your hack by following the schema at the very bottom of this document (see below).                     |
;                                                            |
;------------------------------------------------------------------------------------------------------------------------------------------------------------   *
;                                                            |
; Free space usage:                                                      |
; - Free space used by this patch can be set at the user's will ; The default ranges are:                           |
;                                                            |
;  LoROM $B8:B5A0 to $B8:B69C (inclusive) ie PC $1C:35A0

BigDomino

UNDERWATER DAMAGE :

VIDEO

Part 1/2
[spoiler=ASM+Description];------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; UNDERWATER DAMAGE ASM  [Filename: Underwater_Damage_v.1.00.asm] (version 1.00 ; October 2018) |
; ===================== |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; What do this ASM ? |
; - It makes Samus unable to breath underwater if Gravity suit is not equiped. |
; - This ASM dealt periodic damage to Samus ; The interval between damages decrease after each damage, pointing out the emergency of the situation. |
; - After a certain amount of cycles, Samus will die if she doesnt find a way to breath (ie: finding air reserve underwater or going out of the water). |
; - However, if she find a way to breath, all the damages dealt while underwater (and due to being in water) are fully restored. |
; |
; - This ASM come with a new Block called "Breathable block". |
;   Touching this block allow Samus to breath as if she was out of water. These blocks can be dispatched at strategic places during a long trek underwater.  |
; |
; - Other infos: This ASM disable bubble sound and breathing animation when Samus is underwater and cannot breath. |
;   Red glowing flashes punctuates each damages dealt to Samus while a creepy red coloration grow over time... |
;   A distinctive sound is played when Samus is finaly able to catch her breath and is refilled. Then, the color gradually come back to normal. |
;   When touching a Breathable block, bubble animation and sound are enabled again. |
; |
; - Technical infos: This ASM deal damages only if Samus is fully immersed in water (ie: the top of her Hitbox is lower than the water surface). |
;   This ASM do nothing when the "fake water effect" (aka: FX1 "C" bitflag: BG warp line shift) is used in the room.  |
; |
; - As long as this ASM is called via the FX2 pointer of a room, it is possible to apply it only in specifics rooms (f.ex.: where water is "special"...) |
;   without affecting the other rooms. |
; |
; - In order to perfect the feature described above, a new enemy (F860) should be installed via the patch "Bubble_Enemy_v.1.0.asm". |
;   This enemy display a 15 frames animation of air bubbles arising from the ground. It should be put over the breathable blocks, at ground level. |
;   This animation notify the player that he will be able to catch his breath there. |
;   After installing the present patch, follow instructions in "Bubble_Enemy_v.1.0.asm" to implement this new enemy. |
; |
; How to install ?: |
; - Control free space usage and variables for the present patch (see below). |
; - Apply this ASM patch (Underwater_Damage_v.1.00.asm). |
; - Read info, control free space usage and apply the patch "Bubble_Enemy_v.1.0.asm". |
; - Done. |
; |
; How to use in a room ? (Smile 2.5): |
; - In a water room, set the FX2 pointer to $8F:D24D. |
; - In the FX1 editor, set palette blend value to EA. |
; - If needed, put "breathable blocks" at some places to let Samus catch her breath : Use "air fool X-ray" with a BTS of "0A" |
; - If so, put new enemies F860 over the breathable blocks for the bubbles animation. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Notation: |
; - The [!] marks (in the right margin) point out values / data / addresses that can be changed by the user ( -> several places in this doc). |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Free space usage: |
; - Free space used by this patch can be set at the user's will ; The default ranges are: |
; |
;   LoROM $8F:D24D to $8F:D251 (inclusive) ie: PC $07:D24D to $07:D251 (inclusive). [lenght: $   5 bytes]  \ |
;   LoROM $B8:B200 to $B8:B43D (inclusive) ie: PC $1c:3200 to $1C:343D (inclusive). [lenght: $ 23E bytes]   } -> [Total amount of free space used: $ 24C bytes] |
;   LoROM $94:B220 to $94:B228 (inclusive) ie: PC $0A:3220 to $0A:3228 (inclusive). [lenght: $   9 bytes]  / |
; |
; - If there is data in your ROM at these places, you need to relocate the code of this ASM before applying (see below). |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Data modification: |
; - Some data are changed at the folowing ranges in the ROM: |
; |
;   LoROM $8A:9080 to $8A:90BF (inclusive) ie: PC $05:1080 to $05:10BF (inclusive). [lenght: $  40 bytes] |
;   LoROM $90:8156 to $90:815B (inclusive) ie: PC $08:0156 to $08:015B (inclusive). [lenght: $   6 bytes] |
; |
; - If you have already used these addresses to create HiJack point or other stuff for your hack, you shouldn't apply this patch... |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Pointer redirection: |
; - A pointer is changed to lead to a new address: |
; |
;   LoROM $94:98C0 to $94:98C1 (inclusive) ie: PC $0A:18C0 to $0A:18C1 (inclusive). [lenght: $   2 bytes] |
; |
; - If you have already redirected this pointer (Air fool x-ray block with BTS 0A) you need to use another value. |
;   Other BTS values are suggested in this patch (see below) with the corresponding addresses. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; RAM usage: |
; - For the differents counters and flags, this patch use several free RAM addresses : |
; |
;   RAM $7E:FA04 to 7E:FA05 (inclusive). [lenght: $ 2 bytes] ; used for the "Main water counter". |
;   RAM $7E:FA06 to 7E:FA07 (inclusive). [lenght: $ 2 bytes] ; used for the "Water Damage Counter". |
;   RAM $7E:FA08 to 7E:FA09 (inclusive). [lenght: $ 2 bytes] ; used for the "Color Glow Counter". |
;   RAM $7E:FA0A to 7E:FA0B (inclusive). [lenght: $ 2 bytes] ; used for the "Refill Delay Counter". |
;   RAM $7E:FA0E to 7E:FA0F (inclusive). [lenght: $ 2 bytes] ; used for the "Breathable Flag". |
; |
; - If another patch/code who use the same addresses is intended to RUN* at the same time than this patch in a room, you need to change the addresses above to |
;   other unused one (there is plenty : for example, from 7E:FA10 to 7E:FFFF). |
;   However, don't use RAM addresses in bank $7F ( -> 7F:XXXX) ; They are not handled by the code of this ASM. |
;   * NB: The ASM code of this patch run only when called via the FX2 pointer of a given room ; When this ASM is not running, the RAM addresses are available |
;     for other usage. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Credits: |
; I was able to make this patch thanks to documents and informations found on Metconst / SMW Central / Romhacking.net / jathys.zophar.net / 6502.org, |
; from the following persons: |
; - Kejardon (Block inside reaction dissasembly / Random Routines / RAM map). |
; - Scyzer (RAM Map / ASM lessons). |
; - P.JBoy ("code that handle FX1 header" seen on metconst forum and containing FX3 palette RAM address). |
; - Black falcon / Begrimed (HEX tweek to modify FX1 water tilemap to remove the uncolored line at the surface). |
; - Western Design Center (Programming the 65c816). |
; - Bruce Clark (65C816 Opcodes at http://www.6502.org/tutorials/65c816opcodes.html) |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Patch Created by BigDomino. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

lorom

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ Set the variables below at your own will ] |

!HPWaterDamage = #$0019 ; Set the amount of damage that will be applied to Samus each time the "Main Water Counter" has reached his max value. | [!]

!MaxDamageCounter = #$0014 ; Set how many time damages will be dealt to Samus before the mortal damage is applied (min = #$0000 ; max = #$0014) | [!]
; Nota: If set to #$0000, Samus will die quickly, just after one cycle of the "Main Water Counter"... ; Setting the |
; value above #$0014 will cause an overflow of the "duration table", leading to read some random data after it and use  |
; it as durations for the "dealing damage routine"... pretty bad idea. |

; Set the interval between periodic damages : |
; Interval is intended to decrease after each damage. |
; In this example: Base = 20 seconds then, [20 second / n] where "n" is the nb. of damage already dealt + 1. |
; The delays in this table could be modified at your own will. |
!MaxStep01 = #$04B0 ; 20 seconds    = 1200 frames = $#4B0 frames | [!]
!MaxStep02 = #$0258 ; 20 seconds/2  =  600 frames = $#258 frames | [!]
!MaxStep03 = #$0190 ; 20 seconds/3  =  400 frames = $#190 frames | [!]
!MaxStep04 = #$012C ; 20 seconds/4  =  300 frames = $#12C frames | [!]
!MaxStep05 = #$00F0 ; 20 seconds/5  =  240 frames =  $#F0 frames | [!]
!MaxStep06 = #$00C8 ; 20 seconds/6  =  200 frames =  $#C8 frames | [!]
!MaxStep07 = #$00AB ; 20 seconds/7  =  171 frames =  $#AB frames | [!]
!MaxStep08 = #$0096 ; 20 seconds/8  =  150 frames =  $#96 frames | [!]
!MaxStep09 = #$0085 ; 20 seconds/9  =  133 frames =  $#85 frames | [!]
!MaxStep0A = #$0078 ; 20 seconds/10 =  120 frames =  $#78 frames | [!]
!MaxStep0B = #$006D ; 20 seconds/11 =  109 frames =  $#6D frames | [!]
!MaxStep0C = #$0064 ; 20 seconds/12 =  100 frames =  $#64 frames | [!]
!MaxStep0D = #$005C ; 20 seconds/13 =   92 frames =  $#5C frames | [!]
!MaxStep0E = #$0055 ; 20 seconds/14 =   85 frames =  $#55 frames | [!]
!MaxStep0F = #$0050 ; 20 seconds/15 =   80 frames =  $#50 frames | [!]
!MaxStep10 = #$004B ; 20 seconds/16 =   75 frames =  $#4B frames | [!]
!MaxStep11 = #$0046 ; 20 seconds/17 =   70 frames =  $#46 frames | [!]
!MaxStep12 = #$0042 ; 20 seconds/18 =   66 frames =  $#42 frames | [!]
!MaxStep13 = #$003F ; 20 seconds/19 =   63 frames =  $#3F frames | [!]
!MaxStep14 = #$003C ; 20 seconds/20 =   60 frames =  $#3C frames | [!]
; + Three mandatory last hits of 30 frames each, to inform the player he is about to die. |
; + 10 frames before die to let the last damage sound occure. |
;   NB: These three hits apply even if max is set to 0 hits. |

!RefillDelay = #$000A ; Set the delay (in frame) to wait between each HP refill if Samus is no more in water. | [!]

; Set your standard FX1 colors for "water rooms" when no special color effect is apllied: |
!ColorWaterLines = #$0C62 ; Original FX3 color (water lines pattern) | [!]
!ColorWaterBG = #$0000 ; Original FX3 color (water background) | [!]
!ColorAthmosphere = #$0000 ; Original FX3 color (athmosphere) Nota: If you are accustomed to Palette blend EA, maybe you want a value of #$0400... | [!]

!RefillSound = #$0023 ; Change the sound sample used when Samus can breath again (possible values: 00 to 7F) ; Above 7F, game will crash. | [!]

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; -> This ASM patch can be applied many time succesively to test and find the optimal settings for your hack. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ If you already use these RAM addresses for other patches, be sure to relocate them to unused places in RAM ] |

!MainWaterCounter = $7EFA04 ; Custom RAM address for the "Main water counter". | [!]
!WaterDamageCounter = $7EFA06 ; Custom RAM address for the "Water Damage Counter". | [!]
!BreathableFlag = $7EFA0E ; Custom RAM address for the "Breathable Flag". | [!]
!RefillDelayCounter = $7EFA0A ; Custom RAM address for the "Refill Delay Counter". | [!]
!ColorGlowCounter = $7EFA08 ; Custom RAM address for the "Color Glow Counter". | [!]

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; START OF THIS ASM IN BANK $8F (JUMP TO ANOTHER BANK) |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

org $8FD24D ; Free space in bank $8F to put the Jump to Subroutine Long instruction. | [!]
; This address could be freely modified to match free space anywere in bank 8F. |
; The short address (D24D in this case) should be used as a FX2 pointer in any room where the effect is needed. |
; (Lenght of the following code is #$5 bytes) |

JSL $B8B200 ; To avoid taking to much space in bank 8F, jump to $B8:B200 (lorom) ie $1C:3200 (pc). | [!]
RTS ; After all is done, return to main subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; MAIN ASM CODE START HERE : (other settings need to be checked for the custom "Breathable block" at the end of this document !) |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

org $B8B200 ; Free space in any bank where the main ASM code, the delay table & the 3 colors tables will be located. | [!]
; If you need to change this address, don't forget to change the address in the JSL instruction 2 lines above |
; accordingly.  Appart from that, this code is not bank dependant and could be placed anywere in your ROM. |
; (Lenght of the following code, including table, is #$23E bytes) |

; [ a: Set processor in 16 bit mode ] |
CLC ; Clear carry flag, then... |
XCE ; ... exchange carry with e bit to set the processor in native mode (16 bit). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ b: Set the correct bank to run this asm ] |
SEP #$20 ; Set accumulator size to 8 bit. |
LDA #$7E ; Load #7E value (new bank) into the accumulator. |
PHA ; Push that value into the stack. |
PLB ; Pull that value from the stack into the Data Bank Register. |
REP #$20 ; Set accumulator size to 16 bit. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ c: Clear "Main water counter" if there is random data at that place ] |
LDA !MainWaterCounter ; Load value stored at custom RAM address $7E:FA04 (ie: "Main water counter"). |
CLC ; Clear carry flag. |
CMP !MaxStep01+1 ; Compare the current value of "Main water counter" (in accumulator) to the max value according to the table above + 1. |
BCC CLEAR_WDC ; If the value NOT greater than the max value allowed, branch to the next step, otherwise ... |
STZ !MainWaterCounter ; ... this is more liklely random data that need to be cleared, so store zero to that address (in bank $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CLEAR_WDC: ; [ d: Clear "Water damage counter" if there is random data at that place ] |
LDA !WaterDamageCounter ; Load value stored at custom RAM address $7E:FA06 (ie: "Water damage counter"). |
CLC ; Clear carry flag. |
CMP #$0018 ; Compare to max possible value allowed + 3 hits + 1. |
BCC CLEAR_BF ; If the value is NOT greater than the max value allowed, branch to the next step, otherwise ... |
STZ !WaterDamageCounter ; ... this is more liklely random data that need to be cleared, so store zero to that address (in bank $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CLEAR_BF: ; [ e: Clear "Breathable flag" if there is random data at that place ] |
LDA !BreathableFlag ; Load value stored at custom RAM address $7E:FA0E (ie: "Breathable flag"). |
CLC ; Clear carry flag. |
CMP #$0001+1 ; Compare to max value allowed + 1. |
BCC CLEAR_RDC ; If the value is NOT greater than the max value allowed, branch to the next step, otherwise ... |
STZ !BreathableFlag ; ... this is more liklely random data that need to be cleared, so store zero to that address (in bank $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CLEAR_RDC: ; [ f: Clear "Refill delay counter" if there is random data at that place ] |
LDA !RefillDelayCounter ; Load value stored at custom RAM address $7E:FA0A (ie: "Refill delay counter"). |
CLC ; Clear carry flag. |
CMP !RefillDelay+1 ; Compare to max value allowed + 1. |
BCC CLEAR_CGC ; If the value is NOT greater than the max value allowed, branch to the next step, otherwise ... |
STZ !RefillDelayCounter ; ... this is more liklely random data that need to be cleared, so store zero to that address (in bank $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CLEAR_CGC: ; [ g: Clear "Color glow counter" if there is random data at that place ] |
LDA !ColorGlowCounter ; Load value stored at custom RAM address $7E:FA08 (ie: "Color Glow Counter"). |
CLC ; Clear carry flag. |
CMP #$000C+1 ; Compare to max value allowed + 1. |
BCC CHECK_GAME_CONDITIONS ; If the value is NOT greater than the max value allowed, branch to the next step, otherwise ... |
STZ !RefillDelayCounter ; ... this is more liklely random data that need to be cleared, so store zero to that address (in bank $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CHECK_GAME_CONDITIONS: ; [ A1: Check if there is water in room ] |
LDA $7E196E ; Load the value stored at RAM address $7E:196E (type of FX1 effect) in the accumulator. |
CMP #$0006 ; Check if water is used in this room (0006). |
BNE EXTENSION_REFILL_DAMAGE ; If it's not the case (ie: no [or no more] water in room), branch to "EXTENSION_REFILL_DAMAGE", otherwise ... |

; [ A2: Check if fake water effect is activated (aka FX1 "C" bitflag: BG warp line shift) ] |
LDA $7E197E ; Load the value stored at RAM address $7E:197E (FX1 "C" bitflag) in the accumulator. |
AND #$0004 ; Check if "BG warp line shift" bit is NOT set (% 00000100 or $ 0004). |
BNE EXTENSION_REFILL_DAMAGE ; If it's not the case (ie: the bit is set), branch to "EXTENSION_REFILL_DAMAGE", otherwise ... |

; [ A3: Check if gravity-suit is equiped ] |
LDA $7E09A2   ; Load equiped items bytes from RAM address $7E:09A2 in the accumulator. |
AND #$0020      ; Check if gravity-suit bit ($ 0020 ) is NOT set. |
BNE EXTENSION_REFILL_DAMAGE ; If it's not the case (ie: gravity-suit is equiped), branch to "EXTENSION_REFILL_DAMAGE", otherwise ... |

; [ A4: Check if "Breathable block flag" is set ] |
; (the flag is set by touching Air fool X-ray with BTS = 0A). |
LDA !BreathableFlag ; Load the value stored at custom RAM address $7E:FA0E (breathable flag) in the accumulator. |
CMP #$0001 ; Check if "Breathable block flag" is set (0001 could be set by the block routine ; see below). |
BEQ EXTENSION_REFILL_DAMAGE ; If it's the case (ie: Samus touches such a block), branch to "REFILL_DAMAGE", otherwise ... |

; [ A5: Get the coordinate of Samus hitbox top border ] |
LDA $7E0AFA ; Load Samus vertical coordinate from RAM address $7E:0AFA in the accumulator. |
; Nota: This value count the distance (in pixel) between the top of the room and the center of Samus hitbox. |
SEC ; Set carry flag to prevent miscalculation in the subtraction that follow. |
SBC $7E0B00 ; Subtract from the actual value in accumulator the value stored at RAM address 7E:0B00 (Samus vertical radius). |
; Now, we have the vertical coordinate of the top border of Samus hitbox, counted from the ceiling. |

; [ A6: Check if Samus is underwater ] |
CLC ; Clear carry flag, then... |
CMP $7E195E ; Compare the previous value (still in accumulator) to the one stored at RAM address 7E:195E (Current liquid height). |
BCC REFILL_DAMAGE ; If distance from ceiling of Samus top border is less than the distance from ceilling of the liquid surface, Samus |
; is not underwater, so, Branch to "REFILL_DAMAGE", otherwise ... |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CHECK_IF_GLOW: ; [ B: Before launching the static special FX1 color code, check if a glowing effect need to be executed ] |
LDA !ColorGlowCounter ; Check the actual value stored at custom RAM address $7EFA08 (ie: "Color Glow Counter") |
CMP #$0000 ; Compare with #$0000 (ie: no glow effect needed) |
BNE EXTENSION_SET_GLOW ; If glow is needed, branch to "EXTENSION_SET_GLOW" subroutine (who lead to glowing color routine), otherwise ... |
JSR PREVENT_COLOR_OVERFLOW ; Jump to the Static color subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ C: Starting the "Main water counter" ] |
STZ !RefillDelayCounter ; Because Samus is now underwater, store zero at custom RAM address 7E:FA0A to reset the *Refill delay counter" in case |
; there is still some residual value from a previous (and aborted) refill operation. |
LDA !WaterDamageCounter ; Load current value of the "Water damage counter" at custom RAM address 7E:FA06 to use it as an index to get the |
; right value in the "duration table". |
ASL A ; Multiply by 2 the value in accumulator to match the word-long entries of duration table. |
TAX ; Transfer accumulator to X index register. |
INC !MainWaterCounter ; Increment "Main water counter" at custom RAM address 7E:FA04 ... (assume bank to use is $7E) |
LDA !MainWaterCounter ; ... and load that value to the accumulator. |
CMP MAX_DURATION_TABLE, X ; Compare the current value of "Main water counter" (in accumulator) to the max value according to the table below. |
BEQ CHECK_MAX_DAMAGE ; If current value of "Main water counter" is equal to max value, branch "CHECK_MAX_DAMAGE", otherwise ... |
CLC ; Clear carry flag. |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

EXTENSION_REFILL_DAMAGE: ; [ D: To circumvent the annoying +129 byte / -126 limitation of BEQ / BNE / BCS / BCC / BRA ! ] |
BRA REFILL_DAMAGE ; Branch to the "REFILL_DAMAGE" subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

EXTENSION_SET_GLOW: ; [ E: To circumvent the annoying +129 byte / -126 limitation of BEQ / BNE / BCS / BCC / BRA ! ] |
JMP SET_GLOW_COLORS ; Branch to the "SET_GLOW_COLORS" subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CHECK_MAX_DAMAGE: ; [ F1: Reset the "Main water counter" & check if "Water damage counter" is already maxed ] |
STZ !MainWaterCounter ; Store zero at custom RAM address 7E:FA04 to reset the "Main water counter" (assume bank to use is $7E). |
LDA !WaterDamageCounter ; Load current value of the "Water damage counter" at custom RAM address 7E:FA06 in the accumulator and ... |
CLC ; Clear carry flag. |
CMP !MaxDamageCounter ; ... compare it to #$14 (decimal 20) wich is the max value within the customisable range. |
BCC DEAL_DAMAGE_TO_SAMUS ; If max value is not reached, branch "DEAL_DAMAGE_TO_SAMUS", otherwise ... |

; [ F2: Check if "Water damage counter" top most value is already maxed ] |
CMP #$0017 ; ... compare it to #$14 + 3 (decimal 23) wich is the utter max value for avoiding overflow of the table. |
BEQ KILL_SAMUS ; If utter max value is reached, branch "KILL_SAMUS", otherwise ... |

; [ F3: Check if the "three last hits" process is launched ] |
CLC ; Clear carry flag. |
CMP #$0015 ; ... compare it to #$15 wich is the second step of the three last manatory hit. |
BCS DEAL_DAMAGE_TO_SAMUS ; If WDC value is equal or greater than 15 (but less than 17, see above) the three last hits process is launched. |
; Branch to "DEAL_DAMAGE_TO_SAMUS"to finalize the process (1 or 2 hits remainings), otherwise ... |

; [ F4: Cheat the Water Damage Counter to make the code think it's the 14th damage ] |
; So, the WDC as already reached the max value defined by the user. Now it's time to fake the counter to ask the code |
; to act as if the step #14 was reached ! (the final three last hits will be dealt to Samus). |
LDA #$0014 ; Load #$0014 in accumulator and ... |
STA !WaterDamageCounter ; ... store that value in the "Water Damage Counter", then ... |
BRA DEAL_DAMAGE_TO_SAMUS ; ... branch the "DEAL_DAMAGE_TO_SAMUS" subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

KILL_SAMUS: ; [ G: Kill Samus (0_o) ] |
STZ $7E09C2 ; ... store that value at $7E:09C2 to kill Samus! |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

DEAL_DAMAGE_TO_SAMUS: ; [ H: Check if damages will lower Samus's HP beyond 0000 ] |
LDA $7E09C2 ; Load Samus current HP from RAM address $7E:09C2 in the accumulator. |
CLC ; Clear carry flag. |
CMP !HPWaterDamage ; Compare with the damages that will be applied. |
BCC KILL_SAMUS ; Branch the "KILL_SAMUS" routine to avoid going under 0 HP. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ I: Decrement Samus's HPs by a given number ] |
SEC ; Set carry flag to prevent miscalculation in the subtraction that follow. |
SBC !HPWaterDamage ; Subtract from the actual value in accumulator the damage value defined at the top of this ASM. |
STA $7E09C2 ; Store the value as the new current HP. |
INC !WaterDamageCounter ; Increment "Water damage counter" at custom RAM address 7E:FA06 (assume bank to use is $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ J: Set conditions to start the glowing routine next frame ] |
LDA #$000C ; Load accumulator with the total number of steps that the glowing routine will have to decrement ... |
STA !ColorGlowCounter ; ... and store that value to the "Color Glow Counter" at custom RAM address $7EFA08 |
CLC ; Clear carry flag. |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

REFILL_DAMAGE: ; [ K: Reset Breathable block flag & Main Water Counter ] |
STZ !BreathableFlag ; ... Store that value at RAM address $7E:FA0E to clear the "Breathable block flag" ; This flag will be set back next |
; frame if Samus is still inside the block (assume bank to use is $7E). |
STZ !MainWaterCounter ; ... Store that value at custom RAM address 7E:FA04 to reset the "Main water counter" (assume bank to use is $7E). |
STZ !ColorGlowCounter ; ... Store that value at custom RAM address 7E:FA08 to reset the "Color glow counter" (assume bank to use is $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ L: Check if there is damage to be refilled ] |
LDA !WaterDamageCounter ; Load current value of the "Water damage counter" at custom RAM address 7E:FA06 in the accumulator and ... |
CMP #$0000 ; ... compare it to #$0000 to check if a) there was no damage to refill or b) all the damages were already refilled. |
BEQ END ; If no damage, branch END (RTL), otherwise ... |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ M: Check if refill delay is reached. If not, increment it ] |
LDA !RefillDelayCounter ; Load current value of the "Refill delay counter" at custom RAM address 7E:FA0A in the accumulator and ... |
CMP !RefillDelay ; ... compare it to the delay to refill. |
BEQ REFILL_NOW ; If delay is reached, branch "REFILL_NOW", otherwise ... |
INC !RefillDelayCounter ; ... increment by 1 the "Refill delay counter" (assume bank to use is $7E). |
CLC ; Clear carry flag. |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

REFILL_NOW: ; [ N: Reset the refill delay counter and check if Samus is at max HP ] |
STZ !RefillDelayCounter ; Store zero at custom RAM address 7E:FA0A to reset the "Refill delay counter" (assume bank to use is $7E). |
LDA $7E09C2 ; Load Samus current HP from RAM address $7E:09C2 in the accumulator. |
CMP $7E09C4 ; Compare this value to Samus Max HPs at RAM address $7E:09C4. |
BEQ END ; If these values are equal, branch END. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ O: Check if refill will overflow max HPs ] |
CLC ; Clear carry flag to prevent miscalculation in the addition that follow. |
ADC !HPWaterDamage ; Add to the actual value in accumulator the damage value defined at the top of this ASM. |
CLC ; Clear carry flag. |
CMP $7E09C4 ; Compare this value to Samus Max HPs at RAM address $7E:09C4. |
BCS REFILL_MAX_HP ; If potential current HP exceed (or is equal to) max HPs limit, branch "REFILL_MAX_HP", otherwise ... |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ P: Refill Samus with the "Stolen" HP according to the Water damage counter ] |
STA $7E09C2 ; store the new calculated HP value to the current HP RAM address $7E:09C2. |
DEC !WaterDamageCounter ; Decrement by 1 the "Water damage counter" at custom RAM address 7E:FA06 (assume bank to use is $7E). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ Q: Play a Sound FX ] |
LDA !RefillSound ; Load Sound sample number #0023 of library 2 in accumulator. |
JSL $8090C1 ; Jump long to the sound FX subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ R: Set back FX1 color to standard ] |
JSR PREVENT_COLOR_OVERFLOW ; Jump to the changing color subroutine. |
CLC ; Clear carry flag. |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

REFILL_MAX_HP: ; [ S: Refill Samus to her max HP ] |
LDA $7E09C4 ; Load Samus max HP from RAM address $7E:09C4 in the accumulator. |
STA $7E09C2 ; Store max HP value into current HP value at RAM address $7E:09C2. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

END: ; [ T: Reset Water Damage Counter ] |
STZ !WaterDamageCounter ; ... Store that value at custom RAM address 7E:FA06 to reset the "Water damage counter". |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ U: Set back FX1 color to standard (bis) ] |
JSR SET_BACK_COLORS ; Jump to the restore color subroutine. |
CLC ; Clear carry flag. |
RTL ; Return from subroutine long. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

MAX_DURATION_TABLE: ; [ V: Table of delay between each "underwater damages" ] |

dw !MaxStep01 ; 20 seconds    = 1200 frames = $#4B0 frames |
dw !MaxStep02 ; 20 seconds/2  = 600 frames  = $#258 frames |
dw !MaxStep03 ; 20 seconds/3  = 400 frames  = $#190 frames |
dw !MaxStep04 ; 20 seconds/4  = 300 frames  = $#12C frames |
dw !MaxStep05 ; 20 seconds/5  = 240 frames  =  $#F0 frames |
dw !MaxStep06 ; 20 seconds/6  = 200 frames  =  $#C8 frames |
dw !MaxStep07 ; 20 seconds/7  = 171 frames  =  $#AB frames |
dw !MaxStep08 ; 20 seconds/8  = 150 frames  =  $#96 frames |
dw !MaxStep09 ; 20 seconds/9  = 133 frames  =  $#85 frames |
dw !MaxStep0A ; 20 seconds/10 = 120 frames  =  $#78 frames |
dw !MaxStep0B ; 20 seconds/11 = 109 frames  =  $#6D frames |
dw !MaxStep0C ; 20 seconds/12 = 100 frames  =  $#64 frames |
dw !MaxStep0D ; 20 seconds/13 =  92 frames  =  $#5C frames |
dw !MaxStep0E ; 20 seconds/14 =  85 frames  =  $#55 frames |
dw !MaxStep0F ; 20 seconds/15 =  80 frames  =  $#50 frames |
dw !MaxStep10 ; 20 seconds/16 =  75 frames  =  $#4B frames |
dw !MaxStep11 ; 20 seconds/17 =  70 frames  =  $#46 frames |
dw !MaxStep12 ; 20 seconds/18 =  66 frames  =  $#42 frames |
dw !MaxStep13 ; 20 seconds/19 =  63 frames  =  $#3F frames |
dw !MaxStep14 ; 20 seconds/20 =  60 frames  =  $#3C frames |
dw #$002F ; 1st of the 3 final hits ! |
dw #$002F ; 2nd of the 3 final hits ! |
dw #$002F ; 3rd of the 3 final hits ! |
dw #$001F ; End of table (death) |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

SET_GLOW_COLORS: ; [ W: Glow color routine that runs every time Samus experiences water damage ] |
LDA #$000C ; Load max possible value of the "Color Glow Counter" in accumulator. |
SEC ; Set carry flag to prevent miscalculation in the subtraction that follow. |
SBC !ColorGlowCounter ; Subtract current value from max value to invert the "countdown" to a "counter". |
ASL A ; Multiply by 2 the value in accumulator to match the word-long entries of colors table. |
TAX ; Transfer accumulator to X index register. |
LDA LINES_COLORS_TABLE, X ; Load color from LINES_COLORS_TABLE at the indexed address and ... |
STA $7EC032 ; ... store it in RAM address $7E:C032 (water lines pattern color). |
LDA WATER_BG_COLORS_TABLE, X ; Load color from WATER_BG_COLORS_TABLE at the indexed address and ... |
STA $7EC034 ; ... store it in RAM address $7E:C034 (water background color). |
LDA ATHMOSPHERE_COLORS_TABLE, X ; Load color from ATHMOSPHERE_COLORS_TABLE at the indexed address and ... |
STA $7EC036 ; ... store it in RAM address $7E:C036 (athmosphere color). |
DEC !ColorGlowCounter ; Then, decrement the Color glow counter. |
RTL ; Return from subroutine < LONG > to make this step becoming a loop! |
; (ie: The SET_GLOW_COLORS routine need to deplete the"Color glow counter" entirely before the next steps). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

SET_BACK_COLORS: ; [ X: Set back colors to the original value (when Samus is out of water or is perfectly healed) ] |
LDA !ColorWaterLines ; Load original FX3 color (water lines pattern) into accumulator and ... |
STA $7EC032 ; ... store it as current FX3 color. |
LDA !ColorWaterBG ; Load original FX3 color (water background) into accumulator and ... |
STA $7EC034 ; ... store it as current FX3 color. |
LDA !ColorAthmosphere ; Load original FX3 color (athmosphere) into accumulator and ... |
STA $7EC036 ; ... store it as current FX3 color. |
RTS ; Return from subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *


PREVENT_COLOR_OVERFLOW: ; [ Y: Before overflow control, check if a special color need to be applied ] |
LDA !WaterDamageCounter ; Load current value of the "Water damage counter" at custom RAM address 7E:FA06 to use it as an index to get the |
; right value in the "color table". |
CMP #$0000 ; Compare value to #$0000 (ie: no damage). |
BEQ SET_BACK_COLORS ; If current value of the "Water damage counter" is equal to zero, branch "SET_BACK_COLORS", otherwise ... |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; [ Z: Check if Water Damage counter overflow the several color tables] |
CMP #$0009 ; Compare value to the number of entries of the colors table + 1. |
BCC LOAD_COLORS ; If current value in "Water damage counter" is less than 0009, branch "LOAD_COLORS", otherwise ... |
LDA #$0008 ; ... if value is greater or equal to 0009, reduce it to 0008 (ie: no color progression above step 0008). |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

LOAD_COLORS: ; [ AA: Change FX3 color according to the water damagecounter] |
DEC ; Decrease accumulator by 1 because first color line need an index of 0, not 1. |
ASL A ; Multiply by 2 the value in accumulator to match the word-long entries of colors tables. |
TAX ; Transfer accumulator to X index register. |
LDA LINES_COLORS_TABLE, X ; Load color from LINES_COLORS_TABLE at the indexed address and ... |
STA $7EC032 ; ... store it in RAM address $7E:C032 (water lines pattern color). |
LDA WATER_BG_COLORS_TABLE, X ; Load color from WATER_BG_COLORS_TABLE at the indexed address and ... |
STA $7EC034 ; ... store it in RAM address $7E:C034 (water background color). |
LDA ATHMOSPHERE_COLORS_TABLE, X ; Load color from ATHMOSPHERE_COLORS_TABLE at the indexed address and ... |
STA $7EC036 ; ... store it in RAM address $7E:C036 (athmosphere color). |
RTS ; Return from subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

LINES_COLORS_TABLE: ; [ AB: Table of colors for the Water lines pattern, according to "underwater damages" ] |

; WDC_COLOR_1: ; Colors 1 to 8 are for the static & glowing colors. |
dw #$0004 ; Water lines color step 1 |
; WDC_COLOR_2: ; |
dw #$0005 ; Water lines color step 2 |
; WDC_COLOR_3: ; |
dw #$0006 ; Water lines color step 3 |
; WDC_COLOR_4: ; |
dw #$0007 ; Water lines color step 4 |
; WDC_COLOR_5: ; |
dw #$0008 ; Water lines color step 5 |
; WDC_COLOR_6: ; |
dw #$0009 ; Water lines color step 6 |
; WDC_COLOR_7: ; |
dw #$000A ; Water lines color step 7 |
; WDC_COLOR_8: ; |
dw #$000B ; Water lines color step 8 |
;---------------------------------------; |
; COLOR_9: ; Colors 9 to C are only used for glowing colors. |
dw #$000C ; Water lines color step 9 |
; COLOR_A: ; |
dw #$000D ; Water lines color step A |
; COLOR_B: ; |
dw #$000E ; Water lines color step B |
; COLOR_C: ; |
dw #$000F ; Water lines color step C |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

WATER_BG_COLORS_TABLE: ; [ AC: Table of colors for the water background, according to "underwater damages" ] |

; WDC_COLOR_1: ; Colors 1 to 8 are for the static & glowing colors. |
dw #$0002 ; Water background color step 1 |
; WDC_COLOR_2: ; |
dw #$0003 ; Water background color step 2 |
; WDC_COLOR_3: ; |
dw #$0004 ; Water background color step 3 |
; WDC_COLOR_4: ; |
dw #$0005 ; Water background color step 4 |
; WDC_COLOR_5: ; |
dw #$0006 ; Water background color step 5 |
; WDC_COLOR_6: ; |
dw #$0007 ; Water background color step 6 |
; WDC_COLOR_7: ; |
dw #$0008 ; Water background color step 7 |
; WDC_COLOR_8: ; |
dw #$0009 ; Water background color step 8 |
;---------------------------------------; |
; COLOR_9: ; Colors 9 to C are only used for glowing colors. |
dw #$000A ; Water background color step 9 |
; COLOR_A: ; |
dw #$000B ; Water background color step A |
; COLOR_B: ; |
dw #$000C ; Water background color step B |
; COLOR_C: ; |
dw #$000D ; Water background color step C |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

ATHMOSPHERE_COLORS_TABLE: ; [ AD: Table of colors for the athmosphere, according to "underwater damages" ] |

; WDC_COLOR_1: ; Colors 1 to 8 are for the static & glowing colors. |
dw #$0001 ; Athmosphere color step 1 |
; WDC_COLOR_2: ; |
dw #$0002 ; Athmosphere color step 2 |
; WDC_COLOR_3: ; |
dw #$0003 ; Athmosphere color step 3 |
; WDC_COLOR_4: ; |
dw #$0004 ; Athmosphere color step 4 |
; WDC_COLOR_5: ; |
dw #$0005 ; Athmosphere color step 5 |
; WDC_COLOR_6: ; |
dw #$0006 ; Athmosphere color step 6 |
; WDC_COLOR_7: ; |
dw #$0007 ; Athmosphere color step 7 |
; WDC_COLOR_8: ; |
dw #$0008 ; Athmosphere color step 8 |
;---------------------------------------; |
; COLOR_9: ; Colors 9 to C are only used for glowing colors. |
dw #$0009 ; Athmosphere color step 9 |
; COLOR_A: ; |
dw #$000A ; Athmosphere color step A |
; COLOR_B: ; |
dw #$000B ; Athmosphere color step B |
; COLOR_C: ; |
dw #$000C ; Athmosphere color step C |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

CHECK_BUBBLE_SOUND: ; [ AE: Check if bubble sound is allowed ] |
LDA !MainWaterCounter ; Load value of the "Main water counter" in accumulator ... |
CMP #$0000 ; ... and compare it to zero. |
BEQ ALLOW_BUBBLE_SOUND ; If these values are equal (ie: Samus is able to breath) branch the ALLOW_BUBBLE_SOUND routine. |
JML $90818B ; If not, jump long after the bubble animation and the bubble FX routine). |

ALLOW_BUBBLE_SOUND: ; [ AF: Copy of the code that was removed to make the Hijack point, then return ] |
LDA #$0500              ; -> This is the 1st instruction that was overwrited by Hijack JMP instruction. (don't edit!) |
; ie: Load a value of #$0500 in accumulator (call bubbles GFX 1st sprite) and... |
STA $0AF0  ; -> This is the 2nd instruction that was overwrited by Hijack JMP instruction. (don't edit!) |
; ie: ... store that value at RAm address $7E:0AF0 - atmospheric GFX animation frame number 3 (of 4) |
JML $90815C ; Jump long just after the Hijack point. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; BREATHABLE BLOCK ASM CODE START HERE : |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; Air fool X-ray block is used to make the "Breathable block" : Choose a BTS value to use. |

; Nota: BTS values 00 & 02 are used and usefull in original game and souldn't be used for the new block. |
;       BTS values 0C, 0D, 0E are already used by some usefull patches made by Scyzer - Choose only if not interested by such patches |
;       BTS value 0A has been randomly choosen by me but can be changed by tweeking the ";" mark before "org" in the list below. |
; (No free space is used ; this is just an address substitution) |

;org $9498AE ; delete the ";" before "org" to use BTS = 01 instead of 0A -> $94:98AC + (2 * 01) = $94:98AE | [!]
;org $9498B2 ; delete the ";" before "org" to use BTS = 03 instead of 0A -> $94:98AC + (2 * 03) = $94:98B2 | [!]
;org $9498B4 ; delete the ";" before "org" to use BTS = 04 instead of 0A -> $94:98AC + (2 * 04) = $94:98B4 | [!]
;org $9498B6 ; delete the ";" before "org" to use BTS = 05 instead of 0A -> $94:98AC + (2 * 05) = $94:98B6 | [!]
;org $9498B8 ; delete the ";" before "org" to use BTS = 06 instead of 0A -> $94:98AC + (2 * 06) = $94:98B8 | [!]
;org $9498BA ; delete the ";" before "org" to use BTS = 07 instead of 0A -> $94:98AC + (2 * 07) = $94:98BA | [!]
;org $9498BC ; delete the ";" before "org" to use BTS = 08 instead of 0A -> $94:98AC + (2 * 08) = $94:98BC | [!]
;org $9498BE ; delete the ";" before "org" to use BTS = 09 instead of 0A -> $94:98AC + (2 * 09) = $94:98BE | [!]
org $9498C0 ; put a ";" before "org" to use another BTS value. For BTS = 0A -> $94:98AC + (2 * 0A) = $94:98C0 | [!]
;org $9498C2 ; delete the ";" before "org" to use BTS = 0B instead of 0A -> $94:98AC + (2 * 0B) = $94:98C2 | [!]
;org $9498C4 ; delete the ";" before "org" to use BTS = 0C instead of 0A -> $94:98AC + (2 * 0C) = $94:98C4 | [!]
;org $9498C6 ; delete the ";" before "org" to use BTS = 0D instead of 0A -> $94:98AC + (2 * 0D) = $94:98C6 | [!]
;org $9498C8 ; delete the ";" before "org" to use BTS = 0E instead of 0A -> $94:98AC + (2 * 0E) = $94:98C8 | [!]
;org $9498CA ; delete the ";" before "org" to use BTS = 0F instead of 0A -> $94:98AC + (2 * 0F) = $94:98CA | [!]

dw $B220 ; Write a short pointer (in bank $94) leading to the instructions for the "breathable block" (see below). | [!]

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

org $94B220 ; Free space in bank $94 where the main "Breathable block" routine will be located. | [!]
; If you need to change this address, don't forget to change the adress in the DW instruction 2 lines above accordingly.|
; (Lenght of the following code is #$9 bytes) |

; [ AG: Set the breathable block flag ] |
LDA #$0001 ; Load a value of #$0001 in accumulator and ... |
STA !BreathableFlag ; Store it at custom RAM address $7E:FA0E (breathable block flag). The flag is set. |
CLC ; Clear carry flag. |
RTS ; Return from subroutine. |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; HEX TWEAK TO REMOVE THE UGLY / GLITCHY UNCOLORED HORIZONTAL LINE ABOVE THE SURFACE OF THE WATER : |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

org $8A9080 ; FX3 Water tilemaps data (drawing the air line above the water surface) |
; (No free space is used ; this is just data modification) |

; Go to $8A:9080 (FX3 Water tilemaps) and ... |
dw #$384E ; replace 4E0C by 4E38 (reversed) |
dw #$384E ; ditto |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ... |
dw #$384E ; ditto |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; HIJACK CODE TO DISABLE THE BUBBLE SOUND FX / BUBBLE ANIMATION : |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

org $908156 ; Hijack point created at the start of bubble animation subroutine. |
; (No free space is used ; this is just data substitution). |

JML CHECK_BUBBLE_SOUND ; Jump instead to the "check bubble sound" custom routine who have a counditional branch. |
dw #$EAEA ; The JMP Instrcution above was 1 byte longer than the replaced LDA instruction and overwrited the STA that follow. |
; The STA need to be rewrited - I replace the two byte argument by EA (no operation) because there is no more opcode |
; to use these arguments... |

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
[/spoiler] (main code)

BigDomino

Part 2/2
[spoiler=ASM+Description];------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; BUBBLE ENEMY ASM  [Filename: Bubble_Enemy_v.1.00.asm] (version 1.00 ; september 2019) |
; ================ |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Description: |
; - This patch is a part of the Underwater-Damage feature. It set a new enemy (F860) that display a 15 frames animation of air bubbles arising from the ground. |
; |
; Warning: |
; - This patch use free space at different places of the ROM. Be sure to check the "Free space usage" section before applying. |
; - Only apply this patch after reading the infos in "Underwater_Damage_v.1.0.asm" file. |
; |
; How to install ?: |
; - Apply "Underwater_Damage_v.1.0.asm" patch prior to this patch and read info. |
; - Control free space usage (see below). |
; - Apply this ASM patch. |
; - Put the two files "F860.GIF" and "F860.txt" in the "enemies" folder of Smile : [ C:\ ... \Smile\files\Enemies ] |
; |
; How to use in a room ? (Smile 2.5): |
; - In a water room where "underwater damage" is activated (FX2 pointer = $8F:D24D) and where "breathable blocks" (eg. air fool X-ray BTS 0A) had been |
;   scattered at several places of the room, this enemy should be put over the blocks, at ground level. |
; - This enemy display a bubbles animation that tell the player that he will be able to catch his breath there. |
;   (NB: It's just an animation ; Air fool X-ray BTS 0A is the one that let the player breath). |
; - Settings : |
;   * Add this enemy (F860) to the "Enemies allowed" list. |
;   * Use palette index value 0001 or 0007. |
;   * Special     = 2C00 |
;   * Orientation = 0000 |
;   * Speed 2     = 0000 |
;   * Speed       = 0000 or 0001 or 0002 or 0003 |
;     "Speed" value allow to desynchronize the animations of several bubble-enemies visibles at the same time (up until 4). |
;      Every increment of this "speed" value delay the animation start by $18 frames. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Free space usage: |
; - Free space used by this patch can be set at the user's will ; The default ranges are: |
; |
;  LoROM $A0:F860 to $A0:F89F (inclusive) ie PC $10:7860 to $10:789F (inclusive). [lenght: $  40 bytes] |
;  LoROM $B3:ED80 to $B3:EE75 (inclusive) ie PC $19:ED80 to $19:EEA2 (inclusive). [lenght: $ 123 bytes] |
;  LoROM $87:EC00 to $87:F4BF (inclusive) ie PC $03:EC00 to $03:F4BF (inclusive). [lenght: $ 8C0 bytes] |
;  LoROM $87:F600 to $87:F6BF (inclusive) ie PC $03:F600 to $03:F6BF (inclusive). [lenght: $  C0 bytes] |
; |
; - If there is data in your ROM at these places, you need to relocate the code of this ASM before applying (see below). |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Credit: |
; - P.JBoy for his documentation, specifically the disassembly of banks $A0 & A1 - B3. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; |
; Patch Created by BigDomino. |
; |
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

lorom

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Defines ROM addresses :
; =======================
;
!No_Operation   = $804C ; Pointer for AI when no operation is needed (ie: point to a single RTL instruction).
;
;---------------------------------------------------------------------------------------------------------------------------- *
; Defines constants :
; ===================
;
!Enemy_Bank = #$B3 ; Bank to store init AI, animation code and tilemaps code of the new enemy.
!Enemy_Width = #$0008 ; Semi-width : from sprite's center to left/right edges.
!Enemy_Height = #$0020 ; Full height : from top to bottom.
!Gfx_Size = $0AC0 ; Size of GFX data to load in VRAM.
!Anime_Code_1    = ANIME_CODE_1 ; Word pointer for animation code 1 in bank $B3 (will be stored as a value in RAM).
!Anime_Code_2    = ANIME_CODE_2 ; Word pointer for animation code 2 in bank $B3 (will be stored as a value in RAM).
!Anime_Code_3    = ANIME_CODE_3 ; Word pointer for animation code 3 in bank $B3 (will be stored as a value in RAM).
!Anime_Code_4    = ANIME_CODE_4 ; Word pointer for animation code 4 in bank $B3 (will be stored as a value in RAM).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
org $A0F860 ; [Free space only in bank $A0]
;
; Bubble enemy header (F860) :
; ============================
;
dw !Gfx_Size ; Size of tile data.
dw PALETTE ; Palette pointer.
dw $0028 ; Health.
dw $000F ; Damage.
dw !Enemy_Width ; Width
dw !Enemy_Height ; Height
db !Enemy_Bank ; Enemy bank.
db $00 ; Hurt AI time.
dw $0059 ; Cry.
dw $0000 ; Boss value.
dw INIT_AI ; Initialisation AI pointer.
dw $0001 ; Nb of parts.
dw $0000 ; Unused.
dw !No_Operation ; Running AI.
dw !No_Operation ; Grapple AI.
dw !No_Operation ; Hurt AI.
dw !No_Operation ; Frozen AI.
dw $0000 ; X-ray AI.
dw $0000 ; Death animation.
dd $00000000 ; Unused.
dw !No_Operation ; PB reaction.
dw $0000 ; Unknow.
dd $00000000 ; Unused.
dw !No_Operation ; Enemy touch.
dw !No_Operation ; Enemy shot.
dw $0000 ; Unknow.
dl GFX ; Tile data.
db $02 ; Layer.
dw $0000 ; Drop chance.
dw $0000 ; Vulnerability.
dw $0000 ; Name.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
org $B3ED80 ; [Free space in any "enemies bank" ; bank $B3 is chosen here, arbitrarily]
;
INIT_AI: ; Initialisation AI :
; ===================
;
LDX $0E54 ; Load enemy index in X register.
;
LDA #$804D ; Load word pointer in every bank (leading to a single #$0000 value) in A.
STA $0F8E,x ; Store this address in RAM as new Hitbox pointer for curent enemy.
;
LDA #$0001 ; Load #$0001 value in A.
STA $0F94,x ; Store as instruction timer.
;
STZ $0F90,x ; Store zero in timer.
;
LDA $0FB4,x ; Load curent enemy "speed" value (cf. Smile species editor) in A.
; "Speed" value [ 0000 ; 0001 ; 0002 ; 0003 ] allow to desynchronize the animations of bubble-enemies.
;
CMP #$0003 ; Check if value = #$0003.
BEQ ANIM4 ; If so, branch animation code 4.
;
CMP #$0002 ; Check if value = #$0002.
BEQ ANIM3 ; If so, branch animation code 3.
;
CMP #$0001 ; Check if value = #$0001.
BEQ ANIM2 ; If so, branch animation code 2.
; Else...
LDA.w #!Anime_Code_1 ; Load word address of animation code 1 below (in current bank) in A (as a value).
BRA END ;
ANIM2: ;
LDA.w #!Anime_Code_2 ; Load word address of animation code 2 below (in current bank) in A (as a value).
BRA END ;
ANIM3: ;
LDA.w #!Anime_Code_3 ; Load word address of animation code 3 below (in current bank) in A (as a value).
BRA END ;
ANIM4: ;
LDA.w #!Anime_Code_4 ; Load word address of animation code 4 below (in current bank) in A (as a value).
END: ;
STA $0F92,x ; Store this address in RAM as new instruction pointer.
;
RTL ; Return from subroutine long.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Animation code :
; ================
ANIME_CODE_4: ;
dw $0018 ; Duration for displaying sprite F. (it's a blank tile)
dw SPRITE_F ; Pointer to sprite F tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
ANIME_CODE_3: ;
dw $0018 ; Duration for displaying sprite F. (it's a blank tile)
dw SPRITE_F ; Pointer to sprite F tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
ANIME_CODE_2: ;
dw $0018 ; Duration for displaying sprite F. (it's a blank tile)
dw SPRITE_F ; Pointer to sprite F tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
ANIME_CODE_1: ;
dw $0018 ; Duration for displaying sprite F. (it's a blank tile)
dw SPRITE_F ; Pointer to sprite F tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
dw $0008 ; Duration for displaying sprite 1.
dw SPRITE_1 ; Pointer to sprite 1 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0006 ; Duration for displaying sprite 2.
dw SPRITE_2 ; Pointer to sprite 2 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0008 ; Duration for displaying sprite 3.
dw SPRITE_3 ; Pointer to sprite 3 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0006 ; Duration for displaying sprite 4.
dw SPRITE_4 ; Pointer to sprite 4 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite 5.
dw SPRITE_5 ; Pointer to sprite 5 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite 6.
dw SPRITE_6 ; Pointer to sprite 6 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite 7.
dw SPRITE_7 ; Pointer to sprite 7 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite 8.
dw SPRITE_8 ; Pointer to sprite 8 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite 9.
dw SPRITE_9 ; Pointer to sprite 9 tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0004 ; Duration for displaying sprite A.
dw SPRITE_A ; Pointer to sprite A tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0005 ; Duration for displaying sprite B.
dw SPRITE_B ; Pointer to sprite B tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0005 ; Duration for displaying sprite C.
dw SPRITE_C ; Pointer to sprite C tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0006 ; Duration for displaying sprite D.
dw SPRITE_D ; Pointer to sprite D tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $0006 ; Duration for displaying sprite E.
dw SPRITE_E ; Pointer to sprite E tilemap code.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
dw $80ED ; Pointer to loop instruction in every enemy bank.
dw ANIME_CODE_4 ; Start address of animation code to loop to.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
SPRITE_1: ; Sprite 1 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $40, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_2: ; Sprite 2 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $42, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_3: ; Sprite 3 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $00, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_4: ; Sprite 4 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $02, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_5: ; Sprite 5 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $04, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_6: ; Sprite 6 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $06, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_7: ; Sprite 7 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $08, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_8: ; Sprite 8 tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $0A, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_9: ; Sprite 9 tilemap code :
; =======================
;
dw $0002 ; Number of tiles involved in this sprite.
;
db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $0E, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $0C, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_A: ; Sprite A tilemap code :
; =======================
;
dw $0002 ; Number of tiles involved in this sprite.
;
db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $22, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $20, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_B: ; Sprite B tilemap code :
; =======================
;
dw $0002 ; Number of tiles involved in this sprite.
;
db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $26, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $24, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_C: ; Sprite C tilemap code :
; =======================
;
dw $0002 ; Number of tiles involved in this sprite.

db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $2A, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $28, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_D: ; Sprite D tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $2C, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_E: ; Sprite E tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $E0 ; Tile size, X/Y coordinate and H/V flip settings.
db $2E, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
SPRITE_F: ; Sprite F tilemap code :
; =======================
;
dw $0001 ; Number of tiles involved in this sprite.
;
db $F8, $81, $F0 ; Tile size, X/Y coordinate and H/V flip settings.
db $44, $39 ; Tile number in GFX sheet ; Priority/palette/name setting.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
PALETTE: ; Enemy palette :
; ===============
;
dw $0000, $0000 ; Colors n°00 (transparent) & 01 (unused).
dw $0000, $0000 ; Colors n°02 (unused)      & 03 (unused).
dw $0000, $0000 ; Colors n°04 (unused)      & 05 (unused).
dw $0000, $0000 ; Colors n°06 (unused)      & 07 (unused).
dw $0000, $0000 ; Colors n°08 (unused)      & 09 (unused).
dw $0000, $5AD6 ; Colors n°0A (unused)      & 0B (white).
dw $4210, $294A ; Colors n°0C (light grey)  & 0D (medium grey).
dw $14A5, $0000 ; Colors n°0E (heavy grey)  & 0F (unused).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
org $87EC00 ; [Free space in any bank] (from $03:EC00 pc to $03:F4BF incl pc)
;
GFX: ; Enemy GFX data :
; ================
;
; 16 x 16 GFX tile n°$00, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$01, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$02, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $01, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$03, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $01, $01, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $01, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $10, $10 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$04, (top half) :
db $00, $00, $00, $00, $00, $00, $06, $04 ;
db $09, $08, $00, $01, $02, $00, $01, $00 ;
db $00, $00, $00, $00, $00, $00, $02, $06 ;
db $01, $09, $09, $09, $06, $06, $01, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $40, $40, $40, $00, $A0, $20, $88, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $40, $44, $44, $90, $B0, $A8, $A8 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°05 (top half) :
db $00, $00, $10, $10, $00, $00, $08, $08 ;
db $02, $00, $04, $00, $00, $00, $03, $00 ;
db $00, $00, $00, $10, $01, $01, $04, $0C ;
db $0A, $0A, $04, $04, $00, $00, $03, $03 ;
db $00, $00, $00, $00, $00, $00, $08, $00 ;
db $34, $20, $4A, $40, $88, $00, $50, $08 ;
db $00, $00, $00, $00, $00, $00, $08, $08 ;
db $14, $34, $0A, $4A, $C8, $C8, $78, $78 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$06, (top half) :
db $08, $08, $02, $00, $00, $04, $00, $00 ;
db $02, $00, $04, $04, $00, $00, $02, $02 ;
db $04, $0C, $0A, $0A, $04, $04, $00, $00 ;
db $02, $02, $00, $04, $00, $00, $01, $03 ;
db $00, $00, $00, $00, $40, $40, $00, $00 ;
db $20, $20, $08, $00, $00, $10, $00, $00 ;
db $00, $00, $00, $00, $00, $40, $04, $04 ;
db $10, $30, $28, $28, $50, $50, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°07 (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$00, (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $01, $01, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $01, $02, $02 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $80, $40 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $80, $C0, $C0 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$01, (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $01, $01, $02, $00, $01, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $01, $0B, $0B, $03, $03 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $80, $80, $60, $00, $00, $20, $40, $08 ;
db $00, $00, $00, $00, $10, $10, $00, $00 ;
db $40, $C0, $E0, $E0, $30, $30, $68, $68 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$02, (bottom half) :
db $00, $00, $00, $00, $03, $02, $04, $04 ;
db $00, $00, $01, $00, $00, $01, $00, $00 ;
db $00, $00, $00, $00, $01, $03, $00, $04 ;
db $04, $04, $03, $03, $01, $01, $00, $00 ;
db $00, $00, $80, $80, $60, $00, $C0, $20 ;
db $80, $40, $40, $20, $00, $40, $00, $80 ;
db $10, $10, $40, $C0, $E0, $E0, $E0, $E0 ;
db $C0, $C0, $60, $60, $40, $40, $80, $80 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$03, (bottom half) :
db $00, $00, $03, $02, $04, $04, $00, $00 ;
db $01, $00, $00, $01, $00, $00, $00, $00 ;
db $00, $00, $01, $03, $00, $04, $04, $04 ;
db $03, $03, $01, $01, $00, $00, $00, $00 ;
db $80, $80, $60, $00, $C0, $20, $80, $40 ;
db $40, $20, $00, $40, $00, $80, $00, $00 ;
db $40, $C0, $E0, $E0, $E0, $E0, $C0, $C0 ;
db $60, $60, $40, $40, $80, $80, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$04, (bottom half) :
db $03, $02, $04, $04, $00, $00, $01, $00 ;
db $00, $01, $00, $00, $00, $00, $00, $00 ;
db $01, $03, $00, $04, $04, $04, $03, $03 ;
db $01, $01, $00, $00, $00, $00, $00, $00 ;
db $40, $10, $80, $20, $08, $C0, $40, $00 ;
db $00, $40, $00, $80, $00, $00, $00, $00 ;
db $50, $50, $A0, $A0, $C8, $C8, $40, $40 ;
db $40, $40, $80, $80, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°05 (bottom half) :
db $04, $04, $00, $00, $01, $00, $00, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $04, $04, $04, $03, $03, $01, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $90, $24, $00, $C8, $40, $00, $00, $40 ;
db $00, $80, $00, $00, $00, $00, $00, $00 ;
db $B4, $B4, $C8, $C8, $40, $40, $40, $40 ;
db $80, $80, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$06, (bottom half) :
db $00, $00, $00, $01, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $02, $02, $01, $01, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $88, $00, $00, $00, $00, $00, $80, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $88, $88, $00, $00, $00, $00, $80, $80 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°07 (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $10, $10, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $10, $01, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$08, (top half) :
db $01, $00, $00, $00, $00, $00, $04, $04 ;
db $00, $00, $02, $02, $00, $00, $00, $01 ;
db $01, $01, $00, $00, $00, $00, $00, $04 ;
db $00, $00, $01, $03, $02, $02, $01, $01 ;
db $20, $20, $00, $00, $04, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $00, $00, $00 ;
db $00, $20, $00, $00, $04, $04, $00, $00 ;
db $40, $40, $00, $00, $80, $80, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$09, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0A, (top half) :
db $00, $00, $00, $00, $04, $04, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $04, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $80, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $80, $80, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0B, (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0C, (top half) :
db $04, $04, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $04, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $80, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0D (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $10, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $10, $10, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0E (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $20, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $20, $20, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0F (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $80 ;
db $00, $00, $00, $00, $20, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $80, $80 ;
db $00, $00, $00, $00, $20, $20, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$08, (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $80, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $80, $80, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$09, (bottom half) :
db $00, $00, $00, $00, $00, $00, $04, $00 ;
db $00, $00, $00, $00, $08, $08, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $04, $04 ;
db $00, $00, $00, $00, $00, $08, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $10, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $10, $10, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0A, (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0B, (bottom half) :
db $08, $00, $00, $00, $00, $00, $10, $10 ;
db $00, $00, $02, $00, $00, $00, $02, $00 ;
db $08, $08, $00, $00, $00, $00, $00, $10 ;
db $00, $00, $02, $02, $00, $00, $02, $02 ;
db $00, $00, $00, $00, $10, $00, $00, $00 ;
db $00, $00, $20, $20, $00, $00, $04, $00 ;
db $00, $00, $00, $00, $10, $10, $00, $00 ;
db $00, $00, $00, $20, $00, $00, $04, $04 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°$0C, (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0D (bottom half) :
db $20, $20, $00, $00, $04, $00, $00, $00 ;
db $00, $00, $02, $00, $00, $00, $00, $00 ;
db $00, $20, $00, $00, $04, $04, $00, $00 ;
db $00, $00, $02, $02, $00, $00, $00, $00 ;
db $20, $00, $00, $00, $00, $00, $10, $10 ;
db $00, $00, $80, $00, $00, $00, $00, $00 ;
db $20, $20, $00, $00, $00, $00, $00, $10 ;
db $00, $00, $80, $80, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0E (bottom half) :
db $00, $00, $00, $00, $04, $00, $00, $00 ;
db $00, $00, $08, $08, $00, $00, $01, $00 ;
db $00, $00, $00, $00, $04, $04, $00, $00 ;
db $00, $00, $00, $08, $00, $00, $01, $01 ;
db $00, $00, $10, $10, $00, $00, $80, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $10, $00, $00, $80, $80 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°0F (bottom half) :
db $00, $00, $00, $00, $00, $00, $04, $00 ;
db $00, $00, $00, $02, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $04, $04 ;
db $00, $00, $02, $02, $00, $00, $00, $00 ;
db $80, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $80, $80, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°10 (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°11 (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°12 (top half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;
;---------------------------------------------------------------------------------------------------- *
;
org $87F600 ; [Free space in any bank but should be at GFX adress + A00 bytes]
; [in this case, $87:EC00 + A00 = $87:F600] (from $03:F600 pc to $03:F6BF incl pc)
;
; 16 x 16 GFX tile n°10 (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $01, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $01, $01 ;
db $00, $00, $00, $00, $00, $00, $00, $00  ;
db $00, $00, $00, $00, $00, $00, $00, $80 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $80, $80 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°11 (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $03, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $01, $01, $03, $03 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $00, $00, $C0 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $80, $80, $C0, $C0 ;
;---------------------------------------------------------------------------------------------------- *
; 16 x 16 GFX tile n°12 (bottom half) :
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
db $00, $00, $00, $00, $00, $00, $00, $00 ;
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

[/spoiler] (bubble enemy)

BigDomino

There are really some amazing patches in this thread...
I am very impressed with the latest patches from BlackFalcon and mccad. :whoa:

Hackmi

Good work BigDomino, really like that spotlight effect and the underwater damage in particular, can see both being really useful for a game, may steal the underwater idea lol

Kazuto

Just a quick MZM patch some of you might want. The first pickup for Missiles/Supers/PBs gives double the value. Also affected by the difficulty flag, so hard mode would start you with 4 Missiles instead of 10, for example.

No free space used :grin:

albert v.

Custom Magmoor Caverns Song from Metroid Prime, although does not sound exactly as the original, works pretty great in game.

59C2 Song Long!

albert v.

Upgrade version of the intro + intro story theme for the Clocktober Hack made by moehr and Aran;Jaeger,



I'm Planning to remade all of them.



Mentlegen

BigDomino

I am amazed at your ambitious patches. This communite never ceases to amaze me. Even in 2020, more than 20 years after release, and during a global catastrophe, we are still moving foreward.

Congrats man, you are truly the next pioneer

BigDomino

@Mentlegen :
Thanks man :)

* * *

Here is another patch that I have been maturing for a long time.
Be sure to read the full description before applying and give credit the co-authors if you use it.
( -> Said co-authors can PM me for any problem related to their content being used in my patch).

MORPH-LOCK ANIMATION & SOUND :

VIDEO

[spoiler=ASM+Description];------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; MORPH-LOCK ANIMATION & SOUND ASM  [Filename: Morphlock_Anim_and_Sound_v.1.00.asm] (version 1.00 ; october 2020)
; ================================
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Introductory Note :
; - This patch add new features to the patch "morphlocking.asm" previoulsly made by Scyzer and Insomnia DX.
; - morphlocking.asm is included in this patch and don't need to be applied separately.
; - Hackers who already use morphlocking.asm in their hack can apply this patch without any issue.
; - Comments by the original autor of morphlocking.asm could be seen, next to the original parts of the code, with the lablel [SCY].
; - Introduction and credit of the original autor could be seen at the end of this header.
;
; Description :
; - The original patch by Scyzer allows to lock Samus in morph ball pose by placing air-fool x-ray blocks with a BTS value of 0C on the path to be travelled.
; - An air-fool x-ray blocks with a BTS value 0D allows Samus to stand up again.
; - These two BTS values are still usable after applying this patch and are left unchanged.
; - This patch implement the exact same fonction in two different BTS values (resp. 08 & 09) with two additional features :
;   a) A sound will be played when Samus is locked in morph ball ; another sound when she is unlocked.
;   b) GFX for a new "locking device" are added to the CRE tile-sheet and CRE tile-table.
;      An asm code will animate the tiles of the device to match the lock/unlock effect.
;      This animation could be used in any of the eight area of the game.
;
; Purpose of this patch :
; - While the original patch is primarily useful for preventing bugs when Samus try to stand up through 1.5 block wide passages, locking the player in morph ball
;   pose allows for many interesting gameplay sequence (e.g. bomb-jump maze / fight with bomb only / etc).
;   However, locking the player in a random place (ie: not in a one-tile sized morph-ball tunel), feel completely arbitrary and is incomprehensible for the player.
; - This patch provide a technological justification to the "morph locking" feature (and a visual indication : ON/OFF), allowing to use it anywere.
; - On the lore side, I imagine the device being part of an old Chozo technology intended to prevent "unmorphing accidents" in tight places.
;
; Other interesting aspects :
; - In order to implement the feature described above, this patch use a single conditional-code able to display two differents non-looping animations,
;   (thus moving from one animation-tables to another). The code is also able to stop the animation when needed.
;   This kind of code doesn't exist in the animated tile FX of Vanilla Super Metroid (-> all animations loops endlessly trough a single table).
;   This asm patch may be of educational interest for those who plans to create new animated-tiles with this kind of behaviour in their hack.
;
; What to consider before applying this patch :
; - This patch requires to free up two (optionaly six) 8x8 GFX tiles in your CRE tile-sheet ; These tiles are the ones who compose the 16x16 blocks you use for
;   your common level design (aka CRE Tile-table). Some of them are also used by PLMs / Pick-up PLMs.
;   If don't consider to get rid of 2 (or 6) original tiles, you cannot use this patch.
;
; How to install (SMILE 2.5) ?
; - Introduction:
;   99% of the procedure that follow need to be done manualy by the user and consist of replacing two existing tile of your CRE tile sheet by new ones.
;   I'm forced to do this way because (1) I cannot choose for you the tiles that you want to get rid of, (2) your CRE tile sheet is stored into the ROM
;   in a compressed format ; This .asm file cannot decompress your CRE data, put the new tiles into it, re-compress the data and write it back to your ROM,
;   (3) many users have repointed their CRE tile-sheet in free space, in a place unknow by me (4), many have already edited their CRE sheet.
;   So, here we go.
;
; - Do a backup of your hack.
; - In SMILE 2.5, open your hack and go to "Tools" -> "Graphics editor".
; - Then, go to "GFX" -> "CRE" -> "Export".
; - A file named "YourHackName_CRE.gfx" has been created in the same folder than your hack (-> this is your uncompressed CRE 8x8 tile-sheet).
; - Then, go to "Palette" -> "Export".
; - A file named "YourHackName_0??.tpl" has been created in the same folder than your hack (-> this is your color palette for the curent graphic set).
;
; - Open the software "tlp.exe" that is provided in the .zip file (this is the fixed version of TileLayerPro.exe for headerless file).
; - In tileLayerPro.exe, choose "File" -> "Open..." and select your CRE 8x8 tile-sheet (see above).
; - Then, choose "View" -> "Format" -> "SNES".
; - Then, choose "Palette" -> "Load..." and select your color palette (see above).
; - If you want, you can expand the windows by draging the bottom edge but STOP when you see two lines of withe "X" at the bottom of the sheet !
;   (If you continue to drag the windows below the two "X" lines, your CRE sheet will be damaged...).
;
; - Still in TileLayerPro.exe, choose "File" -> "Open..." and select the file "Morph locker CRE.gfx" provided in the .zip file.
; - Then, choose "View" -> "Format" -> "SNES".
; - Then, choose "Palette" -> "Load..." and select your color palette (see above).
;
; - In your CRE 8x8 tile-sheet, you have to find two consecutive tiles (in a row) that you don't plan to use anymore. That will be your "Free-tiles".
;   (NB1: you shouldn't use spike tiles n°3880 ; 3890 ; 38A0 ; 38B0 & 3D60 ; 3D70 ; 3D80 ; 3D90 because they are involved in another animation).
;   (NB2: you cannot use the white "X" tiles n°3E00 to 3FF0 because they are used by the game to display Pickup PLMs).
;   (PS: If you don't know which tile to "sacrifice", my advice would be those of the "Elevator PLM" who is a cosmetic-only PLM).
; - From the file "Morph locker CRE.gfx", drag and drop the two new tiles and put them in the CRE sheet in your Free-tiles.
; - In the chart below, find the address that match the leftmost tile of your Free-tiles.
; - then, replace "38C0" by your own address in the line below (keep the "$" symbol).
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

   !VRAM_address = $38C0

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; CRE TILE-SHEET, AS DISPLAYED IN TILELAYERPRO:
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2800|2810|2820|2830|2840|2850|2860|2870|2880|2890|28A0|28B0|28C0|28D0|28E0|28F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2900|2910|2920|2930|2940|2950|2960|2970|2980|2990|29A0|29B0|29C0|29D0|29E0|29F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2A00|2A10|2A20|2A30|2A40|2A50|2A60|2A70|2A80|2A90|2AA0|2AB0|2AC0|2AD0|2AE0|2AF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2B00|2B10|2B20|2B30|2B40|2B50|2B60|2B70|2B80|2B90|2BA0|2BB0|2BC0|2BD0|2BE0|2BF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2C00|2C10|2C20|2C30|2C40|2C50|2C60|2C70|2C80|2C90|2CA0|2CB0|2CC0|2CD0|2CE0|2CF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2D00|2D10|2D20|2D30|2D40|2D50|2D60|2D70|2D80|2D90|2DA0|2DB0|2DC0|2DD0|2DE0|2DF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2E00|2E10|2E20|2E30|2E40|2E50|2E60|2E70|2E80|2E90|2EA0|2EB0|2EC0|2ED0|2EE0|2EF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |2F00|2F10|2F20|2F30|2F40|2F50|2F60|2F70|2F80|2F90|2FA0|2FB0|2FC0|2FD0|2FE0|2FF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3000|3010|3020|3030|3040|3050|3060|3070|3080|3090|30A0|30B0|30C0|30D0|30E0|30F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3100|3110|3120|3130|3140|3150|3160|3170|3180|3190|31A0|31B0|31C0|31D0|31E0|31F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3200|3210|3220|3230|3240|3250|3260|3270|3280|3290|32A0|32B0|32C0|32D0|32E0|32F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3300|3310|3320|3330|3340|3350|3360|3370|3380|3390|33A0|33B0|33C0|33D0|33E0|33F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3400|3410|3420|3430|3440|3450|3460|3470|3480|3490|34A0|34B0|34C0|34D0|34E0|34F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3500|3510|3520|3530|3540|3550|3560|3570|3580|3590|35A0|35B0|35C0|35D0|35E0|35F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3600|3610|3620|3630|3640|3650|3660|3670|3680|3690|36A0|36B0|36C0|36D0|36E0|36F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3700|3710|3720|3730|3740|3750|3760|3770|3780|3790|37A0|37B0|37C0|37D0|37E0|37F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+vvvv+vvvv+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile>TILE|TILE<tile|tile| <- | in this ASM, my tiles are placed in this row
; |3800|3810|3820|3830|3840|3850|3860|3870|3880|3890|38A0|38B0>38C0|38D0<38E0|38F0|    | replacing two tiles of the eyes-door gfx.
; +----+----+----+----+----+----+----+----+----+----+----+----+^^^^+^^^^+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3900|3910|3920|3930|3940|3950|3960|3970|3980|3990|39A0|39B0|39C0|39D0|39E0|39F0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3A00|3A10|3A20|3A30|3A40|3A50|3A60|3A70|3A80|3A90|3AA0|3AB0|3AC0|3AD0|3AE0|3AF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3B00|3B10|3B20|3B30|3B40|3B50|3B60|3B70|3B80|3B90|3BA0|3BB0|3BC0|3BD0|3BE0|3BF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3C00|3C10|3C20|3C30|3C40|3C50|3C60|3C70|3C80|3C90|3CA0|3CB0|3CC0|3CD0|3CE0|3CF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3D00|3D10|3D20|3D30|3D40|3D50|3D60|3D70|3D80|3D90|3DA0|3DB0|3DC0|3DD0|3DE0|3DF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3E00|3E10|3E20|3E30|3E40|3E50|3E60|3E70|3E80|3E90|3EA0|3EB0|3EC0|3ED0|3EE0|3EF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; |tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|tile|
; |3F00|3F10|3F20|3F30|3F40|3F50|3F60|3F70|3F80|3F90|3FA0|3FB0|3FC0|3FD0|3FE0|3FF0|
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; ^    ^
; |    |
;     | in this ASM, my tiles are placed in these two columns ---+----+
;     | replacing two tiles of the eyes-door gfx. (leftmost tile address : $38C0)
;
; - Optionally, drag and drop the four other new tiles (-> non-animated) and put them in your CRE sheet, thus replacing four additional unused tiles.
;   These standard static tiles are nice to complement the design of the locking device. Of course, you can instead draw your own tile.
; - Save your modified CRE 8x8 tile-sheet file.
; - Close TileLayerPro.
; - Go to SMILE 2.5 (you are still in the "Graphics editor").
; - Go to "GFX" -> "CRE" -> "Import".
; - Read info in the message-box.
; - If the recompressed size is less or equal than $1CA7, it's fine.
; - If size is greater than $1CA7 there is a risk of overwriting data stored after the CRE tile-sheet (ie: the CRE Tiletable data).
;   You should do a "file comparison" (tanks to your hex editor) between your modified hack and your backup hack :
;   If data are changed within the range $1C:A09C (pc) to $1C:A633 (pc), that means that your bigger CRE tile-sheet have overwritted your CRE TTB.
;   2 possibility :
;    a) Delete the modified hack. With your backup, create a new fresh file and restart the process replacing 2 differents tiles of your CRE tile sheet.
;    b) Consider moving and repointing your CRE tile sheet in free space (not covered by this guide).
; - Still in graphic editor, scroll your SCE / CRE sheet (-> the right part of the windows) until you can see your two new tiles.
; - In the CRE / SCE tile table (-> in the bottom left corner of the windows), choose an unused tile to edit and click on it.
;   NB1: The 16x16 tiles with white "X"s are OK to edit.
;   NB2: Don't edit the eight black 16x16 tile just above the grey doors tiles : They are used for Pick-up PlM.
;   NB3: Don't edit the Scenery tiles after the big row of withe "X"s tiles.
; - In the square shaped Tile table editor (-> in the center of the window) you can see now your selected tile divided in four quarter.
; - From your tile sheet on the right, drag and drop the two news 8x8 tiles toward the Tile editor as follow :
;
;     +--+------+------+--+
;     |  |      |      |  |
;     +--+------+------+--+
;     |  | tile | tile |  |
;     |  |  01  |  02  |  |
;     |  |      |      |  |
;     +--+------+------+--+
;     |  | tile | tile |  |
;     |  |  01  |  02  |  |
;     |  |      |      |  |
;     +--+------+------+--+
;     |  |      |      |  |
;     +--+------+------+--+
;
; - Click on the left-bottom and right-bottom semi-edges to apply an horizontal axial symetry to the bottom two tiles:
;
;     +--+------+------+--+
;     |  |      |      |  |
;     +--+------+------+--+
;     |  | tile | tile |  |
;     |  |  01  |  02  |  |
;     |  |      |      |  |
;     +--+------+------+--+
;     |^ | tile | tile | ^|
;     || |  01  |  02  | ||
;     || |fliped|fliped| ||
;     +--+------+------+--+
;     |  |      |      |  |
;     +--+------+------+--+
;
; - If needed, click on the four corners to toggle between palettes : You want a value of 0 in each corner:
;
;     +--+------+------+--+
;     |0 |      |      | 0|
;     +--+------+------+--+
;     |  | tile | tile |  |
;     |  |  01  |  02  |  |
;     |  |      |      |  |
;     +--+------+------+--+
;     |^ | tile | tile | ^|
;     || |  01  |  02  | ||
;     || |fliped|fliped| ||
;     +--+------+------+--+
;     |0 |      |      | 0|
;     +--+------+------+--+
;
; - Finaly, if needed, click on the four internal square to make a red corner appear on each one (your tile will be draw beside Samus sprite):
;
;     +--+------+------+--+
;     |0 |      |      | 0|
;     +--+------+------+--+
;     |  | tile | tile |  |
;     |  |  01  |  02  |  |
;     |  |     #|#     |  |
;     +--+------+------+--+
;     |^ |tile #|# tile| ^|
;     || |  01  |  02  | ||
;     || |fliped|fliped| ||
;     +--+------+------+--+
;     |0 |      |      | 0|
;     +--+------+------+--+
;
; - Click [Save 16x16 Tile to ROM] button.
; - Optionally, create the additional static 16x16 tile with the four optional 8x8 tiles with the same process than above.
;   (NB: H-flip operations isn't needed for this one but don't forget to save the tile).
; - Close the "Graphics editor".
; - Click "File" in main window, then "Save room".
; - Close SMILE 2.5.
; - Do a second backup of your edited hack.
; - Control free space usage for this patch (see below).
; - Apply this ASM patch (Morphlock_Anim_and_Sound_v.1.00).
; - Done.
;
; Notation:
; - The [!] marks (in the right margin) point out values / data / addresses that can be changed by the user ( -> several places in this doc).
;
; How to use in a room ? (Smile 2.5):
; - Choose a room with a valid FX1 pointer.
; - Open the FX1 editor and, in the "Animate tile" section at the bottom, check the last box.
; - Design your room using your new 16x16 tile at the entrance of a morph-ball tunnel.
;   Set type and BTS value as in the diagram below :
;
;
;                     |      |      |      |      |      |      |      |      |      |      |
;                     +------+------+------+------+------+------+------+------+------+------+
;                     |solid |solid |solid |solid |solid |solid |solid |solid |solid |solid |
;                     |      |      |      |      |      |      |      |      |      |      |
;                     |BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|
;                     +------+------+------+------+------+------+------+------+------+------+
;                      airfoo|airfoo| air  | air    air    air    air  | air  |airfoo|airfoo
; tunel entrance --->  x-ray |x-ray |      |                           |      |x-ray |x-ray   <--- tunel entrance
;                      BTS 09|BTS 08|BTS 00|BTS 00 BTS 00 BTS 00 BTS 00|BTS 00|BTS 08|BTS 09
;           ---+------+------+------+------+------+------+------+------+------+------+------+------+---
;              |solid |solid |solid |solid |solid |solid |solid |solid |solid |solid |solid |solid |
;              |      |      |      |      |      |      |      |      |      |      |      |      |
;              |BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|BTS 00|
;            --+------+------+------+------+------+------+------+------+------+------+------+------+--
;
;                             put locker GFX                            put locker GFX
;                               tiles here                                tiles here
;                            |<----------->|                           |<----------->|
;
;  you are unlocked     unlock  lock           you are morph-locked             lock  unlock    you are unlocked
;                       block  block                                            block  block
;  ...................|<---->|<---->|.........................................|<---->|<---->|...................
;
;
;  outside the tunnel                            inside the tunnel                            outside the tunnel
;  ------------------>|<------------------------------------------------------------------->|<------------------
;
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Free space usage:
; - Free space used by this patch can be set at the user's will ; The default ranges are:
;
;  LoROM $80:CD90 to $80:CDD6 (inclusive) ie PC $00:4D90 to $00:4DD6 (inclusive). [lenght: $  47 bytes]
;  LoROM $87:9F04 to $87:9FC3 (inclusive) ie PC $03:9F04 to $03:9FC3 (inclusive). [lenght: $  C0 bytes]
;  LoROM $87:C964 to $87:C9FF (inclusive) ie PC $03:C964 to $03:C9FF (inclusive). [lenght: $  9C bytes]
;  LoROM $94:B200 to $94:B213 (inclusive) ie PC $0A:3200 to $0A:3213 (inclusive). [lenght: $  14 bytes]
;  LoROM $94:B230 to $94:B29B (inclusive) ie PC $0A:3230 to $0A:329B (inclusive). [lenght: $  6C bytes]
;
; - If there is data in your ROM at these places, you need to relocate the code of this ASM before applying (see below -> [!] ).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Data modification / Pointer redirection:
; - Some data /pointers are changed at the folowing ranges in the ROM:
;
;  LoROM $80:9465 to $80:9467 (inclusive) ie PC $00:1465 to $00:1467 (inclusive). [lenght: $   3 bytes]
;  LoROM $83:AC84 to $83:AC85 (inclusive) ie PC $01:AC84 to $01:AC85 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:ACA4 to $83:ACA5 (inclusive) ie PC $01:ACA4 to $01:ACA5 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:ACC4 to $83:ACC5 (inclusive) ie PC $01:ACC4 to $01:ACC5 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:ACE4 to $83:ACE5 (inclusive) ie PC $01:ACE4 to $01:ACE5 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:AD04 to $83:AD05 (inclusive) ie PC $01:AD04 to $01:AD05 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:AD24 to $83:AD25 (inclusive) ie PC $01:AD24 to $01:AD25 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:AD44 to $83:AD45 (inclusive) ie PC $01:AD44 to $01:AD45 (inclusive). [lenght: $   2 bytes]
;  LoROM $83:AD64 to $83:AD65 (inclusive) ie PC $01:AD64 to $01:AD65 (inclusive). [lenght: $   2 bytes]
;  LoROM $94:98BC to $94:98BF (inclusive) ie PC $0A:18BC to $0A:18BF (inclusive). [lenght: $   4 bytes]
;  LoROM $94:98C4 to $94:98C7 (inclusive) ie PC $0A:18C4 to $0A:18C7 (inclusive). [lenght: $   4 bytes]
;
; - If you have already used these addresses to create HiJack point or other stuff for your hack, you shouldn't apply this patch.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; RAM usage:
; - This patch use several free RAM addresses:
;
;  RAM $7E:FA24 to $7E:FA25 (inclusive). [lenght: $ 2 bytes]
;  RAM $7E:FA26 to $7E:FA27 (inclusive). [lenght: $ 2 bytes]
;  RAM $7E:FA28 to $7E:FA29 (inclusive). [lenght: $ 2 bytes]
;  RAM $7E:FA2A to $7E:FA2B (inclusive). [lenght: $ 2 bytes]
;
; - If another patch/code who use the same addresses is intended to run at the same time than this patch, you need to change the addresses above to
;   other unused one (there is plenty : for example, from 7E:FA1B to 7E:FFFF).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Credit :
; - P.JBoy for his documentation, specifically the disassembly of banks $83 & $87.
; - DChronos for the good explanations on his #animtiles.log
; - Scyzer & Insomnia DX for the original patch reused in this one.
; - Bruce Clark (65C816 Opcodes at http://www.6502.org/tutorials/65c816opcodes.html)
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Introduction and credit of the original patch made by Scyzer :
; << The majority code was done by Insom. Major thanks to him for this and Kejardon for notes on RAM
;   Code modified by Sadiztyk Fish to allow blocks to work in Fool Air X-ray, rather than solid blocks.
;   Fixed check for springball, also added comments so you know what's going on mostly.
;   BTS 0C locks the morphing, BTS 0D unlocks it. >>
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
; Patch modified by BigDomino.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Defines RAM addresses :
; ===================
;
!New_Lock_Flag = $7EFA24 ; Custom RAM address for the current state of the lock-flag.   [!]
!Old_Lock_Flag = $7EFA26 ; Custom RAM address for the previous state of the lock-flag.   [!]
!Lock_Needed   = $7EFA28 ; Custom RAM address for the flag who say that a lock animation need to be performed.   [!]
!Unlock_Needed = $7EFA2A ; Custom RAM address for the flag who say that an unlock animation need to be performed.   [!]
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
lorom ;
;
org $809465 ; Hijack point made by Scyzer : Cannot be changed. [BIGDOMINO]
JSR SCYZER_CODE ; Using a label instead of a declared address for more flexibility. [BIGDOMINO]
;
org $80CD90 ; Free space in bank $80 suggested by Scyzer. This can be changed if needed. [BIGDOMINO]   [!]
SCYZER_CODE: ; Label added to let the user choose another free space if needed. [BIGDOMINO]
;
LDA $09A1 ; LDA equipped items [SCY]
BMI $04 ; Branch if items are equipped [SCY]
LDA $4218 ; LDA value from previous code (before the JSR) [SCY]
RTS ; [SCY]
LDA $0998 ; LDA game state (so you can use UP or JUMP while paused) [SCY]
CMP #$0008 ; This just checks to see if you're paused or playing, etc [SCY]
BEQ $1C ; [SCY]
CMP #$000C ; [SCY]
BEQ $17 ; [SCY]
CMP #$0012 ; [SCY]
BEQ $12 ; [SCY]
CMP #$001A ; [SCY]
BNE $09 ; [SCY]
LDA $09A1 ; If game is paused, LDA equipped items [SCY]
AND #$7FFF ; Remove high bit, allowing you to use UP/JUMP [SCY]
STA $09A1 ; Store new value [SCY]
LDA $4218 ; LDA value from previous code (before the JSR) [SCY]
RTS ; [SCY]
LDA $09A2 ; LDA Equipped items [SCY]
AND #$0002 ; Checks for Springball bit [SCY]
BNE $0B ; [SCY]
LDA #$FFFF ; If Springball comes positive, LDA 1111 1111 [SCY]
EOR $09B4 ; Reset jump bit if positive. Complement of Jump bit [SCY]
AND $4218 ; For some reason, ANDing with the previous routine's loaded value. [SCY]
BRA $03 ; [SCY]
LDA $4218 ; If Springball comes negative, LDA value from previous code (before the JSR) [SCY]
AND #$F7FF ; Reset a bit [SCY]
RTS ; [SCY]
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Change air-fool x-ray BTS pointer to match the new routines : [BIGDOMINO]
org $9498BC ; [BIGDOMINO]
;
DW LOCK_SOUND ; BTS $08 (lock with sound & animation) [BIGDOMINO]
DW UNLOCK_SOUND ; BTS $09 (unlock with sound & animation) [BIGDOMINO]
;
;---------------------------------------------------------------------------------------------------------------------------- *
org $9498C4 ; [SCY]
;
DW LOCK ; BTS $0C (lock) [SCY]
DW UNLOCK ; BTS $0D (unlock) [SCY]
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
org $94B200 ; Free space in bank $94. This can be changed if needed. [BIGDOMINO]   [!]
; Sets up the BTS blocks 0C & 0D : [SCY]
LOCK: ;
LDA $09A1 ;\ [SCY]
ORA #$8000 ; | original Scyzer code [SCY]
STA $09A1 ; | [SCY]
RTS ;/ [SCY]
;
;---------------------------------------------------------------------------------------------------------------------------- *
UNLOCK: ;
LDA $09A1 ;\ [SCY]
AND #$7FFF ; | original Scyzer code [SCY]
STA $09A1 ; | [SCY]
RTS ;/ [SCY]
;
;---------------------------------------------------------------------------------------------------------------------------- *
; Past this line, the code is written and commented by [ BigDomino ].
;---------------------------------------------------------------------------------------------------------------------------- *
;
org $94B230 ; Free space in bank $94. This can be changed if needed.   [!]
; Sets up the BTS blocks 08 & 09 :
LOCK_SOUND: ;
LDA $09A1 ;\
ORA #$8000 ; | original Scyzer code, reused for this patch.
STA $09A1 ;/
LDA !New_Lock_Flag ; Load in Acc. the value of the Lock flag from the previous frame.
STA !Old_Lock_Flag ; Save this value in RAM.
LDA #$0001 ; Load #$0001 in Acc and...
STA !New_Lock_Flag ; ... set the lock flag.
CMP !Old_Lock_Flag ; Compare current and previous value of the Lock falg.
BEQ + ; If equal (= no change), avoid next instructions.
LDA !Lock_Needed ; If non-equal, morph-lock has just occured ; load the "lock animation needed" flag value to accumulator...
INC ; ...increase value by one...
STA !Lock_Needed ; ...store it back in RAM (ie: a lock-animation is now scheduled).
LDA #$0045 ; ... and load Sound sample number #0045 in accumulator.
JSL $8090A3 ; Jump long to the sound FX subroutine for library 2 (max queue = F).
LDA #$002C ; Otherwise, load Sound sample number #002C in accumulator.
JSL $809125 ; Jump long to the sound FX subroutine for library 3 (max queue = F).
+ ;
RTS ;
;
;---------------------------------------------------------------------------------------------------------------------------- *
UNLOCK_SOUND: ;
LDA $09A1 ;\
AND #$7FFF ; | original Scyzer code, reused for this patch.
STA $09A1 ;/
LDA !New_Lock_Flag ; Load in Acc. the value of the Lock flag from the previous frame.
STA !Old_Lock_Flag ; Save this value in RAM.
LDA #$0000 ; Load #$0000 in Acc and...
STA !New_Lock_Flag ; ... reset the lock flag.
CMP !Old_Lock_Flag ; Compare current and previous value of the Lock falg.
BEQ + ; If equal (= no change), avoid next instructions.
LDA !Unlock_Needed ; If non-equal, morph-unlock has just occured ; load the "unlock animation needed" flag value to accumulator...
INC ; ...increase value by one...
STA !Unlock_Needed ; ...store it back in RAM (ie: an unlock-animation is now scheduled).
LDA #$0045 ; ... and load Sound sample number #0045 in accumulator.
JSL $8090A3 ; Jump long to the sound FX subroutine for library 2 (max queue = F).
LDA #$0015 ; Otherwise, load Sound sample number #0015 in accumulator.
JSL $809125 ; Jump long to the sound FX subroutine for library 3 (max queue = F).
+ ;
RTS ;
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
; Animated tile objects pointer array (only pointer for checkbox n°8 is shown for each area) :
; (You can also use different "org" address to assign the animation to another checkbox).
;
org $83AC84 ; Crateria : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83ACA4 ; Brinstar : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83ACC4 ; Norfair : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83ACE4 ; Wrecked ship : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83AD04 ; Maridia : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83AD24 ; Tourian : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83AD44 ; Ceres : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
org $83AD64 ; Debug : checkbox n°8
dw ANIM_LOCK_FX ; Address of the new animated tile object FX.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
org $879F04 ; Free space in bank $87. This can be changed if needed.   [!]
; NeW GFX for the animation :
LOCK_GFX: ;
;
db $87, $F8, $AF, $DF ; 8x8 pixel GFX tile n°1 for sprite n°1
db $9F, $DF, $9E, $D3 ;
db $9F, $D3, $9E, $D3 ;
db $9F, $D3, $9E, $DF ;
db $FF, $00, $FF, $00 ;
db $E0, $00, $E0, $0C ;
db $E0, $00, $E0, $00 ;
db $E0, $0C, $E0, $00 ;
;---------------------------------------------------------------------------------------------------------------------------- *
db $E0, $00, $87, $F8 ; 8x8 pixel GFX tile n°2 for sprite n°1
db $FF, $FF, $FF, $FF ;
db $FF, $FF, $FF, $FF ;
db $FF, $FF, $FF, $FF ;
db $FF, $00, $FF, $00 ;
db $17, $00, $2F, $00 ;
db $17, $00, $2F, $00 ;
db $17, $00, $2F, $00 ;
;---------------------------------------------------------------------------------------------------------------------------- *
UNLOCK_GFX: ; (at $879F44)
;
db $87, $F8, $AF, $DF ; 8x8 pixel GFX tile n°1 for sprite n°2
db $9B, $C7, $95, $CF ;
db $9B, $C7, $95, $CF ;
db $9B, $C7, $95, $CF ;
db $FF, $00, $FF, $00 ;
db $FF, $00, $FF, $00 ;
db $FF, $00, $FF, $00 ;
db $FF, $00, $FF, $00 ;
;---------------------------------------------------------------------------------------------------------------------------- *
db $E0, $00, $87, $F8 ; 8x8 pixel GFX tile n°2 for sprite n°2
db $7F, $FF, $FF, $FF ;
db $7F, $FF, $FF, $FF ;
db $7F, $FF, $FF, $FF ;
db $FF, $00, $FF, $00 ;
db $FF, $17, $FF, $2B ;
db $FF, $17, $FF, $2B ;
db $FF, $17, $FF, $2B ;
;---------------------------------------------------------------------------------------------------------------------------- *
FLASH_GFX: ; (at $879F84)
;
db $87, $F8, $AC, $DF ; 8x8 pixel GFX tile n°1 for sprite n°3
db $8C, $C3, $86, $D1 ;
db $89, $D2, $81, $D2 ;
db $89, $D2, $86, $D1 ;
db $FF, $00, $FF, $00 ;
db $F0, $03, $E8, $11 ;
db $E4, $16, $EC, $16 ;
db $E4, $16, $E8, $11 ;
;---------------------------------------------------------------------------------------------------------------------------- *
db $E0, $00, $07, $F8 ; 8x8 pixel GFX tile n°2 for sprite n°3
db $68, $97, $D0, $2F ;
db $68, $97, $D0, $2F ;
db $68, $97, $D0, $2F ;
db $FF, $00, $FF, $00 ;
db $00, $80, $00, $00 ;
db $00, $80, $00, $00 ;
db $00, $80, $00, $00 ;
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
org $87C964 ;  Free space in bank $87. This can be changed if needed.   [!]
;
ANIM_LOCK_FX: ; Animated tile object FX :
;
dw ANIM_DATA ; Pointer to animation data (-> standard starting point).
dw #$0040 ; GFX size, to transfer to VRAM, all in a row (two 8x8 pixel tiles are used in this animation : 2 tiles x 20 bytes = 40  bytes).
dw !VRAM_address ; VRAM location where to transfer the GFX :
; SCE and CRE are sorted in VRAM the same way than they appear in the Graphics editor tile sheet.
; (Position in VRAM = $10C0 in CRE sheet + $2800 for the entire SCE tile sheet above).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
ANIM_DATA_L: ; Animation data "lock" header :
; (-> alternative starting point for the anime-tile routine, after a lock animation has been performed).
;
dw LOCK_DONE ; Pointer to animation code pre-ASM header, that reset the "lock needed" flag after the animation has been fully executed.
;---------------------------------------------------------------------------------------------------------------------------- *
ANIM_DATA_U: ; Animation data "unlock" header :
; (-> alternative starting point for the anime-tile routine, after an unlock animation has been performed).
;
dw UNLOCK_DONE ; Pointer to animation code pre-ASM header, that reset the "unlock needed" flag after the animation has been fully executed.
;---------------------------------------------------------------------------------------------------------------------------- *
ANIM_DATA: ; Animation data :
; (standard starting point, according to the "Animated tile object FX" data above).
;
dw PRE_ANIMATION_CODE ; Pointer to animation code pre-ASM (ie: the code that can swap between animation table 1 & 2 or prevent any kind of animation).
;---------------------------------------------------------------------------------------------------------------------------- *
;
LOCK_ANIM_TABLE: ; Animation table 1 : "Lock" (it's a one time animation)
;
dw #$0001, LOCK_GFX ; Frame count / GFX short address in $87 for frame 1.0
dw #$0003, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 1.1
dw #$0002, LOCK_GFX ; Frame count / GFX short address in $87 for frame 1.2
dw #$0002, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 1.3
dw #$0003, LOCK_GFX ; Frame count / GFX short address in $87 for frame 1.4
dw #$0001, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 1.5
dw #$0004, FLASH_GFX ; Frame count / GFX short address in $87 for frame 1.6
dw #$0001, LOCK_GFX ; Frame count / GFX short address in $87 for frame 1.7 (this sprite will last forever)
;
dw $80B7, ANIM_DATA_L ; Jump to animation-data "lock" header, that contain the pointer to the "lock" animation code pre-ASM header.
;
;---------------------------------------------------------------------------------------------------------------------------- *
;
UNLOCK_ANIM_TABLE: ; Animation table 2 : "Unlock" (it's a one time animation)
;
dw #$0001, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.0
dw #$0004, LOCK_GFX ; Frame count / GFX short address in $87 for frame 2.1
dw #$0001, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.2
dw #$0003, LOCK_GFX ; Frame count / GFX short address in $87 for frame 2.3
dw #$0002, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.4
dw #$0002, LOCK_GFX ; Frame count / GFX short address in $87 for frame 2.5
dw #$0003, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.6
dw #$0001, LOCK_GFX ; Frame count / GFX short address in $87 for frame 2.7
dw #$0004, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.8
dw #$0001, LOCK_GFX ; Frame count / GFX short address in $87 for frame 2.9
dw #$0001, UNLOCK_GFX ; Frame count / GFX short address in $87 for frame 2.A (this sprite will last forever)
;
dw $80B7, ANIM_DATA_U ; Jump to animation-data "unlock" header, that contain the pointer to the "unlock" animation code pre-ASM header.
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *

; Using the labels of the two tables above to calculate the lenght of the first table.
; This value will be used to shift the address stored in Y index register, when swaping between table1 & table2.


!Address_Table1 = LOCK_ANIM_TABLE ; Put "lock-anim-table" label address into a constant.
!Address_Table2 = UNLOCK_ANIM_TABLE ; Put "unlock-anim-table" label address into a constant.
!Table_Shift = !Address_Table2-!Address_Table1 ; Do subtraction said constants ; The result is a long value (3 bytes).

;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
;
LOCK_DONE: ; Lock animation code pre-ASM header : The anim tile routine will jump at this place after the lock animation has been
; fully played (see the jmp at the end of the lock animation table)
;
LDA #$0000 ; The goal is to reset the "lock needed" flag by storing a #$0000 value...
STA !Lock_Needed ; ... into it, in RAM, thus avoiding the lock animation beeing played again and again.
INY : INY ; Moreover, since animation tables are meant to be read right after anim data pointer (see above) and given the fact that
INY : INY ; the anime-tile routine kept track (in Y) of the last address fetched (-> in this case, the one for the lock header !), we need
; to shift by 4 positions the Y register to make the anime-tile routine land on the correct place (ie: on the anim-tables) after
; this step is finished, in the event that a new animation needs to be played immediately.
; (Without that, the routine would have landed at the place where the pointer to "Unlock animation code pre-ASM header" is stored...)
BRA PRE_ANIMATION_CODE ; Continue (ie: Jump) to standard animation code, avoiding the "Unlock animation code pre-ASM header" underneath.
;---------------------------------------------------------------------------------------------------------------------------- *
;
UNLOCK_DONE: ; Unlock animation code pre-ASM header : The anim tile routine will jump at this place after the unlock animation has been
; fully played (see the jmp at the end of the unlock animation table)
;
LDA #$0000 ; The goal is to reset the "unlock needed" flag by storing a #$0000 value...
STA !Unlock_Needed ; ... into it, in RAM, thus avoiding the unlock animation beeing played again and again.
INY : INY ; Moreover, since animation tables are meant to be read right after anim data pointer (see above) and given the fact that
; the anime-tile routine kept track (in Y) of the last address fetched (-> in this case, the one for the unlock header !), we need
; to shift by 2 positions the Y register to make the anime-tile routine land on the correct place (ie: on the anim-tables) after
; this step is finished, in the event that a new animation needs to be played immediately.
; (Without that, the routine would have landed at the place where the pointer to "animation code pre-ASM is stored"... we don't
; want that to happens because this animation code pre-ASM is just below our position and we'll read it right away).
; In other words, without shifting the Y register, the animation code pre-ASM would have been read twice in a row for no reason.
;---------------------------------------------------------------------------------------------------------------------------- *
;
PRE_ANIMATION_CODE: ; Code that swap between animation-tables 1 & 2 or stop animation according to the values of !Lock_Needed / !Unlock_Needed flags :
;
LDA !Lock_Needed ; Load in acc. the current value of the Lock_Needed flag.
CLC ; Clear carry prior to the addition that follow.
ADC !Unlock_Needed ; Add to acc. the current value of the Unlock_Needed flag.
BEQ + ; If result is #$0000, no animation has been scheduled, so branch +.
; Otherwise...
LDA !Unlock_Needed ; ...load in acc. the current value of the Unlock_Needed flag.
CMP !Lock_Needed ; Compare with the value of the Lock_Needed flag.
BCC ++ ; If Unlock_Needed flag value is less than Lock_Needed flag value, lock animation has priority and have to be played now.
; This animation use the standard anime-table n°1. Simply go to ++, at the end of this subroutine.
; Otherwise...
TYA ; ...we need to use the second animation table for the unlock animation (-> the address is stored in Y).
CLC ; Time to fake the Y index register used by the anime FX routine.
; We want this routine to read animation table n°2 that is N bytes away from the normal position (N = Table2 - Table1 addresses).
; The shifting N was calculated earlier in this asm, by performing a subtraction on the labels of the two tables, making this
db #$69 ; code still working even if the user makes changes in the animation (thus altering the lenght of the tables).
dw !Table_Shift ; #$69 will be read as "ADC" opcode ; dw !Table_Shift is the argument for ADC.
; Writing it with "dw" will force the compiler to use a "word" value for the shifting instead of the natural "long" one.
TAY ; The incrementation of Y is made trough the accumulator after which, the result is transfered back to the Y index register.
BRA ++ ; Branch to the end of this animation code to process animation with the special table n°2.
+ ;
LDA #$0001 ; ... and restore the 1 frame delay (in the FX delay counter) that was decreased by subroutine at $87:8088.
STA $7E1F19,x ; With this 1 frame delay, the instruction at $87:808B will pass over the entire subroutine (ie: branching to $87:80B1 = RTS)
PLA ; Pull (ie: remove) the $808F pointer that was artificlialy pushed into the stack at $87:809A (this pointer was intended to bring
; back in the middle of the subroutine who process eiter ASM instruction or frame animation). This pointer being now removed,
++ ; the next RTS instruction will, instead, bring back three bytes after the last JSR instruction encountered, at $87:8078
; (ie: $87:807B). After that, the end of the subroutine will check if another animation need to be processed and, eventually
; RTS to main routine.
RTS ; Come back to [$87:808F+1 = $87:8090] (or [$87:8078+3 = $87:807B] if animation was cancelled - see above).
;
;------------------------------------------------------------------------------------------------------------------------------------------------------------ *
[/spoiler]

nodever2

SM: Better Bomb Explosions

Ever wish bombs broke diagonally adjacent blocks? Me too.
Worry no more. Got a quick little patch for ya.

3x3 BOMB EXPLOSION GIF:


------------------------------------
EDIT 10-26-2020:
This resource now has 2 patches for you to choose from.
After I posted the original resource, Benox approached me and had rewritten my original 3x3 bomb explosion radius patch to not use any freespace.

He also made a new version of the code which makes bomb explosions more similar to vanilla but act way smarter - if the bomb is in the middle of a tile, it will act like vanilla, but if it is on the edge, it will destroy blocks 1 tile over.
This way, if the player wants to precisely bomb they can still place the bomb in the middle of the tile and it will break blocks in a cross shape, but if they place the bomb right in between two tiles it will break both of them instead of just 1 like vanilla would have done.

If it sounds confusing, just download it and try it yourself. I am uploading both patches here.

SMART BOMB EXPLOSION GIF              VANILLA BEHAVIOR, FOR REFERENCE (without this patch)
                |                                                                             |
                V                                                                             V

Need help? Just ask.
My Hacks | My Resources

Mettyk25jigsaw

Hi Everybody!

This is an improved and improvised version of my door asm patch which allows you to customise loading of scroll colors through the door asm pointer in the door editor.

This one repoints the main chunk of data to anywhere in the Rom, saving you lots of room in bank $8F. It still uses bank $8F, but per door asm entry it will only require 4 bytes in bank $8F + 1 byte for first asm entry ONLY, as all other door asm entries can utilize this same 1 byte.

Cheers.

Door ASM Version 2:

albert v.

Hello! I've Updates this new song, this time using only super metroid soundfonts, this was made for escape sequence or maybe a miniboss figth, IDK it all depend on were you want to use this.

The song is 457F long

MetroidNerd#9001

Here's some ASM I made based on the Power Rush item from the first two Paper Mario games. Whenever Samus is at or below 30 Energy, she deals double damage with her attacks. In its current state, the patch works on the entire hack. At some point, I plan to make it its own item, but I'm putting it out there now in case anyone wants to try it out.

Something to note: The damage doubling doesn't apply to Speed Booster, Screw Attack, or Shinespark damage. This won't affect normal hacks, but if you edited how much damage any of those things deal, you'll have to edit the ASM yourself if you want the effect to apply to them.

dewhi100

Set an event when you clear a room.

The metroid rooms in Tourian already did this, in a terrible, roundabout way which was unintuitive and limited to only a few event values.
Now, you just set the PLM parameter to the event you want set. When enemies killed matches enemies needed, the event will be set.

albert v.

Gerudo Valley from The Legend of Zelda Ocarina of Time, This was a little hard actually, i think sounds good after many hours of work.
+
house theme from The Legend of Zelda Ocarina of Time, is a simple song so it was easier after all.

If you ever want to learn about making music for Super Metroid, you can DM me on Discord: Albert V#5864 And I'll be happy to help.

Oi27

#1173
Instant item pickups like in SM Challenge and Vitality! It also displays the item name in the HUD and stacks the energy tanks into one row.
video: https://youtu.be/wht5Q9HbCIY

Contributors:
-Oi27
-Moehr
-Smiley
-PJ
-DM

Oi27

#1174
you can press a button to go slower c: