L'API du Neo6502
Tout ce que le 65C02 demande au RP2040 — écran, son, fichiers, clavier, horloge — passe par une petite boîte aux lettres en $FF00. Voici son mode d'emploi, fonction par fonction, pour le firmware officiel et pour Trinity, avec des exemples exécutés et vérifiés.
Télécharger la spécification (YAML)
Deux processeurs, une boîte aux lettres
Le Neo6502 d'Olimex associe un vrai W65C02S, qui exécute les programmes, et un RP2040, qui fait tout le reste : sortie vidéo DVI, son, clavier et souris USB, fichiers sur clé USB, horloge. Le 65C02 dispose de 64 Ko de RAM ; pour obtenir un service du RP2040, il écrit une demande dans une zone de 16 octets en $FF00, la boîte aux lettres. Le firmware du RP2040 la lit, rend le service, puis y dépose la réponse.
| Adresse | Rôle |
|---|---|
$FF00 | groupe de la fonction ; l'écrire en dernier lance l'appel ; le firmware le remet à 0 quand c'est fini |
$FF01 | numéro de la fonction dans le groupe |
$FF02 | erreur : 0 si l'appel a réussi |
$FF03 | état : le bit 7 passe à 1 quand on appuie sur Échap |
$FF04–$FF0B | paramètres P0 à P7, en entrée et en sortie |
Un appel, en quatre temps
- Attendre que
$FF00vaille 0 (la boîte aux lettres est libre). - Écrire les paramètres en
$FF04et suivantes. - Écrire la fonction en
$FF01, puis le groupe en$FF00: l'appel part. - Attendre que
$FF00revienne à 0, puis lire$FF02(erreur) et les résultats.
C'est exactement ce que font la routine WaitMessage du noyau ($FFF4), la bibliothèque C de llvm-mos et l'unité neo6502 de Mad Pascal. Le noyau offre aussi quelques points d'entrée prêts à l'emploi : WriteCharacter ($FFF1), ReadCharacter ($FFEE), ReadLine ($FFEB), SendMessage ($FFF7)… Trinity y ajoute les tâches et les sémaphores ($FFC1 à $FFDC).
Conventions
- Les nombres de 16 et 32 bits sont rangés octet de poids faible d'abord (P0, puis P1…).
- Une chaîne est précédée de sa longueur (un octet), sans zéro final ; un paramètre de type adresse en indique l'emplacement dans la RAM du 65C02.
- Quand le firmware renvoie une chaîne dans un tampon, le premier octet du tampon doit contenir, avant l'appel, la longueur maximale acceptée ; le firmware y écrit ensuite la longueur réelle (vérifié dans
DSPSetStdString). - Un appel qui échoue met une valeur non nulle en
$FF02.
Dans chaque langage
- C (llvm-mos) :
#include <neo/api.h>donne des fonctions toutes prêtes (neo_system_timer()…) ; pour les autres, la structureControlPortdeneo6502.hdonne accès direct à la boîte aux lettres. Compilation :mos-neo6502-clang -Os -o prog.neo prog.c. - Mad Pascal : l'unité
neo6502fournit des routines (NeoGetTimer…),NeoSendMessage(groupe, fonction)etNeoWaitMessage. Compilation :mp prog.pas -target:neo, puis l'assembleur MADS.writelnpasse lui-même par la boîte aux lettres : lisezNeoMessage.errorou un résultat dans une variable avant de l'afficher. - NeoBASIC : une cinquantaine de fonctions ont un mot-clé (
time(),key(),locale…). Pour les autres, on écrit dans la boîte aux lettres avecpoke. Attention : NeoBASIC utilise lui-même la boîte aux lettres, par exemple pourprint. Il faut écrire paramètres, fonction et groupe sur une même ligne, et lire les résultats dans des variables juste après l'attente, avant tout affichage et tout calcul — sinon on lit la réponse d'un autre appel.*,/et les fonctions mathématiques passent eux aussi par la boîte aux lettres (groupe 4) : danspeek($ff04) + 256 * peek($ff05) + 65536 * peek($ff06), le dernierpeeklit une valeur déjà écrasée. - Assembleur 65C02 : on écrit directement en
$FF00–$FF0Bet l'on appelleWaitMessage; les exemples s'assemblent avec 64tass et se chargent en$0800.
Firmware officiel et Trinity
Le firmware officiel est celui de Paul Robson ; Trinity est le firmware alternatif du collectif, qui s'appuie sur lui. Chaque fonction porte une étiquette : Officiel (identique dans les deux), Modifié par Trinity ou Trinity (n'existe que dans Trinity). La fonction 1,11 donne la version du firmware en cours.
Comment les exemples sont vérifiés
Chaque exemple publié a été compilé puis exécuté dans l'émulateur Phosphoneo, avec le firmware Trinity. Un banc de test vérifie dans le journal des appels que le programme appelle bien la fonction documentée, sans erreur, puis compare ce qu'il affiche à ce qui est attendu ; la sortie observée est reproduite sous chaque exemple, sauf quand elle dépend d'un matériel branché sur la carte (entrées-sorties UEXT) : l'émulateur n'y rend que des valeurs factices. Un exemple qui n'a pas passé ce banc n'est pas publié.
Ce qu'on ne dit pas : les exemples tournent sous Trinity ; ceux des fonctions officielles n'ont pas été rejoués sur le firmware officiel. Sur la carte, quelques fonctions se comportent autrement que dans l'émulateur (port série, modem, flash) : leur fiche le précise.
Les groupes
| Groupe | Nom | Origine | Fonctions | exemples vérifiés |
|---|---|---|---|---|
| Groupe 1 | Système | Officiel | 25 fonctions | 97 |
| Groupe 2 | Console | Officiel | 24 fonctions | 96 |
| Groupe 3 | Fichiers | Officiel | 30 fonctions | 120 |
| Groupe 4 | Mathématiques | Officiel | 27 fonctions | 108 |
| Groupe 5 | Graphisme | Officiel | 27 fonctions | 108 |
| Groupe 6 | Sprites | Officiel | 5 fonctions | 20 |
| Groupe 7 | Manettes | Officiel | 3 fonctions | 12 |
| Groupe 8 | Son | Officiel | 16 fonctions | 64 |
| Groupe 9 | Tortue graphique | Officiel | 6 fonctions | 24 |
| Groupe 10 | Entrées-sorties UEXT | Officiel | 19 fonctions | 76 |
| Groupe 11 | Souris | Officiel | 5 fonctions | 20 |
| Groupe 12 | Blitter | Officiel | 4 fonctions | 16 |
| Groupe 13 | Éditeur | Officiel | 2 fonctions | 8 |
| Groupe 14 | Série USB (CDC) | Trinity | 6 fonctions | 24 |
| Groupe 32 | QuickDraw | Trinity | 19 fonctions | 76 |
| Groupe 33 | Gestionnaire d'événements | Trinity | 6 fonctions | 24 |
| Groupe 34 | Gestionnaire de fenêtres | Trinity | 12 fonctions | 48 |
| Groupe 35 | Gestionnaire de menus | Trinity | 10 fonctions | 40 |
| Groupe 36 | Gestionnaire de contrôles | Trinity | 10 fonctions | 40 |
| Groupe 37 | Gestionnaire de dialogues | Trinity | 6 fonctions | 24 |
| Groupe 38 | Gestionnaire de ressources | Trinity | 8 fonctions | 32 |