Re: [ql-users] Re: sprites
I agree completely. The system I described does sometimes suffer from frame shear, but it's nowhere near as objectionable as the flicker from simple sprite redraws. Cheers Malcolm ZN wrote: On 2/19/02 at 8:12 PM Marcel Kilgus wrote: [no way to prefent flicker] Joachim Van der Auwera wrote: Oh yes there is... You have to be more intelligent and shift data in your buffer, restoring what is uncovered and saving what is newly covered. More difficult to write, but always gives good results, independent of execution speed. Helps, but doesn't solve the problem (I'm talking theoretically here, possibly with enough effort the effects can be neglected but they are there!). Precisely, Marcel is absolutely right. One should also make a difference between flicker and what is called 'frame shear'. Here is an example: a) 16 sprites to draw, by restoring the background then redrawing all 16 sprites in a new place. Effectively, in a short interval of time, there are no sprites on the screen. Suppose that this is what happens: As the screen is traced from top to bottom, the background is first redrawn. If this is fast enough, at some point in the entire screen scan, say right in the middle, the entire background will be restored, and the top half of the screen will show exactly that - no sprites. Next, the sprites are redrawn, however the scanning of the screen continues asynchronously, and the new sprites will not be seen in the top half untill that part is rescanned. You get sprites shown only in the lower half! Now, depending on how fast the drawing process is in comparison with the scanning, you can get all sorts of effects, from flicker, 'banding' horizontal or even slanted bands on the screen where the sprites or the background is visible only), to areas of the screen where the sprites remain invisible - and everything between. It would also change dynamically depending on what else is going on in the system. b) 16 sprites to draw, by precalculation of new positions from background in memory, and updating only the parts of the screen that need to be updated. In this case, as the scan goes from top to bottom, there will bea point up to which the screen will show the 'old' position, and from there on, a point where it will show the new position. If the movement of the sprites is very fast, several updates will occur as the scan of the screen progresses. This is called frame shear, where the diplayed frame frequencey and the update frequency are not the same. The effect is quite common and is actually preferable to the version a) although you can get 'streaking' effects if a sprite moves downn exactly as fast as the scan progresses. Given current hardware (except perhaps the Q40/Q60) this is unlikely. The only way to completely avoid flicker is a screen update that is synchronous with the screen scanning rate, which is usually done using an interrupt that occurs on every vertical retrace (when the screen scan finishes scanning the last - bottom right - pixel). Only original QL hardware can do something like that because the poll interrupt is equivalent to the vertical synch signal, which is a signal generated to tell the monitor to restart tracing of the screen from top left again. As far as I know, no other QL hardware does this. It may be possible (but is probably unduly complex) for QPC to implement tripple buffering, in which case there would not be frame sheer but frame drop or frame jitter effects, which are sometimes preferable but the implementation comes at a very high price. The SSG works as a task linked into the poll interrupt list, controlled through structures in memory that are set up by the basic keywords or calls to the relevant routines in the extension code. If the interrupt driven code is executed fast enough, it will update the screen quickly enough so that the scan will not overtake the update. The scan will therefore always show the current situation, with no frame sheer or flicker or any other artifact. IIRC (it was a long time ago...) the SSG also handles what needs to be updated, transparency, and collision detection using sprite masks. These are one-bit deep structures that define colision boundaries and which sprite pixels should be visible. Also, IIRC the SSG has several modes of operation, and one uses a background reference 'snapshot' to calculate which parts of the screen need to be modified. The modification is performed by pre-calculation and only writing to the actual screen RAM. Something like this would indeed be a nice addition to the screen driver but also a seizable complication once the PE is taken into account. OTOH the PE window save already provides the background reference. While at the subject of the PE - I was always under the impression that: 1) the PE saves the image of the application window, not a background (i.e. what is under the window), except where saving what is
[ql-users] Re: sprites
Well some preliminary tests I did through Basic using the Memory Copy facility of Turbo seem to work fine... (No flickering that is up to 48 x 48 sprites - above that hmmm okay ;-) I suspect though that through strict assembler that would disappear too - UNLESS of course the absence of flickering has something to do with my fast PC where I run QPC2). Well, there is just no way to avoid flickering. On fast machines the possibility that flicker appears gets smaller but it's never zero. Oh yes there is. The trick is not to restore the screen, save and write the sprite at the new position. You have to be more intelligent and shift data in your buffer, restoring what is uncovered and saving what is newly covered. More difficult to write, but always gives good results, independent of execution speed. I am pretty sure I wrote something like that for The Painter (long, long ago). Joachim
Re: [ql-users] Re: sprites
At 06:41 ìì 19/2/2002 +0100, you wrote: Well some preliminary tests I did through Basic using the Memory Copy facility of Turbo seem to work fine... (No flickering that is up to 48 x 48 sprites - above that hmmm okay ;-) I suspect though that through strict assembler that would disappear too - UNLESS of course the absence of flickering has something to do with my fast PC where I run QPC2). Well, there is just no way to avoid flickering. On fast machines the possibility that flicker appears gets smaller but it's never zero. Oh yes there is. The trick is not to restore the screen, save and write the sprite at the new position. You have to be more intelligent and shift data in your buffer, restoring what is uncovered and saving what is newly covered. More difficult to write, but always gives good results, independent of execution speed. Yes exactly what I was referring to. The calculations involved won't be TOO demanding for small sprites and the area that is to be shifted could be manipulated. Another possibility is to form some kind of caching in the beginning of the process e.g. for x sprites that move on certain directions you generate ALL possible occurences well in advance (it is possible since the sprite positions are limited to the grid you have). This would definately hold a LOT of memory, but it involves (usually) one operation the write-write (next position, previous position) only instead of read-write, compute, write -read. Phoebus I am pretty sure I wrote something like that for The Painter (long, long ago). Believe it or not I have NEVER seen the Painter (the only Painter I've seen was a VERY addictive game that I used to have on Microdrive which my daughter destroyed and don't have it anywhere else :-~~( Phoebus
Re: [ql-users] Re: sprites
At 02:30 ìì 19/2/2002 -0500, you wrote: At 08:12 ìì 19/2/2002 +0100, you wrote: 100 SIZE = SCR_XLIM*SCR_YLIM*2 110 LENGTH% = SCR_XLIM * 2 120 MAX_SCREEN = SCR_BASE + SIZE 130 buffer_norm = ALLOCATION (SIZE) 140 buffer_rev = ALLOCATION (SIZE) 150 FOR I=0 TO SIZE STEP LENGTH% : REMark Read Pixel line 300 MOVE_MEMORY SCR_BASE+I TO buffer_rev+SIZE-I , LENGTH% : REMark Store Pixel Line Finish to Start 320 END FOR I 330 MOVE_MEMORY SCR_BASE TO buffer_norm, SIZE: REMark Store Full (unreversed) screen 340 FOR f=1 TO 100 350 MOVE_MEMORY buffer_norm TO SCR_BASE, SIZE: REMark Copy The unreversed screen to the screen memory 350 MOVE_MEMORY buffer_rev TO SCR_BASE, SIZE: REMark Copy The reversed screen to the screen memory 360 END FOR f 370 DEALLOCATE buffer_rev 380 DEALLOCATE buffer_norm When compiling don't forget to use a huge buffer. I didn't want to experiment so I put Object Buffer 1024K and Turbo Buffer 1024K as well (It handles them extremely well btw) I also compiled with Fast Phoebus
Re: [ql-users] Re: sprites
Of course, the main problem using MOVE_MEMORY is that it cannot provide a way to XOR memory contents therefore making it impossible to have sprites with transparency. That could be overcome of course using TSPRT from the TurboPTR but that's a non elegant solution, which brings us back to our original problem of moving whole blocks of memory and prioritising. Movement priority is not exactly a necessity but for multi-plane scrolling for example it would be. (eg a moving backgroung (say sky) and a plane moving in an opposite direction) I might have to contact the current developers of Turbo_TK to see if we could update it a tad :-) (Still believe that two are the best toolkits on the QL, Turbo TK and DIY - TK-II IMHO is QDOS capabilities left out due to lack of time) Phoebus
Re: [ql-users] Re: sprites
On 2/19/02 at 8:12 PM Marcel Kilgus wrote: [no way to prefent flicker] Joachim Van der Auwera wrote: Oh yes there is... You have to be more intelligent and shift data in your buffer, restoring what is uncovered and saving what is newly covered. More difficult to write, but always gives good results, independent of execution speed. Helps, but doesn't solve the problem (I'm talking theoretically here, possibly with enough effort the effects can be neglected but they are there!). Precisely, Marcel is absolutely right. One should also make a difference between flicker and what is called 'frame shear'. Here is an example: a) 16 sprites to draw, by restoring the background then redrawing all 16 sprites in a new place. Effectively, in a short interval of time, there are no sprites on the screen. Suppose that this is what happens: As the screen is traced from top to bottom, the background is first redrawn. If this is fast enough, at some point in the entire screen scan, say right in the middle, the entire background will be restored, and the top half of the screen will show exactly that - no sprites. Next, the sprites are redrawn, however the scanning of the screen continues asynchronously, and the new sprites will not be seen in the top half untill that part is rescanned. You get sprites shown only in the lower half! Now, depending on how fast the drawing process is in comparison with the scanning, you can get all sorts of effects, from flicker, 'banding' horizontal or even slanted bands on the screen where the sprites or the background is visible only), to areas of the screen where the sprites remain invisible - and everything between. It would also change dynamically depending on what else is going on in the system. b) 16 sprites to draw, by precalculation of new positions from background in memory, and updating only the parts of the screen that need to be updated. In this case, as the scan goes from top to bottom, there will bea point up to which the screen will show the 'old' position, and from there on, a point where it will show the new position. If the movement of the sprites is very fast, several updates will occur as the scan of the screen progresses. This is called frame shear, where the diplayed frame frequencey and the update frequency are not the same. The effect is quite common and is actually preferable to the version a) although you can get 'streaking' effects if a sprite moves downn exactly as fast as the scan progresses. Given current hardware (except perhaps the Q40/Q60) this is unlikely. The only way to completely avoid flicker is a screen update that is synchronous with the screen scanning rate, which is usually done using an interrupt that occurs on every vertical retrace (when the screen scan finishes scanning the last - bottom right - pixel). Only original QL hardware can do something like that because the poll interrupt is equivalent to the vertical synch signal, which is a signal generated to tell the monitor to restart tracing of the screen from top left again. As far as I know, no other QL hardware does this. It may be possible (but is probably unduly complex) for QPC to implement tripple buffering, in which case there would not be frame sheer but frame drop or frame jitter effects, which are sometimes preferable but the implementation comes at a very high price. The SSG works as a task linked into the poll interrupt list, controlled through structures in memory that are set up by the basic keywords or calls to the relevant routines in the extension code. If the interrupt driven code is executed fast enough, it will update the screen quickly enough so that the scan will not overtake the update. The scan will therefore always show the current situation, with no frame sheer or flicker or any other artifact. IIRC (it was a long time ago...) the SSG also handles what needs to be updated, transparency, and collision detection using sprite masks. These are one-bit deep structures that define colision boundaries and which sprite pixels should be visible. Also, IIRC the SSG has several modes of operation, and one uses a background reference 'snapshot' to calculate which parts of the screen need to be modified. The modification is performed by pre-calculation and only writing to the actual screen RAM. Something like this would indeed be a nice addition to the screen driver but also a seizable complication once the PE is taken into account. OTOH the PE window save already provides the background reference. While at the subject of the PE - I was always under the impression that: 1) the PE saves the image of the application window, not a background (i.e. what is under the window), except where saving what is under the menu panes. 2) there was a mechanism that alowed jobs to provid for their own window maintaining regardless of the background save mechanism 3) a way of signalling the job to refresh it's window in RAM was absent. With clever use of the first two, it can be assured
Re: [ql-users] Re: sprites
ZN wrote: One should also make a difference between flicker and what is called 'frame shear'. Yes, I used flicker as a generic word for all king of weird effects. It may be possible (but is probably unduly complex) for QPC to implement tripple buffering, Wouldn't even help much as QPC doesn't know when to switch the buffers. The application would need a way to signal when it's finished with drawing. While at the subject of the PE - I was always under the impression that: 1) the PE saves the image of the application window, not a background (i.e. what is under the window), except where saving what is under the menu panes. Yes, the PE saves the contents of a window once it gets covered by another window, i.e. a window that is always in the foreground never gets saved. But open a 1x1 window over it and the whole thing is copied into RAM. 2) there was a mechanism that alowed jobs to provid for their own window maintaining regardless of the background save mechanism As far as I know this mechanism is pretty much hard coded into the whole PE, i.e. all the routines rely on valid save areas. I was also under the impression that programs using old QL modes under GD2 still save their windows internally as old QL mode bitmap, but the restore included conversion on the fly (I thought this plus changes in screen driver to handle cases where direct writing to screen RAM applied, were how the palette extensions of GD2 were implemented). No, there are no QL mode applications under GD2. The old calls are just translated into the higher colour depth but all applications are allowed to make use of the new calls, too, i.e. a complete high colour copy is always needed. Marcel
Re: [ql-users] Re: sprites
Phoebus R. Dokos wrote: This is the reason why if you move the mouse cursor using the keyboard the movement looks a bit more jerky on QPC than on the original hardware, where the PE can rely on the frame interrupt. I don't know about that since it looks fine to me! I can clearly see it on both my 400Mhz K6-III and the 800Mhz Athlon of my father. Did you compare it to an original QL? Nonetheless to prove my point I used the MEMORY_MOVE command on QPC2 as follows: Well, can't check it, I don't use Turbo and have neither the mood nor the time to set it up. By the way, if you use the PE save/restore calls instead of own memory copy routines you can automatically gain from the accelerated 16bit routines of QPC. And on native platforms it's probably not much slower than any other memory copy routine. Marcel