Hi,
this is more an Atari question than a Hatari one but knowing how many knowledgeable people are here... :)
Even though I'm not actively coding on ST/E machines, out of curiosity I'd like to know how a programmer is supposed to handle double buffering on ST/E.
On Falcon it is easy:
- do your code
- swap buffers
- Vsync() // wait for vbl
- VsetScreen(-1, new_buffer, -1, -1) // set physbase
This works because VsetScreen just writes to FFFF8201 & friends which gets reloaded at the line defined by VDB (btw, you can consider this as a feature request, Hatari doesn't do this yet ;-)). And since we know that the write to FFFF820x is happening during VBL, it's 100% safe to assume that this never happens:
move.b vbasehi,$ffff8201
// VDB --> Videl reloads its internal video base pointer from $ffff8201, $ffff8203 and $ffff820d
move.b vbasemi,$ffff8203 // too late guys...
move.b vbaselo,$ffff820d //
But what about the ST/E shifter? AFAIK the video base is taken into account at line 310 (end of the visible area / start of VBL). So if I do the steps above, Setscreen() will have no effect for the whole frame because when setting it during VBL, the video base has already been read.
I was considering:
- do your code
- swap buffers
- Setscreen(-1, new_buffer, -1) // set physbase
- Vsync() // wait for vbl
which does the trick but then there's the danger of reading only the partially set video base address, isn't it? (see my example above, just replace VDB with line 310...) Assuming that your code may take a variable amount of frames (i.e. you can't set the logical buffer in advance so it reloads by the end of the frame), is there a way to do a 100% safe double buffering on ST/E?
I can think of only one way, optimize the Setscreen() call into one instruction, i.e. align the screen buffer on 256 bytes (8203 = $00) and just
move.l new_buffer,d0 ; $00123400
lsr.w #8,d0 ; $00120034
move.l d0,$ffff8200.w ; not interruptible by the Shifter?