Page 1 of 1

Sprite windowing not working - RESOLVED

Posted: Sat Nov 01, 2014 11:26 pm
by 93143
Why is it that no matter what I write to $2125 it does nothing (ie: $2125 stays zero in no$sns debugger), but writing to $210E sends whatever was previously written to $210E into $2125 (as well as into the low byte of BG1VOFS, like it's supposed to)?

$2123 and $2124 store their values properly, as do $2126-$2129...

More generally, nothing I try seems to have any effect on the actual screen output. Is there some obscure, easy-to-miss trick that you have to do to get windowing working?

You can mask off parts of sprites this way, right?

Code: Select all

; window mask setup
	stz $2123		; turn off both windows for BG1/2
	lda #$0A		; turn on both windows for OBJ, no inversion
	sta $2125
	lda #$5F		; set left side of window 1 to 95
	sta $2126
	lda #$A4		; set right side of window 1 to 164
	sta $2127
	lda #$B5		; set left side of window 2 to 181
	sta $2128
	lda #$FF		; set right side of window 2 to 255
	sta $2129
	stz $212B		; set window combination logic to OR
	lda $1F			; turn on windowing
	sta $212E
...

[much later] I haven't solved the above yet, but... here's a fun addendum: on real hardware, this program shows a regular periodic flicker on some of the sprites, a sort of winking in several spots on the screen at the same time, about twice per second or so. This doesn't happen in higan v094 accuracy core.

That's right, I broke higan with a title screen. Either that or the hardware is starting to go (which might actually be more likely)...

Re: Sprite windowing not working

Posted: Sun Nov 02, 2014 8:04 am
by doppelganger
I can't see anything wrong with this part of the code. Writing to $210E should not affect $2125 at all, since they affect two different screen components. Are you writing to the registers in some other part of the code?

Re: Sprite windowing not working

Posted: Sun Nov 02, 2014 8:28 am
by KungFuFurby
I've seen the sprite masking effect in The Addams Family ~ Pugsley's Scavenger Hunt with the crystal ball level, so I know it's possible.

It looks like your combined window covers 95-255, given that they overlap. Thus, sprites inside this window should end up disabled...

Maybe you're writing a zero to $2125 somewhere else in the code, and thus the effect only works for a split second on real hardware when this write occurs at a high-numbered scanline.

I'd set up a breakpoint to determine where else the your code writes to this particular register.

Re: Sprite windowing not working

Posted: Sun Nov 02, 2014 4:23 pm
by 93143
doppelganger wrote:I can't see anything wrong with this part of the code. Writing to $210E should not affect $2125 at all, since they affect two different screen components. Are you writing to the registers in some other part of the code?
I've got all 8 HDMA channels going, subscreen colour math active, and an extended VBlank using an IRQ and some H/V polling. Lots of register writes, but none to $2125, except in the initializer. I've also got a renderer that pastes some sprites down into BG1 because I ran out of memory, but currently it only runs once and removing it doesn't solve the problem.
KungFuFurby wrote:I've seen the sprite masking effect in The Addams Family ~ Pugsley's Scavenger Hunt with the crystal ball level, so I know it's possible.
Thanks. I'd certainly have thought so based on the descriptions in the docs, but the fact that this one register absolutely fails to work was making me wonder if it was a known issue or something...
It looks like your combined window covers 95-255, given that they overlap. Thus, sprites inside this window should end up disabled...
Isn't there a gap from 165 to 180? Either way, nothing gets masked. I can see the sprites I want as well as the garbage I don't want.

VRAM and OAM are both full (or will be once the main menu shows up), so I can't just redesign my sprite table. I need this to work...
Maybe you're writing a zero to $2125 somewhere else in the code, and thus the effect only works for a split second on real hardware when this write occurs at a high-numbered scanline.
Actually, my first thought about the blinking was that it was a sprite priority rotation issue, since it seems to only happen with overlapping sprites. I seem to recall turning on sprite priority somewhere, but I have no very clear idea how it works. But if it doesn't happen in higan, I have to consider the possibility that either my SNES or my Super Everdrive is off nominal... EDIT: It's not sprite priority. I turned it off, to no effect whatsoever. EDIT2: Apparently I suck at Super Everdrive. It was sprite priority. Protip: to load a new version of a ROM, use the menu instead of just pressing Start...

Regarding writing to $2125, I had stuck a WAI right after the write, so as to inspect the PPU status right then. The write doesn't take. Writing to $210E twice instead gets the correct value into $2125, though it still doesn't actually mask anything...

...and now I've set a breakpoint at the LDA $#0A and stepped through. The accumulator loads fine, but $2125 doesn't see the write.
I'd set up a breakpoint to determine where else the your code writes to this particular register.
Okay, I've downloaded Geiger's Snes9X debugger, and it seems the code only touches $00:2125 twice - once in Neviksti's initializer (an indexed access in a loop), and once in my code, where I attempt to STA $2125 and nothing happens.

I could've told you that, as I already went through my code with Ctrl+F. It's not actually all that complicated...

...

Should I post my entire code? It would have to be without graphical assets, because this is a mockup of the title screen for the game I'm trying to port, and I'm trying to avoid establishing any expectations this early in development (there is, after all, only one Internet)...

Re: Sprite windowing not working

Posted: Mon Nov 03, 2014 1:17 pm
by 93143
Bumping so anyone who cares will know: It seems turning off sprite priority did fix the blinking issue. I was just too dumb to reload the new ROM instead of shortcutting to the already-loaded old one.

But why didn't this happen in higan? What was the root cause? I'm not sure I'm competent to engage in a test campaign... should I ignore it?

And of course I still don't know why windowing isn't working...

Re: Sprite windowing not working

Posted: Tue Nov 04, 2014 12:30 am
by 93143
Okay, everyone, you can go back to your day jobs and start sleeping normally. Your assistance in this matter is no longer required.
doppelganger wrote:I can't see anything wrong with this part of the code.
Yes, well, you weren't the only one...

Turns out the bits in $212E are disable bits... not at all obvious from anomie's docs, but pretty clear in fullsnes (which I looked at second, and apparently missed this critical detail because I thought I already knew how it worked). Nope nope nope. The problem was that I was loading $1F instead of #$1F, and that part of RAM was zeroed. Switching to $00 accessed the renderer's leftover pixel mask, and loaded 9F, which worked.

I guess the weirdness re: $210E etc. is a bug in the no$sns debugger specifically, since no$sns itself seems to work properly.

...

Anyway, I believe that constitutes the last visible bug in this particular program, so unless someone's really interested in that blinky sprite priority issue, I guess the thread is over. Thanks to both of you for trying to help...

Re: Sprite windowing not working

Posted: Tue Nov 04, 2014 2:28 am
by koitsu
93143 wrote:Turns out the bits in $212E are disable bits... not at all obvious from anomie's docs, but pretty clear in fullsnes (which I looked at second, and apparently missed this critical detail because I thought I already knew how it worked).
Referring to your initial post with source code: what was the value in direct page $1F at the time? I ask because Nintendo's own documentation states very clearly that 0 = disable, 1 = enable for $212C through $212F.

Also, what's your value in $212C? $212E is affected by $212C.

Re: Sprite windowing not working - RESOLVED

Posted: Tue Nov 04, 2014 3:04 am
by 93143
BWAHAHAHA!!....

How did I miss that?

$1F is zero. $00 is 9Fh, because my rendering code left it that way.

I guess what nocash is saying is that the windows "disable" their targets inside the designated area, and those bits let them.

Thanks for pointing that out! I need the windows for other stuff later, and I can't count on always (a) forgetting to add '#' to my value, and (b) randomly having the right bits in DP...

$212C is 11h. Just BG1 and OBJ enabled. So yeah, 1Fh is overkill for turning on windowing - but what the heck; it works...

Sorry for wasting everyone's time on this.

...

The no$sns debugger still tells me $2125 is FBh, which is the low byte of the vertical scroll value...

Re: Sprite windowing not working - RESOLVED

Posted: Tue Nov 04, 2014 3:51 am
by KungFuFurby
I've done that mistake before myself, actually. :oops: I've forgotten the # sign and accidentally referred to direct page.

I didn't think of that myself. I also declined to comment on the last couple of lines of code, figuring your coding was sound (and then that's when I realized I didn't look close enough), although I had a small suspicion that maybe you'll accidentally disable more than just the sprites. I did rule that out on the grounds that the previous code appeared to turn that off.

Re: Sprite windowing not working - RESOLVED

Posted: Tue Nov 04, 2014 11:28 am
by AWJ
Yeah, 212C-212F are a bit confusing, I had the wrong idea about them too until I actually rewrote part of the bsnes renderer.

For 212C and 212D (TM and TS), 0 bits mean "masked/transparent" and 1 bits mean "visible". These registers have absolutely nothing to do with the windows--layers masked by TM/TS are masked no matter what any of the window registers say.

For 212E and 212F (TMW and TSW), 0 bits mean "ignore the window" and 1 bits mean "use the window". "Use the window" can mean either "mask inside" or "mask outside", or nothing at all, depending on the window registers (if neither of the windows is enabled for the respective layer then obviously no window masking can occur). And if the corresponding bit in TM or TS is clear then these register bits are irrelevant--again, layers masked by TM/TS are always masked, period.