Réutilisation du code, rétro-ingénierie et collaboration

illustrations illustrations illustrations illustrations illustrations illustrations illustrations
post-thumb

Publié le 30 juin 2022 par Andrew Owen (18 minutes)

Dans cet article, je vais parler de la réutilisation du code, de l’ingénierie inverse et de l’importance de la collaboration. L’exemple que je vais utiliser est mon propre ordinateur de loisir, qui a évolué pour devenir le Chloe 280SE. Par souci de simplicité, je vais présenter les choses dans l’ordre chronologique, en commençant par les années 1960. Cet article va être long. Vous devriez prendre une tasse de café et une boîte de beignets.

En 1964, au Dartmouth College, aux États-Unis, les Américains d’origine hongroise John George Kemeny et Thomas Eugene Kurtz ont mis au point le langage de programmation BASIC (code d’instruction symbolique universel pour débutants). Contrairement aux langages de haut niveau existants qui étaient destinés aux informaticiens et aux mathématiciens, BASIC a été conçu pour être utilisé par tout le monde. C’est pourquoi son jeu d’instructions est basé sur l’anglais.

En juillet 1975, Microsoft a publié une version de BASIC pour l’ordinateur amateur MITS Altair 8800. Elle a été écrite par Paul Allen et Bill Gates sur un émulateur Intel 8080 fonctionnant sur un DEC PDP-11. À cette époque, Kemeny et Kurtz avaient répondu aux principales critiques formulées à l’encontre de BASIC, à savoir qu’il manquait de structure et qu’il encourageait les mauvaises habitudes de programmation. Mais Microsoft BASIC a été inspiré par le BASIC-PLUS de DEC, qui était essentiellement du Dartmouth BASIC avec l’ajout des commandes MID$ et LEFT$ pour le découpage des chaînes de caractères.

Les BASIC les moins chanceux ont pris de mauvaises habitudes et un langage vulgaire. Nous ne penserions pas plus tôt à utiliser le BASIC de la rue que nous ne penserions à utiliser FORTRAN" *-Kemeny & Kurtz_

Les premières versions de Microsoft BASIC ne prenaient en charge que les nombres entiers, mais Mote Davidoff était convaincu qu’il était possible d’utiliser des nombres à virgule flottante, ce qui a conduit à la création du format Microsoft Binary (MBF). Cette version a ensuite été fournie avec la majorité des micro-ordinateurs 8 bits et a permis à Gates et Allen de faire leur première fortune. Notamment, elle a été utilisée dans tous les ordinateurs Commodore 8 bits à partir du PET, après que Jack Tramiel a négocié une licence permanente à prix fixe qui ne nécessitait pas de mention de Microsoft à l’écran.

En 1978, lorsque l’ANSI Standard for Minimal BASIC (X3.60-1978) a été lancé, il était principalement basé sur la version de Microsoft. L’année suivante, en Angleterre, Clive Sinclair confie à Jim Westwood la création du micro-ordinateur ZX80. Inspiré par l’enthousiasme de son fils pour le TRS-80, Sinclair voulait créer quelque chose de beaucoup plus abordable. Cela excluait l’octroi d’une licence pour Microsoft BASIC, et Sinclair s’est donc tourné vers John Grant, de Nine Tiles.

Grant n’avait pas beaucoup d’argent à gagner sur l’affaire, mais il pensait que le projet en valait la peine. Il a écrit le 4K integer BASIC dans l’assembleur de Zilog sur son système de développement ZDS1. Tout en cherchant des moyens d’économiser de l’espace mémoire, il a conçu le système d’entrée par mot-clé, supprimant le besoin d’un tokenizer. Il a également inclus la vérification syntaxique à l’entrée, une fonctionnalité partagée avec Atari BASIC (également écrit en 1979) mais absente de la plupart des autres versions.

Avant même le lancement du ZX80, Sinclair préparait déjà son successeur, le ZX81 (également connu sous le nom de TS1000). Ferranti avait développé un précurseur du field programmable gate array (FPGA) appelé uncommitted logica array (ULA). Westwood a remplacé presque tous les circuits du ZX80 par un seul ULA. Cela a permis de réduire de moitié le coût de la machine. Outre l’ULA, les seules puces présentes sur le circuit imprimé étaient le CPU, la RAM et la ROM, ce qui en fait un précurseur des SoC (system on a chip).

Sinclair s’est à nouveau adressé à Grant pour le BASIC, qui à son tour a engagé Steve Vickers, mathématicien de Cambridge, pour l’écrire. Sinclair lui a donné 4K supplémentaires pour travailler et lui a demandé d’améliorer le package mathématique. Vickers a conservé une grande partie du code de Grant, n’apportant des modifications que là où c’était strictement nécessaire. Au lieu de MID$ et LEFT$, il a permis à l’utilisateur de sélectionner une plage de la chaîne avec s$ (_f_TO_l_), où f est le premier caractère et l est le dernier caractère de la sous-chaîne de s$.

Pour les routines en virgule flottante, Vickers a utilisé un format presque identique à la version 40 bits du MBF. Mais il a ajouté la possibilité de stocker des nombres entiers entre -65535 et 65535. L’utilisateur n’a pas besoin de spécifier les types de variables. Et il est plus rapide que les BASIC qui ne stockent les nombres qu’en virgule flottante, comme celui de Commodore.

Malgré quelques problèmes de production au début, le ZX81 s’est vendu à plus de 1,5 million d’exemplaires. En conséquence Sinclair a décidé de créer une version couleur. Westwood travaillant sur d’autres projets, c’est à Richard Altwasser que revient la tâche de concevoir le matériel. Cette fois, Vickers a reçu 16K pour le BASIC. Ils ont travaillé en étroite collaboration avec le designer industriel Rick Dickinson, car les exigences en matière de clavier étaient étroitement liées au BASIC.

Grant et Vickers auraient aimé recommencer, mais ils n’en ont pas eu le temps. Le ZX81 BASIC a donc été utilisé comme point de départ, avec l’ajout de couleurs, de graphiques et de commandes sonores. Vickers a encore amélioré le paquetage mathématique. Et comme la conception du matériel était incomplète, il a créé une couche d’abstraction matérielle de canaux et de flux. Mais trois mois avant le lancement, Vickers et Altwasser ont tous deux démissionné pour former la société Cantab afin de produire le Jupiter ACE (essentiellement un ZX81 avec Forth à la place de BASIC).

Le ZX Spectrum est lancé en avril 1982. Mais le travail sur le RS232, le réseau et le système de stockage de microcassettes n’était pas terminé, et le BASIC était incomplet. Sinclair a regroupé ces fonctionnalités dans un complément matériel appelé Interface 1. Il disposait de son propre micrologiciel écrit par Ian Logan (qui avait pris comme point de départ le désassemblage par Frank O’Hara du BASIC du ZX81 et avait écrit un désassemblage du BASIC du ZX Spectrum).

Il y avait plus de 1K d’espace libre dans le ROM BASIC. En utilisant le désassemblage de Logan, les hackers disposant de graveurs d’EEPROM ont pu créer des versions personnalisées de la ROM. L’ajout le plus courant était un tokenizer. Il n’était plus nécessaire de mémoriser des combinaisons de touches ou de se référer au clavier pour saisir des mots-clés. Beaucoup de ces tokenizers supportaient les abréviations utilisant un point ( . ), une autre caractéristique partagée avec l’Atari BASIC.

En 1983, Timex a introduit le TS2068, sa version du ZX Spectrum, avec un son et un matériel graphique améliorés et un 24K BASIC étendu (avec l’aide de Vickers). En 1984, Timex Portugal a lancé le TC2048, une version réduite du TS2068 sans la puce sonore et utilisant l’ancien BASIC 16K. En 1985, Investronica a lancé une version du ZX Spectrum avec 128K de RAM, la même puce sonore que le TS2068 et un BASIC 32K étendu (écrit par Martin Brennan, Kevin Males et quelqu’un avec les initiales AT). En 1986, Unimor et Polbrit ont lancé en Pologne une machine dérivée de la version portugaise du TS2068.

En 1986, la société Sinclair n’a plus d’argent et est vendue à Amstrad. Au cours de l’audit préalable, on a découvert que Sinclair n’avait jamais payé Nine Tiles et Amstrad a dû acheter les droits du ZX Spectrum BASIC. Nine Tiles a conservé les droits sur les versions antérieures.

