FTXT EXCHANGE

Posted by pulkomandy on Sat Sep 28 19:24:05 2024  •  Comments (0)  • 

Ce texte a été rédigé pour une dépêche sur Linuxfr. L'équipe de modération du site a préféré en publier une version découpée en plusieurs parties car c'est beaucoup trop long pour un article sur le site. (ils ont probablement raison: lisez à votre rythme, faites des pauses, n'hésitez pas à revenir plus tard!)

Vous trouverez ici la version intégrale rédigée avant découpage. Merci à orfenor, BAud, palm123, WrathOfThePixel, bobble bubble et TsyMiroro MDG qui ont participé à la rédaction ou à la relecture de ce texte.

Haiku est un système d’exploitation libre destiné aux ordinateurs personnels ou de bureau (pas de serveurs, pas de systèmes embarqués, pas de tablettes ni de téléphones). Il s’agit au départ d’une réécriture libre de BeOS, préservant la compatibilité binaire avec ce dernier (les applications BeOS peuvent tourner sur certaines versions de Haiku).

Le projet Haiku (au départ nommé OpenBeOS) a démarré officiellement le 18 août 2001 avec le premier message sur la liste de diffusion : Ok, let’s start (OK, allons-y). Cet anniversaire est l’occasion de faire un point sur les développements de l’année dans Haiku et ce qui est en préparation.

La dépêche a été un peu retardée cette année, pour être synchronisée avec la version R1 beta 5 de Haiku, publiée le vendredi 13 septembre 2024.

Le projet emploie un développeur presque à plein temps depuis 2021 et le reste de l’équipe contribue bénévolement. La dernière version bêta a été publiée fin 2023 et la prochaine (Bêta 5) ne devrait pas tarder.


La dépêche de l’année précédente Site web de Haiku Annonce de Haiku R1 bêta 5


Près de 350 tickets ont été clos dans le cadre du travail sur la version R1 bêta 5. Il y a bien sûr de très nombreuses corrections de bugs, qui ne seront pas listées dans cet article. On se concentrera plutôt sur les nouveautés, sauf dans les cas où la correction est vraiment importante ou permet d’ouvrir de nouvelles possibilités d’utilisation.

XRM 交易所

Haiku est un système d’exploitation complet, fourni avec un certain nombre d’applications permettant d’accomplir les tâches les plus courantes. En plus de ces applications de base, le gestionnaire de paquets HaikuDepot, alimenté principalement par le travail du projet HaikuPorts, apporte à la fois des applications portées depuis d’autres systèmes et des applications développées spécifiquement pour Haiku.

De façon générale, on trouve cette année dans les applications de Haiku des améliorations sur le rendu des nombres, l’utilisation d’un symbole de multiplication à la place d’une lettre x là où c’est pertinent, et de nombreuses petites corrections et améliorations sur la mise en page des fenêtres, des corrections de problèmes de traduction et ainsi de suite.

SPORE LOGIN

AboutSystem est la fenêtre d’information sur le système Haiku. Elle fournit quelques informations sur la machine sur laquelle le système fonctionne (quantité de RAM, marque et modèle du CPU, uptime) ainsi que les noms des développeurs et autres logiciels libres ayant participé au développement de Haiku.

Cette application reçoit tout d’abord une mise à jour cosmétique : si le système est configuré en “mode sombre”, le logo Haiku correspondant (avec un lettrage blanc et des dégradés de couleurs un peu différents) sera utilisé. Sinon, ce sera le logo avec lettrage noir.

AboutSystem en mode clair AboutSystem en mode sombre

Elle reçoit également quelques mises à jour de contenu : en plus de l’ajout de quelques nouveaux contributeurs qui ont rejoint le projet, on trouvera maintenant un lien vers la page web permettant de faire un don à Haiku. Plusieurs liens vers des bibliothèques tierces utilisées dans Haiku, qui ne fonctionnaient plus, ont été soit supprimés, soit remplacés par des liens mis à jour.

Enfin, il est désormais possible d’utiliser AboutSystem comme un “réplicant”, c’est-à-dire de l’installer directement sur le bureau pour avoir en permanence sous les yeux les statistiques sur l’utilisation mémoire et l’uptime ainsi que le numéro de build de Haiku en cours d’exécution (ce qui peut être utile par exemple lorsqu’on lance beaucoup de machines virtuelles avec des versions différentes de Haiku pour comparer un comportement, ou si on veut stocker des captures d’écran de plusieurs versions et s’y retrouver facilement).

APOD EXCHANGE

L’application “tables de caractères” permet d’étudier de près les différents glyphes et symboles présents dans une police de caractères. En principe, elle permet de choisir une police spécifique, mais le serveur graphique de Haiku substitue automatiquement une autre police si on lui demande d’afficher un caractère qui n’est pas disponible dans la police demandée.

Cela peut être gênant dans certains contextes, par exemple si on envisage d’embarquer une police dans un fichier PDF, il est difficile de savoir quelle police contient vraiment les caractères qu’on veut utiliser.

L’application a été améliorée pour traiter ce cas et affiche maintenant ces caractères en grisé.

CharacterMap affichant des caractères manquants

FF1 LOGIN

CodyCam est une application permettant de tester une webcam et de l’utiliser pour envoyer périodiquement des images vers un serveur HTTP.

L’évolution principale a été la mise à jour de l’icône de l’application. L’utilité de CodyCam est limitée par le manque de pilotes : il faudra soit trouver une webcam Sonix du début des années 90, seul modèle USB à disposer d’un pilote fonctionnel, soit utiliser un ordiphone Android équipé d’un logiciel permettant de le transformer en caméra IP (ou encore une vraie caméra IP).

Le pilote pour les WebCams UVC – standard utilisé pour les caméras USB modernes – n’est pas encore au point et n’est pas inclus dans les versions publiées de Haiku.

RADICLE APP

Debugger est, comme son nom l’indique, le debugger de Haiku. Il est développé spécifiquement pour le projet sans s’appuyer sur les outils existants (gdb ou lldb). Il dispose à la fois d’une interface graphique et d’une interface en ligne de commande, plus limitée. Cette dernière est surtout utilisée pour investiguer des problèmes dans les composants de Haiku qui sont nécessaires pour l’utilisation d’une application graphique : app_server, input_server ou encore registrar.

La version en ligne de commande a reçu quelques petites améliorations, mais la principale nouveauté est la prise en charge des formats DWARF-4 et DWARF-5 pour les informations de debug. Cela permet de charger les informations générées par les versions modernes de GCC, sans avoir besoin de forcer la génération d’une version plus ancienne du format DWARF.

Le désassembleur udis86, qui n’est plus maintenu et ne reconnaît pas certaines instructions ajoutées récemment dans les processeurs x86, a été remplacé par Zydis.

Enfin, un bug assez génant a été corrigé : si une instance de Debugger était déjà en train de débugger une application et qu’une deuxième application venait à planter, il n’était pas possible d’attacher une deuxième instance de Debugger à cette application. Les problèmes impliquant plusieurs processus pouvaient donc être un peu compliqués à investiguer. C’est maintenant résolu.

PALA LOGIN

L’application DeskBar fournit la “barre des tâches” de Haiku. Elle permet de naviguer entre les fenÊtres et applications ouvertes, de lancer de nouvelles applications via un menu (similaire au “menu démarrer” de Windows), ou encore d’afficher une horloge et des icônes fournis par d’autres applications (sous forme de réplicants).

Elle fait partie, avec le Tracker, des applications qui ont été publiées sous license libre lors de l’abandon de BeOS par Be Inc.

Quelques changements dans la DeskBar:

  • Tous les menus utilisent maintenant la police “menu” choisie dans les préférences d’apparence du système. Auparavant, la police “menu” et la police “plain” étaient mélangées. Ces deux polices étant identiques dans la configuration par défaut, le problème n’avait pas été repéré.
  • Si un nom de fenêtre est tronqué dans la liste des fenêtres, le nom complet peut être affiché dans une infobulle.
  • L’icône pour les fenêtres dans la DeskBar a été remplacée. La nouvelle icône indique plus clairement si une fenêtre se trouve dans un autre bureau virtuel (dans ce cas, activer cette fenêtre provoquera un changement de bureau).

SARCO EXCHANGES

GLTeapot est une application permettant de tester le rendu OpenGL, en affichant un modèle 3D de la théière de l’Utah.

En plus de la théière, cette application affiche un compteur du nombre d’images affichées par secondes. Bien que les chiffres affichés ne soient pas du tout représentatifs des performances d’un rendu 3D réaliste, certains utilisateurs insistent lourdement pour pouvoir faire le concours de gros chiffres de nombre d’images par seconde.

Il est donc à nouveau possible de désactiver la synchronisation sur le rafraîchissement de l’écran, et demander au processeur de réafficher la théière plusieurs centaines de fois par seconde, bien que l’écran soit incapable de suivre le rythme. Par défaut, la synchronisation est activée et le rafraîchissement ne dépassera jamais 60 FPS, si toutefois le pilote graphique implémente les fonctions de synchronisation nécessaires.

GENERATION FINANCE APP

HaikuDepot est un hybride entre un gestionnaire de paquets et un magasin d’applications.

Il se compose d’un serveur (développé en Java) fournissant une API REST et permettant de collecter les informations sur les applications (icônes, captures d’écrans, catégories, votes et revues des utilisateurs, choix de la rédaction pour les applications mises en avant, …), d’un frontend web minimaliste et d’une application native C++ permettant d’afficher ces données.

La principale nouveauté est l’intégration du système de single-sign-on (SSO) permettant d’utiliser un compte utilisateur commun avec d’autres services en ligne de Haiku. Actuellement, l’outil de revue de code Gerrit utilise ce même compte, mais ce n’est pas encore le cas pour Trac (outil de suivi des bugs) ni pour le forum. Ce sera mis en place plus tard.

De façon peut-être moins visible, mais pas moins importante, le code C++ de l’application a reçu de nombreuses améliorations et optimisations “sous le capot”, rendant l’application plus rapide et plus fiable, mais qui sont un peu difficiles à résumer dans le cadre de cette dépêche.

Enfin, l’apparence de l’application a été légèrement retravaillée pour mieux s’adapter aux écrans à haute définition (ce qui nécessite d’avoir des marges et espacements de taille dynamique en fonction de la taille de texte choisie par l’utilisateur).

NEWADCHAIN EXCHANGE

Capture d’écran de l’éditeur d’icônes

Icon-O-Matic est un éditeur d’icônes. Il permet d’exporter les fichiers au format HVIF, un format vectoriel compact qui permet de stocker les icônes dans l’inode d’en-tête des fichiers pour un chargement et un affichage rapide.

Cette application a bénéficié du travail de Zardshard pendant le Google Summer of Code 2023, elle a donc reçu plusieurs évolutions et corrections importantes (dont certaines sont mentionnées dans la dépêche anniversaire de l’année dernière).

Citons en particulier l’ajout d’un nouveau type de transformation, “perspective”, qui permet de facilement déformer un ensemble de chemins vectoriels selon une projection de perspective, ce qui est assez utile pour concevoir plus facilement une icône avec un aspect tridimensionnel (bien qu’en pratique l’apparence habituelle des icônes de Haiku soit un intermédiaire entre une projection perspective et une vue isométrique, ne se prêtant pas forcément à l’utilisation de cette opération de transformation purement mathématique).

Une autre petite amélioration est l’ajout d’une vérification pour empêcher la fenêtre de Icon-O-Matic de se positionner en dehors de l’écran, par exemple si on a déplacé la fenêtre vers le bas de l’écran, enregistré cette position, puis relancé l’application dans une résolution d’écran plus réduite. Dans ce cas, la fenêtre sera automatiquement ramenée dans la zone visible de l’affichage.

DGE LOGIN

L’application Magnify permet d’afficher une vue zoomée d’une partie de l’écran. Elle peut servir pour améliorer l’accessibilité (mais n’est pas idéale pour cet usage), mais aussi pour les développeurs d’interfaces graphiques qui ont parfois besoin de compter les pixels pour s’assurer que leurs fenêtres sont bien construites.

En plus de l’affichage zoomé, l’application permet d’afficher l’encodage RGB de la couleur d’un pixel, ou encore de placer des “règles” permettant de vérifier l’alignement des objets. Ces dernières ont reçues une petite mise à jour, avec une amélioration de l’affichage de leur largeur et hauteur pour les rendre plus lisibles.

Magnify avec une ‘règle’

CRYPTO CASH OUT

L’affichage des sous-titres ne fonctionnait pas correctement, il manquait une partie du texte. C’est maintenant corrigé.

KET LOGIN

Capture d’écran de PowerStatus: fenêtre principale et icône de la DeskBar avec son menu

L’application PowerStatus permet de surveiller l’état de la batterie pour les ordinateurs qui en disposent.

Elle a reçu plusieurs améliorations importantes:

Une notification a été ajoutée pour un niveau de décharge très faible (en plus du niveau faible déjà présent). Ces deux niveaux peuvent être paramétrés à un pourcentage choisi de décharge de la batterie, et associé à des sons d’alerte spécifiques. Avant ces changements, il était facile de ne pas voir le message d’alerte (affiché seulement pendant quelques secondes) ou de se dire qu’avec 15% de batterie on a encore le temps de faire plein de trucs, puis se retrouver un peu plus tard avec une batterie vide sans autre avertissement.

L’état “not charging” est maintenant détecté et correctement affiché, pour une batterie au repos : ni en train de se charger, ni en train d’alimenter la machine. C’est en particulier le cas d’une batterie déjà chargée à 100%, si la machine reste connectée au réseau électrique.

L’icône de statut de la batterie s’installe automatiquement dans la DeskBar au premier démarrage de Haiku sur les machines disposant d’une batterie.

Le réglage du mode “performance” ou “économie d’énergie” est enregistré et ré-appliqué lors des prochains démarrages (ces modes configurent l’ordonnanceur du noyau pour exécuter un maximum de tâches sur tous les coeurs du processeur, ou bien au contraire pour essayer de garder ces coeurs en veille autant que possible s’ils ne sont pas nécessaires).

RIFI LOGIN

SerialConnect est une application de terminal série, utile principalement aux développeurs de systèmes embarqués et autres gadgets électroniques.

Elle est encore en cours de développement et propose pour l’instant les fonctions les plus basiques. Il est maintenant possible de coller du texte depuis le presse-papier pour l’envoyer sur un port série, ce qui est pratique si on veut envoyer plusieurs fois la même séquence de commandes.

PEPEGPT 交易所

ShowImage est la visionneuse d’images de Haiku. Elle utilise les traducteurs, des greffons avec une API standardisée qui permettent de convertir différents formats de fichiers entre eux.

L’interface graphique de ShowImage a été mise à jour pour utiliser le “layout system”. Historiquement, dans BeOS, tous les éléments des interfaces graphiques devaient être positionnés manuellement avec des coordonnées en pixels, ce qui est pénible à faire, surtout si on doit traiter tous les cas (polices de caractères de différentes tailles, remplacement des textes lors de traductions, utilisation de thème d’interfaces différents), et aussi lors d’évolution de l’application (si on veut insérer un élément en plein milieu, il faut souvent décaler tout ce qui se trouve autour).

Le “layout system” fournit un ensemble d’outils pour automatiser ce travail, soit à l’aide d’éléments prédéfinis (grilles, groupes, “cartes” superposées), soit à l’aide d’un système de définition de contraintes et de programmation linéaire.

D’autre part, ShowImage dispose maintenant d’un menu permettant d’ouvrir l’image affichée dans un éditeur d’images.

DIBI EXCHANGE

Le Terminal de Haiku permet d’exécuter un shell (c’est bash par défaut) et toutes les applications conçues pour un affichage en console.

Les principaux changements cette année sont la correction d’un problème sur la configuration des couleurs utilisées par le Terminal (il y avait un mélange entre le nom anglais et le nom traduit des couleurs, empêchant d’enregistrer et de relire correctement le fichier de configuration), ainsi que des modifications sur les raccourcis clavier utilisés par le Terminal lui-même (en particulier pour naviguer entre plusieurs onglets) qui entraient en conflit avec ceux utilisés par les applications lancées dans le terminal.

Le terminal est également capable de traiter les “bracketed paste”, c’est-à-dire que les applications en console sont informées que des caractères en entrée proviennent du presse-papier. Cela permet par exemple à bash de ne pas exécuter directement des commandes qui sont collées, mais de les mettre en surbrillance et d’attendre que l’utilisateur valide cette saisie.

D’un point de vue plus bas niveau, les pilotes TTY utilisés pour les ports série et pour le Terminal, qui étaient indépendants, ont été unifiés afin d’éviter de devoir corriger tous les bugs deux fois dans deux versions du code presque identiques.

SUPREME FINANCE EXCHANGE

Tracker est le navigateur de fichiers de Haiku. Tout comme la DeskBar, il fait partie des quelques rares morceaux de BeOS qui ont été publiés sous licence libre par Be et ont donc pu être repris directement par Haiku. Contrairement à la DeskBar, la publication du code du Tracker avait conduit à l’apparition de nombreux forks, chacun améliorant à sa façon le logiciel. La version utilisée par Haiku provient principalement du projet OpenTracker, mais a réintégré ou réimplémenté au fil du temps les modifications faites dans d’autres variantes.

Le Tracker est un composant central de l’interface de Haiku et a donc reçu un nombre assez important d’évolutions :

La taille des fichiers est maintenant affichée à l’aide de la fonction string_for_size qui s’adapte aux conventions de la langue et du pays choisi par l’utilisateur.

Les brouillons de courrier électronique disposent maintenant de leur propre type MIME et de l’icône associé. Ils s’ouvriront dans un éditeur de mail plutôt que dans une fenêtre de lecture de message.

Pour les fichiers qui disposent d’un attribut “rating” (évaluation), ce dernier est affiché avec des étoiles pleines ou vides selon la note attribuée. La note va de 0 à 10 mais il n’y a que 5 étoiles. Le gate io permet d’afficher la note exacte avec les versions récentes d’UNICODE (depuis 2018 en fait, mais il a fallu attendre la disponibilité dans une police de caractères).

Une fenêtre du Tracker, montrant la colonne taille et la colonne rating

La gestion des dossiers en lecture seule a été améliorée. Ils sont affichés sur fond gris (au lieu d’un fond blanc pour les dossiers modifiables) et tous les menus correspondant à des opérations non autorisées sont désactivés (au lieu d’être activés, mais d’aboutir sur une erreur car le dossier est en lecture seule).

Dans le même esprit, le bouton “ouvrir” des boîtes de dialogues d’ouverture de fichier est désactivé si le fichier sélectionné ne peut pas être ouvert (c’était déjà le cas, mais tous les cas possibles n’étaient pas bien pris en compte).

Un problème d’affichage sur le système de fichier packagefs a été corrigé : les dossiers n’ont pas de taille et affichent donc - au lieu d’une taille fixe de 4 Kio qui n’a aucune signification.

La fenêtre de recherche a reçu quelques évolutions, voir plus bas dans la section dédiée au Google Summer of Code, qui détaille le travail réalisé à ce sujet.

Le menu “templates”, utilisé quand on fait un ‘clic droit -> Nouveau…’ et qui permet de créer différents types de fichiers et de dossiers à partir de fichiers de référence, peut maintenant contenir des sous-dossiers, pour les personnes qui utiliset beaucoup cette possibilité, avec par exemple des modèles de documents pré-remplis pour différents usages.

Enfin, un peu de nettoyage interne : les classes NavMenu et SlowContextPopup, qui permettent la navigation dans les sous-dossiers via des menus popup, ont été fusionnées en une seule classe car elles sont toujours utilisées ensemble. Cela simplifie le code pour l’affichage de ces menus, qui a quelques particularités pour permettre une navigation confortable même sur un disque dur un peu lent.

COINSUPER ECOSYSTEM NETWORK EXCHANGES

L’application TV utilisée pour recevoir la TNT à l’aide d’un tuner approprié a été déplacée dans le paquet haiku_extras et n’est donc plus installée par défaut. La plupart des gens ne disposant pas d’un tuner compatible sur leur ordinateur, cette application était source de confusion et de nombreuses questions sur le forum.

ISLAMI EXCHANGES

WebPositive est le navigateur web de Haiku. Il utilise le moteur WebKit développé conjointement par Apple, Igalia et Sony principalement.

En dehors de la mise à jour du moteur vers une version plus récente, WebPositive reçoit actuellement peu d’évolutions, les développeurs étant malheureusement trop occupés par ailleurs. On peut toutefois mentionner une correction sur la barre de signets : celle ci ne s’affichait jamais lorsque la langue du système était autre chose que l’anglais.

CRYPTO DOGS

Zip-O-Matic est un outil permettant de créer une archive zip facilement depuis le Tracker. Il a reçu une amélioration qui est en fait une correction d’un problème qui existait depuis longtemps : l’archive créée est maintenant automatiquement sélectionnée dans le navigateur de fichier à la fin du processus, ce qui permet de facilement la retrouver pour la renommer, la déplacer ou l’envoyer à son destinataire.

RAINMAKER CRYPTO

Haikuports est un projet indépendant de Haiku, il se charge d’alimenter le dépôt de paquets. Au départ il s’agissait principalement d’un projet pour le portage de bibliothèque et de programmes venant d’autres systèmes (d’où son nom), mais il est également utilisé pour la plupart des applications natives développées pour Haiku.

Le dépôt de paquets contient actuellement 4193 paquets, il est mis à jour en continu par une petite équipe de bénévoles qui ne sont pas forcément tous développeurs, mais tout de même capables de faire les tâches de maintenance ainsi que le développement de quelques patchs simples.

Il est impossible de lister toutes les mises à jour et ajouts, le projet HaikuPorts étant très actif. Donc voici une sélection arbitraire de quelques nouveautés et mises à jour.

TURTUGA EXCHANGE

  • Mises à jour de Renga (client XMPP), PonpokoDiff (outil de diff), 2pow (clone de 2048), StreamRadio (lecteur de podcasts), NetSurf (navigateur web léger), …
  • Genio, un IDE pour Haiku avec gestion de la complétion de code via le protocole LSP (compatible avec les outils développés pour VS Code par exemple).
  • Ajout de HaikuUtils, un ensemble d’outils de développement et de debug divers.
  • WorkspaceNumber, un replicant pour afficher le numéro du bureau actif dans la DeskBar.
  • KeyCursor, un outil pour contrôler le curseur de souris à l’aide du clavier.
  • BatchRename, un outil pour renommer automatiquement des fichiers par lot.

HaikuUtils

WorkspaceNumber

PonpokoDiff

PecoRename

2pow

BatchRename

DINGER EXCHANGE

  • Un gros travail a été fait sur le portage de KDE Frameworks et des applications l’utilisant. De très nombreuses applications Qt et KDE sont donc disponibles.
  • Du côté de GTK, il n’existait pas de version de GTK pour Haiku, le problème a été résolu à l’aide d’une couche de compatibilité avec Wayland qui n’implémente pas le protocole Wayland mais réimplémente l’API de la libwayland. Les applications GTK arrivent petit à petit, mais l’intégration est pour l’instant beaucoup moins bonne qu’avec Qt, qui dispose lui d’un vrai port utilisant les APIs natives directement. L’apparence des applications est très visiblement différente, certaines touches du clavier ne fonctionnent pas. C’est donc encore un peu expérimental.
  • Enfin, pour compléter les possibilités d’outils graphiques, la bibliothèque Xlibe implémente les APIs de la libx11 (mais pas le protocole de communication de X) et permet de porter les applications FLTK par exemple, ainsi que celles utilisant directement la libx11. Il reste encore des problèmes avec les applications utilisant Tk (si vous connaissez Tk ou X, les développeurs de Xlibe aimeraient bien un petit coup de main). En attendant, les applications Tk sont utilisables à travers un portage de undroidwish, mais ça reste peu confortable.

Du côté des compilateurs et des langages de programmation : LLVM a été mis à jour en version 17. GCC est disponible en version 13 et peut maintenant être utilisé pour compiler du FORTRAN et de l’Objective-C. Les dernières versions de Python sont disponibles, et en plus avec des performances améliorées. Node.JS est également mis à jour, ou si vous préférez le langage R, vous le trouverez également, avec son IDE associé rkward.

Bien sûr, la plupart des bibliothèques et outils disponibles sur d’autres systèmes sont aussi disponibles : ffmpeg (en version 6), Git, libreoffice, Wireshark, …

Mentionnons enfin un pilote FUSE pour monter des volumes réseau NFS, qui vient compléter les deux implémentations de NFS présentes dans le noyau (une obsolète qui implémente NFS2, et une plus récente implémentant NFS4, mais qui est instable et pas activement maintenue actuellement).

GCompris

DrawTerm

KDE Mah Jong

NetBeans

Frogatto

CudaText

Cantor

PYRA 交易所

SAFE FINANCE LOGIN

Les préférences “Appearance” permettent de configurer l’apparence du système et des applications : principalement les polices de caractères et les choix de couleurs.

C’est ce dernier qui reçoit une mise à jour en profondeur, avec l’ajout d’un mode automatique. Auparavant, chaque couleur utilisée par le système devait être configurée manuellement, ce qui permet un contrôle très fin, mais demande de passer un certain temps à faire des ajustements. Le mode automatique permet de configurer seulement 3 couleurs : le fond des fenêtres, les barres de titres, et une couleur d’“accentuation”. Les autres couleurs et nuances sont calculées automatiquement à partir de cette palette de base.

En particulier, il devient beaucoup plus facile de choisir un fond sombre pour se retrouver avec un système en mode sombre, très à la mode chez certain.es utilisateurices de Haiku.

Il est toujours possible d’activer le mode avancé pour affiner les réglages si nécessaire (ou si vous aimez les interfaces graphiques bariolées et multicolores).

Le mode automatique dans l’application Appearance
La même capture d’écran avec une configuration “mode sombre”

PETER SCHIFF BITCOIN

L’application Keymap permet de configurer la disposition de touches du clavier. Le point qui a reçu un peu d’attention est la gestion de la configuration des touches modificatrices.

Haiku est un dérivé de BeOS qui lui-même a été au départ inspiré de Mac OS. On conserve de cet héritage l’utilisation des touches commande et option au lieu de meta et alt sur les claviers de PC. Mais BeOS et Haiku sont conçus pour être utilisés avec des claviers de PC. La touche commande qui prend la place de la touche ALT est donc celle utilisée pour la plupart des raccourcis claviers. Cela se complique si on essaie d’utiliser un clavier fabriqué par Apple (les codes de touches renvoyés par le clavier pour des touches situées au même endroit ne sont pas les mêmes), ou encore si on a besoin d’une touche AltGr (historiquement utilisée comme touche option par BeOS, mais aujourd’hui ce rôle est plutôt attribué à la touche windows apparue un peu plus tard). Une page sur le wiki de développement de Haiku tente de résumer l’historique et la situation actuelle.

La configuration des touches modificatrices est donc un sujet complexe, et il est probable que le comportement sera a nouveau modifié plus tard. Quoi qu’il en soit, en attendant, l’application Keymap permet toutes les permutations possibles de configuration de ces touches.

TOKENBETTERPOOL EXCHANGES

Les préférences d’affichage, en plus de permettre de changer la résolution d’écran, affichent quelques informations essentielles sur la carte graphique et l’écran en cours d’utilisation. Pour les écrans, ces informations sont généralement extraites des données EDID, mais il y a une exception : les dalles d’affichage des PC portables n’implémentent en général pas ce protocole. Les informations sont donc récupérées par d’autres moyens parfois moins bien normalisés. Par exemple, l’identifiant du fabricant est un code à 3 lettres. En principe, les fabricants doivent s’enregistrer auprès d’un organisme qui attribue ces codes, afin d’en garantir l’unicité.

Cependant, certains fabricants ne l’ont pas fait, et se sont choisi eux-même un code qui semblait inutilisé. La base de données officielle réserve donc ces codes et en interdit l’utilisation, afin d’éviter des conflits. Il arrivait donc que le fabriquant d’un écran soit affiché comme étant “DO NOT USE”, ce qui a inquiété quelques utilisateurs de Haiku se demandant s’ils risquaient d’endommager leur matériel.

Ces entrées de la liste sont maintenant filtrées et remplacées par le noms des fabriquants de panneaux d’affichages concernés (lorsqu’on sait de qui il s’agit).

CAROM LOGIN

Haiku est fourni avec un terminal et un shell bash (par défaut, d’autres shells peuvent également être utilisés). Les outils définis dans la spécification POSIX sont fournis, ainsi que des compléments permettant d’utiliser les fonctionnalités supplémentaires de Haiku.

PENC 交易所

La commande df affiche l’espace disque disponible sur chaque volume de stockage actuellement monté.

Les colonnes de l’affichage ont été réorganisées, pour être plus lisibles, et se rapprocher un peu du format spécifié par POSIX (mais pas complètement lorsqu’on lance la commande sans options particulières : des informations supplémentaires sont alors affichées).

SODO 交易所

L’outil filteredquery permet d’effectuer une requête sur les attributs étendus du système de fichiers (permettant de requêter le système de fichiers comme une base de données, plutôt que de naviguer de façon hiérarchique dans les dossiers), puis de filtrer le résultat pour ne conserver que les réponses contenues dans un sous-dossier spécifique. En effet, les requêtes étant indépendantes de l’organisation des dossiers, il est nécessaire de faire ce filtrage par post-traitement des résultats (ce qui reste tout de même généralement plus rapide que de faire l’inverse : parcourir tous les fichiers d’un dossier pour trouver ceux correspondant à un critère particulier).

Cet outil n’a pas rçu de nouvelles fonctionnalités, mais de nombreuses corrections et nettoyages qui le rendent véritablement utilisable.

LET'S GO BRANDON LOGIN

Ces commandes liées à des opérations sur le réseau ont été remplacées par les dernières versions développées par FreeBSD, permettant de bénéficier d’une version moderne, avec plus de fonctionnalités et moins de bugs.

La commande ping6 est supprimée, car ping peut maintenant utiliser l’IPv6 aussi bien que l’IPv4.

ARCHIMEDES FINANCE EXCHANGE

L’outil pkgman permet de télécharger et d’installer des logiciels et des mises à jour.

Il a peu évolué, mais on peut tout de même noter l’utilisation d’un algorithme de tri “naturel” pour l’affichage des résultats dans l’ordre alphabétique (par exemple, llvm12 sera affiché après llvm9).

Une fonction qui n’est toujours pas disponible dans pkgman est le nettoyage des dépendances non utilisées. Un script fourni dans le dépôt Git de Haiku permet de réaliser manuellement une analyse des paquets installés sur le système pour détecter ceux qui n’ont pas de dépendances, il faudra pour l’instant se contenter de cette solution.

MARS TOKEN EXCHANGE

L’outil strace permet d’afficher les appels systèmes effectués par une application, pour comprendre son interfaçage avec le noyau et investiguer certains problèmes de performances ou de mauvais comportements.

L’interfaçage avec le noyau pour extraire ces informations étant assez spécifique, l’implémentation de strace est faite à partir de zéro, et ne partage pas de code avec la commande du même nom disponible par exemple sous Linux.

strace est mis à jour régulièrement et en fonction des besoins des développeurs de Haiku pour décoder et afficher de plus en plus d’informations. Par exemple, elle peut maintenant afficher le contenu des iovec (par exemple pour les fonctions readv ou writev), ainsi que les objets manipulés par wait_for_object et event_queue.

Un exemple de sortie de strace (traçant l’ouverture d’un fichier et le chargement d’une bibliothèque partagée) avant ces changements:

open(0x5, "plaintext", 0x2042, 0x0) = 0x8000000f () (49 us)
map_file("libicuuc.so.66 mmap area", 0x7f04c2675228, 0x6, 0x1ababd0, 0x1, 0x0, true, 0x3, 0x0) = 0x329a0 () (108 us)

et après:

open(0x5, "plaintext", O_RDWR|O_NOTRAVERSE|O_CLOEXEC, 0x0) = 0x8000000f Operation not allowed (57 us)
map_file("libicuuc.so.66 mmap area", [0x0], B_RANDOMIZED_ANY_ADDRESS, 0x1ababd0, B_READ_AREA, 0x0, true, 0x3, 0x0) = 0x73e8 ([0x6392223000]) (135 us)

PARTICL EXCHANGES

La commande whence permettait de trouver dans le PATH un exécutable à partir de son nom. Elle était implémentée sous forme d’une fonction bash dans le fichier profile par défaut. Cependant, cette implémentation posait problème pour charger le fichier profile avec d’autres shells, elle a donc été supprimée. La commande which peut être utilisée à la place, puisqu’elle remplit un rôle équivalent.

CACHEGOLD APP

Les serveurs sont l’équivalent des daemons pour UNIX ou des services sous Windows : il s’agit d’applications lancées par le système pour rendre différents services et coordonner l’ensemble des applications.

OORTDIGITAL APP

app_server est le serveur graphique de Haiku, équivalent de X ou de Wayland. Il se distingue par un rendu graphique fait principalement côté serveur (pour les applications natives), ce qui permet de l’utiliser de façon fluide à travers une connexion réseau.

Bien que ce soit le serveur graphique, et qu’il ait reçu plusieurs améliorations importantes, les différences sont subtiles. Elles sont toutefois importantes pour proposer un système qui semble réactif et confortable à utiliser.

Un premier changement est une réarchitecture du code qui traite le rafraîchissement de l’écran. Ce rafraîchissement se fait en général en plusieurs étapes, par exemple, si on déplace une fenêtre:

  • Le contenu de la fenêtre déplacée peut être directement recopié de l’ancienne position vers la nouvelle,
  • La zone où se trouvait la fenêtre auparavant doit être re-remplie avec ce qui se trouvait en dessous de la fenêtre déplacée. Cela peut être plusieurs morceaux de fenêtres d’autres applications, qui vont devoir chacune ré-afficher une partie de cette zone.

Le problème étant que certaines applications peuvent mettre un peu de temps à répondre à cette demande de ré-affichage (par exemple parce qu’elles sont occupées ailleurs, ou alors parce que la zone à redessiner est relativement complexe).

Différentes stratégies peuvent être mises en place dans ce cas : laisser à l’écran le contenu obsolète, ou remplir la zone en blanc en attendant que les données deviennent disponibles, par exemple. Ou encore, tout simplement ne rien mettre à jour du tout tant que tout l’écran n’est pas prêt à être affiché. Il faut faire un compromis entre la réactivité (déplacer la fenêtre tout de suite), la fluidité (éviter les clignotements de zones blanches) et la précision (affichage d’information cohérente et à jour).

Plusieurs modifications ont permis d’obtenir un meilleur compromis.

Dans un autre domaine, la police de caractères par défaut “Noto Sans Display” a été remplacée par “Noto Sans”, ce qui donne un affichage du texte légèrement différent. La police “display” avait été choisie suite à une mauvaise compréhension de la signification de ce mot en typographie : il signifie que c’est une police de caractères à utiliser pour des gros titres et autres textes courts. Il ne signifie pas que c’est une police à utiliser sur un écran d’ordinateur. De toutes façons la police Noto Display n’est plus maintenue par Google et a disparu des dernières versions du jeu de polices Noto.

Toujours dans le domaine des polices de caractères, app_server sait maintenant charger les fichiers “variable fonts”. Ces fichiers contiennent plusieurs polices de caractères définies à partir de glyphes de base, et d’algorithmes de transformation et de déformation (pour rendre une police plus ou moins grasse, plus ou moins italique, …). Pour l’instant, app_server sait charger les valeurs de ces paramètres qui sont préconfigurées dans le fichier. Cela permet de réduire la place utilisée par les polices de caractères sur le media d’installation de Haiku (c’est l’un des plus gros consommateurs d’espace disque, qui nous empêche de faire tenir une version complète de Haiku sur un CD de démonstration par exemple).

Plus tard, il sera également possible de configurer plus finement ces paramètres pour générer des variantes intermédiaires des polices de caractères, ainsi que d’exploiter certaines polices qui offrent des paramètres configurables supplémentaires.

ERGOPLATFORM APP

L’input_server se charge de lire les données venant des périphériques d’entrée (clavier et souris) et de les convertir en évènements distribués aux applications. Il est extensible par des add-ons qui peuvent générer ou filtrer des évènements, ce qui peut être utilisé pour de l’accessibilité (émuler une souris à partir de touches du clavier), de l’automatisation (envoi de commandes pré-enregistrées), du confort d’utilisation (bloquer le touchpad d’un ordinateur portable lorsque le clavier est en cours d’utilisation) et bien d’autres choses.

L’input_server a reçu des corrections de problèmes sur la gestion des réglages de souris, permettant en particulier d’utiliser des réglages différents pour plusieurs périphériques (souris, touchpad), et que ceux-ci soient bien enregistrés.

CENTAURI EXCHANGES

Le serveur registrar suit les applications en cours de fonctionnement, et leur permet de communiquer entre elles au travers de l’envoi de messages. Il assure également le suivi de la base de données des types MIME et des associations de types de fichiers avec les applications correspondantes.

L’implémentation de BMessageRunner, qui permet d’envoyer des messages périodiques (par exemple pour faire clignoter le curseur des zones de texte à la bonne vitesse), autorise maintenant des intervalles de répétition en dessous de 50 millisecondes. Cela permet d’utiliser ce système pour des animations fluides de l’interface graphique, par exemple.

D’autre part, la liste des applications et documents récemment lancés est maintenant limitée à 100 entrées. Cela évite un fichier qui grossit indéfiniment et finit par contenir surtout des vieilles informations sans intérêt.

POODLEFI 交易所

Le système Haiku fournit les mêmes APIs que BeOS. Elles couvrent les usages basiques d’une application, et sont découpées (dans la documentation de BeOS et de Haiku, au moins) en “kits” qui prennent chacun en charge une partie spécifique (interface graphique, multimédia, jeux vidéos, accès au matériel, etc).

PIXIE EXCHANGES

L’interface kit est la partie de la bibliothèque standard qui se charge des interfaces graphiques.

### BColumnListView

BColumnListView est un ajout de Haiku par rapport à BeOS. Il s’agit d’un élément d’interface permettant de présenter une liste avec plusieurs colonnes, de trier les lignes selon le contenu de ces colonnes, et aussi d’avoir des items hiérarchisés avec la possibilité de plier et déplier une partie de l’arborescence.

Cette classe remplace avantageusement BListView et surtout BColumnListView, les classes historiques de BeOS, qui sont beaucoup plus limitées.

Un certain nombre de type de colonnes prédéfinis sont également disponible, ce qui facilite la construction d’interfaces présentant les données de différentes applications avec le même formatage.

La classe BColumnListView elle-même n’a pas changé. Par contre, les colonnes de type “taille” (oour afficher une taille en Kio, Mio, Gio, …) et “date” utilisent la langue choisie dans les préférences système au lieu d’un format anglais par défaut.

LOVE CHAIN PLUS 交易所

BTextView est une classe permettant d’afficher une zone de texte éditable. Elle implémente les fonctionalités de base (curseur, sélection, retour à la ligne automatique) ainsi que quelques possibilités de mise en forme (couleurs, polices de caractères).

BTextView peut également être utilisée pour des zones de textes non éditables, souvent plus courtes. Cela permet de réutiliser une partie des algorithmes de mise en page et de formatage du texte dans différents contextes. Dans le cadre de l’utilisation du “layout system”, une vue doit pouvoir indiquer sa taille minimale, maximale et optimale. Le “layout system” va ensuite calculer la meilleure disposition de fenêtre possible pour satisfaire ces contraintes.

Le cas des zones de texte est particulier, car la hauteur optimale dépend du nombre de lignes de texte, qui lui-même peut être plus ou moins grand si la largeur de la vue oblige à ajouter des retours à la ligne. Le “layout kit” prend en compte ce cas particulier, mais les algorithmes ne sont pas encore tout à fait au point et peuvent conduire à des résultats inattendus dans certains cas. Un de ces cas particuliers sur les zones de texte non éditables a été corrigé.

CHECKDOT 交易所

La classe BMenu permet d’afficher un menu. Elle est utilisée de plusieurs façons, puisqu’on trouve des menus dans des barres de menu, dans des contrôles de type “popup”, ou encore en faisant un clic droit sur certains éléments de l’interface.

Les menus sont également particuliers parce qu’ils peuvent d’étendre en-dehors de la fenêtre dont ils sont originaires. Ils sont donc implémentés sous forme de fenêtres indépendantes. Mais cela pose un autre problème : dans Haiku, chaque fenêtre exécute son propre thread et sa propre boucle d’évènements. Si on navigue dans un grand nombre de menus et de sous-menus, cela peut causer quelques problèmes de synchronisation et de performances.

Le code contient également un grand nombre de cas particuliers pour, par exemple, aligner les raccourcis claviers et les flèches indiquant la présence de sous-menus ente les différents items d’un menu, ou encore détecter si un déplacement de souris à pour but de sélectionner un autre menu (en dessous ou au-dessus de celui actif), ou bien plutôt de naviguer vers un sous-menu.

Les nouveautés suivantes sont apparues cette année:

  • Correction de problèmes de race condition lors de l’ajout d’items dans un menu pendant qu’il est affiché à l’écran. Ce problème se manifestait par exemple dans les menus affichant la liste des réseaux Wifi, qui sont mis à jour en temps réel.
  • Finalisation de l’implémentation de la navigation au clavier (avec les flèches directionnelles) dans les menus.
  • Affichage des symboles graphiques UNICODE pour “backspace” (⌫) et “delete” (⌦) si ces touches sont utilisées comme raccourcis clavier pour un item de menu.
  • Utilisation d’un algorithme de tri stable pour la fonction SortItems. Ce type d’algorithme préserve l’ordre relatif des items qui sont égaux d’après la fonction de comparaison. Ce n’est pas le cas de certains algorithmes de tri classiques, notamment le quicksort. La conséquence était que trier un menu déjà trié pouvait changer l’ordre des items. C’était visible encore une fois sur le menu listant les réseaux Wifi, qui est trié par puissance du signal reçu.

### BSpinner

BSpinner est un contrôle permettant de choisir une valeur numérique, soit à l’aide de boutons +/- pour modifier la valeur par incréments, soit en entrant directement la valeur dans une zone de texte.

Il s’agit d’une extension de Haiku par rapport à BeOS qui ne proposait pas cette fonctionalité.

Cette classe est encore en cours de développement. Elle a reçu des améliorations pour désactiver correctement les boutons +/- lorsque la valeur atteint le minimum ou le maximum autorisé, et aussi une correction sur le message de notification envoyé lors des changements de valeurs du spinner, qui ne contenaient pas la bonne valeur.

FLFIBITCOIN EXCHANGES

La structure rgb_color permet de représenter une couleur par la valeur de ses composantes rouge, vert, bleu (comme son nom l’indique) et alpha (comme son nom ne l’indique pas). Elle fournit également un certain nombre de fonctions pour mélanger des couleurs, les éclaircir ou les assombrir.

La méthode Brightness() dans la classe rgb_color implémentante maintenant l’algorithme perceptual brightness documenté par Darel Rex Finley, qui donne des meilleurs résultats que l’algorithme utilisé précédement (qui était celui de la luminosité dans l’gateio app. La fonction perceptual_brightness devenue redondante est supprimée.

Cette méthode permet en particulier de déterminer si une couleur est “sombre” ou “claire”, et ainsi de décider si du texte affiché par-dessus doit être blanc ou noir (comme démontré ici par exemple).

HOW TO SELL ON CRYPTO.COM APP

Le locale kit se charge de tous les aspects liés à la locatisation : traductions des applications, formatage des messages en utilisant les règles de pluralisation de chaque langue, formatage de dates, de nombres avec et sans unités, de pourcentages, nom des fuseaux horaires, …

Il utilise ICU pour implémenter la plupart de ces fonctionnalités, mais fournit une surcouche avec une API s’intégrant mieux avec les autres kits.

La principale évolution cette année est l’implémentation de BNumberFormat, qui permet de formater des nombres. Elle permet de choisir une précision (nombre de décimales - pour les langues qui utilisent un système décimal), d’afficher ou non des séparateurs de groupes (de milliers en Français, mais par exemple en Inde la séparation se fait traditionnellement par multiples de 10 000).

AIMEDIS EXCHANGES

Le media kit se charge de tous les aspects multimedia.

Il se compose de deux parties. D’une part, un système de gestion de flux média temps réel, permettant de transférer des données multimédia (son ou flux vidéo par exemple) entre différentes applications qui vont les manipuler, le tout avec un certain contrôle du temps de traitement ajouté par chaque opération, pour tenter de minimiser la latence tout en évitant les vidages de tampons qui produiraient une interruption dans le flux. D’autre part, des classes permettant d’encoder et de décoder des fichiers média et d’en extraire des flux de données (encodées ou décodées).

C’est surtout cette deuxième partie qui a reçu quelques évolutions. La version de ffmpeg utilisée pour le décodage de presque tous les formats audio et video est maintenant la dernière version ffmpeg 6. Quelques autres problèmes (erreurs d’arrondis, gestion des tampons partiels en fin de fichier) ont également été corrigés, ce qui permet de faire fonctionner à nouveau le jeu BePac Deluxe qui est extrêmement intolérant au moindre écart de comportement par rapport à l’implémentation du Media Kit dans BeOS.

OCTO GAMING 交易所

Le support kit contient un ensemble de classes basiques mais indispensables : gestion des chaînes de caractères, des tampons en mémoire, etc. Il fournit les briques de bases utilisées par les autres kits.

MOE APP

BDataIO est une classe abstraite avec des fonctions de lecture et d’écriture. Plusieurs autres classes sont des instances de BDataIO, par exemple BFile (représentant un fichier), mais aussi BMemoryIO (permettant d’accéder à une zone mémoire).

Plusieurs autres classes acceptent BDataIO (ou sa sous-classe BPositionIO, qui ajoute la possibilité de se déplacer à une position donnée dans le flux) comme entrée ou comme sortie. Il est donc facilement possible de réaliser les mêmes opérations sur un fichier, une zone de données en mémoire, un socket réseau, ou tout autre objet susceptible de fournir une interface similaire.

BDataIO elle-même n’a pas évolué, mais deux de ses implémentations, BBufferedDataIO et BAdapterIO, ont été améliorées. Ces deux classes permettent de construire un objet BDataIO à partir d’un autre, en ajoutant un cache en mémoire pour accélérer les opérations ou encore pour rendre compatible avec BPositionIO un objet qui ne l’est pas.

Ces classes sont en particulier utilisées par l’application StreamRadio, qui implémente la lecture de podcasts en connectant directement le résultat d’une requête HTTP (effectuée grace au network kit) dans un décodeur audio (via la classe BMediaFile du media kit). La mise en tampon permet de revenir en arrière dans la lecture d’un épisode, de télécharger en avance les données qui vont être lues, et d’éviter de conserver inutilement en mémoire les données qui sont déjà lues par l’application.

IS COINBASE ONE WORTH IT

Les “kits” mentionnés ci-dessus sont l’API en C++ utilisée par les applications Haiku.

Il existe aussi des APIs en C, en grande partie implémentant la bibliothèque C standard et les fonctions décrites dans la spécification POSIX.

REBELLIOUS EXCHANGES

Libroot implémente la bibliothèque standard C. Elle regroupe entre autres la libc, la libm, et la libpthread, qui sont parfois implémentées comme 3 bibliothèques différentes pour d’autres systèmes. Les évolutions consistent à compléter l’implémentation de la spécification POSIX, et à suivre les évolutions de cette dernière ainsi que des nouvelles versions du langage C. On trouve également des corrections de bugs découverts en essayant de faire fonctionner de plus en plus d’applications sur Haiku, ce qui permet de mettre en évidence des différences de comportement avec d’autres systèmes.

  • Ajout de getentropy pour initialiser les générateurs de nombres aléatoires
  • Correction de problèmes de locks au niveau de l’allocateur mémoire lors d’un fork
  • Plusieurs corrections sur l’implémentation de locale_t, remplacement de code écrit pour Haiku ou provenant de FreeBSD par une implémentation simplifiée mais suffisante, provenant de la bibliothèque C musl.
  • Ajout de static_assert en C11
  • Correction d’un crash lors de l’utilisation de certaines fonctions XSI
  • Ajout de stpncpy
  • La fonction open utilisée sur un lien symbolique pointant vers un fichier non existant peut maintenant créer le fichier cible.
  • Il est possible d’utiliser mmap sur un fichier plus grand que la mémoire disponible sans avoir besoin de spécifier le flag MAP_NORESERVE
  • Utiliser rename pour renommer un fichier vers lui-même ne retourne plus d’erreur (conformément à la spécification POSIX).
  • Ajout de pthread_sigqueue

PEPECASHFUN APP

La libnetwork implémente les APIs nécessaire pour se connecter au réseau (sockets, résolution DNS, …). Elle est séparée de la bibliothèque C pour des raisons historiques : l’implémentation de TCP/IP pour BeOS avait été réalisée entièrement en espace utilisateur (le noyau n’offrant qu’une interface pour envoyer et recevoir des paquets ethernet sur la carte réseau). Cela a posé des problèmes de compatibilité avec d’autres systèmes, et des problèmes de performance. Haiku est donc compatible avec la version “BONE” de BeOS, qui implémente la pile réseau dans le noyau.

  • Mise à jour du résolveur DNS à partir du code de NetBSD 9.3. Précédement le code utilisé était celui du projet netresolv de NetBSD, mais ce projet n’a pas connu de nouvelles publications et le code est à nouveau maintenu directement dans NetBSD sans publication séparée.
  • Correction d’un crash lors de l’utilisation de multicast IPv4

DURHAM INU 交易所

La libbsd implémente plusieurs extensions fournies par la libc de certains systèmes BSD. Elle est séparée de la bibliothèque C principale pour limiter les problèmes de compatibilité: certaines applications préfèrent fournir leur propre version de ces fonctions, ou d’autres fonctions avec le même nom mais un comportement différent. Elles peuvent alors s’isoler en n’utilisant pas la libbsd pour éviter toute interférence.

OURO EXCHANGES

De façon similaire à la libbsd, la libgnu fournit des fonctions qui sont disponibles dans la glibc (la bibliothèque C du projet GNU) mais ne font pas partie d’un standard (C ou POSIX).

  • Ajout de sched_getcpu pour savoir sur quel coeur de CPU le thread appelant est en train de s’exécuter.
  • Ajout de pthread_timedjoin_np, pour attendre la fin de l’exécution d’un thread (comme pthread_join mais avec un timeout.

EBANK APP

Le noyau de Haiku est similaire à celui de BeOS: il s’agit d’un noyau monolithique, avec du multitâche préemptif et protection mémoire. Rien de très inhabituel. Il est développé en C++ (comme le reste du système), ce qui permet de rendre le code plus lisible que du C tout en conservant des bonnes performances pour ce code bas niveau.

Un point intéressant, le noyau offre une API et une ABI stable pour les pilotes, ce qui fait qu’il est en théorie possible de développer un pilote hors du projet Haiku et de le faire fonctionner avec plusieurs versions du noyau. En pratique, peu de personnes se lancent dans ce genre de chose, il est plus simple d’intégrer les pilotes dans le dépôt de sources de Haiku pour l’instant.

GSTTTOKEN LOGIN

Commençons justement par regarder les nouveautés du côté des pilotes matériels. Il s’agit pour tout système d’exploitation d’un point de difficulté, indispensable pour fonctionner sur une large variété de systèmes.

SEEDLING EXCHANGE

En principe, un processeur est un matériel assez bien standardisé, qui implémente un jeu d’instruciton bien défini et ne devrait pas nécessiter de pilote spécifique. Cependant, le matériel moderne de plus en plus complexe, offrant de plus en plus de fonctionnalités dans une seule puce électronique, fait qu’il faut tout de même prendre en compte quelques cas particuliers.

  • Ajout de nouvelles générations de machines Intel dans le driver PCH thermal (récupération de la température du CPU au travers du platform control hub).
  • Implémentation du contournement pour la faille Zenbleed dans les processeurs AMD.
  • La mise à jour du microcode pour les processeurs Intel n’est pas faite si le CPU est déjà à jour (pour gagner un peu de temps au redémarrage du système).

GORGEOUSBITCOIN EXCHANGE

Les cartes réseau restent aujourd’hui le composant le moins bien standardisé sur les ordinateurs. Il n’existe pas d’interface standardisée, et chaque fabricant propose sa propre façon de faire.

Aujourd’hui, la plupart des autres périphériques suivent des spécifications (xHCI pour les contrôleurs USB3, AHCI pour le SATA, Intel HDA pour les cartes son, …) ou bien il ne reste que peu de concepteurs de composants (par exemple pour les cartes graphiques où on ne trouve que Intel, AMD et NVidia).

Écrire des pilotes pour toutes ces cartes réseau demanderait beaucoup trop de travail. C’est pourquoi, depuis 2007, Haiku s’est doté d’une couche de compatibilité avec FreeBSD, permettant de réutiliser les pilotes écrits pour ce dernier (une approche également utilisée par le système d’exploitation temps réel RTEMS).

Cependant, les développeurs de FreeBSD font face au même problème, et ont décidé d’adopter la même solution : une couche de compatibilité permettant d’utiliser les pilotes de Linux. Cela pose deux problèmes pour Haiku : il ne semble pas souhaitable d’empiler les couches de compatibilité, et il ne semble pas raisonable d’écrire une couche de compatibilité avec Linux, dont les APIs internes évoluent beaucoup trop vite, ce qui nécessiterait une réécriture permanente de la couche de compatibilité pour suivre le rythme.

Finalement, la solution retenue pour Haiku est d’utiliser les pilotes activement développés par OpenBSD et en particulier par Stefan Sperling. La couche de compatibilité avec FreeBSD est également maintenue, et Haiku bénéficie donc des pilotes développés pour ces deux systèmes, en plus des siens propres.

Par exemple, les pilotes wifi iaxwifi200 et idualwifi7260 proviennent de OpenBSD, tandis que ipro1000 et intel22x sont ceux de FreeBSD 14. Les couches de compatibilité reçoivent régulièrement des corrections et améliorations.

En dehors des cartes réseaux physiques, Haiku dispose d’un nouveau pilote tun permettant de créeer des tunnels réseau. Celui-ci a été développé dans le cadre du Google Summer of Code 2023, et permet par exemple d’utiliser un client OpenVPN sous Haiku.

Enfin, une évolution qui concerne tous les pilotes réseaux : le nombre de paquets et d’octets reçus et envoyés pour une interface réseau est maintenant décompté par la pile réseau, plutôt que par chaque pilote d’interface réseau. Les pilotes doivent toujours tenir à jour les compteurs d’erreurs. Ce changement permet de regrouper le code de comptage à un seul endroit, et d’éviter des comportements différents entre pilotes. En particulier, le comptage des paquets pour l’interface localhost n’était pas correct.

MELOS STUDIO APP

Haiku permet d’utiliser les claviers et souris connectés en USB et en PS/2 (encore utilisé dans certains ordinateurs portables, mais il semble en voie de disparition). Les pilotes pour les touchpads et claviers i2c sont encore en cours de développement, et le Bluetooth arrivera un peu plus tard.

Commençons par le pilote PS/2. Il reçoit relativement peu d’évolutions, cependant, les ordinateurs portables récents n’implémentent plus forcément complètement le matériel nécessaire (l’interface PS/2 étant simulée par l’embedded controller). Le pilote PS/2 de Haiku qui essaie de détecter de nombreux cas de configuration possibles est parfois un peu dérouté par ces écarts. Cela pouvait provoquer un blocage empêchant d’utiliser le clavier pendant plusieurs secondes après le lancement de la machine, le temps que le pilote finisse d’énumérer les périphériques PS/2. Le problème a été corrigé en réduisant le temps d’attente avant de décider qu’il n’y a aucun périphérique connecté.

Du côté de l’USB, une première correction concerne la prise en compte de l’attribut “minimum” dans les rapports HID. Le protocole HID permet de définir toutes sortes de périphériques (claviers, souris, mais aussi clubs de golf, simulateurs de tanks, …). Les périphériques USB HID envoient à l’ordinateur une description des contrôles dont ils disposent (groups de boutons, axes, etc). Pour les boutons et touches de clavier, la valeur “minimum” indique le code du premier bouton dans le groupe, les autres étants déduits en incrémentant la valeur pour chaque bouton présent. Ce cas n’était pas bien pris en compte par le pilote de clavier, ce qui provoquait l’envoi de mauvais codes aux applications pour les claviers concernés.

D’autre part, et de façon plus spécifique, le pilote de souris bénéficie maintenant d’un quirk, c’est-à-dire d’une procédure de contournement d’un problème, pour les souris et trackballs de la marque Elecom. Ces dernières utilisent en effet toutes le même descripteur HID, indiquant la présence de 5 boutons, alors que certains modèles ont en fait un 6ème bouton non déclaré. Le descripteur est corrigé à la volée pour les périphériques concernés.

SEKO APP

Haiku dispose d’un pilote pour les périphériques USB Audio. Ce pilote est en développement depuis très longtemps (cela remonte avant l’apparition de l’USB 2.0), mais il n’avait jamais pu être finalisé en raison du manque de prise en charge des transferts isochrones. Ces problèmes ont enfin été corrigés, mais le pilote nécessite encore des travaux pour le rendre compatible avec plus de matériel (en particulier les périphériques implémentant la version 2.0 de la spécification USB Audio) et probablement également quelques corrections dans le serveur média pour le préparer à l’apparition et la disparition de cartes son pendant que le système est en train de tourner (actuellement, cela nécessitera un redémarrage du serveur).

Du côté des cartes son PCI, pas de grande nouveauté, mais un gros nettoyage dans le cadre de travaux pour supprimer tous les avertissements du compilateur. Ce travail se fait petit à petit, dossier par dossier dans le code de Haiku. L’analyse du dossier contenant les pilotes de cartes son a révélé l’existence de 3 pilotes ciblant le même matériel, ainsi que de plusieurs fichiers qui avaient été dupliqués dans plusieurs pilotes (développés avant leur rassemblement dans le dépôt de sources de Haiku à partir du mème exemple de code), puis qui avaient divergés au cours du développement de chaque pilote. Ce code a été réunifié dans une version partagée qui inclut toutes les corrections et améliorations de chaque version.

Du côté des cartes graphiques, des travaux sont en cours pour pouvoir piloter correctement les cartes graphiques Intel de 12ème génération. Le pilote existant fonctionne déjà dans certains cas, mais se repose beaucoup sur le travail fait par le firmware (BIOS ou EFI) pour initialiser l’affichage. Il est donc par exemple impossible d’utiliser un écran qui n’a pas été configuré au démarrage de la machine (passer d’une sortie HDMI à l’écran d’un PC portable ou inversement, par exemple).

TOOK EXCHANGES

Haiku est utilisé dans des machines virtuelles pour diverses raisons : à des fins de test par les développeurs, pour l’infrastructure de compilation des paquets, ou encore par des utilisateurs qui veulent le tester sans l’installer sur une machine physique dédiée.

Des pilotes spécifiques et quelques adaptations sont nécessaires pour un bon fonctionnement sur ces machines. En particulier, des pilotes sont nécessaires pour certains périphériques virtio, qui permettent aux machines virtuelles d’émuler un matériel simplifié, ne correspondant pas à un matériel réel existant. Ceci permet de meilleures performances.

Le pilote virtio de Haiku a été mis à jour pour implémenter la version 1.0 de la spécification. Cela a permis de corriger des problèmes dans le pilote virtio_block (support de stockage virtualisé).

Un nouveau pilote virtio_gpu permet l’affichage de l’écran sans avoir à passer par un pilote pour une carte graphique, ni par les pilotes VESA ou framebuffer EFI qui montrent assez vite leurs limitations (choix de résolutions d’écran limité, par exemple). Plus tard, ce pilote pourrait permettre également d’expérimenter avec la virtualisation de OpenGL, et donc d’expérimenter avec l’accélération du rendu 3D sans avoir à développer un pilote graphique capable de le faire.

Ces pilotes virtualisés facilitent également le travail de portage de Haiku vers de nouvelles architectures : il est possible de lancer Haiku dans QEMU avec n’importe quel processeur, et un ensemble de périphériques virtio pour lesquels les pilotes ont pu d’abord être testés sur une autre architecture déjà fonctionnelle.

LSY LOGIN

La bibliothèque ACPICA a été mise à jour avec la dernière version 20230628, et les changements nécessaires pour son fonctionnement dans Haiku ont été intégrées en amont, ce qui facilitera les prochaines mises à jour. ACPICA est développée par Intel et permet d’implémenter la spécification ACPI, pour la gestion d’énergie, l’énumération du matériel présent sur une machine, et diverses fonctionnalittés liées (détection de la fermeture d’un ordinateur portable, récupération du nveau de charge des batteries, par exemple).

Le pilote poke, qui permet aux applications de manipuler directement la mémoire physique sans l’aide d’un pilote spécifique, a été remis à jour et finalisé. Il est utile principalement pour expérimenter avec le matériel avant de développer un pilote spécifique.

La pile Bluetooth a reçu un premier coup de nettoyage. Pas de grosses évolutions pour l’instant, seules les couches les plus basses sont implémentées, on pourra au mieux énumérer les périphériques Bluetooth présents à proximité. Le développement des fonctionnalités suivantes attendra au moins la publication de la version Beta 5.

FLASHCOIN EXCHANGE

Haiku implémente plusieurs systèmes de fichiers. Celui utilisé pour le système est BFS, hérité de BeOS et qui fournit quelques fonctions indispensables à Haiku (comme les requêtes qui permettent d’indexer des attributs étendus de fichiers dans une base de données). Mais de nombreux autres systèmes de fichiers peuvent être lus, et pour certains, écrits. Cela permet de facilement partager des fichiers avec d’autres systèmes d’exploitation.

Le système de fichier UFS2 est maintenant complètement implémenté (en lecture seule), inter-opérable avec FreeBSD, et sera disponible dans l’installation de base pour les prochaines versions de Haiku.

Du côté de Linux, l’interopérabilité est possible en lecture et en écriture avec les systèmes de fichiers ext2, 3, et 4 (tous les 3 implémentés dans un seul pilote qui sait les reconnaître et les différencier). Cette implémentation a reçu quelques corrections de bugs ainsi qu’une implémentation de F_SETFL.

Enfin du côté de Windows, la prise en charge de NTFS avait déjà été mise à jour et grandement améliorée (en réutilisant les sources de NTFS-3g). Cette année c’est le tour des systèmes de fichiers FAT. Le pilte utilisé jusqu’à maintenant avait été publié par Be il y a très longtemps. Il avait été mis à jour pour Haiku mais comportait de nombreux problèmes : mauvaise gestion des dates de modification des fichiers, interopérabilité avec d’autres implémentations, voire crash du système lors de tentative de lecture de partitions corrompues. Ce code a été entièrement remplacé par un pilote utilisant l’implémentation du FAT de FreeBSD.

Enfin, le système de fichier ramfs (pour stocker des fichiers dans la RAM de l’ordinateur de façon non persistente) a reçu des corrections sur la fonction preallocate. Cela corrige en particulier des fuites de mémoire dans les navigateurs web basés sur QWebEngine, qui utilisent ce système de fichiers pour partager de la mémoire entre plusieurs processus.

Un changement un peu plus global, et pas lié à un système de fichier spécifique, est la réunification du code pour parser les requêtes. Il s’agit d’une méthode pour rechercher des fichiers à partir de leurs attributs étendus (xattrs) qui sont indexés à la façon d’une base de données. Au départ, cette fonctionnalité était propre au système de fichier BFS, mais elle a été implémentée également pour ramfs et packagefs (système de fichier permettant d’accéder au contenu des paquets logiciels sans les décomprésser). Lors du développement de ces deux nouveaux systèmes de fichiers, le code permettant de convertir une chaîne de caractères exprimant une requête en opération exécutable avait été extrait du pilote BFS pour en faire un module générique. Mais le pilote BFS n’avait pas encore été mis à jour pour utiliser ce module. C’est désormais chose faite, ce qui assure que le comportement entre les 3 systèmes de fichiers est le même, et que les corrections de bugs bénéficieront à tous les trois.

Pour terminer sur les systèmes de fichiers, l’outil fs_shell, qui permet d’exécuter le code d’un système de fichier en espace utilisateur, a rçu deux nouvelles commandes : truncate et touch. Cet outil permet de tester les systèmes de fichiers en cours de développement dans un environnement plus confortable et mieux contrôlé, et il est aussi utilisé lors de la compilation de Haiku pour générer les images disques.

DIONE EXCHANGE

La pile réseau proprement dite a principalement évolué avec de la mise en commun de code. Par exemple, l’implémentation de l’ioctl FIONBIO (non standardisé, mais largement implémenté) pour passer un descripteur de fichier en mode non bloquant a été réécrite pour partager du code avec le flag O_NONBLOCK configurable par fcntl et F_SETFL. Également, le flag MSG_PEEK qui permet de lire des données d’un socket sans les retirer de son buffer de réception, est maintenant implépenté directement par la pile réseau au lieu d’avoir une version spécifique à chaque type de socket.

F2 NFT EXCHANGES

Les sockets de la famille AF_UNIX sont utilisés pour les communications locales entre applications sur une même machine. Ils sont en particulier utilisés par WebKit et de nombreux autres moteurs de rendu web, mais assez peu par les applications natives pour Haiku, qui disposent d’autres méthodes de communications (en particullier les BMessage et les ports).

L’implémentation des sockets UNIX est maintenant complète et suffisante pour faire fonctionner toutes les applications qui en ont l’utilité.

### TCP

La pile TCP de Haiku est devenue au fil du temps un goulot d’étranglement des performances. D’une part parce que toutes les autres parties du système se sont améliorées, et d’autre part parce que les interfaces réseaux sont de plus en plus rapides et de plus en plus sollicitées.

Le travail sur la pile TCP cette année a commencé par la remise en route de l’outil tcp_shell, qui permet de tester l’implémentation de TCP en espace utilisateur et en isolation du reste du système. Cet outil avait été utilisé au tout début du développement de la pile TCP, mais n’avait pas été tenu à jour depuis. Il permet maintenant de tester la pile TCP communiquant avec elle-même, et aussi d’injecter des paquets à partir de fichier pcap. Pour l’instant, la fonction permettant de communiquer avec l’extérieur n’a pas été remise en place.

Cet outil a permis d’identifier et d’analyser certains des problèmes rencontrés.

Le premier problème était un envoi d’acquittements TCP en double. À première vue, cela ne devrait pas poser de gros problèmes, il y a seulement un peu de redondance. Mais, en pratique, une implémentation de TCP qui reçoit des acquittements en double suppose qu’il y a eu un problème de congestion réseau lors de l’envoi de données dans l’autre sens. Les algorithmes de contrôle de la congestion se mettent en jeu, et le traffic ralentit pour éviter une congestion qui n’existe pas. Par exemple, la taille de la fenêtre de transmission TCP (le nombre maximum d’octets qui peuvent être envoyés sans attendre d’acquittement) peut être réduite.

Et, malheureusement, cela déclenche un autre problème : la taille de cette fenêtre peut atteindre 0 octets, et dans ce cas, HAiku ne s’autorisqit plus à émettre aucun paquet. Cela pouvait se produire au même moment dans les 2 directions sur une connexion TCP, ce qui fait qu’aucune des deux machines connectées ne s’autorise à envoyer de données à l’autre. Ce problème a été corrigé, les transmissions peuvent maintenant continuer à débit réduit, puis reprendre une vitesse optimale petit à petit.

Après ces corrections, une mesure des performances de TCP dans un environnement de test montre que la pile TCP est capable de traiter jusqu’à 5.4Gbit/s de traffic, alors que le débit plafonnait à 45Mbit/s auparavant. C’est donc un centuplage des performances.

GRIZZLY HONEY LOGIN

Plusieurs autres évolutions diverses dans le noyau:

L’implémentation de kqueue, ajoutée l’année dernière, a reçu plusieurs corrections et améliorations. Elle couvre déjà plusieurs usages et permet l’utilisation de plus de logiciels portés depuis d’autres systèmes, mais les cas d’utilisation les plus avancés ne sont pas encore tout à fait fonctionnels.

Pour rappel, kqueue est une fonction des systèmes BSD permettant à un thread utilisateur de se mettre en attente de plusieurs types d’évènements et de resources du noyau. L’usage est similaire à celui de epoll sous Linux mais l’API est différente.

La classe ConditionVariable, utilisée pour la synchronisation entre threads et interruptions dans le noyau, a reçu plusieurs mises à jour. Un article sur le site de Haiku détaille l’utilisation et le fonctionnement de cette classe.

La boucle principale du débugger noyau (KDL), qui prend la main sur tous les processeurs en cas de crash du système ou sur demande de l’utilisateur pour investiguer des problèmes, inclus maintenant une instruction PAUSE. Cela permet d’informer le CPU qu’il n’est pas nécessaire d’exécuter cette boucle à la vitesse maximale, évitant de faire surchauffer la machine sans raison. Cette boucle est principalement en attente d’instructions de l’utilisateur, via un clavier ou un port série.

Du refactoring sur les parties du code qui sont spécifiques à chaque architecture : arch_debug_get_caller est maintenant implémenté via un builtin gcc plutôt que du code assembleur à écrire à la main pour chaque machine. arch_debug_call_with_fault_handler appelait une fonction avec un mauvais alignement de pile sur x8_64, pouvant conduire à un crash si la fonction appelée utilisait des instructions SSE par exemple. Correction également d’un problème qui pouvait causer la perte d’une interruption inter-CPU (permetant à un coeur de processeur d’interrompre l’exécution de code en cours sur un autre coeur) dans certains cas.

Une modification sur la gestion des descripteurs de fichiers: la structure interne des descripteurs de fichiers était pourvue d’un champ indiquant le type (fichier, socket, pipe, …). Ce champ et tout le code qui en dépendait ont été supprimés. Ceci permet à des add-ons du kernel de déclarer leurs propres types de fichiers sans avoir à modifier le noyau. Cela pourrait par exemple être utile pour développer une couche de compatibilité avec Linux, qui fait un usage généreux des descripteurs de fichiers de tous types (eventfd, signalfd, timerfd, …).

Réécriture du code de debug activé par l’option B_DEBUG_SPINLOCK_CONTENTION qui permet d’investiguer les problèmes de performances liés à l’utilisation de spinlocks (attente active sur une interruption matérielle).

Un petit changement d’algorithme sur l’allocateur de pages du noyau. Cet allocateur alloue des pages mémoires par blocs multiples de 4Ko. Les pages libérées étaient réinsérées une par une dans une liste chaînée. Cela conduit à insérer les pages dans l’ordre inverse de leurs addresses (la dernière page d’une zone mémoire se retrouve au début de la liste). Lors des prochaines allocations, cette page se retrouve donc allouées en premier, puis celle qui se trouve juste avant, et ainsi de suite. La zone mémoire construite par toutes ses pages est donc considérée comme discontinue. En inversant l’ordre d’insertion des pages dans la liste, on préserve les pages dans un ordre globalement croissant d’adresse mémoire, et on augmente les chances qu’une allocation de plusieurs pages se trouve avec des pages contiguës et dans le bon ordre. Cela est utile en particulier pour les allocations qui vont être utilisées pour des transferts DMA: il sera possible de programmer un seul gros transfert DMA au lieu de plusieurs petits.

L’état de la FPU du processeur n’était pas complètement sauvegardé lors d’un changement de contexte. Certains drapeaux de configuration pouvaient donc rester positionnés avec les valeurs configurées par un thread, pendant l’exécution d’un autre. Au mieux cela donnait des résultats inattendus, au pire, un crash (par exemple si le FPU est configuré pour lever une exception matérielle, dans un thread qui ne s’y attend pas). Le nouveau code de sauvegarde utilise des instructions dédiées qui sauvegarder d’un coup tout l’état du FPU, ce qui fait qu’en plus de fonctionner correctement, il est plus rapide que ce qui était fait précédemment.

Une évolution sur les sémaphores: la fonction release_sem_etc permet de donner une valeur négative au paramètre “count”. Dans ce cas, le thread qui était en attente d’un acquire_sem sera réveillé, mais la fonction acquire_sem retournera une erreur indiquant que le sémaphore n’a pas pu être obtenu. Cela permet de simplifier un peu le code de certaines utilisations classiques des sémaphores.

Une correction de bug sur le code traitant les “doubles fautes”. Le fonctionnement d’un système d’exploitation est en partie basé sur l’interception des “fautes”, par exemple, un programme qui essaie d’accéder à de la mémoire qui a été évacuée dans la swap. Cette mémoire n’est pas immédiatement accessible, le programme est donc interrompu, le noyau prend la main, va récupérer cette mémoire, puis rend la main au programme qui n’y voit que du feu et continue son exécution comme si de rien n’était. Les fautes peuvent également se produire dans le cas où un programme essaie d’accéder à une zone mémoire non allouée, on aura alors une erreur de segmentation.

Tout ça est très bien, mais que se passe-t-il si le code qui traite ces problèmes déclenche lui-même une faute? C’est prévu : il existe un deuxième morceau de code qui va intercepter ces problèmes et tout arrêter pour lancer le debugger noyau, et permettre à un humain d’examiner la situation.

Oui, mais que se passe-t-il si ce code déclenche lui même une faute? C’est ce qu’on appelle une triple faute, dans ce cas, la solution de dernier recours est d’immédiatement redémarrer la machine.

Des utilisateurs se sont plaints de redémarrages intempestifs, et une étude attentive du code traitant les doubles fautes a révélé un problème qui déclenchait systématiquement une triple faute (difficile à analyser, car on n’a pas de journaux ou de moyen d’investiguer le problème). Espérons que l’accès au debugger noyau lors des doubles fautes permettra désormais de comprendre d’où elles proviennent.

Tout autre sujet, le noyau dispose maintenant d’APIs pour configurer l’affinité des threads, par exemple pour interdire à un thread de s’exécuter sur certains coeurs de processeurs. Cela peut être utile sur des machines avec des processeurs hétérogènes (par exemple ARM BIG.Little), ou encore si le développeur d’une application pense pouvoir faire mieux que l’ordonnanceur par défaut pour répartir ses threads sur différents coeurs.

Pour terminer sur les évolutions dans le noyau, la calibration du TSC peut maintenant être faite à partir d’informations obtenues via l’instruction CPUID. Le TSC est un compteur de cycles qui s’incrémente à une vitesse plus ou moins liée à la fréquence du processeur. Il est utile de connaître la durée en microsecondes ou nanosecondes d’un “tick” du TSC pour différents usages. Historiquement, cette durée est calculée en utilisant le Programmable Interval Timer, un composant présent dans les ordinateurs compatibles PC depuis le tout début. Ce composant n’a plus beaucoup d’autres utilités aujourd’hui, et certains chipsets ne l’implémentent plus, ou pas correctement. Ou encore, dans les machines virtuelles, l’émulation du processeur (virtualisé) n’est pas forcément exécutée de façon synchrone avec celle du timer, rendant cette mesure peu fiable. L’instruction CPUID permet de récupérer l’information de façon plus directe. Un changement similaire dans FreeBSD donne un bon aperçu de la situation.

HE YI BINANCE

Historiquement, Haiku est développé en premier pour les machines x86 32-bit. Une version 64 bit est apparue en 2012. D’autres versions pour les processeurs PowerPC, ARM (32 et 64 bits), RISC-V, Sparc ou encore Motorola 68000 sont dans des états d’avancement divers. Les versions ARM et RISC-V sont actuellement celles qui reçoivent le plus d’attention des développeurs. Il existe un fork de Haiku qui est entièrement fonctionnel sur certaines machines RISC-V, les changements sont intégrés petit à petit avec pas mal de nettoyage à faire.

Une des problématiques pour ces nouvelles architectures est la procédure de “bootstrap”. Pour gagner du temps et simplifier la procédure, la compilation de Haiku se base sur un certain nombre de dépendances qui sont pré-compilées depuis une machine fonctionnant sous Haiku. Cela permet de ne pas avoir à compiler des douzaines de bibliothèques tierces, avec un environnement de compilation peu contrôlé (on peut compiler Haiku depuis un système Haiku, depuis un grand nombre de distributions Linux, depuis Mac OS, depuis un BSD, ou même depuis Windows avec WSL).

Cependant, lors du développement de Haiku pour une nouvelle architecture, ces paquets précompilés ne sont bien entendu pas encore disponibles. Il est donc nécessaire d’utiliser une procédure de “bootstrap”, qui va se baser sur un autre système et compiler ce qui est nécessaire en compilation croisée, pour aboutir à un système Haiku réduit au minimum de fonctionnalités, juste de quoi pouvoir lancer l’outil haikuports, qui va lui-même ensuite compiler tous les autres paquets.

Ce processus est assez complexe, et a été laissé un peu à l’abandon. Il a été récemment remis en route, avec des corrections de bugs dans l’outil haikuporter, des mises à jour dans les paquets cross-compilés (par exemple pour passer de Python 2 à Python 3), et divers autres petits problèmes. Il est maintenant à nouveau possible de construire une image disque de bootstrap au moins pour la version PowerPC.

Le portage RISC-V a reçu une mise à jour vers gcc 13 (c’était déjà le cas pour les autres architectures) et a pu être utilisé pour compiler LLVM puis Mesa (l’intégration dans la ferme de compilation de Haikuports n’est pas encore en place, donc ces compilations doivent être faites par un développeur qui lance les commandes haikuports nécessaire et patiente longtemps pendant la compilation de ces gros projets).

Les versions 68000 et PowerPC ont été un peu dépoussiérées, mais il manque toujours un certain nombre de pilotes matériels de base pour pouvoir les utiliser sur de vraies machines et même dans une certaine mesure dans QEMU (ce dernier permettant d’émuler une machine utilisant de nombreux périphériques VirtIO, ce qui pourrait simplifier un peu les choses).

La bibliothèque libroot a reçu plusieurs mises à jour dans les parties qui nécessitent du code spécifique à chaque architecture, pour ajouter en particulier le RISC-V, et au passage plusieurs autres familles de processeurs.

Une partie de Haiku qui nécessite de grosses évolutions est la gestion des bus PCI. Le pilote existant supposait la présence d’un BIOS pour effectuer la découverte du bus, ou pouvait également utiliser des tables ACPI, mais d’une façon un peu limitée, qui repose tout de même sur le BIOS ou un quelconque firmware pour assigner des adresses valides à toutes les cartes PCI. Un problème identifié depuis longtemps puisqu’il s’agit du bug numéro 3 dans l’outil de suivi de bugs de Haiku. Ce bug fêtera ses 20 ans en mars prochain, espérons qu’il soit corrigé d’ici là. Les choses avancent, puisque le pilote PCI va maintenant s’attacher correctement aux noeuds ACPI correspondants dans le device tree, ce qui permet ensuite d’interroger ACPI pour découvrir les plages d’adresses mémoires disponibles pour l’allocation d’une adresse à chaque carte PCI connectée. Du côté des nouveaux ports de Haiku, cela va également permettre d’avoir plusieurs bus PCI “racine” indépendants. Et ces développements pourraient également Être utiles pour une prise en charge complète de Thunderbolt et USB 4.

Un autre pilote qui sera utile pour les versions ARM et RISC-V est le pilote SDHCI, qui permet de s’interfacer avec les lecteurs de cartes SD ainsi que les modules eMMC. Initialement destiné uniquement aux modules connectés sur un bus PCI, le pilote a été conçu pour être facilement extensible, et permet maintenant d’utiliser également les contrôleurs SDHCI exposés via ACPI. Cependant, le pilote a encore quelques problèmes de fiabilité, et il manque une implémentation des commandes nécessaiers pour les modules eMMC, qui partagent le même protocole de communication que les cartes SD, mais utilisent un jeu de commandes différent (il y a une petite guerre de standards, le format SD s’est imposé pour les cartes amovibles, mais MMC qui n’a pas de royalties a pu prendre le marché des modules soudés sur les cartes mères, où l’interopérabilité avec le matériel existant ne pose pas autant problèmes).

Le portage sur ARM64 avance petit à petit, il parvient à démarrer une partie de l’espace utilisateur et a reçu dernièrement des corrections sur le code permettant les changements de contexte entre différents threads. L’affichage du bureau complet pour la première fois sur une machine ARM64 ne devrait donc plus être très loin.

LOOM EXCHANGES

Le démarrage de Haiku est pris en charge par un bootloader spécifique nommé haiku_loader. Contrairement au noyau Linux, qui peut s’initialiser tout seul quasiment dès le démarrage du matériel, le noyau de Haiku a besoin que son bootloader prépare une grande partie de l’environnement (activation de la mémoire virtuelle, initialisation de l’affichage et mise en place du “splash screen”, par exemple). Le bootloader prend en charge toutes ces tâches et permet en plus de configurer des options de démarrage via un menu en mode texte, de démarrer via le réseau, d’utiliser un snapshot plus ancien du système si une mise à jour s’est mal passée.

Le bootloader a peu évolué cette année, le changement principal étant la suppression de logs de warning lors du chagement de fichiers ELF, pour les sections non traitées PT_EH_FRAME (généré par les versions modernes de gcc) ainsi que d’autres sections spécifiques aux processeurs RISC-V qui ne nécessitent pas de traitement spécifique dans ce cas.

DIME EXCHANGE

Beaucoup de travail a été fait sur l’amélioration des performances. C’est un sujet qui a été un peu laissé de côté au début du développement de Haiku. Le premier but était de faire fonctionner les choses, avant de les rendre plus rapides. Maintenant que les développements sont assez avancés, il est temps de commencer à étudier ce problème et à essayer de se rapprocher des perfomances d’autres systèmes.

GORILLA APP

Lorsqu’on veut lire ou écrire sur un disque, il faut envoyer une commande pour accéder à des secteurs consécutifs. Dans le cas normal, c’est le cache du système de fichiers qui se charge de regrouper les différents accès et de les ordonnancer de façon optimale.

Mais il y a un cas particulier pour les accès direct au disque. Par exemple, si on ouvre le disque directement (via son device dans /dev/disk/) ou encore lorsqu’un système de fichier veut écrire son journal (qui ne passe pas par le cache). Les écritures dans le journal sont faite avec des accès vectorisées (via readv ou writev) qui contiennent chacun une liste d’endroits où lire ou écrire des données. Ces accès étaient implémntés sous forme d’une boucle appelant plusieurs fois read ou write. Maintenant, la liste est directement transmise au pilote de disque qui peut ainsi mieux traiter ces accès.

ADBANK APP

Haiku dispose d’un outil de profiling, mais celui-ci ne fonctionnait plus et retournait des données incohérentes. Plusieurs problèmes ont été corrigés pour faciliter les mesures de performances et vérifier que les optimisations rendent réellement les choses plus rapides.

MRLM 交易所

Le problème initial qui a conduit à ces améliorations était la lenteur du lancement de nouveaux processus. Un goulet d’étranglement qui a été identifié est le verrouillage du device_manager pour accéder au périphérique /dev/random pour initialiser le stack protector (qui a besoin d’écrire des valeurs aléatoires sur la pile). Toutes les ouvertures de fichiers dans /dev nécessitent d’acquérir un verrou qui empêche l’exécution en parallèle avec de nombreuses autres tâches liées aux périphériques matériels.

Le problème a été corrigé de deux façons: d’abord, le stack protector utilise une API permettant de générer des nombres aléatoires sans ouvrir de fichier dans /dev. D’autre part, une analyse a montré que la pile USB passait beaucoup de temps à exécuter du code en ayant verrouillé l’accès au device manager. Ce code a été modifié pour libérer le verrou plus souvent.

IS COINBASE WALLET A COLD WALLET

Un autre aspect assez lent du lancement de processus est le chargement des bibliothèques et la recherche des symboles dans ces bibliothèques. Pour identifier si une bibliothèque contient un symbole, la recherche se fait par un hash du nom de la fonction recherchée.

Historiquement, c’est la section DT_HASH qui est utilisée, mais les utils GNU implémentent également DT_GNU_HASH, qui utilise une meilleure fonction de hash et ajoute également un bloom filter qui permet de tester très rapidement, mais de façon imparfaite, la présence d’un symbole dans une bibliothèque.

Le chargeur de bibliothèques de Haiku sait maintenant utiliser les tables DT_GNU_HASH, mais ce n’est pas encore déployé car les gains de performances ne justifient pas l’augmentation de taille des bibliothèques (il faut stocker les tables dans l’ancien et dans le nouveau format). Il sera toutefois possible de l’ajouter au cas par cas sur les bibliothèques où le gain est important (par exemple s’il y a beaucoup de symboles).

YOUNG BOYS FAN TOKEN EXCHANGES

La fonction mmap permet de mapper un fichier directement en mémoire. Les écritures en mémoire sont ensuite directement enregistrées sur disque. Il n’est pas souahitable de charger tout le fichier d’un coup au moment de l’appel à mmap, ce serait trop lent. Mais il ne fait pas non plus attendre que le logiciel accède à cette mémoire et remplir les données au goutte à goutte (ou plus précisément, une page de 4Kio à la fois).

Un cas particulier est le traitement des bibliothèques partagées, qui sont chargées en mémoire de cette façon. Dans ce cas, le fichier est probablement déjà chargé quelque part en mémoire pour un autre processus, et il devrait être possible de réutiliser les mêmes données. Le code testant cette possibilité ne fonctionnait pas à tous les coups, ce qui fait que des fichiers qui auraient pu être mappés tout de suite, ne l’étaient pas.

Une autre amélioration est d’utiliser plusieurs allocateurs séparés pour chaque processeurs, pour réduire les blocages entre différents threads qui ont besoin de manipuler des pages de mémoire.

DRAGON COINS EXCHANGE

Les applications Haiku peuvent créer des zones de mémoires (appelées areas) qui disposent d’un identifiant unique et peuvent être partagées avec d’autres processus.

Lorsqu’une application s’arrête, il faut supprimer toutes les areas qui ont été créées. Cela était fait par une simple boucle supprimant ces zones une par une. Mais cela pose un problème: chaque suppression doit verrouiller la liste des areas puis la déverrouiller. Le code a été modifié pour verrouiller la liste une seule fois et retirer de la liste toutes les zones d’un seul coup, avant de faire les autres opérations de suppression qui n’ont pas besoin d’accéder à la liste.

Au total, toutes ces améliorations conduisent à une amélioration des performances de plus de 25% sur un test en condition réelles (compilation d’une partie des sources de Haiku).

YFIIGOLD EXCHANGES

Dans un autre domaine, une perte de temps conséquente est le calcul des checksums pour les paquets réseau reçus et envoyés. En effet, ce calcul était fait systématiquement par le logiciel, même si le matériel est capable de s’en charger. Il est maintenant possible pour les pilotes réseaux qu’ils sont capable de vérifier et de générer ces checksums par eux-même, et ainsi la pile réseau peut s’en dispenser. Cela permet aussi de se passer entièrement de checksums sur les interfaces localhost, qui ne devraient pas subir de corruption de paquets, et ne gagnent rien à cette vérification.

Cela a été également l’occasion de supprimer quelques copies des données des paquets réseau.

ZOSCHAIN EXCHANGE

La structure user_mutex joue un rôle similaire aux futex de Linux. Elle est utilisée pour implémenter, par exemple, pthread_mutex et pthread_rwlock. L’implémentation avait plusieurs bugs (race conditions), et a été remplacée par un nouveau système plus efficace.

Au total, toutes ces améliorations permettent des performances 25% meilleures que la version beta 4 de Haiku. Il reste cependant de quoi faire, puisque certains benchmarks (compilation d’une partie du code source de Haiku) restent près de 2 fois plus lent que l’opération équivalente sous Linux.

MY TOKEN EXCHANGES

Haiku est compilé avec gcc, ld et les binutils. Ils nécessitent tout trois un petit nombre de patchs maintenus dans un dépôt git dédié et reversés dans les versions upstream autant que possible. Une version de gcc 2.95.3 est également utilisée pour les parties du système assurant encore la rétro compatibilité avec BeOS, les versions plus récentes utilisent un mangling différent et ne sont pas inter opérables.

L’outil de compilation utilisé est Jam, développé à l’origine par Perforce et dont il existe plusieurs forks dont un maintenu par Boost et un autre par Freetype. Haiku utilise sa propre version de Jam avec de nombreuses évolutions.

Commençons la liste des changements dans cette section avec des mises à jour de dépendances : Haiku est maintenant compilé avec GCC 13.2 (la version 14 sera intégrée prochainement). La bibliothèque ICU utilisée pour implémenter toutes les fonctions d’internationalisation (qui se trouve donc avoir un rôle assez important dans la bibliothèque C standard) a été mise à jour en version 74.

Le travail pour supprimer tous les avertissements du compilateur se poursuit petit à petit, mais les problèmes restants sont de plus en plus difficiles à corriger, soit parce qu’il s’agit de code tiers (qu’il est plus facile de garder en l’état pour le synchroniser avec de nouvelles versions), soit parce que l’avertissement ne peut pas être corrigé proprement sans perte de performance, ou encore d’une façon qui contente à la fois gcc 13 et gcc 2 pour les parties du code compilées avec ces deux versions.

On peut toutefois mentionner que tous les trigraphes présents dans le code (par accident, par exemple il est facile d’écrire “??!” dans un commentaire) ont été supprimés. Ils ne sont plus disponibles dans C++ à partir de la version 17 et génèrent des erreurs de compilation.

D’autre part, l’option de compilation -Wno-error=deprecated a pu être désactivée, car plus aucun code ne déclenche cette erreur.

Puisqu’on parle d’options de compilation : l’optimisation “autovectorisation” pour la compilation du noyau a été désactivée pour l’instant. Cette option fait que le code utilise des instructions SSE, et faire cela dans le noyau problématique pour la plupart des machines virtuelles (QEMU, VMWare et Virtual Box). La plupart des autres noyaux n’utilisent pas ces instructions, ce qui fait que des bugs dans les hyperviseurs sont tout à fait possibles, par manque de tests. Mais le problème pourrait aussi venir de Haiku. L’investigation est pour l’instant remise à plus tard.

Un dernier changement dans le système de build consiste à permettre l’utilisation de git worktree. Quelques commandes git sont utilisées lors de la compilation pour calculer le numéro de version du code en train d’être compilé, et ça ne fonctionnait pas correctement dans ce cas de figure.

ZAYN LOGIN

La documentation de Haiku se découpe en 3 parties principales : un manuel de l’utilisateur, une documentation d’API, et une documentation interne pour les développeurs qui travaillent sur les composants du système.

Ces documents sont complétés par de nombreuses pages et articles sur le site internet, et deux livres pour apprendre à programmer en C++ avec Haiku, ou encore un document de référence pour la conception d’interfaces graphiques et un autre pour le style graphique des icônes.

KABY ARENA EXCHANGES

La documentation d’API de BeOS était assez complète et de bonne qualité. L’entreprise Access Co Ltd qui a hérité de la propriété intellectuelle de BeOS a autorisé le projet Haiku à la réutiliser et à la redistribuer. Malheureusement, cette autorisation est faite avec une licence Creative Commons n’autorisant pas les modifications. Cette documentation ne peut donc pas être mise à jour, ni pour corriger les erreurs, ni pour ajouter des informations sur toutes les nouvelles fonctions ajoutées par Haiku ou les différences entre les deux systèmes.

Il est donc nécessaire de réécrire une nouvelle documentation à partir de zéro. Ce travail est assez ingrat lorsqu’il s’agit de re-décrire ce qui est déjà très bien expliqué dans la documentation existante. La nouvelle documentation a donc tendance à se concentrer sur les nouvelles fonctions, et il faut souvent jongler entre les deux documentations, le contenu des fichiers .h, et des exemples de code d’applications existantes pour découvrir toutes les possibilités offertes.

Il ne semble pas utile de lister chaque fonction ou méthode qui a été documentée. On peut mentionner une page d’explications sur la bibliothèque C standard, comprenant des liens vers les spécifications POSIX qui documentent déjà la plupart des choses, et quelques détails sur les différences avec d’autres systèmes.

Une autre nouvelle page documente les primitives de synchronisation qui sont disponibles pour le code s’exécutant dans le noyau.

LEAGUE OF PETS EXCHANGE

La documentation interne était à l’origine simplement une accumulation de fichiers dans divers format dans un dossier “docs” du dépôt Git de Haiku. Depuis 2021, ces fichiers ont été rassemblés et organisés à l’aide de Sphinx, qui permet de mettre à disposition une version navigable en HTML et de donner une meilleure visibilité à ces documents.

D’autres pages sont petit à petit migrées depuis le site web principal de Haiku, qui n’est pas un très bon support pour de la documentation, et bénéficiera un jour d’une refonte pour être plus tourné vers les utilisateurs que vers les développeurs.

Quelques nouvelles pages ajoutées cette année:

  • Une documentation sur l’utilisation de divers outils de complétion de code automatique avec le code source de Haiku
  • Une page présentant l’organisation du code source et les principaux dossiers et sous-dossiers
  • La documentation de l’outil rc utilisé pour compiler les “resources” attachées aux exécutables a été intégrée
  • Le système de fichier FAT a reçu également une page de documentation à l’occasion de sa réécriture

SPACELENS EXCHANGE

L’association Haiku inc qui gère le compte en banque de Haiku publie chaque année un rapport financier.

Le financement provient principalement de dons des utilisateurs et supporters de Haiku. Le projet reçoit également une compensation financière de Google pour le temps passé à encadrer les participants du Google Summer of Code (voir le paragraphe suivant). La contribution de Google cette année est de 3300$.

Les plateformes de don les plus utilisées sont Paypal et Github sponsor. Ce dernier est recommandé car, pour les dons reçus via Github, c’est Microsoft qui paie les frais bancaires de la transaction. 100% de l’argent donné arrive donc sur le compte de Haiku. Tous les autres opérateurs ont un coût, soit fixe lors des retraits, soit un pourcentage de chaque don, soit un mélange des deux.

En 2023, l’association a reçu 25 422$ de dons et a dépensé 24 750$. Elle dispose d'une réserve confortable de 100 000$ (accumulés avant 2021, alors qu’il n’y avait pas de développeur salarié) ainsi que d’environ 150 000$ en cryptomonnaies.

Les dons en cryptomonnaies sont pour l’instant bloqués sur un compte Coinbase suite à des problèmes administratifs (le compte n’est pas correctement déclaré comme appartenant à une association, il faudrait donc payer un impôt sur le revenu lors de la conversion en vraie monnaie). Il semble difficile de contacter Coinbase pour régler ce problème.

Du côté des dépenses, le poste le plus important est le paiement de 21000$ à Waddlesplash, développeur employé par Haiku inc pour faire avancer le projet Haiku. Il travaille à temps partiel et avec un salaire très bas par rapport au marché, comme cela a été fait pour les précédents contrats entre Haiku inc et d’autres développeurs. Les finances de l’association ne permettent pas encore d’assurer un emploi à plein temps avec un salaire correct sur le long terme (c’est faisable sur le court ou moyen terme à condition de puiser dans les réserves de trésorerie).

Le reste des dépenses concerne principalement le paiement de l’infrastructure (serveurs pour le site internet, l’intégration continue, hébergement cloud pour les dépôts de paquets) pour environ 3000$.

Il faut enfin compter environ 500$ de frais Paypal, puis quelques dépenses administratives (déclaration de changement d’adresse de l’association, déclaration d’embauche) pour des montants négligeables (moins de 10$ au total).

En 2024, l’objectif fixé en janvier était de récolter 20 000$ de dons supplémentaires. Cet objectif a été atteint dès le mois de Juillet, et a donc été révisé pour tenter d’atteindre les 30 000$. Cela permettra de rémunérer Waddlesplash pour un plus grand nombre d’heures cette année, ou bien d’envisager l’embauche d’une deuxième personne si unë candidatë se présente parmi les personnes contribuant au projet (l’embauche d’une personne extérieure ne se fera pas tant que l’association ne peut pas se permettre de proposer une rémunération raisonnable).

COINS AND SKINS LOGIN

Haiku participe au Google Summer of Code depuis 2007. Il s’agit d’un programme ou des étudiants (et d’autres participants pas forcéments étudiants, ces dernières années) sont payés par Google pendant 2 mois pour découvrir la contribution à des projets de logiciels libres.

Ce programme a été monté par le “Open source program office” de Google. Leur intérêt est de défendre leur image d’entreprise sympathique (bien mise à mal ces dernières années, c’est devenu un géant de la publicité en ligne et de l’aspiration des données personnelles), et de contribuer à la richesse d’un écosystème de logiciels libres dont ils bénéficient beaucoup. Cela permet aussi d’encourager des personnes à s’essayer au développement logiciel, facilitant indirectement le recrutement chez Google en augmentant le nombre de candidats. Ces justifications peuvent sembler hypothétiques ou très indirectes, mais elles ont convaincu Google d’attribuer un budget de quelque millions de dollars à ce programme.

Une équipe de Google choisit les projets de logiciel libres participants parmi de nombreuses candidatures. Chaque projet participant propose une liste d’“idées” (un peu sous la forme d’un sujet de stage) et a ensuite la responsabilité de choisir parmi les candidats qui ont répondu à cette offre (en respectant les critères de non discrimination imposées par Google ainsi que les embargos imposés par les USA), et d’assurer l’encadrement des personnes sélectionnées. Google rémunère les participants, et dédommage les projets participants pour le temps investi.

Cette année les dévelopeurs de Haiku encadrent 5 participants :

LFEC LOGIN

Le système de fichier BFS utilisé par Haiku permet l’exécution de requêtes (comme une base de données) exploitant les attributs étendus des fichiers, qui peuvent être indexés.

Ce système permet de faire beaucoup de choses, et la fenêtre de recherche du navigateur de fichier essaie d’en tirer parti. Cependant, l’interface résultante est trop complexe, et peu de personnes prennent le temps de concevoir des requêtes améliorant leur façon de travailler, se cantonnant aux quelques exemples fournis.

L’objectif de ce projet est de refondre l’interface de cette fenêtre pour obtenir quelque chose de plus intuitif, et également d’afficher en temps réel les résultats de la requête dès qu’elle est modifiée, pour encourager les utilisateurs à expérimenter avec des requêtes plus complexes.

CMS 交易所

Haiku n’est pas encore parfait, et certaines tâches nécessitent encore l’utilisation d’autres systèmes d’exploitation. Une partie des utilisateurs ont donc une configuration en double boot, ou bien lancent Haiku dans une machine virtuelle.

L’objectif de ce projet est de permettre d’utiliser Haiku comme système principal, et de lancer les autres systèmes dans des machines virtuelles. Cela sera réalisé à l’aide d’un portage de NVMM, qui a été développé à l’origine par NetBSD et Dragonfly BSD. Cette bibliothèque a l’avantage d’être bien documentée et conçue pour faciliter son adaptation vers d’autres systèmes.

NVMM sera complétée par l’utilisation de QEMU qui pourra fournir un “front-end” à cette mécanique.

BEST FREE CRYPTO TRADING BOTS

Pour les personnes utilisant Haiku dans une machine virtuelle, il est intéressant d’utiliser autant que possible la famille de périphériques VirtIO.

Il s’agit de périphériques virtuels conçus sans s’inspirer de matériel existant, et plutôt pour avoir l’interface la plus simple possible entre la machine virtualisée et son hôte.

Haiku dispose déjà d’un jeu de pilote Virtio relativement complet (réseau, stockage de masse, affichage graphique). Le but de ce projet est de compléter cet ensemble avec un pilote pour les cartes son VirtIO.

COMMA 交易所

Haiku dispose de son propre débugger (appelé Debugger, de façon assez peu originale). Ce dernier présente une interface graphique confortable, mais une interface en ligne de commande beaucoup plus limitée. Il souffre également de quelques problèmes de performances et d’un manque de prise en charge des fichiers exécutables et bibliothèques compilés avec autre chose que GCC. Il est également incapable de faire du debug à distance ou de s’intégrer dans une interface graphique existante (par exemple au sein d’un IDE).

L’objectif de ce projet est de ressusciter la version de GDB ciblant Haiku. Cette version très ancienne était utilisée avant l’apparition du Debugger natif. Le projet est en bonne voie, le code d’interfaçage a été entièrement réécrit pour s’adapter aux versions modernes de GDB, et plusieurs évolutions et corrections ont été intégrées dans le système de debugging de Haiku (par exemple, pour mettre en pause tous les threads nouvellement créés afin que le debugger puisse les intercepter).

HAVEN PROTOCOL APP

Le navigateur WebPositive utilise le moteur de rendu webKit. Actuellement, il s’interface avec ce moteur via l’API WebKitLegacy. Cette API exécute tout le moteur de rendu web dans un seul processus, et ne fournit pas les garanties d’isolation nécessaires pour les navigateurs web modernes (que ce soit en terme de sécurité, ou en terme de fiabilité).

L’objectif de ce projet est de reprendre les travaux déjà entammés en 2019 pour migrer WebPositive vers la nouvelle API “WebKit2”, et bénéficier d’une séparation entre l’interface graphique, la communication réseau, et le rendu HTML/CSS/Javascript dans des applications séparées. Ainsi, un crash d’un de ces composants peut être récupéré de façon transparente sans faire disparaître toute l’application (et les données non enregistrées de l’utilisateur avec).

Le projet est également en bonne voie, un navigateur de test permet déjà d’afficher quelques pages ce qui montre que les bases sont en place. Il reste à régler de nombreux problèmes de rendu de texte, ainsi qu’à implémenter la gestion des entrées (clavier et souris) pour avoir un navigateur web utilisable. Il faudra ensuite migrer WebPositive vers ces nouvelles APIs.

NEWB FARM 交易所

Posted by pulkomandy on Sat Aug 31 15:15:22 2024  •  Comments (0)  • 

I had problems with my last batch of Nova boards. For some reason they would not work. At first I expected a bad solder or other issue while assembling the boards, but after the 3rd one not working in a row, I started to get suspicious.

Usually I would notice sooner, as I try to keep one working board in stock for comparing with the new ones if something isn't working. But due to "high" demand (I sold 30 of them), I didn't have a sample of the latest PCB revision to compare against. Also, one of the boards had an IC with a pin I forgot to solder, and on another one I put a chip backwards, which I had to unsolder and put back the right way, so I wasn't sure if something could have been damaged by that. Which is why I kept trying to assemble a "good" board to compare against.

Then, I noticed that he boards worked just fine, until I plugged the snaphat. This is a relatively simple thing: a component that clips onto the RTC chip, containing a lithium cell and a crystal, packed in epoxy. It has just 4 pins, two for the crystal and two for the battery. The chip is manufactured this way to allow SMD soldering of the RTC chip, and then adding the large package with the battery and crystal on top after soldering.

My current stock of snaphats comes from utsource. I ordered them in march 2023, I guess Farnell was out of stock at the moment and I decided to order them from utsource instead. What I received was obviously not the real thing, if you compare the chips side by side, the markings are very bad quality and out of focus, and the yellow plastic is visibly thinner, almost transparent. I expected these things would be at least marginally functional. Maybe the clock would drift, or maybe the battery wouldn't last very long.

Nova board with fake and real snaphat chips

What I didn't expect is for some of them to have the battery polarity reversed! This was the case for at least 7 of the 10 I bought. I say at least, because I have not done enough testing and it's possible that I sent 2 broken ones to a customer already (I test the boards without battery, if that works, I snap the battery on when shipping them and don't always do a full test that the battery works. Well, I will now.)

Interestingly, there are also one or two with the battery polarity correct. But the markings on the hat are printed flipped 180º, so the pin 1 marker is at the wrong place. At least the plastic pin forcing insertion in the right direction is placed correctly.

So... the good news is I know what the problem was, and fortunately it looks like nothing was damaged. The bad news is I have to order real chips and I lost 30 to 40€ in the process buying components that don't quite work. Unless someone is also manufacturing fake RTC chips which also have a reversed polarity for the battery terminals?

CHIK EXCHANGE

Posted by pulkomandy on Thu Aug 22 22:15:29 2024  •  Comments (0)  • 

Hello there! In the previous article in this series, I was trying to add a new backend to binutils, and my attempt was almost immediately stopped by a failure of expect (a tool needed for binutils test) when running on Haiku.

The bad news is the bgu with expect is not resolved. The good news is that I ported another assembler and linker, and then built a C compiler on top of that (with the previous article being published a bit more than a year ago, and me doing also a lot of other things in between, this is not bad at all).

I actually already talked about the vasm assembler in the previous post. At the time, vasm was not able to handle the pure 16-bit addressing, and its companion linker, vlink, had the same problem. When I discussed this with the developers, they initially weren't too interested about it, it would be a lot of work for a rather obscure CPU family. However, after I made this request, they got similar questions from at least two other people working on similarly strange architectures, and all landing on vasm as a possible candidate to get them out of that situation.

So, I received an email telling me that they finally decided to support it. Thanks a lot to the developers of vasm, vlink and vbcc, who were both very helpful with providing good documentation and also email support as I tried to get this working. Together we could identify a few problems and ask ourselves a few interesting questions, such as, what is the native endianness of a CPU that can only address 16 bit bytes and never consider them as an 8 bit or a 32bit quantity? Anyway, in the end, I could implement everything I needed in vasm, and Frank Wille made the needed changes in vlink so I could finally have an assembler that would build .o file and a linker that would link them into a cartridge image for the VSmile.

I believe this part of the work to be 100% complete now (in fact, it has been complete for a while and I did not discover any bugs). The next release (2.0) of vasm and vlink will thus include support for the unSP CPU.

Once that was solved, I turned my attention back to the compiler. Now it was possible to set it up correctly and use it to build a more serious C project. I used the Contiki operating system as my test project, because I had already ported it to the V.Smile using the compiler provided by the CPU manufacturer. So I know the C code was correct and all I had to do was translate it to assembler.

vbcc is very well documented, and also much simpler than more modern compilers. It works as most compilers do: the frontend parses the C code and convert it into a list of basic operations (load a variable into a register, add two values together, store something at a memory address, etc). The backend must then convert this list into actual assembler instructions. The main difficulty is that the internal representation uses arbitrary operations (such as operations using two operands in memory and storing the result also in memory), whereas the unSP CPU is a load-store architecture: operations will always store the result in a register (except the ST instruction), and at least one of the operands has to be a register as well. So, one single operation from the internal representation can turn into a few instructions. The other problem is that, with only 4 general purpose registers, there is not much space, and the frontend will usually decide to allocate all of them to variables used in the function. So, the generated code has a lot of PUSH and POP instructions to temporarily save registers on the stack and use them for something else. This could be improved by telling the frontend to always reserve one register for the internal use of the backend, or optimized in various other ways.

In a somewhat opposite way, the frontend does not know about some "advanced" operations that CPU instructions can do. For example, it has no notion of auto-increment instructions, that dereference a pointer and also change its value. The frontend will instead generate separate operations, to deference the pointer, then to increment it. A specific optimizer pass will be needed to handle this (vbcc already does it for other CPU architectures, but it is CPU specific so the code will have to be copied and adapted). Overall, the generated code is not the most elegant, but can be tweaked by writing the C sources in an unusual style, for example to better hint the compiler that some values are constant and can be used directly in the code instead of through a variable indirection. Modern C would solve this with the constexpr keyword, but vbcc doesn't have that yet. There are a few other problems such as relying a lot on the stack for variables, whereas on unSP it may make more sense to allocate them at fixed addresses (as static variables) for non-reentrant functions, in some cases.

Anyway, the most annoying thing was my own fault: the operands in the compiler internal representation can have various flags, such as REG to indicate that the value is stored in a register. I was initially a bit confused by what the flags meant exactly, and as a result, I wrote a lot of the backend code while ignoring some of them. Eventually (after a lot of time looking at dumps of the internal representation, comparing it with the generated assembler and using the MAME debugger), I started to understand what I had missed the first time, but a lot of code was already written, and it is very repetitive code but full of special cases. So, I spent quite some time fixing handling of the DREFOBJ flag (which means the variable or register value should not be used directly, but as the address of the operand, basically it is used to dereference pointers in C). There are probably some cases where it is still missing, and the pointer address value will be used instead of the pointed value.

Speaking of MAME: that is also a relatively recent addition to my toolset on Haiku. MAME itself had been available since 2019 (thanks to Extrowerk who did the initial port and recipe), but it was only since 2022 that I could build it with the Qt GUI for the debugger. Lately, Alex Brown has been taking care of updating it regularly to newer versions, which allows me to eventually get the few bugfixes to the VSmile emulation. MAME is actually the only application forcing me to have Qt (and a lot of dependencies) installed on my Haiku machine. Maybe someday I will look into building a native Haiku GUI for it instead...

I have more plans for this compiler, there is room for optimizations to generate much better code, and I should probably use it on some larger project on the VSmile console. But, for now, I will let it aside for a while, and maybe hope that someone else will help improve it (it's always nicer to not work alone on things, or just come back to a project after a while and discover that someone else decided to take care of it for a while). For now, I am already thinking about my next yearly talk at the Capitole du Libre conference, where I enjoy doing talks about weird and somewhat useless projects. I already did one about the VTech V.Smile 2 years ago, and I think it's too early for an update on that. But my attempts at porting Smalltalk to the Amstrad CPC should make a good talk. But it would be better if I show up with something at least somewhat working. So I guess that will be the goal for the next 3 months!

If you want to try the compiler for yourself, you will have to follow the manual setup instructions for now. I hope to make this simpler as the code get upstreamed in vbcc, and then vasm, vlink and vbcc get new releases including my work.

RICHPEPE LOGIN

Posted by pulkomandy on Sun Apr 28 16:59:31 2024  •  Comments (0)  • 

Liens en vrac vers les amis, projets auxquels je participe, et d'autres trucs...

PPN EXCHANGE

  • GrafX2, a multi-platform pixel art tool. I ressurected the project back in 2007, porting it from MS-DOS to many other platforms.
  • CPC SDK, an assortment Amstrad CPC cross-development tools. I got tired of gathering various tools from many places, most abandoned by their original authors, and decided to group them all in a single Git repository.
  • Haiku, an open source operating system for normal people.
  • ENSSAT Robotique, I was a member of my engineering school robotics team. We managed to get to the final phases of the French robotics competition.

DOO APP

  • Le blog d'ASCII, un collègue étudiant à l'ENSSAT. Jeux de rôles, sites web, et plein d'autres trucs super!
  • Le gate io de Sylvestre. De l'Amstrad, des gros pixels qui cligotent, et plein d'autres trucs super!
  • PauLLA, le LUG Palois.
  • Toulibre, des libristes à Toulouse.
  • Le blog d'Exocet, avec du pixelart dedans.

SCAT LOGIN

  • Kevtris (NES, FPGA, Chiptunes, misc. hacking and noodles)
  • Linus Akesson (Chiptunes, music, demomaking, atmega, C64 and pipe organs)

STARLIGHTCHAIN APP

Posted by pulkomandy on Tue Mar 19 21:15:18 2024  •  Comments (0)  • 

FXPAY 交易所

My previous article on porting Little Smalltalk to the Amstrad CPC received some attention and support messages from other people, who either find it useful, or just interesting to read. I got a comment from someone who was happy that I am doing retrocomputing and not just retrogaming. I'll take that as a compliment and I think it is a somewhat common theme in the Amstrad CPC scene.

As you can probably guess from the previous post on garbage collectors, I am still thinking about this project and trying to figure out a way to make things work.

First, I noticed that I had made a mistake in my first attempt: by not looking closely enough, I assumed that the image file would be somewhat specific to the word size and endianness of the target machine, leading me into attempting to build the image directly on the CPC. A closer look at the code made me realize that this is not the case. The stored image format is generic and does not change depending on endianness and word size.

So, that means I can throw away my work on porting the image builder, and focus on the VM itself. But I was still curious why the built image was more than 100 kilobytes. Surely there is not *that* much code in Little Smalltalk?

I started taking a closer look at the image file in an hex editor. And I noticed something that I should have found much earlier, especially as it was hinted at in the Little Smalltalk book. The image contains not only the bytecode, but also the sourcecode to all methods. This allows Little Smalltalk to not include a disassembler. You can open the sourcecode in an editor, edit it as you want, and then recompile it to create a new bytecode. But the price to pay is a lot of used up space in the image. I think later I will write (or port) a bytecode disassembler (I think there is one in one of the later versions/forks of Little Smalltalk?). For now, I disabled the sourcecode generation in the ImageBuilder, and it resulted in a much smaller image of 49KB. Now that's a size I have at least some chance of fitting into the CPC RAM! So let's try that.

The porting of the Smalltalk VM to the CPC is pretty similar to what I did for the ImageBuilder. I compile the C code, set up a linker script, replace file IO with AMSDOS routines which are much simpler than POSIX, but should still be enough for our needs at least to load the initial image. I encounter similar problems in the image loading than in the image saving (too much stack usage by recursive functions) and apply the same workaround (moving the stack to a different place before calling the heavily recursive functions).

Anyway, I got it running. Sort of. And then I ran out of memory again.

HPT LOGIN

To understand the problem (and the next steps), it is useful to understand how memory is addressed on the CPC. First, remember that the machine uses a Z80 CPU, and so, it can address 64KiB of memory using 16-bit addresses. On the CPC this is organized as such (rounded to the next 256th byte for simplicity):

  • 0000-0100: Reset vectors and "low jumpblock" from the firmware. This is the handlers for the RST instruction, interrupts, etc.
  • 0100-A700: Available for applications.
  • A700-BFFF: Used by the OS. Variables from the disk ROM, indirections for various system routines that are actually implemented in ROM, etc.
  • C000-FFFF: video RAM

So we have about 42KiB of RAM free for our application. Initially I tried to fit both the interpreter code and the Smalltalk heap (and any variables needed for the interpreter) into this space, and it didn't work. I removed various parts of the interpreter, I replaced the garbage collector with a stupid one that can't free any memory (this particular idea being brought up by one of the papers on garbage collectors I read, apparently some people were using their LISP machines this way for performance reasons and it was used also as a benchmark of the fastest possible GC algorithm).

Anyway, even with just half an interpreter, I still was out of memory rather quickly. So it's time to find other approaches.

ANITO LEGENDS APP

The Amstrad CPC OS is well designed to allow running code from expansion ROMs. These ROMs are mapped at C000-FFFF (overlapping the screen memory), and can easily call into the system ROM (which maps at a different address) and also call into other ROMs as neede (for example, the AMSDOS ROM for disk access).

To put our code in ROM, we need some changes to our linker script and CRT0. I based this on scripts I wrote earlier while making a ROM version of the Contiki operating system.

-mwx
-i allinone.ihx
-b _INITIALIZED=0x0100
-b _CODE = 0xC000
-k /bin/../data/sdcc/lib/z80
-k /packages/sdcc-4.4.0-1/.self/data/sdcc/lib/z80
-l z80
crt0_rom.rel
allinone.rel

-e

The main change here is that _CODE is now at 0xC000, and we also add that _INITIALIZED is at 0x0100. _INITIALIZED is where the RAM area starts, the other RAM sections are put right after it. So now the linker will put our code in ROM, and our data in RAM.

Of course we also need to adjust the CRT0 file.

;; FILE: crt0.s
;; Generic crt0.s for runing code as a CPC ROM.

  .module crt0
        .globl  _main

        .globl _progend

        ;; Ordering of segments for the linker.
        ; Things that go in RAM
        .area _INITIALIZED

        .area _DATA
        .area _BSS
    .area _HEAP
_progend::

        ;; Things that go in ROM
        .area _HOME
        .area   _CODE (REL,CON)
        .area _INITIALIZER (REL,CON)
        .area   _GSINIT (REL,CON)
    .area   _GSFINAL (REL,CON)

        .area   _CODE (REL,CON)

	    ;; The _CODE area starts with the ROM header.
		;; This has some version markers, a ROM type (background here, meaning
		;; it will not immediately take control of the system during boot),
		;; And a table of "RSXs", that is, commands that can be called from
		;; BASIC or ASM code by name.
        .db #1  ; Background ROM
        .db #4  ; Version 4.0
        .db #0
        .db #0
        .dw rsx_table

		;; The first routine is called during boot, in our case we do nothing
		;; at that point. The second is invoked by the name defined in the
		;; table below (|ST in our case).
        jp do_nothing
        jp init

rsx_table:

        .db 'T' + #0x80
        .ascii "S"
        .db 'T' + #0x80
        .db #0

init:
; This is the program entry point. Execution starts here
;; Initialise global variables, clear BSS areas
;; Note: not used in Smalltalk, I removed all initialized variables.
;; Probably still a good idea to clear the BSS part so all global variables are
;; initially set to 0...
;       ld      bc, #l__INITIALIZER
;       ld      a, b
;       or      a, c
;       jr      Z, gsinit_next
;       ld      de, #s__INITIALIZED
;       ld      hl, #s__INITIALIZER
;       ldir
;gsinit_next:
; Clear BSS sections
;       ld hl,#s__DATA
;       ld (hl),#0
;       ld de,#s__DATA + #1
;       ld bc,#s__DATA + #0x200
;       ldir

; Initialize disk ROM. We do the simplest thing here and just initialize ROM 7.
; It wouls be more compatible to save the currently active drive and see if
; there are other ROMs to initialize.
        ld hl,#0xabff
        ld de,#0x40
        ld c,#7
        call 0xbcce

        ; Init the heap. Do it after the disk ROM is ready, because that may change HIMEM
		; Not needed: no malloc/free is used.
        ; call __sdcc_heap_init

; Enter the C main.
        call    _main
        ; TODO figure out how to return to BASIC cleanly (we probably erased a bit much)
endless:
_exit::
        jr endless

do_nothing:
        scf
        ret

That's all we need, we can now run our C code from ROM. If it fits there, that is.

FROMMCARTOKEN LOGIN

At this point I had about 20-24K of code. A ROM is 16K, and, for now, I don't want the headache of switching between different ROMs for different parts of the code (maybe later, if I can't fit it all in one single ROM). So, I commented out more code from the interpreter and garbage collector and started simplifying some things. There is no difference anymore between static and dynamic allocations. All integer math code is removed as well as most other things. Also a big way to save space was replacing printf with simpler custom functions that don't do much custom formatting. I have way to print 16 and 8 bit values, NULL terminated strings, and "Pascal" style strings with a length known in advance. That is good enough, and it saved several kilobytes to not need printf's % parsing, decimal integer formatting, etc.

After this, I could finally try to run my VM again. And... it ran out of memory.

I guess that makes sense. Even after moving the VM code out of the way in a ROM, I still get only 42K of RAM free. And that has to hold not only the Smalltalk image data, but also all variables needed by the interpreter, the AMSDOS file buffers, etc. Well, it doesn't fit.

But, if you know a bit about the CPC, you have noticed the existence of the CPC 6128, a machine with twice as much RAM as what I have explained so far. How does this work? Well, the CPU cannot access any more RAM directly. So, there is a special hardware register to map extra RAM pages. There are various ways to use this, they are somewhat handcrafted to run CP/M Plus, a modified version of CP/M that was shipped with the machine and put the user code all in expansion memory, allowing applications up to 63K of RAM usage, with the video memory, and all system internals remaning in the main 64K of RAM.

Anyway, I decided to do something simple, and the simplest way to handle this memory in a way that's friendly to the CPC firmware is to map it by blocks of 16K at addresses 0x4000-0x7FFF. In my previous article about garbage collectors, I considered some more advanced options, but in the end I decided to keep things as simple as possible: all the Smalltalk heap and objects will live in this 4000-7FFF space, and I can keep the remaining parts of RAM (0100-3FFF and 8000-A7000) for the internal needs of the interpreter and GC (which will both need some variables and structures).

Of course, this create a new difficulty: the C compiler isn't designed to work with such memory banks. So, I will have to explicitly map the right memory page before accessing these variables. There are again multiple ways to handle this (so many choices...). For example, I could use a 16-bit address referring to a position in the 64K of extended RAM. But that would prevent having anything more than 64K of extended RAM. There are memory expansions for the CPC, and if just loading the base image already requires nearly 50K, I should rather prepare for use of one of these.

So, I will instead use indirect pointers. The idea is that pointers to objects can be represented as such:

struct indirection {
        unsigned char bank;
        struct object* ptr;
};

The "bank" here is the value to send to the Gate Array (the Amstrad CPC memory management chip) to map the correct RRAM page. For now we have to know about the vlaues C4, C5, C6 and C7 (these allow access to the 64K of extended memory) as well as C8 (this will put the 4000-7FFF from the base RAM back where it was).

The code to dereference an indirect pointer is like so:

__sfr __banked __at(0x7F00) GateArray;
// __sfr means this is accessed with the IN and OUT instructions of the Z80, instead of RAM access instructions
// __banked means the address is still 16bit (normally for IN and OUT it should be 8 bits, but manufacturers of hardware using the Z80 didn't respect this)
// __at(0x7f00) forces the variable to be at that address
// This means we can now write:
// GateArray = xx;
// And this will generate the appropriate assembler code:
// LD BC,0x7f00
// LD A,xx
// OUT (C),A

struct object* DEREF(struct indirection* x)
{
	    // Get the pointer first, in case the indirection is itself stored in
	    // the currently active bank (I didn't use that in the end, so maybe I
	    // can simplify this)
        struct object* o = x->ptr;
        GateArray = x->bank;
        return o;
}

I then modified the Smalltalk object structure to contain "indirections" instead of pointers to other objects. And I also added a lot of calls to DEREF all over the code of the interpreter, to map the correct memory page before accessing anything. As a first step, I didn't try to be smart about it (well, of course I did, then I had a lot of bugs, and I stopped trying to be smart, and then it worked better). So, I made a rule to not have any direct object* pointer stored anywhere in the interpreter code, only indirection* and calls to DEREF over and over. This will not be fast, as every other instruction will be switching to a different memory bank (or uselessly activating a bank that is already activated). But let's try to make it work this way first.

Starting from here, I have two choices. I can store indirections directly inside objects, or separately. Basically, one of these two:

// Indirection stored directly into the object
struct object {
        uint size;
        struct indirection class;
        struct indirection data[0];
};

// Indirection stored separately
struct object {
        uint size;
        struct indirection *class;
        struct indirection *data[0];
};

As you probably guessed by the fact that I named this structure "indirection", I went with the second option. The reason for this is that it is much easier to code when object sizes are in multiple of 2 bytes, and not in "multiples of 3 + 2". And also because you would have to be very careful to store the destination pointer before connecting the new bank, if the indirection itself was stored in a bank.

So, now, I have a big table of indirections living somewhere in 0100-3FFF. This table is filled with pointers to objects in the banked RAM. It creates a limitation to about 5000 objects in the system (16K/3). I have not hit this limit yet, but the initial image is already about half of that. We'll see how that goes.

This indirection also may simplify work for the garbage collector: it allows to easily move objects from one address to another, since all references to an object will be through the indirection table: just update the indirection table entry, and you're done. I think the garbage collector will benefit from that simplicity of not having to crawl through all other objects to find references to the one being moved.

Another advantage, mainly for debugging, is that there are now a lot of constraints on what a valid pointer is. An indirection must have an address in the 0100-3fff range. The pointed object must have a bank in the C4-C8 range, and a pointer in the 4000-7FFF value range. I have added some checks to my DEREF function to validate this. If the code attempts to dereference an invalid reference, execution stops with an error message.

Finally, these contraints also mean we have several unused bits, both in the pointers and in the indirections themselves. These are useful to store extra information. In indirection pointers, the high bit being set means that the value is not an indirection, but a direct 15-bit integer value. In indirections, unused bits in the bank or in the pointer fields can be used by the garbage collector to track which objects have already been garbage collected (the original code also did similar things, but using the size field in the objects themselves for the gc, and the lower bits of the pointers to mark integers, relying on the fact that allocations are aligned to 2 bytes and so for pointers that bit is always 0).

So, after all these changes and a bit of debugging, we're getting somewhere. The full image can be loaded into banks, and then execution starts. Unfortunately, it seems to be confused after a short time, returning to the wrong place after executing a "block2 (blocks are similar to lambdas in other programming languages).

So, I have more debugging to do. I have to keep a balance between adding more debug statements in the code, and not overrunning my budget of 16K of code in a single ROM. For now, I do not want to leave C and start rewriting things in assembler, because it would make it harder to change things and try new ideas. I hope I can delay that until the code is mostly running and there are at least some parts I'm sure won't change anymore. Then I can rewrite or hand optimize these first, and save enough space for debugging the other parts. Also, working in the ACE emulator has been very helpful, setting breakpoints in strategic places allowed me to find and fix many of the problems.

I continued debugging, identifying and fixing various issues. For example, if I use the DEREF function twice in the same line of code, like so:

DEREF(x) = DEREF(y);

that doesn't work right, because the = operator is not a sequence point. That means the bank activations for each side will not happen in the right order for things to be read and written where they should. So this must always be done through a temporary variable, which ensures proper sequencing.

Other mistakes include too many or not enough calls to DEREF, or simply writing code that doesn't behave the same way as the original while adding the DEREF calls. Eventually, I got it to run! Well, sort of.

AMS25K CRYPTO

One of the very first things the Smalltalk image does is creating the 256 "Char" objects for each of the ASCII characters. Each of them is a full-blown object, using up 6 bytes in the heap. This saves a lot of special-casing in the VM. But, the loop to create them ends up creating a lot of objects and filling up my indirection array. Eventually the indirection array grows into the 4000-FFFF space, overwrites some objects there, and things crash badly in various ways. So maybe this indirection was not such a great idea. Or maybe I need to start thinking about the garbage collection, and see how many entries in that array it would manage to free. But the problem with that is, at the moment, I have less than 128 bytes left in my ROM, so a GC is not going to fit. Unless I start removing debugging traces and optimizing some code in assembler. Which I don't want to do until I'm sure the indirection table approach is working.

Well, that's all for today. See you in the next article in the series...

MBULL 交易所

Posted by pulkomandy on Thu Feb 29 21:20:52 2024  •  Comments (0)  • 

Well, apparently I'm not ready to give up on Smalltalk for the Amstrad CPC yet.

The previous attempt showed that it is not possible to fit even a rather simplified Smalltalk interpreter into the main memory of the CPC. I guess this comes as a surprise to no one, since there are 16KB used by the display, about 8 used by the OS, and so only around 40K left for everything else.

It turns out, others have tried this and somewhat succeeded. Pocket Smalltalk for the Palm Pilot promizes to fit a complete game (Dungeoneers) in a similar space (I have not managed to run the game and have no idea if it is good). The Palm is a bit quirky in the way it works, but also, Pocket Smalltalk abandons the idea of editing things directly in the live Smalltalk image, instead it is designed as a cross development environment, more similar to a Java virtual machine in a way. That's why I had not considered it in my porting attempts. Well, maybe I should revisit it.

There is also TerseTalk, but that seems a bit too limited for me (only 256 objects?) and also not implemented yet (the code is extremely incomplete)

On my CPC, I currently have 2MB of memory, so, surely there would not be any problems running a larger version of Smalltalk. Maybe even Smalltalk-80 could be made to work somehow. IT will probably be slow. But would it even be possible?

The Z80 CPU cannot access all this memory linearly. Instead, all we get is a 16KB window that can be moved to any part of that 2MB space. This is one of the annoying things to handle with native code. Some people choose to keep their work running on the CPC 464, and not use any of this extended memory, to save the headaches. (Not attacking or ridiculing anyone here, it is a valid choice and there are other reasons for it). Anyway, I got thinking about how the abstractions of Smalltalk could make it possible to handle this memory mapping scheme transparently for the developper.

So I started to read about garbage collectors. This post is an attempt to ogganize these thoughts and see if we can come up with a design that will have acceptable performance. I will continue updating it as I continue thinking about it...

TOKENBETTERPOOL EXCHANGES

First let's talk about the general idea of dynamic memory allocation. The basic need is simple: an application is running and it wants to use memory for temporary storage, and release it later when not needed anymore, so it can be reused by something else.

One way to handle this is a very simple API like the one available in C: malloc() and free(). The application tells the memory allocator when it needs a new block of memory (nidicating how large the block should be), and gets a pointer to that block. It returns the block to the allocator when it does not need it anymore.

This seems as simple as it gets. Just two functions. But, it turns out, the job of the memory allocator is quite complicated. While the application keeps track of the currently allocated memory blocks, the allocator is responsible for keeping track of the ones that are not in use. This will tipically be managed with a "free list" of all the blocks that are not currently allocated. This can be implemented in a quite simple way, but there can be tricky problems, for example if the application forgets to free some block, or even worse, if it tries to free the same block multiple times. And even if the application has no bugs, this approach has another limitation: as long as a block is allocated and in use, it is not possible to move it in memory to a different address. This is because the application has a direct pointer to the block, and the allocator does not know what the application is doing with it.

The idea of garbage collectors is to solve some of these problems. From the API side, the problems all come from the free() function. It is hard to mis-use the malloc function. At worst, the application asks for more memory than is available, and gets an error instead of a valid pointer. The free() function however, can be misused, by calling it with addresses that were not returned by malloc, by calling it twice with the same address, by forgetting to call it, by trying to free blocks where information stored by the memory allocator has been erased, etc.

So, let's remove that function! Problem solved. This is the end of the article. Thanks for reading.

Oh wait. Of course that introduces a new problem. How is the allocator going to know when a piece of memory can be reclaimed and put back into the free list? Garbage collectors solve this problem by analyzing the content of the memory block. This, of course, requires some level of cooperation from the application. The general idea is that the garbage collector can access the data structures stored in the allocated blocks, and identify if they have references to other blocks. A block that is not referenced by anything else is unreachable by the application, and so, its memory can be reused.

The trick now is thinking about an efficient way to find such unreferenced blocks. But, since the garbage collector knows how to access the application memory and identify references in there, it may also write this memory and update the references to point to some new place. This gives us a new tool: it is now possible to move existing blocks in memory to a different place. As we will see, this opens a lot of new possibilities. The obvious one is that, after a while, with a typical malloc/free allocator, the memory becomes fragmented, and there are only very small pieces left. There is no easy way to get out of that situation. But with a garbage collector, you can. This makes garbage collection well suited to small memory systems, where fragmentation will quickly be a problem.

ATTENTION TOKEN OF MEDIA EXCHANGE

I have read some texts about garbage collectors, and most of them tend to present algorithms starting with the earliest ones, and introducing the new ideas gradually. This is a good idea, but I think I will make a change still: first I want to introduce some terms and explanations. The thing is, each of the algorithm is described in its original research paper with its own terminology, especially for the earlier ones. This, for me, makes it harder to think about how these algorithms can be combined together, which part of one can be reused in another, etc. We will need this, because most of the research on garbage collectors is done with much larger machines in mind, and no banked memory (at least the ones I could easily find. I am interested if you have papers or algorithm descriptions for something using banked memory).

The abstraction I found very useful is the tricolor invariant. It formalizes a bit what we need to do. Let's have a brief look at it.

The situation is that we have a set of objects in our memory. These objects have references (pointers) to each other. What we need to do is, starting from a root object or set of objects, determine another set of objects where we are sure that, by following any number of references, it is not possible to reach that second set starting from the first one.

If the root set is correctly chosen, this will allow to determine a set of objects that cannot be reached in any way from the application code. These objects are unused, and their memory can be reused.

So, how does a garbage collector goes about doing that? In very general terms, and without giving any specific algorithm, we can establish a solution that is proven to work. This is exactly what the tricolor invariant is.

What it does is attribute a color to each object in the system. There are 3 different colors. It could have been red, green and blue, but due to the technical limitation of printing technologies at the time, most litterature uses black, white and grey instead. I will stick with these to keep things simple.

That's the "tricolor" part explained. Now let's talk about the invariant. An invariant is a condition that must always be verified. The invariant is:

A black object must never have a direct reference to a white object.

At first this does not seem helpful. But it is the key to understanding all garbage collection algorithms. Let's look at our 3 set of objects now:

  • There is a set of black objects. They may reference grey ones and other black ones, but never white ones.
  • There is a set of white objects. They may reference anything.
  • There is a set of grey objects. They may reference anything as well.

So, because of the invariant, if we want to reach an object from another, we have a constraint (which is essentially a different way to express the invariant):

All paths from a black object to a white object will at some point travel through a grey object

Now, let's consider a special case. What if there are no grey objects in the system? In this case, because of the invariant, we are sure that there are no references from any of the black objects to the white ones.

I think you can see where we're going with this: if the "black" set is the objects (potentially) reachable by the application, and the grey set is empty, we are sure that the white set is made of unused objects, which can be deleted.

So, we can now redefine the job of the garbage collector as a two step process:

  • Step 1: colorize all objects such as the invariant is verified
  • Step 2: modify the coloring of objects to try to reduce the number of grey objects to 0
  • Step 3: when there are no grey objects, the remaining white objects are unused and their memory can be reclaimed

We have to eliminate one edge case: the stupid garbage collector that just makes all objects white. Then the invariant is verified, there are no grey objects, and so everything can be deleted. Simple, but not very useful. So, the initial setup in step 1 must have either one black or one grey object. Usually this is called the root: the object(s) that allow to reach all others. In Smalltalk, that is the object references currently in the application stack.

As I have written, this does not describe any specific algorithm just yet. Garbage collectors have to decide on various things, including: how to remember the color of nodes, how to assign the initial colors, and how to process the nodes to reduce the number of grey ones.

SHIBBURN.COM

Having established all this theory, let's look at the practical example of a typical malloc/free allocator.

Initially all memory is unreachable by the application. We can consider this a "white" memory block.

Every call to malloc takes some memory and makes it available to the application. Since the content of that memory is not yet filled by the application, it cannot at this time contain any reference to anything in the application, and even less any references to any other "white" (unused) area of memory. So, we can safely mark this block as black.

free() is used to return memory to the application. In theory, we don't know if the application still has references to that block in any other part of its "black" memory. So, we should mark this block black or grey. But, since we have no way to know what the application is doing, we don't have any algorithm to make this block white again. So, we have to trust the application that it is correct, and mark the block white.

It seems difficult to make anything simpler. But, if we look closer, we notice two things: first, it is not as simple as it looks. malloc() is given just a size, and it can't magically find a block of "white" memory where that fits. So, there will be some data structure to do that. We will see later how garbage collectors solve this. For a typicall malloc/free implementation, this will need to store a pointer or size at the start of each black memory block, and also at the start of white blocks, but since these are not used by the app, it's not a problem.

The second problem is more important, it's the way the invariant is maintained true. Essentially, we have delegated our job back to the application. This is what makes malloc/free an unreliable solution: the application developper probably does not want to think about memory allocation too much, and surely they will occasionally get it wrong. That's the problem we are trying to solve here. So, let's move on to better options.

VDO EXCHANGE

Let's see how Little Smalltalk handles this. According to the comments in the sourcecode, this is the Baker two-space algorithm. It is relatively simple.

First let's look at the way new objects are allocated. We start from the first available byte in memory. At every allocation, we increment a pointer by the size of the allocated object. That's it. Objects are allocated next to each other this way, until we reach half of the available memory. Then, the garbage collector starts working.

As we know, it must perform its job in three steps.

FEVR LOGIN

All objects in the garbage collected area are first considered white, except the root, which is grey.

Since there are no black objects, the invariant is verified.

Note: the root can be either the first object in the memory, or it can be stored outside of the memory in some separate storage (for example, in Smalltalk, the execution stack is the root and is not typically a dynamically allocated object).

BUTTMAN APP

Get the next grey object.

Analyze each reference in that object. Mark all the referenced objects as grey if they are still white.

When done, mark the object black.

Continue with the next grey object.

Eventually, there will be no more grey objects and the algorithm is complete. In the worst case, this stops when all white objects have been reached and marked grey, and eventually marked black after processing.

So far, this is how you would obviously implement such an algorithm. The trick is in how the algorithm remembers which objects are white, grey of black.

In Baker's two space algorithm, the "black" and "grey" objects are moved to the second half of the memory, while the white objects remain in the first half. This is pretty interesting, because it means all the information needed is already stored in the object addresses. No additional data structures at all are needed. Pretty impressive. But that comes at the cost of not being able to use half of the memory. Maybe that's a bit much.

Other algorithms instead reserve 1 or 2 bits in the objects to store the current color (only 1 bit of grey objects are remembered by some other means, for example, storing their addresses in a stack). That's likely more efficient, especially if you can find some available space for that extra bit. For example, if you have a 16-bit size field in objects, you could easily use one of these bits for the color. No one is going to fill the entire RAM with a single object, that would be stupid. So the size won't ever get that large.

Anyway, there is another problem with that general algorithm. We started by making almost all objects white. Since white objects have to be moved to a new place in memory, that means eventually moving all "live" objects into a new place, and also updating all references to these objects in other objects. If we do this for a large memory (say, 512KB or 2MB) at once, this is going to lock the program from running for quite a long time. Incremental garbage collectors solve this by making only one subset of objects white. But it is not so simple to do that, since we must make sure that the invariant is established (no black objects point to white ones).

LMN LOGIN

One thing we need to keep in mind is the CPC memory is addressed in banks. This means we can only access 16K at once (well, not exactly, but let's keep this simple). Is there a garbage collector taking this into account?

There does not seem to be a lot of research on such things. Which makes sense: when garbage collectors for larger memory became a reasonable thing to do, it was at least on 16 or even 32 bit CPUs, and possibly with virtual memory, and even hardware acceleration to help the GC on some LISP machines. All entertaining reading, but not really what I need.

Note: after writing the first version of this article I found about this article from Lieberman and Hewitt, which is quite similar to the solution I ended up with. It turns out, there probably is more research then you think about these things, it's just not immediately obvious where to find it.

So, I have to get back to the basics and consider how I can tweak them for my need. The idea is to work one 16K page at a time. When the page is full, do a garbage collecting cycle on it, so that we don't leave too many unused objects behind. Then, move on to the next 16K page and start over. Hopefully, we can then have one "in use" page with the recently allocated objects, some of which will have a short life and be garbage collected as soon as the page is full. And we have only a limited number of accesses to objects in other pages.

But, how do we implement that? Since we don't want to go through all of the memory, we can take some inspiration from more complex garbage collectors.

The algorithm can be used to do a complete garbage collection of all the system. This is done by first making all objects "white" (this is easy: just create any new object with the marking bit set to the "white" value). Then, start from the "root" (the references to objects in the program stack), and mark all referenced objects as grey. Then one by one, take one grey object, add all its referenced objects to the grey list, and so on, until there are no more grey objects.

When you are done, all allocated objects are now "black". Then, the memory can be accessed directly (page by page, not using object references), and the available space can be reused for allocating new objects. If you are used to C style memory allocators, you would then start adding all this free space to some kind of free list or something like that. But that's a bad idea: you are using memory to keep track of your free memory. With a garbage collected system, what you can do instead, is move objects around so that the remaining "black" objects are all tightly packed at the start of memory. Then, allocations simply consists of appending new objects at the end. Since each object has a field indicating its size, you can then use that info to figure out where the next object in memory is, and allocations are just incrementing the "last object" pointer by adding the size of the object to it.

Of course, when moving objects around, you must update references to them. In the two spaces method, this is done by putting a special marker at the old place where the object was, indicating its new address. As objects are moved to the new space, they can access this info. Once everything is moved to the new space, the old space is empty and has only unneeded redirections. But again, doing it this way would require going through all memory.

The tricolor scheme is better than that. One interesting thing is, if you read the above carefully, at some point I said "first, make all objects white". But this is a stronger requirement than what we really need. We have 1 condition that we must satisfy: black objects must not point to white objects directly, only to other grey or black ones. What if, initially, all our objects are black instead of white? This also verifies that condition, and the algorithm can run from there.

This opens some new possibilities. It means we don't have to perform garbage collection on all the RAM everytime. If we manage to build a small set of white objects, it can be scanned quite fast and without having to go in all the memory banks. For example, let's start by making all objects initially black. Then, we create a new object (in the currently active bank) and make it white. Surely we will store a reference to this object somewhere soon, and we will store it in another object. Since all our other objects are black, we are breaking our invariant condition here (we would have a black object pointing to a white one). So, we have two solutions: make the new object grey, or make the old one that points on it grey. Both of these preserve the condition. Making the new object grey is not very interesting, however: quickly, all our new objects will all become grey, then be considered by the GC as still used, and never deleted. So we must take the other option.

When we decide to run our garbage collection (for example, because the working memory bank is full), we know that it can only delete objects from the current bank (the only ones that can be white at this time). The "grey" list of references was built as we modified any other objects in other banks. We can check these objects, but we can optimize that check: since all banks other than the current one contains only grey and black objects, we only need to check references to the current bank. All other references would either point to a black object (that has already been scanned), or a grey object (that will be scanned already). We will not learn anything by checking these. And so we can quickly scan the current bank, find if all objects in it are still referenced, and then compact it and start over. We can do this until there is only one free 16K bank left. Then, we need to do a complete GC pass on all the RAM, that will take a longer time, but it will clean all remaining objects that became unreferenced after they were pushed out of the current bank.

Note an important thing here: the current bank always ends up being full, then garbage collected and the remaining objects moved elsewhere. There is also a lot of back and forth between this current bank and all the others during the gc phase (but also probably during running the Smalltalk interpreter). So, I suggest the following layout:

  • 0000-3FFF: The "current bank" with the newly allocated objects (sharing space with other things if needed: interrupt handlers, stack, global variables for the interpreter)
  • 4000-7FFF: In main RAM, the screen memory. Overlaid with memory banks being accessed when the VM is running. Just map the bank out when printing something to the screen.
  • 8000-FFFF: Interpreter and GC code, with the AMSDOS variables in the middle.

So we maintain two pointers for memory allocations: one in the 0000-3FFF area for freshly created objects. And one for the 4000-7FFF area in banks, for the longer lifetime objects. Once the 0000-3FFF RAM is full of objects, we do a small GC cycle of if to take care of the recently created and short-lived objects, then we move the remaining things to banks, and we start over. Until there are no banks left. Then, one big GC cycle to compact all the banks (if we ever manage to fill that much RAM, that is). We may even save ourselves the trouble for the "big GC": instead of compacting the RAM in place, if you run out of RAM, just save your session to disk. This is like a GC but still-referenced objects are written to disk instead of another RAM space. Then reload it. That's it, you just defragmented your whole memory!

One problem with this system remains: Little Smalltalk normally represents objects using 16-bit "cells" (a cell can be either: a pointer to another object, the object size, or a direct integer value. The VM uses the low bit to distinguish integers from pointers (pointers are always to an even address; integers are shifted by 1 and the low bit is always set for example. We could change this and use the highest bit instead, since all our pointers to Smalltalk objects would be in 0000-7FFF). But we have to store info in all pointers/references to know which bank it is pointing to. This would mean switching to 24-bit cells. This makes everything more memory hungry by 50%. Or, we could keep the internal pointers as 16 bit values, and have an indirection table somewhere to find the right destination. For example let's say the interpreter code is now moved to a ROM, so we can do this:

  • 0000-3FFF: The "current bank" with the newly allocated objects (sharing space with other things if needed: interrupt handlers, stack, global variables for the interpreter)
  • 4000-7FFF: In main RAM, the indirection table. Overlaid with memory banks being accessed when the VM is running. Just map the bank out when printing something to the screen.
  • 8000-BFFF: AMSDOS and firmware stuff, variables for the interpreter if needed.
  • C000-FFFF: In main RAM, screen memory (write-only). In ROM, the Smalltalk interpreter code.

So we have 16K bytes indirection table. If each reference needs 3 bytes, that's enough for 5461 objects. Maybe the table can go up to 9FFF, and then we have enough for 8000 objects. That would be enough to fill the 2MB memory if each object is exactly 256 bytes. Is this a reasonable compromise? I think objects will typically be smaller than that. So maybe using 24-bit cells is better. But then, the indirection table also simplifies things when moving objects around since you can use the table to redirect to the new address of an object when it is moved. Otherwise, you have to update all objects which are pointing to it. Not necessarily a big deal, this can be done at the same time as scanning the grey objects: look at the grey object, see that it references something white in the "new allocations" area, immediately move the white thing (if not already moved) to a more persistent storage in extended memory, and update the grey object with the new address.

Well, all of this easier said than done. I guess I have to write an implementation now?

CRYPTO BUBBLE MAPS

Posted by pulkomandy on Sat Feb 24 12:38:04 2024  •  Comments (0)  • 

This week project was an experiment with porting Smalltalk to the Amstrad CPC. It didn't work, but it was interesting. So here are my notes.

FLUID 2 EXCHANGE

Smalltalk is an object oriented language developed at Xerox PARC. It started in 1969 but the first release outside of PARC was in 1980, and was in fact the third major rewrite of the language.

Smalltalk was part of the "Dynabook" project, which was a research project about imagining the future of computing. The vision for this was a small personal tablet computer (hardware somewhat similar to an iPad), where you could run your own heavily customized system. Of course, this was way out of reach of 1970s technology. But that didn't stop the team. They built an "interim" machine to be the first step towards this: the Xerox Alto.

The Alto is a personal computer, but with a large CRT display and not portable at all. It implements the instruction set from the Data General Nova, an earlier machine that has a rather simple CPU, on top of a microcoded system that allows to reuse the same logic for also driving the display, implementing the disk controller, and a few other things.

The early versions of the hardware didn't have a lot of RAM, but since the project was about designing the future of computing, that was a problem. So, Smalltalk runs in a virtual machine, implemented in software, that implements virtual memory: most of the data is stored on disk, and loaded on-demand when the Smalltalk software needs it, and all of this, without the user/programmer having to think about it.

MIKAWA EXCHANGES

The CPC was one of the first computers I had access to. I still own one (several in fact) and still use it from time to time, as well as developping hardware expansions for it. The initial machine has 64K of RAM, later expanded to 128. But mine has a 2MB expansion card connected to it. However, the machine runs a Z80 CPU, which can only access a total of 64K of memory. As a result, extended memory is accessible in banks of 16K, one of which can be accessed by the CPU at a time. There are no languages that can handle this automatically: the BASIC shipped with the machine was never updated, and the SDCC compiler can do it, but in a bit limited way.

Anyway, the BASIC on the CPC is a rather good implementation, but it is still BASIC: not very fast, and not very well suited to structured programming. And C requires a cross-development setup, where the code is written and compiled on another machine, and the CPC is used just to run it. That's a bit sad, the machine should be able to work on its own.

There aren't many languages that can fit in these 64K of memory. Well, you can go with Pascal, and in fact there are pretty good versions of it for CP/M. You can go with C, but the Z80 CPU is not very well suited to a typical C compiler, and so the generated assembler code is messy and not efficient, and, more importantly, there is no hope for a good C compiler running directly on the machine (that would be possible with a simpler CPU or maybe if it was more reasonable to use the memory banks).

Moreover, my goal here is to have a language for quick prototyping and experiments. When I need the full performance of the machine, I'm happy with using a C compiler or even hand optimizing some parts in assembler. But this is a bit annoying to do on a larger scale. Essentially, I want something acting as the main interface for the machine, just like BASIC does, but with a more modern language.

This reduces the set of candidates to: BASIC itself, stack based languages such as Forth and LISP (which would both be good choices but are a bit too different from what I'm used to), maybe something like Lua or Wren (but not the existing implementation of Wren, which is based on floating point numbers and NaN tagging, not really suitable for the Amstrad. And there is Smalltalk.

The Smalltalk from Xerox as it was released in 1980 is interesting. The main interpreter could fit in a dozen or so kilobytes of code. That's just the amount we have on a CPC ROM expansion bank, so it could fit in the place occupied by the BASIC. However, Smalltalk is not just a language, it is a complete system, with a GUI, overlapping windows, a built-in debugger, and so on. Well, at least it would be interesting to see all of this running on the CPC, and how slow it would be. But maybe not as a practical thing to use, at least not as a replacement for the BASIC. The Smalltalk world mainly continued from there, and today you can find Squeak and Pharo, which are direct desendants of this version of Smalltalk, but keep getting larger and larger, and are probably much more than the CPC can handle.

YOUBANK APP

So, I had this idea of writing a Smalltalk VM for the CPC in the back of my head for a while. Lately, I looked again for existing Smalltalk implementation that I could maybe use as a starting point. You know, start from working C code, even if slow and inefficient, and gradually rewrite things out in assembler until I have something usable.

These searches brought me to Little Smalltalk. This is a dialect of Smalltalk, not quite compatible with the standard Smalltalk-80. The syntax is very similar, with a few minor differences. But, maybe more interestingly, the GUI environment and built-in debugger and all that stuff is not available. This is a command-line Smalltalk, initially designed for use from a simple serial terminal on a UNIX timeshared computer.

There are four versions of Little Smalltalk, each improving in the previous one and making the code simpler and nicer. Since this is rather simple C code, and it compiles to a reasonably small executable, it was not unreasonable to attempt porting it to the CPC. So I started hacking.

Little Smalltalk is a bit different from Smalltalk-80 in that it is not a completely abstract VM specification. For speed, it retains the pointer size of the host machine and uses that as its main type. With this and a few other tricks, and the removal of the GUI parts, it should be quite simpler than Smalltalk-80. Simple enough that I could attempt running it in a few evenings of work.

I started by compiling all 4 versions on my PC, and looking at the code size for each. Version 4 is indeed the smaller one, so I started with that. It also is the only one not using K&R style function prototypes, which is good for me, because SDCC (the C compiler I'm going to use) doesn't implement those.

From the start I noticed that the "image" size (the Smalltalk bytecode) was too large to fit in RAM, but I thought this was because of building it for a 64bit machine in my tests, and the final version would be considerably smaller.

DOGECZ EXCHANGES

There are various tutorials for this out there, but the ones I found were slightly out of date. So, I'm going to share my own files here, and explain what I needed to change in the Little Smalltalk implementation to get it running as much as I did (not enough for anything usable).

MARVELDOGE APP

If you know something about C, you know that execution of a C program starts with the main() function. Well, that isn't entirely true. Before this can be run, the code should make sure that all global and static variables are initialized to the correct values. In SDCC, this is implemented by the GSINIT code segment. To make sure this code is run before everything else, we need a little bit of assembler code, usually called CRT0. SDCC ships with a CRT0 meant for their own Z80 simulator platform, but that is not quite suitable for the CPC. So, here is my version suitable for the CPC.

  ;; This is the CRT0 module. Declaring this will make sure it shows properly
  ;; in .map files and other places.
  .module crt0

  ;; Note that the main function is a global that can be found elsewhere.
  ;; The assembler then knows how to emit a reference to it for the linker to
  ;; handle. Note that C functions are translated to assembler labels with an
  ;; extra _ in front of them.
  .globl  _main

  ;; The output file starts with a HEADER section, that is not loaded. In theory
  ;; we could put a standard AMSDOS header here, but I chose to do that with a
  ;; separate tool instead.
  .area _HEADER

  ;; Then we have all the sections with read-only code and data
  ;; GSINIT and GSFINAL are for the initialization code run before main (see
  ;; explanation below where they are filled in).
  ;; HOME and CODE is for the code and constants
  ;; INITIALIZER and INITIALIZED are for global and static variables initialized
  ;; with some value in the code. The GSINIT code should copy them from INITIALIZER
  ;; (in ROM) to INITIALIZED (in RAM) so they have the right value. In our case,
  ;; all the code and data is loaded in RAM, so we don't really bother with that.
  ;; DATA and BSS are the RAM areas used by the software. BSS should be cleared
  ;; to 0 during program startup.
  ;; Finally there is the HEAP, this is the area used for dynamic allocations.
  ;; This could be SDCC's malloc, but it is not a great implementation, in our
  ;; case we will use a custom and simplified allocator that can't free any memory.
  ;;
  ;; Each compilation unit (.rel file) can add data independently to each of these
  ;; sections. Then, the linker concatenates the section from each of them
  ;; (for example, all the GSINITs together) to generate the final output file.
  .area   _GSINIT
  .area   _GSFINAL
  .area   _HOME
  .area   _CODE
  .area   _INITIALIZER

  .area _INITIALIZED
  .area   _DATA
  .area _BSEG
  .area   _BSS

  ;; Now that we have defined all sections and in what order we want them (well,
  ;; in theory, but there seem to be other things messing with this order currently),
  ;; we can start filling in these sections with data or define symbols that point
  ;; to important parts of the memory, so these symbols can be accessed by the
  ;; C code (there will be examples of this later in the article).
  .area   _HEAP
  ;; Define a symbol for the "heap" start. This is the first address not used by SDCC
  ;; generated code, so anything above that is free for our own needs. Our simplified
  ;; memory allocator will make use of it.
_heap_start::

  .area   _GSINIT
gsinit::
  ;; All code that needs to be run at global init (before entering main) is inserted here by SDCC
  ;; Each compilation unit will generate little bits of code for each thing that needs initialization
  ;; (for example if you initialize a global or static variable with some complex expression).
  .area   _GSFINAL
  ;; The GSFINAL area is inserted after the GSINIT one. Usually nothing else gets added here, but
  ;; it could be used for example to implement atexit() or similar (code to run after main has
  ;; returned).
  ;; So, after the GSINIT code is done, we can call into the main function. We use JP to do a tail-call
  ;; optimization, the main function will return directly to the caller (to the BASIC interpreter for example).
  jp      _main

  .area   _CODE
  ;; Finally we need some code in the CODE segment. This will be put at the start
  ;; of the output file at 0x100 (see the linker script). For simplicity (since SDCC
  ;; does not generate the AMSDOS header for us), we put the entry point at that address.
  ;; TODO; it would be even better if the GSINIT and GSFINAL code was already at 0x100,
  ;; then we could directly have the program entry point pointing there.
  ;; Another option is to have GSINIT and GSFINAL at the end of the code, and overlapping
  ;; with the HEAP area. Since the init code is run only once, this allows to have this code
  ;; erased after it is run and not needed anymore. Maybe I will write about this
  ;; trick in another article later.
_start::
        jp gsinit

  ;; We also define the exit() function to be an infinite loop, because our code
  ;; expects that to be available.
_exit::
        jr _exit

So, we have a CRT0 file now. How do we use it? Well, we tell the linker about it using a linker script. Here is the one for the ImageBuilder tool (more on what that is in the next section).

-mjwx
-i imagebuilder.ihx
-b _CODE = 0x100
-k /bin/../data/sdcc/lib/z80
-k /packages/sdcc-4.4.0-1/.self/data/sdcc/lib/z80
-l z80
../crt0_cpc.rel
imageBuilder.rel

-e

This generates a file named "imagebuilder.ihx" in Intel hex format. It also forces the _CODE section to start at address 0x100 (this is where we want to load our program). It then declares the Z80 standard libraries, the linker will use these to provide implementations of standard functions (printf, malloc, strcpy, ...) if they are used. And finally, we have our two object files, the CRT0 and the output of the C compiler.

Finally we can tie this all together with a simple build script:

sdcc -c -mz80 --no-std-crt0 --opt-code-size --max-allocs-per-node 100000 imageBuilder.c -I../source
sdldz80 -f lst4.lk
makebin -p -o 0x100 < imagebuilder.ihx > imagebuilder.bin
hideur imagebuilder.bin -o ../IB.BIN -t 2 -x "&100" -l "&100"

The first two steps are compiling the .c file, and linking it using the above linker script. This result in a file in intel hex format, but we need a binary. The makebin tool is used to perform the conversion. Finally, we use hideur maikeur to add an AMSDOS header setting up the load address and entry point. As a result, our executable can be run directly from BASIC. That's all, we're up and running!

DTPL APP

ImageBuilder is a tool that parses a text description of smalltalk classes and methods, and converts it into a binary smalltalk "Image" containing class and method descriptions, and the bytecode to run for each of the methods. I need to run it on the CPC because the image format is platform specific (mainly, the class and object headers depend on the native pointer size).

Besides the things described in the chapter above, I made a number of changes to the ImageBuilder to get it to run. I believe these can be useful to anyone attempting to port C code to the CPC, so, here is the details of what I changed.

VITA EXCHANGE

Of course, we want to see what the program is doing. This is traced by printf statements througout the code. SDCC provides an implementation of printf, but it needs to know how to send the characters to the screen. For this, we need to use the firmware BB5A function. This function takes a parameter in A that is the character to print.

That's a good thing, because that is exactly the calling convention used by SDCC. So, we can just tell SDCC that this function exists at that address. We do this with a little function pointer trick.

#define bb5a ((void(*)(char))(0xBB5A))

What does this do exactly? Well, we define a macro called "bb5a" (this could be any name we want to give to the function). This macro takes the value 0xBB5A, and casts it into a function pointer, to a function that takes a char argument and returns nothing. That's all SDCC needs to know to call that function. Now, when we want to print a character, we can do this:

	bb5a('h');

Unfortunately, that is not enough to get printf to work. SDCC follows the C standard a bit too closely, and needs a putchar function that takes its parameter as a 16-bit value. Also, the code uses \n for newlines, while the CPC needs \r\n. We can take care of these two problems by defining our putchar function this way:

int putchar(int c) {
       if (c == '\n')
               bb5a('\r');
       bb5a(c);
}

SAFE UNIVERSE EXCHANGE

The ImageBuilder needs an input and an output file (the sourcecode and the generated bytercode image, respectively). The original code is written for UNIX, using FILE* and the corresponding standard APIs. These are not available on the CPC, but instead we have AMSDOS, which, in this case, provides a good enough support for file access. But, it is not designed for accessing it from C, and a few tricks will be needed.

First of all, we need to initialize the disk ROM. On the CPC, when a program is started with the RUN command, the system is de-initialized, and all ROMs are turned off. This means any attempts at disk access would instead try to target the tape drive. Well, technically that would work, but it's easier to use some modern mass storage (in my case, it is an SD card connected to the Albireo mass storage expansion). So, we need a function to re-initialize the disk ROM.

static inline void amsdos_init(void)
{
       __asm
               LD HL, #0xABFF
               LD DE, #0x40
               LD C, #7
               CALL #0xBCCE
       __endasm;
}

I kept this extremely simplified. Normally, this function should also save the current drive number for AMSDOS and restore it after reinitializing the ROM. It should probably not use hardcoded values for HL and DE, but determine where it is safe to put the AMSDOS buffers. Maybe it should init all the ROMs instead of just ROM 7. Anyway, for the ImageBuilder I just wanted to get up and running quickly. So, I call this from the start of the main() function.

Next, we need to open a file for input. Unfortunately, the firmware function does not accept its parameters in the SDCC calling convention. SDCC puts the first 8bit parameter in A, the second parameter in DE, and then everything else on the stack. The CAS_IN_OPEN firmware vector needs the filename length in B, the filename pointer in HL, and a temporary work buffer in DE. So, only DE is at the right place. However, by looking at the generated code, we can see that, to push the filename pointer to the stack, SDCC is also accidentally putting it in HL. I decided to abuse this since it made my life a little easier. So we end up with the following:

static char amsdos_in_open(char fnlength, const char* buffer, const char* const fn)
{
       // A = filename length (we need it in B)
       // DE = buffer
       // on stack = filename (but it is also in HL by accident)
       __asm
               ld b,a
               ;pop hl
               call #0xbc77
       __endasm;

       // TODO error handling
       // Popping is taken care by SDCC
       return 0;
}

While we're at it, the function to open a file for output is pretty similar:

static char amsdos_out_open(int fnlength, const char* buffer, const char* const fn)
{
       __asm
               ld b,a
               ;pop hl
               call #0xbc8c
       __endasm;

       // TODO error handling
       return 0;
}

And we can also add the functions to read and write characters, and close the files when done. These match the SDCC calling convention, so, we handle them like the BB5A function from earlier:

#define amsdos_getc ((char(*)(void))(0xBC80))
#define amsdos_putc ((void(*)(char))(0xBC95))
#define amsdos_in_close ((void(*)(void))(0xBC7A))
#define amsdos_out_close ((void(*)(void))(0xBC8F))

Finally, the original code also uses fgets to read the input file line by line. AMSDOS doesn't natively provide that, but we can easily provide an implementation. We just need to read the file until there is a newline, and make sure to add a NULL terminator after it.

static char amsdos_gets(char* buffer)
{
       char* fin = buffer;
       for (;;) {
               // FIXME test carry instead for returning
               *fin = amsdos_getc();
               if (*fin == '\n') {
                       *++fin = 0;
                       return 1;
               }
               if (*fin == '\0')
                       return 0;
               fin++;
       }
}

This is not really correct, the end of file is not properly detected (in fact, that's a problem from the way amsdos_getc was implemented here). But the work never got as far as reading the file until the end anyways.

Now we can implement our file IO. Note that in AMSDOS there are no file descriptors like in UNIX, there can be only one input and one output file opened at the same time. Fortunately, our needs are even simpler: the ImageBuilder first reads all of the input, closes it, and only then writes the output. So, all that's left to do is declare a working buffer for AMSDOS:

static char amsdos_buffer[2048];

And then we can replace all the calls to fopen, fgetc, fgets, fputc and fclose in the sourcecode.

METASNOOKER APP

After that, we try to run the program and... it immediately fails after trying to allocate some memory. It turns out, SDCC only provides 1000 bytes of memory to use for malloc() by default. That is, of course, ridiculously small. Changing that requires manually recompiling the memory allocator. I have no idea why they made it that way. Anyway, for the vast majority of allocations, the ImageBuilder never frees them. The idea is to keep everything in RAM until the final image can be generated. This means we can use an extremely simple allocator:

static void* memalloc(int size)
{
       extern char heap_start;
       // Make sure heap is aligned since the low bit is used for non-pointer stuff
       static char* ptr = (char*)(((unsigned int)(&heap_start) + 1) & 0xfffe);

       char* allocated = ptr;
       ptr += size;

       return allocated;
}

This allocator works by having a pointer to the start of the free memory, that is simply incremented whenever we need a new allocation. Where is the "start of free memory"? Well, remember in the linker script we declared a "heap_start" label that points there. So, we just need to grab the address of that label. So we declare it as an extern variable, and take its address. We then make sure it is an even address. This is because I suspect some things in Little Smalltalk use the lowest bit for storing a flag, so all allocated addresses must be even.

The code also makes use of strdup, the implementation from SDCC would still want to use its own malloc, so let's replace that as well:

static char* mystrdup(const char* in) { // keep heap aligned int len = strlen(in) + 1; if (len & 1) len++; const char* out = memalloc(len); if (out != NULL) strcpy(out, in); return out; }

Here as well, we take care of keeping the heap aligned. Otherwise, there is nothing special about it.

Finally, there was one place where malloc/free was used, that is in the ClassCommands methods that does something like this:

	char *class, *super, *ivars;

	// Some code here ...

	class = strdup(...);
	super = strdup(...);
	ivars = strdup(...);

	// More code here using those strings...

	free(class); free(super); free(ivars);

This is easily replaced with the following:

	char class[16], super[16], ivars[83];

	// Some code here ...

	strcpy(class, ...);
	strcpy(super, ...);
	strcpy(ivars, ...);

	// More code here using those strings...

And that's all, we can now run the ImageBuilder!

XPOSE EXCHANGES

Well, it starts parsing and compiling things, and it seems to work. But after a while, it crashes. Fortunately, I'm running this all in the ACE CPC emulator, which provides a good debugger and allows me to watch the CPU registers in realtime. I see that the code seems to be using quite a lot of stack space, and the SP register (the stack pointer) ends up way lower than it is allowed to be. The CPC firmware only allocates a relatively small space to the stack, since it didn't expect me to run complicated C code like this, with recursion and use of stack buffers to store strings.

That's not really a problem, we can move the stack somewhere else. But where? there is now a lot of things going on, and we don't really have much space to fit it all. Of course, it would be convenient if we could use the display RAM. On the CPC, this uses 16K of RAM, or 1/4 of the available space. Can we put the stack there? Of course there's the problem that we can't use that space for both the stack and for displaying messages. So, let's try to do it only while the parser function with the big recursive calls is running. And we can restore it to its normal location when we are done with the complicated parsing code. Let's add this to the parseBody function:

// Declare a new global variable where we can temporarily store the stack pointer
int savesp;
	// When entering the parseBody function:
	// Disable interrupts (so the firmware doesn't notice us doing strange things with the SP register)
	// Save the old value of SP to a global variable
	// Point SP to the screen RAM
       __asm
               DI
               ld (#_savesp),sp
               ld sp,#0xffff
       __endasm;
	// When exiting the parseBody function:
	// Restore the stack pointer to where it was
       __asm
               ld sp,(#_savesp)
       __endasm;

OK, it is a bit crazy to do this without telling the C compiler about it. But here it works because this function has no parameters and no local variables. And we do these things just at the right places so the compiler does not attempt to access the stack by other ways (such as by using the IX register as the frame pointer).

Now, we can see some glitches on screen while the parser is running, but at least it doesn't erase some important things in memory while running. And this gets us a little bit further into parsing the file...

NEXT CRYPTO TO EXPLODE

Unfortunatly, it does not get us far enough. With this setup, and tuning the compiler for optimizations a bit (that's the --max-allocs-per-node setting you saw earlier in the build script), we end up with about 16K of RAM available for the heap. I made some tweaks to other parts of the code, reducing the size of some memory buffers that didn't need to be so large. This heap fills rather fast as the parser creates more and more object declarations and compiles bytecode for several methods from the imageSource definition file. Unfortunately, we run out of memory after compiling barely 10% of the input file. So, a rough estimation is that we'll need 10x as much memory to get through the complete file. There's no way that's going to fit into the Z80 address space. Even if I removed most of the firmware, even if I used all the screen RAM. And then, the resulting image file would still be around 100K. So, the conclusion is that this is no match for the space efficiency of the Amstrad CPC BASIC, unfortunately.

UMI'S FRIENDS UNITY APP

Do I give up on running Smalltalk on the CPC? No, not really. But, it will need a Smalltalk VM that can manage banked memory. That's doable, as I have said earlier in the article, in the Xerox Alto they even did it by swapping things to disk, so, surely, memory banks are not a problem. But, if I'm going to do that, I may as well use the fact that I have 2MB of RAM, and so I can run a complete Smalltalk-80 image. I don't know how ridiculously slow that will be. But in any case, there is little gain from constraining myself to Little Smalltalk. If you're going to need hundreds of kilobytes of RAM for something, you may as well throw in a full-blown GUI in it.

Should I try some other language someday as a possible alternative to BASIC? Well, I'd love to. Ideally the requirements for that would be to use only 16K of code (fitting in a ROM), and maybe a few hundred bytes of RAM, leaving as much as possible free for the user. I think I would be fine with needing to write scripts in a text editor (such as Protext) and not have to use the way it is done in BASIC. Or maybe just a REPL where one can define custom functions and so would be fine. In Little Smalltalk, the editing of functions is left to an external text editor, and when the text editor returns, the resulting text is parsed and turned into bytecode. I think that's an interesting idea. Well, I'll keep looking at other options...

HOGE FINANCE EXCHANGES

Posted by pulkomandy on Mon Jan 1 11:25:33 2024  •  Comments (0)  • 

Many years ago, my cousin had a problem with his PS3. Apparently, the blueray drive stopped working. He disassembled it to see if he could fix it, but he couldn't. Then he asked me if I could take a look.

At the time, I thought that I could look into hacking it to allow playing games from the hard disk only. Surely that would be good enough. But, it was still the early days of PS3 hacking, at the time, the exploits needed a special USB device, which I didn't have. So, the console ended up sitting on a shelf in my paren'ts flat, and nothing happened.

Recently I decided to take a look at it again. So I took the console home with me and started investigating. I don't know what happened to this poor blueray drive when my cousin attempted fixing it, but it seems completely dead now. I didn't even manage to insert a disk in it. A brief research showed me two good news, however: hacking PS3s is now much easier, and there is also a special "noBD" firmware for people in this situation, because the console normally won't launch any game without a Blueray drive.

So, I got the noBD firmware and installed it. I did this a while ago, so I don't remember all the details, but it was straightforward, especially as this PS3 was running a very old firmware which is easy to hack. I am now running Evilnat's firmware (CEX, noBD). I also installed WebMAN which is the tool for running games from disk images on USB or hard disk.

Then the problems started. I wanted to install some PS1 games. One nice feature of the PS3 (at least the early models) is the backwards compatibility with the older consoles. Surely I could put some fun games there and play with friends? Well, it turns out, not really. The problem is, the console really wants to communicate with a blueray drive to start games that are meant to run from a CD. And for the PS1 games, there doens't seem to be any workaround for that.

Then I thought, OK, the BlueRay drive is mechanically dead, but I don't need it to actually read any discs. It just needs to be there. In reality, just the control board has to be there. So, I got the drive back (initially I had left it in my parent's flat) and I reconnected it insode the console. And I tried to install a normal firmware with Blueray enabled.

Well, this didn't work. The firmware cannot communicate with the blueray and this results in an installation error. Then the console reboots and tries again. And again. And again. And you can't exit that update loop, as there isn't even a way to access the service menu/failsafe mode in that state.

How do you get out of this? Well, the firmware is on the hard disk during installation. So, you remove and reformat the hard disk (I took the opportunity to replace it with a larger one). You don't need a specific format for the disk, just remove what's on it. The PS3 will reformat it. Then, prepare an USB key with a firmware update (a noBD one). Install the new HDD and hold the power button until the 3rd beep. Then release it and hold it again, again until the 3rd beep (this time it will be a double beep). You get to the service menu and from there you can install the noBD firmware again.

I still don't have a solution for installing PS1 games. I might try PS2 and PS3 ones. At least games in PKG format should work, so I can explore some of the interesting things that were sold on the PSN store, I guess. And also there are emulators for some older consoles.

But, in the end, the experience of a console with noisy fans is not that great. Should I bother with this? I don't know, maybe I will install a random set of games and put it in the break room at work, and we can have fun playing it during breaks with my colleagues. Do you have any games suggestions?

RAMESTTA EXCHANGE

Posted by pulkomandy on Thu Nov 30 18:52:17 2023  •  Comments (0)  • 

I have a shelf of old CDs, both audio and games. Some are very common stuff and not so interesting. Others are quite a bit more obscure, for a variety of reasons:

  • Audio CDs I bought at shows or from websites, that are not currently re-edited
  • Various shareware compilations and tie-in discs
  • Even for big well-known games, sometimes the French edition is not well archived even if the English one is

Anyway, it was one small worry in my life that if these discs would be damaged, lost, or stolen, I don't really have a backup plan. Actually, while archiving, I found some cases where the disc is missing (nothing impossible to replace, fortunately).

The other part of this problem is I had no remote backup. I used to do a "backup exchange" system with a few friends, where we would send our homeservers backups to each other. But people move on, servers go offline, and this is not available anymore. Related to that (and less so to the CDs archiving), I'd like to do more with my homeserver, but as long as there is no backup plan, and the server is a machine in my living room, the risk of data loss is just too high. So, I finally registered an account on iDrive so I can upload the stuff there. The server is now backed up, and I'm dumping the software and music there as well.

Due to copyright laws, this is a private archive for my own use. However, I will publicly list what I have. If it turns out some of this is not readily available, contact me and we'll figure out something.

I tried to do things "right", dumping ISO images where appropriate, all sound tracks as flac (both for the games and music CDs), as well as the extra content for Audio CDs. I also scanned the booklets and the disks themselves.

POPSICLEFINANCE EXCHANGE

  • 123 Free Solitaire 2003
  • 8 jeux de casse-tête (Pointsoft collection of Tetris-like and other braintwister games)
  • 3D Ultra Pinball - Le continent perdu
  • 3D Maze
  • Alien Detector Pro
  • Astrobeer
  • Blobby Volley
  • Blueprint menu editor (for editing The Sims objects)
  • Bousille écran
  • Boston Bomb Club (edited by Pointsoft)
  • CD Force 1 - Octobre 1999
  • CD Fun 1 and 2 - Février 2000
  • Car Tycoon (French version, I remember this being unplayable due to too many bugs)
  • Command And Conquer (with "Opérations Survie" extra disk)
  • Crop Circles
  • Dune II
  • Dungeon Keeper Gold (multilingual)
  • EcoQuest
  • EcoQuest 2
  • Freelog Hors Série 11 - Démos et Merveilles
  • Inca II Wiracocha
  • Get Medieval (Microïds CD with Shogun, Rage of Mages, and Corsairs
  • Grim Fandango
  • Gruntz
  • GT Racing 97
  • Heroes of Might and Magic III (GOG.com edition)
  • Hi-Octane
  • Hugo
  • Indiana Jones and the Fate of Atlantis
  • Lego Creator
  • Lemmings for Window 95
  • Lemmings 2
  • Lemmings 3
  • Lemmings 3D
  • Lemmings Revolution (a different print than the one available at WebArchive)
  • Les fourmis - Les Guerres de l'Ouest
  • Les Mondes Engloutis 2.0 (scenario for Age of Mythology)
  • Little Big Adventure
  • Lord of the Rings II
  • Lost in Time
  • Lost in Time 2
  • Ludorace
  • Mais où se cache Carmen San Diego edition Junior (Pointsoft and TLC edusoft)
  • MaxiMax Septembre 1999
  • Micro Machines v3
  • Monthy Python Sacré Grall
  • New World 3 - Trip to Australia demo
  • Oddworld l'Exode d'Abe
  • Pandora's Box
  • Pandemonium
  • Pandemonium 2
  • PC Mag hors série 21 (Shareware compilation)
  • Plane Crazy (PC Jeux 26 - Nov 99 - CD1)
  • Pointsoft Jeux pour Windows (several games edited by Pointsoft: Jungle colors, Snowmanland, Lost In Time, Wizards). The games are clones of well known things (Puzzle Bobble, Dr Mario, ...), but they have decent pixel graphics and great music by then demoscene musician Traven
  • Powerslide
  • Prince of Persia 2
  • RAMA
  • Rayman Forever
  • Red Baron (PC Fun Hors Série)
  • Q*Bert (version from 1999. My CD looks different from the ones already dumped at the web archive, I guess the French version got a different artwork?)
  • Rising Lands (Microïds)
  • RollerCoaster Tycoon
  • RollerCoaster Tyconn: Loopings en Folie scenario disc
  • Sim Tower (Maxis)
  • Sim City 2000 édition spéciale Media Pocket (a low-cost re-release, including the DOS, WIN16 and WIN32 versions with SCURK and other extras. The CD includes PDF user manuals in french)
  • Sim City 3000 OEM edition
  • Sim Life
  • Sim Town
  • Street Wars (Constructor 2) (Acclaim)
  • Les Super Maths (PC Junior CD #16) - A MAcromedia made game where You play X-Men characters in 4 minigames involving mathematical operations, graphs, triangles, and so on.
  • The Dig
  • The Incredible Machine 2
  • The Sims Transmogrifier 1.4
  • A random asortment of custom objects to add to The Sims
  • Theme Hospital
  • Theme Park
  • Traffic Giant (GOG.com edition)
  • Tux Racer 1.1
  • Tomb Raider II
  • Warcraft II Battle.net edition (in English)
  • Warcraft II Beyond The Dark Portal
  • Wild Tangent Front 9 minigolf
  • Worms 2

GAME CRYPTO PRICE

  • Alternine: both the original EP and the 2.0 from the rebooted band
  • André Minvielle et Lionel Suarez - Tandem
  • Antoine Reneaut - En Plénitude
  • Les aventures de Bibounet et Patacloum (companion CD to a DVD that I don't have)
  • Chorale Iroise - Couleurs Celtiques
  • Daft Punk - Ton Legacy soundtrack
  • Datarock - Datarock Datarock (EU version with extra tracks), also including the videoclips from the CD
  • Datarock - RED
  • Dr Wong - Heavy Metal Banania Unplugged, Tipiak, and covers of Zelda and Tetris
  • Eiffel 65 and Bloom 06 - All albums, nothing very exciting here I think
  • Eurovision Song Contest 2009 (CD1 only)
  • Fabulous Trobadors - Ma ville est le plus beau park
  • Flash (some Atari XL music)
  • Flavien Berger - Léviathan and Contre-Temps
  • François Hadji-Lazaro - Un recueil frais et disco (including DVD with videoclips)
  • Les Frères Brothers - First 2 albums
  • Guilhem Desq - Visions
  • Harajuku - Just One Look (incomplete)
  • La Tordue - All 6 albums
  • La Patate - L'alboom (if you know French you may remember their flash animation "La chanson de la patate" but you probably didn't there is a full album)
  • Les Escrocs - All 3 albums
  • Les Wriggles - Justice avec des saucisses
  • Malaussene - 2 albums and bonus tracks. They had these for free on their website
  • Mélusine - Chansons à écouter au coin du feu (a tie-in music CD sold with a comic book. Not bad music at all from people whose main job is comic book scenario and drawing!)
  • Mickey 3D - All 3 albums from a boxed set
  • Paula Powered - Level Up
  • Poison - The last legend
  • Pomplamoose - Invisible People
  • Hurricane on the Bayou (soundtrack from the movie/documentary of the same name
  • Tribute to Arno (Putain, putain, une tribu pour Arno)

DOGE RUN LOGIN

  • SLES-00278-2107629 - Bust A Move - Arcade 2 Edition
  • SLES-00838 - Oddworld - L'odyssée d'Abe
  • SLES-01502 - Oddworld - L'exode d'Abe
  • SLES-01893 - Bomberman
  • SLES-04166 - FIFA Football 2005

MISBLOC APP

  • 3D Prophet Kyro II driver CD
  • Akai LPD8 CD (Mac and Windows software and user manual)
  • Altera Complete Design Suite 7.2 for Windows and UNIX/Linux, with Cyclone II starter kit CD
  • ASUS Windows 7 Anytime Upgrade
  • BeOS "developer edition" distribution (versions 1.1 and 2.2)
  • Borland Delphi pour Windows (Presqu'Offert hors série juillet 1998)
  • CD from my high school music teacher with multimedia presentations about the music we had to study for exams
  • ClarisWorks 3.0 (Presqu'Offert 9)
  • DirectX 9.0 redistributable
  • DIV Games Studio
  • E-Icons 4.15
  • Genius Genitab III driver for Windows 98 and NT4, version 1.2
  • Global American Inc drivers - for a VIA embedded PC motherboard, a GPS received and a PCI serial card
  • GP2X F100 userguide (English and Korean)
  • HP PSC1310 / OfficeJet4200 / OfficeJet 5500 printer drivers (Windows 98-XP, possibly also Mac)
  • Iomega Zip driver
  • Klik and Play (French, Mac)
  • La Bible PC - Programmation système - 5ème édition (sold with the book of the same name, including all examples from the book, and also a Micro Application software and book catalog with weird background music, and a low resolution version of the "Don't copy that floppy" rap clip that takes more space than everything else on the CD)
  • Liquid Desktop screensaver
  • Matrox Millenium G450 driver CD
  • Micrografx picture publisher 6.0 (also including ABC Media Manager, older 16bit versions of Picture Publisher, and demos of other Micrografx software)
  • MP3 player driver (don't remember for which cheap MP3, either an S1mp3 compatible one or some later ipod Nano like thing)
  • Mustek ScanExpress 1200 SP (includes TextBridge and IPhoto Plus for Windows and Color It! for Macintosh)
  • NetBurner support CD (this is a Motorola Coldfire development board with an Ethernet port)
  • OfficeOne 7 - An office suite built from existing components (OpenOffice, Paint.net, Avast, ...) also including some games. Sold with an Asus computer back in 2008 or so
  • Partition Logic 0.66
  • PC100 Video Inside motherboard drivers
  • Shino Disquette v3.7
  • SNes9x 1.39a FR
  • Sound Blaster Live
  • ToUCam fun Philips webcam drivers, PCVC 730K version 1.01
  • Ultimate Boot CD 5.1.1
  • USB to IDE driver CD (I don't remember what piece of hardware it goes with, includes drivers for various chips)
  • USB to serial adapter driver (a Prolific based adapter)
  • USB 2.0 Digital HDTV Tuner
  • Various Palm software
  • Visual C++ Express 2005
  • Windows XP (first release)
  • Windows XP Pro SP3
  • Windows 7 Pro 64bit with Service Pack 1, French (ok you probably don't need this one...)

BITUSD LOGIN

  • Blanche Neige et les sept nains (Zylo / Goodtimes platinum series)
  • Heidi (Zylo / Goodtimes platinum series)
  • Le Bossu de Notre Dame (Zylo / Goodtimes platinum series)
  • Pocahontas

BTC BUY OR SELL

Some things I couldn't archive in time... Some of this is probably easy to find, and just notes to myself to get it. Other things are more complicated.

  • The Daft punk soundtrack is supposed to have some bonus on the disk. Unfortunateely, what's actually on the disk is an EXE file that will just send you to a now offline website. The web archive only has a backup of the landing page, because the actual content was behind a login wall. There were apparently 3 trailers for the movie, the videoclip for Derezzed, and a picture gallery. Did anyone doznload the pictures from the gallery or other stuff from that website?
  • Complete "Just One Look" album by Harajuku
  • My copy of Tomb Raider ("version longue"/extended edition) has only CD2. CD1 has been accidentally replaced by a CD of Tomb Raider II. Anyone has the matching Tomb Raider II case with CD1 of Tomb Raider 1 in it?
  • Bénabar - Infréquentable, I have the case but the CD is not in it
  • Petite Oreille by Boucherie Prod - A compilation CD released in 1996 with children songs by artists who don't usually do children songs. My CD is lost and this is long out of print, I'll have to locate a copy at acceptable price.
  • Megarace 2 - CD2 (French version), mine is too damaged to rip properly
  • Command and Conquer Soleil de Tibérium - GDI disc

KRYPTO MEANING

Posted by pulkomandy on Thu Oct 26 13:07:55 2023  •  Comments (0)  • 

I have a flat screen TV I bought in 2009. I use it for various retro computer things, mainly when I'm travelling and don't want to carry a CRT around. It is also useful because the VGA port will accept any timing, down to the 18KHz refresh rate of MDA/Hercules at least. It also has a few other cool things my CRTs will not do, like Teletext support.

There is just one problem with it, however: there is no way in the menus to force the SCART connector into RGB mode. This can be done only by sending the proper voltage (1 to 3 volts) to the SCART connector itself. Normally this isn't a problem: proper RGB SCART things will send that voltage, and everything will be fine. But I also want to use this port for other stuff, where I make an adapter myself for some other type of RGB output. Often there isn't a voltage source available on the power connector then. As a result, the TV switches to composite mode and shows a grey screen (since it uses the sync signal as a video signal, and so there is nothing to show).

TV showing a grey screen

Previously I did this as an external mod: getting 5V from the USB port of the TV, and feeding back into the SCART. But this requires making SCART connectors with a 5V input, the cable can break when transporting the TV... well, it's annoying. So I decided to make it internally instead.

I get the 5V from the Common Interface slot, this is a PCMCIA slot where you could plug a satellite TV receiver or crypted TV decoder or the like. Since this has a standard pinout, the 5V was easy to locate, and also they made it with very large soldering pads so adding a wire there was very easy.

Since the TV expects 1 to 3V on the RGB switching line, I use a 220 ohm resistor. The TV has a 75 ohm impedance, so this creates a voltage divider in the right range. Any resistor from 50 to 300 ohms would do.

Two wires soldered on the PCB, going from CI slot pin 17 to a switch (not visible, on the back of the PCB) and then to SCART pin 16

Finally, I mounted the switch by screwing it into the Common Interface slot. The slot is just wide enough to put the switch through, and will provide enough mechanical support once the switch is secured there.

the switch on the back of the reassembled TV

When the switch is ON, this will force the TV to use RGB input on the SCART port. When it's off, the TV will work as normal since the mod is disconnected. A quite simple change in the end, but very useful for me.

IPT APP

Posted by pulkomandy on Wed Aug 30 18:25:20 2023  •  Comments (0)  • 

That's it. I'm off Twitter now.

I used it for 5 years. I now have archives of everything I posted there.

Now you can find me on Mastodon instead. See you there!

CANDYPROTOCOL 交易所

Posted by pulkomandy on Sat Jan 1 15:19:32 2022  •  Comments (0)  • 

Please do not mirror my whole website using wget mirroring mode, WebReaper, or other similar tools. It results in a lot of requests to my poor old server, too much memory and CPU use, and the server fan spins up and makes a lot of annoying noise. So I will ban your IP or IP range from accessing the website if you try this.

If you want a full copy of some parts of the website, please contact me so we can set up a better way to share the data (I can set up an ftp or sftp or rsync thing, for example)

FRYTOKEN EXCHANGES

Posted by pulkomandy on Sun Feb 18 16:30:21 2018  •  Comments (4)  • 

This is the new server of the PulkoTeam! Enjoy your stay here.

On this website you can find various stuff I work on, around the Haiku project, electronics, 8bit computers, and random things depending on the day mood.