asm cheat sheet ?

digit2600

Member
can someone break down simply for me how to go about basic conditionals and instructions?

I'm so used to writing in high level instructions, all this lda, sta, jsr, Bne stuff is melting my mind. ..

i know what they stand for but dammit, I'm missing something. ..

for example, how would I write something like-
if (condition 1){player_y--}else {do this instead }
this of course is just simple movement logic, but i figure its as good a starting point to try to understand how to translate this down to asm..

or even to change states- if (key is down (key.a) && !jumping ){jumping=true;play jump animation }

how would simple things like this break down into asm?
 

Kasumi

New member
How to write "if (condition1) depends on what (condition1) is. It sounds like a non-answer, but it's actually true.
player_y-- would be dec player_y.
This post might be of interest to you: http://nesmakers.com/viewtopic.php?f=20&t=284#p1776

I also recommend reading this guide: https://skilldrick.github.io/easy6502/

Feel free to ask questions about that guide.
 

Kasumi

New member
Rather than edit that post, I'll just make a new post to get to the last bit. The thing to realize is that other than what the hardware expects, everything is defined by the programmer. There is no "play jump animation" function unless you write it. What "true" means is also defined by you. It's usually non zero, but you can do whatever.

It's the same for the buttons. NES Maker actually stores them "backwards" to how my game Indivisible does. In NES maker to do something if the A button is held:
Code:
lda gamepad;the gamepad variable is now in the accumulator
and #%00000001;A button is the rightmost bit in the byte in NES Maker.
;Imagine the 8 bit number in the accumulator and the number next to the and being placed
;on top of each other
;If the top AND the bottom bit are both 1, a 1 will be placed in the accumulator in that 
;bit's place in the accumulator after.
;Otherwise, a 0 will be placed in that bit's place in the accumulator.
;after.

;Because the first 7 bits are clear in the number provided to the AND
;The final result in A will be one (non zero) if the button was pressed 
;(since that bit is 1 in the number next to AND, all it takes to get
;a 1 result is for the bit for the A button to also be 1 in the gamepad byte.
;Otherwise it's 0.
beq nojump;branch if equal to zero. In other words, if the result of that
;and was zero, go to the label provided
;If the branch didn't happen, that means A is being held
lda jumping;Assuming non zero means we are jumping.
;But again, this depends on what you decided, the CPU doesn't care
bne nojump;If we ARE jumping that means we shouldn't continue
;since you only want to continue when we're not jumping
;If here, we weren't jumping.
lda #$01;A non zero value which means "true" for the jump variable is now in the accumulator
sta jumping;Now jumping is "true". We have just stored 1 there,
;which would make the above condition branch next time.
jsr playjumpanimaton;Assuming... you wrote this function this would work
nojump:;The label to skip to if the condition wasn't true.
For multiple conditions, like you saw above, you have to check each one separately. It's hard to make a cheat sheet. You have to understand AND to use AND effectively and you have to understand the processor status flags to create conditionals properly.
 

FrankenGraphics

New member
The one thing that will confuse most people coming from a high level language is that in those, if/else/case clauses will execute exceptions within brackets. branch instructions, the decision making counterpart in assemply, SKIPS exceptions. It's really the same thing, but the human side of the semantics are reversed.

so in a high level language you might have something like this.
Code:
If something we test is true, then do the following: (the following goes here).
in assembly, it's rather like this
Code:
If something we test is true, then skip around the following: (the following goes here).
basically, whenever you test something with the "branch" set of instructions, you're testing whether to make a GOTO or not. The caveat with 8-bit assembly languages is that the jump cannot be more than a signed bytes' worth away in relative PC addressing. If you want to go longer, you need to wrap a JMP or JSR inside an inverted branch clause:

Code:
If the opposite of what we really want to test is true, skip the following: (jump to the thing we want to do if true here).

Hypothetically, an assembler can automate this so that the programmers' interface is more high-level-like without loosing efficiency. The commercial 6502 cross-assembler cross-32 has an assembly methodology which lets you construct macros to fully emulate both "long branches" and if/else/case clauses like in a high level language. This is something you mostly cannot do in asm6 or ca65. ca65 (maybe asm6 too, haven't tested) can do automated long branches, but this is not optimized, so i think it is better to just do it by hand.

note that branches can also go backwards, not just forwards. so branch instructions are, from the perspective of a high level language, both decision makers and loops, depending on how you use them.
 

