Hello, I have a question about the pallet and the screen. Every 6 frames I update the pallete, the scroll value gets affected temporally. How can you fix this?

HERE'S THE CODE:

Code:

NMI:

INC scroll ; add one to our scroll variable each frame

NTSwapCheck: LDA scroll ; check if the scroll just wrapped from 255 to 0 BNE NTSwapCheckP2 NTSwap: LDA nametable ; load current nametable number (0 or 1) EOR #$01 ; exclusive OR of bit 0 will flip that bit STA nametable ; so if nametable was 0, now 1 ; if nametable was 1, now 0NTSwapCheckP2:

NTSwapCheckP2: LDA scrolly ; check if the scroll just wrapped from 255 to 0 BNE NTSwapCheckP3

NTSwap2: LDA nametabley ; load current nametable number (0 or 1) EOR #$01 ; exclusive OR of bit 0 will flip that bit STA nametabley ; so if nametable was 0, now 1

Not sure if it's the culprit, but I see that you have "PPU cleanup" twice and one of them comes after your scroll updates.

I see some other bad things as well. You have logic at the beginning of your NMI handler, logic is better to have in the main loop, or after all graphic updates (OAM, VRAM and certain register updates) in the NMI, else it will steal vblank time. The NMI handler first needs to backup registers A, X and Y to stack (unless you are doing the all-in-NMI approach) then immediately do graphic updates. The order of the graphic updates is ideally something like this:1) Check your render flag and skip all graphic updates if clear (read bellow)2) Read $2002 to reset high/low latch3) Sprite updates (OAM DMA)4) Background updates5) Palette updates6) $2000 and $2001 updates7) Scroll updates ($2005)4, 5 and 6 can probably come in any order, but OAM DMA should be done early for PAL compatibility and Scroll should be updated last because PPU register writes affects the scroll register.

After all the graphic updates, you can have things that don't have to be in vblank, like sound updates or controller updates, though I heard controller updates are better to have in your main loop to avoid possible inconsistencies. Sound is best to be in NMI though since it ensures mostly constant tempo timing.

About the needppureg flag, he uses it whenever he has made changes to $2000 or $2001 in their buffers so that the NMI only updates them when the flag is set. I don't think it's really necessary to make them conditional separately. You should make the whole graphic update block conditional though. Have a render flag that is set at the end of each main loop and cleared at the end of each NMI. If the flag is not set, jump past all the graphic updates (but not sound and everything after that). That way there is no risk for drawing partly updated frames when the game lags.

