Jump to content
IGNORED

Reading Palettes from $2007?


TylerBarnes

Recommended Posts

Anyone have the secret sauce on reading palettes from the PPU via $2007? I know it is not buffered like normal reads from VRAM since palettes are stored on the PPU itself, but everytime I try to read palettes to save in RAM, I get values from my name table. I'm doing this in my NMI with other graphics updates.

Routine:                      
    LDA $2002                  ; Clear Hi/Lo Latch
    LDA #$3F                   ; Opening the port $3F00
    STA $2006                  ; to read palette data
    LDA #$00 
    STA $2006 
    TAX                        ; Use #$00 already in A as an X offset.
SaveCurrentPalette:
    LDA $2007
    STA TempPalette, x
    INX 
    CPX #$20                   ; Do this 32 times to aquire both palettes
    BNE SaveCurrentPalette


The pallet I loaded into the PPU at bootup: 

$3E,$16,$36,$3E,$3E,$27,$37,$3F,$3E,$27,$36,$17,$3E,$3E,$3D,$0C
$3F,$1A,$3A,$0B,$3F,$16,$36,$06,$3F,$27,$38,$17,$3F,$20,$3D,$2D


What I get after this routine tries to read the pelette to store into ram. These value are present in my .nam and the first $9A you see there starts at $0260 of that file. That $00 would no doubt be the throw away buffer read.

$00,$9A,$9A,$9A,$BE,$99,$99,$99,$99,$99,$99,$99,$99,$99,$99,$99
$99,$99,$99,$99,$99,$99,$99,$99,$99,$99,$99,$99,$99,$CD,$BF,$9A

,

Edited by TylerBarnes
Link to comment
Share on other sites

Okay, people figured out how to get me to join this site. Let someone's programming question go unanswered. 🙂

Try adding one more line of LDA $2007:

Routine:                      
    LDA $2002                  ; Clear Hi/Lo Latch
    LDA #$3F                   ; Opening the port $3F00
    STA $2006                  ; to read palette data
    LDA #$00 
    STA $2006 
    TAX                        ; Use #$00 already in A as an X offset.
SaveCurrentPalette:
    LDA $2007                  ; Probably gibberish
    LDA $2007                  ; Real value
    STA TempPalette, x
    INX 
    CPX #$20                   ; Do this 32 times to aquire both palettes
    BNE SaveCurrentPalette
Edited by KHAN Games
  • Like 6
Link to comment
Share on other sites

17 minutes ago, KHAN Games said:

Okay, people figured out how to get me to join this site. Let someone's programming question go unanswered. 🙂

Try adding one more line of LDA $2007:


Routine:                      
    LDA $2002                  ; Clear Hi/Lo Latch
    LDA #$3F                   ; Opening the port $3F00
    STA $2006                  ; to read palette data
    LDA #$00 
    STA $2006 
    TAX                        ; Use #$00 already in A as an X offset.
SaveCurrentPalette:
    LDA $2007                  ; Probably gibberish
    LDA $2007                  ; Real value
    STA TempPalette, x
    INX 
    CPX #$20                   ; Do this 32 times to aquire both palettes
    BNE SaveCurrentPalette

Palette reads should not be buffered based on documentation. Yes, I am getting a buffer read of $00 and data from my .nam, but everything is pointing to not needing a dummy read specifically for palettes. So your solution only account for this $00 offset but not the fact I'm reading the mirrored nam data in the buffer and not the palette data on the bus. 

nesdev wiki:
"Reading palette data from $3F00-$3FFF works differently. The palette data is placed immediately on the data bus, and hence no dummy read is required. Reading the palettes still updates the internal buffer though, but the data placed in it is the mirrored nametable data that would appear "underneath" the palette."

 

Link to comment
Share on other sites

I see you've asked this on both here on nesdev which means you have to deal with answers in both places 🙂

That said, are you sure it's actually running during NMI? (ie that your vblank code didn't take too long and now you're out of vblank?) Having it hit outside of vblank would cause issues similar to what you're seeing (I think)

Edited by gauauu
Link to comment
Share on other sites

5 minutes ago, gauauu said:

I see you've asked this on both here on nesdev which means you have to deal with answers in both places 🙂

That said, are you sure it's actually running during NMI? (ie that your vblank code didn't take too long and now you're out of vblank?) Having it hit outside of vblank would cause issues similar to what you're seeing (I think)

Thank you. Yes, tokumaru mentioned this. And this is the behavior I would expect from that too. However, I am testing this in a blank project file for sandboxing. All my NMI is trying to do is check the controller for A to be hit, setting a flag, and when the flag is set to just do this read.

Edited by TylerBarnes
Link to comment
Share on other sites

I'm going to approach this from a different angle. Why are you trying to read the palette from the PPU to put it in RAM?

I would approach this by designating 32 bytes in RAM for the palette and then update the palette from that buffer in RAM during the next NMI. This way, the Pal buffer RAM will always match what is in the PPU.

I used to only write to the Pal in the PPU when I need to change a color. I found it is much easier and doesn't eat a ton of NMI time to just write the 32 bytes from the Pal RAM buffer every NMI.

If I'm way off basis here, I apologize.

  • Like 2
Link to comment
Share on other sites

Thanks for the suggestion, you are 100% correct. I can indeed do what I'm trying to do with allocating ram space for the palette as a buffer and constantly update that instead of using that time to read the PPU. This is what my practical code turned into since it is more compatible with the emulator. However, the learner in me also wants to know how to perform things that the documentation claims the system can do, haha. Cheers. 

Link to comment
Share on other sites

Awesome. I was wondering if it was just sheer curiosity. 🙂 Don't get me wrong, there are some functionalities that may call for reading values from the PPU. I know that was an idea I had for finding a solution on how "pass" spites behind background objects in isometric environments, but that was long ago.

Good luck, I honestly have no idea as I have never successfully done this on other registers of the PPU.

  • Like 1
Link to comment
Share on other sites

It turns out that reading the palette just isn't reliable, it works on some PPUs and not others.  There is a test program in this post here:

http://forums.nesdev.com/viewtopic.php?p=99773#p99773

Like using the $2004 register, now it makes sense that no games ever did it that way.  Except for Micro Machines ($2004 reading), and as a result it's screwed up on older Famicoms (and maybe some rare NESes with early chips, if that combo exists).

I didn't know that either, before you asked.

Edited by Memblers
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...