Step 1 of 5 · Reading · ~3 min
Read
Display & Input
Display: DRW Instruction
After this lesson your emulator draws. The screen is a 64 by 32 grid of pixels that are on or off, and exactly one instruction writes to it. The test ROM at the end of this lesson is the 132-byte IBM logo that every CHIP-8 author runs first; if your screen shows the three striped letters, the rest of the machine is trustworthy.
A sprite is N bytes at I
DXYN draws N rows of 8 pixels. Row r is the byte at address I + r, and its most significant bit is the leftmost pixel. VX and VY give the position of the sprite's top-left corner. The byte 0x3C is the row ..####.., and the font digit 7 is five such rows:
F0 ####....
10 ...#....
20 ..#.....
40 .#......
40 .#......
Drawing is XOR
A sprite bit of 0 changes nothing. A sprite bit of 1 flips the screen pixel under it: off becomes on, on becomes off. The rule has a payoff: drawing the same sprite twice at the same place erases it, so a game moves a ball by drawing it where it was (erasing) and then where it goes next. It also means the interpreter needs no background and no save buffer.
A one-row trace, with a screen row that already holds ..####.. (0x3C) and a sprite row 0x18 drawn over it:
screen ..####..
sprite ...##...
result ..#..#.. two pixels went from on to off
VF reports collisions
At the start of every DXYN, VF is set to 0. If any pixel is flipped from on to off during the draw, VF becomes 1. Drawing onto empty pixels does not count, and neither does a sprite byte of 0, which flips nothing. Games use this for hit tests: draw the ball, and if VF came back 1 it touched something. Note that a later DXYN clears the flag again, so read it before drawing anything else.
Edges: wrap the start, clip the rest
The starting coordinates wrap: x = VX mod 64 and y = VY mod 32, so VX = 70 starts at column 6. After that, pixels that would fall past the right edge or the bottom edge are cut off. They do not wrap round to the other side. (Some emulators wrap them too; that is one of the quirks later.) N = 0 draws zero rows and just clears VF; SUPER-CHIP gave it a different meaning, classic CHIP-8 did not.
00E0 clears the whole screen and leaves VF alone. DXYN never changes I.
Common mistakes
- Overwriting pixels instead of XOR-ing them, so a second draw cannot erase.
- Using the register numbers X and Y as coordinates instead of the values VX and VY.
- Setting VF when a sprite merely overlaps lit pixels, rather than when a pixel is turned off, or forgetting to reset it to 0 at the start of each draw.
- Reading the sprite bits least-significant first, which draws every sprite mirrored.
- Wrapping a sprite that runs off the right edge onto column 0.
Your exercise
The starter can already print the screen with the SCREEN command (32 lines of 64 characters, # for on and . for off). You add DXYN and 00E0. Run the IBM logo first; the edge cases are in the hidden tests.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…