After Asteroids, Rainbow-OS gets its second arcade classic: a full
Space Invaders, launched with the invaders shell
command and running at 800×600 in the graphical console. The best part is
how little new code it took — everything the game needs already existed.

Standing on the previous game’s shoulders
Adding Asteroids had forced three pieces of infrastructure into the kernel: a
PIT timer for frame pacing, a held-key state table in the keyboard driver, and a
one-pass svga_blit() that pushes a RAM back buffer to video memory.
Space Invaders reuses all of it unchanged. The new module mirrors the Asteroids
one almost exactly — draw into a back buffer, blit once per frame, advance
on the timer — so the change touched only a new file plus a few lines of
shell and build wiring. No driver changes at all.
It is also simpler than Asteroids: there is no rotation, no vectors,
no fixed-point trigonometry. Space Invaders is a grid, and the whole game runs on
plain integer arithmetic.
The marching fleet
The aliens are a 5×11 grid of small bitmap sprites — three types
(the classic squid, crab and octopus shapes), each with two animation frames,
worth 30, 20 and 10 points by row. Rather than move each invader individually,
the whole fleet shares one offset and a direction. On a timed cadence it steps
sideways; when the leftmost or rightmost living invader would cross the screen
edge, the fleet instead drops a row and reverses, toggling its animation frame as
it goes.
The signature acceleration falls out naturally from one line: the number of
frames between steps is proportional to how many invaders are still alive.
int interval = 2 + (alive_count * 22) / (ROWS * COLS);
Start with 55 invaders and the fleet crawls; shoot it down to the last one and
it skitters across the screen at top speed — exactly the rising tension the
original is famous for.
Sprites from a handful of bytes
Each invader is an 11×8 bitmap stored as eight 16-bit rows, drawn at
3× scale by a tiny blitter that walks the bits and fills a small block for
each set pixel:
static void gsprite(int x, int y, const uint16_t *rows, int nrows,
int ncols, int scale, uint8_t color) {
for (int r = 0; r < nrows; r++)
for (int col = 0; col < ncols; col++)
if (rows[r] & (1 << (ncols - 1 - col)))
gfill(x + col*scale, y + r*scale, scale, scale, color);
}
The same routine draws the player’s cannon. Text for the score, wave and lives
HUD is blitted straight from the VGA ROM font, just like the console itself.
Bombs, bunkers and lives
The lowest invader in a random column periodically drops a bomb. The player
fires one bullet at a time (the classic rule), and collisions are simple
axis-aligned box tests between the bullet and each living invader. The four green
bunkers are the nice touch: each is a coarse grid of little
blocks, and both your bullets and the invaders‘ bombs chip blocks away on contact
— so cover erodes over a round exactly as it should. Take a bomb to the
cannon and you lose one of three lives; clear the fleet and a new, faster wave
drops in; let the invaders reach the bottom and it’s game over.

The loop
Like Asteroids, the game advances one frame every three 100 Hz timer
ticks (about 33 FPS), hlt-ing in between. Each frame it polls the
held-key state for left/right/fire, marches the fleet on its shrinking timer,
moves bullets and bombs, resolves collisions, and redraws. Press Q
and you drop straight back to a clean shell prompt with your score.
Two arcade games down, both rendered pixel-by-pixel on a 486 with a
from-scratch kernel — and the second one mostly just reused the first.
