Jump to content
IGNORED

Sprite collision detection.


marc.hull

Recommended Posts

A few VDP/Sprite questions.....

 

When is the sprite/sprite collision bit set ? at the end of the frame or when collision occurs on the scan line ?

 

If using the VDP interrupt I assume the data is made available in the scratchpad only after each frame(a no brainer but just making sure..... correct ?

 

If testing the VDP status directly with the ISR disabled do you need to wait for the end of frame or can you test it reliably at any time without missing collisions at the bottom of the screen?

 

Does the start of a new frame reset the collision bit ?

Link to comment
Share on other sites

When is the sprite/sprite collision bit set ? at the end of the frame or when collision occurs on the scan line ?

Let's generally assume real iron (no emulator).

 

It is set almost immediately after collision occurs. Tursi proved that it was possible to react on it on a scan line basis. See background color follow sprites/collision:

 

http://www.youtube.com/watch?v=3ioC3dqGxk8

 

If using the VDP interrupt I assume the data is made available in the scratchpad only after each frame(a no brainer but just making sure..... correct ?

Yes.

 

If testing the VDP status directly with the ISR disabled do you need to wait for the end of frame or can you test it reliably at any time without missing collisions at the bottom of the screen?

No, don't have to wait.

 

Does the start of a new frame reset the collision bit ?

No.

 

:)

Edited by sometimes99er
Link to comment
Share on other sites

A few VDP/Sprite questions.....

 

When is the sprite/sprite collision bit set ? at the end of the frame or when collision occurs on the scan line ?

 

The datasheet does not say specifically when the status register 'C' (collision) bit is updated, but the collision of two sprites is detected *as* the sprites "during pixel generation". So, it is feasible that the 'C' bit is updated mid-scanline, but I would think at least by the end of the current scanline. The F18A updates the status register within 100nS of the collision.

 

 

If using the VDP interrupt I assume the data is made available in the scratchpad only after each frame(a no brainer but just making sure..... correct ?

 

Not sure, but since the ISR only runs via the VDP interrupt, and the ISR updates the scratchpad areas, this is a pretty safe assumption.

 

If testing the VDP status directly with the ISR disabled do you need to wait for the end of frame or can you test it reliably at any time without missing collisions at the bottom of the screen?

 

You can poll the VDP status any time, but doing so will clear the status register. So, if you are polling for the INT bit (which happens at VSYNC), you will be clearing the 'C' bit too, each time you poll. So to poll for the INT and also use the 'C' bit, you would need to store the collision status any time you polled for the INT. Then when you detect the INT, you would then check your saved collision status to see if there had been a collision.

 

Does the start of a new frame reset the collision bit ?

 

No. Only reading the status register clears the INT, C, and 5S (5th sprite indicator) bits, and reading the VDP status reg clears *all* the bits. So any time you read the status, you have to use and / or save the bits you care about.

Link to comment
Share on other sites

A few VDP/Sprite questions.....

 

When is the sprite/sprite collision bit set ? at the end of the frame or when collision occurs on the scan line ?

 

The datasheet does not say specifically when the status register 'C' (collision) bit is updated, but the collision of two sprites is detected *as* the sprites "during pixel generation". So, it is feasible that the 'C' bit is updated mid-scanline, but I would think at least by the end of the current scanline. The F18A updates the status register within 100nS of the collision.

 

 

If using the VDP interrupt I assume the data is made available in the scratchpad only after each frame(a no brainer but just making sure..... correct ?

 

Not sure, but since the ISR only runs via the VDP interrupt, and the ISR updates the scratchpad areas, this is a pretty safe assumption.

 

If testing the VDP status directly with the ISR disabled do you need to wait for the end of frame or can you test it reliably at any time without missing collisions at the bottom of the screen?

 

You can poll the VDP status any time, but doing so will clear the status register. So, if you are polling for the INT bit (which happens at VSYNC), you will be clearing the 'C' bit too, each time you poll. So to poll for the INT and also use the 'C' bit, you would need to store the collision status any time you polled for the INT. Then when you detect the INT, you would then check your saved collision status to see if there had been a collision.

 

Does the start of a new frame reset the collision bit ?

 

No. Only reading the status register clears the INT, C, and 5S (5th sprite indicator) bits, and reading the VDP status reg clears *all* the bits. So any time you read the status, you have to use and / or save the bits you care about.

 

OK thanks (to both of you.) Those answers may have solved a problem.

Link to comment
Share on other sites

  • 2 weeks later...

I don't think collision detection is made available to the TI until the end of frame. Testing the Memory mapped status register, I got into over run problems and had to introduce a delay of >01FF to make sure I got good data. Mike's video is unclear to me exactly what he is testing (it does not look like coincidence.)

 

Mike what did the bubble floating up video show (and please dumb it down 8). )

Link to comment
Share on other sites

I don't think collision detection is made available to the TI until the end of frame. Testing the Memory mapped status register, I got into over run problems and had to introduce a delay of >01FF to make sure I got good data. Mike's video is unclear to me exactly what he is testing (it does not look like coincidence.)

 

Mike what did the bubble floating up video show (and please dumb it down 8). )

http://tech.groups.yahoo.com/group/ti99-4a/message/56769

 

:)

