Page 1 of 1

Sprite glitch on BSNES / Higan but not on actual hardware

Posted: Mon Dec 11, 2017 4:30 pm
by drludos
Hi everyone!

A few months ago, I've started to make my first (tiny) SNES homebrew, the "newbie way": I'm using PVSNESlib and C coding. Thanks to all the docs and the many questions answered here, I've been able to come over a lot of my dev issues, but there is one that I couldn't find any answer for:

- My game use both 16x16 sprites (SMALL), for the player and ennemies, and 32x32 sprits (LARGE) , for the explosions.
- When an enemy (or the player) is hit, I hide his (16x16) sprite and I display a larger explosion Sprite over it (32x32). The OAM for explosion sprite is lower (#5-15) than player and enemies (#20-50)
- On an actual SNES it runs fine, as intended (unmodified PAL 50hz + SD2SNES).
- On ZNES and No$SNS it runs fines too, like on the SNES hardware
- On BSNES / Higan and on SNES9X, the 32x32 sprites are displayed only partially: only the top half of the 4 animations frames (out of 7) are displayed. The first 4 frames are displayed only in the top half, and the remaining 3 animations frames are simply not displayed.

Here is a comparison picture (left is ZSNES / right is BSNES)
Image Image

My sprites are stored starting at 0x4000 in VRAM. At first I thought there could be some memory alignment issues between the two sprite sizes, so I've tried to store 16x16 sprites data in 0x4000 and the 32x32 ones in 0x6000, the result is the same.

However, I then tried to "invert" the order of which I loaded my sprite in VRAM (i use two 16x16 spritesheets and one 32x32 spritesheet). Instead of loading the two 16x16 spritesheets then the 32x32 one, I loaded one 16x16 sprite sheet (the player), the 32x32 one (explosion) and the other 16x16 one (enemies). By doing this, it still works on ZSNES and hardware, but the enemies, stored in VRAM after the 32x32 explosions, are no longer displayed in SNES9X and BSNES / Higan.

To summarize, it appears that, BSNES / Higan and SNES9X have trouble to display my 32x32 sprites and everything stored after them in VRAM, for a reason i can't explain.

What puzzles me my the most is that my program is working on actual hardware but glitching on BSNES / Higan, which I thought impossible due to the high level of emulation accuracy.

Do you have any idea of what can be the cause of this issue?
And a lead to a possible fix?

Thanks a lot for your help!

Re: Sprite glitch on BSNES / Higan but not on actual hardwar

Posted: Mon Dec 11, 2017 5:07 pm
by KungFuFurby
Is Higan/BSNES running the game as a PAL game (same goes for SNES9X)? Perhaps it only works on PAL, and NTSC does not have enough VBlank time to load all of the graphics.

Re: Sprite glitch on BSNES / Higan but not on actual hardwar

Posted: Mon Dec 11, 2017 5:45 pm
by drludos
KungFuFurby, you're my hero!
This problem has been bugging me for weeks, and you found the solution in less than one hour, kudos! :)

The game is indeed developed as a NTSC ROM (60hz is my target speed for ingame CPU load), so all the emulator play it in 60Hz. But when I run it with BSNES forced to run as a 50Hz PAL system, the 32x32 sprites in my game finally shows!

I was indeed to trying to upload all my sprite data (I have about 12 16x16 frames and 8 32x32 frames in total) in a single DMA pass. As you found it, it simply didn't have time to upload all the data (and I guess no$SNS and ZSNES are simply more "lax" about the VBLANK timing differences between PAL and NTSC).

So, what kind of fix do you suggest for this issue. I first dma the 16x16 sprites, then wait for next VBlank() and send the 32x32 sprites so it's all made in two Vblanks instead of one?
Or is there a better way to address this issue?

Thanks a lot for help, I could never have thought of that by myself!

P.S.: I'm thinking about modding my SNES so it can switch between 50Hz and 60Hz mode. If i use a 60Hz mode on a PAL SNES, regarding VBlank timings, will it be the same as running a real 60hz NTSC console?

Re: Sprite glitch on BSNES / Higan but not on actual hardwar

Posted: Mon Dec 11, 2017 6:11 pm
by tepples
Sprite VRAM is 16384 bytes. DMA can transfer one byte per slow-ROM cycle, or (1364 - 40) / 8 = 165.5 bytes per scanline. In the 224-line mode of NTSC (or presumably nonstandard PAL-60), the remaining (262 - 224 - 1) = 37 lines are enough for 6123 bytes, which is just barely enough to send an entire 5760-byte frame buffer from the Super Game Boy accessory but certainly not 16384 bytes of sprite cels.

You should be able to rewrite the entire sprite VRAM over the course of three frames. The trick for smooth animation is to send only those sprite cels that have changed. If you really need to rewrite all of sprite VRAM plus OAM, you'll need (16384 + 544)/165.5 = 103 lines of blanking. This means you'll need to force blanking in the top and bottom (103 - 37 / 2) = 33 lines, for a total of (224 - 33 * 2) = 158 active lines. That won't even fill a 16:9 TV in zoom mode.

Re: Sprite glitch on BSNES / Higan but not on actual hardwar

Posted: Mon Dec 11, 2017 6:14 pm
by KungFuFurby
That sounds like a good idea. Or, if you're loading all of those graphics at the very beginning into VRAM (that is, not swapping them out), store a $80 to INIDISP ($2100) to activate forced blank, load all of the graphics at once, then disable forced blank, all of your graphics should have loaded correctly. Otherwise, tepples has the right idea if you're swapping out graphics on the fly.

Modding SNESes are out of my scope, but it should be correct...

Re: Sprite glitch on BSNES / Higan but not on actual hardwar

Posted: Tue Dec 12, 2017 3:12 pm
by drludos
Thanks a lot KungFuFurby and Tepples for your help!

I've gone with the "load less than 6123 bytes of data during each Vblank", and the data no display correctly on every emulator I tested (and hardware too!).

But I'm keep the "forced blank" idea somewhere, it can be very useful too.