Banner
Views: 793,651,517
Time:
13 users online: 7 up, Adriel_Isaque, Dan2point5,  FPzero, Fullcannon, GamerMario101, KingHD,  Lazy,  Ninja Boy, Nowieso, Ralshi02, RollingRigatonis, Rykon-V73 - Guests: 38 - Bots: 178 Users: 41,425 (1,480 active)
Latest: Dildon
Tip: Verify your ROM is unedited by using ROMclean.Not logged in.
Schwa's ASM tutorial
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Schwa's ASM tutorial
Pages: « 1 2 3 411 12 »
(I request a sticky for this thread.)

This is a tutorial I've been working on a bit at a time, to explain ASM in a hopefully easy-to-understand way. I admit, Ersanio's tutorial is good, but when I was first learning ASM it was EXTREMELY hard for me to understand... Other ASM tutorials I found were scattered around the Internet, and most of them were even worse.

So, here's this. If you want to understand ASM better, read through this. Meanwhile I'll be here to answer any questions you have about it. Be warned, though, that people like smkdan and smwedit are about 20 times better at ASM than I am, so by their standards this tutorial might not be perfect. It's the best I got though. If anyone here has a suggestion as to how to improve the tutorial, let me know in this thread. I'm trying to help people here, not show off. :)

Here goes. :)


LESSON 1: The Core Commands

The first thing you should know are the two, what I call, Core Commands. These are LDA and STA. The way ASM works is that you get three variables to use-- the Accumalator (I like to call it "A"), the X Register (I call it "X") and the Y Register (I call it "Y"). I'll explain X and Y later on, but "A" is very very important. It's what you use to transfer data into the game.

The command LDA (which means "Load Data to Accumalator") loads a hex value into "A". The command STA (which means "Store Data from Accumalator") takes whatever's in "A" and transfers it to a value on the Ram Map. So suppose we want a custom block that immediately makes you Big Mario when you pass over it.

Well, let's look at the Ram Map. It says the address $19 is Mario's Powerup status. So how would we set this block up?

LDA #$01 (Load the value 01 into "A". The # sign before the $ sign means we're loading a specific number, NOT a Ram Address. If we didn't have the # sign, it would load whatever's in $01 on the Ram, which is apparently the Y position of a sprite... We don't want that.)
STA $19 (Take whatever's in "A", in this case the value 01, and change Ram Address $19 to that. Since $19 is Mario's Powerup status, setting it to 01 will change him to Big Mario.)
RTS (This is a biggie. The RTS command stands for Return From Subroutine, and it makes the code stop executing and get back to the game. If you don't have RTS at the end of the code, the game will freeze.)

Get it so far? LDA loads a value into "A", STA takes "A" and puts it in the game, and RTS finishes the code.

Here's another nice command. STZ. It takes a Ram Address, and makes it 00 no matter what. You don't even have to have anything in "A" first. So if we want to make a custom block that always makes Mario small, we only need two lines:

STZ $19 (Set the Powerup status to 00, meaning Small Mario)
RTS (End the code)

STZ is cool mainly 'cause you don't need to change "A" to get it to work. But be warned: you can't STZ a "long address" (an address that's 6 hex digits long instead of 2 or 4) or the game will crash.


LESSON 2: Branching and Conditions

Next up: Branching. What if you want your code to do certain things depending on if certain conditions are met? You need some new commands for this.

First is CMP. It takes whatever's in "A", and compares it to a value. Then you use other codes that do stuff depending on if the compared values match or are different. The BEQ command needs to be used RIGHT after CMP. If the compared values are EQUAL, the code jumps to somewhere else in the file that you specify. But how do we specify? We use something called Symbols.

Suppose we want the custom block to only make Mario big if he's small, kinda like how the Midway Point does. Well...

