Question about SNES palette writes
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Question about SNES palette writes
I'm using the following macro call and macro to make changes to palettes. The issue I'm having is that a significant portion of the time, rather than writing to the CGRAM destination that is given, it writes to CGRAM destination $01 instead. Does anyone with DMA transfer experience know what could cause this discrepancy? Thanks.
%SetPalette(#$B0, #$8000, #$e0, #$0020)
macro SetPalette(bank, source, dest, size)
;---header
php
rep #$30
pha
phx
phy
sep #$20
rep #$10
;---main
ldx <source>
stx $4372
lda <bank>
sta $4374
ldy <size>
sty $4375
lda <dest>
sta $2121
ldx #$2202
stx $4370
lda #$80
sta $420b
;---footer
rep #$30
ply
plx
pla
plp
endmacro
%SetPalette(#$B0, #$8000, #$e0, #$0020)
macro SetPalette(bank, source, dest, size)
;---header
php
rep #$30
pha
phx
phy
sep #$20
rep #$10
;---main
ldx <source>
stx $4372
lda <bank>
sta $4374
ldy <size>
sty $4375
lda <dest>
sta $2121
ldx #$2202
stx $4370
lda #$80
sta $420b
;---footer
rep #$30
ply
plx
pla
plp
endmacro
Re: Question about SNES palette writes
rep #$30
Then
Plp
, the rep #$30 is meaningless, since plp restores the original processor state.
Last edited by dougeff on Tue May 16, 2017 7:15 am, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
Re: Question about SNES palette writes
The rep #$30 is for the ply, plx, pla. These are pushed in 16-bit mode, so I need to pull them in 16-bit mode, too.dougeff wrote:the rep #$30 is meaningless, since plp restores the original processor state.
Re: Question about SNES palette writes
I see. That makes sense.
nesdoug.com -- blog/tutorial on programming for the NES
-
- Posts: 271
- Joined: Sun Mar 27, 2011 10:49 am
- Location: Victoria, BC
Re: Question about SNES palette writes
What assembler are you using? Have you checked to see that this is getting assembled correctly?
Re: Question about SNES palette writes
Asar. Yeah, I've stepped through the disassembly and everything checks out, as far as I can tell. Here's the disassembly:adam_smasher wrote:What assembler are you using? Have you checked to see that this is getting assembled correctly?
$B8/C99E 08 PHP A:0002 X:0000 Y:0C70 P:envMxdizc
$B8/C99F C2 30 REP #$30 A:0002 X:0000 Y:0C70 P:envMxdizc
$B8/C9A1 48 PHA A:0002 X:0000 Y:0C70 P:envmxdizc
$B8/C9A2 DA PHX A:0002 X:0000 Y:0C70 P:envmxdizc
$B8/C9A3 5A PHY A:0002 X:0000 Y:0C70 P:envmxdizc
$B8/C9A4 E2 20 SEP #$20 A:0002 X:0000 Y:0C70 P:envmxdizc
$B8/C9A6 C2 10 REP #$10 A:0002 X:0000 Y:0C70 P:envMxdizc
$B8/C9A8 A2 00 80 LDX #$8000 A:0002 X:0000 Y:0C70 P:envMxdizc
$B8/C9AB 8E 72 43 STX $4372 [$05:4372] A:0002 X:8000 Y:0C70 P:eNvMxdizc
$B8/C9AE A9 B0 LDA #$B0 A:0002 X:8000 Y:0C70 P:eNvMxdizc
$B8/C9B0 8D 74 43 STA $4374 [$05:4374] A:00B0 X:8000 Y:0C70 P:eNvMxdizc
$B8/C9B3 A0 20 00 LDY #$0020 A:00B0 X:8000 Y:0C70 P:eNvMxdizc
$B8/C9B6 8C 75 43 STY $4375 [$05:4375] A:00B0 X:8000 Y:0020 P:envMxdizc
$B8/C9B9 A9 E0 LDA #$E0 A:00B0 X:8000 Y:0020 P:envMxdizc
$B8/C9BB 8D 21 21 STA $2121 [$05:2121] A:00E0 X:8000 Y:0020 P:eNvMxdizc
$B8/C9BE A2 02 22 LDX #$2202 A:00E0 X:8000 Y:0020 P:eNvMxdizc
$B8/C9C1 8E 70 43 STX $4370 [$05:4370] A:00E0 X:2202 Y:0020 P:envMxdizc
$B8/C9C4 A9 80 LDA #$80 A:00E0 X:2202 Y:0020 P:envMxdizc
$B8/C9C6 8D 0B 42 STA $420B [$05:420B] A:0080 X:2202 Y:0020 P:eNvMxdizc
$B8/C9C9 C2 30 REP #$30 A:0080 X:2202 Y:0020 P:eNvMxdizc
$B8/C9CB 7A PLY A:0080 X:2202 Y:0020 P:eNvmxdizc
$B8/C9CC FA PLX A:0080 X:2202 Y:0C70 P:envmxdizc
$B8/C9CD 68 PLA A:0080 X:0000 Y:0C70 P:envmxdiZc
$B8/C9CE 28 PLP A:0002 X:0000 Y:0C70 P:envmxdizc
Re: Question about SNES palette writes
I'm assuming this code is run in the NMI handler or a setup routine during force-blank? Is there any other part of your program that accesses the same registers? And is this debugger stepthru from a successful run?
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
Re: Question about SNES palette writes
Successful and unsuccessful runs look identical. It's not run in the NMI handler, and I'm not really sure what that is, but upon some brief reading: it sounds like that's probably what I'm missing! Thanks for the info.
Re: Question about SNES palette writes
Well are you trying to call this during initialization or during gameplay? For gameplay it belongs in the NMI handler, if it's initialization you should enable force-blank (it's a bit in the INIDISP register at $2100) to turn off the display so you have free access to the PPU registers without needing to wait for NMI.
This page has information on when you can reliably access the different registers (during force-blank, v-blank (NMI), h-blank, or any time).
Edit: While in your initialization routine you might also want to disable the v-blank interrupt (or otherwise prevent your NMI routine from doing anything). If NMI fires while you're writing to the registers and then does its own writes to the registers you might get some strange results. So you should check for that as well.
Edit 2: Another observation: If SetPalette will be used in performance critical code you may want to cut down on the register-to-stack operations. At the very least, you can optimize this by replacing the ldy/sty instructions with ldx/stx and then removing the phy/ply instructions surrounding the operation.
This page has information on when you can reliably access the different registers (during force-blank, v-blank (NMI), h-blank, or any time).
Edit: While in your initialization routine you might also want to disable the v-blank interrupt (or otherwise prevent your NMI routine from doing anything). If NMI fires while you're writing to the registers and then does its own writes to the registers you might get some strange results. So you should check for that as well.
Edit 2: Another observation: If SetPalette will be used in performance critical code you may want to cut down on the register-to-stack operations. At the very least, you can optimize this by replacing the ldy/sty instructions with ldx/stx and then removing the phy/ply instructions surrounding the operation.
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
Re: Question about SNES palette writes
It's during gameplay, so I'll look into the NMI route.HihiDanni wrote:Well are you trying to call this during initialization or during gameplay? For gameplay it belongs in the NMI handler
I don't believe it is during critical code, but I'll go ahead and at least make that optimization.HihiDanni wrote:Edit 2: Another observation: If SetPalette will be used in performance critical code you may want to cut down on the register-to-stack operations. At the very least, you can optimize this by replacing the ldy/sty instructions with ldx/stx and then removing the phy/ply instructions surrounding the operation.
Re: Question about SNES palette writes
Update: after doing some reading about NMI, I was able to locate the game's v-blank routine and altered my macro to write to the game's queue of graphics changes to make during NMI, rather than having the macro perform a DMA transfer on its own. Looks like this has resolved the issue.
Thanks for the help!
Thanks for the help!