SNES sprites hardware issue

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
SNES sprites hardware issue
by on (#204730)
Hey, look, bsnes-plus says I've made a bit of progress in my fighting game! A 32x32 portion of Sektor appears as a sprite.
Image
higan says so too on my desktop, except I can't provide a screenshot (haven't bothered building higan on this slow laptop).

Well, uh, my SNES disagrees. It shows the sprite when it's moved to the very left part of the screen. Other than that, it's absent. This shakily recorded video proves it.

I've played around a bit, looked for changes to make and so far have only tried changing sprite size. Had to change the tile too, but 8x8 is confirmed to have the same issue with me.

This is the code as of me posting this. Builds with latest version of bass-untech. The code in fighter.asm should show in a pretty straight-forward way what I'm doing. The actual OAM magic is in oam.inc, which I got from tepples (and need to remember to add the lorom-template license to the repo for, because that's not all that I've taken from it). Every other game I've played on my SNES has worked perfectly, I don't know what the deal could be.
Re: SNES sprites hardware issue
by on (#204736)
If it's a difference between higan and real hardware, then it's beyond me... Hope byuu sees this, something this simple really shouldn't be misbehaving on emulator. Sorry I can't help. :/
Re: SNES sprites hardware issue
by on (#204737)
I tested it on my own Super Everdrive and got results much like yours.
Attachment:
fighter1.jpg
fighter1.jpg [ 89.14 KiB | Viewed 3521 times ]

However, I have it set so that resetting resets the ROM rather than returning to the menu, and upon resetting and moving it back to the left, I ended up with this instead, with much more of the sprite being shown.
Attachment:
fighter2.jpg
fighter2.jpg [ 100.18 KiB | Viewed 3521 times ]

Because of that, it seems very likely that there's something wrong with your init code. It might not be the cause of the sprite only showing up on the left, but it does seem to be a serious issue regardless.
Re: SNES sprites hardware issue
by on (#204738)
Huh...changing the OAM transfer code to not copy the high table at all causes the example to work perfectly upon reset. I think I'm not using the high table code properly.
Re: SNES sprites hardware issue
by on (#204739)
So the solution to the problem turned out to be something pretty ridiculous.

Usually when you end up with an incorrect opcode size in your code, your code just doesn't work. It eventually will hit a brk or something, maybe a return or something.

But in my sprite clearing routine, that uh...that didn't happen. Somehow all the wrong opcodes ended up making the code work anyway, just without properly initializing sprites.

So now the demo's working on hardware always, but there's junk in the top left corner. Let's see what kind of fun I have figuring this one out.
Re: SNES sprites hardware issue
by on (#204740)
You're not setting the DMA bank properly on the OAM transfer.

Code:
ldx #zero; stx DMAADDR   // set to correctly to $811d
lda #bankbyte(zero); sta DMAADDRBANK  // this write fails
ldx #$0000; stx DMALEN  // this write should be $0000 but is $811d, so the ldx failed to execute


Likely reason is lda #bankbyte(zero) is being miscompiled as 16-bit whereas A is 8-bit here.

It ends up being set as #$ff in higan.

You're thus relying on uninitialized state, so it's going to vary between hardware and higan's attempts at pseudo randomization.
Re: SNES sprites hardware issue
by on (#204750)
Assuming that you're zero-initializing your RAM copy of OAM, having all other sprites in the top left corner is normal. You'll probably want to move them offscreen by setting the nineth byte of their X coordinate.
Re: SNES sprites hardware issue
by on (#204751)
On the NES, the correct way to hide unused sprites is to use large Y coordinates (239 or larger) to put them past the bottom of the screen, otherwise they may still contribute to the sprites-per-scanline limit. I assume it's the same with the SNES, so you should hide sprites at the bottom, not the sides.
Re: SNES sprites hardware issue
by on (#204752)
Quote:
I assume it's the same with the SNES, so you should hide sprites at the bottom, not the sides.


It's not the same.

On SNES, sprites wrap past the bottom back to the top of the screen. And, you can have sprite sizes larger than the 16 pixels below the bottom of the screen.


Also, I think, only sprites in "range" are counted in the scanline count....so sprites far enough offscreen to the left don't count. (Not sure, correct me if I'm wrong).


EDIT, however, if you have sprites set to 8x8 or 16x16, then, yes, you could put their Y value at $ef (239), and it won't show up.
Re: SNES sprites hardware issue
by on (#204753)
On at least the NTSC Super NES, Y=224 also works unless you're using 64x64.
Re: SNES sprites hardware issue
by on (#204754)
dougeff wrote:
On SNES, sprites wrap past the bottom back to the top of the screen. And, you can have sprite sizes larger than the 16 pixels below the bottom of the screen.

Then maybe you should set both X and Y coordinates to large values. I won't pretend I know anything about SNES development though.

Quote:
Also, I think, only sprites in "range" are counted in the scanline count....so sprites far enough offscreen to the left don't count. (Not sure, correct me if I'm wrong).

On the NES, "in range" means in the current scanline. Like I said, I know jack shit about SNES development, but from a hardware standpoint, it makes more sense to exclude sprites after one range check (Y only, like on the NES) rather than 2. It would be nice if someone could clear this up.
Re: SNES sprites hardware issue
by on (#204756)
By the NES definition, a 64x64 pixel sprite at Y=208 is in range on scanlines 208-224 and 0-15. In 239-line mode, a 32x32 pixel sprite at scanlines Y=232 through Y=239 and Y=0 through Y=7.

(These Y values may be off by one.)
Re: SNES sprites hardware issue
by on (#204759)
HihiDanni wrote:
Assuming that you're zero-initializing your RAM copy of OAM, having all other sprites in the top left corner is normal. You'll probably want to move them offscreen by setting the nineth byte of their X coordinate.

If you do this, just note that the official manual explicitly cautions against setting the X coordinate to $100 (-256), because in this case it will count against the sprite limitations despite not being displayed.
Re: SNES sprites hardware issue
by on (#204770)
I'm placing mine at X=-255 (originally intended as a code optimization but I guess it also works to avoid the bug(?) you described).