A8 - Introduction to Computer Graphics
Up until now, everything we've made the console do has only been visible in the debugger. If the console wasn't a debug version, the user would be staring at a blank screen, and would have no idea that all of our clever programming was taking place at all!
In almost all modern consumer cases, a program needs graphical output. Whether it's just lighting up a lamp to say that the oil needs changing, or putting HD graphics on a ceiling-to-floor television, the basic principal is still the same; a visual output is used to convey information to the user.
This is going to be quite a long article, so grab something to drink and get comfortable.
The Concept of Graphical Output
If you already understand a bit about RGB and screens, you can skip this heading and the next one. This is aimed at the beginner.
Now, graphical output may seem daunting, but it doesn't actually break any new ground in our knowledge - it's still just devices that are mapped to memory addresses that we can write data to to control their functions.
Imagine a very simple computer that consists of a lamp and a CPU. We want to control the lamp with our code. Assuming the lamp has a control register at memory address 0 as follows:
- (Not used for anything)
- Turns on the lamp when set to 1, and turns it off when set to 0
Then it would be a simple matter of turning it on with commands like
addi r1,r0,1 ;set r1 to 1 sb 0,r1 ;write 1 to the lamp register at location zero
And similarly, we could turn it off again with
addi r1,r0,0 sb 0,r1
Now, to extend the example, what if we had a computer with 16 lamps? In this case, they might have two bytes worth of control registers, at memory positions 0 and 1, where each bit controls one lamp. Perhaps these lamps are all arranged on a wire (like christmas lights), and we could program them to flash in a pattern. More interestingly, though, they could be arranged in a 4-by-4 grid. In that case, if we wrote the following commands:
pattern .halfu 2#0110100110010110 ;make our pattern lh r1,pattern ;load it into memory sh 0,r1 ;save it to our lamp control registers
The lamps would display the following:
○ ● ● ○ ● ○ ○ ● ● ○ ○ ● ○ ● ● ○
With a slight change:
pattern2 .halfu 2#1001011001101001 ;make our next pattern lh r1,pattern2 ;load it into memory sh 0,r1 ;save it to our lamp control registers
We could turn our circle into a cross:
● ○ ○ ● ○ ● ● ○ ○ ● ● ○ ● ○ ○ ●
Simple, right? With a sufficiently large grid of lamps, we could draw some very detailed pictures indeed! Of course, the more lamps we have, the more commands we have to use to fill them - if we get more than 32 lamps, we won't be able to set all of them even with a sw command - we'd have to use two.
Now, in Technicolor!
In the previous section, I explained how a black and white monitor could work and be manipulated. However, you'd have to go back a long way in history to find a black and white console - even the gameboy had 4 shades of gray.
In the case of a colour display, things don't change dramatically - it's just that now, instead of just turning the lamps on and off, we need to choose their colour as well. By the way - these individual dots that make up our graphical output, regardless of how they're implemented in the real world, are referred to as "Picture Elements", or pixels for short.
Generally speaking, we choose the colour of each pixel by deciding how much each of red, blue and green to put into it. It's a lot like mixing paint - except since we're using light instead of dye, the more colour we add, the brighter the mixture gets. Mixing the maximum of red, green and blue will give you white, while mixing none at all will give you black.
In modern computers, each colour channel (red, green and blue) is represented by one whole byte, meaning we have 256 different levels of each colour we can mix. They're generally organised in that order, and may look something like
RRRR RRRR GGGG GGGG BBBB BBBB
This allows us to make an enormous amount of colours - enough that adding more wouldn't make much difference, because some of the colours are already so close together that the human eye can't tell them apart. However, on older systems, our colour choice was very limited.
Graphics on the VO-EM
VO-EM is one such system with a limited choice of colours. There is more than one way to draw graphics to the screen on this console, but the most simple is the Bitmap Overlay device.
The bitmap overlay device is a grid 120 pixels wide and 80 pixels high. Each pixel can be invidually switched on and off. When switched on, you can choose to mix 4 levels each of red, green and blue, for a total of 64 unique colours per pixel.
In the next tutorial, we'll learn how to use the above concepts to actually draw to the screen with the VO-EM!