Dungeon used compiled QBASIC to switch to CGA graphics mode (320x200x2bpp) and render sprites using the PUT method. The PUT command was a pretty fast method to poke a set of bytes into screen RAM and draw a sprite. It couldn’t cope with clipping (going out of bounds of the screen), transparency or a host of other issues but it was pretty fast.
It was substantially faster than PSET (pixel set) command in a loop.
The PUT command took an x,y pair and an array of data. The equivalent GET command took the sprite from screen (where you can render it with PSET) and stuffed it into the array, also storing the width and height in the first two short elements of the array.
To speed up loading the sprites I created a sprite sheet (texture atlas) in an offline program, and use BSAVE to save the screen directly to disk. I would only save the amount of scanlines required to cover the height of the spritesheet.
This technique worked really well, it had a small downside. CGA screen RAM is actually interlaced. To go from line 1 to line 2 is actually a jump offset and not simply the next byte along. The main upside is the fact that all sprites can be dealt with in a single load command (followed by lots of get commands of course) which is substantially faster than opening and closing lots of files. This is why I don’t BSAVE the sprites directly but in fact create an on screen sprite sheet. File loading speed was a very big factor when the files were on floppy disk.
I actually issued a pair of BSAVE commands, offset by a magic constant which equates to a single line down the screen (because of the interlacing). When you load with BLOAD, the same offset is incorporated and the sprites stitch themselves back together and GET commands can be used to fetch from screen RAM to the program memory (which in turn can be used in PUT commands).