[M1] Getting .asm and/or .ips - Modifications to work on EXPANDED Roms.

Started by Flower, April 18, 2016, 07:22:54 AM

Previous topic - Next topic

Flower

Hello everyone,

like the title says, i want to get certain Modifications to work on an Expanded NEStroid-ROM.
Mainly: Healthy/Hurty-Blocks, Walljumping, not getting hurt while passing through a door and adjusting door transition speed.  :bounce:
At first it seems (for example HealthBlocks) that this isn't possible, 'cause everytime i load the expanded ROM with the Patch applied on it, the Game crashes.
Loading the ROM into Editroid or TilyLayerPro shows the Patch garbled and messed up Banks and Tiles. So i guess the code of  the Patch has to be loaded into another Bank as in unexpanded ROMs.

Unfortunately, i am no asm-Expert, so I'm asking you: Are there possibilities to get things done?
I don't want to decide between Expanding the ROM or using the Patches, I want to use both obviously.

I hope somebody can help.

Thanks and greets  :^_^:

Wirtualnosc

You probably will need to patch the game with asm files (preferably via projects) and replace the addresses at which patches are applied. First of all, you should apply patches at bank 0F instead of 07. You might also need to change the addresses themselves - the unused saving code (which the patches might replace - addresses CA35 to CAF5) is used in expanded roms by default. Address C6A0 seemed to work fine for me without problems, though.

Flower

OK i tried to convert the code below to get to work on EXPANDED Roms. I replaced all the .PATCH 07:xxxx to .PATCH 0F:xxxx. This isn't enough, the game still crashes - what do i do wrong? I am just starting to get used to asm, if someone could help solving this problem, this would be great.
Afterwards i would include the working code on the Wiki.

; ---------------------------------------------------------------------------
; Health Blocks
;
; by snarf and Drevan Zero
;
; 2/3/2013 - Version 1.0
; ---------------------------------------------------------------------------

.include labels.asm
    ; Includes all Metroid variables declared in the Metroid disassembly.
    ; Very convenient.


; ---------------------------------------------------------------------------
; Config
; ---------------------------------------------------------------------------

; To disable an option, place a semi-colon before the .define.
; To enable an option, remove a semi-colon.

;.define DEBUG                   ; Include debugging code
.define HealBlocks              ; Include heal blocks
.define HurtBlocks              ; Include hurt blocks
;.define HealSolid               ; Heal blocks are solid
;.define HurtSolid               ; Hurt blocks are solid
;.define BounceOnHurt            ; Get thrown back when touching a hurt block
;.define HurtWhenBlinking        ; Drain health while blinking
.define NoHurtWithVaria         ; Player is immune to hurt blocks with Varia

HealyTile = $FD                 ; (Tile number must be greater than $80)
HurtyTile = $FE                 ; (Tile number must be greater than $80)

; These two values use BCD. Use $, but write it as if decimal. E.g. to
; heal 1.5 health per frame, set HealRate to $0015
HealRate = $0001                ; Tenths of health added per frame
HurtRate = $0001                ; Tenths of health subtracted per frame

; ---------------------------------------------------------------------------
; Declarations
; ---------------------------------------------------------------------------

; Variables ------------

TouchingHealyBlock = $C9
TouchingHurtyBlock = $CA

; Existing Functions----

MakeCartRAMPtr   = $E96A
IsBlastTile      = $E9BE
Exit16           = $E81D
LavaAndMoveCheck = $E269
AddHealth        = $CEF9
SubtractHealth   = $CE92

; ---------------------------------------------------------------------------
; Code
; ---------------------------------------------------------------------------


; ---------------------------------------
.PATCH 07:E7E6
; Hit test Hijack
; ---------------------------------------

    ; This part of the routine is unchanged

HitTestHijack:
    LE7E6: 
        jsr MakeCartRAMPtr ;($E96A)Find object position in room RAM.
        ldy #$00
        lda ($04),y     ; get tile value
        cmp #$4E
        beq $E81E
        jsr $95C0
        jsr $D651
        bcc Exit16      ; CF = 0 if tile # < $80 (solid tile)... CRASH!!!
        cmp #$A0 ; is tile >= A0h? (walkable tile)

    ; These branches are changed to use the new IsWalkableTile that does our additional
    ; testing for healy blocks.   
    ;(its okay to overflow into next function because it is now unused)

    ;    bcs IsWalkableTile
    ;    jmp IsBlastTile  ; tile is $80-$9F (blastable tiles)
       
        bcc +
           jmp IsWalkableTile
        *
        jmp IsBlastTile

       
       
