This is an area where many people have done a lot of work, but it requires an intimate knowledge of a number of things. First of all, a knowledge of pointers in C++ only partially helps, because memory addresses in QuickBASIC are segmented (read this FAQ for more information: faq314-290 "What are segments and offsets, PEEK(), POKE and DEF SEG, and how does QB store strings?"

. As for allocating memory for a buffer, [tt]
DIM[/tt] works as shown above, but has some hidden caveats. In source code, [tt]
DIM[/tt] will always produce segment-aligned buffers, but in compiled programs, it will not. This can lead to confusing errors if you don't take [tt]
VARPTR(buf%(0))[/tt] into account.
Also shown above is the use of [tt]
PUT[/tt] to place the buffer onto the screen. This is generally a good approach, as it is fairly fast and avoids shearing by synchronizing with the vertical retrace. However, more is required than simply placing pixels into the buffer. The [tt]
PUT[/tt] routine requires a specific header to be present prior to the pixel data in the buffer. It has the following format:
[tt]
Offset Size Description
-----------------------------------------------------------
0 WORD Number of bits per scan line (in SCREEN 13,
this means 8 times the number of pixels per
scan line).
2 WORD Number of scan lines (in other words, the
pixel height of the region).
[/tt]
So before you can [tt]
PUT[/tt] the array, you need to place these values into it.
The header is 4 bytes, and an entire buffer in [tt]
SCREEN 13[/tt] is 320 * 200 = 64000 bytes, so the buffer needs to be 64004 bytes long. If the buffer is made out of QB [tt]
INTEGER[/tt]s, then it will need to contain 32002 elements. As the first element is 0 (barring [tt]
OPTION BASE 1[/tt]), the last element (the value specified in the [tt]
DIM[/tt] statement) must be 32001. Here is an example of actual working code that uses an offscreen buffer to draw to the screen. It animates bars scrolling upwards.
[tt]
DIM buf%(32001)
bufseg% =
VARSEG(buf%(0))
bufptr% =
VARPTR(buf%(0))
SCREEN 13
DEF SEG = bufseg%
DO
animationIndex% = (animationIndex% + 1)
AND 255
offset& = bufptr% + 4
' allow for PUT header
FOR y% = 0
TO 199
thisRowColour% = (y% + animationIndex%)
AND 255
FOR x% = 0
TO 319
POKE offset&, thisRowColour%
offset& = offset& + 1&
NEXT x%
NEXT y%
buf%(0) = 320 * 8
' set up PUT header
buf%(1) = 200
PUT (0, 0), buf%,
PSET
LOOP UNTIL INKEY$ <> ""
SCREEN 0:
WIDTH 80, 25
[/tt]
This example doesn't actually calculate the pixel offset. Instead, it draws the pixels strictly in ascending order of offset. The subroutine demonstrates calculating the offset:
[tt]
SUB setPixel(segment%, offset%, x%, y%, colour%)
DEF SEG = segment%
bufferOffset& = offset% + 4 + x% + 320& * y%
POKE bufferOffset&, colour%
END SUB
[/tt]
The parameters for this function would be passed as follows:
[tt]
setPixel
VARSEG(buf%(0)),
VARPTR(buf%(0)), x%, y%, colour%
[/tt]
Obviously, this could be optimized to not [tt]
DEF SEG[/tt] for every pixel, and to avoid making a function call (in other words, it could be inlined into the code where it is needed).
Good luck with your class, and encourage your students to visit online sources of programming information themselves! As well as this site, there is a huge repository of BASIC code that they can read and learn from called "All Basic Code", or ABC

The URL for ABC is: