tutorial · gerla.cctutorial · gerla.cc
Il ciclo di vita di un giocoThe life cycle of a game
Un videogioco, sotto tutto il resto, è un anello che gira: parte, aspetta la pressione del tasto, dà tre vite, le porta via una a una, dice game over, salva il record e ricomincia. Vediamo com'è fatto quell'anello, fase per fase, sui due ambienti in gioco: Commodore 64 (6502) e Mega Drive (68000). Tutto in assembler, con il codice spiegato riga per riga dai commenti. A video game, underneath everything else, is a loop that spins: it boots, waits for the button, gives three lives, takes them away one by one, says game over, saves the record and starts again. Let's see how that loop is built, phase by phase, on the two environments at play: Commodore 64 (6502) and Mega Drive (68000). All in assembler, with the code explained line by line by the comments.
Nota: nel gioco vero, sul Mega Drive scrivo la logica in C. Qui però mostro l'ossatura in 68000 assembly, perché un tutorial sul loop rende di più a nudo: è esattamente quello che il compilatore produce, e che la macchina esegue davvero.
Note: in the real game, on the Mega Drive I write the logic in C. Here, though, I show the skeleton in 68000 assembly, because a tutorial on the loop reads better bare: it's exactly what the compiler produces, and what the machine actually runs.
accendi la macchina, prepara tuttopower on, set everything up
aspetta che premi FUOCO / STARTwaits for FIRE / START
Accendere la macchinaPowering on
All'accensione la macchina esegue il primo indirizzo che le diciamo. Prima di ogni cosa mettiamo a tacere le interruzioni, sistemiamo lo schermo e i registri video, e azzeriamo le variabili: quante vite, che punteggio. Poi si salta alla schermata home. È il gesto d'apertura, si fa una volta sola.
At power-on the machine runs the first address we point it to. Before anything, we silence the interrupts, set up the screen and video registers, and zero the variables: how many lives, what score. Then we jump to the title screen. It's the opening move, done exactly once.
C64 · 6502
Mega Drive · 68000
Stessa idea, due dialetti: spegni il rumore, prepara il video, imposta vite e punteggio, vai al titolo.
Same idea, two dialects: silence the noise, prepare the video, set lives and score, go to the title.
Aspettare che premi il tastoWaiting for the button
La schermata home fa una cosa sola: aspetta. Disegna «PREMI FUOCO» e poi gira in un piccolo anello leggendo il joystick a ogni frame, finché non premi. Il trucco è la pazienza: un giro dell'anello per ogni quadro video, così il controllo resta reattivo senza mangiarsi la macchina. Appena arriva il tasto, si salta alla partita.
The title screen does one thing: it waits. It draws "PRESS FIRE" and then spins in a small loop reading the joystick every frame, until you press. The trick is patience: one turn of the loop per video frame, so the control stays responsive without hogging the machine. The moment the button arrives, it jumps to the game.
C64 · 6502
Mega Drive · 68000
Un ciclo che non fa nulla se non ascoltare. Il gioco vero comincia solo quando decidi tu.
A loop that does nothing but listen. The real game begins only when you decide.
Il cuore: un frame alla voltaThe heart: one frame at a time
Qui vive il gioco. Ogni giro dell'anello è un fotogramma: aspetti l'inizio del quadro (il vblank, il momento in cui il pennello video torna in cima), leggi i comandi, muovi il personaggio, muovi i nemici, controlli le collisioni. Se sei ancora vivo, riparte il giro. Sessanta volte al secondo, sempre uguale. Tutta l'azione che vedi è questo anello che gira in fretta.
This is where the game lives. Every turn of the loop is a frame: you wait for the start of the frame (the vblank, the moment the video beam returns to the top), read the inputs, move the player, move the enemies, check collisions. If you're still alive, the loop restarts. Sixty times a second, always the same. All the action you see is this loop spinning fast.
C64 · 6502
Mega Drive · 68000
Il wait_vblank è il metronomo: senza, il gioco andrebbe a velocità diverse su macchine diverse. Con, tutto scorre a tempo.
The wait_vblank is the metronome: without it, the game would run at different speeds on different machines. With it, everything flows in time.
Morire, e contare le viteDying, and counting lives
Quando muori, l'anello della partita si spezza e si arriva qui. La regola è semplice: togli una vita. Se ne restano, rimetti il personaggio in pista e torni a giocare. Se sei a zero, la strada porta al game over. Una sottrazione decide tutto.
When you die, the game loop breaks and you land here. The rule is simple: take away one life. If any are left, put the player back on the field and return to play. If you're at zero, the road leads to game over. One subtraction decides everything.
C64 · 6502
Mega Drive · 68000
Il dec/subq abbassa il contatore e, di colpo, imposta anche il segnale «è zero?». Il salto subito dopo legge quel segnale: niente confronti in più.
The dec/subq lowers the counter and, at once, also sets the "is it zero?" flag. The branch right after reads that flag: no extra comparisons.
Salvare il punteggio più altoSaving the high score
Finita la partita, si confronta il punteggio con il record. Se l'hai battuto, il record si aggiorna. Ed è qui che i due mondi si separano davvero. Sul Mega Drive la cartuccia può avere una SRAM con batteria: scrivi lì il record e resta anche a console spenta, per sempre. Sul C64 non c'è batteria: il record vive in RAM per la sessione, e se lo vuoi eterno lo salvi su disco. Stessa idea, due modi di ricordare.
When the game ends, the score is compared with the record. If you beat it, the record updates. And this is where the two worlds truly part ways. On the Mega Drive the cartridge can have a battery-backed SRAM: write the record there and it survives even with the console off, forever. On the C64 there's no battery: the record lives in RAM for the session, and if you want it eternal you save it to disk. Same idea, two ways to remember.
C64 · 6502
Mega Drive · 68000
Il confronto a 16/32 bit si fa un pezzo alla volta, dal byte più pesante: se quello decide, il resto non serve nemmeno guardarlo.
The 16/32-bit comparison is done a piece at a time, from the heaviest byte: if that one decides, the rest isn't even worth looking at.
E si ricominciaAnd round again
Ultimo anello: si aspetta un attimo, o un tasto, e si torna alla schermata home. Il cerchio si chiude e la macchina è di nuovo pronta ad aspettare il prossimo giocatore. È lo stesso jmp title del primo giorno: da qui, tutto ricomincia.
Last loop: wait a moment, or a button, and go back to the title screen. The circle closes and the machine is ready again to wait for the next player. It's the same jmp title from day one: from here, everything starts over.
C64 · 6502
Mega Drive · 68000
Nota che il record NON si azzera: vite e punteggio ripartono, ma il primato resta. È la memoria del gioco.
Note that the record does NOT reset: lives and score start over, but the best stays. It's the game's memory.
Un anello dentro un anelloA loop inside a loop
Tutto qui: un anello grande (home → partita → game over → home) e dentro un anello piccolo che gira sessanta volte al secondo (la partita, frame per frame). Cambiano il dialetto e i dettagli della macchina, ma la forma è la stessa dal 1982 a oggi, e anche nel gioco HTML5 da cui sono partito. Impari questo, e hai imparato l'ossatura di qualunque gioco.
That's all: a big loop (title → play → game over → title) and inside it a small loop spinning sixty times a second (the game, frame by frame). The dialect and the machine details change, but the shape is the same from 1982 to today, and in the HTML5 game I started from too. Learn this, and you've learned the skeleton of any game.