LDA $19 (We're loading whatever's in the Powerup status to "A". So if he's small, we're loading 00, if he's big we're loading 01, etcetera.)
CMP #$00 (We take what's in "A", and compare it to the number 00, which is Small Mario.)
BEQ MakeBig (Okay, check this out. After BEQ I didn't put in a value, I put in a word. BEQ works like this. But you HAVE to have that word as a Symbol somewhere else in your code or the game will crash.)
RTS (If $19 is NOT equal to the compared value 00, the game will not branch to "MakeBig" and instead call this code, ending the code and doing nothing.)
MakeBig: (Otherwise it'll jump to "MakeBig" and start calling the code below. See how I set this up? This is how you should set up Symbols.)
LDA #$01 (Load 01 into "A"...)
STA $19 (...then load "A", which is 01, into the Powerup Status, making Mario into Big Mario.)
RTS (End the code.)

See how this works? First the game checks to see if the Powerup Status is 00. If it is, it skips ahead to the code that makes you Big Mario, then finishes. If it's not, it doesn't skip ahead, and instead finishes right away.

There are MANY other branching codes. BNE is the opposite of BEQ. The BNE command branches if the compared value is NOT equal. BCC branches if "A" is LESS THAN the compared value. BCS branches if "A" is GREATER THAN the compared value. Finally, BRA always branches, and you don't even need a CMP command in front of it. There are other branching codes, but these are just about the only ones you need.

Here's another technique to keep in mind. If you use a Branch command without using CMP first, it counts as using CMP #$00. This is true with any Branch command. The above example would've worked just as well without the CMP #$00 in there.


LESSON 3: Math commands

The INC command increases a value by 1, and DEC decreases a value by 1. So if we want a block that acts as a conveyor belt and moves Mario to the right one pixel every frame, we should use this code:

INC $7E (Increase Mario's X Position on the screen by 1. The screen will scroll with him, making it act as a conveyor belt.)
RTS (Finish the code.)

Or if we move to the left instead of the right? Simple, just change that INC to DEC.

This is important: If you use INC when the value is FF, it becomes 00, and if you use DEC when it's 00 it becomes FF. Don't forget this.

But more often than not, we don't want to count by just ones. Let's make a block that moves Mario 64 pixels to the right when he touches it (that's 40 in hex). For this, we need some new commands: CLC and ADC.

LDA $7E (First we load Mario's screen x position into "A").
CLC (This goes by itself, and ADC always comes right after.)
ADC #$40 (What this command does is add a value to "A". So if the value (in this case Mario's screen x-position) is, say, 24, now it's 64.)
STA $7E (Now that we've taken the X position and added 40 to it, let's store the new value back into the Ram, essentially moving Mario to the right 40 pixels.)
RTS (Finish the code.)

For subtraction, instead of CLC and ADC, you need to use SEC and SBC respectively.

For multiplication, use ASL. It should be set up like this:

ASL A

All this does is multiply "A" by 2. For division, use LSR instead, but set it up the same way. You can also multiply what's in Ram Addresses by putting the Address instead of A next to ASL. Be careful when doing this though.


LESSON 4: Tables and Indexing

Remember how I said there were three variables you can use? "A" for Accumalator, the X register and the Y register. Yes. Well, it's time to learn about X and Y.

X and Y pretty much work the same way as "A", but with two differences. One, they have more uses than "A". Two, the game has more specific uses for them in many cases. You can load values to X and Y almost the same way as you can with "A". While the LDA command loads a value into "A", to load to X and Y you use LDX and LDY respectively. To take X or Y and store it to a Ram Address, instead of STA you use STX and STY respectively.

It's very, very useful to have these two extra variables at your disposal, as it helps to have more control over various elements of your code without having to do any serious data rearranging. But X and Y's main use is for Tables.

What is a Table? It's basically a variable with more than one possible value. Tables are set up like this (below), and they need to be set up in parts of the code SEPERATE from the executing part. So the best place to set these up are in between Symbols and RTS commands, where the code will never actually execute (but the game will still read these lines).

TABLE:
dcb $7F,$3F,$00,$98

Note that the hex values on this Table were just values I pulled off the top of my head... The values in the Table can be anything you want, not just what I have written up there. But they're always set up just like that; Symbol name in front of the Table, dollar sign in front of each number (no # sign or spaces, ever), comma seperating each number and no comma at the end.

Making the Table is only the first step... Now we want to USE the table. Suppose we want a custom block that activates the Blue P-switch for a longer period of time depending on whether you're Small, Big, or Fire/Cape Mario. This is how we'd do it.

LDY $19 (Load the power-up status into the Y Register. If you're Small, 00 is loaded, if you're Big we load 01, Cape is 02 and Fire is 03.)
LDA TIMER_TYPE,y (See how I set this up? At the end of the code is the Table with this Symbol name attached. What we're doing is taking Y, which is the Powerup status of Mario, and choosing the value at that position of the Table and setting it to "A". So if it's 00, we take the first value, if it's 01 we take the second value, 02 we take the third, and 03 we take the fourth. Make sure you set it up JUST like this; no space after the Symbol name, a comma, and either the x or y in lower-case RIGHT after the comma.)
STA $14AD (Now we take "A", which has a value based on your Powerup status thanks to the Table below, and set it to the remaining Blue POW timer. Note that this does NOT change the music-- if we want to do that, we need to add some more code.)
RTS (Finish the code.)
TIMER_TYPE: (Now we're declaring the Table, and we put it after the RTS so it won't be treated like actual code.)
dcb $3F, $7F, $FF, $FF (Here's the values on the Table. Remember how I said 00 was small, 01 was Big, 02 and 03 were Fire and Cape Mario? Well, the first value on the Table, which loads if the Powerup Status is 00 (meaning Small), is 3F. So if Mario's Small, the Blue Pow Timer will be set to have 3F time left on it (which is 25% of the time a normal P-switch gives you; normal switches give you FF time). If the Powerup status is 01, it loads the second value, which is 7F, so the Blue Pow Timer gets 7F time on it if Mario is Big (which is 50% the normal value). Finally, if it's 02, it loads the third value, and if it's 03 it loads the fourth value. Both of these are FF, so this means if Mario is Fire OR Cape Mario, the Blue Pow Timer will have 100% it's max value when hit.)

We don't put another RTS at the end of the Table, since it's not actually executable code, so it's not needed.

So, what this block should do is set the Blue Pow Timer to 25% the normal time if you're Small, 50% time if you're Big, and 100% time if you're Fire or Cape Mario. And of course, you can change these table values around to change the times. If you want it to last longer if you're Small and shorter if you're Big or Fire or Cape, simply put bigger values in front and smaller values in back. The best way to decide what you like best is to experiment a bit until you find your favorite settings.

If we want to change the music when we hit the block, add this code right after the LDA $14AD and right before the RTS.

LDA #$-- (Replace the dashes with the value that matches the music number you want to play. You may have to look in Lunar Magic to see.)
STA $1DFB (Remember this address. $1DFB controls the music that's playing. Any time you write a value to this address, you can change the music.)

To make sound effects play along with or instead of music, use $1DF9, $1DFA and $1DFC. Each of these addresses control a different selection of sound effects, called "banks". There's probably a list somewhere of which sound numbers are what, but unless you have that you'll need to experiment, unless you have the SMAS SFX patch, which has a list, but with that patch you can't use non-SMAS custom music. (However you do get more sound effects to choose from.)

So, recap. LDX and LDY load values into the X and Y Registers. STX and STY take X and Y, and load them into a Ram Address (but you actually won't use these very often). To load a value from a table, use LDA [table name],x or LDA [table name],y but make SURE you actually have a value stored in X or in Y in the first place.

Here's some more sweet commands you can do with X and Y.

TAX and TAY take "A" and copy it into X or Y. These are very useful.
TXA and TYA do the opposite; they take X or Y and copy it to "A".
TXY takes X and copies it to Y.
TYX takes Y and, you guessed it, copies it to X.


LESSON 5: Using the Stack

Alrighty, time to learn about the Stack.

The Stack is awesome. It's like a really huge bookshelf you can put all your "books" in and take them out later. The problem is, you can only take out the last book you put in. If this doesn't make any sense, hopefully it will later. It's not really a bookshelf... it's just a massive database in the Ram for your benefit. Watch...

PHA means "Push Accumalator". It takes "A" and stores it to the Stack as the next "book". Now this value is preserved, and you can restore it to "A" any time you like with PLA "Pull Accumalator".

It works like this. Suppose you load "A" with the value in some Table. Now, the value in the Table isn't always the same, obviously. And you need to use this value again in some later code, but you can't use LDA #$-- because the value isn't always the same. You use the stack! Use PHA (with nothing after it), and the value is stored in that virtual bookshelf, no matter what it is. Then when you write PLA (again, with nothing after it), it takes that last stored value, whatever it was, and loads it into "A" once again. Be careful; when Pulling from the Stack, whatever was "pulled" no longer exists in the Stack. Never try pulling something from the Stack that doesn't exist.

Furthermore, you can push multiple values to the Stack. If you have PHA in your code three seperate times, the Stack will have three values. You could say the "bookshelf" has three "books". But when you Pull, the code pulls only the number on TOP of the Stack. So if you have three PHA commands, then you have a PLA, it'll pull the value stored with PHA Number Three. Then if you PLA again, it'll pull the value from PHA Number Two. Again, don't try and pull from the Stack when the Stack is empty, or your emulator will fall through a woodchipper.

So, PHA and PLA deal with "A". To push X or Y, you should use PHX and PHY. And to pull from the Stack and load it to X or Y, you should use PLX and PLY.

There are not three seperate stacks for "A", X and Y. They all share the same Stack. Keep that in mind.

The Stack is extremely useful when coding custom sprites, as X and Y have to be certain values at certain points of the code (not so much in custom blocks). But I'll get to that in a future lesson.

Oh yes, one thing smkdan reminded me about... There are some commands known as JSR and JSL. Both of these work like the BRA command, except when the code comes to an RTS (or RTL, in the case of a JSL), it jumps back to the point right after the JSR/JSL. The catch: These commands use the Stack to store what part of the code to jump back to. So, if you Push to the Stack, then JSR, then Pull again before the JSR code is finished, well, your code will make itself into some delicious scrambled eggs. NOT something you want to do. Keep this in mind when using JSR/JSL and the Stack together. ;)


LESSON 6: Binary commands

This one's a little tricky. Basically it's possible to get multiples of a value by using Binary. To do that, you use the AND command.

What AND does is take the hex value in "A", and another hex value, then converts them both to an 8-digit binary number (binary is only 0s and 1s). Then it compares the two binary values, and makes a third value (also 8 digits) depending on what the other two values are. The rule: If the same digit of either value is a 0, the digit in the 3rd value is a 0. If both digits in either value are a 1, that digit in the 3rd value is a 1. Once the 3rd value is generated based on this rule, the value is converted back into X and stored to "A".

Complicated? Here's an example. By the way you should really use Windows Calculator to help you when transferring hex to binary and back.

LDA #$88 (The first value is 88. In binary, this translates into 10001000.)
AND #$C6 (The second value is C6. In binary, this becomes 11000100.)

Okay, now we have our two values. AND will do this to it:

10001000 (first)
11000110 (second)
10000000 (result)

The first digit had a 1 in both values, so it stayed a 1. All the other digits had at least one 0 between the two values, so that digit in the 3rd value became 0. Then the result, 10000000, is converted back into hex, which is 80. This means that "A" now has the value 80.

Here's another example. Let's change that LDA #$88 to an LDA #$7C. This translates into 01111100.

01111100 (first)
11000110 (second... it's the same as in last example)
01000100 (result)

The first digit had one 0, so the result had a 0. The second had two 1s, so it resulted in a 1. Digits 3 through 5 had one 0, so they all resulted in 0s. The 6th digit had two 1s, so the result was a 1. The 7th digit had a 0 so it results in a 0, and the last digit had two 0s so it also results in a 0. The result, 01000100, translates into hex as 44, so the value 44 is what's now stored in "A".

So how is AND useful? Suppose we want a custom block that randomly makes you Small, Big, Fire or Cape Mario. SMW does have a Random Number Generator, but it's difficult to use, so we can just get it based on the animation frame. And to make THAT work, we can use AND to make the animation frame a multiple of 4, and transfer it to the Powerup status! Watch.

LDA $13 (Load "A" with the Animation Frame number. Note: In Lunar Magic it says there are 16 animation frames. Well, one of THOSE animation frames is 0F of this.)
AND #$03 (Compare "A" with the Binary value 00000011. This makes "A" into a multiple of 4. It sounds crazy, but test it and it works every time. The first six digits are always 0, the last digit is 1 only if "A" is an Odd number, and the second-to-last digit is 1 if the ones digit has been Odd and then Even again an Even number of times. It sounds seriously crazy, but you'll amazingly get a number from 00 to 03 EVERY time with this. It's an incredible technique.)
STA $19 (Store this multiple of 4 to the Powerup status. Now Mario will be Big, Small, Fire or Cape depending on the animation frame, which is moving so fast it's at a seemingly random time.)
RTS (Finish the code.)

Remember, if you want to play a sound effect, you need to write in the extra code before the RTS.

Here are some other binary-effecting commands. ORA is like AND, only it works opposite. If either of the two values have a 1, the third will have a 1. The third value will only be a 0 if both values have a 0 in that digit. ORA is good when you are dealing with sprite properties, which are stored in binary format, and need to combine two values together.

Then there's EOR. This one's a bit tricky. If the first and second values both have 0, the third will have 0. If they both have 1, it'll also be 0. If one has a 1 and one has a 0, the third will be a 1. EOR is useful when you want a value to go back and forth between two possibilities based on some conditions, though it's not easy to set up sometimes.

There are other binary-effecting commands out there, but they're too obscure and/or complicated for me to have to explain.



ADVANCED FURTHER READING

The Data Bank (DB) register

When accessing memory (ROM or RAM), you pick an appropriate addressing mode to use in your instruction. The '816 has many of these, but here's a few common ones:

Code
LDA $78       ;direct (1byte address)
LDA $0078     ;absolute (2byte address)
LDA $7E0078   ;long (3byte address) 


Normally all of these would access the same RAM (7E:0078) but when using absolute addressing (and ONLY absolute addressing), the DB register is used. The '816 has 24bit addressing, but since absolute only provides a 16bit address, it needs the remaining 8bits to come form somewhere. This is what the DB register is used for; it specifies the bank / upper 8 bits of the address.

The DB register is modified with the PLB instruction. It pulls 1 byte from the stack and sets that as the new DB. An example of it being used can be:

Code
LDA #$7E ;I want to change the DB to the first RAM bank
PHA       ;push A (7E)
PLB       ;pull DB (DB = 7E now)
LDA $2000 ;if you look in the RAM map, this would access the first byte of a decompressed GFX file


A common use is in custom sprites, where data is accessed using absolute addressing.

Code
PHB ;save the original DB
PHK     ;by pushing the PB register (bank of code currently running)...
PLB     ;...the DB is effectively set to the bank of the sprite's code and data


This allows absolute addressing to access data within the sprite's code bank.

When using direct addressing, the DB is always overriden temporarily to use bank 00.

When using long addressing, the DB is overridden temporarily to use the bank supplied in the instruction.

--------------------
It's me!!

High on life is the best high.
Hi. This looks familiar...
Anyway, if you keep posting detailed "How to make a Carol grade custom boss" tutorials, I think everyone will get off your back :D
Edit: I say sticky too, these tutorials are very useful.
Rather than sticky, you should make it a txt. and submit it into the Docs section.
Originally posted by B.B.Link
Rather than sticky, you should make it a txt. and submit it into the Docs section.

I thought about it, but for some reason I thought posting it here on the forums was a better option... The main reason for that is because I planned to add to it at some point, for example stuff about making custom sprites (which there's more to than there is to custom blocks), and also, if others want to add to it as well, they can do that. Plus it's in plain sight for everyone in the Advanced Forum to see. AND I can link to this thread in my sig (which I was going to do once it was stickied).

So there's a lot of good reasons for making it a thread instead of a document. At least I think so, anyway.

--------------------
It's me!!

High on life is the best high.
It's stickied (for now, anyway), because it's reasonably well written and will serve as a handy, unmissable resource for one of the most asked about topics in this forum.
I look forward to reading this, as soon as I'm done with Brawl which will be a long time. Another good reason for having a thread instead of having it the Documents section is. Sometimes beginner hackers will not think to look around the documents section and they just go right to the forums and ask an easy thing to do like inserting ExGFX, when there's already a tutorial for it in the Doc. section
This is the very time I've been able to look at an ASM tutorial and actually understand a single word beyond the introductory paragraph. This is really nice of you to make, Schwa - it was obviously very time-consuming, too, so it is much appreciated. Nice nice work!

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

[?] Miscellaneous Helpful Hints
If I moderated your hack, there was apparently a 90 percent chance it was rejected.
I admit it, you are better in explaining stuffs than me... >_<;
Well, it was amazing how you explained everything. Everything was extremely detailed.
This sticky is worth it, seriously.

--------------------
My blog. I could post stuff now and then
Ersanio, your explanation of indexing is extremely lacking, and you need to fix it. >_<

But your tutorial is nice too.

--------------------
It's not even close to Halloween, and already Christmas Sales are starting early!
Here's a sound effect chart I made up a few months ago, but never really uploaded. These values go at $1DFC. If anyone has something they want corrected/added to it, let me know.

00 = Nothing
01 = Coin
02 = Mushroom appears from ? block
03 = Mushroom appears from ? block, lower pitch
04 = Spin Jump
05 = 1-UP
06 = Shoot a fireball
07 = Break a turn block with a spin jump
08 = Spring jump
09 = Bullet Bill shoot
0A = Egg hatches
0B = Item goes in reserve
0C = Item falls from reserve
0D = Same as 0C
0E = L/R Screen Scroll
0F = Enter a door
10 = Same as 09
11 = Score counting at end of level
12 = End of score count
13 = Lose Yoshi!
14 = Er...?
15 = Er...??
16 = Castle destroyed on Overworld
17 = Fireball from Bowser Statue
18 = Valley of Bowser lightning SFX
19 = Clapin' Chuck's clap
1A = Weird low grunting noise.
1B = Fireball effect of some kind
1C = Fanfare SFX
1D = Time Running Out SFX!
1E = Whistlin' Chuck's underwater whistle
1F = Yoshi noise
20 = Koopa Kid falls into lava
21 = Yoshi's tongue
22 = Message Box
23 = Level tile Beep! on Overworld
24 = P-Switch Timer running out!
25 = Yellow Yoshi's stomp
26 = Swooper swooping sound
27 = Fireball jumping
28 = Stomp on Koopa Kid
29 = Correct! SFX
2A = Incorrect! SFX
2B = Firework shooting up SFX
2C = Firework exploding
2D - 34 = Fireball jumping
35 = Sound of Mario hitting a solid block
36 = Spin jump on spiked enemy
37 = Kick a shell
38 = Big Mario turning to small Mario
39 = Midway point SFX
3A = Yoshi swallowing something
3B = Stomp on Dry Bones
3C = Spin jump and kill enemy
3D = Accelerate with cape
3E = Get a mushroom
3F = Hit a switch
40 = ? .. sounds like a weird screen scroll
41 = Get a cape
42 = Swim in water
43 = Get hit by enemy while flying SFX
44 = Yoshi spitting something out
45 = Pause game
46 = Unpause game
47 = Consecutive jump 1
48 = Consecutive jump 2
49 = Ditto
4A = Consecutive jump 3
4B = Ditto
4C = Consecutive jump 4
4D = Consecutive jump 5
4E = Grinder or chainsaw moving
4F = Ditto, but other part of the SFX.
50 = Get a Yoshi Coin
51 = Part of Time Running Out SFX
52 = Get a P-Balloon!
53 = Koopa Kid defeated
54 = Yoshi spitting a shell
55 = Rolling thunder .. ?
56 = Nothing
57 = Lemmy/Wendy falling into lava.
Schwa, You explain this very well! I'm starting to understand some stuff that didn't quite click when I read another tutorial the other day.

[?]

--------------------
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
Hazzah! This is definitely a great thing to have in the forum. Also, if you do add in more info to it specifically geared towards custom sprites it will be the most powerful force in the universe!! ... Wait. Thats the Deathstar. It will be an even more kick-ass tut than it already is. And I agree that you've done a great job of making the concepts more understandable. I and I'm sure many others have been waiting for something like this. Hazzah!

--------------------
Krakenskin Leather Works, my Etsy store.
LordVanya, my art page.
FundamentalEssence, my game development page.
Nice work! It must have taken you forever to type all that!

I have spotted a few things you might want to add/change, though:

Originally posted by Schwa
Note that these four commands don't COPY the value... they MOVE it. So if you use TAX, X has the new value, but "A" no longer has it. At least I think this is the case...

Actually, they do copy it, so you don't have to worry about preserving "A" before you use "TAX" or whatever.

Originally posted by Schwa
By the way you should really use Windows Calculator to help you when transferring hex to binary and back.

LDA #$88 (The first value is 88. In binary, this translates into 10001000.)
AND #$C6 (The second value is C6. In binary, this becomes 11000100.)

Instead of converting binary to hex before you put it in the code, you can use LDA #%10001000 instead of LDA #$88. I don't know why so few people seem to know about this, it's really useful when you're working with bits instead of whole values, especially with AND, ORA, REP, SEP, etc.
Fixed the first suggestion. smkdan said the same thing, actually.

I heard about that second one, though, but I didn't say anything about it because I heard from some post somewhere that using #% tends to cause glitches in some ASM-converting programs. Is that untrue? If it's untrue, I'll add it.

--------------------
It's me!!

High on life is the best high.
I think every assembler I tried is fine with the binary format in instructions. Personally when I see bitwise instructions I can see #$40 as bit 6, #$08 as bit 3, #$C0 as bit 7 + 6 etc. Personal preference I guess, or if you keep having to use calculator for the conversions % is an option.
My only thing is to say what each code it stands for. It makes it easier to remember.

--------------------
<TLMB> I use YY-CHR to edit DNA
This is the best tutorial ever. Thank you schwa!

how far are you planning to have the lessons go? I am a total noob at asm, so obviously this ongoing tutorial has my full attention.


as the kind of person these noob tutorials are directed toward, my suggestion would be to not stop at the actual code instuction, but to get the reader capable of making their own basic block/sprite and getting it in-game. you know, like how to get it from just knowledge to a txt file and finally into the fully assembled file ready to be used in blocktool/spritetool. that would be alot of effort, but i am not aware of any good tutorial that really does that.

on a more personal note, i have always been clueless when it comes to having the custom whatever 'spawn' something (like a projectile or a sprite). same goes with custom sprites. sprites are evil...

--------------------
Well, I didn't include the technical stuff because it should be fairly common knowledge... For custom blocks, drag the .ASM file (you can just rename your .TXT file, it's fine) to the program that comes with SpriteTool called TRASM.EXE and it'll make it into a .BIN file. Then set up the custom block in BlockTool's data interface with that .BIN file and you're set.

For custom sprites, you need a .CFG to go with the .ASM file. Just copy an existing one, rename it, go into the CFG editor and change stuff around (don't forget the text box in the upper left). Then insert it into the List and you should be good to go.

Spawning sprites is highly complicated... For Extended Sprites, you're best off copying the ball-shooting code in mikeyk's SMB2 Snifit. For custom sprites, copy the egg code in "Birdo w/ rideable egg". For normal sprites, copy the bomb-throwing code from the Bomb Bro. I'll go into detail about it some other time, but not now. I'm exhausted.

--------------------
It's me!!

High on life is the best high.
I agree with jesus. what I is really needed is a more detailed explanation of how to set up a working sprite. The technical stuff about TRASM.EXE etc etc is very basic info that a noob ASM hackers should know before they even get to this tutorial. Definitly what the community really needs is info on proper sprite animation and maybe a lesson or 2 on some more advanced concepts that there is no info about.

--------------------
Krakenskin Leather Works, my Etsy store.
LordVanya, my art page.
FundamentalEssence, my game development page.
Originally posted by Schwa
LESSON 4: Tables and Indexing

Remember how I said there were three variables you can use? "A" for Accumalator, the X register and the Y register. Yes. Well, it's time to learn about X and Y.

X and Y pretty much work the same way as "A", but with two differences. One, they have more uses than "A". Two, the game has more specific uses for them in many cases. You can load values to X and Y almost the same way as you can with "A". While the LDA command loads a value into "A", to load to X and Y you use LDX and LDY respectively. To take X or Y and store it to a Ram Address, instead of STA you use STX and STY respectively.

It's very, very useful to have these two extra variables at your disposal, as it helps to have more control over various elements of your code without having to do any serious data rearranging. But X and Y's main use is for Tables.

What is a Table? It's basically a variable with more than one possible value. Tables are set up like this (below), and they need to be set up in parts of the code SEPERATE from the executing part. So the best place to set these up are in between Symbols and RTS commands, where the code will never actually execute (but the game will still read these lines).

TABLE:
dcb $7F,$3F,$00,$98



A question that bugs me still you helped me on Jul but never got answered: Those four values in the table... what are they supposed to do? And why THOSE numbers? I don't think that you can write any number you want or it wouldn't be important, not? Can you explain me what they do and why those numbers?
Pages: « 1 2 3 411 12 »
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Schwa's ASM tutorial

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

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


Total queries: 7

Menu

Follow Us On

  • YouTube
  • Twitch
  • Twitter

Affiliates

  • SMBX Community
  • ROMhacking.net
  • MFGG