Link to comment
Share on other sites

I don't think collision detection is made available to the TI until the end of frame. Testing the Memory mapped status register, I got into over run problems and had to introduce a delay of >01FF to make sure I got good data. Mike's video is unclear to me exactly what he is testing (it does not look like coincidence.)

 

Mike what did the bubble floating up video show (and please dumb it down 8). )

http://tech.groups.yahoo.com/group/ti99-4a/message/56769

 

:)

 

OK that makes sense. Perhaps the issue is the asynchronous nature of the CPU/VDP relationship. There evidently are some timing considerations that must be taken into account when not working from the interrupt.

Link to comment
Share on other sites

The video showed that you could change the background color register on a per-scanline basis, and that you can use the sprite collision bit mid-frame. Unfortuately I was tired, and didn't feel like typing the hex code into minimemory a second time that night when I noticed that you could only see the border color, and that the main screen wasn't using transparent for the character background colors. ;)

 

The only thing I'll add not noted here is that the MSX guys figure that the bit may be updated as late as 1 or 2 scanlines after the actual first collision, and that it was not necessarily predictable. But it would always happen midframe and be "close". So if you used it for midframe detection, you need to assume that the actual detection will be off by a couple of scanlines and leave yourself some space. (For instance, the MSX demos that change graphics mode mid-frame usually leave a gap).

 

You can detect more than once per frame if your code is fast enough. You can also use the 5-on-a-line flag, but of course that takes more sprites.

 

There are no timing considerations that I am aware of. Sprite collision detection is 100% detached from the end-of-frame interrupt. But you might be forgetting that when you read the status register, you clear all the bits. That means that if you care about both collision and end-of-frame, you always have to check for both, since reading the status register will clear both. Likewise, if interrupts are enabled, the console interrupt routine will read the status register and clear both on you.

 

Tell us what the problem you are having is? :)

Link to comment
Share on other sites

The video showed that you could change the background color register on a per-scanline basis, and that you can use the sprite collision bit mid-frame. Unfortuately I was tired, and didn't feel like typing the hex code into minimemory a second time that night when I noticed that you could only see the border color, and that the main screen wasn't using transparent for the character background colors. ;)

 

The only thing I'll add not noted here is that the MSX guys figure that the bit may be updated as late as 1 or 2 scanlines after the actual first collision, and that it was not necessarily predictable. But it would always happen midframe and be "close". So if you used it for midframe detection, you need to assume that the actual detection will be off by a couple of scanlines and leave yourself some space. (For instance, the MSX demos that change graphics mode mid-frame usually leave a gap).

 

