Language…
8 users online: Green Jerry, Ice Man, kurtistrydiz, Nyumi_996, Phyll, Shiki_Makiro, Sluwu, TheMorganah - Guests: 112 - Bots: 99
Users: 69,207 (2,358 active)
Latest user: lapakspin99

Untouchable Enemies [Help]

Hi Everybody,

I have an idea to create some kind of 'pacifist mod' for smw, where touching enemies will kill mario.
I've been trying to use chatGPT to write some logic that wont allow mario to touch enemies and using asar to compile it, but It's been very challenging to find the correct collision stuff without crashing the game.
Does anyone have any kind of help to provide?

Thank you so much!
Originally posted by eddyhazard
I've been trying to use chatGPT to write some logic that wont allow mario to touch enemies and using asar to compile it, but It's been very challenging to find the correct collision stuff without crashing the game.

Yeah, even if by some miracle you get Asar to compile whatever ChatGPT hallucinates, this won't work. To use GPT (or any other LLM for that matter) to generate code for such a niche usecase will not work well, what with not being enough material to train to begin with.

Now then, for where you could begin looking. This is complicated by the fact different sprites can use different, specific interaction routines. In the simplest case, we have the sprites which use "default interaction", such as Koopas or Piranha Plants, which share an interaction routine which begins at ROM location $01A83B. Skipping below the routine for when Mario has a star or is interacting with a carryable sprite, we have this code block.
Code
CODE_01A897:        A9 14         LDA.B #$14                
CODE_01A899:        85 01         STA $01                   
CODE_01A89B:        A5 05         LDA $05                   
CODE_01A89D:        38            SEC                       
CODE_01A89E:        E5 01         SBC $01                   
CODE_01A8A0:        26 00         ROL $00                   
CODE_01A8A2:        C5 D3         CMP $D3                   
CODE_01A8A4:        08            PHP                       
CODE_01A8A5:        46 00         LSR $00                   
CODE_01A8A7:        A5 0B         LDA $0B                   
CODE_01A8A9:        E9 00         SBC.B #$00                
CODE_01A8AB:        28            PLP                       
CODE_01A8AC:        E5 D4         SBC $D4                   
CODE_01A8AE:        30 36         BMI CODE_01A8E6           

What this does in simple terms is see whether Mario touched the top or the bottom of a sprite. That last line branches is Mario is touching the bottom, where the code does some extra checks to see whether to hurt Mario. We could change this branch to always jump no matter where Mario is contacting the sprites:
Code
org $01A8AE
    db $80

If we now check $01A8E6, we see another branch.
Code
CODE_01A8E6:        AD ED 13      LDA.W $13ED               
CODE_01A8E9:        F0 0E         BEQ CODE_01A8F9           

This makes sure Mario isn't sliding and branches if he isn't. If you want Mario to also get hurt with sliding on an enemy, you would change this to always branch as well.
Code
org $01A8E9
    db $80

Finally, this last block.
Code
CODE_01A8F9:        AD 97 14      LDA.W $1497               ; \ Return if Mario is invincible 
CODE_01A8FC:        D0 1D         BNE Return01A91B          ; / 
CODE_01A8FE:        AD 7A 18      LDA.W RAM_OnYoshi         
CODE_01A901:        D0 18         BNE Return01A91B          
CODE_01A903:        BD 86 16      LDA.W RAM_Tweaker1686,X   
CODE_01A906:        29 10         AND.B #$10                
CODE_01A908:        D0 07         BNE CODE_01A911           
CODE_01A90A:        20 30 AD      JSR.W SubHorizPos         
CODE_01A90D:        98            TYA                       
CODE_01A90E:        9D 7C 15      STA.W RAM_SpriteDir,X     
CODE_01A911:        B5 9E         LDA RAM_SpriteNum,X       
CODE_01A913:        C9 53         CMP.B #$53                
CODE_01A915:        F0 04         BEQ Return01A91B          
CODE_01A917:        22 B7 F5 00   JSL.L HurtMario           
Return01A91B:       60            RTS                       ; Return 

If you want Mario to outright get killed and don't care about him being on Yoshi and such, you'd change this to only jump to the kill routine and then finish. To do so:
Code
org $01A8F9
    JSL $00F606 ;   There was contact. Kill Mario.
    RTS         ;   Stop.

Our patch then would be:
Code
; This patch makes sprites with default interaction kill Mario when touched.

org $01A8AE     ;   always act as if Mario touched below the sprite, to check if kill him.
    db $80
org $01A8E9     ;   bypass slopes.
    db $80
org $01A8F9     ;   actually hurt Mario.
    JSL $00F606 ;   There was contact. Kill Mario.
    RTS         ;   Stop.

Then you'd have to take care of every special sprite which DOESN'T use default interaction, such as Wigglers. This is more tedious and will definitely require more work. If you want to check, I recommend getting a disassembly (such as all.log or Thomas' disassembly) and looking for where a custom interaction routine is run. In all.log you can find those as lines which are JSR.W MarioSprInteractRt or JSL.L MarioSprInteract and then followed by a BCC or BCS.
Please check out BOWSIE!
better days coming for sure
Holyyyyyy, that works wonders! I really appreciate your help,  Erik!

But it seems like this is waaaay out of my league to undertand and code the other iterations haha

By the way, why cant I find the $018A3B address on the map?
I'll try to dig a little deeper
Originally posted by eddyhazard
Holyyyyyy, that works wonders! I really appreciate your help,  Erik!

But it seems like this is waaaay out of my league to undertand and code the other iterations haha

You're welcome!
If you want to keep exploring this idea and get stuck with something, you can always either make a post in here or join the SMWC Discord server and ask for guidance in the #asm channel. The Discord is pretty active so chances are you'll get someone to help you in there 😃

Quote
By the way, why cant I find the $018A3B address on the map?

This is a ROM address, so it's in the ROM Map.
Still, there may be occasions where you don't find something in the map. Not every single piece of code is documented in the map.
e: oh I accidentally mistyped it lol... I meant to say $01A83B in my original post, and that's why. Sorry!
Please check out BOWSIE!
better days coming for sure
 Erik, once again thanks a lot for your help!

I started doing some more research, joined the discord, and I can understand things a little better now (halfway through Ersanio's tutorial).

In the code you provided, for example:

org $01A8AE
db $80

Is this db $80 just an arbitrary value to overwrite the comparison on the address 01A8AE or is there any other reason for it?

Thank you!
The purpose of org $01A8AE : db $80 is to replace an opcode. It originally is a BMI for the purpose to check if Mario's feet are above or below the sprite and the code will jump to the SpriteWins routine if they aren't. Changing it to $80 means to replace it with BRA which causes it to always jump to SpriteWins.

tl;dr It changes a conditional jump to an unconditional jump.