Page 1 of 1

When is the collision bit cleared?

Posted: Wed May 11, 2016 9:58 am
by cero
The status register has a sprite collision bit. When exactly is it cleared? sega2f is silent on this one.

Re: When is the collision bit cleared?

Posted: Thu May 12, 2016 6:03 am
by Mask of Destiny
I've been meaning to test this to make sure my implementation matches the hardware. I just wrote and ran a quick test. As you might expect, the flag appears to be set during sprite rendering when the collision is detected. The flag is cleared immediately after reading from the status register. In theory, his allows you to determine exactly which lines have sprite collisions. In practice this is a bit messy as you don't want to poll the flag when sprite rendering is happening, but that is exactly what happens if you poll from an H-Interrupt handler.

Re: When is the collision bit cleared?

Posted: Thu May 12, 2016 7:43 am
by cero
So it is not cleared any time during vblank? (automatically, that is)

Re: When is the collision bit cleared?

Posted: Thu May 12, 2016 5:33 pm
by Mask of Destiny
I did not explicitly test that. I'll have to check this evening after work.

Re: When is the collision bit cleared?

Posted: Thu May 12, 2016 7:23 pm
by cero
Thanks for going to the trouble.

Re: When is the collision bit cleared?

Posted: Fri May 13, 2016 8:24 am
by cero
Would you know if the vblank bit also behaves like that - cleared on read? If so, it could explain my DMA issues, and would mean the SGDK waitVSync function is buggy. But would need to know exactly when it's set and when it's cleared.

Re: When is the collision bit cleared?

Posted: Fri May 13, 2016 9:45 am
by Stef
VBlank bit remains set during all vblank (hopefully), i guess you're mistaking with the "VInt occured" bit which is cleared when you read it if i remember correctly.

Re: When is the collision bit cleared?

Posted: Fri May 13, 2016 1:25 pm
by Sik
Yeah there are two flags, the vblank bit is set during all of vblank (and while display is disabled, watch out!) while the interrupt bit (the so-called F flag) gets cleared after reading. Note that the F flag was inherited from the TMS9918A, which may explain why it isn't well documented by Sega. (also I don't remember if it also got set for hblank interrupts, which kind of ruins it if you're doing raster effects?)

Re: When is the collision bit cleared?

Posted: Fri May 13, 2016 4:44 pm
by Stef
As far i remember the F flag is set only for V-Int and not H-Int.

Re: When is the collision bit cleared?

Posted: Fri May 13, 2016 5:50 pm
by Eke
From what I tested, VINT flag is NOT cleared by reading status register (at least in Mode 5, this works differently in Mode 4), it is set even if VINT is disabled on VDP side and remains set until level 6 interrupt got acknowledged by 68k.

viewtopic.php?f=22&t=787

As for Sprites Overflow and Collision flags, they remain set until status register is read (same behavior as SMS mode) and are not cleared automatically after VBLANK. Those flags are obviously only set when display is enabled but I didn't tested if disabling display after they were set would clear them.

Re: When is the collision bit cleared?

Posted: Sat May 14, 2016 12:02 am
by Sik
Eke wrote:From what I tested, VINT flag is NOT cleared by reading status register (at least in Mode 5, this works differently in Mode 4), it is set even if VINT is disabled on VDP side and remains set until level 6 interrupt got acknowledged by 68k.
That may be because the VDP keeps asserting the interrupt until it's acknowledged (this is also what causes "spurious" interrupts if you aren't careful with how you enable them).

Re: When is the collision bit cleared?

Posted: Sat May 14, 2016 7:48 am
by cero
Sik, can you elaborate?

What's the recommended way to enable them?

And do you mean the following is possible?

1. Ints are disabled just slightly too long, so the vblank period has started
2. Ints are enabled
3. The v-int happens immediately at that point (I thought it'd happen at the start of the next vblank!)
4. There may not be enough vblank time for the v-int DMA then, galaxies explode

Re: When is the collision bit cleared?

Posted: Sat May 14, 2016 9:39 pm
by Sik
I don't recall the exact details but yes there's a possibility of that happening. Take into account that interrupts can be disabled in two points: the VDP (through its first two registers) and the 68000 (through its SR register). The VDP knows nothing about the latter, so it may just keep waiting until the 68000 acknowledges it, resulting in the interrupt triggering at the wrong time.

Re: When is the collision bit cleared?

Posted: Sat May 14, 2016 11:10 pm
by Mask of Destiny
Well as Eke said, the VINT pending flag gets set even when VINTs are disabled on the VDP side so it doesn't matter how you enable the interrupts. If you've the point in the frame where the flag is set since the last time the interrupt was acknowledged, it will fire more or less immediately after you enable it (there's a one instruction latency if you enable via the VDP registers which is not present if enabling via SR, but otherwise it's the same).

This issue also exists for horizontal interrupts, but you can prevent the internal HINT pending flag from being set by setting the HINT counter load register to a high value such that it never reaches 0. Note though that the HINT counter is only loaded from the register during VBLANK and when the counter expires.

The interrupt hardware in the Genesis/Megadrive doesn't seem particularly well thought out to me. It would make more sense if disabling interrupts via the VDP registers cleared the pending flags since you can just mask the interrupts with SR if you want to disable them with out killing the pending status. The HINT counter behavior is also kind of annoying for certain cases. Anyway, it seems to cause a lot fewer problems in practice than I would expect. It is good to be aware of it though so you don't waste a bunch of time if it does become a problem.

Re: When is the collision bit cleared?

Posted: Sun May 15, 2016 3:15 am
by Sik
Don't forget about what happens when the 68000 is over with the last hblank interrupt right as the vblank one starts... The VDP thinks the vblank interrupt was over and not the hblank one, so the vblank interrupt never starts on the 68000. Whoops. (particularly dangerous in that there's a spurious hblank interrupt after the last line and the vblank interrupt triggers in the middle of said line)

Hblank is all sorts of trouble and should be avoided unless there's no other reasonable option for what you want to do (and when you do, try to ensure that any side-effects from spurious trigger would be reasonably innocuous)