Sprite #0

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Sprite #0

Post by WedNESday »

I am finding it hard to get my Sprite #0 hit detection to work.

Here are the circumstances that I set bit 6 of 2002 under;

if( Sprite == 0 && Pixel != Transparent )
SetFlag;

If the collision is behind the background then I have no problem. But if the sprite is in the foreground (like the 2nd NT of Super Mario.) then there seems to be an error. NEStress give me an error for my code. Anything else that I should know?
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Post by Anes »

i have problems too, but you should do:

Code: Select all


if( Sprite == 0 && Pixel != Transparent  && Background != Transparent) 
SetFlag; 

ANes
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

Yeah, I am already doing that, but for some unknown reason collision detection is a bit buggy. Games that seems to use a bg #0 sprite are ok but the other way around seems to fail. I'll keep trying.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

The sprite 0 hit flag is raised when a non-transparent BG pixel "hits" a non-transparent sprite 0 pixel. The logic ANes provided gives the general idea.

As for timing it... you must know that each scanline consists of 341 PPU cycles... the first 256 of which render pixels on the scanline. So if sprite 0 hit happens on, say, pixel 120 of the scanline... then $2002.6 is raised on PPU cycle 120 of the scanline (on an NTSC system, this would translate to CPU cycle 40 of the scanline -- 113.6666667 CPU cycles per scanline).

Rouding that time off to the start or end of the scanline might cause the timing to go off in some games.
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

Because WedNESday renders a scanline and THEN goes back and draws the sprites I suppose tha this may have an effect on certain games. Would it explain why NEStress gives me an error then?
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

How you render doesn't make any difference at all. What matters is that the game gets the flag set when it expects it. I'm not exactly sure what triggers a NEStress error... so I can't really help you with that.
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Post by Anes »

be carefull with nestress, i when i was starting i supossed nestress was very fiable, but it is not. As a starting point for cpu emulation and ppu emu is fine, but... i remember when nestress throw me constantly that ADC Overflow operation was OK and some games have errors cos it wasnt at all OK.
Just an advice.

Disch wants to say that "when the game exepct it" you can calculate it of how many cpu cycles has to pass to sprite hit flag goes up
and if your emu ppu timing is correct or in other way nearly exact calculating the cycles to pass to hit flag to set is cool.

But, you mentioned before you dont want or you are not interested in Brad Taylor "2C02 Referece" wich is a crucial doc to have a good understading on NES Architecture for (al least at a functional level, which is fine for emu dev) a good emulation (altought mmc3 topic is bad).
Understading that doc will clarify a lot of your doubts (which are already explained there).
I tell you becouse when i was starting my project a lot of things where unclarify for me. So i talk you from my expirience and thanks to other people who helped me here in the forum.

EOP
ANes
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

After doing some testing, FCE Ultra is the only emulator that seems to get an ok from NEStress, even though there seems to be no issues with other emulators and their hit detection (i.e. games that use it play just fine).

Let's just clarify one thing. If a sprite's pixel (i.e. 1-3 in the palette indicies (NOT including att colour?)) is also on the same pixel as a background pixel (i.e. !Transparent) then the hit flag is set. Is this correct?

This is now the only graphical issue I have left with my emulator and I am now very keen to get onto memory mapping and other things. So please help!!!
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

The flag is set when a non-transparent BG pixel is to be rendered on the same space a non-transparent sprite-0 pixel. Given the following graphics:

Code: Select all

sprite:        background:    Sprite 0 would hit on this pixel:
....xxxx       xxxx....       ........
....xxxx       xxx.....       ........
....xxxx       xx......       ........
....xxxx       x.......       ........
xxxxxxxx       ........       ........
xxxxxxxx       ...x....       ...X....
xxxxxxxx       ..xxx...       ........
xxxxxxxx       .xxxxx..       ........
('x' denotes a non-transparent pixel, '.' denotes a transparent pixel)

Sprite 0's background/foreground priority does NOT matter. It can be rendered in front or behind the background.... it will not affect the hit flag at all. Attribute data and contents of the palette also do not matter.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Don't set it if the only overlap occurs with x=255. This breaks RTC Demo at the raster bars but that's broken on HW as well.

Don't set it if the only overlap occurs with x in [0..7] if sprites or the BG is masked.
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

Here is the code that sets the hit detection flag.

if( !Transparent )
if( Background && Sprites == Visible )
if( SpriteNo. == 0 )
if( !( !( Sprite Clipping && Spritex < 8 ) )
if( Spritex != 255 )
if( BgPixel != Transparent )

SetFlag

(Phew...)

Can anyone see what is wrong with this code?
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Post by Anes »

First: DONT TRUST NESTRESS, you should only trust in games that need sprite 0 hit if they work ok (smb, castlevania, etc). Its difficult (i know) to have an accurate engine for all games.

Second:
This can help for you scanline based engine:

- ONE scanline takes 341 / 3 = 113.67~ CPU Cycles ("~" means approx.)
- You have to take into account how much cpu cycles takes a scanline to be rendered. It should be 256 ppu cyles / 3 = 85 cpu cycles.
- And (341 - 256) ppu cycles / 3 = 28.3~ cpu cycles. You should do NOTHING since it is HBLANK

Third:
Instead of setting hit flag when the ppu is rendering you can calculate how many cycles will take until it will be "set" this can be done in this way:

- There are 341/3 cpu cycles per scanline
- There are 240 scanlines rendered (including the dummy one)
- You know sprite zero is in scanline (going from 0 to 240) 17 (Y Position) , but there are only pixels in scanline 19!! , but you have to know that Y pos is programmed one scanline minus the scanline it will appear on, so sprite 0 will render in scanline 20!, now you can do something like this:

20 scanlines * 341 ppu cycles = 6820 ppu cycles will take sprite hit since scanline 0 starts render to set the hit flag, which equals to: 6820 ppu cycles / 3 = 2273.34~ cpu cycles. After your cpu cycles counter is >= of that value you should set the 2002.5 flag.

Please correct me if im wrong.

I know its not the most accurate way of calculating sprite zero hit but you can take it like a begining.
ANes
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

I know that people say the you should not trust NEStress and all that. One emulator DOES actually pass the test in NEStress and that is FCE Ultra. So it is possible to get a pass. WedNESday does not process graphics in the way that you have described.

Here is how it works for WedNESday;

(Scanline for Scanline basis)

Allow 113 CC of CPU time;
Draw Background;
Go back and Draw Sprites

I know that this method is unconventional but it is very simple to emulate. Could this be affecting the hit detection?
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

WedNESday wrote: Allow 113 CC of CPU time;
Draw Background;
Go back and Draw Sprites

I know that this method is unconventional but it is very simple to emulate. Could this be affecting the hit detection?
If you're setting the sprite 0 hit flag when you draw the sprites (according to that layout)... then yes.

Say, for example, Sprite 0 hit happens on pixel 90 of the scanline. Normally this will mean that the Sprite 0 hit flag will be raised on PPU cycle 90 of the scanline (90/3 = CPU cycle 30). If you're running the CPU for a full scanline before looking for sprite 0 hit.. then the flag will be raised after the scanline is complete... on CPU cycle 113 of the scanline... 83 CPU cycles later than it should.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I just polished my sprite 0 hit test ROM and verified each result code by breaking my emulator in that manner. It currently only checks with an accuracy of 4 CPU clocks (12 PPU clocks). It tests time it's cleared each frame, time it's set at upper-left corner, time for each PPU pixel, and time for each PPU scanline. This should find most problems with the timing of it.

sprite_hit_timing.zip

I've improved my test framework so it now displays a bit more text on screen. The result codes are listed at the beginning of the asm source code included.
Post Reply