Sprite #0
Moderator: Moderators
Sprite #0
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?
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?
i have problems too, but you should do:
Code: Select all
if( Sprite == 0 && Pixel != Transparent && Background != Transparent)
SetFlag;
ANes
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.
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.
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
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
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!!!
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!!!
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:
('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.
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.. ........
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.
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.
Don't set it if the only overlap occurs with x in [0..7] if sprites or the BG is masked.
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.
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
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?
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?
If you're setting the sprite 0 hit flag when you draw the sprites (according to that layout)... then yes.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?
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.
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.
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.