; ---------------------------------------
.PATCH 07:CD81
; Per frame Hijack
; ---------------------------------------

    ; Relacing this:
        ; jsr LavaAndMoveCheck
    ; With this:
        jsr HealthBlockCheck
       
    ; HealyBlockCheck will jump to LavaAndMoveCheck
       
; ---------------------------------------
.PATCH 07:CA35
; NEW CODE
; ---------------------------------------

    IsWalkableTile:
        ; New implementation of IsWalkableTile that does
        ; additional testing for healy blocks
           
   
        ldy IsSamus
        beq @NotSamus
       
        ; special case for Samus
       
       
    ; Test for healing block
        .ifdef HealBlocks
            cmp #HealyTile                  ; Is it a healy block?
            bne @NotHealyBlock
       
                lda #$01     
                sta TouchingHealyBlock     
               
                .ifdef DEBUG   
                    sta TankCount           ; Give samus 1 energy tank (debug only)
                .endif
               
                .ifdef HealSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHealyBlock:
        .endif
       
    ; Test for hurting block
        .ifdef HurtBlocks
            cmp #HurtyTile                  ; Is it a hurty block?
            bne @NotHurtyBlock
       
                lda #$01     
                sta TouchingHurtyBlock     
               
                .ifdef DEBUG   
                    lda #$02                 
                    sta TankCount           ; Give samus 2 energy tanks (debug only)
                .endif
               
                .ifdef HurtSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHurtyBlock:
        .endif
        pha                             ; Preserve tile number
       
        lda #$00
        sta TouchingHealyBlock
        sta TouchingHurtyBlock
        .ifdef DEBUG
            sta TankCount               ; Remove energy tank
        .endif
        pla                             ; Proceed with normal hit testing
       
       
        ; Below code is unchagned from original routine
       
        dey      ; = 0
        sty SamusDoorData
        cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
        cmp #$A1 ; crash with tile #$A1? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
       
        @NotSamus:
        dex
        beq +
        jsr $E98E
        jmp $E7E6
       
        *
        sec      ; no crash
        ; NO ;  Exit16:
        rts
       

    HealthBlockCheck:
        ; New routine that checks the TouchingHealyBlock variable and
        ; heals samus if applicable

        .ifdef HealBlocks
            lda TouchingHealyBlock
            beq +                       ; Touching healy block?
           
                ; Add health
                .if HealRate > $00FF
                    lda #>HealRate      ; Only set high byte if > $FF
                    sta HealthHiChange
                .endif
                lda #<HealRate
                sta HealthLoChange
                jsr AddHealth
               
                lda FrameCount          ; Every 20th frame...
                and #$1F
                bne +
                jsr $CBCA               ; Play sound
           
            *
        .endif
       
        .ifdef HurtBlocks
            lda TouchingHurtyBlock
            beq +                           ; Touching healy block?
           
                .ifndef HurtWhenBlinking
                    lda SamusBlink          ; Don't hurt samus if blinking
                    bne +
                .endif
               
                .ifdef NoHurtWithVaria
                    lda SamusGear           ; Don't take damage with varia
                    and #gr_VARIA
                    bne +
                .endif
           
                ; Subtract health
                .if HurtRate > $00FF        ; Only set high byte if > $FF
                    lda #>HurtRate
                    sta HealthHiChange
                .endif
                lda #<HurtRate
                sta HealthLoChange
                jsr SubtractHealth
               
                .ifdef BounceOnHurt
                    lda SamusBlink          ; Only bounce back when not blinking
                    bne +
                   
                    lda #$FF                ; This causes hit animation to occur
                    sta SamusHit
                .else
                    lda FrameCount      ; Every 20th frame...
                    and #$1F
                    bne +
                    jsr $CBCA           ; Play sound
                .endif
               
            *
        .endif
       
       
        jmp LavaAndMoveCheck        ; Return from hijack

       
    EndOfCode:
        ; If the assembled code extends beyond the available unused space,
        ; produce an error.
       
        .if EndOfCode >= $CAF5
            .error Code exceeded available size!
        .endif

