Impara a programmare in C sviluppando un emulatore per il CHIP-8
◷ 7 marzo 2026
Quando ho frequentato l'università un dubbio che mi continuava ad accompagnare le giornate di studio era relativo alla programmazione. Sapevo che stavo studiando un sacco di idee interessanti e stavo imparando ad utilizzare la matematica per ragionare sul mondo. C'era però qualcosa che mancava. Nello specifico, non sentivo particolari progressi nel contesto della scrittura del codice. Nella programmazione avevo la sensazione di aver imparato solamente le cose elementari. Studiavo quasi tutti i giorni una buona parte del pomeriggio, eppure non mi sentivo ancora un "bravo programmatore".
Ma come si impara a programmare?
Queste domande sono buffe. Perchè tutti ce le chiediamo, la riposta è tremendamente banale, ma ciascuno di noi ci arriva in modi diversi. Personalmente ho iniziato a capire la risposta a questa domanda nel corso di sicurezza informatica che ho avuto la fortuna di seguire il terzo anno della triennale. Non perché in quel corso abbiamo programmato tanto, ma perché è stato il primo corso in tutta la mia vita che non poteva essere studiato. Non potevi "studiare la sicurezza informatica". La dovevi provare, sulla tua pelle. Ti dovevi sporcare le mani, sul terminale. Dovevi capire i mille componenti e come venivano messi assieme, per trovare delle falle, delle vulnerabilità, e sfruttarle per ottenere qualcosa di nuovo. L'esame finale è durato 6 ore. In queste 6 ore, avevamo accesso ad internet, potevamo ricercare qualsiasi cosa. Eppure, ciò non ha reso l'esame meno difficile, ed infatti sono state necessarie tutte e 6 le ore. È stato uno degli esami più belli che abbia mai fatto.
La sicurezza informatica mi ha fatto notare che il modo in cui stavo approcciando l'apprendimento era incompleto. Mi concentravo troppo sulla teoria. Passavo troppo tempo sui libri, a scrivere formule, e non abbastanza sul terminale, a scrivere codice, eseguire comandi, ed in generale a vedere le conseguenze delle mie computazioni. Capito questo, ho cambiato il tiro. E finalmente ho capito come imparare a programmare.
E quindi, come si impara a programmare?
Si impara a programmare programmando progetti a basso livello che necessitano di utilizzare le più fondamentali e caratterizzanti conoscenze informatiche. Si impara a programmare scrivendo, da zero, progetti con un livello di complessità medio-alto. E qui per complessità non mi sto solo riferendo alle righe di codice, ma anche alla natura di quelle righe, ovvero alla logica che stiamo implementando. Si impara a programmare sviluppando progetti che ci forzano a pensare al design delle astrazioni, e che ci forzano poi a pensare a come implementarle quelle astrazioni. Che cos'è una astrazione utile? Quali sono le caratteristiche semantiche del linguaggio che sto utilizzando, e come queste mi possono supportare e/o vincolare nello sviluppo?
Il basso livello qui è richiesto per una semplice ragione: forza la mente a ricostruire soluzioni a problemi già risolti da altre persone. La mente umana è pigra. Cerca, in ogni momento, di ottenere il beneficio massimo con lo sforzo minimo. Questa è una legge della natura. Quando ti presento una soluzione già esistente, tu la utilizzi. Non ti metti lì ad impararla, nella maggior parte dei casi. Ed è proprio per andare contro a questo meccanismo, a questa pigrizia umana, che invece è necessario mettersi lì e rifiutare, in un esercizio didattico, le soluzioni già esistenti, per crearsi la propria soluzione. Non sarà la soluzione più efficiente, ma sarà la nostra, e questo è l'unico vero modo di imparare a programmare. Tutti i programmatori bravi sono passati per questa strada. Non c'è altra via.
Avendo compreso questo meccanismo, ho deciso di portare nell'offerta formativa del progetto Esadecimale una serie di corsi incentrati esclusivamente sullo sviluppo di progetti interessanti in diversi linguaggi di programmazione. Oggi voglio parlare del primo di questi corsi, che ho finito di registrare da poco: un emulatore per il CHIP-8.
Il CHIP-8 è un linguaggio interpretato, sviluppato da Joseph Weisbecker negli anni 70 per semplificare la scrittura di videogiochi per i primi microcomputers come il COSMAC VIC. Attualmente vari giochi sono stati scritti in questo linguaggio.

Sviluppare un emulatore per il CHIP-8 significa scrivere un programma, l'emulatore, che è in grado di leggere ed eseguire un programma scritto per il CHIP-8.

Per fare questo è necessario capire l'architettura della macchina che si vuole emulare e come le diverse istruzioni vanno a modificare questa architettura.
struct Chip8 {
// simple flag to signal if the CHIP-8 is running or not.
unsigned char running;
// The Chip 8 has 35 opcodes which are all two bytes long.
unsigned short opcode;
// The Chip 8 has 4K memory in total
//
// The systems memory map:
//
// 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
// 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
// 0x200-0xFFF - Program ROM and work RAM
//
unsigned char memory[4096];
// ...
}
In altre parole, sviluppare un emulatore per il CHIP-8 significa scrivere la logica di lettura, interpretazione, ed esecuzione delle classiche istruzioni del CHIP-8.
[leo@esadecimale ]$ hexdump -C test-ibm-logo.ch8
00000000 00 e0 a2 2a 60 0c 61 08 d0 1f 70 09 a2 39 d0 1f |...*`.a...p..9..|
00000010 a2 48 70 08 d0 1f 70 04 a2 57 d0 1f 70 08 a2 66 |.Hp...p..W..p..f|
00000020 d0 1f 70 08 a2 75 d0 1f 12 28 ff 00 ff 00 3c 00 |..p..u...(....<.|
00000030 3c 00 3c 00 3c 00 ff 00 ff ff 00 ff 00 38 00 3f |<.<.<........8.?|
00000040 00 3f 00 38 00 ff 00 ff 80 00 e0 00 e0 00 80 00 |.?.8............|
00000050 80 00 e0 00 e0 00 80 f8 00 fc 00 3e 00 3f 00 3b |...........>.?.;|
00000060 00 39 00 f8 00 f8 03 00 07 00 0f 00 bf 00 fb 00 |.9..............|
00000070 f3 00 e3 00 43 e5 05 e2 00 85 07 81 01 80 02 80 |....C...........|
00000080 07 e1 06 e7 |....|
00000084
È anche necessario scrivere il codice che connette la logica interna del CHIP-8 al nostro particolare computer, in modo da poter gestire corretamente gli aspetti di output come grafica e suono e l'aspetto di input. Senza questo layer di piattaforma infatti l'emulatore sarebbe solo un cervello senza corpo: funzionante, ma imperscrutabile.
while (chip8->running) {
uint32_t startFrameTime = SDL_GetTicks();
handleInput(chip8);
for (int i = 0; i < INSTRUCTIONS_PER_FRAME; i++) {
chip8Step(chip8);
}
chip8UpdateTimers(chip8);
if (chip8->draw == 1) {
drawScreen(chip8, renderer);
chip8->draw = 0;
}
uint32_t frameDuration = SDL_GetTicks() - startFrameTime;
if (frameDuration < MILLISECS_PER_FRAME) {
SDL_Delay(MILLISECS_PER_FRAME - frameDuration);
}
}
Il corso Sviluppo Emulatore CHIP-8 in C mostra step-by-step come scrivere questo emulatore e come scrivere un layer di piattaforma utilizzando la libreria SDL2.

Per onorare l'obiettivo e la visione del progetto Esadecimale, ovvero migliorare la didattica dell'informatica, il codice sviluppato durante il corso è stato pubblicato come free-software sotto licenza GPLv3. Attualmente è possibile trovare il software su GitHub.

Ti ringrazio per la lettura e buona fortuna nel tuo percorso di apprendimento!
Leonardo Tamiano.