Branching - 6502 Assembly Crash Course 03

  Рет қаралды 21,981

NesHacker

NesHacker

Күн бұрын

In this episode I show you how NES games make decisions using branching and comparison instructions on the 6502.
Support the channel on Patreon: / neshacker
- Code Repository: github.com/NesHacker/Assembly...
- 6502 Instruction Reference: www.masswerk.at/6502/6502_ins...
Chapters:
0:00 Introduction
1:21 Making Decisions
2:55 The Program Counter (PC)
5:05 Processor Status Flags
8:00 Code Example
10:50 Conclusion

Пікірлер: 61
@bensmith218
@bensmith218 2 жыл бұрын
The carry flag is set for A >= Memory, because subtraction is actually treated as adding a negative value. Negative numbers are encoded using two's complement, which means that to negate a number you invert the bits and add 1. So, for example, if we want to compare $03 and $05 we negate $05 and add it to $03: $03 - $05 $03 + $fb This gives the answer $fe which is the two's complement encoding of -2. The carry flag is not set because this addition didn't overflow. If we instead compare $05 to $03 we get: $05 - $03 $05 + $fd This gives the answer $02, but also sets the carry flag since the actual result was $102. Similarly, if you compare two values that are equal, you will set the carry flag since the resulting addition will always be $100.
@NesHacker
@NesHacker 2 жыл бұрын
Wow, that is a slick mathematic explanation, nicely stated!
@amaiorano
@amaiorano 2 жыл бұрын
Hey Ben, I love how I keep bumping into you, even on random KZbin comments :)
@bensmith218
@bensmith218 2 жыл бұрын
@@amaiorano Heh, true! Good to see you Antonio! Working on a NES emulator or just watching some good vids?
@amaiorano
@amaiorano 2 жыл бұрын
@@bensmith218 Always wanted to write an NES game myself, and now my son wants to as well! These videos are great.
@georgiysrbsk
@georgiysrbsk 2 жыл бұрын
Easily the most approachable 6502 assembly course on KZbin. Love the series, Ryan. You earned a sub and like on every video. Greetings from Serbia!
@NesHacker
@NesHacker 2 жыл бұрын
That means a lot! Thank you very much for the support! Also, Serbia? Nice! I’m half Hungarian, though I’ve only been to Eastern Europe once as a kid… :D
@georgiysrbsk
@georgiysrbsk 2 жыл бұрын
@@NesHacker Wow, that is awesome. After the pandemics end, you should definitely visit more. Budapest is my favorite destination. :D
@Desmaad
@Desmaad Жыл бұрын
I'd say he gives some insight into assembly in general. Sure, every CPU does things differently, but I think I can assume there's enough similarities to get the gist of them all (except the PDP-8; that architecture is whack.)
@NesHacker
@NesHacker 2 жыл бұрын
So what do you all think about branching on the 6502? Stick around to the end of the episode where I present a coding challenge! *UPDATES* - There is a typo on line 20 of the example: it should read: “sta $02” (not $01). Thanks @Captain N! - Turns out there _is_ a slick math reason why the CMP instruction sets Carry Flag is set when A >= Memory. See the awesome comment by @Ben Smith below!
@lolbruah
@lolbruah Жыл бұрын
As an IT guy, who learned all the digital-tech stuff in school 25 years ago, and also had an NES as Kid (magical greybox) I gotta admit: I‘m eating up your 6502 content for hours straight since yesterday. Maybe it‘s time to get into programming again :)
@NesHacker
@NesHacker Жыл бұрын
Sweet :), glad you’re enjoying the channel!
@michmart9261
@michmart9261 2 жыл бұрын
To make the routine branch-less I would lda #0 rol Which pushes the carry flag into the lowest bit of A which can be used as the output
@32BitChronicles
@32BitChronicles Жыл бұрын
I would avoid branching by storing the carry in the address $01: ; Initialize Health, Damage, and the Return Value lda #25 sta $00 lda #30 sta $01 lda #0 sta $02 ; Check if Damage >= Health lda $01 cmp $00 ; Set address $01 with the value of the carry to indicate the player has died or not lda #0 adc #0 sta $01 Amazing videos by the way! I hope you release more soon!
@ordozgoite
@ordozgoite Жыл бұрын
Amazing! I just didn´t understand why the result of the adc is stored on $01. I thought the return value should be stored in $02, since #0 was stored there on the beggining of the code.
@razorblade413
@razorblade413 5 ай бұрын
@@ordozgoite honestly I don't know why the result of adc is stored on $01. Is not supposed that $01 stores the damage? should not be the result of adc stored on $02 or any new memory address since health and damage have already assigned their spaces? What about if an enemy does an incoming damage of 1 then?
@razorblade413
@razorblade413 5 ай бұрын
@@ordozgoite In fact I still don't get it why Ryan set address $01 instead of $02 to indicate if the player has died or not.
@wildside4822
@wildside4822 9 ай бұрын
This was very helpful thanks
@popoffs5273
@popoffs5273 2 жыл бұрын
The 6502 processor sets the carry flag when the A reg is large that memory because when you do subtraction, the carry out will be on if the answer is positive, and off if it is negative. When it does subtraction it does a process called twos compliment in which, you flip the bits and then add on, when added to a number it subtracts if you ignore the carry out.
@mikolanimator
@mikolanimator 2 жыл бұрын
Thank you for your videos. You have an awesome channel. Great explanation and production quality. Please keep them coming. Thank you
@NesHacker
@NesHacker 2 жыл бұрын
Thanks for watching them! It’s always a thrill when folks watch the new videos right after I put them out :)
@adrian-587
@adrian-587 2 жыл бұрын
Great video Ryan! I hope to see next video soon! Keep it up.
@NesHacker
@NesHacker 2 жыл бұрын
Appreciate it!
@jeffjohnson7984
@jeffjohnson7984 10 ай бұрын
Random question... what software do you use to create the stylized graphics that represent the various concepts in your videos? I think it is very well done and very clear! Thank you.
@NesHacker
@NesHacker 10 ай бұрын
I do custom graphics using Adobe Illustrator and animate them using After Effects.
@bandlsd
@bandlsd 2 жыл бұрын
Excellent tutorial, thanks!
@PixelguardianGame
@PixelguardianGame 2 жыл бұрын
Liked and subbed! I love this channel and this series
@NesHacker
@NesHacker 2 жыл бұрын
Appreciate it! There’s so much more cover, so I’ll be making a LOT more videos, haha XD
@andreazaffino
@andreazaffino 2 жыл бұрын
Simply sublime 😃
@PabloSanchez-th5em
@PabloSanchez-th5em 2 жыл бұрын
Amazing course this it is!
@8_BitKing
@8_BitKing 2 жыл бұрын
I loved this
@DPBOX
@DPBOX 2 жыл бұрын
Is this the way to do it without branching? ; Initialize Health, Damage, and the Return Value lda #25 sta $00 lda #30 sta $01 lda #0 sta $02 ; Check if Damage >= Health lda $01 cmp $00 rol A and #1 ; Set carry flag into $01 to to indicate the player has died sta $01 rts I do assembly on the Super Nintendo because I hack Super Mario World, but I think the Super Nintendo's processor is backwards compatible with the NES one.
@NesHacker
@NesHacker 2 жыл бұрын
Beautiful! Yep, that was pretty much exactly what I was thinking :D
@knghtbrd
@knghtbrd 2 жыл бұрын
@@NesHacker The question there is did you wanna teach cmp/bcc or and/rol and instruction cycle length. While and and rol might be good fodder for a crash course, the reason why you'd do it over just branching surely isn't. 😁 Gotta say, I'm enjoying your approach to the basics, Ryan. Watching because I need to deoxit my brain's contacts a little. It's all coming back to me, like falling off a bicycle. (Ouch.) Now what's the equivalent of applying rust converter paint to the chassis again?
@yt_n-c0de-r
@yt_n-c0de-r Жыл бұрын
Would have loved a bit of comment how/why rol & and are used here, for all us noobs not proficient in (S)nes dev (yet)... In the meantime I found a solution of "pushing the carry bit out" (ROL) - still wrapping my old head around it XD Love the videos, even if after 20years of trying to learn this it still all is just magic to me :)
@ezekieloruven
@ezekieloruven 2 жыл бұрын
I feel like address $02 was forgotten in this subroutine. It looks like the result of the routine is supposed to be stored in $02, but it gets stored in $01 instead, overwriting the damage taken. This probably doesn't matter but I'd prefer using $02 to store results. lda #25 sta $00 lda #30 sta $01 lda #0 sta $02 lda $01 cmp $00 rol $02 rts
@NesHacker
@NesHacker 2 жыл бұрын
You’re correct. I made a mistake and accidentally used $01 instead of $02 (which is what I intended) in the example. Thanks for letting me know, another viewer had already done so, and I usually put corrections in a pinned comment on the videos. Thanks for watching and paying such close attention! :D
@MrMassaraksh
@MrMassaraksh Жыл бұрын
Thanks!
@amnotonline3011
@amnotonline3011 2 жыл бұрын
Is this the solution to the "check hp without branching" puzzle? LDA $HP_LOCATION SEC SBC $DAMAGE_LOCATION ; If the HP is greater or equal to the Damage, the C flag will be set STA $HP_LOCATION LDA #$00 ADC #$00 ; If the carry is clear (Player is alive / HP is exactly 0 (Call the one extra point of HP benevolent Game Design ;)), 0 will be in A, else, the carry will factor in and A will contain 1 STA $DEAD_STATE (Hopefully this works the same as in 65816 asm. Love your videos!)
@NesHacker
@NesHacker 2 жыл бұрын
It’s close but it doesn’t give the *exact* same output. But bonus points for “benevolent game design,” haha. Thanks for watching!
@captainnintendo
@captainnintendo 2 жыл бұрын
I really appreciate you doing these videos and putting so much time into making the visual representations easy to understand. I have s question or two. First, I get the N flag and the Z flag. That makes sense, but I don't really get why the C-flag would also set in if the A value is equal to the compared value... Isn't that whole point of the Z flag. And what if I only want something to happen if the compared value is higher than equal? Also for the very last part of the code that is executed if the carry flag is 0 (Lethal hit) Should it be $02 that gets a value of #1, not $01?
@NesHacker
@NesHacker 2 жыл бұрын
So you’re right! I have a typo and it should have been $02 instead of $01 there! As far as I understand it, the Carry Flag is set this way so we can check all of the inequalities () via a single flag. If the 6502 only set the Carry when A > M then I’m pretty sure we’d have to use two checks in order to handle the “>=“ and “=“ and “
@captainnintendo
@captainnintendo 2 жыл бұрын
@@NesHacker I guess that makes sense. This is still really new to me so I'm just trying to wrap my head around the logic of all of it.
@hicknopunk
@hicknopunk 2 жыл бұрын
Oh I just hate you 😄 was about to go to bed and saw this upload. You b@stard! 😅 Thanks for making these. Could you make a review of several 6502 hobby boards? Would I be better off just using a NES without a NES10 chip than buying something modern? It would be lovely to see the NES go up against 2 to 3 modern 6502 boards.
@NesHacker
@NesHacker 2 жыл бұрын
I haven't messed with them too much but that's a great idea for a video! I'm finally getting all my electronics lab stuff setup so once I get the lab put back together I'd be more than happy to do an episode on the subject. Do you have any in particular you'd like my thoughts on? Unfortunately I can't answer your question about which to use right now, since I haven't done much with them, but you can't go wrong getting some vintage NES gear in my opinion haha.
@mohdyasir1645
@mohdyasir1645 2 жыл бұрын
Most of the things are similar to Assembly Language and Architecture of 8085 Microprocessor
@kirby0louise
@kirby0louise 2 жыл бұрын
Just copy the carry flag into the $01 No branch instruction needed
@NesHacker
@NesHacker 2 жыл бұрын
Indeed :)
@dr.ignacioglez.9677
@dr.ignacioglez.9677 Жыл бұрын
I LOVE C64 👍🥂🎩
@kythrathesuntamer9715
@kythrathesuntamer9715 Жыл бұрын
keep making videos.
@randysmith7094
@randysmith7094 Жыл бұрын
@ 3:58 - are absolute addresses always reversed in their 2 bytes? If I'm looking in the ROM code for a reference to RAM address $0321 then I should do a HEX string search for "2103"? Or if I know the instruction is STA, it should be found as "8D2103" somewhere in the ROM code? Right? Or does this code look different in the ROM file? Because I'm having trouble finding code for a certain "lives count" address.
@dimi144
@dimi144 2 ай бұрын
Yes. The 6502 is a little-endian machine, meaning that when it stores multi-byte values it always stores the less significant byte first, so when you write $2103 the assembler will assemble it to 0321 because the processor expects you to give it the low byte first and then the high byte after
@pancelor
@pancelor 2 жыл бұрын
thanks for the little coding challenge; it got me to set up a dev enviroment and write some NES code for the first time! my solution: ; Initialize Health, Damage, and the Return Value lda #17 sta $00 lda #33 sta $01 lda #0 sta $02 ; Set Carry iff Damage >= Health lda $01 cmp $00 lda #0 adc #0 ; Set address $02 to death state (1=dead,0=alive) sta $02 rts
@NesHacker
@NesHacker 2 жыл бұрын
Nice!
@NesHacker
@NesHacker 2 жыл бұрын
@@jakeelliott1512 So when you use ADC to add 0 to 0 it will result in a 1 if the carry flag is set (this is why it’s called Add with Carry). At this point the A register has a value of 1 if and only if the damage >= health (because the CMP instruction above only sets the carry flag in this case). So they write out the value to $02 where we want to store the result. Hope that helps :)
@peterponomarev1622
@peterponomarev1622 2 жыл бұрын
If Damage < Health, couldn't BMI be used as well instead of BCC? Or am I not understanding? Thanks.
@peterponomarev1622
@peterponomarev1622 2 жыл бұрын
I think I just answered my own question ... The carry flag would be set on greater than OR equal, both of which result in Game Over
@vuurniacsquarewave5091
@vuurniacsquarewave5091 2 жыл бұрын
@@peterponomarev1622 BMI and BPL are really good for terminating loops though when iterating through a set of data, because you will also need to complete your loop when the counter is 0. So right after a decrement instruction you can BPL back to the start of the loop.
@Ensign_Cthulhu
@Ensign_Cthulhu 6 ай бұрын
Amateur C64 programmer here. I note the absence of the Break flag on the NES. I'm assuming this is because there's simply no need for it at the user level on a system whose only function is to play cartridge games.
@16bitdude36
@16bitdude36 Жыл бұрын
;lets assume HP=$00 , DMG=$01 lda $01 cmp $00 bcc gameoverYEAHHHHHHHHHHHHHHHH rts; gameoverYEAHHHHHHHHHHHHHHHH: ;insert code Is the above code equivalent to this? void isAlive(uint_8 hp,uint_8 dmg)// { if(dmg>=hp) gameover(); //insert code return; }
@saganandroid4175
@saganandroid4175 3 ай бұрын
OMFG can you STOP that up and down voice thing. It's like a girl that keeps up pitch talking then rapidly cycling. I'm sure you are knowledgeable and have useful information to convey but oh my God it is painful to hear people talk like this. ValleyGirl would be less painful.
Bitwise Logic - 6502 Assembly Crash Course 04
14:42
NesHacker
Рет қаралды 20 М.
Basics - 6502 Assembly Crash Course 01
12:49
NesHacker
Рет қаралды 105 М.
How To Choose Ramen Date Night 🍜
00:58
Jojo Sim
Рет қаралды 31 МЛН
CAN FOXY TRICK HIM?! 🤣 #shorts *FOXY AND NUGGET!*
00:17
LankyBox
Рет қаралды 18 МЛН
Coding NES Loops
17:10
NesHacker
Рет қаралды 26 М.
HOW TRANSISTORS RUN CODE?
14:28
Core Dumped
Рет қаралды 30 М.
Reverse Engineering Game Code from the Neutral Zone
40:59
Retro Game Mechanics Explained
Рет қаралды 474 М.
Teaching myself C so I can build a particle simulation
11:52
Gradience
Рет қаралды 38 М.
How NES Games Use State Machines For Everything
8:21
NesHacker
Рет қаралды 29 М.
Coding NES Subroutines
8:15
NesHacker
Рет қаралды 53 М.
How Zelda Saves Your Game
10:03
NesHacker
Рет қаралды 202 М.
Computing Pi on the NES
9:43
NesHacker
Рет қаралды 164 М.
Теперь это его телефон
0:21
Хорошие Новости
Рет қаралды 170 М.
Как открыть дверь в Jaecoo J8? Удобно?🤔😊
0:27
Суворкин Сергей
Рет қаралды 1 МЛН
Photo editing changing Boder Work solution New tools
0:52
UNIQUE PHOTO EDITING
Рет қаралды 219 М.
Пленка или защитное стекло: что лучше?
0:52
Слава 100пудово!
Рет қаралды 1 МЛН