Mickey Mania emulator comparison

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Thu Mar 26, 2009 6:29 am

Nemesis wrote:It's not as simple as the first sprite being ignored for sprite masking.
Nemesis wrote:I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware.
Both incorrect :)

This has nothing whatsoever to do with sprite masking, and everything to do with the fact there are more than 10 32x32 sprites on a single line. This is not taken into account properly in Fusion due to a silly bug.

I can confirm that sticking multiple sprites at zero does nothing. Neither does sticking the last one at 1,1.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Thu Mar 26, 2009 7:47 am

Snake wrote:This has nothing whatsoever to do with sprite masking, and everything to do with the fact there are more than 10 32x32 sprites on a single line. This is not taken into account properly in Fusion due to a silly bug.
I can see how that's true for y=253 but how is it true for y=233? I must be missing something.

EDIT: Nevermind -- I misunderstood. So very tired.
Snake wrote:I can confirm that sticking multiple sprites at zero does nothing. Neither does sticking the last one at 1,1.
That's a relief. :D
Last edited by TascoDLX on Thu Mar 26, 2009 5:54 pm, edited 1 time in total.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Thu Mar 26, 2009 8:28 am

Snake wrote:
Nemesis wrote:It's not as simple as the first sprite being ignored for sprite masking.
Nemesis wrote:I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware.
Both incorrect :)

This has nothing whatsoever to do with sprite masking, and everything to do with the fact there are more than 10 32x32 sprites on a single line. This is not taken into account properly in Fusion due to a silly bug.

I can confirm that sticking multiple sprites at zero does nothing. Neither does sticking the last one at 1,1.
Yep, I finally figured that out half an hour ago. I messed up a test yesterday, and spent the entire evening working from a false premise. :roll:

I have found two different ways to break sprite handling/masking in Kega Fusion however (and yeah, a lot more than two in every other emulator :)). I'm going to finish off this test ROM and post it here when it's done. I think it'll help everyone to have a single ROM that validates everything, rather than testing 100 different games and still missing some stuff.

Eke
Very interested
Posts: 885
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Thu Mar 26, 2009 12:04 pm

TascoDLX wrote:
mickagame wrote:It's like the sprite with x_pos = 0 is the first sprite of the list...
Yes, indeed it is (and, in this case, the second, third, fourth, and fifth as well). Any sprite, no matter what the x_pos, should set the sol_flag. Therefore, it should look like this:

Code: Select all

if(xpos == 0 && sol_flag) return; /* stop rendering sprites */ 
sol_flag = 1;
you're right... I didn't notice before because I didn't wait enough but the bug was indeed here :oops:

considering all that has been said above, can we say that THIS is the correct sprite masking implementation (i.e ignoring the first sprite for sprite masking) ?

I now do something like this and this indeed works (count being the counter in the sprite list):

Code: Select all

    if(!xpos && count) return;

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Thu Mar 26, 2009 9:44 pm

considering all that has been said above, can we say that THIS is the correct sprite masking implementation (i.e ignoring the first sprite for sprite masking) ?
Not quite. My notes from testing:
-Sprite masks at x=0 only work correctly when there's at least one higher priority sprite on the same line which is not at x=0. (This is what Galaxy Force II relies on)
-Sprite masks at x=0 are never effective when not proceeded by a higher priority sprite not at x=0 on the same line, unless the previous line ended with a sprite pixel overflow, in which case, the mask becomes effective for that line only. If that line also causes a dot overflow, the mask will also be effective on the following line, and so on.
-A sprite mask does contribute to the pixel overflow count for a line according to its given dimensions just like any other sprite. Note that sprite masks still count towards the pixel count for a line when sprite masks are the first sprites on a line and are ignored. (This is what Mickey Mania relies on)
-A sprite mask at x=0 does NOT stop the VDP from parsing the remainder of sprites for that line, it just prevents it from displaying any more pixels as a result of the sprites it locates on that line. As a result, a sprite pixel overflow can still occur on a line where all sprites were masked, but there were enough dots in the sprites given after the masking sprite on that line to cause a dot overflow.