En conséquence, pendant le développement du SAM Coupé, MGT a approché Nine Tiles pour obtenir une licence sur le progiciel mathématique de Vickers, mais le prix demandé était trop élevé. Andrew Wright a écrit SAM BASIC en commençant par la ROM BASIC du ZX Spectrum et en remplaçant un module à la fois jusqu’à ce qu’il ait un programme entièrement nouveau qui soit largement rétrocompatible.

Avance rapide jusqu’en 1999. À cette époque, des centaines de clones de ZX Spectrum ont été créés, en particulier dans les pays de l’ex-Union soviétique. Il y avait probablement presque autant de compatibles ZX Spectrum que de Commodore 64 (l’ordinateur 8 bits le plus vendu de tous les temps). Les discussions sur Usenet ont montré qu’il y avait un appétit pour une machine compatible avec le ZX Spectrum, modestement améliorée, qui pourrait faire tourner autant de logiciels existants que possible, et je me suis mis à réfléchir à la manière d’y parvenir.

En Pologne, Jarek Adamski avait déjà créé une modification pour les modèles Timex qui leur permettait d’exécuter des logiciels écrits pour la machine Investronica, le modèle le plus populaire à l’époque. J’ai eu l’idée de connecter 128K de RAM supplémentaires à l’unité de gestion de la mémoire (MMU) de la Timex. Dans la TS2068, la MMU était connectée aux 8K de BASIC supplémentaires et à un port cartouche de 64K. Sur le TC2048, elle n’était connectée à rien. Le fait d’avoir 32K de RAM dans la zone normalement occupée par la ROM permettait à la machine d’émuler des systèmes antérieurs tels que le ZX80, le ZX81, le Jupiter ACE et le TS2068.

La puce sonore a été installée et connectée aux deux jeux de ports utilisés par les modèles Timex et Investronica. Nous l’avons appelé le ZX Spectrum SE. Le prototype utilisait une version du 32K BASIC, modifiée pour améliorer la rétrocompatibilité avec le modèle original du ZX Spectrum. J’ai également imaginé un système de palette pour augmenter les couleurs disponibles de 16 à 256, mais sa mise en œuvre dans le prototype aurait nécessité le remplacement de la version Timex de l’ULA, qui à l’époque n’était pas documentée.

Le fait d’avoir un prototype réel a suffi pour que la machine soit prise en charge par l’émulateur FUSE. Le matériel étant terminé, j’ai commencé à travailler sur le BASIC. Au départ, il s’agissait de combiner tous mes patches préférés à partir de ROMs modifiés disponibles publiquement. Ceux-ci comprenaient la commande LIST étendue de Ian Collier, le support hexadécimal de Jonathan Graham Hartson, le tokenzier de Jiri LeMac, la gestion améliorée du curseur de Milan Pikula, et de nombreuses fonctionnalités de Slavomír Lábsky, ainsi que de nombreuses corrections de bogues documentées publiquement.

En 2008, Chris Smith développait son propre clone du ZX Spectrum en logique discrète. Il s’est lié d’amitié avec le patron de Datel, une société surtout connue pour la production de cartouches de triche pour les micro-ordinateurs et les consoles. Datel a découpé au laser et scanné la puce ULA pour Smith, ce qui lui a permis d’en faire l’ingénierie inverse. Il a consigné ses découvertes dans un livre intitulé How to Design a Microcomputer que j’ai édité. Il a également eu l’idée de créer un plug-in de remplacement de l’ULA basé sur un CPLD ou un FPGA et m’a informé qu’il y aurait de la place pour prendre en charge l’amélioration de ma palette.

J’ai réuni une équipe de passionnés pour m’aider à élaborer les spécifications de ce qui allait devenir ULAplus sur Google Wave. Cette équipe comprenait des concepteurs de matériel, des auteurs d’émulateurs et des utilisateurs finaux. Je reviendrai plus en détail sur ULAplus dans un prochain article sur le matériel Chloe 280SE, mais il a été initialement mis en œuvre par Alessandro Dorigatti en tant que noyau FPGA pour la cartouche Turbo Chameleon 64 pour le Commodore 64 en 2009.

