Тёмный

Coding NES Subroutines 

NesHacker
Подписаться 94 тыс.
Просмотров 57 тыс.
50% 1

Learn all about programming subroutines in the 6502 assembly on the NES.
Support the channel on Patreon: / neshacker
Code Challenge:
Submissions will be chosen from the comments through 1/22/2023 and the winner selected and pinned on 2/1/2023.
Music:
Evgeny Bardyuzha - Speed Freak
2050 - Nova
Luke Melville - After Midnight
Alchemorph - Raintown (My Love fore You) - Instrumental Version
Chapters:
0:00 Introduction
0:28 Subroutines Explained
2:07 The Stack
5:08 Using Parameters
6:49 Coding Challenge

Наука

Опубликовано:

 

23 июл 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 235   
@aidangarvey7049
@aidangarvey7049 Год назад
Here's my submission for the challenge, it's my first time programming in 6502 so there might be mistakes (I'm more familiar with 68K) ; ============================================= ; pickup_refill ; --------------------------------------------- ; Refills player health or weapon from a pickup ; --------------------------------------------- ; Parameters: ; $00: pickup type (health = 0, weapon = 1) ; $01: pickup size (small = 0, large = 1) ; --------------------------------------------- ; Notes: ; - Player's health is stored at $0100 ; - Player's weapon charge is stored at $0101 ; ============================================= pickup_refill: ; get pickup type in X so desired player stat is at $0100,X ldx $00 ; load stat value into A lda $0100,X ; get pickup size, add appropriate amount to A ldy $01 beq small_pickup ; large pickup: grant 25 health/weapon adc #15 ; (intentional fall-through to add rest of value) small_pickup: ; small pickup: grant 10 health/weapon adc #10 ; if we went over 100 health/weapon, limit to 100 cmp #100 bmi save_value lda #100 save_value: ; store new health/weapon value sta $0100,X rts
@NesHacker
@NesHacker Год назад
Congrats! The patrons chose your code to get pinned! Shout out to the runners up: @dedgzus6808, @kentwidman, and @soulite2574 :D
@aidangarvey7049
@aidangarvey7049 Год назад
Thank you so much to everyone who voted for me!
@CallousCoder
@CallousCoder Год назад
That’ll do nicely for sure.
@EvilSandwich
@EvilSandwich Год назад
One tiny and easily fixable issue. It looks like you're storing the player's health and weapon charge on the Stack Page. Just swap out the $0100 and $0101 with $0300 and $0301 and you're perfect! :) Great job though!
@brighthades5968
@brighthades5968 Год назад
@@EvilSandwich Most games don't use the whole stack area so they can store other values there
@AndyScott
@AndyScott Год назад
I love watching these thinking "one day I'll do this" knowing full well I will not....yet I will watch this kind of magnificently crafted educational lesson all day long.
@zzeck431
@zzeck431 Год назад
There are online 6502 assemblers and emulators you can use to begin. I used skilldrick easy 6502, because I was too lazy to dig up my cc65 assembler setup.
@NesHacker
@NesHacker Год назад
Honestly I just think it’s cool that so many people like the things that I like too :)
@dedgzus6808
@dedgzus6808 Год назад
I always had the same thought to but then after this video I just opened notepad and wrote up some code. Give it a shot.
@InsaneFirebat
@InsaneFirebat Год назад
Programming has been an interest of mine since I was young, but it was super intimidating with no formal education. I started off making copy/paste edits in Super Metroid's speedrun practice hack source and eventually started looking up what the opcodes do. Once I started looking into addressing modes, the doors flew open and everything started to make sense. It's been very rewarding and I wish they'd taught me this stuff in elementary school. Hope you can dig in some day. The 65x processors are awesome.
@Cubearr
@Cubearr Год назад
Honestly and truly: Just start doing it. post about it on rhdn or anywhere else, ask questions, do research, thumb through sections of code and try to understand it. you can make it happen for you, it just takes some focus and a little bit of work. Doing it badly is fine, just doing it at all is fun and rewarding.
@MerrStudio
@MerrStudio Год назад
Holy crap this channel is underrated AF. Watched the video first, noticed the like count/views second. Both of these should be x100 at least! You just earned a sub sir.
@NesHacker
@NesHacker Год назад
Welp that’s how it goes, one sub at a time :)
@MatteoTarantino1979
@MatteoTarantino1979 Год назад
Agreed 100%
@guillermomoreno4287
@guillermomoreno4287 Год назад
The editing, information and quality are top notch
@NesHacker
@NesHacker Год назад
Thanks, I try my best :)
@scottwilliams895
@scottwilliams895 Год назад
First time watching your channel. Big ups to your style! This video is basically a course mini-lecture on teaching programming, while still being interesting to watch for those of us students who aren't doing the homework.
@NesHacker
@NesHacker Год назад
That’s the idea, at least. The hope is that the videos straddle the line between lecture and entertainment, and do it so everyone comes away with something 😀
@scottwilliams895
@scottwilliams895 Год назад
@@NesHacker You hit it just right! Half way thru, I was like "Yeah, I *should* learn to program in Assembly... for the NES!! "
@CallousCoder
@CallousCoder Год назад
Maybe you’ll like a lot of my content too. I have a rom of C64 and some Amiga now. And also ARM64 assembly on Linux. But also game hacking cracking which uses 6502, z80 and 68000
@MrBoogerblood
@MrBoogerblood Год назад
I’m addicted to these videos. I have way too many other things going on to ever hope to have time to mess with this too but you’re subject matter presentation is next level. So much info crammed into a 15-20 min video and it doesn’t feel overwhelming. Great job man.
@NesHacker
@NesHacker Год назад
Thanks, I put a lot into them so I am glad you like the videos so much 😀
@maverick_loneshark
@maverick_loneshark Год назад
あけましておめでとうございます、 NESHacker! Kind of tied up with attempts at modern, wannabe-retro game dev right now (trying to write a better shader for simulating a high end CRT), but you have me inching closer and closer to doing a NES homebrew game jam. Thank you for all of the valuable NES dev info!
@NesHacker
@NesHacker Год назад
You’re more than welcome, and happy new year to you too, Maverick!
@jimmyraconteur2522
@jimmyraconteur2522 Год назад
LOL I love your handle! It reminds me of a character from a Yakuza game!
@maverick_loneshark
@maverick_loneshark Год назад
@@jimmyraconteur2522 for all we know, *this* IS a game...
@akkoestranha4323
@akkoestranha4323 Год назад
I was waiting this so much! Love your videos!
@NesHacker
@NesHacker Год назад
Thanks, I’m happy to oblige :)
@jake967
@jake967 Год назад
Outstanding visuals!
@sanderbos4243
@sanderbos4243 10 месяцев назад
Found your channel yesterday while looking for 6502 documentation online, and your 6502 Assembly Crash Course playlist this is part of has been unimaginably helpful to me! I've also got VS Code set up with fceux64 using your tutorial, so it is time to crank out the classic Game of Life! :D
@JustixLoL
@JustixLoL Год назад
Omfg, last month everything I've been doing is digging info about old consoles, especially the NES and programming 6502 cpu. Planned to develop a small NES game to touch it myself for better understanding and HERE YOU ARE - THE HERO! Right in time! Many thanks for you exceptionally helpful material! Please, keep going
@NesHacker
@NesHacker Год назад
The hero, huh? Haha, well I don't know about that, but I am glad I can help!
@ebs777
@ebs777 Год назад
I been working on super mario bros hacks on and off for a couple years and even knowing the asm i do now your videos always teach me something new. Thank you so much
@NesHacker
@NesHacker Год назад
You’re very welcome, I’m glad to help :)
@ajhieb
@ajhieb Год назад
What a great start to the year! NesHacker and Retro Game Mechanics Explained posting new videos on the same day!
@NesHacker
@NesHacker Год назад
I considered releasing it yesterday… but I was worried people would be too tired to digest 6502 assembly xD
@Raubritterr222
@Raubritterr222 Год назад
I love your NES videos so MUCH! Thank you! 🎮
@NesHacker
@NesHacker Год назад
You’re very welcome :)
@8_BitKing
@8_BitKing Год назад
really nice videos and great animations!
@NesHacker
@NesHacker Год назад
Thanks!
@3DSage
@3DSage Год назад
You make me want to program a NES game! Really great and clear explanation so thank you!
@Cr_nch
@Cr_nch Год назад
-3d on nes-
@NesHacker
@NesHacker Год назад
Nice! It’s definitely work but it is totally doable, just start small and build up from there :)
@djrmarketing598
@djrmarketing598 Год назад
Funny when you say 6502 assembly the first thing that comes to mind is Commodore 64 programming, but that was 10 year old me back in the day having no idea that 6502's were in just about everything by 1988. Had I been 10 years older I probably could have put all that learning to use professionally, but alas it was my gateway to x86 assembly language. I made so many inline assembly routines inside C and Pascal programs back then, back when every cycle mattered.
@tmanley1985
@tmanley1985 Год назад
I never subscribed so fast in my life. This is incredibly well done.
@NesHacker
@NesHacker Год назад
Nice! This was probably my best editing job thus far, so I hope you like my other videos too.
@repeaterlanes8024
@repeaterlanes8024 Год назад
Health: $00FF Energy: $00FE 32 bytes in the zero page for subroutine parameters like you would do. 1 byte ($0000) actually used for this function. the High nybble (Bits 4 - 7) will be type, the Low nybble (Bits 0 - 3) will be the amount. This method would allow 16 types and 16 amounts in case it will be used elsewhere, however in this case it will be optimised for this challenge refill: lda #$F0 and $00 //Obtain the high nybble to dictate what type to add to lsr lsr lsr lsr tax lda #$19 //Load 25 into Accumulator. This is the small amount pha lda #$0F and $00 //Obtain the low nybble to dictate what amount to add to the variable beq skip_big_refill //If 0, then it is the small amount, otherwise add 25 to the value to get the medium amt pla adc #$19 //Add 25 to Accumulator, making the amount from earlier to the medium amount, 50 pha skip_big_refill: pla clc adc $FE, x //Add the corresponding variable (Health or Energy) to Accumulator cmp #$64 // check if result is more than 100. if so, set the Accumulator to 100 bpl skip_clamp lda #$64 skip_clamp: sta $FE, x //finally, store the accumulator to the variable rts (Fair note, its been a while since ive coded 6502 asm, so my syntax might be off. dont really have a way to verify it admittedly but i hope it works) (Edit: Forgot to shift the upper nibble parameter 4 times to the left)
@sprobertson
@sprobertson Год назад
I think you're reaching a good pace/level of explanation with these last few videos... tbh I was a bit worried when inx/dex took up 3 minutes in the first one haha. Great to see the very practical example of using parameters especially.
@NesHacker
@NesHacker Год назад
Haha, yeah… Now that I’ve covered a lot of the basics I feel I can go more briskly and use broader strokes without getting bogged down in the details too much.
@orti1283
@orti1283 Год назад
Thank you so much for such magnificent content!
@NesHacker
@NesHacker Год назад
Haha, "magnificent" is quite the compliment. Thank you!
@Ribiveer
@Ribiveer Год назад
I haven't got a lot of experience writing assembly code from scratch, mainly having edited assembly from Super Mario Bros., so this is good exercise for me! Though that Super Mario Bros. is my only real experience with assembly might show a little... ; First, let's define RAM values. Starting at $0300 since you did in the video as well. ; Though I wonder, why not $0200? The stack ends at $01FF, and I can't find anything about $0200 - $02FF being used for anything. I do $0300 just to be safe, though. Bars = $0300 ; This is where the "list" of bars starts. Since it starts at the Health Bar, it's got the same value as it. HealthBar = $0300 WeaponBar = $0301 ; Somewhere else, we have some values for the amounts to add. These contain values of 10, 20 and 50. CapsuleValues: .db $0a, $14, $32 ; This is how this method would be called: ldy #$01 ; We load the type of bar to refill. In this case, the weapon bar. Storing it in Y will be useful for our trick coming up. ldx #$02 ; We load the amount to refill. In this case, 50. Storing it in X will be useful for our trick coming up jsr HandleCapsule ; Onto our subroutine! ; Somewhere else... HandleCapsule: lda Bars,y ; The Y register means that it gets added to the address, so we load the value at $0300 + $01 = $0301, the Weapon Bar, into the accumulator. clc ; Prepare for adding by clearing the carry. adc CapsuleValues,x ; We do the same trick here: add X to the address of our starting value. In this case, we add 2, so we get the third value from CapsuleValues: $32 cmp #$65 ; We compare the resulting value with 101 bcc ExitHandleCapsule ; If A < 101, we're good! We can exit the subroutine. lda #$64 ; Otherwise, we're gonna take the value of 100 instead ExitHandleCapsule: sta Bars,y ; Finally we store our value, be it 100 or something below it, into our designated Bar. rts ; We can go back to the previous part in the code, now!
@dedgzus6808
@dedgzus6808 Год назад
Very similar to my method expect you never push values onto the stack to be sure the registers don't get corrupted. also you used a more rigid amount method.
@ClassicTVMan1981X
@ClassicTVMan1981X Год назад
In Super Mario All-Stars (for the Super NES), the lives code for both Super Mario Bros. and Super Mario Bros.: The Lost Levels went like this: lda NumberofLives ; load the current player's lives counter inc NumberofLives ; increase the lives counter by one if Mario/Luigi collects a 1-UP Mushroom, 100 coins, knocks down eight or more enemies in a row with a Koopa shell or Buzzy Beetle, or stomps on a Koopa shell or Buzzy Beetle at least eight times on a stairstep. cmp #$80 ; compare resulting value with 128 bcc EndCheckL ; if A less than 128, we're fine and we can leave the subroutine! lda #$7f ; otherwise, set this value to 127 instead sta NumberofLives ; store whatever number we have, be it 127 or lower, into $075A, EndCheckL: rtl ; and leave! (the RTL at the end means "return from subroutine, long" which indicates we can use this subroutine in other program banks; for example, since the code above is originally in bank 4 at address 0x8596, if we want to jump to it in other program banks we use these four bytes: 22 96 85 04, the leading 22 pointing to JSL, or "jump to subroutine, long")
@Nat-qm5vb
@Nat-qm5vb 9 месяцев назад
To answer your question way after you asked it, by convention the $0200-$02FF space in RAM is used for sprite data, which gets written directly to the OAM DMA register on the PPU during VBLANK.
@Ribiveer
@Ribiveer 9 месяцев назад
@@Nat-qm5vb Ah, I see. Thank you for answering!
@trapr00t
@trapr00t Год назад
Just love explanation clarity, EXCELLENT VIDEO, can't wait for more! (I eddited and removed INCORRECT stuff about pushing ppu status to the stack, that I writen before to awoid confusion)
@michaelbarry8005
@michaelbarry8005 Год назад
In my version of reality *BRK* , *IRQ* and *NMI* push the processor status register after pushing the return address (three bytes total), but *JSR* stacks only the return address - 1 (two bytes total).
@NesHacker
@NesHacker Год назад
Yeah I am pretty sure JSR doesn't push the processor status. At least according to my 1976 MOS Microcomputers Programming Manual, it doesn't :D
@trapr00t
@trapr00t Год назад
@@NesHacker ah, I'm so sorry for the missinformation, I checked it to, and it appears that I truly confused it with NMI I feel embarrassed, for my irresponsible comment before 😳
@caldog20
@caldog20 Год назад
Video is very well put together
@NesHacker
@NesHacker Год назад
Thanks Caleb!
@brandongunnarson7483
@brandongunnarson7483 Год назад
I wish I knew the first thing about assembly but this is awesome!
@NesHacker
@NesHacker Год назад
Thanks :D, I’m glad you watched the episode anyway, haha
@NesHacker
@NesHacker Год назад
Just an FYI: the finalists for the coding challenge have been selected and the poll is up on Patreon. Voting ends Monday (Feb 6th) at 11:59 PM EST, after which I'll pin the winning post here.
@dedgzus6808
@dedgzus6808 Год назад
I'd like to nominate my code for its simplicity and because it gets the job done in only 9 lines of code.
@NesHacker
@NesHacker Год назад
@@dedgzus6808 That was the very reason I chose you as one of the finalists. But now it's in the hands of the patrons ;D
@dedgzus6808
@dedgzus6808 Год назад
@@NesHacker Haha. Thanks. Also for your information, after I finally got myself around to writing those couple of lines of 6502asm it took hold of me and I've been working on getting a "game" working. Currently messing with getting scrolling working. Thanks for the videos.
@soulite2574
@soulite2574 Год назад
My code for the refill subroutine (expanded to avoid people spoiling themselves, ca65 syntax because that's what I'm used to) ("params" is a 32 byte variable in the zeropage, +0 +1 etc, are offsets) PlayerRefill: ;PLAYER REFILL SUBROUTINE ; (params+0: type) - if refill is for health or energy ; (params+1: amount) - how much health/energy to refill LDA params+0 CMP #$01 ;Switch on type (0-Energy Refill, 1-Health Refill) BNE :+ JMP PlayerRefillHealth : PlayerRefillEnergy: ;Add refill to energy LDA params+1 CLC ADC playerEnergy ;A = playerEnergy + ammount ;IF the result exceeds max energy, set to max energy CMP #100 BCC :+ LDA #100 : STA playerEnergy JMP PlayerRefillEnd PlayerRefillHealth: ;Add refill to health LDA params+1 CLC ADC playerHealth ;A = playerHealth + ammount ;IF the result exceeds max energy, set to max energy CMP #100 BCC :+ LDA #100 : STA playerHealth PlayerRefillEnd: RTS
@keytronic5631
@keytronic5631 Год назад
Great to hear that you will do this full time. Lovely animations. How are you doing these? What software are you using? manim? Also what is your profession before you went all in on this channel? Cheers,
@NesHacker
@NesHacker Год назад
I use After Effects for the animations along with Photoshop and Illustrator to create most of the graphics. As far as what I did before the channel? It’s a shocker: I was a software engineer xD
@thedrunkmonkshow
@thedrunkmonkshow Год назад
Thanks so much and now I better understand how this works in Assembly. As someone who's only dabbled with high level languages, I never understood how to replicate variables, Sub Routines and Functions in Assembly. I only knew the JMP command and not the JSR and RTS and i also didn't understand how to pass arguments to and from. There's an online Javascript 6502 emulator so yeah..lemme try building my own like a pixel plotting routine to put this new knowledge into action. 😄
@NesHacker
@NesHacker Год назад
You’re welcome, sounds like you’re in for a world of new fun :)
@consis
@consis Год назад
beautiful vid
@NesHacker
@NesHacker Год назад
Thanks!
@jimmyraconteur2522
@jimmyraconteur2522 Год назад
Your videos are excellent!
@NesHacker
@NesHacker Год назад
Thank you, I appreciate that :D
@Chad_Thundercock
@Chad_Thundercock Год назад
4:55 What, no man - Stack Overflow is always my first go to when I need something obscure sorted out.
@NesHacker
@NesHacker Год назад
😝
@gadgetdeez7069
@gadgetdeez7069 7 месяцев назад
I know this is an old video but i really like the format. Making the viewer do a little homework for a contest is legit awesome too. Love seeing atuff like this. Only gripe is i feel the vids are a little on the short side. Right when the itch is a out satisfied you pull the plug. Darnit. Lol
@razorbackroar
@razorbackroar Год назад
Fav channel
@NesHacker
@NesHacker Год назад
Thanks choom 😉
@mykalimba
@mykalimba Год назад
If your subroutine is simple/straightforward enough, you can often pass arguments in registers!
@NesHacker
@NesHacker Год назад
True, and super useful sometimes!
@kyoobqa
@kyoobqa Год назад
For such quality, you are criminally underrated.
@NesHacker
@NesHacker Год назад
I guess that’s a lot better than being overrated xD
@menitoon
@menitoon 3 месяца назад
When will the next episode be released ? I want to actually make a NES game ! But I really love your videos, they're so helpful !
@oleschoolgamers
@oleschoolgamers Год назад
Crazy editing skills, I think you're videos are as good as your NES explanations haha. What do you use for video editing anyway?
@NesHacker
@NesHacker Год назад
Thanks! I use Final Cut Pro to edit. After Effects, Illustrator, & Photoshop for graphics.
@vakulasan4613
@vakulasan4613 Год назад
Amazing illustrations, great video editing and main - you can see it on "one breath" because every detail is explained. Keep doing so. Good luck. From me like 👍 and subscription🔔)
@NesHacker
@NesHacker Год назад
The plan is to keep going as long as I can ☺️
@spearPYN
@spearPYN Год назад
I am Atari 8-bit programmer but the 6502 assembly explanations are top notch.
@NesHacker
@NesHacker Год назад
Atari, C64, and NES programmers are all like cousins. Our choice in console is different, but we all love hacking some 6502 😆
@mykalimba
@mykalimba Год назад
For me, and possibly many other "old school" coders who got started on 8-bit home computers, calling too many subroutines in assembly language will always be the first thing that comes to mind when I hear the term "stack overflow". These days, most coders know "stack overflow" only to mean that website you go to when you don't know how to solve a coding problem and you need someone else to do it for you. :D
@NesHacker
@NesHacker Год назад
Mhm, I figured some of the newer folks wouldn’t know the term’s origin. So it was a fun thing to throw in there :)
@BainesMkII
@BainesMkII Год назад
While I understand wanting to stick to a single concept, it feels like you should have mentioned manually saving and restoring register values with the stack (when necessary) when entering and exiting subroutines.
@NesHacker
@NesHacker Год назад
Yeah for sure, it’s always a challenge to figure out what to include and what not to. That’s a super valid and common use for the stack so I should have probably included it!
@marcus9374
@marcus9374 Год назад
Your videos are great!! Confrats for your work! One question I always have is how do things like events are coded using assembly. Examples like “when character touches an enemy, X happens”. The other one would be around types and hierarchy. Are analogies around objetc oriented programming observed somehow in these games code? If not, what are the constructs developers use to represente those concepts? Those would be great topics for a future video!
@NesHacker
@NesHacker Год назад
It's all done as part of the game loop. An event messaging system would be way to heavyweight to implement with such limited system resources. So you would simply do the checks for everything that "can" happen as part of the main game loop logic. Old-school game programming is quite a bit different than modern game engines.
@jumanji4037
@jumanji4037 Год назад
Really nice video and well explained! I’ve been looking for some courses and tutorials for making NES games and your videos have really helped explain the basics. Which resources or websites would you recommend for learning more? Thanks and looking forward to your future videos!
@NesHacker
@NesHacker Год назад
www.nesdev.org/wiki/Nesdev_Wiki - This has a ton of information on programming the NES, but it can be a little hard to get through at times. I don't have any books in particular to share, sorry.
@jumanji4037
@jumanji4037 Год назад
Thanks! I’ll have a look to it.
@alexeisenhart
@alexeisenhart Год назад
This is a great video! What software do you use for your code animations?
@NesHacker
@NesHacker Год назад
I mostly use After Effects.
@exxor9108
@exxor9108 Год назад
The way that you speak and explain how subroutines work, I'd love to hear you explain the note block crash glitch in Super Mario Bros. 3. The one that speedrunners use to jump from world 7-1 to the chamber Princess Toadstool is held in. I say Toadstool because she wasn't named Peach in the US until after Super Mario 64.
@NesHacker
@NesHacker Год назад
Oh interesting, yeah that's a pretty good idea. I'd have to do the research first, of course (and be able to pull it off myself so I can get a feel for it xD).
@soulite2574
@soulite2574 Год назад
When I'm in an underrated channel challenge and my opponent is NesHacker (insert Squidward glass braking gif)
@NesHacker
@NesHacker Год назад
Not gonna lie, it’s unreasonable how happy your comment made me xD
@ric8248
@ric8248 Год назад
This tutorials are absolutely awesome, made me instantly like and subscribe. Thank you very much for uploading. And ughh I hate to say this, but for some reason it bothers me to no end how the elements on the screen feel the need to jump whenever they are mentioned! It makes waaay more harm than good. So there you go, sorry for this unsolicited feedback, but it's been killing me lol.
@NesHacker
@NesHacker Год назад
So I spend a *lot* of time working on the animations for these videos, usually it is the majority of the work. In some sections I don't want to make things too complicated so the viewer can focus on what I'm saying while using the visual reference to help guide their understanding. That said, leaving still graphics up for too long can make things kinda boring, so I use the jump and camera zooms to keep a sense of motion while focusing on a single shot. If I find a better way to do this in the future, I'll certainly use the bounce less and and less :D
@ric8248
@ric8248 Год назад
@@NesHacker maybe it's my fault for binge watching all the videos since l discovered your channel yesterday
@NesHacker
@NesHacker Год назад
@@ric8248 Haha I find ZERO fault with you binge watching all of my videos 🤣
@luxuryhomes8889
@luxuryhomes8889 Год назад
so if the control flow has a routine and savor tine executing the task for the 16-bit on the stack??? i think im getting it
@NullUndefined1337
@NullUndefined1337 Год назад
😉 thanks XD nice video perfekt sound ^^
@NesHacker
@NesHacker Год назад
Yeah I was pretty happy with the sound design on this one. Glad you liked it! :D
@thanhvinhle2893
@thanhvinhle2893 Год назад
struct capsule{ uint8_t type:1; uint8_t amount:7; } And then a function with parameter is that struct... Oops, sorry wrong language 😅
@ChrisBouchard
@ChrisBouchard Год назад
I know in some architectures it's common to pass parameters and return values on the stack. E.g., push on the arguments before the JSR, and then write in the return value before the RTS. This has the benefit that subroutines are reentrant, but does eat up more stack space. Is this style used at all in NES programming?
@dedgzus6808
@dedgzus6808 Год назад
When JSR is called it pushes the address for the RTS onto the stack so you would have to pull that address off of the stack, store it, pull your parameters, store them, run your subroutine, push the return onto the stack and then load your return address, push it onto the stack and then call RTS. I don't know why anyone would do it that way but I am no expert.
@ChrisBouchard
@ChrisBouchard Год назад
@@dedgzus6808 In that calling convention, you would push your arguments before the JSR, and then read them by offset relative to the stack pointer inside the subroutine. (Though as I write this I'm not actually sure if the 6502 has stack-relative addressing. Without that, this would be painful, as you say.)
@ChrisBouchard
@ChrisBouchard Год назад
Reading more, I see that 6502 doesn't have native stack-relative addressing - so yeah, maybe this calling convention wouldn't be very popular for NES programing. I guess in theory you could move the stack pointer into the X register and use it to do indirect addressing. So you could do something like TSX ; Copy stack pointer into X. (I'm assuming that it points to the top of the stack -- if it points to the next free location, we need an extra INX.) INX ; Point one byte below stack pointer, first argument LDA $100,X ; Load argument INX ; Move pointer to next argument CLC ADC $100,X ; Add it to the second argument I suppose it would be easier to achieve reentrancy by passing arguments by known address and having the convention that the caller must preserve and restore those memory locations.
@grendell
@grendell Год назад
Any guidance for when to use a subroutine/.proc and when to use a macro? Am I correct in guessing that macros function similarly to C, with simple text replacement?
@NesHacker
@NesHacker Год назад
Macros can get really *really* tricky if you use them too much… I plan on doing an episode about my take on them, but here’s the TL;DR: if it’s something where you’d have to write out all the code anyway (e.g. setting parameters for a routine, etc.) then use a macro. If you absolutely have to save the cycles it would cost to perform the JSR and RTS *and* you can significantly improve the readability of your code then use a macro. Otherwise, stick with subroutines.
@MattHughson
@MattHughson Год назад
You mentioned coding your own games in this video a few times. Are there any NES homebrew you've worked on? Or do you do hacks?
@NesHacker
@NesHacker Год назад
I’ve done some really small game projects in the past and have been chipping away at a bigger project for a while now, though progress is slow since I started the channel 😂
@MattHughson
@MattHughson Год назад
@@NesHacker Awesome! I can't wait. Do you post dev updates on the project anywhere that I could follow (twitter, etc)?
@cron93
@cron93 Год назад
I do web programming, but if I wanted to get into this, is there a way to get the old source code for NES games and run them on a local computer?
@nasrimarc7050
@nasrimarc7050 Год назад
You can imagine that, this game was coded in assembler language by the 90's dev team
@NesHacker
@NesHacker Год назад
Mind-blowing, right?
@mikethered123
@mikethered123 Год назад
Any tips for knowing “where” you are without knowing the memlocs/memory map? How does it know when to “interrupt” “normal” routines and do graphics? What about slow down?
@NesHacker
@NesHacker Год назад
Kinda, so the return values for each routine call will be pushed to the stack and the vectors that define the entry points for interrupt handlers are always located in the same spot of the ROM ($FFFA-$FFFF). It’s a little complicated but if you pause a program at any point you can work out if you’re in the “main” thread or an interrupt handler by working backwards through the call stack until you get either to the main loop or a handler. Though it’s possible to write code that obfuscates this by jumping into an interrupt handler and jumping out before the RTI.
@michaelbarry8005
@michaelbarry8005 Год назад
Nicely done. At 3:30 you show the low byte of the return address being pushed first, which is incorrect, but only significant if you are doing low-level stack manipulation or manually constructing and pushing your own "return addresses" like Woz did in Sweet-16 and the Apple ][ monitor ROM.
@NesHacker
@NesHacker Год назад
Oops, yeah it's high-byte then low-byte of return address, right?
@meepk633
@meepk633 Год назад
Great animations. What do you use?
@NesHacker
@NesHacker Год назад
I use After Effects mostly
@vuurniacsquarewave5091
@vuurniacsquarewave5091 Год назад
I think some context is needed to understand how I'd do this. I have a fixed size array of existing objects on the screen. Let's say the game can handle up to 16 of such. So the 16 bytes represent the object ID of the active object. A value of $FF represents that there is nothing in that slot and the game is free to use it for spawning a new object. This could be a bullet, a pickup, or the stage might want to spawn something, whatever the case may be. Every frame there is a subroutine called "ObjectHandler" that looks through the 16 ID slots and if the value is $FF it skips to the next one, otherwise it will load a 16-bit pointer with the object ID as the index into the pointer tables (one for the high byte, and one for the low byte) and then jump to that pointer. So now each object can have its behavior defined, but of course I could have the same pointer included in the tables more than once for common stuff. Let's say we're in the "obj_Capsule" routine from either of the four capsule items' object IDs. Now as you'll see this code makes a few assumptions and restricts you to the following rules to work properly: - The capsule object IDs MUST be arranged in order and their lowest two bits must be 00, 01, 10, 11 in that order. - The player's hp and weapon energy must be in two neighboring RAM addresses because we will add the capsules' refill amount to them in an indexed way. Starting state of the CPU registers: A - undefined, still holds part of the address we loaded X - Object ID we currently looked up and jumped to Y - undefined obj_Capsule: txa and #%00000011 ; use the low two bits of the object ID as a new index to grab the refill amount tay and #%00000001 ; create an index to decide if it's hp or weapon energy tax lda obj_Player_hp,x clc adc arr_obj_Capsule_refill,y ldx @zplocal_currentobjslot ; this is a temporary ZP variable the ObjectHandler uses to know which of the 16 slots it's processing right now, gets incremented after every slot lda #$FF sta obj_slot,x ; the object 'removes itself from the list of existing objects' ; here you could call an init subroutine to start a sound effect of the capsule being picked up rts ; goes to the common end point where processing one obj_slot ends arr_obj_Capsule_refill: .db $02,$04,$02,$04 ; we could have all four capsules have any arbitrary amount that they refill.
@johnmills3864
@johnmills3864 Год назад
Whooo !
@scottwilliams895
@scottwilliams895 Год назад
Your content & production quality far exceeds your current # of Subscribers. 2023-01-29: 20.8K I expect that number will grow very quickly.
@NesHacker
@NesHacker Год назад
I think you might be right... 2023-01-31: 21.2K
@ssygon2
@ssygon2 Год назад
4:38 JSR many times without returning = stack buffer overflow 😂
@NesHacker
@NesHacker Год назад
Just write a recursive routine without a base case 😛
@Oxxyjoe
@Oxxyjoe Месяц назад
I request a part two, where you walk me through one or two of the subroutines that got submitted in response to this challenge. In particular, also, how Did megaman really handle the refill capsule spawning?
@Archeious
@Archeious Год назад
When passing the parameters why does you just push the parameters onto the stack? That is what we would do on old school x86 processors (and I think happens on current processors). I am not familiar is 6502.
@NesHacker
@NesHacker Год назад
Well you could, but there’s the issue that they’d be pushed prior to the JSR, so you’d have to do some bespoke stack handling to manage them along with the return address. The approach works fine, but it’s a lot easier to handle parameters in the zero page, especially if you don’t need a generalized and flexible approach (which is usually the case when writing 6502 assembly by hand).
@BillAnt
@BillAnt 11 месяцев назад
So what happens if a subroutine pushes more data onto the stack without popping it off before reaching the RTS? Would that mess up the RTS address? Gotta love a StackOverflow.... the programmer's website that is. ;)
@kayakexcursions5570
@kayakexcursions5570 Год назад
;6502 asm: ;refill(x=type, c=amount) ;health type x=0 ;weapon type x=1 ;c = large amount (64) ;nc = small amount (32) healthVal = $00 ;players health value weaponVal = $01 ;players weapon value Refill: lda #32 ;set a as small amount bcc Small ;branch if small required lda #64 ;set a as large amount Small: clc ;clear carry for addition adc healthVal,x ;add a and value sta healthVal,x ;store new value cmp #101 ;check for overflow bcs Max ;branch if over 100 rts ;return Max: lda #100 ;set a as max value sta healthVal,x ;store max value rts ;return ;z80 asm: ;refill(z flag = type, c flag = amount) ;z = weapon type ;nz = health type ;c = large (64) ;nc = small (32) healthVal = $0000 weaponVal = $0001 Refill: ld a,32 ;set a as small amount jp nc,Small ;skip multiply if small selected rla ;set a as large amount Small: ld hl,healthVal ;point to health value jp nz,Health ;skip increment if health selected inc hl ;point to weapon value Health: add a,(hl) ;add amount to value cp 101 ;check for overflow ld (hl),a ;store new amount ret nc ;return if no overflow ld (hl),100 ;set value to max ret ;return with max value
@kayakexcursions5570
@kayakexcursions5570 Год назад
I know I said I was going to make an NES game in a previous comment, but unfortunately I haven't had time. That's going to be my new years resolution I guess, to make an NES game! Currently I only know z80 so I started off with that. I left the z80 in the comment and tried to convert it to 6502 as close as possible. Its my first time using 6502 and I realized using only flags as an input wasn't going to work. Lda modifies the z flag and rol a modifies both the z and c flag. I swapped rol a for lda so I could at least save the carry flag. z80 and 6502 are very similar, just have to forget about the extra registers.
@NesHacker
@NesHacker Год назад
Hey it’s no rush, just start small and chip away at it… But most of all, have fun learning and playing around. Hopefully my videos will help along the way, and know that I’m rooting for ya! :)
@soulite2574
@soulite2574 Год назад
dude really went above and beyond with the Z80 code, respect
@tr1p1ea
@tr1p1ea Год назад
Z80, nice 😀
@kayakexcursions5570
@kayakexcursions5570 Год назад
@@tr1p1ea Haha, I know you trip, Im the assembly bandit.
@yod1213
@yod1213 Год назад
@NesHacker Can you do some SNES videos? Im especially interested in the SNES's sprite handling capabilities, because I always though that it was rather weak showing considering its specs.
@NesHacker
@NesHacker Год назад
I’m hoping to dip into some 16-bit content in the future, I’ll keep you and your wanting to see how sprites work in mind when I do
@oc-steve
@oc-steve 13 дней назад
Does the 6502 not use the stack for parameters and return values?
@ClergetMusic
@ClergetMusic Год назад
What is the synth piece playing ca. 5:45?
@NesHacker
@NesHacker Год назад
I think that’s “After Midnight” by Luke Melville. Just so you know, I usually put new songs I use in videos in the description for the video, ordered by when they’re played in the video :)
@majinnaibu
@majinnaibu Год назад
Why don't you use the stack for parameters/return values/local vars? Is there some larger problem with recursion on the NES that makes it not matter? Or maybe a lack of a good way to address the memory relative to the stack pointer? Cool tutorials by the way. I haven't touched asm in like 20 years.
@NesHacker
@NesHacker Год назад
You can use the stack to hold params, but it's kinda annoying since the jsr instruction pushes the return to the stack. So best case scenario you'd be pulling the stack pointer into the X register and doing some weird offset loads and then finally having to pop them off at the end. Not too bad, but if you're doing something where cycles count (like rendering during a PPU vblank) then it might bite you.
@Diablokiller999
@Diablokiller999 Год назад
Maybe you should've said something about saving registers before entering a subroutine? Otherwise the subroutine could overwrite stuff you are currently calculating/using :D Also you can use the stack to transfer parameters or return values fast, since it uses only one clock cycle on most architectures.
@Kaijuking84
@Kaijuking84 Год назад
First of all what an Awesome channel. And secondly, I'm just gonna throw this out here I'm in school for computer programming and working full time with a family to support. Does anyone know of any resources I could use to help with my studies, I'm not a slow learner, but working full time trying to support my family kinda puts my brain on the fryer, some I'm looking for any resources I can find audiobooks, anything, something I can multi-task with while I'm working.
@LBXZero
@LBXZero Год назад
From memory of my assembly language class, shouldn't there be other stack related instructions to store register values to the stack? One of the issues of jumping around to functions and subroutines is your subroutine interruption may involve using a register that already holds data that needs to be restored when jumping back to the parent loop. Of course, we can say that not saving important register outputs to memory in a timely manner is a bad thing as well as your parameter could be a value stored in a register for immediate access. But I will say when you jump around to subroutines, knowing the instructions to push register values on the stack and popping back into place is important.
@NesHacker
@NesHacker Год назад
It’s a good point, I considered going in-depth on the stack related registers but I felt it would drag the video a little off topic. That said, no reason I couldn’t do a follow up to give the stack a little more love :)
@LBXZero
@LBXZero Год назад
@@NesHacker I figure you will have a whole video in regards to the stack and all that fun.
@kez963
@kez963 Год назад
Can I program nes using apple iic? 😅
@saltymashedpotatoes
@saltymashedpotatoes Год назад
Piece of cake.
@NesHacker
@NesHacker Год назад
I love cake :)
@o1phoenix79
@o1phoenix79 Год назад
The cake is a lie 😜😆
@Cyberfoxxy
@Cyberfoxxy Год назад
So you'd need to write a parameter stack too to use nested subroutines.
@NesHacker
@NesHacker Год назад
If you wanted a generalized approach, like an ABI for use by a compiler, you’d basically have to do that. A simple solution would be to have stack frames based on lexical levels to keep track of all the variables in a systematic way based on call. In practice when writing programs at the assembly level you don’t often need to go that deep. For instance, you can store variables elsewhere temporarily when you need to free up the parameter space.
@RetroCheats
@RetroCheats Год назад
I usually write game genie codes.
@NesHacker
@NesHacker Год назад
That makes sense, you know… considering 😂
@lapalourde75
@lapalourde75 Год назад
👍 You use nesasm3 like compiler? Thanks
@RandyFortier
@RandyFortier Год назад
He posted a video which walks you through the environment setup. I recommend checking that out.
@NesHacker
@NesHacker Год назад
I use ca65 which is part of the cc65 suite. Like Randy said, check out my “NES Development Environment” video and I show the tools I use (for the most part, I mostly use Mesen now over FCEUX).
@lapalourde75
@lapalourde75 Год назад
@@NesHacker 👍😃
@leandrormor
@leandrormor Год назад
I'm trying to paste either my code or my link but they are not showing up =|
@NesHacker
@NesHacker Год назад
Hmm… not sure what could be happening. Others have been able to post their code 🤔
@leandrormor
@leandrormor Год назад
@@NesHacker I got it, yt was filtering out if my code contains a link to .asm file
@akko8210
@akko8210 Год назад
Hey! I got a Quick question in 1:19 in one of the lines of the code shows this: bpl :+ .What is this about?
@grendell
@grendell Год назад
bpl is "branch on plus" or "branch on positive", and ":+" refers to the next label in the code, so that bpl :+ looks at the result of the sbc, cmp's it to the value at $301, and skips the lda #0 if it is greater, presumably to avoid health going negative/underflowing. Hope that helps!
@akko8210
@akko8210 Год назад
@@grendell Thx man
@NesHacker
@NesHacker Год назад
You’re great @grendell, I’ve been shooting video all day and was finally taking a moment to come answer this and boom! You had me covered :)
@DarkKodKod
@DarkKodKod Год назад
Just to add to this answer. :+ refers to the next label. :++ is for the second next label, :- is to go back to the previous label. Usually you use unnamed labels to avoid collisions for some trivial code flow. Like a loop or just whatever you want that you think you don't need to name the label for whatever reason.
@renecura
@renecura Год назад
I understand that you put the parameters in ram for clarity, so this comment is just to add a bit of info. In general, the parameters goes to the stack to be in some way just for the subroutine. And more, you can make recursive subroutines.
@NesHacker
@NesHacker Год назад
No, I put them in the RAM because this is how it is usually done when writing 6502 by hand. If you're working on compiler for a higher level language, this would probably be the way to handle them, but when programming in assembly this would rarely, if ever, be done.
@renecura
@renecura Год назад
@@NesHacker indeed, that is what a compiler does in general. I wonder why is this strategy not preferred when writing asm by hand.
@NesHacker
@NesHacker Год назад
@@renecura Mostly because of cycle overhead. Using stack manipulation instructions to manage the parameters on the stack adds a lot of cycles. The 2A03 (modified 6502) on the NES clocks in at 1.79 MHz on NTSC, which is really slow. Considering some operations, like VRAM updates, need to be done in roughly 2500 cycles and every little bit of optimization counts. Further, I think doing it that way causes your code to become *less* readable. Since you don't often need recursion, and most subroutines are *not* general purpose. It's best to simply map out the parameters to RAM for the application in most cases, as opposed to using a general purpose approach.
@renecura
@renecura Год назад
@@NesHacker great! Ty for the explaination!
@2lt.hyakutaro382
@2lt.hyakutaro382 Год назад
My solution (although late for the challenge) I use the following memory locations: ; $00: character's health ; $01: character's energy ; $02: type param (=0 for health, =1 for weapon) ; $03: big/small param (=0 for small capsule, =1 for big capsule) capsule_values: .byte 20, 50, 30, 60 ; small health, big health, small energy, big energy refill: lda $02 asl adc $03 tax ldy $02 lda $00, y adc capsule_values, x cmp #100 bcc :+ ; if health(or energy) >= 100 lda #100 : sta $00, y rts
@darkseid2584
@darkseid2584 Год назад
I almost clicked on the back btn after hearing this 00:27
@Lilithe
@Lilithe Год назад
Solution: - 0 page has a table of value, 1-byte address (within 0 page) - routine takes a single byte, split into bits, each bit representing one of 8 stats to effect - routine starts by multiplying the active bit in the input byte by 2 byte address spaces within the table (each table entry has 2 bytes, a value and an address) - routine loads the target byte within the 0 page, based on the target address from the table, with the value from the table - return Does that work?
@JarppaGuru
@JarppaGuru 5 месяцев назад
6:58 i have know idea. im here learn LOL load value jump routine that do something with it- mean load 2 value(parameter) do something in subroutine based on parameter. thats that? i passed without coding
@technomicah
@technomicah Год назад
;I'm new at 6502 assembly, but I think I know a simple method for health/weapon refill subroutine currentHealth = $0300 ;current health value currentWeapon = $0301 ;current health value refillType = $0444 ;Refill type parameter. 0 is health and 1 is weapon refill refillAmount = $0445 ;Refill type parameter, small is 16 and large is 32 capsule: ldx refillType ;load refill type to X, making it the health/weapon modifyer lda currentHealth,x ;load current health/weapon to A clc adc refillAmount ;add refill amount to current health/weapon value cmp #$64 ;new value vs max value, max is 100 or 0x64 bcc :+ ;more than max? From the NES loops video lda #$64 ;we've exceeded max, load max value of 100 instead :sta currentHealth,x ;store new health/weapon level to RAM rts ;I've edited it a couple times as my understanding for 6502 gets clearer Prior to watching your videos I really had no idea on how 6502 assembly code worked. I've learned alot from watching your videos. This last video really challenged me to actually apply what I've learned. I'm amazed that I was able to come up with a solution that seems to make sense to me... Hope it makes sense. Thank you for your amazing videos!!! They've really satisfied a 30+ year desire to know how those old games worked. Looking forward to more. I'd like to some day edit the famicom game Convoy No Nazo to actually be playable
@technomicah
@technomicah Год назад
;After thinking about this for a couple of days, I think this routine should handle all the power-up items. ;I'd like to clean this up while its on my mind ;I'll store the current power-up item info in one masked byte @$0444 ;Edit, I forgot the Etanks currentHealth = $0300 ;current health level currentWeapon = $0301 ;current weapon level currentLives = $0302 ;current number of lives left currentEtanks = $0303 ;current number of etanks left collectedLetters = $0304 ;One byte that has the high 4 bits for the Beat letters collected and we can use the remaining 4 bits for something like the power balancer from MM6 powerUp = $0444 ;power-up ;Weapon/health-up when bit1 is set, bit0=weapon/health modifier (0 is health and 1 is weapon) and bit4/5 determine if its +16 or +32 weapon/health-up ;1-Up/Etank when bit2 is set, bit0 1=Etank, 0=1-Up, the other 6 bits arnt used in this case ;Beat letter (or power balancer) when bit3 is set, bit7=B, bit6=E, bit5=A, bit4=T, bit0=Power Balancer power-up: lda powerUp ; load powerUp byte to A and #$02 ; begin checking if its a health/weapon-up by looking at bit1 beq :Other Item ; if A is 0, branch to then check what kind of item it is lda powerUp ; load powerUp byte to A again and #$01 ; determine if its a health/weapon-up by looking at bit0 tax ; store result of A in X as our health/weapon modifier lda powerUp ; load powerUp byte to A for a 3rd time and #$30 ; so we get only the increase value of +16 or +32 clc adc currentHealth,x ; refill current health/weapon, offset by X cmp #$64 ; is the new value more than 100? bcc:+ ; branch over the next line if the carry is clear, meaning that adding the refill didnt exceed 100 lda #$64 ; load 100 (max refill) to A, we wont run this line unless we've met or exceeded max refill of 100 :sta currentHealth,x ; store new health/weapon amount after adding refill jmp End Sub-routine: ; jump to the end of the sub-routine Other Item: lda powerUp ; load powerUp byte to A, again and #$08 ; begin checking if its a BEAT letter or Power Balancer by looking at bit3 beq :Add 1-Up ; if A is 0, then item must be a 1-Up/Etank by process of elimination, jump to that code to finish it up lda powerUp ; load powerUp byte to A for the third time (didn't I say that already?) eor #$08 ; Exclusive Or out the bit that identifies it being a Beat/power balance item clc adc collectedLetters ; the location in RAM would have the same bit mask BEAT---(PowerBalancer), so I think adding it is okay, non? jmp End Sub-routine: ; jump to the end of the sub-routine Add 1-Up: lda powerUp ; load powerUp byte to A, again and #$01 ; check if its a 1-up/Etank by looking at bit0 tax ; store result of A in X as our 1-Up/Etank modifier inc currentLives, X ;increment lives or Etanks if X is 1 End Sub-routine: rts ; return from sub-routine ; I think that should do it. This time took me less time than the first
@boody8844
@boody8844 13 дней назад
Here's mine: ; Initialize player's health and ammo into RAM lda #100 sta $0300 ldx #150 stx $0301 ; Enemy's health and damage lda #50 sta $0310 ldx #80 stx $0311 ; Player gets attacked Damaged: ; Loading player's health into reg a lda $0300 ; Taking damage sec sbc $0311 sta $0300 ; Player attacks back Attack: lda $0301 sec sbc #10 sta $0301 ; Enemy taking damage lda $0310 sec sbc #20 sta $0310 ; Player finds refill lda #3 sta $10 RefillUsed: lda $10 cmp #1 BEQ RefillHealthBig cmp #2 BEQ RefillAmmoBig cmp #3 BEQ RefillHealthSmall cmp #4 BEQ RefillAmmoSmall rts RefillHealthBig: lda #100 sta $0300 rts RefillAmmoBig: lda #150 sta $0301 rts RefillHealthSmall: clc lda $0300 cmp #50 bcs RefillHealthBig adc #50 sta $0300 rts RefillAmmoSmall: clc lda $0301 cmp #100 bcs RefillAmmoBig adc #100 sta $0301 rts
@DobinSergei
@DobinSergei 11 месяцев назад
You didn't cover here saving and restoring registers values before and after subroutines. Without that, people get stuck in simplest task. For ex. if you use registers X or Y as a counter in loop, then JSR, where you definitely will change them, it will break everything.
@xs6819
@xs6819 Год назад
You still write code for that old stuff!!!!!
@NesHacker
@NesHacker Год назад
Yeah it’s fun, there’s a whole hobby community of folks that do 😁
@zzeck431
@zzeck431 Год назад
I used skilldrick's easy 6502 define SMALL 2 define LARGE 10 define HEALTH 0 define ENERGY 1 define HEALTH_ADDR 2 define ENERGY_ADDR 3 LDA #HEALTH_ADDR STA 0 LDA #0 STA 1 LDA #100 STA HEALTH_ADDR LDA #1 STA ENERGY_ADDR LDA #LARGE LDY #ENERGY JSR meters ;for checking result in debugger registry dump LDA ENERGY_ADDR BRK ;A passes container size, SMALL or LARGE ;Y passes container type, HEALTH or ENERGY meters: CLC ADC (0), Y CMP #100 BCC less_max LDA #100 less_max: STA (0), Y RTS
@dedgzus6808
@dedgzus6808 Год назад
I've never written any 6502 asm before but here ya go. Sorry if there are syntax errors and I tried to comment so you'd understand the addresses apply_item: ldx $01 ; $0001 is 0 for health, 1 for weapon lda $0300,x ; $0300 is address for health, $0301 for weapon clc adc $02 ; $0002 is amount cmp #100 ; check if it's over 100 bcc :+ lda #100 ; if so set to 100 : sta $0300,x ; store the result rts edit: removed pushing and pulling from stack as it is not assumed that it is done
@dedgzus6808
@dedgzus6808 Год назад
Any and all feedback would be welcome.
@SuperNickid
@SuperNickid 5 месяцев назад
@NESHacker: Could you explain the reason why sometimes because of a glitch in the game, the game can execute the X-cordonate of sprite as program code. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-l-oUiG3yJE8.html The stack did over flow into my capture card that is what cause the excessive corrupt graphic, the excessive corrupt graphic where not part of the game. My capture card is fine, it did not break it, and my capture card is still working properly. The JSR instruction place with the shell is JSR $8F$E3 Since the X of sprite start on $0090 that is mario X postion, $0091 X postion of the last enemies that spond if the other 4 are full. So the $0093 sprite cordinate de-spond at X coordinated $20, the $0094 at X coordinated $E3 and then $0095 at X coordinated $8F.
@sunxnes
@sunxnes Год назад
print "Hello World!"
@NesHacker
@NesHacker Год назад
I’m afraid that’s gonna cause a buffer overflow, you forgot the null character at the end! ;D
@Waferdicing
@Waferdicing Год назад
💚🖤🖤🤎❤️💙💙💜😆
@NesHacker
@NesHacker Год назад
🥺
@ashlandwithouttheshd
@ashlandwithouttheshd Год назад
Stacks are FIFO not FILO
@NesHacker
@NesHacker Год назад
Queues are FIFO (First-In First Out). Stacks are very much FILO or LIFO (First-In Last-Out, or Last-In First-Out).
@ashlandwithouttheshd
@ashlandwithouttheshd Год назад
@@NesHacker you’re right. Looking at this again idk what I was thinking when I posted that
@hugeuglygorillaz9599
@hugeuglygorillaz9599 Год назад
Well, dammit... I get why the website is called "Stack Overflow" now. Nerds are weird. Lol
@joevaghn457
@joevaghn457 Год назад
Why the f*ck do you sound so much like swankybox XDDDD
@NesHacker
@NesHacker Год назад
I don't know who that is 🤔
@kentwidman
@kentwidman Год назад
It was fun messing around with how to structure the refill code and subroutines. This is what I came up with using your starting template: .export Main .segment "CODE" .proc Main ; Current healthbar value ldx #10 stx $0300 ; Current weaponbar value ldx #50 stx $0301 ; Call health/weapon refill subroutines. jsr small_health_refill ; after routine: healthbar = 18, weaponbar = 50 jsr large_health_refill ; after routine: healthbar = 48, weaponbar = 50 jsr large_health_refill ; after routine: healthbar = 78, weaponbar = 50 jsr small_health_refill ; after routine: healthbar = 86, weaponbar = 50 jsr small_weapon_refill ; after routine: healthbar = 86, weaponbar = 58 jsr large_weapon_refill ; after routine: healthbar = 86, weaponbar = 88 jsr large_health_refill ; after routine: healthbar = 100, weaponbar = 88 jsr large_health_refill ; after routine: healthbar = 100, weaponbar = 88 jsr small_health_refill ; after routine: healthbar = 100, weaponbar = 88 jsr small_weapon_refill ; after routine: healthbar = 100, weaponbar = 96 jsr large_weapon_refill ; after routine: healthbar = 100, weaponbar = 100 rts ; End of Main small_health_refill: ; load parameters for refill subroutine ldx #0 ; type = health stx $00 ldx #8 ; amount = 8 stx $01 jsr refill rts ; End of small_health_refill large_health_refill: ; load parameters for refill subroutine ldx #0 ; type = health stx $00 ldx #30 ; amount = 30 stx $01 jsr refill rts ; End of large_health_refill small_weapon_refill: ; load parameters for refill subroutine ldx #1 ; type = weapon stx $00 ldx #8 ; amount = 8 stx $01 jsr refill rts ; End of small_weapon_refill large_weapon_refill: ; load parameters for refill subroutine ldx #1 ; type = weapon stx $00 ldx #30 ; amount = 30 stx $01 jsr refill rts ; End of large_weapon_refill ; refills heathbar or weaponbar located at $0300 or $0301 ; params (type $00, amount $01) ; type == 0, setting heathbar ; type == 1, setting weaponbar refill: ldx $00 ; x is use as an offset for heathbar or weaponbar. lda $0300, X ; load heathbar or weaponbar clc adc $01 ; Add refill amount cmp #100 ; make sure new health/weapon value is not over 100 bcc skip_refill_limit lda #100 ; set health/weapon value to 100 skip_refill_limit: sta $0300, X ; set final amount for health or weapon bar. rts ; End of refill .endproc
@strayling1
@strayling1 Год назад
Looks good to me. This should be pinned.
@Octal_Covers
@Octal_Covers Год назад
; Here's the code I came up with ; Note: I'm a bit rusty with 6502 assembly, as the last time I did it was in 2019 ; How did I do? ; A: xxxxxxyy ; most sig y: type (0 -> health, 1 -> power) ; least sig y: value (0 -> small [5], 1 -> big [10]) refill: ; Push A to stack to store value pha ; Check size bit and $01 cmp $01 bne reAmEl ; Big ldx #0A jmp reAmEn ; Refill Amount Else reAmEl: ; Small ldx #05 ; Refill Amount End reAmEn: ; Pull A from stack to get value pla ; Check type bit and $02 cmp $02 bne reTyEl ; Energy stx $01 jmp ReTyEn ; Refill Type Else reTyEl: ; Health stx $00 ; Refill Type End reTyEn: rts
Далее
NES Architecture Explained
18:28
Просмотров 279 тыс.
NES Development Environment
14:58
Просмотров 348 тыс.
Разбудили Любимой Песней 😂
00:14
НОВАЯ ПАСХАЛКА В ЯНДЕКСЕ
00:20
Просмотров 1,3 млн
Coding NES Loops
17:10
Просмотров 28 тыс.
Game Boy Graphics & How To Code Them
9:02
Просмотров 93 тыс.
x86 Assembly Crash Course
10:45
Просмотров 826 тыс.
Rearchitecting the 6502
16:17
Просмотров 13 тыс.
The Truth about the Fast Inverse Square Root on the N64
10:01
NES Controllers Explained
16:52
Просмотров 84 тыс.
Computing Pi on the NES
9:43
Просмотров 210 тыс.
Basics - 6502 Assembly Crash Course 01
12:49
Просмотров 112 тыс.