You can detect more than once per frame if your code is fast enough. You can also use the 5-on-a-line flag, but of course that takes more sprites.

 

There are no timing considerations that I am aware of. Sprite collision detection is 100% detached from the end-of-frame interrupt. But you might be forgetting that when you read the status register, you clear all the bits. That means that if you care about both collision and end-of-frame, you always have to check for both, since reading the status register will clear both. Likewise, if interrupts are enabled, the console interrupt routine will read the status register and clear both on you.

 

Tell us what the problem you are having is? :)

 

It was a conceptual problem more than anything. I assumed just because I rendered the collision sprite that it was being drawn right away when in fact it may no be drawn until the next frame. For example if the scan line is mid frame and the sprite is rendered at the top of the screen then there will be no sprite or collision until the next go-round.

 

A reordering of routines and checking the frame bit at the start of the loop solved the issue. IE.

 

1) update game data

2) render collision sprite

3) check for coincidence

4) wait for frame bit

 

Did not work reliably but....

 

1) Wait for frame bit

2) render collision sprite

3) update game data

4) check for coincidence

 

Works just fine....

 

Just had to think a bit harder. That's difficult sometimes when your normal MO tends to be brute force .....;-).

Link to comment
Share on other sites

fascinating stuff :cool:

 

 

This got me thinking. Can a TMS9900 assembly program estimate the scanline that is currently being generated by the TMS9918 VDP ?

 

Wonder if you could use the timer mode of the TMS9901 for doing something like that ?

I guess it's safe to assume that the TMS9918 has a very tight rendering schedule. So if you wait for the frame bit, setup the TMS9901 with the time it takes to render a screen you could then read the 9901 decrementer bit as input for a calculation about the scanline ?

 

Do not know how useful it would be because during that time you can't use the 9901 for doing stuff like polling the keyboard/joysticks.

hhmmm well you could poll the keyboard durig VBLANK :ponder:

 

Guess a CPU tight loop might be an option. But it would be not be very useful if you wanna do something in between.

 

 

Then again perhaps I'm just talking crap, dunno :D

 

 

EDIT: If we're talking 60 frames a seconds that means the rendering of a screen takes about 16 milliseconds ?

 

Just checked Thiery's page on what the timer mode can handle:

 

One unit on the decrementer represents 64 clock periods, thus 64*333 = 21.3 microseconds. This is the resolution of the timer, the smallest time that it can measure.

 

The other limitation is that the maximal possible time is 16383*64*333 ns = 349.2 milliseconds.

Edited by retroclouds
Link to comment
Share on other sites

fascinating stuff :cool:

 

 

This got me thinking. Can a TMS9900 assembly program estimate the scanline that is currently being generated by the TMS9918 VDP ?

 

Wonder if you could use the timer mode of the TMS9901 for doing something like that ?

I guess it's safe to assume that the TMS9918 has a very tight rendering schedule. So if you wait for the frame bit, setup the TMS9901 with the time it takes to render a screen you could then read the 9901 decrementer bit as input for a calculation about the scanline ?

 

Do not know how useful it would be because during that time you can't use the 9901 for doing stuff like polling the keyboard/joysticks.

hhmmm well you could poll the keyboard durig VBLANK :ponder:

 

Guess a CPU tight loop might be an option. But it would be not be very useful if you wanna do something in between.

 

 

Then again perhaps I'm just talking crap, dunno :D

 

 

EDIT: If we're talking 60 frames a seconds that means the rendering of a screen takes about 16 milliseconds ?

 

Just checked Thiery's page on what the timer mode can handle:

 

One unit on the decrementer represents 64 clock periods, thus 64*333 = 21.3 microseconds. This is the resolution of the timer, the smallest time that it can measure.

 

The other limitation is that the maximal possible time is 16383*64*333 ns = 349.2 milliseconds.

 

 

