L'environnement Simple8
Avant d'écrire la première ligne de code, ce chapitre présente les outils : ce que fait le compilateur, les machines qu'il connaît, ses bibliothèques, comment l'installer et le lancer, puis comment préparer Simple8 IDE.
1.1Ce qu'est Simple8
Simple8 est à la fois un langage et un compilateur.
Le langage ressemble à Java et au C : des blocs entre accolades, des types
(byte, int, uint…), des fonctions, des boucles
for et while. Le compilateur traduit ce code en assembleur
natif pour la machine choisie, l'assemble, et produit le fichier que l'on charge dans un
émulateur ou sur la vraie machine : une ROM PC Engine, un .prg Commodore 64,
une disquette Amiga…
Dans sa version actuelle, Simple8 a été pensé pour les petits processeurs 8 bits : le 6502 et ses dérivés (HuC6280, 6510, 2A03), le Z80 et le SM83 de la Game Boy. Ses types, sa gestion de la mémoire et son code généré sont taillés pour des machines qui ont peu de registres, une page zéro et quelques kilo-octets de RAM. Les machines à 68000 sont prises en charge à titre d'essai (voir les architectures).
Un programme Simple8 dit toujours, en première ligne, pour quelle machine il est écrit :
architecture nec.pce; // ce programme est pour la PC Engine
Tout le reste en découle : le processeur visé, la façon d'organiser la mémoire, les bibliothèques disponibles et le format du fichier produit.
L'environnement complet se compose de :
- le compilateur, un programme Java livré sous la forme d'un fichier
LitleCompilator.jar, qui se lance en ligne de commande ; - les bibliothèques, le dossier
libs8/, qui donnent accès au matériel de chaque machine (affichage, sprites, son, manettes…) ; - Simple8 IDE, l'éditeur qui pilote le compilateur et lance les émulateurs ;
- et, pour les graphismes, SquareDot et 3DSpriteMaker, présentés dans leurs propres chapitres.
1.2Comment fonctionne le compilateur
Le compilateur part du fichier principal (main.s8p) et arrive à un fichier
prêt à lancer. Entre les deux, le programme passe par une chaîne d'étapes :
Dans le détail :
- LectureLe fichier principal, ses bibliothèques
(
addlib) et ses units (addunit) sont lus et découpés en arbre syntaxique. - AnalyseTypes, variables, portées et appels de fonctions sont vérifiés ; les erreurs sont signalées avec leur ligne.
- Représentation intermédiaireLe programme est réécrit en instructions simples, encore indépendantes du processeur.
- Code mortLes fonctions jamais appelées, y compris celles des bibliothèques, sont écartées.
- GénérationLe générateur du processeur (6502, Z80, SM83, 68000) écrit l'assembleur, puis l'optimise.
- AssemblageL'assembleur intégré produit le fichier final, les listings et les rapports.
Tout se fait dans le même programme : il n'y a aucun outil externe à
installer, ni assembleur ni éditeur de liens. Le compilateur écrit son travail
dans un dossier asm/, à côté du fichier compilé :
| Fichier | Contenu |
|---|---|
main.asm | l'assembleur généré, lisible, avec le code des bibliothèques utilisées |
main.lst | le listing : chaque instruction avec son adresse et ses octets |
main.sym | la table des symboles, que lisent les émulateurs-débogueurs |
main_report.html | le rapport de compilation : mémoire occupée, fonctions, code écarté |
main.pce, main.prg… | le programme à lancer, au format de la machine |
Lire l'assembleur généré est le meilleur moyen de comprendre ce que coûte une ligne de Simple8. Les chapitres suivants y reviendront souvent.
Quand l'abstraction ne suffit pas, le langage laisse descendre au niveau du matériel :
un bloc _asm { … } insère de l'assembleur au milieu du code, et le
compilateur vérifie les instructions selon le processeur de la machine.
1.3Les architectures
Une architecture désigne une machine précise. Son nom s'écrit
constructeur.machine, et c'est lui qui suit le mot architecture
en tête du programme.
| Architecture | Processeur | Machine | Fichier produit |
|---|---|---|---|
nec.pce | HuC6280 | PC Engine / TurboGrafx-16 | .pce |
nec.sgx | HuC6280 | PC Engine SuperGrafX | .pce et .sgx |
commodore.c64 | MOS 6510 | Commodore 64 | .prg, .d64 |
nintendo.nes | Ricoh 2A03 | NES / Famicom | .nes |
mos.6502 | MOS 6502 | 6502 générique | binaire brut |
amstrad.cpc6128 | Z80A | Amstrad CPC 464 / 664 / 6128 | .bin, .dsk |
zilog.z80 | Z80 | Z80 générique (MSX, Master System, Spectrum) | .bin |
nintendo.dmg | Sharp SM83 | Game Boy | .gb |
sega.megadrive | 68000 | Mega Drive / Genesis (expérimental) | .md |
commodore.amiga | 68000 | Amiga 500 PAL / OCS (expérimental) | .adf (disquette) |
Le langage est le même partout. Ce qui change d'une machine à l'autre, ce sont les bibliothèques (il n'y a pas de sprites matériels à l'identique sur une PC Engine et un Amstrad CPC), la mémoire disponible et la taille des nombres que le processeur manipule sans effort.
Les architectures 68000 sont des essais. Simple8 est aujourd'hui conçu pour les processeurs 8 bits. La Mega Drive et l'Amiga 500 fonctionnent, mais leur prise en charge reste expérimentale : le langage et le code généré ne tirent pas encore parti d'un processeur 16/32 bits. Une prochaine version de Simple8 doit améliorer le développement sur 68000.
motorola.68000, de son côté, est reconnue mais ne produit pas de code :
pour le 68000, on choisit une machine concrète, sega.megadrive ou
commodore.amiga.
1.4Les bibliothèques
Les bibliothèques sont des fichiers .s8l, écrits en Simple8 (souvent avec
un peu d'assembleur). Elles sont rangées dans le dossier libs8/, une branche
par machine :
libs8/
├── nec/pce/ PC Engine
│ ├── boot/boot.asm le démarrage de la machine
│ ├── system/ la bibliothèque système
│ ├── config.json la carte mémoire de la machine
│ ├── vdc/ l'affichage : tuiles, sprites, défilement
│ ├── vce/ les couleurs
│ ├── psg/ le son
│ └── io/ la manette
├── commodore/c64/
├── nintendo/nes/
├── …
└── math/ les bibliothèques communes à toutes les machines
Un programme charge une bibliothèque avec addlib, suivi du dossier et du nom
du fichier, séparés par un point :
architecture nec.pce;
addlib vdc.base; // libs8/nec/pce/vdc/base.s8l
addlib io.base; // libs8/nec/pce/io/base.s8l
Le compilateur cherche le fichier dans cet ordre, et prend le premier trouvé :
- le dossier de la machine :
libs8/nec/pce/vdc/base.s8l; - les bibliothèques communes :
libs8/vdc/base.s8l; - vos bibliothèques personnelles, dans le dossier indiqué par la variable
S8_USER_LIBS; - les bibliothèques du projet, dans son dossier
userlibs/.
Grâce à l'élimination du code mort, charger une bibliothèque ne coûte rien : seules les fonctions réellement appelées finissent dans la ROM.
1.5Installer Simple8
Ce qu'il faut
| Outil | Pour quoi faire |
|---|---|
| Java (JDK 21) | construire et faire tourner le compilateur |
| Git | récupérer les sources |
| Maven ou Ant | construire le compilateur |
Récupérer et construire le compilateur
-
Récupérer le dépôt :
git clone https://github.com/beddy70/Simple8.git cd Simple8 -
Construire le compilateur, au choix avec Ant ou avec Maven :
# Ant : le fichier est écrit dans dist/ ant compile jar # Maven : le fichier est écrit dans target/, et les tests sont lancés mvn package -
Vérifier qu'il répond :
java -jar dist/LitleCompilator.jar --help
Indiquer où sont les bibliothèques
Le compilateur doit savoir où se trouve le dossier libs8/. Le plus simple
est de le déclarer une fois pour toutes dans la variable d'environnement
S8_LIBS_PATH :
# macOS, Linux : à ajouter dans ~/.zshrc ou ~/.bashrc
export S8_LIBS_PATH=/chemin/vers/Simple8/libs8
export S8_USER_LIBS=~/mes_libs_simple8 # facultatif
# Windows
setx S8_LIBS_PATH C:\Simple8\libs8
Sans S8_LIBS_PATH ni option -l, le
compilateur ne cherche pas les bibliothèques dans le dossier courant : il ne les trouve
pas, et signale Library not found.
1.6Compiler en ligne de commande
Le compilateur se lance avec Java, en lui donnant le fichier principal du projet :
java -jar LitleCompilator.jar -f main.s8p
| Option | Effet |
|---|---|
-f, --file fichier | le fichier .s8p à compiler (on peut aussi le donner seul, sans -f) |
-l, --libs dossier | le dossier libs8/ ; passe avant S8_LIBS_PATH |
-d, --debug | affiche les étapes internes : arbre, représentation intermédiaire, assembleur |
-h, --help | l'aide |
Lancer la commande depuis le dossier du projet. Le dossier
asm/ est créé dans le dossier courant : compiler depuis un autre endroit
y déposerait les fichiers générés.
Essayer avec un exemple
Le dépôt contient des programmes d'exemple, rangés par machine dans
Examples/. Pour compiler le premier programme NES :
cd Examples/nintendo/nes/HelloNES
java -jar ../../../../dist/LitleCompilator.jar -l ../../../../libs8 main.s8p
Si tout va bien, la compilation se termine sans erreur et le dossier asm/
contient main.nes, une cartouche qui se lance directement dans Mesen,
FCEUX ou Nestopia.
1.7Simple8 IDE
La ligne de commande suffit, mais Simple8 IDE rend le travail plus confortable : on écrit, on compile et on lance l'émulateur sans quitter l'application. Les erreurs de compilation apparaissent soulignées dans le code, et l'assembleur généré se lit dans un onglet voisin.
L'installer
Bientôt des versions prêtes à installer. Des versions compilées de Simple8 IDE pour macOS, Windows et Linux seront proposées. Une version en ligne de la suite Simple8, utilisable depuis un navigateur, verra aussi le jour. En attendant, l'IDE se construit à partir des sources, comme décrit ci-dessous.
L'IDE se construit depuis le dossier ide/ du dépôt. Il demande, en plus de
Java, Rust (version stable) et Node.js 20 ou plus
récent :
cd ide
npm install
npm run tauri build # l'application, prête à installer
npm run tauri dev # ou : lancer l'IDE directement depuis les sources
Ouvrir un projet
Fichier → Ouvrir un projet… (⌘O) : on choisit le dossier du projet. L'IDE y cherche ensuite :
- le compilateur :
dist/LitleCompilator.jardans le dossier du projet, puis dans chacun de ses dossiers parents. Un projet rangé dans le dépôt le trouve donc tout seul. Sinon : Projet → Choisir le compilateur… ; - le fichier principal :
main.s8p, ou à défaut le premier.s8pdu dossier. C'est toujours lui qui est compilé, quel que soit l'onglet ouvert ; - les bibliothèques : le dossier
libs8/voisin dedist/, ou celui deS8_LIBS_PATH.
Fichier → Nouveau projet… (⇧⌘N) demande un nom,
une architecture et un dossier, puis crée un main.s8p prêt à remplir.
Sur macOS, une application ouverte depuis le Finder ou le Dock ne voit
pas les variables du terminal (S8_LIBS_PATH, S8_USER_LIBS).
Si on en a besoin, lancer l'IDE depuis un terminal.
Les raccourcis essentiels
| Action | Raccourci |
|---|---|
| Compiler le fichier principal | ⌘B |
| Compiler puis lancer dans l'émulateur | ⌘R |
| Ouvrir l'assembleur généré | ⌥⌘A |
| Ouvrir le listing | ⌥⌘L |
| Ouvrir le rapport de compilation | ⌥⌘R |
| Configurer les émulateurs | ⌘, |
Pendant la compilation, la sortie du compilateur défile dans l'onglet Sortie. Les erreurs et avertissements sont rassemblés dans l'onglet Problèmes : un clic ouvre le fichier sur la ligne en cause.
Git
Simple8 IDE gère aussi le dépôt Git du projet, sans passer par le terminal. Tout se règle dans Configuration → Git… :
- le dépôt : s'il n'existe pas, l'IDE propose de le créer, avec la
branche
mainet un.gitignoreadapté. Il affiche ensuite la branche, les commits en avance ou en retard et le nombre de fichiers modifiés ; - l'identité : le nom et l'e-mail des commits de ce projet ;
- le
.gitignore: le bouton Modèle Simple8 y ajoute ce qui ne doit pas être suivi, à commencer par le dossierasm/généré ; - les serveurs : ajouter, modifier ou supprimer les dépôts distants, et choisir ceux où envoyer le travail. Les mots de passe ou jetons d'accès sont confiés au gestionnaire d'identifiants de Git, jamais à un fichier de l'IDE ;
- valider et pousser : la liste des fichiers changés, un message, puis Valider ou Valider et pousser.
| Action | Raccourci |
|---|---|
Valider tous les changements du projet (git commit) | ⇧⌘K |
Pousser la branche vers les serveurs choisis (git push) | ⇧⌘P |
1.8Configurer les émulateurs
Le bouton ▶ Lancer compile le programme puis, si la compilation réussit, ouvre le fichier produit dans l'émulateur choisi. La liste ne montre que les émulateurs compatibles avec la machine du programme.
L'IDE en connaît un par défaut pour chaque machine :
| Machine | Émulateur par défaut | Autres choix prévus |
|---|---|---|
| PC Engine | Geargrafx | ares, Mednafen |
| SuperGrafX | Geargrafx | Mednafen |
| Commodore 64 | VirtualC64 | VICE |
| Amstrad CPC | Caprice32 | CPCemu |
| NES | Mesen | |
| Game Boy | Gearboy | |
| Mega Drive | ares | |
| Amiga 500 | FS-UAE |
Les émulateurs eux-mêmes s'installent à part. Ensuite, la fenêtre Configuration → Émulateurs… (⌘,) indique pour chacun si son exécutable est trouvé (●) ou non (○), et permet de choisir son chemin et l'émulateur par défaut de chaque machine.
Le fichier emulators.json
Pour aller plus loin, la configuration est un fichier JSON, ouvert par
Configuration → Éditer emulators.json. Un projet peut aussi avoir son
propre fichier simple8-emulators.json, qui remplace la configuration
générale entrée par entrée :
{
"defaults": { "nec.pce": "ares-pce" },
"emulators": {
"ares-pce": {
"name": "ares (PC Engine)",
"command": "/Applications/ares.app/Contents/MacOS/ares",
"args": ["--system", "PC Engine", "--no-file-prompt", "${rom}"],
"architectures": ["nec.pce"],
"rom": "${asmDir}/${name}.pce"
}
}
}
| Variable | Valeur |
|---|---|
${projectDir} | le dossier du fichier compilé |
${name} | son nom, sans extension |
${asmDir} | le dossier asm/ du projet |
${rom} | le fichier à lancer |
${sym} | la table des symboles, pour les émulateurs-débogueurs |
1.9L'organisation d'un projet
Un projet Simple8 est un simple dossier :
MonJeu/
├── main.s8p le programme principal
├── Joueur.s8u d'autres units, ajoutées avec addunit (facultatif)
├── userlibs/ des bibliothèques propres au projet (facultatif)
├── simple8-emulators.json les émulateurs du projet (facultatif)
└── asm/ créé par le compilateur
| Extension | Rôle |
|---|---|
.s8p | le programme : il déclare l'architecture et contient la unit principale, avec main() |
.s8u | une unit dans son propre fichier, pour découper un programme qui grandit |
.s8l | une bibliothèque, chargée avec addlib |
Le dossier asm/ est entièrement régénéré à chaque compilation : on peut le
supprimer sans risque, et il n'a pas besoin d'être conservé dans Git (le modèle .gitignore de l'IDE l'exclut).
L'environnement est prêt. Le chapitre suivant écrira le premier programme.
