Mickey Mania emulator comparison

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

mickagame
Very interested
Posts: 228
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Sat May 04, 2013 8:14 pm

I read today this old post about sprite masking in mickey mania :-)
So the conclusion was the sprite aren't display in some lines because the vdp don't have time to fetch all sprite data because of the display is re-enabled too late?
So there is no sprite masking effect in this game?

Mask of Destiny
Very interested
Posts: 591
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Sun May 05, 2013 12:22 am

The VDP is busy throughout pretty much the entire line, including during the HBLANK interval, with the exception of a handful of external access slots. So if you disable the display for part of the line, something will be sacrificed. If you do it inside the border area/HBLANK the think you will lose are some/all of the sprites.

So it's not so much that the display is re-enabled too late so much as the fact that it disables the display at all. Other than that your summary is correct.

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

Post by Nemesis » Tue May 14, 2013 4:21 am

For a running example, I emulate this accurately in Exodus (http://www.exodusemulator.com), although you'll see that the display gets disabled slightly too early on the line due to a current lack of microcode-level bus timing emulation, giving some minor corruption on the right side of the screen. I'm hoping to fix this soon.

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

Post by Eke » Mon Sep 09, 2013 9:17 pm

Some more thinking about this:
TascoDlx wrote: However, since the VDP fetches the majority of the sprite patterns during this time, and since any scheduled fetching is NOT performed while the display is disabled, this severely reduces the number of sprite pixels that can be displayed on each line. Mickey Mania uses this effect to mask background sprites on these lines.

From experimentation, it appears the number of sprite pixels that may be displayed on each effective line is around 120-128. The limit is not that noticeable during gameplay as it usually only occurs on a few lines for a short time. For lines that don't have foreground sprites on them, the limit is hit by the masking sprites (160 sprite pixels).
It appears the recently released Overdrive demo is somehow using similar feature to hide some sprites (the infamous "your emulator suxx" text :wink: )

Like with Mickey Mania, display is disabled at the start of HBlank for a few cycles necessary to one CRAM palette DMA. The number of updated palette entries is different (15 vs 16 in Mickey Mania) but the period during which display is disabled is roughly the same (350-400 MCycles in my emulator).

The difference however is that, contrary to Mickey Mania, twhen there are preceding sprites on the same line (the "spinning" titan message), the amount of rendered sprite pixels does not hit the sprite "pixel" limit resulting from the display off period (~128 pixels according to TascoDLX tests, 144-160 pixels theoretically when using Nemesis timings table). Also, there are lines where the only sprites are the ones that should be masked !

My theory is that there is something more going on during HBLANK than just filling sprite line buffer and that this is actually sprite Ypos/Size pre-processing from internal cached SAT. The sprites that are supposed to be masked are indeed located at the end of the linked sprite list and it seems that disabling display during the start of HBLANK not only reduce the number of sprite pixels rendered for the upcoming line but also reduces the number of sprites (usually 80) that can be parsed from the internal SAT cache for the next line.

Note that this also fits with this initial observation from TascoDLX, except the number of "masking" sprites is not relevant, the indexes of the "masked" sprites in parsed internal SAT are.
TascoDlx wrote:In the sprite table, the ypos and size of the "masking" sprites are irrelevant. The only item I'd expect to be relevant is the link. That would indicate that the number of "masking" sprites is what's important.

Mask of Destiny
Very interested
Posts: 591
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Mon Sep 09, 2013 10:33 pm

Eke wrote:
My theory is that there is something more going on during HBLANK than just filling sprite line buffer and that this is actually sprite Ypos/Size pre-processing from internal cached SAT. The sprites that are supposed to be masked are indeed located at the end of the linked sprite list and it seems that disabling display during the start of HBLANK not only reduce the number of sprite pixels rendered for the upcoming line but also reduces the number of sprites (usually 80) that can be parsed from the internal SAT cache for the next line.
Based on where rendering resumes after VBLANK, I'm fairly certain SAT cache scanning starts on the 4th sprite rendering slot. It needs to be complete (or at least mostly complete) before the first slot that reads the uncached portion of the SAT (slot 53 if you consider the first sprite render slot as 0). My current assumption is that the VDP can scan 2 sprites per slot, but I've been meaning to test that and try to verify exactly which slots have sprite scanning.

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

Post by TascoDLX » Tue Sep 10, 2013 2:09 pm

Eke wrote:The difference however is that, contrary to Mickey Mania, twhen there are preceding sprites on the same line (the "spinning" titan message), the amount of rendered sprite pixels does not hit the sprite "pixel" limit resulting from the display off period (~128 pixels according to TascoDLX tests, 144-160 pixels theoretically when using Nemesis timings table). Also, there are lines where the only sprites are the ones that should be masked !
Correct, but there's something else worth mentioning. There is an important difference between the methods of Overdrive and Mickey Mania. Overdrive actually aligns the DMA operation. It fills the VDP FIFO and then NOPs a bit so it basically knows at what pixel the transfer occurs. (In MM, if you move the transfer period into the active display, you can see the starting position varies wildly from line to line.) Also, during the "YOUR EMULATOR SUXX" scene, the number of sprites is fixed, so the break occurs at the same point in the list every time (though there are a couple buffer sprites, so it could vary a little).

Here's where things get interesting. Obviously we thought something was strange about the way MM is masking the sprites. It just so happens that MM is double masking the sprites. The programmers may have been able to figure out the masking caused by disabling the display, but it's not totally reliable it that situation -- there's just too much fluctuation. Even with 10 buffer sprites added at position (0,0), there are still some places (generally with few sprites in the scene) where the moose bleeds through a bit and such. However, if you move those sprites down and max size them so they hit the reduced pixel limit on those lines, it's perfect.
Eke wrote:My theory is that there is something more going on during HBLANK than just filling sprite line buffer and that this is actually sprite Ypos/Size pre-processing from internal cached SAT. The sprites that are supposed to be masked are indeed located at the end of the linked sprite list and it seems that disabling display during the start of HBLANK not only reduce the number of sprite pixels rendered for the upcoming line but also reduces the number of sprites (usually 80) that can be parsed from the internal SAT cache for the next line.

Note that this also fits with this initial observation from TascoDLX, except the number of "masking" sprites is not relevant, the indexes of the "masked" sprites in parsed internal SAT are.
Indeed, though the number of "masking" sprites is not entirely irrelevant. It's just part of a solution for this particular case.

Also, in case you missed it, I noted during my tests that pushing the transfer into the active display really messed up the sprite lines. It seems to interfere with the drawing of the sprite line in an ugly sort of way, partially because of the unaligned transfer. I would be curious to see how it reacted with a short, aligned transfer instead.

Kabuto
Interested
Posts: 27
Joined: Sun Aug 25, 2013 6:56 pm

Post by Kabuto » Tue Sep 10, 2013 3:36 pm

A few comments about this scene:
* Yes, it tries to align the start. But there's the Z80 which is randomly stealing cycles and thus there's still a lot of randomness in the timing. I aligned it to the earliest position that doesn't create bugs on real hardware to reduce the number of bugs due to delays caused by the Z80 accessing the ROM.
* It appears that on real MD the "display enable" has to wait until the FIFO is empty (or is it queued in as well?). In Exodus, re-enabling the display after the DMA causes the last few DMA words to be written as if the display wasn't disabled. Inserting NOPs before re-enabling the display gave an improvement in Exodus but not on real hardware (only made it worse IIRC).
* Also, Z80 seems to steal way more cycles on real hardware than it does in Exodus.
* With Z80 disabled and timing aligned carefully there can be up to 30 sprites visible at once with the next 2 sprites having some lines flickering into existence now and then (this is why they're not used at all in this effect). Having unreliable timing due to Z80 made the last ones of the first 30 sprites flickering a bit as well, so I arranged sprites so that those that are flickering a bit are used where sprites appear/disappear behind the ball where this flickering isn't apparent.
* Also, with Z80 disabled timing is still varying by 2 or 3 pixels in a pattern that looks like (a*rasterline+b)%c with a,b,c being constants as one would expect with 2 clocks running asynchronously. However, it's perfectly aligned in exodus.

Mask of Destiny
Very interested
Posts: 591
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Tue Sep 10, 2013 6:25 pm

Kabuto wrote:* It appears that on real MD the "display enable" has to wait until the FIFO is empty (or is it queued in as well?).
There's a bit of latency between when the write happens and when the display is actually disabled. I doesn't matter whether the FIFO is full or emtpy.
Kabuto wrote:In Exodus, re-enabling the display after the DMA causes the last few DMA words to be written as if the display wasn't disabled. Inserting NOPs before re-enabling the display gave an improvement in Exodus but not on real hardware (only made it worse IIRC).
Because DMA transfers go through the FIFO, it's possible for the DMA to complete before all the data is actually written to the target RAM. Between the latency on the display enable and the slowness of the 68K relative to the VDP its hard to re-enable the display too early. Maybe you can run into trouble with VRAM since it's byte-wide (and thus the FIFO takes at least twice as long to empty), but for CRAM (and presumably VSRAM) I haven't seen it be an issue on real hardware.

One thing I have seen as an issue on real hardware is disabling the display as part of a long-word write that also writes the first word of the DMA command. For some reason, it seems that the display is never disabled in that case.

Post Reply