digit2600

Member
I've been messing around with the movement code today, and I think I'm getting sonewhere. im still lost on multiple conditions, so I'm going to read up more...

but right now, I'm getting a lot of mileage out of cmp and beq commands for control of my melee and moving states.

where I'm fucking up is;

I've got-
cmp $03 (attacking )
beq ++
cmp $02 (jumping)
beq+

change states 3, 2
+start moving
++ just face dir

so, when attacking, my char stops.. i want that. but when jumping and attack how do I over ride the state 2 animation, as well branch back to + ?
I've tried

cmp 3 && 2
beq +++

+++
change states
beq +....

am I in the ball park ?
 

Kasumi

New member
There is a difference between cmp #$03 and cmp $03.

cmp #$03 compares the accumulator to the value 3.
cmp $03 compares the accumulator to the value stored in RAM location $0003.

Make really sure you're using #$, not $. Also, if I were you, I'd just name the labels.
Code:
cmp #$03
beq attackstate
cmp #$02
beq jumpstate
;some code, whatever

attackstate:
Could you maybe write what you want in a higher level language again? Without seeing the destinations for the branches, it's hard to follow.
 

digit2600

Member
thanks kasumi, I can...here's my original code (sorta) from the pc release. .. originally done in as2.... this is just a quick pseudo code mockup )

if (walking && !jumping &&!attacking ) {go-to walk animation; speed=max}else
if (walking && jumping &&!attacking ){go-to jump animation; speed=max } else
if (walking && jumping && attacking ){go-to attack;speed=max} else
if (attacking && !jumping){go-to attack anim; speed=0,walking =false }

that should give you an idea what I'm trying to do... my original code is accessible if you wanna see that, but this should be fairly self explanatory. ..

really, it's just a standard platformer action instruction set...
 

digit2600

Member
it could have been closer to this too.... it's been ages since I wrote it... but you'll get it... please don't mock my shitty embedded if statements. .. it worked lol, that's all I'll say !
if (keyleft){dir=l;speed=max; walk=true }
if (keyright){dir=r;speed= max; walk=true }
else {walk=false }
}
if (keyA){jump=true}
if (keyB){attack=true }
}
if (attacking ){
if (walking && !jumping ){speed=O; play attack}
if (walking && jumping ) {speed=max;play attack}
else{ play attack }
}else
if( jumping ){play jump}
if (walking ){play walk}
}
 

Rob Burrito

New member
digit i'm stuck on a similar spot in writing these (what seems like) very basic code snips. i appreciate everyone taking the time to answer, hopefully it clicks for us all soon!
 

dale_coop

Moderator
Staff member
Wow... I am kinda lost here...what are the ASM scripts your are currently using?
And what doesn't work yet?

I was supposing (1 button pressed) walk, jump, attack already work as you want...
Maybe (2 butttons pressed) walk+attack already work too, natively?

The problem is with jump?
 

digit2600

Member
These are the modified Scripts I'm using right now... #$03 is the melee state....
I've got it to the point now where it will fire off the attack animations when I need them to, Now I'm just trying to figure out how add one more condition...

When you attack- The player stops in place which is what I want. Except when you are jumping, then I want it to continue to move in whatever direction..
Code:
 ;;;;;;Start moving player right script;;;;;;;
    LDX player1_object
    GetCurrentActionType player1_object
    CMP #$01;;walk
    BEQ+
   
    CMP #$03    ;; if attacking movement isn't possible
    BEQ ++  
    
    CMP #$02;; if jumping movement is possible
    ;;;; How would I add a clause to the argument that if it is both jumping AND attacking to branch to + ?;;;
    
    BEQ +
     
    ChangeObjectState #$01, #$02, #$03 
    +
    StartMoving player1_object, MOVE_RIGHT
 ++
    FaceDirection player1_object, FACE_RIGHT
  
    RTS
;;;;;;;;;;;;;;;Melee script;;;;;;;;;;;;;;;;;; 
    
  LDA gameHandler
 AND #%00100000
 BEQ notNPCstate_attack
 JMP doneAttacking
notNPCstate_attack
 LDA weaponsUnlocked
 AND #%00000001
 BNE canAttack
 JMP doneAttacking
canAttack:
LDX player1_object
 GetCurrentActionType player1_object
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this is just to make sure that it plays the attack animation whether the player is walking or jumping;;;;;
 CMP #$01 ;if player is walking
 BNE notAlreadyAttacking 
 CMP #$02 ; if player is jumping
 BNE notAlreadyAttacking 
 JMP doneAttacking
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;I don't think I messed with anything under here, other than reassigning the melee state to #$03 
notAlreadyAttacking
 ;;; don't attack if already attacking.
 ;;; do we have to check for hurt here?
 ;;;;; Here, we WOULD create melee
 ChangeObjectState #$03, #$02
  
 LDA Object_movement,x
 AND #%00001111
 STA Object_movement,x
 LDA #$00
 STA Object_h_speed_hi,x
 STA Object_h_speed_lo,x
 STA Object_v_speed_hi,x
 STA Object_v_speed_lo,x
 
 LDA Object_x_hi,x
 STA temp
 LDA Object_y_hi,x
 STA temp1
 
 LDA Object_movement,x
 AND #%00000111
 STA temp2
 AND #%00000010 ;; this will be 0 on up and down, but 1 on left right
 BNE createLRmelee
    LDA temp2
    TAY
    LDA temp
    SEC
    SBC #$08 ;; width of weapon
    CLC
    ADC weaponOffsetTableX,y
    STA temp
    LDA temp1
    SEC
    SBC #$10
    CLC
    ADC weaponOffsetTableY,y
    STA temp1
 
    CreateObject temp, temp1, #$02, #$00
  JMP meleeCreated
createLRmelee:
    LDA temp2
    TAY
    LDA temp
    SEC
    SBC #$10 ;; width of weapon
    CLC
    ADC projOffsetTableX,y
    STA temp
    LDA temp1
    SEC
    SBC #$08
    CLC
    ADC projOffsetTableY,y
    STA temp1
    CreateObject temp, temp1, #$01, #$00
meleeCreated:
    ;;;; x is now the newly created object's x.
    LDA Object_movement,x
    ORA temp2
    STA Object_movement,x
   ; PlaySound #sfx_slash
doneAttacking:
 
RTS


;;000 down
;010 right
;100 up
;110 left

I didn't bother including the move left script.. it's the same edits as the move right script.
It's like 85 percent there.... lol...
 

dale_coop

Moderator
Staff member
Try with this modifications to your melee script:
Code:
  LDA gameHandler
 AND #%00100000
 BEQ notNPCstate_attack
 JMP doneAttacking
notNPCstate_attack
 LDA weaponsUnlocked
 AND #%00000001
 BNE canAttack
 JMP doneAttacking
canAttack:
LDX player1_object
 GetCurrentActionType player1_object
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this is just to make sure that it plays the attack animation whether the player is walking or jumping;;;;;
 CMP #$01 ;if player is walking
 BEQ notAlreadyAttacking 
 CMP #$02 ; if player is jumping we skip the change state and modification movement.
 BEQ continueCreatingMelee 
 JMP doneAttacking
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;I don't think I messed with anything under here, other than reassigning the melee state to #$03 
notAlreadyAttacking
 ;;; don't attack if already attacking.
 ;;; do we have to check for hurt here?
 ;;;;; Here, we WOULD create melee
 ChangeObjectState #$03, #$02
 
 LDA Object_movement,x
 AND #%00001111
 STA Object_movement,x
 LDA #$00
 STA Object_h_speed_hi,x
 STA Object_h_speed_lo,x
 STA Object_v_speed_hi,x
 STA Object_v_speed_lo,x
 
continueCreatingMelee:
 LDA Object_x_hi,x
 STA temp
 LDA Object_y_hi,x
 STA temp1
 
 LDA Object_movement,x
 AND #%00000111
 STA temp2
 AND #%00000010 ;; this will be 0 on up and down, but 1 on left right
 BNE createLRmelee
    LDA temp2
    TAY
    LDA temp
    SEC
    SBC #$08 ;; width of weapon
    CLC
    ADC weaponOffsetTableX,y
    STA temp
    LDA temp1
    SEC
    SBC #$10
    CLC
    ADC weaponOffsetTableY,y
    STA temp1
 
    CreateObject temp, temp1, #$02, #$00
  JMP meleeCreated
createLRmelee:
    LDA temp2
    TAY
    LDA temp
    SEC
    SBC #$10 ;; width of weapon
    CLC
    ADC projOffsetTableX,y
    STA temp
    LDA temp1
    SEC
    SBC #$08
    CLC
    ADC projOffsetTableY,y
    STA temp1
    CreateObject temp, temp1, #$01, #$00
meleeCreated:
    ;;;; x is now the newly created object's x.
    LDA Object_movement,x
    ORA temp2
    STA Object_movement,x
   ; PlaySound #sfx_slash
doneAttacking:
 
RTS


;;000 down
;010 right
;100 up
;110 left


If your player is jumping... just skip all the part that modifies/stops the player movements.
 

dale_coop

Moderator
Staff member
I think you could clean up a little the script. It's meant to be used in adventure module... topdown.
The script uses a different object as weapon when the player facing Up/Down. But in a platformer, the player never face up/down.
So you could remove all that part and just keep the Left/Right part (you will save more space for more scripts ;))

Maybe like that:
Code:
	LDA gameHandler
	AND #%00100000
	BEQ notNPCstate_attack
	JMP doneAttacking
notNPCstate_attack
	LDA weaponsUnlocked
	AND #%00000001
	BNE canAttack
	JMP doneAttacking
canAttack:
	LDX player1_object
	GetCurrentActionType player1_object
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this is just to make sure that it plays the attack animation whether the player is walking or jumping;;;;;
	CMP #$01 ;if player is walking
	BEQ notAlreadyAttacking 
	CMP #$02 ; if player is jumping, we skip all the changing state / stoping the player
	BEQ continueCreatingMelee 
	JMP doneAttacking
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;I don't think I messed with anything under here, other than reassigning the melee state to #$03 
notAlreadyAttacking
	;;; don't attack if already attacking.
	;;; do we have to check for hurt here?
	;;;;; Here, we WOULD create melee
	ChangeObjectState #$03, #$02

	LDA Object_movement,x
	AND #%00001111
	STA Object_movement,x
	LDA #$00
	STA Object_h_speed_hi,x
	STA Object_h_speed_lo,x
	STA Object_v_speed_hi,x
	STA Object_v_speed_lo,x
 
continueCreatingMelee:
	LDA Object_x_hi,x
	STA temp
	LDA Object_y_hi,x
	STA temp1
 
	LDA Object_movement,x
	AND #%00000111
	STA temp2

	LDA temp2
	TAY
	LDA temp
	SEC
	SBC #$10 ;; width of weapon
	CLC
	ADC projOffsetTableX,y
	STA temp
	LDA temp1
	SEC
	SBC #$08
	CLC
	ADC projOffsetTableY,y
	STA temp1
	CreateObject temp, temp1, #$01, #$00
	
	;;;; x is now the newly created object's x.
	LDA Object_movement,x
	ORA temp2
	STA Object_movement,x
	;; PlaySound #sfx_slash
   
doneAttacking:
	RTS
 

digit2600

Member
Thanks Dale Coop, it works ! I made one more change afterwards...

I added an extra state #$05 (jumpAttack) and added some changes to a few lines-
Now I just have to find a way to sync up the physics....

in Melee:
canAttack:
LDX player1_object
GetCurrentActionType player1_object
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this is just to make sure that it plays the attack animation whether the player is walking or jumping;;;;;
CMP #$01 ;if player is walking
BEQ notAlreadyAttacking
CMP #$02 ; if player is jumping, we skip all the changing state / stoping the player
ChangeObjectState #$05, #$02 ;; changes to jumpAtttack state
BEQ continueCreatingMelee
JMP doneAttacking

;;;;;;;;;;;;;;;;;;;;;;;;then for moving left/right i just added another conditional for jumpAtack;;;;;;;;;;;;;;;;;
LDX player1_object
GetCurrentActionType player1_object

CMP #$01;;walk
BEQ+
CMP #$03;;attack
BEQ ++
CMP #$02;; jump
BEQ +

CMP #$05;; jumpAttack
BEQ +


ChangeObjectState #$01, #$03, #$05

+
StartMoving player1_object, MOVE_LEFT
++
FaceDirection player1_object, FACE_LEFT




RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 

Kasumi

New member
I won't make fun of your if statements, but you can use code tags to preserve your indentation.

Typing what's in the below image
MFQeSbF.png

will get the below text.
Code:
if you use code tags
      indentation is preserved
I looked into this, but I always end up not being super confident I can make safe changes within the engine since I'm not super familiar with it yet... one benefit of writing everything is super familiarity with how what you write will affect things.
 
Top Bottom