Mickey Mania emulator comparison
Moderator: BigEvilCorporation
Consider the way Galaxy Force 2 uses sprite masking. It must be able to mask out a single line. But, the smallest possible sprite covers eight lines. So, if it stopped on the first sprite (xpos = 0), it couldn't mask less than eight consecutive lines at a time.
Not checking the first sprite for xpos = 0 allows for the possibility of an overlap where only one line of an off-screen sprite (xpos = 1) is processed before that of the masking sprite (xpos = 0). It's certainly not the most versatile system but it allows for that kind of detail while keeping things relatively simple.
Not checking the first sprite for xpos = 0 allows for the possibility of an overlap where only one line of an off-screen sprite (xpos = 1) is processed before that of the masking sprite (xpos = 0). It's certainly not the most versatile system but it allows for that kind of detail while keeping things relatively simple.
It's not as simple as the first sprite being ignored for sprite masking. I've started writing a "Sprite masking/overflow test rom", and I'm currently debugging it on the hardware. Yes, if you have a masking sprite at x=0 as the first sprite on a line, then follow it by a visible sprite, the masking sprite will not take effect, and the second sprite will be visible. It's not only the first sprite that causes this however. According to tests I did last night, if you have two masking sprites at x=0 at the start of a line, masking still doesn't take effect. We know that masking does take effect with 5 masking sprites at the start of a line however, as this is what Mickey Mania uses, and we know that if you have a sprite with x=1 (or probably anything that's not 0) at the start of the line, and follow it by a sprite with x=0, masking does take effect, as this is what Galaxy Force II does (I've confirmed there's no switch to a "mode 2" sprite masking for the remainder of the frame).
I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware. I'll be doing more tests today.
I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware. I'll be doing more tests today.
No, there doesn't. It's much simpler than Charles describes.TascoDLX wrote:So, I highly doubt there exists a "mode 2".
Never seen this problem before - and looking at the shots, and the description of what it's doing/what's happening... I have no idea at all why this wouldn't work in Fusion already. It must be a very silly bug. When I actually get a chance to look at my code (
I kinda figured there was more to it. I haven't a clue why Mickey Mania uses the five masking sprites instead of just masking the normal way (as it appears to do for the top border).Nemesis wrote:It's not as simple as the first sprite being ignored for sprite masking.
I hope your tests end better than mine did, though I am very limited in my setup. The only thing I managed to find is that the horizontal size of the masking sprite likely gets added to the pixel count of the line (I didn't get a chance to confirm that). Other than that, I couldn't get hardware to do anything different than Fusion does, so I don't know why Mickey Mania works right.Nemesis wrote:I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware. I'll be doing more tests today.
Nemesis wrote:It's not as simple as the first sprite being ignored for sprite masking.
Both incorrectNemesis wrote:I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware.

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.
I can see how that's true for y=253 but how is it true for y=233? I must be missing something.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.
EDIT: Nevermind -- I misunderstood. So very tired.
That's a relief.Snake wrote:I can confirm that sticking multiple sprites at zero does nothing. Neither does sticking the last one at 1,1.

Last edited by TascoDLX on Thu Mar 26, 2009 5:54 pm, edited 1 time in total.
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.Snake wrote:Nemesis wrote:It's not as simple as the first sprite being ignored for sprite masking.Both incorrectNemesis wrote:I don't think any of the current implementations of sprite masking are fully emulating the behaviour of the hardware.
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.

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

you're right... I didn't notice before because I didn't wait enough but the bug was indeed hereTascoDLX wrote: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:mickagame wrote:It's like the sprite with x_pos = 0 is the first sprite of the list...Code: Select all
if(xpos == 0 && sol_flag) return; /* stop rendering sprites */ sol_flag = 1;

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;
Not quite. My notes from testing: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) ?
-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.
I can confirm what Nemesis says here is absolutely correct.
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...
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.Nemesis wrote:Note point number 2. Nothing emulates that
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...
-
- Very interested
- Posts: 2452
- Joined: Tue Dec 05, 2006 1:37 pm
- Location: Estonia, Rapla City
- Contact:
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

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

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

http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen
well, I took some time to analyse MickeyMania sprites on each lineNemesis wrote:Not quite. My notes from testing: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) ?
-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.
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:
as you can see, the amount of pixels is less than 320 so no pixel overflow should stop sprite rendering*** 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
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:
we can figure that:*** 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
- 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
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.