En 2010, j’ai créé la version 2.0 de SE Basic avec le support de ULAplus, y compris la commande PALETTE. J’utilisais alors un assembleur croisé au lieu de patcher directement la ROM originale, mais il était toujours basé sur un code de copyright propriétaire. Il était autorisé à être utilisé dans l’émulation, mais ne pouvait pas être utilisé dans le matériel (le propriétaire actuel, Comcast, maintient cet arrangement). Il est apparu clairement qu’un micrologiciel de remplacement était nécessaire.

Matt Westcott avait indépendamment commencé à coder le projet Open82, un micrologiciel de remplacement open source pour le ZX Spectrum. Je me suis demandé si Grant et Wright ne seraient pas ouverts à l’idée d’accorder une nouvelle licence pour le ZX81 et les SAM BASIC sous une licence open source. Je leur ai donc demandé et ils ont répondu par l’affirmative. En combinant ces routines avec le code non dérivé de SE Basic et Open82, et en utilisant les routines de cassette d’un périphérique SAM Coupé appelé The Messenger, j’étais très proche d’un firmware de remplacement open source entièrement fonctionnel, mais il me manquait encore quelques routines clés.

Selon la loi britannique, qui s’appliquait au ZX Spectrum BASIC à l’époque, il était légal de faire de l’ingénierie inverse de logiciels à des fins d’interopérabilité sans avoir besoin d’une salle blanche (dans une salle blanche, ceux qui font de l’ingénierie inverse ne peuvent pas être familiers avec le code). L’unité centrale Z80 fournit de multiples instructions qui peuvent créer un binaire différent mais aboutir au même résultat (par exemple, vous pouvez remplacer LD A, H ; OR L par LD A, L ; OR H). C’est ainsi que The Messenger a été créé et j’ai donc pensé qu’il pouvait être utilisé pour le code manquant. La mise en garde était qu’il n’était pas légal de fournir de la documentation, ce qui signifiait que la source resterait non commentée.

En avril 2011, OpenSE BASIC 3.0 a été publié avec l’approbation de toutes les personnes dont le code était inclus. Cette version a ensuite été incluse dans la distribution principale de Debian, ce qui a permis à FUSE d’être également inclus. À la fin de l’année, j’ai forké le code pour créer SE Basic IV qui visait spécifiquement le matériel ZX Spectrum SE. Il s’agissait d’une ROM de 32K avec deux versions distinctes de BASIC ; la version standard et une version 80 colonnes utilisant le mode vidéo haute résolution de Timex. Le passage d’une version à l’autre se faisait à l’aide d’une commande MODE.

En Espagne, en 2013, une équipe de passionnés du ZX Spectrum s’est réunie pour concevoir un clone basé sur un FPGA (le ZX-Uno). Initialement, le clone ne devait supporter que les modèles originaux. Mais j’ai persuadé Miguel Angel Rodríguez Jódar d’ajouter la spécification ZX Spectrum SE avec ULAplus. Lorsque la version financée par le crowdfunding a été publiée en 2016, elle incluait OpenSE BASIC 3 et SE Basic IV, ce qui en faisait le premier clone légal du ZX Spectrum sans licence.

En 2017, un clone de ZX Spectrum sous licence, similaire mais incompatible avec le ZX-Uno, a été financé avec succès sur Kickstarter. À ce moment-là, j’ai réalisé que la fenêtre d’opportunité du ZX Spectrum SE s’était refermée, et que si je voulais poursuivre le projet, il fallait lui donner une nouvelle direction. C’est ainsi que le Chloe 280SE a été conçu comme un noyau FPGA pour le ZX-Uno qui ferait le meilleur usage possible du matériel.

Mais il y avait un problème. Le ZX-Uno prenait en charge une interface de carte SD, mais le seul système d’exploitation disponible pour cette carte était fermé. Le développement d’un nouvel interpréteur BASIC était donc un véritable casse-tête. La solution consistait à faire de l’ingénierie inverse sur le noyau du système d’exploitation, en utilisant les mêmes techniques que celles utilisées à l’origine pour SE Basic. C’est ainsi que j’ai créé UnoDOS 3 (nommé d’après le matériel hôte et un jeu de mots en espagnol).

