mamedev / mame

MAME
https://www.mamedev.org/
Other
7.95k stars 1.98k forks source link

Leftover sprites after continue countdown in contra #7957

Open furrtek opened 3 years ago

furrtek commented 3 years ago

Sprites forming the digits of the countdown timer aren't cleared properly after pressing start when it shows 10. Shown here: https://mametesters.org/view.php?id=401

I tried simplifying how the sprite RAM is handled to reflect how the real chip works (no buffer copying involved) but it didn't solve the issue.

The CPU maintains a sprite list starting at 0x1200 in RAM, which is used to generate the sprite RAM data for k007121_2 each new frame. The first few entries seem to always be used for P1's sprite and bullets. When the countdown timer starts, those entries are overwritten by several 8x8 sprites to form the digits.

If the player presses start when the counter is below 10, P1's sprites overwrite enough of the entries to clear the single digit. However if the press happens at 10, more sprites are used so P1's sprites aren't enough anymore to clear both digits. Firing or jumping causes P1's sprite list to expand for a moment, effectively clearing the remaining sprites in a few steps.

It seems that the CPU is rewriting the garbage sprites, since they reappear even if the k007121_2's sprite RAM (0x5000~0x5FFF) is cleared manually. So the bug might not be related to the k007121.

galibert commented 3 years ago

I don't know that hardware (I know the following ones), but Konami tends to follow a line of design. In the later ones there can only be one sprite per priority level because that level tells the chip where to write the sprite data in its internal sprite ram (we don't emulate that correctly, partially because we don't emulate that part of the tbyahhoo protection correctly), and sprites with the lowest priority level (0 or ff, depending on a register) are ignored. Could there be something similar going on?

OG.

On Thu, Apr 15, 2021 at 6:28 AM Furrtek @.***> wrote:

Sprites forming the digits of the countdown timer aren't cleared properly after pressing start when it shows 10. Shown here: https://mametesters.org/view.php?id=401

I tried simplifying how the sprite RAM is handled to reflect how the real chip works (no buffer copying involved) but it didn't solve the issue.

The CPU maintains a sprite list starting at 0x1200 in RAM, which is used to generate the sprite RAM data for k007121_2 each new frame. The first few entries seem to always be used for P1's sprite and bullets. When the countdown timer starts, those entries are overwritten by several 8x8 sprites to form the digits.

If the player presses start when the counter is below 10, P1's sprites overwrite enough of the entries to clear the single digit. However if the player presses start at 10, more sprites are used so P1's sprites aren't enough to clear both digits. Firing or jumping causes P1's sprite list to expand for a moment, effectively clearing the remaining sprites.

It seems that the CPU is rewriting the garbage sprites, since they reappear even if the k007121_2's sprite RAM (0x5000~0x5FFF) is cleared manually. So the bug might not be related to the k007121.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mamedev/mame/issues/7957, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACGSF4LOBWEGIMUILU4DPATTIZTOVANCNFSM426U7XOQ .

furrtek commented 3 years ago

If I understood correctly, the k007121 only has global priority settings and individual priority bits for scroll layer tiles only. The sprites seem to be rendered one after the other in the order they are in sprite RAM.

Contra clears unused sprites by setting their Y position to 0xF0. For a moment I thought that could be a sprite list end code, since stopping sprite rendering with that condition solved the countdown issue, but that also caused some blinking when sprites were moved so it must not be the right solution. I also can't find how a sprite attribute byte could stop the parsing counter in the chip's schematics.

About the sprite RAM double buffering, it's actually very simple: reg 3 bit 3 selects which buffer is used for rendering (0000-07FF or 0800-0FFF). The bit is toggled each frame, so the CPU can load the free buffer while the other is being used. I'm not 100% sure if the CPU can always access both buffers, or only the free one.

smf- commented 3 years ago

Could the sprite hardware also have an auto clear (either always or based on a flag?)

On 15/04/2021 23:21, Furrtek wrote:

About the sprite RAM double buffering, it's actually very simple: reg 3 bit 3 selects which buffer is used for rendering (0000-07FF or 0800-0FFF). The bit is toggled each frame, so the CPU can load the free buffer while the other is being used. I'm not 100% sure if the CPU can always access both buffers, or only the free one

galibert commented 3 years ago

Seems like furrtek already tested that and the cpu happily rewrites the bad sprites...

OG.

On Fri, Apr 16, 2021 at 11:24 AM smf- @.***> wrote:

Could the sprite hardware also have an auto clear (either always or based on a flag?)

On 15/04/2021 23:21, Furrtek wrote:

About the sprite RAM double buffering, it's actually very simple: reg 3 bit 3 selects which buffer is used for rendering (0000-07FF or 0800-0FFF). The bit is toggled each frame, so the CPU can load the free buffer while the other is being used. I'm not 100% sure if the CPU can always access both buffers, or only the free one

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mamedev/mame/issues/7957#issuecomment-821045160, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACGSF4OZC5UU7YMGEK5L2ELTI763DANCNFSM426U7XOQ .