Wirtualnosc

Those are the changes I applied:
- Removed the include directive, as labels are included in Editroid projects by default.
- Moved all the patches from bank 07 to 0F.
- Moved the 07:CA35 patch to 0F:C6A0 (since, as I mentioned, 0F:CA35 patch would overwrite expanded ROM's code - this is what most likely caused the crashes).
- Changed label IsWalkableTile to IsWalkableTileA as that label was already used (and Editroid didn't allow using it without messing with declarations files).
- Modified the address on EndOfCode check to $C7A0 (from what I know, it could actually be omitted; I left it here just in case, though).
The whole thing was compiled as Editroid project and worked without problems. If you want to apply more asm patches, just do more or less the same things I did. Most importantly, be careful of where you apply your additional, new code. Changing banks might not be enough - if it's not a hijack, then it probably needs to be patched at different offset as well.

Flower

Thanks a lot! Now i understand a little bit more about asm-Coding. But i need to gain knowledge.

For people interested: The changed code, working for expanded Roms via the Project Menu of Editroid:

; ---------------------------------------------------------------------------
; Health Blocks
;
; by snarf and Drevan Zero
;
; 2/3/2013 - Version 1.0
; ---------------------------------------------------------------------------

;.include labels.asm
    ; Includes all Metroid variables declared in the Metroid disassembly.
    ; Very convenient.


; ---------------------------------------------------------------------------
; Config
; ---------------------------------------------------------------------------

; To disable an option, place a semi-colon before the .define.
; To enable an option, remove a semi-colon.

;.define DEBUG                   ; Include debugging code
.define HealBlocks              ; Include heal blocks
.define HurtBlocks              ; Include hurt blocks
;.define HealSolid               ; Heal blocks are solid
;.define HurtSolid               ; Hurt blocks are solid
;.define BounceOnHurt            ; Get thrown back when touching a hurt block
;.define HurtWhenBlinking        ; Drain health while blinking
.define NoHurtWithVaria         ; Player is immune to hurt blocks with Varia

HealyTile = $FD                 ; (Tile number must be greater than $80)
HurtyTile = $FE                 ; (Tile number must be greater than $80)

; These two values use BCD. Use $, but write it as if decimal. E.g. to
; heal 1.5 health per frame, set HealRate to $0015
HealRate = $0001                ; Tenths of health added per frame
HurtRate = $0001                ; Tenths of health subtracted per frame

; ---------------------------------------------------------------------------
; Declarations
; ---------------------------------------------------------------------------

; Variables ------------

TouchingHealyBlock = $C9
TouchingHurtyBlock = $CA

; Existing Functions----

MakeCartRAMPtr   = $E96A
IsBlastTile      = $E9BE
Exit16           = $E81D
LavaAndMoveCheck = $E269
AddHealth        = $CEF9
SubtractHealth   = $CE92

; ---------------------------------------------------------------------------
; Code
; ---------------------------------------------------------------------------


; ---------------------------------------
.PATCH 0F:E7E6
; Hit test Hijack
; ---------------------------------------

    ; This part of the routine is unchanged

HitTestHijack:
    LE7E6: 
        jsr MakeCartRAMPtr ;($E96A)Find object position in room RAM.
        ldy #$00
        lda ($04),y     ; get tile value
        cmp #$4E
        beq $E81E
        jsr $95C0
        jsr $D651
        bcc Exit16      ; CF = 0 if tile # < $80 (solid tile)... CRASH!!!
        cmp #$A0 ; is tile >= A0h? (walkable tile)

    ; These branches are changed to use the new IsWalkableTileA that does our additional
    ; testing for healy blocks.   
    ;(its okay to overflow into next function because it is now unused)

    ;    bcs IsWalkableTileA
    ;    jmp IsBlastTile  ; tile is $80-$9F (blastable tiles)
       
        bcc +
           jmp IsWalkableTileA
        *
        jmp IsBlastTile

       
       
; ---------------------------------------
.PATCH 0F:CD81
; Per frame Hijack
; ---------------------------------------

    ; Relacing this:
        ; jsr LavaAndMoveCheck
    ; With this:
        jsr HealthBlockCheck
       
    ; HealyBlockCheck will jump to LavaAndMoveCheck
       
; ---------------------------------------
.PATCH 0F:C6A0
; NEW CODE
; ---------------------------------------

    IsWalkableTileA:
        ; New implementation of IsWalkableTile that does
        ; additional testing for healy blocks
           
   
        ldy IsSamus
        beq @NotSamus
       
        ; special case for Samus
       
       
    ; Test for healing block
        .ifdef HealBlocks
            cmp #HealyTile                  ; Is it a healy block?
            bne @NotHealyBlock
       
                lda #$01     
                sta TouchingHealyBlock     
               
                .ifdef DEBUG   
                    sta TankCount           ; Give samus 1 energy tank (debug only)
                .endif
               
                .ifdef HealSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHealyBlock:
        .endif
       
    ; Test for hurting block
        .ifdef HurtBlocks
            cmp #HurtyTile                  ; Is it a hurty block?
            bne @NotHurtyBlock
       
                lda #$01     
                sta TouchingHurtyBlock     
               
                .ifdef DEBUG   
                    lda #$02                 
                    sta TankCount           ; Give samus 2 energy tanks (debug only)
                .endif
               
                .ifdef HurtSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHurtyBlock:
        .endif
        pha                             ; Preserve tile number
       
        lda #$00
        sta TouchingHealyBlock
        sta TouchingHurtyBlock
        .ifdef DEBUG
            sta TankCount               ; Remove energy tank
        .endif
        pla                             ; Proceed with normal hit testing
       
       
        ; Below code is unchagned from original routine
       
        dey      ; = 0
        sty SamusDoorData
        cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
        cmp #$A1 ; crash with tile #$A1? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
       
        @NotSamus:
        dex
        beq +
        jsr $E98E
        jmp $E7E6
       
        *
        sec      ; no crash
        ; NO ;  Exit16:
        rts
       

    HealthBlockCheck:
        ; New routine that checks the TouchingHealyBlock variable and
        ; heals samus if applicable

        .ifdef HealBlocks
            lda TouchingHealyBlock
            beq +                       ; Touching healy block?
           
                ; Add health
                .if HealRate > $00FF
                    lda #>HealRate      ; Only set high byte if > $FF
                    sta HealthHiChange
                .endif
                lda #<HealRate
                sta HealthLoChange
                jsr AddHealth
               
                lda FrameCount          ; Every 20th frame...
                and #$1F
                bne +
                jsr $CBCA               ; Play sound
           
            *
        .endif
       
        .ifdef HurtBlocks
            lda TouchingHurtyBlock
            beq +                           ; Touching healy block?
           
                .ifndef HurtWhenBlinking
                    lda SamusBlink          ; Don't hurt samus if blinking
                    bne +
                .endif
               
                .ifdef NoHurtWithVaria
                    lda SamusGear           ; Don't take damage with varia
                    and #gr_VARIA
                    bne +
                .endif
           
                ; Subtract health
                .if HurtRate > $00FF        ; Only set high byte if > $FF
                    lda #>HurtRate
                    sta HealthHiChange
                .endif
                lda #<HurtRate
                sta HealthLoChange
                jsr SubtractHealth
               
                .ifdef BounceOnHurt
                    lda SamusBlink          ; Only bounce back when not blinking
                    bne +
                   
                    lda #$FF                ; This causes hit animation to occur
                    sta SamusHit
                .else
                    lda FrameCount      ; Every 20th frame...
                    and #$1F
                    bne +
                    jsr $CBCA           ; Play sound
                .endif
               
            *
        .endif
       
       
        jmp LavaAndMoveCheck        ; Return from hijack

       
    EndOfCode:
        ; If the assembled code extends beyond the available unused space,
        ; produce an error.
       
        .if EndOfCode >= $C7A0
            .error Code exceeded available size!
        .endif

Flower

OK, as i tried further to include asm in my Editroid-Project, the Walljump-Addon won't get to work.
The Code is from the Wiki: http://wiki.metroidconstruction.com/doku.php?id=metroid:asm:walljump.

; This code allows for a wall-jump in Metroid (NES)
; Copyright 2002-2004 Parasyte
; http://parasyte.panicus.org/
;
; The above copyright notice may not be removed or changed.
;
;
; Notes:
; Simply overwrite the data at file address 0x01CADF (38 bytes, max)
; with this code. Then set the hook by patching 0x01CC34 to 0xCF,0xCA


.org $CACF ;assemble our code to run at this (CPU) address
;.mem 8 ;setup accumulator and index regs for NES code
;.index 8


;--constants
BtnRight = $01 ;Joypad button definitions.
BtnLeft = $02
BtnDown = $04
BtnUp = $08
BtnStart = $10
BtnSelect = $20
BtnB = $40
BtnA = $80


;--pointers
JoypadDown = $12
Joypad = $14

JumpSpeed = $0308

DoJump = $CD40 ;Makes Samus Jump

WallToLeft = $E880 ;Checks for a wall to the left of Samus, returns result in C flag: Set = no, Clear = yes.
WallToRight = $E88B ;Checks for a wall to the right of Samus, returns result in C flag: Set = no, Clear = yes.




;--Entry Point
; Inputs: None
; Outputs: None
; Description: Checks if Samus is able to wall jump, performs action if possible.

lda JoypadDown ;Is A button just pressed?
bpl exit

lda #BtnRight
bit Joypad ;D-Pad Right held?
bne +

asl
bit Joypad ;D-Pad Left held?
beq exit

;Check if able to wall jump to the left.
jsr WallToRight
bcs exit
bcc ++ ;Branch always.

;Check if able to wall jump to the right.
+ jsr WallToLeft
bcs exit

++ lda JumpSpeed ;Is Samus in a slow decent?
bne exit

jsr DoJump

exit:
jmp $CCC2 ;Bye-bye!


As from Wirtualnosc's former instructions, i changed ".org $CACF" to ".org $C6A0" and then (just to try out if it collides with the already included Code above "HealthBlocks") to ".org $C6A1".
Maybe there need to be several things changed?
QuoteIt is (probably) intended for X816 but should assemble with ASM6 with little or no modification.

Conclusion: The Code just doesn't work. The Game doesn't crash, but neither does the Walljump work.  :bounce:

Any suggestions?
Thanks!! =) great Forum!!  :^_^:

Flower



:cry: When i tried to (re-)open the ROM, in which i included the Healthyblock Code (as quoted above) i got an exception, and thus am unable to open it and edit it any further.
What to do now :?:

I included a created .ips-file and the nes.proj from Editroid, just in case.

Thanks for you help!

snarfblam

I had to dissect the file to recover everything, but I think it's fixed now. (You'll want to rename it to match the ROM, of course.)

