Hello people! I just finished studying the first part of the Nerdy Nights tutorials.
I had a lot of questions, but most of them are now solved thanks to your support
Before proceeding, I wrote my "hello, world" ROM where I implemented most of the ideas that I learnt.
Sadly, when I load it on my real hardware (AVS retroUSB + EZ Everdrive N8 Pro), I just get a blank screen.
Does anybody know, what the cause might be?
In case, my code is attached. Thanks in advance for your help!
Ps: the code shows a "Title Screen". After pressing Start, you move Mario and get a Game Over when hitting Goomba.
Everything very rudimentary, just for the sake of practicing.
Loading my "hello, world" on real hardware (AVS)
Moderator: Moderators
Loading my "hello, world" on real hardware (AVS)
- Attachments
-
- mario2.chr
- (8 KiB) Downloaded 81 times
-
- draft.nes
- (24.02 KiB) Downloaded 85 times
-
- draft.asm
- (8.93 KiB) Downloaded 82 times
Re: Loading my "hello, world" on real hardware (AVS)
One thing that you seem to be getting wrong in your programs is that you're only waiting for one vblank before using the PPU, while the recommendation is to wait for two. Also, it's good practice to do a preliminary $2002 read before the actual wait loop, to prevent the case where no waiting takes place due to the code being called at a time when the vblank flag is already on:
I don't know if this is the problem preventing your program from working correctly (probably not, specially if you're loading this from a flashcart, but you should definitely fix this.
In which emulators have you tested this? If you can find an emulator which gives the same result as on hardware that has at least some debugging features, you can try tracing through the code to see if all the code is executing as expected.
Code: Select all
WaitForPPU:
bit $2002 ;makes sure the vblank flag is off
Wait:
bit $2002
bpl Wait
rts
In which emulators have you tested this? If you can find an emulator which gives the same result as on hardware that has at least some debugging features, you can try tracing through the code to see if all the code is executing as expected.
Re: Loading my "hello, world" on real hardware (AVS)
Found another BIG problem with your code: you don't have the holy pair of 6502 instructions at the very beginning of your reset routine - SEI and CLD. You don't have a valid IRQ handler (it's set to address 0, another shortcoming of Nerdy Nights), so if an IRQ fires (and the APU is known to fire IRQs from time to time if not properly initialized), the CPU will jump to address $0000 and most likely crash. Better disable IRQs altogether by putting a SEI instruction as the first thing in the reset handler. As for CLD, even though the decimal flag isn't a thing on the NES, it doesn't hurt to put that instruction in.
Re: Loading my "hello, world" on real hardware (AVS)
Great! I corrected my code and it worked perfectly!
Thank you so much, especially for having clearly explained the reasons beyond any suggestion
Thank you so much, especially for having clearly explained the reasons beyond any suggestion
Re: Loading my "hello, world" on real hardware (AVS)
Maybe now is a good time to talk about a couple of gripes I have with the Nerdy Nights tutorials. One is the use of 0 as the IRQ vector... There's always a chance you'll accidentally enable IRQs, or execute a BRK instruction, in which case the CPU will jump to address $0000 and crash. The fix for this is very simple and doesn't consume any extra resources: just point the IRQ vector to the RTI instruction at the end of the NMI handler:
If at some point you end up needing an actual IRQ handler (for an audio engine or an scanline counter), just give the NMI handler its own RTI back.
Now for the biggest problem in the Nerdy Nights tutorials: the entire game logic runs during vblank! The NMI signal is there to notify the CPU that vblank has started, so that you can make the most out of that short period and do all your video updates (sprites, name tables, palettes, etc.). But that's not how the tutorials use it, instead they do a bunch of tasks that have no place running during vblank, such as reading the controllers and reading sprite, and only after that will it carry out the necessary video updates.
Since video updates can only be done during vblank, this means that both the game logic and the video updates have to fit in the vblank period, witch is a measly 20 scanlines out of 262. That's right, Nerdy Nights programs can only use less than 8% of the CPU power of the NES before they start to glitch.
I'm not sure if they fix this in later lessons (I hope they do!), but sometimes you see people trying to create basic games such as Pong using Nerdy Nights as a base, and the games suddenly breaks because they added too much logic and the video updates started spilling out o vblank and into rendering time.
The simplest fix here is to invert the order in which you do things in the NMI handler: first do the video updates (using data computed during the previous NMI), then process the game logic for the *next* frame. Just be careful to not do a glitchy round of video updates the first time the NMI handler runs, possibly by having a flag signal whether the NMI handler is supposed to do any video updates. A flag like this is normally needed anyway for cases when you want to disable rendering and do big name table updates, so the NMI handler won't interfere with those.
Code: Select all
NMI:
;(do all your NMI stuff here)
IRQ: ;<-- point the IRQ vector to this label, instead of 0
rti ;returns from either the NMI or the IRQ
Now for the biggest problem in the Nerdy Nights tutorials: the entire game logic runs during vblank! The NMI signal is there to notify the CPU that vblank has started, so that you can make the most out of that short period and do all your video updates (sprites, name tables, palettes, etc.). But that's not how the tutorials use it, instead they do a bunch of tasks that have no place running during vblank, such as reading the controllers and reading sprite, and only after that will it carry out the necessary video updates.
Since video updates can only be done during vblank, this means that both the game logic and the video updates have to fit in the vblank period, witch is a measly 20 scanlines out of 262. That's right, Nerdy Nights programs can only use less than 8% of the CPU power of the NES before they start to glitch.
I'm not sure if they fix this in later lessons (I hope they do!), but sometimes you see people trying to create basic games such as Pong using Nerdy Nights as a base, and the games suddenly breaks because they added too much logic and the video updates started spilling out o vblank and into rendering time.
The simplest fix here is to invert the order in which you do things in the NMI handler: first do the video updates (using data computed during the previous NMI), then process the game logic for the *next* frame. Just be careful to not do a glitchy round of video updates the first time the NMI handler runs, possibly by having a flag signal whether the NMI handler is supposed to do any video updates. A flag like this is normally needed anyway for cases when you want to disable rendering and do big name table updates, so the NMI handler won't interfere with those.
Re: Loading my "hello, world" on real hardware (AVS)
Nope, at least not in Bunnyboys tutorials (though which are great in many ways anyway) IIRC. The Nerdy Nights sound tutorial by Metalslime does teach you this however which is one reason it's also great. It's a sound tutorial but it actually teaches you how to make a buffering system for the graphics, just for the purpose of the simple music player interface it uses to teach sound.
I highly recommend to look at this tutorial after you are quite comfortable with what's taught in the regular tutorials.
Re: Loading my "hello, world" on real hardware (AVS)
Oh, wow, thank you a lot for the added information!
My apologize for being so late (busy with work): I saved your post in order to be ready when I am more comfortable with NES programming
My apologize for being so late (busy with work): I saved your post in order to be ready when I am more comfortable with NES programming