Language…
5 users online: Alex No, CONLUSH666, Rykon-V73, synthie_cat,  Tahixham - Guests: 253 - Bots: 401
Users: 64,795 (2,377 active)
Latest user: mathew

Schwa's ASM tutorial

Thanks Joe13, but I got it working- In the blocktool interface, I put in
nameofmypracitceblock.asm</b></i> instead of nameofmypracitceblock.bin</b></i>

And it worked! It actually worked! I MADE a block! Yay! Yay! Yay! :)


Unexpected end tag (</b>) at 113, expected </u>
Unexpected end tag (</i>) at 117, expected </u>
Unexpected end tag (</b>) at 171, expected </u>
Unexpected end tag (</i>) at 175, expected </u>
Tag (s) was not closed.
Tag (u) was not closed.
Tag (i) was not closed.
Tag (b) was not closed.
Tag (i) was not closed.
Tag (b) was not closed.
Really?

Well then, maybe I should also try it that way...

--------> Don't follow "Find Roy's Dignity", my hack. Because it's pretty outdated. <--------
Great Guide, Schwa! I've made my first sprite using your guide. But, I'm needing of help. My 2nd sprite is a custom Layer 2 Scroller. How I do to make it to move using the RAM data? The command INC just increases 1 value, but it doesn't repeats to make the movement. What is wrong?
Now I leave my IPS patches of my hacks for everyone play and edit as you want to.

Bramble Invasion & Surreliatus


Oh my goodness... To be honest I've never monkeyed around with Layer 2 scrolling before, and am not sure how to help you. There's not even an X or Y Layer 2 speed variable in the Ram Map...

I feel bad. I wish I could help you get it to work. If you figure it out before I do, I might do something special for you. ^_^

Incidentally, what is the first sprite you made? I'm curious. ;)
It's me!!

High on life is the best high.
Originally posted by Schwa
Oh my goodness... To be honest I've never monkeyed around with Layer 2 scrolling before, and am not sure how to help you. There's not even an X or Y Layer 2 speed variable in the Ram Map...

It's easy enough to modify Layer 2 with these addresses:

$7E:001E | 2 bytes | Misc. | Layer 2 X position
$7E:0020 | 2 bytes | Misc. | Layer 2 Y position
I've tryied just those adresses. I've used this:

INC #01
STA $001E
INC #01
STA $001F
BEQ RETURN
RETURN RTL

But, they makes a huge movement, so big that I can see scrambled graphics as the Layer 2. I want something more slower, just like the original scrollers, I just want to know how to change the speed and the time to change of direction.
Now I leave my IPS patches of my hacks for everyone play and edit as you want to.

Bramble Invasion & Surreliatus


Oh, I see what the problem is...

Use the AND command to INC or DEC the Layer 2 position only once every so-and-so frames, but keep that value a power of 2. (So, every 2 frames, 4 frames, 8 frames, etc.)

To get it to go back and forth, my guess would be to have the game check either the X or Y position of Layer 2 (whichever you prefer) at the beginning of the code, and if it equals a certain value, set a specific variable in the Ram (you choose) to 00, and if it equals another value, set it to 01, then check that variable and check if it's 00... If it is, INC the Layer 2 position, otherwise DEC it instead.

Does that make sense?

Something to keep in mind though: Generator-class sprites don't have an INIT Routine, and thus I don't think they use the X register as their own sprite index (since they don't count as a sprite), but if I'm wrong, someone please let me know...
It's me!!

High on life is the best high.
Okay, I've just finished reading through lesson 4 of the tutorial, and I don't get something...

Why are tables so important. What you did in the tutorial could have been done just as easily using the CMP, right? And the CMP command seems an awful lot simpler than tables...

So, I guess my question is, am I missing something? Do tables have another use?
Ok. So if I want to write a code that would make mario lose one coin every time he shoots a fireball, I would do something like...

LDA $(I need the RAM address for shooting a fireball)
SEC (This goes by itself, and ADC always comes right after.)
SBC #$01 (or is it #$8D01??) (Take one coin away from...)
STA $0DB6 (Mario's Coins)
RTS (Finish the code.)

Or do I need to replace LDA with JSL? I'm sure this is all wrong!

[?]
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
...


it would go more something like this:

Code

; (assuming you were using xkas as an assembler)

!playerCoins = $7E0DBF

SEP #$20 ; ensures that the accumulator is 8-bits
; otherwise you'd have to use an AND #$00FF to zero out the high byte
; that would get read out in the LDA below

LDA !playerCoins ; A = the number of coins the player has

BEQ dontShootFireball ; branches to a label below b/c if we don't have coins

SEC
SBC #$01
STA !playerCoins

JSL shootFireBall

dontShootFireball:

RTL

; end of routine



Ok. So in order to set what RAM I am working with, I just use

!SomethingHere = RAM address.

And then it will use that any time I have it in the code after that? That makes sense. I was wondering how that worked.

Do I have to do the same thing for the BEQ? I see that you just put 'DontShootFireball', but would I also have to have !DontShootFireball = 'whatever RAM address fireballs is' for it to know what to stop doing if it runs out of coins, and the same to let the JSL know what 'ShootFireball' means?

In other words...

Code

; (Do I need that ; thing here?) 

!playerCoins = $7E0DBF 
!ShootFireball - $7E(Fireball RAM address)
!DontShootFireball

...etc.

Tag (pre) was not closed.
Tag (div) was not closed.
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
I think you're a little unclear on how this all works.

the semicolon is a comment marker:

Code

; this whole line is a comment
this line is not an will be treated as code! and it will not compile b/c it isn't valid assembly language.

; both of these lines are commented out
; LDA $7E0000 this will do absolutely nothing b/c of the semicolon!

!x = $7E3000 ; this does something b/c the comment market comes after I've actually done something on this line.



Also, you need to realize that most of the time code on the SNES is not running in RAM. In fact, very few games seem to do that at all (FFVI does).

This means that generally speaking you "jump" or "branch" to ROM locations and you "access" RAM locations. One means to "go somewhere else" and the other means to "obtain information".

The point of the ! symbol is to label an address, such as $7E1234. But the addresses you jump to, rather than "access" are automatically calculated for you by the assembler (xkas). So doing something like:

!dontShootFireball = dontShootFireball

is redundant. You already have a label for that address, why make another?
Yeah. Unclear. You could say that. :-) But I'm hear to learn, so I appreciate you taking the time to help make it more clear.

So when I do a BEQ to DontShootFireball, this xKas program already knows what this means? So the code you provided is complete, But in order to make the patch work, I would have to point to the original fireball command like this?

Code
header
lorom

org $fireball ;(I think it may be $00D062, which is fireball and
;capeswing routine, so I may try to find the Mario pose for shooting 
;a fireball instead so cape swings don't take coins away, 
;if that will work)

:fireball

!playerCoins = $7E0DBF 

SEP #$20 

LDA !playerCoins 

BEQ dontShootFireball 

SEC 
SBC #$01 
STA !playerCoins 

JSL shootFireBall 

dontShootFireball: 

RTL 


Or is all that other stuff at the beginning unnecessary?

[?]
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
You should keep the header and lorom part in. Xkas will try to find the location with the label to not shoot the fireball. It's fine.

Putting you code right in the routine will overwite essential code in it.
I found a good spot a bit into the routine to install the hack and where the fireball actually gets created...
Try patching the following code (which should work):
Code
lorom
header

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!playerCoins = $0DBF ; Unnecessary 7E
!shootFireBall = $00D0AA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

org $D0A0
JML main ; jump to main


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "STAR" ; RATS tag used to protect data from other programs
dw Endcode-Startcode
dw Endcode-Startcode^#$FFFF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Startcode:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org $freespace ; Point to freespace in ROM (SNES format of course)

JUMP_00D0A8:
JMP $00D0A8

main:

LDA $13E2               
AND #$10                
BEQ store           
INY                       
store:
STY $76; your code

LDA !playerCoins

BEQ dontShootFireball 

SEC 
SBC #$01 
STA !playerCoins

JML !shootFireBall ; changed to jump

dontShootFireball: 

JML $00D0AD ; jump back instad of return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Endcode:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

When you use RAM addresses you can shorten them up as follows:
For $7E0000-$7E00FF use $00-$FF
For $7E0100-$7E1FFF use $0100-$1FFF
All other values use need full addresses

If you didn't know:
JML is like JSL except don't RTL back but you can JSL again back to the rountine you came from. (It doesn't store the location you came from to go back.)

