Sprite #0 Hit Problems

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Sprite #0 Hit Problems

Post by 3gengames »

Well, I had sprite 0 added to a little program I am working on, and for some reason, it just doesn't work. I am either on nametable 0 ot 1 in the program, and it switches back and forth, and when the needed info on both is done, will switch to nametable #0. With this code, it is always on nametable 0 and is just perplexing me.

Code: Select all

Sprite0HitTest:
  LDA $2002
  AND #$40
  BEQ Sprite0HitTest
  LDA PPUCTRL
  AND #$FE
  STA $2000
  RTS
I just need it to wait for it, and then write the MSB of the main nametable to 0. It just doesn't work though. I've tried BIT $2002 then BVC to loop it first, but that didn't work. I moved my sprite up and make sure it was on the background white pixel, but that's a no-go either. So I made the sprite the same as what it went over and moved it there and it still doesn't work at all. Would me doing the write in the middle of the scanline be affecting it? I also tried writing scroll too but that didn't do anything either. It's always 0 with this little program so that's not the problem either. So I'm kinda at a loss of what is causing this. If I do just a JSR/RTS from it, it works perfectly and the nametable switches as needed, but with it, it just breaks and stays on the nametable 0. I just can't figure this out. I'd post more code, but I am confident the problem is just this routine. The program even reflects the change when grabbing the characters, this just doesn't work.

Thanks! :)


EDIT:

Got it to work, my problem is that I assumed at NMI being flagged it cleared, but I guess not, as this new code works for anybody else having this problem: [Somewhat aken from Nerdy Nights]

Code: Select all

Sprite0HitTest:
  BIT $2002
  BVS Sprite0HitTest ;Wait for it to be cleared for some reason. That reason is because if we run this inside of vblank, it is not instantly tripped, causing the splitting scroll to never happen.
Sprite0HitLoop:
  BIT $2002
  BVC Sprite0HitLoop ;Wait for it to hit again.
  LDA PPUCTRL
  AND #$FE
  STA $2000
  RTS
Well, for anyone else who has a problem, hope this helps, sorry for posting a topic. Of course, 30 minutes of trying and I figure it out after I post a topic, ugh. So is it cleared at the start of rendering? Is that what happens?
Last edited by 3gengames on Wed Sep 07, 2011 12:24 pm, edited 1 time in total.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

I'm not sure I can contribute with a solution to the problem, but is there any reason why you are not using the overflow flag to check for the hit? Here's what I mean:

Code: Select all

Sprite0HitTest:
	bit $2002
	bvc Sprite0HitTest
You make the loop that waits for a hit as fast as possible, to reduce the jitter that might result from too much timing fluctuation. Even without using the N or V flags it could be faster (I do this for detecting a sprite overflow):

Code: Select all

	lda #$20
WaitSpriteOverflow:
	bit $2002
	beq WaitSpriteOverflow
Anyway, your problem might be that you are starting the wait for the hit too early. When a sprite hit happens, the flag will be set until the start of the next frame, which means that the flag remains set during VBlank. If you finish your VBlank updates and immediately start waiting for the hit, the hit flag will be set from the last frame, causing an instant nametable switch. The trick is to first wait for the flag to be cleared, and then wait for it to be set:

Code: Select all

WaitHitClear:
	bit $2002
	bvs WaitHitClear
WaitHitSet:
	bit $2002
	bvc WaitHitSet
EDIT: Heh, don't you just LOVE when programmers write comments containing sentences like "for some reason"? It shows that they have no clue about what they're doing. This is specially lovely when found in tutorial code. No offense. But yeah, the flag remains set until the end of VBlank.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

Heh, yeah, I'll change it back to that, it just never worked 1st time around, forgot to add it when I got it working. And yeah, I knew what I was doing, just not what was happening technically causing the implementation to be crap. I put that for then until somebody explained why it didn't work, heh. I was about to run out of school anyway, didn't have time to get into detal either. :)

Okay, flag stays set until end of vblank, that's all I really needed to find out I guess to get it working. Thanks!
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Can I nitpick some more? :)
That reason is because if we run this inside of vblank, it is not instantly tripped, causing the splitting scroll to never happen.
It's the exact opposite... If you don't wait for the flag to be cleared, the hit is instantly tripped (because the flag is set from the last frame), causing the split to happen too soon (i.e. before rendering even starts). So, technically, it's not a "split", because rendering already started with the effect applied, but the effect was indeed applied.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

My brain is fried, I'll edit it again later. But in good news, my demo is now done, so now I will have time to just realize how it works now, heh. ;)
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox »

tokumaru wrote:EDIT: Heh, don't you just LOVE when programmers write comments containing sentences like "for some reason"? It shows that they have no clue about what they're doing. This is specially lovely when found in tutorial code.
FYI, there's no comment like that in the tutorial itself.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

thefox wrote:FYI, there's no comment like that in the tutorial itself.
I don't even know which tutorial 3gengames is using, if any. My comment was a reference to GBA Guy's tutorials, those were full of reassuring comments like that. Sorry if it seemed like I was bashing a decent tutorial.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

Nah, I wasn't using any, just trying to make sense of why the code worked and mine didn't. I looked at NN's tutorial after I couldn't figure it out and that's how I figured out that VBlank didn't clear the hit but the next rendering start did.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

The good thing about the sprite 0 hit and the sprite overflow flags being cleared only when rendering starts is that they can be used for detecting the end of VBlank. Of course it would be even better if the VBlank flag stayed up until the end of VBlank (like the the people that programmed Nesticle assumed) instead of being cleared when read, but that's OK.
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

EDIT: Heh, don't you just LOVE when programmers write comments containing sentences like "for some reason"? It shows that they have no clue about what they're doing. This is specially lovely when found in tutorial code. No offense. But yeah, the flag remains set until the end of VBlank.
I think this happens mainly with tutorials that explain only some of the things that are going on (like why you're clearing memory but not why you're setting the I flag and clearing the D flag, or other stuff like that). I'm not really much for tutorials myself for that very reason (that they tend to exclude some essential stuff) but to each his or her own.
Be whatever the situation demands.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

Yeah, agreed. I use the wiki as a reference to hardware and then tutorials if it doesn't work, but I didn't reference a tutorial for Sprite 0 until after I posted this [Because NA is blocked at my school] but it explained it there that the flag isn't cleared until rendering starts, while the wiki fails to state so.
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

Oversight rectified.
Be whatever the situation demands.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

"When the sprite 0 hit flag is set on a frame, it will not be cleared until the vertical blank has ended on the next frame. If attempting to use this flag for raster timing, it is important to ensure that the sprite 0 hit check happens outside of vertical blank, otherwise the CPU will "leak" through and the check will fail. The easiest way to do this is to place an earlier check for D6 = 0."

Very much so, thanks! :)
Post Reply