Le problème du système d’exploitation étant résolu, j’ai enfin pu assembler en 2019 le ZX-Uno que j’avais depuis 2014, et j’ai pu commencer à développer SE Basic 4.2. Au cas où vous vous poseriez la question, la version 4.1 était une tentative big bang ratée de refactorisation du code. Cette approche était une erreur et j’ai donc recommencé avec OpenSE Basic 3.

Pour l’anecdote, dans la Chloe, les premiers 16K de BASIC et les premiers 8K du système d’exploitation sont stockés en ROM. Les 7K restants du BASIC et les 4K du système d’exploitation sont copiés en RAM à partir d’une ROM de démarrage de 16K qui initialise le système lors d’un redémarrage à froid. Le framebuffer est partagé avec la RAM principale, mais en fonctionnement normal, il est paginé. La zone qui contenait le framebuffer contient maintenant les 7 derniers Ko de BASIC, y compris les commandes du système de fichiers qui ne peuvent pas être placées dans les 16 Ko inférieurs de la ROM (parce qu’ils paginent dans la ROM du système d’exploitation et la RAM dans cette zone). Les avantages de cette approche sont que la ROM de démarrage peut vérifier les mises à jour du micrologiciel et que la ROM du système d’exploitation n’a pas besoin de charger quoi que ce soit à partir du disque.

J’avais commencé à utiliser GitHub lorsque j’ai commencé le développement de SE Basic IV, mais maintenant je m’y appuie fortement. Ce qui avait commencé comme un projet personnel en 1999 allait devenir une pièce de portefeuille, démontrant les pratiques de développement modernes, y compris les API, la compilation croisée, les opérations de développement, les documents en tant que code, l’émulation, les IDE, les ressources JSON, la localisation, et ainsi de suite.

Une fois l’infrastructure en place, j’ai commencé à travailler sur le code. Je l’ai ramené à quelque chose qui ressemble au ZX81 BASIC, sans son, sans graphique, sans imprimante et sans commandes de système de fichiers. La compatibilité ascendante n’étant plus un souci, j’ai décidé de rendre la syntaxe aussi proche que possible de Microsoft BASIC, en partant du principe que c’est ce que la plupart des gens connaissent.

J’ai travaillé pendant environ un an sur le projet avant d’avoir l’équivalent de l’angoisse de la page blanche pour les développeurs. La plupart des fonctionnalités de base étaient réalisées, mais il manquait encore les commandes graphiques et sonores, et le code que j’avais devait être nettoyé. J’avais besoin de changer de rythme.

J’ai donc contacté Translation Commons, avec qui j’avais déjà travaillé en tant qu’éditeur bénévole, pour obtenir de l’aide pour la localisation. Grâce à un groupe de traducteurs bénévoles, j’ai pu étendre la couverture à plus de 20 langues. Aujourd’hui, avec l’aide de la traduction automatique, ce nombre est plus proche de 50.

Pendant ce temps, Daniel Nagy travaillait depuis plusieurs années sur son propre firmware pour le ZX Spectrum. Nous avions échangé des idées et il avait utilisé quelques idées de SE Basic IV dans son projet, mais il n’avait pas encore contribué. Il était impatient, mais il avait besoin d’un environnement de construction Linux.

Pendant des années, j’ai utilisé l’assembleur Zeus de Simon Brattel, principalement parce qu’il a toujours bien répondu aux demandes de fonctionnalités. Cependant, Apple a abandonné le support des binaires 32 bits, ce qui m’a empêché de faire tourner des applications Windows comme Zeus sous WINE, et j’étais donc déjà à la recherche d’une alternative. Heureusement, j’ai découvert RASM, dont l’auteur Edouard Berge est tout aussi ouvert aux demandes de fonctionnalités.

L’une des autres choses que j’ai faites pendant que j’étais bloqué a été de travailler sur la documentation utilisateur, en la basant sur la documentation de Rob Hagemans pour sa version de PC-BASIC qui est sous licence Creative Commons. Cela a constitué une référence inestimable sur la façon dont les nouvelles commandes étaient censées fonctionner, car Daniel ne connaissait pas le dialecte de Microsoft.

