Micro Machines glitches
Moderator: Moderators
Micro Machines glitches
Shaky horizontal lines appear on the right-side of some of the screens of Micro Machines in my emulator. The game itself seems to play okay though.
The Tricky-to-emulate games lists mentions, "Micro Machines requires correct values when reading PPU $2004 (OAMDATA) during rendering." What does this refer to exactly?
The Tricky-to-emulate games lists mentions, "Micro Machines requires correct values when reading PPU $2004 (OAMDATA) during rendering." What does this refer to exactly?
Re: Micro Machines glitches
It's referring to the behavior of $2004 reads during visible scanlines described here: http://wiki.nesdev.com/w/index.php/PPU_ ... evaluation
get nemulator
http://nemulator.com
http://nemulator.com
Re: Micro Machines glitches
I carefully implemented that logic (see here), but I'm still getting the Micro Machines glitches. Did I miss something on that page?James wrote:It's referring to the behavior of $2004 reads during visible scanlines described here: http://wiki.nesdev.com/w/index.php/PPU_ ... evaluation
Re: Micro Machines glitches
Wait a second. I downloaded a different ROM and this one wants to use mapper 71 instead of mapper 2. WTF?
I'll implement that mapper and see what happens...
Edit: Unfortunately, implementing mapper 71 did not help. The graphical glitches still look the same.
I'll implement that mapper and see what happens...
Edit: Unfortunately, implementing mapper 71 did not help. The graphical glitches still look the same.
Re: Micro Machines glitches
re: mapper 2 vs. 71: http://wiki.nesdev.com/w/index.php/INES_Mapper_071
As far as $2004 reads go, this (hack) should be enough to make Micro Machines work:
I don't completely understand what the game is doing here, but it seems that the whole purpose of these reads is to adjust timing:
The only impact that BMI can have is on the number of clock cycles consumed, so make sure that you're accounting for the extra clock cycle on a taken branch.
As far as $2004 reads go, this (hack) should be enough to make Micro Machines work:
Code: Select all
if (rendering)
{
if (current_cycle < 64)
return_value = 0xFF;
else if (current_cycle < 256)
return_value = 0x00;
else if (current_cycle < 320)
return_value = 0xFF;
else
return_value = sprite_buffer[0];
}
Code: Select all
...
FD6E: BIT $2004
FD71: BMI $FD73
FD73: PHA
...
get nemulator
http://nemulator.com
http://nemulator.com
Re: Micro Machines glitches
Thanks. That did not solve the problem, but it did have a noticeable effect. It reduced the amount of glitching.
What's the concept behind the hack? Is there an accurate way to do this?
What's the concept behind the hack? Is there an accurate way to do this?
Re: Micro Machines glitches
Micro Machines reads $2004 around dot 320. If the read occurs before dot 320, it needs to see a value with the high bit set (implemented properly, the read would return $FF because it would take place while the PPU is fetching from an empty sprite slot). If the read occurs >= dot 320, it needs to see a value without the high bit set (which it does, because the first byte in secondary OAM is < 0x80).zeroone wrote:What's the concept behind the hack?
Yep. Implement it as described on the wiki.Is there an accurate way to do this?
get nemulator
http://nemulator.com
http://nemulator.com
Re: Micro Machines glitches
James, thanks for the reply.
Does that mean that $2004 returns the contents of secondary OAM?
Why will $2004 return 0 between PPU cycles 64 and 256?
I implemented as close to the wiki description as I could, but I must be misinterpreting something.James wrote:Yep. Implement it as described on the wiki.
I see the wiki says:James wrote:implemented properly, the read would return $FF because it would take place while the PPU is fetching from an empty sprite slot
Cycles 1-64: Secondary OAM (32-byte buffer for current sprites on scanline) is initialized to $FF - attempting to read $2004 will return $FF.
Does that mean that $2004 returns the contents of secondary OAM?
You also seem to be implying that $2004 returns the contents of secondary OAM. What address/offset into secondary OAM is accessed (if it is accessed)?James wrote:If the read occurs >= dot 320, it needs to see a value without the high bit set (which it does, because the first byte in secondary OAM is < 0x80).
Why will $2004 return 0 between PPU cycles 64 and 256?
Re: Micro Machines glitches
$2004 reads return the contents of secondary OAM during these phases:zeroone wrote:Does that mean that $2004 returns the contents of secondary OAM?...You also seem to be implying that $2004 returns the contents of secondary OAM. What address/offset into secondary OAM is accessed (if it is accessed)?
wiki wrote: Cycles 257-320: Sprite fetches (8 sprites total, 8 cycles per sprite)
1-4: Read the Y-coordinate, tile number, attributes, and X-coordinate of the selected sprite from secondary OAM
5-8: Read the X-coordinate of the selected sprite from secondary OAM 4 times (while the PPU fetches the sprite tile data)
For the first empty sprite slot, this will consist of sprite #63's Y-coordinate followed by 3 $FF bytes; for subsequent empty sprite slots, this will be four $FF bytes
Cycles 321-340+0: Background render pipeline initialization
Read the first byte in secondary OAM (while the PPU fetches the first two background tiles for the next scanline)
$2004 reads at that time will expose what's happening during sprite eval. If you're referring to my code, it's not accurate behavior.zeroone wrote:Why will $2004 return 0 between PPU cycles 64 and 256?
Somebody who has implemented proper sprite eval logic can probably explain it better.
Oh, one more thing: I'm using the "old" PPU cycle terminology: e.g., idle cycle = 340, not 0, so adjust accordingly if you're not.
get nemulator
http://nemulator.com
http://nemulator.com
Re: Micro Machines glitches
What address of secondary OAM does it return?James wrote:$2004 reads return the contents of secondary OAM during these phases
By returning what exactly?James wrote:$2004 reads at that time will expose what's happening during sprite eval.
Re: Micro Machines glitches
Here is the $2004 read according to Nintendulator:
The Sprite array appears to represent both primary and secondary OAM.
According to the wiki:
Edit: On a side note, FCEUX 2.2.1 looks more screwed up than my emulator:
Code: Select all
int __fastcall Read4 (void)
{
if (IsRendering)
readLatch = Sprite[SpritePtr];
else readLatch = Sprite[SprAddr];
return readLatch;
}
According to the wiki:
Can someone please provide more information? The wiki seems incomplete.Reading OAMDATA while the PPU is rendering will expose internal OAM accesses during sprite evaluation and loading; Micro Machines does this. It used to be thought that reading from this register wasn't reliable, however more recent evidence seems to suggest that this is solely due to corruption by OAMADDR writes. In the oldest instantiations of the PPU, as found on earlier Famicoms, this register is not readable. It's not known exactly which revision of the 2C02 added the readability—it is certainly absent in the RP2C02C, and present by the RP2C02G.
Edit: On a side note, FCEUX 2.2.1 looks more screwed up than my emulator:
Re: Micro Machines glitches
FCEUX is pretty bad at emulating these kinds of obscure quirks.
Re: Micro Machines glitches
If the rendering is disabled and the PPU address is between $3F00-$3F1F, that's the color it outputs.
Re: Micro Machines glitches
Can you elaborate on this?If the rendering is disabled and the PPU address is between $3F00-$3F1F, that's the color it outputs.
Re: Micro Machines glitches
- If rendering is disabled, and the current VRAM address is $0000-$3EFF, the PPU will output the color at $3F00.
- If rendering is disabled, and the current VRAM address is $3F00, the PPU will output the color at $3F00.
- If rendering is disabled, and the current VRAM address is $3F01, the PPU will output the color at $3F01.
- If rendering is disabled, and the current VRAM address is $3F02, the PPU will output the color at $3F02.
- If rendering is disabled, and the current VRAM address is $3F03, the PPU will output the color at $3F03.