Note point number 2. Nothing emulates that, and my test ROM will be checking for it. I haven't yet confirmed whether a sprite count overflow on the previous line causes this behaviour, or whether only a sprite dot overflow on the previous line triggers it.

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Thu Mar 26, 2009 11:39 pm

I can confirm what Nemesis says here is absolutely correct.
Nemesis wrote:Note point number 2. Nothing emulates that
Indeed. In Fusion, this is mainly because I jump to the wrong place at the wrong time, and now that I've realised this it's something I plan to fix, when I actually get the chance.

I actually think the 'sprite masking' thing is a side effect of something else/hardware bug rather than a feature. That'd seem to be backed up by the fact Sega didn't document it immediately, and then when they did, they got it completely wrong. It doesn't make any sense at all that it would continue to process, but not draw, the rest of the sprites.

Anyway - I only looked at this briefly, and after TascoDLX's comments I had another quick look at the sprite table. I actually think there is something *else* going on in this game because the phenomenon is still not completely explained...

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Fri Mar 27, 2009 12:04 am

this masking is extremely useful so all info regarding it is highly welcome :)
I stumbled upon it accidently when I was making Glass Breaker MD, I placed all things that weren't active outside screen to x coord 0 and I noticed that my sprites got "sliced"... now I'm using it on statusbar in one game I'm making so pther sprites would not end up on it in any case :D
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Fri Mar 27, 2009 12:15 am

Snake wrote:Anyway - I only looked at this briefly, and after TascoDLX's comments I had another quick look at the sprite table. I actually think there is something *else* going on in this game because the phenomenon is still not completely explained...
You mean... I'm NOT crazy?!? Oh thank god! :D

Eke
Very interested
Posts: 885
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Fri Mar 27, 2009 3:27 pm

Nemesis wrote:
considering all that has been said above, can we say that THIS is the correct sprite masking implementation (i.e ignoring the first sprite for sprite masking) ?
Not quite. My notes from testing:
-Sprite masks at x=0 only work correctly when there's at least one higher priority sprite on the same line which is not at x=0. (This is what Galaxy Force II relies on)
-Sprite masks at x=0 are never effective when not proceeded by a higher priority sprite not at x=0 on the same line, unless the previous line ended with a sprite pixel overflow, in which case, the mask becomes effective for that line only. If that line also causes a dot overflow, the mask will also be effective on the following line, and so on.
-A sprite mask does contribute to the pixel overflow count for a line according to its given dimensions just like any other sprite. Note that sprite masks still count towards the pixel count for a line when sprite masks are the first sprites on a line and are ignored. (This is what Mickey Mania relies on)
-A sprite mask at x=0 does NOT stop the VDP from parsing the remainder of sprites for that line, it just prevents it from displaying any more pixels as a result of the sprites it locates on that line. As a result, a sprite pixel overflow can still occur on a line where all sprites were masked, but there were enough dots in the sprites given after the masking sprite on that line to cause a dot overflow.

Note point number 2. Nothing emulates that, and my test ROM will be checking for it. I haven't yet confirmed whether a sprite count overflow on the previous line causes this behaviour, or whether only a sprite dot overflow on the previous line triggers it.
well, I took some time to analyse MickeyMania sprites on each line
and it seems this is not only a case of handling non-visible sprite for pixel overflow (which genesis plus already did correctly despite the fact the bug still occured)