Début 2022, en l’espace d’un mois, Daniel a apporté une énorme contribution au projet et j’ai retrouvé mon enthousiasme. Il a converti la logique booléenne en logique bit à bit, ajouté les fonctions mathématiques manquantes, ajouté le découpage des chaînes MID$ et LEFT$ (tout en conservant la méthode de Vickers), modifié l’ordre de préséance, corrigé le détokéniseur et ajouté la prise en charge des noms de variables longs.

Le simple fait d’avoir quelqu’un d’autre avec qui travailler sur le code a donné un coup de fouet à ma productivité. Dans la version suivante, j’ai refait le code du système de fichiers, y compris l’accès aux fichiers basé sur les canaux et les flux, j’ai ajouté un pré-parseur de compatibilité, j’ai corrigé le support des macros, et j’ai écrit une série d’actions GitHub pour automatiser la construction et le déploiement.

Dans la même version, Daniel a ajouté les boucles IFTHENELSE et WHILEWEND. Et dans la version suivante, j’ai ajouté une API publique pour le système d’exploitation et un système d’aide en ligne basé sur un sous-ensemble de Markdown et de HTML. Dans la prochaine version, nous allons nous attaquer au son et aux graphismes.

Et c’est l’histoire partielle du firmware de Chloe jusqu’à présent. De nombreuses personnes que je n’ai pas nommées dans cet article ont donné de leur temps pour tester, écrire des outils ou soutenir le projet d’une autre manière. Je leur suis reconnaissant et j’espère que ce projet est un témoignage de la valeur de la réutilisation du code, de l’ingénierie inverse et, surtout, de la collaboration.

Mise à jour

J’ai publié la dernière version bêta publique du BASIC en juillet 2023 et je suis passé au travail sur les fonctions de haut niveau du système d’exploitation. L’une des dernières pièces du puzzle était l’écriture d’un convertisseur de nombres entiers non signés de 40 bits en virgule flottante de 32 bits pour l’accès aléatoire aux fichiers. Puis le matériel de développement original a rendu l’âme. Mais j’ai maintenant un nouveau matériel. SE Basic IV est maintenant son propre dialecte de BASIC. Ses caractéristiques sont les suivantes:

  • Modes vidéo palettisés à 40 colonnes (16 couleurs) et 80 colonnes (2 couleurs).
  • Evaluation permanente des expressions (utilisation des variables comme noms de fichiers).
  • Format de paquet d’application avec prise en charge de la transformation des programmes BASIC en applications.
  • Saisie automatique des nombres entiers et des nombres à virgule flottante.
  • Logique bitwise (AND, NOT, OR, XOR).
  • Système d’aide intégré.
  • Choix du découpage des chaînes de Microsoft (LEFT$, MID$ et RIGHT$) ou de Sinclair (TO).
  • Caractères composables (supporte le vietnamien).
  • Système de fichiers sur disque (pas de bandes).
  • Manipulation de la mémoire sur deux octets (DEEK, DOKE).
  • Gestion des erreurs (ON ERROR…, TRACE).
  • Contrôle de flux (IFTHENELSE, WHILEWEND).
  • Accès aléatoire complet aux fichiers depuis BASIC (OPEN, CLOSE, SEEK).
  • Support des claviers de taille normale (DEL, HOME, END et ainsi de suite).
  • Commandes graphiques en mode 40 colonnes (CIRCLE, DRAW, PLOT).
  • Localisation des jeux de caractères, des messages d’erreur et de la disposition du clavier.
  • Noms de variables longs.
  • Entrée de nombres à la Motorola (% ; binaire, @ ; octal, $ ; hexadécimal).
  • Super BREAK (interruption non masquable).
  • Vérification de la syntaxe à l’entrée.
  • Commande PLAY avec PSG à 6 canaux et support MIDI.
  • Fonctions récursives définies par l’utilisateur.
  • Abréviations et raccourcis (& ; AND, ~ ; NOT ; | ; OR, ? ; PRINT, ' ; REM’).
  • Annulation de NEW (OLD).
  • Canaux matériels définis par l’utilisateur.
  • Jeux de caractères définis par l’utilisateur (256 caractères).
  • Macros définies par l’utilisateur.
  • Modes d’écran définis par l’utilisateur.