You would want to use JML if there is a routine that needs to be accessed with JSR and you out of that bank and need to go back under a certain condition.
Ok. I got it to patch (I changed the address for my empty space. first one I tried gave me a black screen). Only problem is is that it won't shoot fireballs at all now (Even with coins). Going to mess around with it a little.

(Edit)
Ok! Interesting things are happening here! I don't think $D0A0 is where the fireball is created normally. That's actually Mario's spin jump while he has the flower, which SHOULD shoot two fireballs! It takes away coins when I spin jump, but only if I have the flower, and I still can't shoot fireballs.

[?]
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
"!playerCoins = $0DBF ; Unnecessary 7E"

In many situations, you would be right. However, once you start doing a bit more advanced ASM work you might want to change the data bank register. (for example, to set $7F as the data bank and read memory locally from it)

Code
PHB

LDA #$7F
PHA
PLB ; sets the data bank to $7F

LDA $0DBF ; this reads from $7F0DBF, not $7E0DBF!


luckily, SMW is a LoROM game and almost any access from $0 to $1FFF in any bank you're likely to be working in will resolve to $7E, but only for that range. $2000-$FFFF in banks like $00-$3F will resolve to either hardware registers or an open bus effect (meaning it's just stale data sitting on the system.) This means that $7E:2000-$7E:FFFF are NOT the same as $00:2000-$00:FFFF!
I looked into this a bit more. It turns out I messed with the code before the fireball if spin jumping. I installed this were the firball is created.
You can enable some of the optional code if you want...
Try it:
Code
lorom
header 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
!playerCoins = $0DBF ; Unnecessary 7E
!shootFireBall = $00FEB5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
org $FEA8
JML main ; jump to main 

;org $D064 ; remove semicolons to shoot fireballs with any powerup
;NOP
;NOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
db "STAR" ; RATS tag used to protect data from other programs 
dw Endcode-Startcode 
dw Endcode-Startcode^#$FFFF 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
Startcode: 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
org $freespace ; Point to freespace in ROM (SNES format of course) 
LDA
 
; your code 
LDA !playerCoins 
BEQ dontShootFireball 
;LDA $140D             ; \remove semicolons to disable spinjump fireball
;BNE end ; /

LDX.B #$09                ; Find a free fireball slot (Ext spr slot 08-09) 
check:
LDA.W RAM_ExSpriteNum,X   ; this is restoring damaged code
BEQ shoot         
DEX                       
CPX.B #$07                
BNE check           
BRA end                 ; Return if none 

shoot:

;LDA $140D             ; \ remove semicolons to stop removing coins when spin jumping
;BNE dontremovecoin    ; /

SEC 
SBC #$01 
STA !playerCoins 
dontremovecoin:
JML !shootFireBall ; changed to jump 

dontShootFireball: 
; LDA #$??        ;\remove semicolon to store a you can't shoot any fireballs SFX
; STA $1DFC      ;/ you must change ?? to SFX value
end:
JML $00FEB4 ; jump back instad of return 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
Endcode: 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 


Edit: Wait, why should all these questions go in here and not the ASM help thread? If this place is supposed to be for Schwa's answers only then I don't see too much of a point to post when it's faster when anyone has a chance answer in the help thread...

Edit2: forgot pound sign for the sfx thing.
You're right. Didn't even cross my mind. I guess my initial question about the DEC oppcode spawned this discussion and it just went on and on. I'll try this code, and if I have any further questions, I'll post them in the help thread. (Sorry Schwa!)

[?]
I've removed my NoFades patch until I can find the brightness code for Star Road warps.
I know that the act of re-posting a question, usually because the asker feels that his or her question has been overlooked, is generally frowned upon, but understand that often questions ARE overlooked, for various reasons, making it necessary to re-post. Due to the discussion following InvisibleCoinBlock's question, this is one of those times.

Originally posted by wowfunhappy
Okay, I've just finished reading through lesson 4 of the tutorial, and I don't get something...

Why are tables so important. What you did in the tutorial could have been done just as easily using the CMP, right? And the CMP command seems an awful lot simpler than tables...

So, I guess my question is, am I missing something? Do tables have another use?


Thanks.