here's what I got on the incriminated line:
*** LINE 110 (53688 / 53680 cycles) ***
Sprite Parsing line 239 :
0: sprite 20(21): xpos= 0x0, ypos = 0xe9, size=32x32
1: sprite 21(22): xpos= 0x0, ypos = 0xe9, size=32x32
2: sprite 22(23): xpos= 0x0, ypos = 0xe9, size=32x32
3: sprite 23(24): xpos= 0x0, ypos = 0xe9, size=32x32
4: sprite 24(25): xpos= 0x0, ypos = 0xe9, size=32x32
5: sprite 30(31): xpos= 0x104, ypos = 0xd1, size=32x32
6: sprite 35(36): xpos= 0x124, ypos = 0xe1, size=16x24
as you can see, the amount of pixels is less than 320 so no pixel overflow should stop sprite rendering
if we apply rule #1 which genesis plus originally used, the masking should not occur for sprite 30 and 35 which is wrong (same thing for the following lines)


now, if we look at the previous line to check for rule #2:
*** LINE 109 (53158 / 53156 cycles) ***
109(53158): HINT (OFF) pending (0001ac30)
Sprite Parsing line 238 :
0: sprite 2(3): xpos= 0x15a, ypos = 0xdf, size=16x16
1: sprite 20(21): xpos= 0x0, ypos = 0xe9, size=32x32
2: sprite 21(22): xpos= 0x0, ypos = 0xe9, size=32x32
3: sprite 22(23): xpos= 0x0, ypos = 0xe9, size=32x32
4: sprite 23(24): xpos= 0x0, ypos = 0xe9, size=32x32
5: sprite 24(25): xpos= 0x0, ypos = 0xe9, size=32x32
6: sprite 30(31): xpos= 0x104, ypos = 0xd1, size=32x32
7: sprite 35(36): xpos= 0x124, ypos = 0xe1, size=16x24
we can figure that:

- rule #1 applies and sprites 30/35 are indeed masked (same for previous lines)

- there is no sprite overflow neither pixel overflow

so rule #2 does not apply for the next line

sure this is one line among other and values probably differs from frame to frame but this somehow contradicts what you tested, no ?


PS: using the simple rule "sprite masking occurs when a low priority sprite with xpos=0 is found" , which is also the test case used in official Sega document, works for all game I tried so far, including Galaxy Force 2

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Fri Mar 27, 2009 6:16 pm

Unfortunately I've been unable to recreate Mickey Mania's sprite masking on real hardware (at least based on VRAM), but I'm wondering if the game's disabling the display and DMAing through the hsync period is somehow messing with sprite processing? Has anyone done any hacking with the game and a game genie? I only have the latter.

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Fri Mar 27, 2009 8:10 pm

Eke wrote:PS: using the simple rule "sprite masking occurs when a low priority sprite with xpos=0 is found"
I think what Nemesis meant by 'high priority' was a sprite earlier in the list, i.e. high priority with respect to the current sprite - and not the background priority settings, which have no effect.

But I still don't think this is sprite masking. It'd be interesting to hack the ROM to move all those X=0 sprites to X=8 - and see if it still works...
TascoDLX wrote:You mean... I'm NOT crazy?!? Oh thank god! :D
No, Sir, you're still very much on the right side of Genius.
TascoDLX wrote:Unfortunately I've been unable to recreate Mickey Mania's sprite masking on real hardware (at least based on VRAM), but I'm wondering if the game's disabling the display and DMAing through the hsync period is somehow messing with sprite processing? Has anyone done any hacking with the game and a game genie? I only have the latter.
This is the only explanation I have so far. We know that writing to VRAM during active scan is limited, and we know that the writes happen 99% during the visible area, and not during H-SYNC. Therefore, the VDP must be busy doing something important during H-SYNC. So, if you steal the H-SYNC by blanking the screen for most of it, *something* bad is going to happen. I've always wondered about this but have never found a specific effect before...

I think in this case what happens is it halves (or at least cuts down significantly, due to the amount of time stolen from the VDP) the amount of sprite pixels you can show on a line - so only 5 32x32s, rather than 10, are needed.

Obviously testing is needed, I was working on a test ROM to post here but I got sidetracked.

All this is, of course, assuming that this actually does happen on real hardware... there will, of course, be some masking due to the area where there ARE 10 sprites on a line, but it really needs to be watched closely to make absolutely sure ALL the sprites are masked.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sat Mar 28, 2009 1:23 am

I can confirm that the CD version (at least the EUR version) shows exactly the same: same code, same problem in Fusion, but works on real hardware.

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Sat Mar 28, 2009 4:16 am

TascoDLX wrote:I can confirm that the CD version (at least the EUR version) shows exactly the same: same code, same problem in Fusion, but works on real hardware.
Ok, well that's a good start, means I'm not wasting my time ;)
But I still don't think this is sprite masking. It'd be interesting to hack the ROM to move all those X=0 sprites to X=8 - and see if it still works...
..hint hint... ;) You already know how to do this, right? I assume your IPS patch does something like this? Info please, Sir :)

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sat Mar 28, 2009 4:49 am

Snake wrote:
But I still don't think this is sprite masking. It'd be interesting to hack the ROM to move all those X=0 sprites to X=8 - and see if it still works...
..hint hint... ;) You already know how to do this, right? I assume your IPS patch does something like this? Info please, Sir :)
Oh yes, that's right.

019EF4:0008 (BCSA-CAHY) for the sprites at y=233
019F0C:0008 (BCST-CAAN) for the sprites at y=253

Can't get much simpler than that.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Sat Mar 28, 2009 2:42 pm

Ok, so I think I've finished messing around with my sprite test rom for the time being. Here's the ROM:
http://nemesis.hacking-cult.org/MegaDri ... estRom.bin

And here's the source:
http://nemesis.hacking-cult.org/MegaDri ... estRom.zip

I've ended up with a set of 9 tests, which I've engineered to be as evil as possible. Here's a short description of each test:
1. Max sprites per line. This test checks that the correct number of sprites are being displayed on a given line. The first result verifies that the last visible sprite is displayed correctly. The second result verifies that the first discarded sprite is not displayed.
2. Max sprite dots - basic. This test checks that new sprites are being displayed up until the sprite dot count for the line is reached, and that new sprites stop being displayed once the maximum number of sprite dots for the line have been exceeded.
3. Max sprite dots - complex. More thorough than the basic test. Verifies that sprite dot overflow cuts off a sprite partway through when the sprite dot count is reached, and that sprite masks contribute to the dot count, amoung other things.
4. Sprite masking. Verifies that basic sprite masking is working when the sprite mask is not the first sprite on the line.
5. Sprite masking in slot 1. Verifies that sprite masks are ignored when they appear before any other sprites on a line.
6. Sprite masking in slot 1 on dot overflow. Verifies that sprite masks at the beginning of a line become effective when a sprite dot overflow occurs on the previous line.
7/8. Verifies that the emulator is not implementing the non-existant sprite masking mode 2.
9. Max sprites per frame. Verifies that the "sprite limits" for the frame are being followed. Actually, most emulators fail this test. Per-frame sprite limits actually determine the number of entries which are read from the sprite table. Under H32 mode, only the first 64 entries of the table are read. Under H40 mode, only the first 80 entries of the table are read. All sprite entries after these maximums are ignored. If you try and, for example, jump to sprite entry 65 under H32 mode, that sprite entry will not be processed and the sprite list will terminate, even if you jump to it directly from the first sprite.


Here's what you get on the real system:
ImageImage

Here's what you get on Kega:
ImageImage
Kega is the only emulator which passes the complex sprite dot overflow test.

Here's what you get on Gens:
ImageImage
That isn't a pass for the sprite masking on dot overflow. Note the red line at the bottom. This test is conditional on the above test passing, which it doesn't.

Here's what you get on Regen:
ImageImage
Regen is the only emulator which passes the per-frame sprite limits in H32 mode.

Here's what I currently get on my emulator:
ImageImage
Looks like I've got some work to do. Note that I followed the sprite masking mode 2 info, which causes test 8 to fail.

And just for the fun of it, here's Genecyst:
ImageImage
Could be worse.

So yeah, hopefully this test ROM will help everyone to verify their sprite overflow/masking code.

Post Reply