Micro Machines glitches

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Micro Machines glitches

Post by zeroone »

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.

Image

Image

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?
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: Micro Machines glitches

Post by James »

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
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

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
I carefully implemented that logic (see here), but I'm still getting the Micro Machines glitches. Did I miss something on that page?
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

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.
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: Micro Machines glitches

Post by James »

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:

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];
}
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:

Code: Select all

...
FD6E:	BIT $2004
FD71:	BMI $FD73
FD73:	PHA
...
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.
get nemulator
http://nemulator.com
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

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?
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: Micro Machines glitches

Post by James »

zeroone wrote:What's the concept behind the hack?
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).
Is there an accurate way to do this?
Yep. Implement it as described on the wiki.
get nemulator
http://nemulator.com
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

James, thanks for the reply.
James wrote:Yep. Implement it as described on the wiki.
I implemented as close to the wiki description as I could, but I must be misinterpreting something.
James wrote:implemented properly, the read would return $FF because it would take place while the PPU is fetching from an empty sprite slot
I see the wiki says:
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?
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).
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)?

Why will $2004 return 0 between PPU cycles 64 and 256?
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: Micro Machines glitches

Post by James »

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)?
$2004 reads return the contents of secondary OAM during these phases:
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)
zeroone wrote:Why will $2004 return 0 between PPU cycles 64 and 256?
$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.

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
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

James wrote:$2004 reads return the contents of secondary OAM during these phases
What address of secondary OAM does it return?
James wrote:$2004 reads at that time will expose what's happening during sprite eval.
By returning what exactly?
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

Here is the $2004 read according to Nintendulator:

Code: Select all

int	__fastcall	Read4 (void)
{
	if (IsRendering)
		readLatch = Sprite[SpritePtr];
	else	readLatch = Sprite[SprAddr];
	return readLatch;
}
The Sprite array appears to represent both primary and secondary OAM.

According to the wiki:
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.
Can someone please provide more information? The wiki seems incomplete.

Edit: On a side note, FCEUX 2.2.1 looks more screwed up than my emulator:

Image

Image
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Micro Machines glitches

Post by tokumaru »

FCEUX is pretty bad at emulating these kinds of obscure quirks.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Micro Machines glitches

Post by Zepper »

If the rendering is disabled and the PPU address is between $3F00-$3F1F, that's the color it outputs.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Micro Machines glitches

Post by zeroone »

If the rendering is disabled and the PPU address is between $3F00-$3F1F, that's the color it outputs.
Can you elaborate on this?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Micro Machines glitches

Post by tepples »

  • 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.
It stores a table of colors at $3F00-$3F1F and expects to be able to switch to the next color by reading one byte from or writing one byte to the VRAM data port, which advances the VRAM address by 1.
Post Reply