Everything in your NMI before the sprite DMA looks like logic to me (it does not write to VRAM, OAM or PPU registers, so it's not graphic updates). It should be in your main loop.

Is the main loop in your NMI? In that case it should come after the graphic updates, because the first part of the NMI always happens during the vblank interval, which is limited. The article you linked to explains this too.

Definitely writing to PPU outside V-blank. I dropped your code into a blank template, and put some breakpoints on when the final scroll setting is done. About every 8 frames, you are clear down to scanline 7, occasionally more, by the time you set the scroll for the screen. [I had to make some assumptions, since you didn't provide the entire source code, I might be off by a few lines]

Eliminating the line...jsr LoadPalettes2 (you are updating the entire palette, every frame)-I don't know why you said "Every 6 frames". It happens every frame.

...improves this quite a bit, but still hitting scanline 1 occasionally, which would shift the entire screen by 1 pixel. Jittery. If you tightened your code a bit (made loops slightly more efficient). You could probably avoid the scroll shift entirely.

A more ideal solution, would be to do most of the calculations before hand (outside of NMI). Load all updates into a buffer (also outside of NMI), and make a much more efficient system of writing to the PPU. Then you could put the palette updates back in.

EDIT: also...

[deleted some code advice, I didn't like my wording]

You need to be careful about which direction PPU writes are going. You specifically set it to +32 in the DrawColumn / DrawColumn2 subroutines, but that comes after the attribute table subroutine, and it's still set to +1 mode from the end of the NMI write to $2000 [I guess that won't cause a problem, now that I look at it]. Further, it is still in +32 mode (sometimes) when it gets to LoadPalettes2, which needs it to be in +1 mode.

_________________nesdoug.com -- blog/tutorial on programming for the NES

Cool. 1. Is updating the palette EVERY FRAME a bad thing and can it be done with buffering?2 whuts buffering?3 pla does What?Also Would It help to give you the .nes file for reference?Heres the new CODE:

1. Not a bad thing as long as it is updated in vblank, and yes buffering is the preferable way to do it. The palette isn't that big but if you are short on vblank time you could make a buffer system that only updates parts of the palette instead of the whole palette every time. You could also make a buffer system that updates nametable and palette together so that changing BG characters also changes their colours at the same time.

2. Buffering is keeping a copy of whatever you buffer (usually graphic updates) in a RAM area. You update this buffer in your game logic (main loop) and in the beginning of NMI (vblank) you just copy the contents of this buffer to VRAM/OAM etc. This way you can keep game logic and graphic updates separate. You are already buffering the OAM by using the RAM area $0200 to $02FF as an OAM buffer (or shadow OAM as they also call it). But DMA can only be used for OAM (sprite attributes), not for VRAM (nametable and palette), so you have to code a different buffer system for those. Updates to $2000 and $2001 should also be buffered in their own RAM registers so that they are also only changed in vblank.

3. PLA pulls the topmost value from the stack and puts it in the accumulator. If you have your main loop outside of NMI handler (in your RESET handler), you need to backup both the accumulator and the index registers X and Y on the stack at the start of your NMI handler and pull them out again in reverse order. PHA pushes the accumulator on to the stack but there are no instructions for pushing or pulling X or Y to or from stack, so you have to transfer X and Y into A first (using TXA/TYA when pushing and TAX/TAY after pulling):

Code:

NMI: pha txa pha tya pha ;save A, X and Y to the stack

;(NMI code here)

pla tay pla tax pla ;restore A, X and Y from the stack rti

This is needed because the NMI is an interrupt that could happen at any time in your main loop, and since both main and NMI uses the registers it could mess up your code. You don't need to backup the status flags however, because they are backed up automatically whenever an interrupt occurs.

NTSwapCheck: LDA scroll ; check if the scroll just wrapped from 255 to 0 BNE NTSwapCheckP2 NTSwap: LDA nametable ; load current nametable number (0 or 1) EOR #$01 ; exclusive OR of bit 0 will flip that bit STA nametable ; so if nametable was 0, now 1 ; if nametable was 1, now 0

.org $FFFA ;first of the three vectors starts here .dw NMI ;when an NMI happens (once per frame if enabled) the ;processor will jump to the label NMI: .dw RESET ;when the processor first turns on or is reset, it will jump ;to the label RESET: .dw 0 ;external interrupt IRQ is not used in this tutorial

What this is doing so far is that you ave a character running around with 5 8x8 sprites attached to it.You can jump, the pallete stack $3F11 should change constantly, The nametables $20 and $28 should be both filled with a screen worth of info if a full level is loaded ala SMB3, Finally, paletteswap is the palette swapping variable.GAME : Kitsune Tales

I see you moved out some of the logic from the beginning of the NMI, not everything though, the INC Scroll and the NTSwapCheck stuff are also logic and should be moved down after graphic updates. But now you have much more vblank time, do you still have the same problem?

I saw some other weird things. You clear RAM (at "clrmem") except page 3 that you fill with $FE:

Code:

;... LDA #$FE STA $0300, x ;...

You probably meant to fill page 2 with $FE to avoid stray sprites at boot since you are using that page as your OAM buffer for OAM-DMA.

And you only read bit 0 of $4016/$4017 in your controller reading routine so expansion port controllers doesn't work. You should read bit 1 as well unless it's a 4-player game.

Also I see you are doing the All-in-NMI approach. That's fine (Super Mario Bros is doing it that way) but it has its limits, and having logic in the main loop (the loop at "Forever" in your code) makes things more clear I think.

1. Yes, But listening to you des make a difference and that's nice. Wait I moved more logic around and It made a difference.2. I Don't want the All nmi approach. I want some of the rendering to go Outside Like text, boss AI and other stuff. I heard that It boggles down speed if your not careful.3. It's a one player game. However, If I get to demaking smash bros., I'll need that info4. I found an article on stacks pha and pla. I just need to figure out where my buffer's going to go.5. that was on the nerdy nights tutorial.6. The scroll is only affected when it loads a section of the attibutes and the back ground.7. I feel like I went too far off talking about stacks and what not. Should I continue?

2. I Don't want the All nmi approach. I want some of the rendering to go Outside Like text, boss AI and other stuff. I heard that It boggles down speed if your not careful.

Then just move out all your logic from the NMI and put it in your forever loop. Only keep the graphic updates (OAM, VRAM, $2000, $2001 and $2005 writes) in the NMI.

IMAGICA wrote:

3. It's a one player game. However, If I get to demaking smash bros., I'll need that info

You misunderstand me. If it's a one player game, you need to read both bit 0 and bit 1 of $4016 to your controller 1 data so that people can use both standard controllers and Famicom expansion port controllers. Nerdy Nights doesn't teach this but it's good practice to do it. Else people might not be able to use their arcade sticks and other controllers with your game.

IMAGICA wrote:

4. I found an article on stacks pha and pla. I just need to figure out where my buffer's going to go.

Your buffers goes into RAM wherever there is space. You are already buffering OAM and scroll in RAM. I like to keep my OAM buffer on RAM page 2 ($0200~$02FF), BG and palette buffers in page 3, and scroll and $2000/$2001 buffers in the zero page. The BG buffer can't be too big (there's not enough vblank time to draw the whole nametable), so you could also keep BG and palette buffers at the beginning of page 1. The stack starts in the other end of page 1 so unless you use a lot of stack there's no risk they will collide.

Who is online

Users browsing this forum: No registered users and 5 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum