It is currently Wed Dec 13, 2017 11:33 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Mon Aug 31, 2015 5:58 am 
Offline
User avatar

Joined: Sat Aug 15, 2015 3:42 pm
Posts: 109
Location: France
Hi everyone,

I've got a status bar which is working fine (with sprite 0 hit) here's the code in my NMI routine :

Code:
    LDA #$00
    STA $2006
    STA $2006

    STA $2005
    STA $2005
                        ; switch CHR bank
    LDA #$03
    TAX
    STA bankTable,X
                        ; switch nametable to $2400
    LDA ctrl_var
    EOR #%00000001
    STA $2000

@WaitNotSprite0:
        LDA $2002
        AND #%01000000
        BNE @WaitNotSprite0   ; wait until sprite 0 not hit

@WaitSprite0:
        LDA $2002
        AND #%01000000
        BEQ @WaitSprite0      ; wait until sprite 0 is hit

        LDX #$10
@WaitScanline:
        DEX
        BNE @WaitScanline

                        ; switch CHR bank
    LDA #$00
    TAX
    STA bankTable,X

                        ; switch nametable back $2000
    LDA ctrl_var
    STA $2000


Everything's fine for now.

What I'd like to do is to swap some colors in the palette for the status bar, and put the original colors back for the rest of the screen.

I manage to do this BUT instead of having the $2000 nametable starting "below" the status bar, it begins "under" the status bar. Am I clear ? (not sure ...)

Here's the code I used :

Code:
    LDA #$00
    STA $2006
    STA $2006

    STA $2005
    STA $2005
; PALETTE SWAP
        LDA #$3f
        STA $2006
        LDA #$01
        STA $2006
        LDA #$30
        STA $2007

        LDA #$00
        STA $2006
        STA $2006

                        ; switch CHR bank
    LDA #$03
    TAX
    STA bankTable,X
                        ; switch nametable to $2400
    LDA ctrl_var
    EOR #%00000001
    STA $2000

@WaitNotSprite0:
        LDA $2002
        AND #%01000000
        BNE @WaitNotSprite0   ; wait until sprite 0 not hit

@WaitSprite0:
        LDA $2002
        AND #%01000000
        BEQ @WaitSprite0      ; wait until sprite 0 is hit

        LDX #$10
@WaitScanline:
        DEX
        BNE @WaitScanline

    LDA #%00000001  ; rendering disabled + grayscale
    STA $2001

; PALETTE SWAP
    LDA #$3F
    STA $2006
    LDA #$01
    STA $2006
    LDA #$1A
    STA $2007

    LDA #$00
    STA $2006
    STA $2006

                        ; switch CHR bank
    LDA #$00
    TAX
    STA bankTable,X

                        ; switch nametable back $2000
    LDA ctrl_var
    STA $2000


I guess I'm doing something wrong, writing to a wrong register, or forgetting to write to a register ...
Any advice ?


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 9:08 am 
Offline
User avatar

Joined: Sat Aug 15, 2015 3:42 pm
Posts: 109
Location: France
This is my starting point :

Attachment:
File comment: Screen 1
screen_1.png
screen_1.png [ 101.99 KiB | Viewed 2538 times ]


There's an action when I press B in front of the foutain, and the text box appear. I want to change 3 colors for the text box and then write back the original colors after the sprite 0 hit.

If I add the first palette swap, I've got this :

Attachment:
File comment: Screen 2
screen_2.png
screen_2.png [ 96.29 KiB | Viewed 2538 times ]


Which is ok.

But if I write back the original colors :

Attachment:
File comment: Screen 3
screen_3.png
screen_3.png [ 92.12 KiB | Viewed 2538 times ]


The colors are ok, but the "image" is misplaced.

Any thoughts ?


Sorry for the english ...


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 10:06 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19342
Location: NE Indiana, USA (NTSC)
After you write back the original colors, how are you setting the scroll position? You need to use the $2006-$2005-$2005-$2006 sequence.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 10:15 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Mid-screen palette swaps are particularly tricky, and you should definitely not be relying on FCEU alphabet soup alone to do your testing, because it's notoriously inaccurate when it comes to raster effects.

In order to successfully modify the palette mid-screen, you have to turn off rendering. There's a very short amount of time during Hblank when the PPU is not touching $2006 or its memory, but this time is not enough to set the PPU address and update colors, so unless you turn off rendering, there will be a conflict between you trying to write colors and the PPU trying to render tiles.

Also, when rendering is off and the VRAM address is pointing to the palette area, the color being pointed gets displayed on the screen. This means that you get "rainbow" glitches if you don't time the writes to happen during hblank.

In order to keep things glitch-free, you're gonna need some blank scanlines, because you can only really do stuff during hblank. First you wait for the hblank to turn rendering off, and then you can point to the palette you want to change. Then you wait for the next hblank and blast the new colors (pre-loaded in A, X and Y), and then reset the scroll (using the $2005/6 trick) and enable rendering on the next hblank.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 10:30 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
The idea behind blasting the new colors from pre-loaded registers is that you can safely point to color 0 of any palette beforehand and as long as they were all initialized to the same value it will be like the PPU was rendering the background color. Then you can pre-load the 3 colors that will be changed in A, X and Y, and do this during hblank:

Code:
bit $2007 ;skip color 0
sta $2007 ;write color 1
stx $2007 ;write color 2
sty $2007 ;write color 3

After the last write, the VRAM address register will conveniently be pointing to color 0 of the next palette, so there will be no glitches on screen.

Then you can do the same with another palette (each palette will cost another blank scanline) or take your time with the $2005/6 trick to set the scroll and enable rendering during the next hblank.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 10:54 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
tokumaru wrote:
you should definitely not be relying on FCEU alphabet soup alone to do your testing

The usual recommendation is to test this kind of stuff against nintendulator, but test it on hardware if you can, too. (If you don't have a flash cart / NES yourself, post a ROM that already works in nintendulator and ask someone here to test it for you.)


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 11:03 am 
Offline
User avatar

Joined: Sat Aug 15, 2015 3:42 pm
Posts: 109
Location: France
OK let's see if I understand everything right here.

Before updateing any color, I'd like to turn off an on rendering without glitch (screen 3)

Actually I'm doing this :

00 : load new palette
01 : switch CHR bank
02 : set BG "page" to 1
03 : write %xxxxxx01 to $2000 to switch nametable
04 : wait for not sprite 0 hit
05 : wait for sprite 0 hit
06 : wait for hblank (end of scanline?)
07 : write $00 to $2001 to turn rendering off
08 : switch CHR bank
09 : set BG "page" to 0
10 : write %xxxxxx00 to $2000 to switch nametable
11 : write %xxx11xxx to $2001 to turn rendering on

It's ok so far, everything's working.

So now I have to update palette between points 07 and 08 right ?

07.1 : write $3FC0 to $2006
07.2 : wait for hblank
07.3 : write color to $2007
07.4 : wait for hblank (???)
07.5 : write $00 to $2006-$2005-$2005-$2006

Should be ok ?

I'll test with Nintendulator and I've got an Everdrive N8 to test on real hardware.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 11:18 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
glutock wrote:
09 : set BG "page" to 0
10 : write %xxxxxx00 to $2000 to switch nametable

This is already taken care of by the $2006-$2005-$2005-$2006 sequence.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 11:29 am 
Offline
User avatar

Joined: Sat Aug 15, 2015 3:42 pm
Posts: 109
Location: France
Oh ok, thanks

Otherwise, it is correct ?


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 11:31 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
glutock wrote:
07.4 : wait for hblank (???)
07.5 : write $00 to $2006-$2005-$2005-$2006

You don't need to wait for hblank specifically, but it does matter where in the line you turn rendering back on. If you do it before the Y increment at dot 256, I believe you'll get a partially rendered line, and then the first full line will begin rendering at Y+1. If you do it in hblank the next line will begin rendering at Y+0. (There's some notes on this in the article I linked in the previous post.)


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 12:06 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6520
Location: Seattle
One of the previous times this came up, I marked up what the title screen for Indiana Jones and the Last Crusade was doing for its mis-screen palette changes.

Specifically on this screen, because there's no change in X fine scroll, and the positions of the gradients correspond to specific fine Y scroll values, they're able to skip the writes to $2005.


Top
 Profile  
 
PostPosted: Mon Aug 31, 2015 12:47 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
glutock wrote:
07.1 : write $3FC0 to $2006
07.2 : wait for hblank
07.3 : write color to $2007

If you write only one color to $2007, the VRAM address register will be pointing to a color other than 0, and this color will be rendered on the next scanline until you modify the address with the $2006/5/5/6 writes, which will look like a glitch. This is why I recommended you wrote 3 colors in succession, so that the address register would be pointing at color 0 of the next palette after all the writes.

If you want to update only 1 or 2 colors, replace the writes you're not doing with BIT or LD* instructions, to advance the VRAM address without modifying the colors. For example, to update only color 2:

Code:
bit $2007
bit $2007
sta $2007
bit $2007

This will always ensure that when the next scanline starts, the VRAM address is pointing to a color 0.


Top
 Profile  
 
PostPosted: Tue Sep 01, 2015 6:05 am 
Offline
User avatar

Joined: Sat Aug 15, 2015 3:42 pm
Posts: 109
Location: France
I'm sorry to insist but I really want to understand.

I've attached a rom and source as an example.
If you press A, it updates a color an show a status bar using sprite 0 hit.

If I uncomment lines 350 to 353 and lines 368 to 372, it's not working anymore.

Why ?


Attachments:
sprite_0_hit+palette_swap.rar [6.9 KiB]
Downloaded 173 times
Top
 Profile  
 
PostPosted: Tue Sep 01, 2015 12:39 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6520
Location: Seattle
When you write 0 to 2006, 2005, 2005, 2006, you're resetting the full scroll to (0,0), which is why it appears to re-scroll to the top of the screen. (Is this the problem you're referring to? If so, for now, you can just use a shorter version that writes specific non-zero values to 2006 twice, since you seem to be not changing X or Y fine scroll.)

In the future, once the bottom part is scrolling independently, you'll need to keep track of the specific values that will appear in all four registers and write them instead. (see also: nesdevwiki:PPU scrolling#Split X/Y scroll)


Top
 Profile  
 
PostPosted: Tue Sep 01, 2015 2:27 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
lidnariq wrote:
When you write 0 to 2006, 2005, 2005, 2006, you're resetting the full scroll to (0,0), which is why it appears to re-scroll to the top of the screen. (Is this the problem you're referring to? If so, for now, you can just use a shorter version that writes specific non-zero values to 2006 twice, since you seem to be not changing X or Y fine scroll.)

Just wanted to clarify this: The reason you need the set the scroll is that changing the palette modifies the VRAM address register, so you have to reconfigure the whole address again. Ideally, just writing the new address to $2006 would work fine, but unfortunately the PPU automatically clears one bit related to the vertical scroll on the first write to $2006, so you need the $2006/5/5/6 trick to fully set all the scroll bits.

I don't see anything obviously wrong with your code, but I don't have the setup to uncomment those lines and build a new ROM for further testing. When you say "it's not working anymore", what's the expected behavior and what is actually happening? Where have you tested this behavior?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Revenant and 4 guests


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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group