Banner
Views: 854,150,317
Time:
20 users online:  1UPdudes, AnasMario130, autisticsceptile1993, Dispace, Duraner Hawkeye, ExONightZ, Far, Golden Yoshi,  KevinM, KitikuSa, Matheus2653, MecchaSugoiTntn, MegaSonic1999, Nicoke42, Ralshi02, RyanRocksHacking, Synergic,  Tahixham, viniciuskombat, WhiteYoshiEgg - Guests: 47 - Bots: 62 Users: 47,133 (2,480 active)
Latest: Helloworld
Tip: Use PIXI to insert custom sprites into your hack.Not logged in.
Pat's Simple Basic ASM Tutorial!
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Pat's Simple Basic ASM Tutorial!
Pages: « 1 »
Hello, most of you may not know me, but I had a bit of trouble with ASM at first. A lot of ASM tutorials seemed too complex, too wordy, too unorganized. Without a doubt, Schwa's ASM tutorial and Ersanio's ASM tutorial helped me a lot, but it was still a bit hard to get used to. I don't want anyone else to be confused, so let's get ready to rock and roll!

Just to let you guys know, I haven't mastered sprites enough to be too trustworthy about that, but I assure you when I do I will add that to the tutorial. #w{=3} On the other hand, I'm confident I'm very good at blocks and other ASM in general.

1: Values.

Let's start off with learning about values like 0, a hexadecimal value, or just hex for short. This translates to 0 as a real number we use in the real world outside of programming. Likewise, hex 1 translates to 1, and hex 2 translates to 2. Hex 9 translates to 9. A, B, C, D, E, and F are also hex values. Hex A translates to 10, hex B translates to 11, all the way up to hex F, which is 15. After you get past hex F, it's just hex 10, and the cycle repeats. For example, hex 1F is 32, and hex FF is 256. One more thing you should note, hex 0 is still treated as any other value. This is why every value from hex 0 to hex F is actually 16 different values you can use!

There are hex 1FF sublevels, or 512, in Super Mario World! There's no doubt that you can fit a long and fun hack into that amount!

2: Basic commands.

We're not going to work on blocks just yet. For now, you'll learn the basic commands that you'll need to know first!

LDA is a vital command in ASM. It loads either an independent value, as I like to call them, that you specify, or loads whatever is already stored to a RAM address. You can find what is stored in RAM addresses by clicking this link.

First we'll work with exact values. Let's look at this piece of code.

Code
LDA #$01


This is loading #$01, a hex value. This is the independent value you're loading because it doesn't rely on other RAM addresses. You can load anything from #$00 to #$FF.

Try looking at this code now.

Code
LDA $19


This is loading the hex value that is currently loaded to the RAM address $7E0019. You don't have to type the whole thing if it's only two ending hex values like 19. If it was $7E1697, which you can see is the amount of enemies stomped if you click here and look at the top of the webpage, you'd only need to type $1697. So, if you stomped on 4 different Koopas, this value would be #$04. If you haven't stomped on anything, it would just be #$00. Note that other addresses don't necessarily have #$00 mean nothing. $14AF, the value used by the ON/OFF blocks, uses #$00 to indicate that the switch is set to ON, and #$01 to indicate that it is set to OFF.

Let's look at the same code again.

Code
LDA $19


You now know it's loading the value of Mario's power-up status. If Mario is small, it's #$00. If he's big, it's #$01. If he has a cape, it's #$02. If he has a fire power-up, it's #$03. Now, let's look at the RAM address used for message box triggers. You're probably wondering what Mario's power-up has to do with message boxes. Well, let's look at this next code!

Code
LDA $19
STA $1426


STA is the command that stores the value you last loaded using LDA to the RAM address you specify. In this case, it's storing the value of Mario's power-up to $1426. If Mario has no power-up, nothing will happen. If he does, he will be faced with a message box when the code is run. If he's big, the level's first message will appear; if he has a cape, the second one will appear. If he has the fire flower, Yoshi's thank you message will appear.

Let's look at the code once more!

Code
LDA $19
STA $1426
RTL


You're probably wondering what "RTL" means. Remove all the complicated talk and you know RTL ends the code, and returns to the beginning of the code to attempt to run again if need be.

There's also two commands that help a bit every once in a while. INC increases a RAM address by 1, and DEC decreases a RAM address by 1. If the address' stored value is #$FF, INC will change it to #$00. If it's #$00, DEC will make it #$FF.

Code
INC $19
RTL


This would make Mario turn into big Mario if he's small, or caped if he's big, and so on. Not recommended to use unused power-ups.

Code
DEC $19
RTL


This does the exact reverse, and once again you should not use unused power-ups.

Sometimes you'll need to work with more than just 1, so you're going to need to use a few more commands.

Code
LDA $0DBE
CLC
ADC #$05


The RAM address being used right now is the amount of lives the player has. This code adds #$05 to the $0DBE, so if the player has #$A8 lives, this code will make the player have #$AD lives.

Code
LDA $0DBE
SEC
SBC #$05


This command does the opposite; this means it will subtract #$05 from a given RAM address' value. #$A8 would become #$A3.

You can also multiply or divide a value by 2.

Code
LDA #$02
ASL A
RTL


This multiplies #$02 by 2, which is pointless because we can just do LDA #$04. However, you can also use a RAM address instead, such as $0DBE.

Code
ASL $0DBE
RTL


This will multiply the player's lives by 2. If the player has #$09 lives, they will have #$12 lives.

Code
LSR $0DBE
RTL


This will divide the player's lives by 2. Simple, right?

There's one more command before we move on. That is STZ. STZ sets the specified RAM address to #$00. Like this:

Code
STZ $19
RTL


This code would instantly make Mario lose his power-up.

3. Branching.

A lot of times just LDA and STA won't cut it; you're going to need conditional commands that only work when certain conditions have been met. Here you'll learn about branching.

Let's look at some of our previous code.

Code
LDA $19
STA $1426
RTL


This stores the value of Mario's power-up to the message box trigger. But what if we wanted to exclude Yoshi's thank you message? We'd use a branching command.

Let's look at this new code.

Code
LDA $19
CMP #$03


CMP is short for "compare." The value of Mario's current power-up is being compared to #$03. This means if the value $19 is being compared to matches the value #$03, the system will know that Mario's current power-up is the cape. But where does branching come in?

Code
LDA $19
CMP #$03
BEQ Label
RTL


BEQ is a branching command. "Label" can be changed to anything, but we'll go over that in a bit. BEQ checks if the value being loaded matches the value it's compared to. If it does match, it jumps to the label's code. If not, it proceeds to the code below the BEQ command. Now, let's see about that confusing label.

Code
LDA $19
CMP #$03
BEQ Label
RTL

Label:
LDA #$03
STA $1426
RTL


As you know, if $19 matches #$03, it will jump to the code under "Label." Once again, "Label" can be changed to anything, you just need to make sure BEQ will redirect to the correct label. But what if we wanted to display Yoshi's message only, and only when Mario has a power-up?

Code
LDA $19
BNE Label
RTL

Label:
LDA #$03
STA $1426
RTL


First off, you may notice I didn't add CMP #$00 after LDA $19. This is because BEQ and BNE treat the compared value as #$00 if you don't specify what the compared value is.

BNE is another branching command that works the opposite of BEQ. If the loaded value doesn't match the value it's being compared to, only then it will jump to the label. This means if $19 was any value from #$01 to #$FF (which normally shouldn't happen) it would jump to Label and display Yoshi's thank you message, but if it was #$00 it wouldn't.

You could also use this:

Code
LDA $19
BCS Label
RTL

Label:
LDA #$03
STA $1426
RTL


BCS is a branching code that branches to the specified label if the loaded value is greater than the value it's compared to. BCC is another branching code that branches if the value is less than the compared value. So you could also use this code:

Code
LDA $19
CMP #$01
BCC Label
RTL

Label:
LDA #$03
STA $1426
RTL


However, this is less efficient because it's a waste of a line, which wastes free space in your ROM. Remember, you only have so much room to work with, so make the best of it!

Code
BRA Label


This code is by itself because BRA is a special branching command. It always jumps to the specified label if it's run! This means you can have a code like this:

Code
LDA $19
BEQ Message1
LDA #$03
STA $1426
BRA Message2

Message1:
LDA #$01
STA $1426
BRA End

Message2:
LDA #$02
STA $1426
BRA End

End:
LDA #$03
STA $19
RTL


And you won't have to write the code in the "End" label two times. In this case it doesn't matter too much because it's such a small amount of code, but on a bigger project BRA will definitely help.

4. Blocks.

Now we can actually start doing something with our new knowledge of ASM!

For a block, you'll need to start off with adding this at the top of your ASM file:

Code
db $42


You'll want to put this under that as well:

Code
JMP MarioBelow : JMP MarioAbove : JMP MarioSide
JMP SpriteV : JMP SpriteH
JMP Cape : JMP Fireball
JMP MarioCorner : JMP MarioBody : JMP MarioHead


You've probably seen people use different JMPs if you've used blocks in the SMW Blocks section. I myself didn't know this, but LX5 helped a lot with their post:

Originally posted by LX5
You can rename the JMP's labels and their code will be run regardless of their name when Mario/Sprites touches the block. It's matter of preference and doesn't impact the insert size or speed.


All of that basically gives the block code for interaction; without all that the game would crash. Every one of these interactions is coded like labels. Since you know pretty much everything you need to know about those, you can do this pretty easily.

One thing to note is that blocks only run code when they're touched by Mario or a sprite, which means you can't make any moving blocks. Also, they run code every frame whenever their code is being run.

Let's try out coding one of the interactions.

Code
MarioAbove:
STZ $19
RTL


This will make Mario lose his power-up whenever he stands on it! Even if he gets a mushroom, cape, or fire flower while he's on it, it will just make him small again until he steps off of the block because the code's run every frame.

5. I'll add a sprite tutorial once I git gud at that.

6. End.

I really hope this helps a lot of people that are confused by wordy tutorials, or scarily long ones. I made this tutorial because I myself found this one of the hardest things about learning ASM, and I didn't want others to be discouraged like I was for quite some time. Once again, I hope this really helped, and if I messed up anywhere in this tutorial please let me know in the replies! Thanks for your time, peace out!
Quote
JMP MarioCorner : JMP MarioHead : JMP MarioBody


You got MarioHead and MarioBody mixed, it's MarioBody then MarioHead.

Quote
I've seen other people make blocks with different JMPs, if someone could tell me what's up with that I'd be glad to add that to the tutorial.


You can rename the JMP's labels and their code will be run regardless of their name when Mario/Sprites touches the block. It's matter of preference and doesn't impact the insert size or speed.

I usually follow this template for blocks because it makes reading the block's code more easy instead of having a bunch of yes/no labels and trying to figure what's up with the block.
Fixed and updated, thanks a lot!
Why not end the code with RTS?

--------------------
My Mode 0 guide.

My Discord server. It has a lot of archived ASM stuff, so check that out!
Originally posted by DaSpongeBobMan
Why not end the code with RTS?

Not easy to understand but I intepretend it as "Why does all codes here ends with a RTL and not with a RTS?" It actually depends whether you use an RTS or RTL. RTL is used for all kind of codes which are accessed with a JSL while RTS is used for subroutines accessed with an JSR (if you e.g. put a code into a block, you use a RTL while in UberASM you use a RTS). There is also a difference between them aside from their sizes (JSR takes up three, JSL four and RTS and RTL just one byte): JSL can be just everywhere while JSR only at the same bank. Because of how they work you can't use a RTL for a JSR and similar, a RTS for a JSL. The explaination is a bit complicated:
JSR and JSL pushes the next opcode's address minus 1 (i.e. if there is a JSR at $008000 then $008002 is pushed to the stack because a JSR takes up three bytes) into the stack (not explained in the tutorial) and RTS and RTL pulls it. The difference between these are is that a JSR pushes two and a JSL three bytes and as you would have thought it, a RTS pulls two and a RTL three bytes.

--------------------
Okay, my layout looks ugly.
This was a really good tutorial Pat, I've tried Schwa's, Maxx's, and imamelia's tutorials but I still couldn't fully understand.

If you have knowledge of PHA, PLA, TAX, please make a tutorial for those too.
My YouTube Channel
Best SMW Hacks Compilation
Originally posted by chineesmw
This was a really good tutorial Pat, I've tried Schwa's, Maxx's, and imamelia's tutorials but I still couldn't fully understand.

If you have knowledge of PHA, PLA, TAX, please make a tutorial for those too.

Thank you! I have NO idea how the stack really works, but TAX is just storing A into X. Nesquik Bunny has pretty good explanations of the opcodes in their user bio actually.
This was great.

I am wanting more details regarding the blocks though.
Great tutorial! This also seems very easy for beginners to get into!

One thing to point out: You should mention that STZ opcode does not work with long addresses (3 bytes or $xxxxxx) because snes does not have that opcode for long addresses. I've seen this in other tutorials and I find it quite important to point out.
Originally posted by ThePat545
Originally posted by chineesmw
This was a really good tutorial Pat, I've tried Schwa's, Maxx's, and imamelia's tutorials but I still couldn't fully understand.

If you have knowledge of PHA, PLA, TAX, please make a tutorial for those too.

Thank you! I have NO idea how the stack really works, but TAX is just storing A into X. Nesquik Bunny has pretty good explanations of the opcodes in their user bio actually.

I have no idea how and where to use the stack too!

--------------------
My Mode 0 guide.

My Discord server. It has a lot of archived ASM stuff, so check that out!
How to replace The layer of Message Box / Level Names with a custom one?
Originally posted by Wario W. 97
How to replace The layer of Message Box / Level Names with a custom one?

You go into the overworld editor and edit the layer 3 submap under "File."
Originally posted by Wario W. 97
How to replace The layer of Message Box / Level Names with a custom one?


And this not related with your tutorial, ha,ha.
Anyway,can't wait for sprite part of this titorial ThePat95!

--------------------


Don't ask why I felt like reading this now. Anyway:
All in all it's a good tutorial for beginners there are a few things though:

Originally posted by ThePat545
hex 1F is 32, and hex FF is 256

Actually 1F is 31 and FF is 255.

Originally posted by ThePat545
This code adds #$05 to the $0DBE, so if the player has #$A8 lives, this code will make the player have #$AD lives.

While the code does add #$05 to $0DBE just doing this only keeps it in A and doesn't store it to $0DBE therefore not technically making the player have #$AD lives.

Originally posted by ThePat545
This means if the value $19 is being compared to matches the value #$03, the system will know that Mario's current power-up is the cape.

#$03 isn't a cape it's a flower in normal ROMs

Originally posted by ThePat545
BCS is a branching code that branches to the specified label if the loaded value is greater than the value it's compared to.

Actually BCS branches if the loaded value is greater than or equal to the compared value

Originally posted by ThePat545
Code
LDA $19
BEQ Message1
LDA #$03
STA $1426
BRA Message2

Message1:
LDA #$01
STA $1426
BRA End

Message2:
LDA #$02
STA $1426
BRA End

End:
LDA #$03
STA $19
RTL

That doesn't make much sense. If the player is not small it'll store #$03 to the messagebox trigger then branch to Message2 and overwrite the messagebox trigger with #$02... So much for saving space #tb{:p}

Other than that it's a good tutorial for beginners
Oh crap, that really went over my head. Thanks, I'll fix it sometime later
Pages: « 1 »
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Pat's Simple Basic ASM Tutorial!

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2020 - SMW Central
Legal Information - Privacy Policy - Link To Us


Menu

Follow Us On

  • YouTube
  • Twitch
  • Twitter

Affiliates

  • Super Mario Bros. X Community
  • ROMhacking.net
  • Mario Fan Games Galaxy