EGA, 1984
The EGA added planes. Four of them, 16 colours out of 64, latch registers sitting between you and video memory, and a start address you can scroll. This era works each of those by hand until the plane model stops feeling strange.
Graphics track · 27 missions · boss mission, written exam and certificate · free, no signup. Everything below runs in the browser terminal on the SERVBG home page.
What you will do
- render the reference scene through the EGA pipeline
refIBM announced the Enhanced Graphics Adapter in September 1984 alongside the PC/AT: 640x350 in 16 colours, against the CGA's four. The card listed at 524 dollars and the 5154 Enhanced Color Display at 849.
- enter 640x350 with 16 colours out of 64
mode 10hSixteen colours at 640x350 need 112,000 bytes, so a 64KB EGA ran mode 10h from two planes in four colours; the full 16 needed the Graphics Memory Expansion Card. IBM shipped the 64KB version first and the picture everybody wanted required the upgrade.
- paint the 16 palette registers as colour bars
barsA pixel on an EGA never stores a colour. It stores a number from 0 to 15, and the attribute controller decides what that number looks like.
- dump the 16 attribute-controller palette registers
paletteThe 16 palette registers live at port 3C0h and hold 6 bits each. There is no DAC on an EGA: those six bits drive six TTL wires, two per channel, so 64 colours exist and any 16 of them can be on screen.
- decode one 6-bit rgbRGB colour code by hand
bits 0x14The bit order is rgbRGB: the low three bits are the primary red, green and blue at value 170, the high three the secondary set at 85. Four levels per channel, 4x4x4 = 64.
- break the brown fix and watch bar 6 turn olive
palette 6 0x06Without the fix, index 6 is red plus green at equal strength: AAAA00, a dark yellow nobody wanted. IBM had already faced this on the CGA and cured it in the 5153 monitor by halving the green.
- restore the brown fix
palette 6 0x14On the EGA the fix is not hardware at all, just the default value 14h in one register, which swaps in the secondary green bit for AA5500. Any program was free to overwrite it and some did.
- list all 64 colours the EGA output can generate
gamutSixty-four available, sixteen loadable. Every EGA picture is two separate decisions: which 16 of the 64, and which of those 16 each pixel points at.
- retint index 1 from dark blue to bright cyan
palette 1 0x3bReprogramming one register repaints every pixel holding that index in a single I/O write, however much of the screen it covers. Palette animation on the EGA cost nothing per pixel.
- see the planar memory map and its arithmetic
vramAll four planes are mapped at A000:0000 at once. The address selects the pixel group; registers, not the address, select which plane a read or write actually touches.
- set one pixel and watch four separate plane bits move
plot 320 175 12One pixel costs four memory writes, one per plane. That is why EGA code that mattered never plotted single pixels and always worked eight at a time.
- read one byte from all four planes at once
peek 14040The offset arithmetic is y * 80 + (x >> 3): scan line 175 at byte column 40 is offset 14040, covering pixels 320 to 327. A real read returns one plane's byte, chosen by Read Map Select at 3CEh index 04h.
- paint eight pixels with a single byte store
poke 14040 0xffWith the map mask wide open, one 8-bit store sets the same bit pattern in all four planes, turning eight adjacent pixels white. Eight pixels per instruction is the whole reason the planar layout existed.
- write-enable plane 1 only
mapmask 0x02The Sequencer Map Mask register sits at 3C4h index 02h. Its low four bits say which planes a CPU write is allowed to reach; the rest keep whatever they already held.
- repeat the same write with only one plane enabled
poke 14120 0xffIdentical instruction, identical data, different result: only bit 1 of each pixel is set, so the eight pixels come out green rather than white. The colour was decided by a register, not by the value you wrote.
- restore write access to all four planes
mapmask 0x0fLeaving a narrow map mask set is one of the classic EGA bugs: every later drawing routine quietly paints in one bit-plane and the picture comes out in the wrong colours.
- load all four latches with one dummy read
latch 14040The EGA holds four 8-bit latches, one per plane. Any CPU read of video memory fills all four, even though the CPU itself only receives one byte back.
- write the latches back somewhere else: a 4-plane block copy
latchwrite 14200In write mode 1 the byte the CPU stores is discarded and the latches go out instead. One read plus one write moves 32 bits of picture across the card without the data ever crossing the ISA bus.
- blank plane 2 at display time and lose the red bit
plane 2 offColor Plane Enable is attribute controller register 12h. It forces a plane's bit to 0 on the way to the output while video memory keeps every bit it had - the standard way to build a fade or a flash without touching the frame.
- let plane 2 reach the output again
plane 2 onThe picture comes back untouched, which proves the masking happened after memory and before the output pins rather than anywhere in between.
- build a 16x16 tile map across the whole frame
tiles fillA tile engine stores a small map of tile numbers, not a screen-sized picture. Re-stamping 16x16 blocks was the only way an 8 MHz machine could keep a 112,000-byte frame moving.
- load a 16x16 four-colour glyph
sprite loadThe EGA had no hardware sprites. Every moving object was software: save the background, draw the glyph, restore the background next frame, and do it before the beam catches you.
- move the sprite to a new position
sprite move 300 160Index 0 in a sprite is not black, it is transparent - the blit skips those pixels entirely. Forget to restore the saved background and the sprite leaves a trail, the most common EGA game bug of the decade.
- shift the view one pixel with pel panning
scroll 1CRTC registers 0Ch and 0Dh at port 3D4h hold the address the frame starts from, in bytes - so 8 pixels at a time. Attribute register 13h, horizontal pel panning, supplies the 1 to 7 pixels in between.
- move a full byte and watch pel panning wrap back to zero
scroll 8Eight pixels of movement is exactly one increment of the start address, so the pel panning value returns to 0. No pixels were copied for any of this: the card simply began reading from a different address.
- poll 3DAh bit 3 for vertical retrace and lose the tear
vsync onInput Status Register 1 at 3DAh sets bit 3 during vertical retrace, the gap after the last scan line while the beam returns to the top. Change the start address inside that window and the whole next frame is drawn from one consistent value.
- Boss missionrun the full scrolling pipeline — tiles, sprite, all four planes, retrace-synced
scroll demoJohn Carmack had a 16-colour EGA scrolling smoothly in September 1990 with adaptive tile refresh: redraw only the tiles that actually changed and let the start address carry everything else. Commander Keen shipped on it that December. The received wisdom was that a PC could not scroll like a console. It could, on hardware that was six years old by then.
Certificate
This track is certifiable. Clear the boss mission in the terminal, then run EXAM EGA for the written paper: 20 server-graded questions drawn from our own bank, pass mark 14 of 20. The certificate is issued once both are done, and it carries a verification code.