Memblers wrote:
That's fine, totally normal. If 'BNE True' is out of range, just do BEQ False / JMP True. With CA65 there are some built-in "longbranch" macros. Instead of BNE you do JNE, and it will change it to a jump whenever it becomes needed. I don't know if anyone has made a similar macro for NESASM.
Sometimes you can avoid out of range branches by putting the destination somewhere else, but I wouldn't do it unless it makes the code easier to read. One fairly common way this shows up, if you need to branch to an RTS instruction, you can move that RTS so it's before the start of the subroutine, instead of at the end. Or sometimes it's the RTS that's part of an already existing subroutine that's in memory below this one.
Kasumi wrote:
1. When branching, you want to go the label if the condition is true, and under the label when the condition is false.
If the branch is out of range, you still want the code to go to the same places in the same conditions.
Essentially, when a branch is out of range, reverse the condition and branch over a jmp. This will go to the same code for the same condition. The branch will never be too far since it is only branching over a jmp.
So you should never need more than one branch.
Just flipping the condition around is sometime not enough, at least, not enough if I want to try and keep the code more readable
Good to know that it is an option to branch on code over instead of only below, the machine does not care if it memory goes forward or backward.
Memblers wrote:
The best way is to set the Y coordinate to $EF or higher. If you put them at coordinate 0,0 they will probably be off screen on an NTSC TV, but maybe not on a PAL TV.
Yeah, best to avoid using sprite zero. If you'll be having more than 8 sprites per line in your game, you'll probably want to avoid tying game objects to specific sprite numbers.
Kasumi wrote:
2. To disable a sprite, just put it offscreen. (Y position of 239 or greater. 239 works because sprites are drawn one pixel lower than the given coordinate, and 240 is below the screen.)
But that's not exactly related to 8 sprites per scanline. What most games do is write to the RAM page used as a sprite buffer in a way that ensures the same parts of the same objects aren't dropped from being drawn every frame.
Sprite 0 ($0200-$0203 if you're using RAM Page 2 for sprites) will always be drawn. Sprite 1 will always be drawn as well. Same for sprites 2-7 because they are the highest priority sprites. Sprite 8 will drawn so long as all of sprites 0-7 are not in the same row of pixels as sprite 8. etc.
So say player 1 is one sprite. Games will write player 1's tile/position/attributes to $0200-$0203 in frame 0, then $0204-$0207 the next frame (frame 1). Etc. It will cycle all the other objects in a similar way. This ensures a different set of sprites will be drawn whenever there are more than 8 sharing a horizontal line, rather than the same objects always getting dropped.
(There are better methods than offsetting it by one every time, but maybe that's for another post.)
There's no reason to avoid using Sprite 0 unless you're actually using sprite 0 for the special thing it can do.
Using sprite 0 should be fine overall, but just in case, I will avoid it for now.
I should not need a tons of sprites at the same time, if what I am thinking of is going to work.
Putting sprite offscreen is good enough for disabling them (and if possible #$EF or bigger)
Memblers wrote:
That's correct sometimes, it depends. It might makes sense to turn off the screen when you're loading a large amount of data (like 8kB of pattern tables into CHR-RAM). But usually not for nametables, unless you're coming into it from a blank screen anyways (like title screen, or other transitions).
To update the background/nametables, usually the way to go is to create a buffer in RAM, so you can update that at any time. Then in the NMI routine, check if that buffer is ready, and write it to the PPU if it is.
Kasumi wrote:
3. Indeed, you don't have a lot of time to safely update tiles after an NMI hits. Four columns/their attributes is close to the practical limit, even with really fast code. If you want to do more than this in a single frame, you have to turn off background/sprite rendering, yes.
If you want to do writes that aren't in order (like tile columns are) the limit is lower. (Since you also have to update $2006 which takes more time than just a $2007 write.)
Yes for turning of if need a lot of change
About 4 columns of sprite after NMI hit is at best what I can change in a frame, I doupt I will need this for this game, but good to know.
Write a buffer if needed.
Memblers wrote:
Yeah, that's normal. Sprite rendering kinda lags behind. I guess it's because while a line is being rendered, the PPU is evaluating which sprites will be displayed on the next line.
Kasumi wrote:
4. That's just how the NES is. A Y position of 0 will draw the sprite on pixel 1, and there's no way to draw a sprite on pixel 0.
Oki Doki Loki!
Memblers wrote:
I shall read it tomorrow, but parsing it quickly, it seems good!
samophlange wrote:
Oh that's cool, that will save me a lot of headaches! They have docs about the "longbranch" macros and other things in the
ca65 user's guide.
It is another thing I need to read, since apparently "most" people here use ca65.
But I am happy with NESASM for the moment.
Thanks again for your answers!