https://dl.dropboxusercontent.com/u/12027218/Temp/Metroid%20%28USA%20fixt%29.nes.proj

I had to dig around a little to figure out exactly what happened. You probably want to download this more recent build of Editroid. Sorry about that!


Flower

Thanks a lot snarf!  :^_^:

Fortunately i did not build any tiles, sprites or rooms in the ROM above.
My graphical hacking progress ('til now only tiles, neither combos nor structures or rooms) is saved into external bitmap-files.
I gradually gain knowledge about painting tiles and sprites, coding asm, thinking about level design, ... That's one thing i love about Hacking: It's such multifarious work!  :wink:

I am curious about the new Version of Editroid, it's such a great tool. Let's see if it deals better with additional asm.

Keep up the good work!

Wirtualnosc

The wall jump code you presented might need more modifications:
- You'll have to add a patch at 0F:CC34 and add a jmp instruction to your code,
- Replace pluses at the beginning of each line they appear with asterisks,
- You'll have to find other address to paste than C6A0 (as your health block code is there already). I recommend adding a label at the end of that patch and pasting the code here instead.
- I'd recommend replacing .org directive with .patch.

Flower

Hey snarf, the Code from HealthBlocks (as is in the .proj-File) works when it is build into my ROM.
But i've got a Problem: Doors don't work anymore! The Game glitches, Samus is somewhere off Screen, thus Game-Breaking.

I guess the Problem is with this part of the Code:
; Below code is unchagned from original routine
       
        dey      ; = 0
        sty SamusDoorData
        cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
        cmp #$A1 ; crash with tile #$A1? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
       
        @NotSamus:
        dex
        beq +
        jsr $E98E
        jmp $E7E6
       
        *
        sec      ; no crash
        ; NO ;  Exit16:
        rts


I used the Roidz-Hack to start with, where there are Vertical Door Tiles from A0-A7 and Horizontal Door Tiles from A8-AF.
I don't get the Code changed to work with those additional Door Tiles.

I tried to change this part:
cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
        cmp #$A1 ; crash with tile #$A1? (horizontal scrolling door)
        bne ++

to this:
cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
cmp #$A1 ; crash with tile #$A1? (scroll toggling door)
        beq +
cmp #$A2 ; crash with tile #$A2? (scroll toggling door)
        beq +
cmp #$A3 ; crash with tile #$A3? (scroll toggling door)
        beq +
cmp #$A4 ; crash with tile #$A4? (scroll toggling door)
        beq +
cmp #$A5 ; crash with tile #$A5? (scroll toggling door)
        beq +
cmp #$A6 ; crash with tile #$A6? (scroll toggling door)
        beq +
cmp #$A7 ; crash with tile #$A7? (scroll toggling door)
        beq +
        cmp #$A8 ; crash with tile #$A8? (horizontal scrolling door)
        bne ++
        cmp #$A9 ; crash with tile #$A9? (horizontal scrolling door)
        bne ++
        cmp #$AA ; crash with tile #$AA? (horizontal scrolling door)
        bne ++
        cmp #$AB ; crash with tile #$AB? (horizontal scrolling door)
        bne ++
        cmp #$AC ; crash with tile #$AC? (horizontal scrolling door)
        bne ++
        cmp #$AD ; crash with tile #$AD? (horizontal scrolling door)
        bne ++
        cmp #$AE ; crash with tile #$AE? (horizontal scrolling door)
        bne ++
        cmp #$AF ; crash with tile #$AF? (horizontal scrolling door)
        bne ++

or this:
cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
cmp #$A1 ; crash with tile #$A1? (scroll toggling door)
cmp #$A2 ; crash with tile #$A2? (scroll toggling door)
cmp #$A3 ; crash with tile #$A3? (scroll toggling door)
cmp #$A4 ; crash with tile #$A4? (scroll toggling door)
cmp #$A5 ; crash with tile #$A5? (scroll toggling door)
cmp #$A6 ; crash with tile #$A6? (scroll toggling door)
        beq +
        cmp #$A7 ; crash with tile #$A7? (scroll toggling door)
        cmp #$A8 ; crash with tile #$A8? (horizontal scrolling door)
        cmp #$A9 ; crash with tile #$A9? (horizontal scrolling door)
        cmp #$AA ; crash with tile #$AA? (horizontal scrolling door)
        cmp #$AB ; crash with tile #$AB? (horizontal scrolling door)
        cmp #$AC ; crash with tile #$AC? (horizontal scrolling door)
        cmp #$AD ; crash with tile #$AD? (horizontal scrolling door)
        cmp #$AE ; crash with tile #$AE? (horizontal scrolling door)
        cmp #$AF ; crash with tile #$AF? (horizontal scrolling door)
        bne ++

...but that didn't solve the Problem.

One more thing to mention is i tried that with the Door Scrolling Patch applied AND also without it.

Do you or anyone else know how to fix this?

SChase123

Did you try applying the patch before expanding the ROM file?

Flower

Actually no. In this case I took an expanded Rom and applied the patch via the Project Menu from Editroid. Without the patch everything works well regarding doors. But when I build and launch the Rom I get those door mistakes. And my guess was to change the certain part of the code to work for more door tiles (usually there are just 2, not 16 like in my case). And I don't know how..yet

Flower

My approach was to paint tiles and draw levels first before applying any asm changes. I thought this was safer. Last time I used the map and save patch in advance and was unable to use the test room feature. What a mess!

Flower

I did find out for myself how it's possible to use the Health / Hurt - Blocks Code for more than 2 door tiles (in this case 16 like for example in the Roidz-Hack with tiles A0-A7 normal or vertical door tiles and A8-AF horizontal door tiles).

You just need to expand the Code a bit, so it's like that:
; ---------------------------------------------------------------------------
; Health Blocks
;
; by snarf and Drevan Zero
;
; 2/3/2013 - Version 1.0
; ---------------------------------------------------------------------------

;.include labels.asm
    ; Includes all Metroid variables declared in the Metroid disassembly.
    ; Very convenient.


; ---------------------------------------------------------------------------
; Config
; ---------------------------------------------------------------------------

; To disable an option, place a semi-colon before the .define.
; To enable an option, remove a semi-colon.

;.define DEBUG                   ; Include debugging code
.define HealBlocks              ; Include heal blocks
.define HurtBlocks              ; Include hurt blocks
;.define HealSolid               ; Heal blocks are solid
;.define HurtSolid               ; Hurt blocks are solid
;.define BounceOnHurt            ; Get thrown back when touching a hurt block
;.define HurtWhenBlinking        ; Drain health while blinking
.define NoHurtWithVaria         ; Player is immune to hurt blocks with Varia

HealyTile = $FD                 ; (Tile number must be greater than $80)
HurtyTile = $FE                 ; (Tile number must be greater than $80)

; These two values use BCD. Use $, but write it as if decimal. E.g. to
; heal 1.5 health per frame, set HealRate to $0015
HealRate = $0001                ; Tenths of health added per frame
HurtRate = $0001                ; Tenths of health subtracted per frame

; ---------------------------------------------------------------------------
; Declarations
; ---------------------------------------------------------------------------

; Variables ------------

TouchingHealyBlock = $C9
TouchingHurtyBlock = $CA

; Existing Functions----

MakeCartRAMPtr   = $E96A
IsBlastTile      = $E9BE
Exit16           = $E81D
LavaAndMoveCheck = $E269
AddHealth        = $CEF9
SubtractHealth   = $CE92

; ---------------------------------------------------------------------------
; Code
; ---------------------------------------------------------------------------


; ---------------------------------------
.PATCH 0F:E7E6
; Hit test Hijack
; ---------------------------------------

    ; This part of the routine is unchanged

HitTestHijack:
    LE7E6: 
        jsr MakeCartRAMPtr ;($E96A)Find object position in room RAM.
        ldy #$00
        lda ($04),y     ; get tile value
        cmp #$4E
        beq $E81E
        jsr $95C0
        jsr $D651
        bcc Exit16      ; CF = 0 if tile # < $80 (solid tile)... CRASH!!!
        cmp #$A0 ; is tile >= A0h? (walkable tile)

    ; These branches are changed to use the new IsWalkableTileA that does our additional
    ; testing for healy blocks.   
    ;(its okay to overflow into next function because it is now unused)

    ;    bcs IsWalkableTileA
    ;    jmp IsBlastTile  ; tile is $80-$9F (blastable tiles)
       
        bcc +
           jmp IsWalkableTileA
        *
        jmp IsBlastTile

       
       
; ---------------------------------------
.PATCH 0F:CD81
; Per frame Hijack
; ---------------------------------------

    ; Relacing this:
        ; jsr LavaAndMoveCheck
    ; With this:
        jsr HealthBlockCheck
       
    ; HealyBlockCheck will jump to LavaAndMoveCheck
       
; ---------------------------------------
.PATCH 0F:C6A0
; NEW CODE
; ---------------------------------------

    IsWalkableTileA:
        ; New implementation of IsWalkableTile that does
        ; additional testing for healy blocks
           
   
        ldy IsSamus
        beq @NotSamus
       
        ; special case for Samus
       
       
    ; Test for healing block
        .ifdef HealBlocks
            cmp #HealyTile                  ; Is it a healy block?
            bne @NotHealyBlock
       
                lda #$01     
                sta TouchingHealyBlock     
               
                .ifdef DEBUG   
                    sta TankCount           ; Give samus 1 energy tank (debug only)
                .endif
               
                .ifdef HealSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHealyBlock:
        .endif
       
    ; Test for hurting block
        .ifdef HurtBlocks
            cmp #HurtyTile                  ; Is it a hurty block?
            bne @NotHurtyBlock
       
                lda #$01     
                sta TouchingHurtyBlock     
               
                .ifdef DEBUG   
                    lda #$02                 
                    sta TankCount           ; Give samus 2 energy tanks (debug only)
                .endif
               
                .ifdef HurtSolid
                    clc                     ; Return, solid block
                .else
                    sec                     ; Return, air block
                .endif
                rts
            @NotHurtyBlock:
        .endif
        pha                             ; Preserve tile number
       
        lda #$00
        sta TouchingHealyBlock
        sta TouchingHurtyBlock
        .ifdef DEBUG
            sta TankCount               ; Remove energy tank
        .endif
        pla                             ; Proceed with normal hit testing
       
       
        ; Below code is unchagned from original routine
       
        dey      ; = 0
        sty SamusDoorData
        cmp #$A0 ; crash with tile #$A0? (scroll toggling door)
        beq +
        cmp #$A8 ; crash with tile #$A8? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A1 ; crash with tile #$A1? (scroll toggling door)
        beq +
        cmp #$A9 ; crash with tile #$A9? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A2 ; crash with tile #$A2? (scroll toggling door)
        beq +
        cmp #$AA ; crash with tile #$AA? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A3 ; crash with tile #$A3? (scroll toggling door)
        beq +
        cmp #$AB ; crash with tile #$AB? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A4 ; crash with tile #$A4? (scroll toggling door)
        beq +
        cmp #$AC ; crash with tile #$AC? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A5 ; crash with tile #$A5? (scroll toggling door)
        beq +
        cmp #$AD ; crash with tile #$AD? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A6 ; crash with tile #$A6? (scroll toggling door)
        beq +
        cmp #$AE ; crash with tile #$AE? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
        cmp #$A7 ; crash with tile #$A7? (scroll toggling door)
        beq +
        cmp #$AF ; crash with tile #$AF? (horizontal scrolling door)
        bne ++
        inc SamusDoorData
        *
        inc SamusDoorData
        *
       
        @NotSamus:
        dex
        beq +
        jsr $E98E
        jmp $E7E6
       
        *
        sec      ; no crash
        ; NO ;  Exit16:
        rts
       

    HealthBlockCheck:
        ; New routine that checks the TouchingHealyBlock variable and
        ; heals samus if applicable

        .ifdef HealBlocks
            lda TouchingHealyBlock
            beq +                       ; Touching healy block?
           
                ; Add health
                .if HealRate > $00FF
                    lda #>HealRate      ; Only set high byte if > $FF
                    sta HealthHiChange
                .endif
                lda #<HealRate
                sta HealthLoChange
                jsr AddHealth
               
                lda FrameCount          ; Every 20th frame...
                and #$1F
                bne +
                jsr $CBCA               ; Play sound
           
            *
        .endif
       
        .ifdef HurtBlocks
            lda TouchingHurtyBlock
            beq +                           ; Touching healy block?
           
                .ifndef HurtWhenBlinking
                    lda SamusBlink          ; Don't hurt samus if blinking
                    bne +
                .endif
               
                .ifdef NoHurtWithVaria
                    lda SamusGear           ; Don't take damage with varia
                    and #gr_VARIA
                    bne +
                .endif
           
                ; Subtract health
                .if HurtRate > $00FF        ; Only set high byte if > $FF
                    lda #>HurtRate
                    sta HealthHiChange
                .endif
                lda #<HurtRate
                sta HealthLoChange
                jsr SubtractHealth
               
                .ifdef BounceOnHurt
                    lda SamusBlink          ; Only bounce back when not blinking
                    bne +
                   
                    lda #$FF                ; This causes hit animation to occur
                    sta SamusHit
                .else
                    lda FrameCount      ; Every 20th frame...
                    and #$1F
                    bne +
                    jsr $CBCA           ; Play sound
                .endif
               
            *
        .endif
       
       
        jmp LavaAndMoveCheck        ; Return from hijack

       
    EndOfCode:
        ; If the assembled code extends beyond the available unused space,
        ; produce an error.
       
        .if EndOfCode >= $C7A0
            .error Code exceeded available size!
        .endif


It was just a little change necessary but i am indeed a little bit proud having found out how to do it.
I hope it is useful!!
Cheers!

Flower

Quote from: Wirtualnosc on April 22, 2016, 12:25:05 PM
The wall jump code you presented might need more modifications:
- You'll have to add a patch at 0F:CC34 and add a jmp instruction to your code,
- Replace pluses at the beginning of each line they appear with asterisks,
- You'll have to find other address to paste than C6A0 (as your health block code is there already). I recommend adding a label at the end of that patch and pasting the code here instead.
- I'd recommend replacing .org directive with .patch.

@Wirtualnosc Dude, I am a asm-noob, can you just lend me a hand and modify the code and post it here? That would be absolutely awesome!