← Francisco Cascalheira

Case study · LCOM (Laboratório de Computadores) · FEUP, LEIC 2025/26

Delivered

KeyBlitz

The same person who ships Prisma-and-React platforms also wrote a device driver and drew a game one pixel at a time, in C, on a microkernel with no graphics library underneath it.

Course
LCOM (Laboratório de Computadores) · FEUP, LEIC 2025/26
Team
Group 2LEIC6_1 · a team of four
Role
The RTC driver + the game's interface layer — one of four
Stack
C · MINIX 3 · VBE framebuffer · i8042 / PS-2 · interrupts
Corroboration

The game runs, and the code is open to read.

The weakest-corroborated of the four here, on purpose — the claim is breadth, not a mark.

fig. 0 · the game, redrawn

SCORE0HEATCAUGHTBLOWSATRESTSKYy = 420 · EarthQWERTYUIOPASDFGHJKLZXCVBNM
fig. 0 — KeyBlitz on MINIX 3, redrawn: the HUD, the word-asteroids, the danger line at y=420, the on-screen keyboard · my interface layer

What this document claims.

KeyBlitz is a typing-speed game for MINIX 3: words ride falling asteroids toward Earth and you type them to shoot them down, with lives, a live words-per-minute and accuracy read-out, and high scores stamped with the real-time clock. Four of us built it for FEUP's Computer Laboratory course from raw device drivers up — no engine, no framework, every frame written to the VBE linear framebuffer by hand. My part was the RTC driver and the game's whole interface layer; my three teammates wrote the keyboard, mouse, timer and video drivers.

5
devices driven
timer, keyboard, mouse, video (VBE), RTC · four on interrupt lines
0
graphics libraries
every frame drawn to the raw VBE framebuffer; text from a bitmap font, glyph by glyph
4.8k
lines of C
project/src, the whole game · wc -l
Delivered
handed in, it runs
MINIX 3 · demoed and graded, June 2026

When the mountain is gone.

Everything else in this dossier runs on top of a mountain of other people's code — a database engine, a rendering framework, a garbage collector, an operating system that hands you files and sockets and threads. That abstraction is the job most of the time, and it is the right tool. It also lets you go a long way without ever finding out whether you understand the machine underneath it.

LCOM is the course that takes the mountain away. You write in C on MINIX 3, a microkernel where talking to hardware means subscribing to an interrupt line, reading a device's registers by their hex addresses, and being handed nothing but a flat framebuffer to draw into. There is no library that draws a rectangle for you, no event loop you didn't write, no clock you didn't read out of the chip yourself. The point of building a whole game in that setting is that it can't be faked: either the interrupts are wired correctly and the thing runs at sixty frames a second, or it doesn't.

The rules of the metal.

Interrupts, not polling

Every device — timer, keyboard, mouse, real-time clock — is read through its hardware interrupt, not by burning CPU asking 'is there data yet?'. The process blocks in the kernel until hardware wakes it. Getting that wrong doesn't slow the game down; it hangs it.

No graphics library

The only thing the video hardware gives you is a pointer to a linear framebuffer — one byte per colour channel per pixel. Every asteroid, every letter, every menu box is bytes written into that buffer. Text is a bitmap font drawn one glyph at a time; there is no drawString.

One shared C codebase, four people

Four students sharing one MINIX project with no module system to hide behind — the device drivers, the game state and the interface all link into a single binary. The interfaces between them had to be agreed and held to, in a language with no guardrails.

It has to survive a live defence

LCOM is graded partly by opening the source in front of the examiner and being asked to read and justify any function on the spot. Code you don't understand is code you can't defend — so the parts you own, you own completely.

Four interrupts, one loop.

A microkernel doesn't hand you an event loop — you write one. Four devices raise hardware interrupts; a single blocking call collects them and a bitmask says which fired. This is the whole team's architecture; my line in it is the RTC.

driver_receive(ANY) — blocks in the kernel until hardware wakes it

  1. IRQ 0Timertimer_ihthe 60 Hz frame tick — advances the game and redraws
  2. IRQ 1Keyboardkbc_ihevery keystroke, through the i8042 controller
  3. IRQ 12Mousemouse_ihPS-2 packets for the menus
  4. IRQ 8RTCrtc_ih · minethe real-time clock, for score timestamps

one message loop · four interrupt lines · a bitmask says which fired

fig. 1 — one blocking driver_receive fans four interrupt lines out to their handlers · main.c · the team's architecture

A driver, and everything you see.

Two things on this screen are mine. The first you can't see: the RTC driver, the code in fig. 2 that reads the wall clock out of the CMOS chip so a high score can carry a real date and time. It is a small driver, but it is a whole one — subscribe, interrupt, read, decode, done — and it is the piece of this project that is unambiguously low-level systems work.

The second is everything you can see. The game has no graphics library, so the menu, the on-screen keyboard, the score and lives read-out, and the text rendering — every glyph drawn from a bitmap font, one at a time, into the framebuffer — is the interface layer I wrote. The asteroids and the falling words are the shared game state my teammates and I built together; the surface they're drawn onto is mine.

What I did not write, and won't claim: the keyboard, mouse, timer and video drivers. Those were my three teammates' work, and the game is theirs as much as mine.

  1. 01 subscribe

    rtc_subscribe_int enables the update-ended interrupt (bit 4 of register B) and hooks IRQ 8.

  2. 02 wait for update-ended

    The chip updates once a second; reading mid-update returns garbage. The handler waits for the update-ended flag rather than racing it.

  3. 03 read the registers

    Seconds, minutes, hours, day, month, year — each read from its own register address on the CMOS bus.

  4. 04 BCD → binary

    The clock stores each field in binary-coded decimal — 0x59 means 59, not 89. Every field is converted: (bcd & 0x0f) + (bcd >> 4) * 10.

  5. 05 stamp the score

    The decoded date and time are written next to a new high score, so the board reads '14 Jun · 21:30' — a real timestamp, from the real chip.

fig. 2 — reading the wall clock out of the CMOS chip, done properly · devices/rtc.c, mine

Why it's in the dossier.

KeyBlitz was delivered, demoed on MINIX 3, and graded. It runs — the honest corroboration for this page is exactly that, the working game and the code you could open and read, not an outside authority. That makes it the weakest-corroborated of the four case studies here: there is no council minute, no production database, no examiner's rubric quoted, because the claim doesn't need one. The claim is only that I can work at this level, and a running game built from raw drivers is its own proof.

That is the whole reason it's in the dossier. The other three case studies all live at the top of the stack — TypeScript, Prisma, Firebase, React. This one is the counterweight: a device driver and a framebuffer and a microkernel, in C, with nothing underneath. Breadth is the argument, and you can only make it by showing both ends.