Know thy hardware
Suppose we write the background image, as we did in the previous post, starting at address #01000h. That display would appear if we wrote the nibbles 0,0,0,1,0 to the locations =DISP1CTL, =DISP1CTL+1 ... =DISP1CTL+4 (or "write #01000h to =DISP1CTL"). This is how the screen will look if we write #00FDEh (#01000h - 34) instead:
|One pixel/row/step up|
We observe that we can change what is shown on the screen without redrawing it. We just wrote a different number in =DISP1CTL and the display changed. Not much, but it changed. Can we use it? Yes. Can we abuse it? Of course!
So by rendering a 136*128 background (instead of the current 136*64) and decrementing/incrementing the value we write to =DISP1CTL by 34, we can move the image down/up (scroll up/down) respectively.
What about horizontal scrolling? Well, things now get tricky: =DISP1CTL can only accept addresses on byte boundaries, so we can only do a big step left/right by 8 pixels. There is, however, a 4bit address, called =BITOFFSET, which sets the pixel offset of what is shown on the screen. Right now it is set to 0. To scroll towards the left, as the player moves right, we would have to increment =BITOFFSET by 1 for each pixel towards the right and when we're about to increase it from 7 to 8, write 0 to it instead and increment =DISP1CTL by 2. That, however, implies the image we are displaying is wider than 136 pixels: if we did this with the image we have shown until now, the screen would become garbled and at the start of each row of pixels, pixels from the ending of the previous row would appear. We need to adjust =LINENIBS, to configure how many nibbles the display controller should skip after reaching the end of each row, by an amount appropriate to the size of the displayed image.
So, we need a larger image. And with a larger image comes heavier memory usage. And longer rendering times. For now however, we can, theoretically, scroll a static image back and forth, up and down, without much cpu usage: just a couple writes. That's a big step from earlier when we didn't have time to render one screen's worth of data in time.