You can set the 9901 in timer mode. Load a value and go back to I/O mode. The 9901 will operate the decrementer on it's own, independent of being back in I/O mode. In other words it is set it and forget it. I think a better description for the mode would be "Timer read/write" mode.

 

I used the 9901 timer in the SID Player but only because I needed finer resolution than 1/60 of a second.

 

prediction of a scan line may be possible but I don't know that you could do much else. Depends on the how much code you could get to execute in roughly (1/60)/191 of a second. That's Mike and Matt's territory there.....

Link to comment
Share on other sites

It was a conceptual problem more than anything. I assumed just because I rendered the collision sprite that it was being drawn right away when in fact it may no be drawn until the next frame. For example if the scan line is mid frame and the sprite is rendered at the top of the screen then there will be no sprite or collision until the next go-round.

 

That is correct, the sprite would not appear or be considered for collision detection until the next frame, if the scanline is past the sprite (the scanline is greater than the sprite's Y location + sprite size + magnification) when you make it active (or move it.)

 

According to the datasheet: "The VDP checks each pixel position for coincidence during the generation of the pixel...". Also note that "Sprites beyond the Sprite Attribute Table terminator (>D0) are not considered."

 

Something I need to test is whether collision detection is performed on sprites 5 and up, when you have more than 4 on a line. Since the collision detection is done during pixel generation, and there are only 4 sprite shift registers in the VDP, I don't see how the other sprites could be considered when you have more than 4 sprites on a single line.

Link to comment
Share on other sites

Something I need to test is whether collision detection is performed on sprites 5 and up, when you have more than 4 on a line. Since the collision detection is done during pixel generation, and there are only 4 sprite shift registers in the VDP, I don't see how the other sprites could be considered when you have more than 4 sprites on a single line.

 

... annnnd.. we did that test this morning, and they do not collide when they are not drawn due to the 5-sprite on a line. :)

Link to comment
Share on other sites

I am now surmising that it would be good practice to check for collision at the frame after the sprite pattern/position updates.

 

I am curious as to when the ISR checks for coincidences. I would assume that it does it before any updates but don't know for sure.

 

I am also curious as to how much of the missing coincidence problem in XB is due to the update/checking conundrum and how much is due to the slowness of the language.

Link to comment
Share on other sites

I am now surmising that it would be good practice to check for collision at the frame after the sprite pattern/position updates.

 

I am curious as to when the ISR checks for coincidences. I would assume that it does it before any updates but don't know for sure.

 

I am also curious as to how much of the missing coincidence problem in XB is due to the update/checking conundrum and how much is due to the slowness of the language.

 

Having re written XB on numerous occasions I can testify to the fact that it is totally the slowness of the language.

 

I have added more commands to RXB and the result is RXB is a little slower at detection depending on the organization of the programs.

 

That was one reason for making the ALL command in the sprite detection in RXB along with some attempts a making it faster in GPL.

 

Running in Turbo mode really improves the detections of sprites.

Link to comment
Share on other sites

I am now surmising that it would be good practice to check for collision at the frame after the sprite pattern/position updates.

 

I am curious as to when the ISR checks for coincidences. I would assume that it does it before any updates but don't know for sure.

 

I am also curious as to how much of the missing coincidence problem in XB is due to the update/checking conundrum and how much is due to the slowness of the language.

 

Sorry Rich, but there /is/ more to it than the speed of the language. There is also a race against the ISR.

 

To start with Marc's questions: the ISR does NOT check for coincidences. But it has to read the VDP status register in order to clear the VDP interrupt, so it saves a copy of the register off in scratchpad. That may be what you are thinking of.

 

