2007-07-06

Scrolling and Double Buffering

Trying to work out the best way to handle scrolling in the AmigaGuide reader. Currently, all of the text currently visible is re-drawn at a new location every time the user pushes Up or Down - this means I’m re-drawing the entire screen and am not taking advantage of the DS’ built-in hardware scrolling.

As this is a slow process, the screen was tearing when it was re-drawn. The most obvious way to fix this is to double-buffer the display, so I set about doing that. I thought that the easiest way to do this was to allocate a screen-sized (49192 x 2 bytes) chunk of RAM and use that as a buffer - write to it, then use DMA_Copy() to output it to VRAM. Wrote a DoubleBuffer class to do just that, and gave it a try.

It’s really slow - it has to perform lots of write operations then a huge copy operation before the screen can be displayed.

Pondered this for a while, and concluded that what I should really do is create the buffer in VRAM, then somehow update the display pointer to point to the buffer when it’s ready to be displayed, and use the original VRAM as the buffer until they switch back. This would seem to be a much more logical way of doing things, and I’d guess that this is the way it’s supposed to be done. (Had a quick look at the libnds double buffering example, and they seem to have done exactly that.) The problem is that I’m using 16-bit mode, and there isn’t enough VRAM to hold a buffer.

Nuts.

Had a look at the PALib forums (which have since vanished from the internets - server problems, it looks like), and it seems Mollusk has implemented a double-buffer routine using the 8-bit display mode in the latest version of PALib. I’ve been holding off from upgrading as I’ve done a few fixes in the PALib code that may not have made it back into the new release (I’ve posted them all on the forums, but who knows whether they’ve been included or not), but now I’ve got a good reason to switch.

I could make all of this more efficient by creating a large bitmap using the PA_InitLargeBg() function and scrolling around that, only re-drawing when the bitmap is about to wrap around. The problem with this is that it might introduce stuttering when the screen is redrawn.