Comment les entreprises de jeux "fabriquaient-elles à la main" leurs jeux avant les moteurs matures ?


La réponse à cette question est bien plus brute que la plupart des gens ne l’imaginent.

Les développeurs de jeux d’aujourd’hui ouvrent Unity ou Unreal, et l’éditeur est là, le moteur physique est là, le pipeline de rendu est là, le système d’éclairage est là. Leur travail consiste à remplir un cadre déjà construit. Cela n’existait tout simplement pas dans les années 1980. Il n’y avait pas de framework, pas de moteur, pas d’infrastructure réutilisable. Si tu voulais créer un jeu, tu devais d’abord construire une machine capable de le faire tourner, puis sur cette machine, en langage assembleur, tu lui disais de quelle couleur devait être chaque pixel.

Tout a commencé avec des pixels.

Les graphismes des premiers jeux étaient écrits directement en mémoire. Les programmeurs devaient connaître l’adresse mémoire correspondant à chaque position à l’écran. Pour dessiner un point à un endroit donné, tu écrivais une valeur à cette adresse — la valeur représentait la couleur. Pour tracer une ligne, tu écrivais une boucle, disant au CPU d’écrire tous les N octets de cette adresse à cette autre. Pour dessiner un personnage, tu convertissais chaque rangée de pixels en nombres hexadécimaux, tu les écrivais ligne par ligne, tu trouvais le bon décalage à l’écran, et tu plaçais ces nombres là.

Cette opération s’appelle aujourd’hui “rendu logiciel”. À l’époque, elle n’avait pas de nom, car il n’y avait pas d’alternative — on l’appelait simplement “comment l’image sortait”.

Quand Carmack travaillait sur le premier Wolfenstein, il faisait face à un problème spécifique : l’architecture graphique du IBM PC ne supportait pas le défilement horizontal fluide. L’écran se mettait à jour en rafraîchissant l’intégralité de l’image d’un coup, provoquant un déchirement lorsque l’image bougeait — on aurait dit qu’elle tremblait. Il a passé énormément de temps à étudier les registres bas niveau de la carte graphique et a trouvé un moyen de tromper le matériel pour faire quelque chose qu’il ne supportait pas nativement, en le simulant par logiciel — et l’image a pu défiler en douceur.

Il n’y avait pas de documentation pour cela, pas d’expérience antérieure. Il s’est simplement assis, a épluché les manuels du matériel et l’a découvert petit à petit par essais et erreurs.

C’était l’état de base du travail des programmeurs de cette époque. Tu ne faisais pas face à un système avec un manuel — tu faisais face au matériel lui-même. Tu devais connaître le matériel mieux que le matériel ne se connaissait lui-même, et trouver de l’espace dans ses interstices.

Le son était un problème d’une toute autre dimension.

Le système sonore des premiers PC était un vibreur — le PC Speaker. Il ne pouvait produire qu’un seul son : un bip. Pour jouer de la musique avec, tu devais contrôler la fréquence de vibration de ce vibreur, en commutant entre différentes fréquences à une vitesse extrêmement élevée, en utilisant la persistance auditive humaine pour donner l’impression qu’une mélodie jouait. Cette technique s’appelle PWM, la modulation de largeur d’impulsion. Le principe est la physique acoustique, l’implémentation est un contrôle de timing précis à la microseconde. Si tu te trompais ne serait-ce qu’un peu, tu n’obtenais que du bruit.

Il y avait à l’époque des programmeurs qui专门 étudiaient comment extraire plus de couches sonores du PC Speaker. Leur méthode consistait à basculer entre différentes fréquences dans des fenêtres de temps extrêmement courtes, créant un effet pseudo-stéréo. Cette technique était traitée comme de la magie noire dans la scène démo de l’époque. Tu prenais un vibreur qui ne pouvait faire que “bip”, et tu produisais quelque chose qui ressemblait à de la musique. Les autres programmeurs qui l’entendaient n’avaient aucune idée de comment tu avais fait — car le principe n’était pas intuitif. Il fallait une compréhension extrêmement précise du contrôle de timing pour y parvenir.

Quand Adlib et Sound Blaster sont arrivés, ils ont apporté le son à synthèse FM. C’était un autre système à apprendre de zéro. Le principe de la synthèse FM est d’utiliser la forme d’onde d’une fréquence pour moduler la forme d’onde d’une autre, produisant des timbres complexes. Différents paramètres de modulation produisaient différents sons d’instruments. Les programmeurs devaient ajuster eux-mêmes les paramètres, tester quelles combinaisons sonnaient comme un piano, lesquelles comme un violon, lesquelles comme une explosion. Il n’y avait pas de réponse standard — tout dépendait de l’oreille et de l’expérience. À l’époque, chaque programmeur son de chaque entreprise avait ses propres tables de paramètres accumulées. C’étaient des secrets commerciaux au sens le plus strict.

Le sens du design au niveau de la logique du jeu était une autre affaire.

Pas de moteur signifiait pas de détection de collision prête à l’emploi, pas de simulation physique prête à l’emploi, pas de framework d’IA prêt à l’emploi. Si tu voulais qu’un personnage s’arrête en atteignant un mur au lieu de le traverser, tu devais écrire la détection de collision toi-même, définir ce qu’est une “collision” toi-même, et décider comment la vitesse et la position du personnage changeraient après la collision toi-même.

La détection de collision des premiers jeux était simple et brutale : traiter à la fois le personnage et les obstacles comme des rectangles, vérifier si les deux rectangles se chevauchent, et si oui, s’arrêter. Ce schéma était rapide, mais le problème est que les vrais personnages de jeux ne sont pas des rectangles — ce sont des sprites avec des formes. Il y avait toujours un écart entre la boîte de collision rectangulaire et le graphisme réel. C’est pourquoi dans les premiers jeux, des balles qui manquaient clairement leur cible étaient quand même comptées comme des touches, ou des personnages s’arrêtaient avant d’avoir visiblement touché le mur.

Les joueurs de l’époque n’appelaient pas ça un bug. Ils appelaient ça une caractéristique du jeu. Parce qu’ils ne savaient pas que ça pouvait être différent.

Autre chose qui mérite d’être mentionnée : les premiers PC avaient une mémoire extrêmement limitée. 640 KB a été le plafond matériel pendant une décennie entière. Ce nombre aujourd’hui ne peut même pas contenir une seule capture d’écran. Les programmeurs devaient fourrer tout le contenu du jeu — graphismes, effets sonores, cartes, code logique — dans ces 640 KB, et en plus laisser de la place pour les données d’exécution.

Comment ? Compression, chargement par blocs et réutilisation.

La compression des données graphiques était une discipline à part entière. Les programmeurs devaient inventer leurs propres algorithmes de compression, rendant les données graphiques aussi petites que possible lors du stockage et les décompressant instantanément lors de l’affichage. Si la carte était trop grande pour tenir, tu la divisais en blocs, tu chargeais le bloc où se trouvait le joueur, tu le déchargeais quand il partait. Aujourd’hui, cette technique s’appelle le streaming. À l’époque, ça s’appelait “pas d’autre solution”.

Chaque octet en mémoire était disputé. En écrivant du code, les programmeurs devaient constamment penser : puis-je utiliser un type de donnée plus petit pour cette variable ? Puis-je utiliser moins de variables temporaires pour cette logique ? Puis-je réduire le nombre d’accès mémoire dans cette boucle ? Cette façon de penser est largement inutile pour les programmeurs d’aujourd’hui. Le matériel moderne a suffisamment de marge mémoire et les compilateurs sont assez intelligents en optimisation — tu n’as pas besoin de compter chaque octet.

Mais les programmeurs de cette époque avaient dans la tête le fonctionnement complet de l’ordinateur. Des cycles d’instruction du CPU à la disposition de la mémoire en passant par les registres du GPU, ils devaient comprendre chaque couche, car chaque couche était un interstice qu’ils pourraient avoir à exploiter.

Carmack a écrit un morceau de code pour calculer l’inverse de la racine carrée, avec un commentaire qui disait “what the fuck”. Ce code utilisait une astuce de manipulation de bits extrêmement contre-intuitive pour approximer rapidement l’inverse de la racine carrée, bien plus rapide que la bibliothèque mathématique standard — le tout pour économiser du temps de calcul dans le rendu 3D. Ce bout de code est devenu plus tard une légende dans la culture des programmeurs, cité encore et encore, car il représentait une façon de penser qui a depuis disparu : la méthode consistant à extraire de la performance des mathématiques et de la créativité dans les limites du matériel.

Les programmeurs de jeux de cette époque étaient plus proches d’un hybride d’ingénieurs et de scientifiques. Le problème qu’ils résolvaient n’était pas seulement “comment implémenter cette fonctionnalité” — c’était “est-ce que cette fonctionnalité peut être implémentée dans les limites physiques de cette machine ?”

Ce sont deux questions très différentes.

La première question a une réponse standard : consulter la documentation, appeler l’API, suivre les étapes. La deuxième question n’a pas de réponse standard. Tu dois inventer la réponse toi-même. Parfois la réponse existe, parfois non. Tu devais d’abord déterminer dans quel cas tu te trouvais, puis décider quoi faire.

L’industrie du jeu d’aujourd’hui est un système collaboratif massif. Entreprises de moteurs, entreprises de middleware, entreprises d’outils — chaque couche a quelqu’un qui y travaille. Les développeurs se tiennent au sommet de ce système, concentrés sur le contenu lui-même. C’est un progrès, c’est une bonne chose — cela permet à plus de gens de créer des jeux, et laisse l’échelle et la complexité des jeux dépasser de loin ce qui était possible autrefois.

Mais cette époque de construction de jeux à partir des pixels avait quelque chose qui n’existe plus aujourd’hui.

Tu ouvres le jeu, et tu sais d’où vient chaque point à l’écran, comment chaque son a été produit, comment chaque collision a été jugée. Parce que tout cela a été écrit par toi, ligne par ligne. Rien n’a été fait par quelqu’un d’autre à ta place.

Ce sentiment a un nom. Cela s’appelle le contrôle absolu.

Alors, les grands qui développaient des jeux à cette époque — c’étaient de vrais grands. Vraiment remarquables.