While the speed of XB does contribute to missed coincidences of moving sprites, there is also a race condition as I mentioned. The ISR reads the status register in order to clear the VDP interrupt -- this also clears the collision bit. But CALL COINC(ALL) /also/ directly reads the VDP status register, and not the mirror in scratchpad, which means that whether or not you see the collision depends on exactly when on the frame the CALL COINC happens. (It won't interfere with the VDP interrupt except in super rare instances, because that gets control of the system before the command can be executed).

 

You can very easily see how bad the problem is, and that it's not strictly the speed of XB. Just set up two touching, NON-MOVING sprites, and poll/print the CALL COINC(ALL) result. Even though the sprites are not moving, they will still miss many collisions. I have not verified this next theory, but the nature of the race suggests that the closer the sprite is to the bottom of the screen, the more likely you will miss the collision. The best workaround would seem to be to avoid COINC(ALL) and use PEEK() on the copy of the VDP register in scratchpad, at least as long as you don't mind requiring the 32k.

 

Example app showing the issue:

 

10 CALL CLEAR
20 CALL SPRITE(#1,65,2,100,128)
30 CALL SPRITE(#2,66,2,100,132)
40 CALL COINC(ALL,A)
50 PRINT A
60 GOTO 40

Link to comment
Share on other sites

I am now surmising that it would be good practice to check for collision at the frame after the sprite pattern/position updates.

 

I am curious as to when the ISR checks for coincidences. I would assume that it does it before any updates but don't know for sure.

 

I am also curious as to how much of the missing coincidence problem in XB is due to the update/checking conundrum and how much is due to the slowness of the language.

 

Sorry Rich, but there /is/ more to it than the speed of the language. There is also a race against the ISR.

 

To start with Marc's questions: the ISR does NOT check for coincidences. But it has to read the VDP status register in order to clear the VDP interrupt, so it saves a copy of the register off in scratchpad. That may be what you are thinking of.

 

While the speed of XB does contribute to missed coincidences of moving sprites, there is also a race condition as I mentioned. The ISR reads the status register in order to clear the VDP interrupt -- this also clears the collision bit. But CALL COINC(ALL) /also/ directly reads the VDP status register, and not the mirror in scratchpad, which means that whether or not you see the collision depends on exactly when on the frame the CALL COINC happens. (It won't interfere with the VDP interrupt except in super rare instances, because that gets control of the system before the command can be executed).

 

You can very easily see how bad the problem is, and that it's not strictly the speed of XB. Just set up two touching, NON-MOVING sprites, and poll/print the CALL COINC(ALL) result. Even though the sprites are not moving, they will still miss many collisions. I have not verified this next theory, but the nature of the race suggests that the closer the sprite is to the bottom of the screen, the more likely you will miss the collision. The best workaround would seem to be to avoid COINC(ALL) and use PEEK() on the copy of the VDP register in scratchpad, at least as long as you don't mind requiring the 32k.

 

Example app showing the issue:

 

10 CALL CLEAR
20 CALL SPRITE(#1,65,2,100,128)
30 CALL SPRITE(#2,66,2,100,132)
40 CALL COINC(ALL,A)
50 PRINT A
60 GOTO 40

 

The XB source code says:

*----------------------------------------------------------

* Insert a line here in sprite handling code for speeeding

* up XB 5/22/81

* RXB PATCH LABLE ************

SPNUM5 ST @FAC1,V@SPNUM Keep sprite number

*----------------------------------------------------------

DEC @FAC1 Adjust for internal use

DSLL 2,@FAC Get location of SAL

DADD >0300,@FAC Sprite # * 4 + >0300

DST @FAC,@SPSAL Save SAL location

RTN

 

There was a similar statement in the XB ROM code that said they did not get the update into the ROMs in time for release.

Said something like Future release. They were going to remove the MVDN and MVUP commands and the GVWRITE and GVREAD as they really were not any faster then the GPL MOVE command.

The ********** was me saying a cuss-word. Really to bad all the Hand written stuff I have on my original copies is gone.

 

I should add that most misses on COINC with XB are it is executing a different section of code when the window for COINC is best and that happens more often the bigger the program.

And you are totally correct the ALL is a crap command the Tolerance works 3 times as well as all. And XB does check the >837B in COINC and >837C also.

Edited by RXB
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...