The CHIP-8 has an additional memory buffer used for storing the graphics to display. It is 64 pixels wide and 32 pixels high. Each pixel is either on or off, so only two colors can be represented.
Understanding and then emulating its operation is probably the most challenging part of the entire project (but still very easy compared to the NES).
I’ll cover the exact implementation of the draw instruction down below, but first let’s cover how the drawing works. As mentioned, a pixel can be either on or off. In our case, we’ll use a uint32 for each pixel to make it easy to use with SDL (discussed later), so on is 0xFFFFFFFF and off is 0x00000000.
The draw instruction iterates over each pixel in a sprite and XORs the sprite pixel with the display pixel.
Sprite Pixel Off XOR Display Pixel Off = Display Pixel Off
Sprite Pixel Off XOR Display Pixel On = Display Pixel On
Sprite Pixel On XOR Display Pixel Off = Display Pixel On
Sprite Pixel On XOR Display Pixel On = Display Pixel Off
In other words, a display pixel can be set or unset with a sprite. This is often done to only update a specific part of the screen. If you knew you had drawn a sprite at (X,Y) and you now want to draw it at (X+1,Y+1), you could first issue a draw command again at (X,Y) which would erase the sprite, and then you could issue another draw command at (X+1,Y+1) to draw it in the new location. This is why moving objects in CHIP-8 games flicker.
As an example, let’s pretend we have a blank screen that is 16x10.

We draw a 10x4 sprite at (1,1), so it extends from (1,1) to (10,4).

We then draw an 8x2 sprite at (6,6), so it extends from (6,6) to (13,7).

If we then draw a 3x4 sprite at (7,3), it would cut a piece out of each of them and draw a line in the gap. The overlapping pixels would turn off (on XOR on = off), and the off pixels would turn on (off XOR on = on).

Some references I’ve read say that a sprite should wrap around to the other side of the screen if attempting to draw off-screen, so that’s what we’ll do.