Articles avec le tag « VG5000 ».

VG5000µ, SetPoint en C

Après cette implémentation en assembleur Z80 d'une fonction setpoint qui affiche, de manière assez basique, un point à l'écran, je me pose la question d'utiliser un langage de plus haut niveau... mais pas trop.

J'ai une assez longue expérience du C et la question que je me pose est : qu'est-ce que ça donne de programmer en C pour générer du code sur Z80.

Programmer en C a quelques avantages a priori : c'est nettement plus concis et lisible que de l'assembleur, j'y suis plus habitué et c'est portable sur de nombreuses plateformes. C'est le cas d'autres langages, mais le choix naturel pour moi puisque écrire du C m'est habituel. En tout cas bien plus habituel que d'écrire directement de l'assembleur Z80.

Premier essai

Voici le code C d'un premier essai :

#include <stdint.h> // Afin d'utiliser les types standards

void setpoint(uint16_t x, uint8_t y) // Définition de la fonction
                                     // En entrée …
Lire la suite →

VG5000µ, SetPoint en ASM, afficher le point

À présent que l'on sait diviser par 3, reprenons l'affichage d'un point à l'écran. Pour rappel.

En entrée, nous avons : des coordonnées X et Y, comprises entre 0 et 79 pour X et 0 et 74 pour Y.

En effet de bord, c'est-à-dire en modification de l'état de la machine, nous voulons : le point correspondant à l'écran qui prend la couleur d'encre définie.

Pour cette version, la procédure ne prendra pas d'information de couleur, je me contenterai d'utiliser la couleur d'encre 0 (noir) sur fond 6 (bleu), qui est la combinaison à l'initialisation de la machine.

Les étapes, d'après les articles précédents, sont donc :

  • À partir de X et Y, trouver les coordonnées du caractère à modifier à l'écran
  • À partir de X et Y, trouver les coordonnées à l’intérieur du caractère semi-graphique
  • À partir de coordonnées du caractère, calculer l'adresse mémoire écran correspondante
  • Récupérer les valeurs pour la …
Lire la suite →

VG5000µ, SetPoint en ASM, diviser par 3 sans diviser

Les trois derniers articles sur la division on permit de s'attarder sur trois manière de diviser un nombre entier par 3.

La méthode de cet article, qui sera le dernier avant de revenir à l'affichage d'un point, va diviser grâce à, globalement, une seule addition. Oui ! Une seule addition.

L'idée

Au tout début de la série d'articles sur la division, j'ai mis en place un système de tests pour m'assurer que mes bouts d'assembleurs faisaient ce qu'il étaient censés faire. Et pour cela, je comparais une série de divisions avec un tableau de résultats.

Mais alors, pourquoi ne pas utiliser un tableau de résultats directement ? On stock quelque part le résultat de toutes les divisions par 3 des nombres entiers de 0 à 255, et on …

Lire la suite →

VG5000µ, SetPoint en ASM, diviser encore plus vite

Dans le dernier article, j'avais cherché une version plus rapide pour effectuer une division par 3, toujours dans l'optique d'afficher un point à l'écran en transcrivant la routine écrite en BASIC vers de l'assembleur Z80.

Le résultat était mitigé : une routine en moyenne plus rapide et plus stable, mais sur le domaine de définition considéré (le nombre de lignes graphiques du VG5000µ), pas entièrement gagnante.

Dans cet article, je vais donc étudier une autre manière de faire, un peu différente. Alors que les deux premières implémentations permettait de diviser par n'importe quel nombre de 1 à 255, cette nouvelle version est spécialisée dans la division par 3.

Est-ce que cette spécialisation permettra de gagner en performance et/ou en taille ?

L'idée

Le Z80 n'a pas d'instruction pour diviser de manière générale, cela a déjà été mentionné dans les articles précédents. Par contre, il est tout à fait possible de …

Lire la suite →

VG5000µ, SetPoint en ASM, diviser plus vite

Dans le dernier article, j'avais écrit une première manière d'effectuer une division, en spécialisant la routine pour une division par 3 puisque c'est ce qui m'intéresse pour afficher un point à l'écran du VG5000µ.

Pour référence, cette routine nécessitait 15 octets en mémoire et son exécution pouvait prendre jusqu'à 695 cycles, ce qui est plutôt grand.

Micro optimisation

La première optimisation est une micro optimisation. On appelle micro optimisation une amélioration de la routine par un détail de fonctionnement, plutôt que par une réflexion sur l'ensemble de la méthode.

Ici, l'idée est de remplacer le couple push bc / pop bc en début et fin de la routine par un couple exx / exx. L'instruction exx du Z80 effectue un renommage des registres BC, DE et HL. Ces registres (ainsi que d'autres, mais qui ne sont pas touchés par cette instruction) existent en deux exemplaires dans le Z80. Un exemplaire de chaque …

Lire la suite →

VG5000µ, SetPoint en ASM, diviser

À présent que j'ai un garde fou pour vérifier que je ne fais pas d'erreur d'inattention, me voilà près à diviser des nombres. Pour rappel j'ai besoin de diviser des nombres afin de faire les calculs permettant d'affiche le bon pixel à l'écran.

Pour second rappel, le Z80, au cœur du VG5000µ (et de beaucoup d'autres ordinateurs de l'époque) n'a pas d'instruction de division.

La division

Lorsque je divise de manière entière a par b, je veux trouver le nombre c tel quel $c * b = a$. Comme la division ne tombe pas toujours juste, j'ai aussi un reste r tel que $c * b + r = a$.

Autrement dit, combien de fois dois-je additionner b pour obtenir a (au reste près). Une manière de trouver le résultat est de soustraire b à a autant de fois que l'on peut sans passer sous 0.

Par exemple, $\frac{21}{7}$ se trouve comme ceci …

Lire la suite →

VG5000µ, SetPoint en ASM, vérifier les résultats

Après avoir mis en place une vérification (légère) de l'intégrité de la pile, je passe à la vérification de la validité de l'appel d'une fonction.

Le fonctionnement du test est assez simple : je prends une suite de nombres, j'appelle une fonction avec en paramètre chacun de ces nombres, je vérifie que le résultat est conforme à ce que j'attendais.

Par exemple, si je veux tester une fonction diviser par 2 (division entière), je peux utiliser la suite de nombre 0, 10, 32, 255 et comparer les résultats respectifs avec 0, 5, 16, 127 (255 étant impair, le résultat de la division entière est 127, avec un reste égal à 1).

Encore plus simple qu'une division par 2, il y a la fonction identité : celle qui renvoie le paramètre sans le toucher. Tester cette fonction permet de se concentrer sur le développement du test.

La fonction en elle-même est très …

Lire la suite →

VG5000µ, SetPoint en ASM, vérifier la pile

Il y a maintenant pas mal de temps, j'avais implémenté, en BASIC, une routine pour afficher un point à l'écran. Puis de là, une routine pour tracer une ligne, puis un cercle. Le constat était que c'était très lent. Le BASIC interprété est déjà plutôt lent de manière générale, et celui du VG5000µ n'est pas particulièrement rapide.

Il y a plusieurs raisons à cela, et ce sera peut-être le contenu d'articles futurs.

Mais en attendant, et après tous les efforts pour se confectionner un environnement de travail pour développer en assembleur, je repars sur l'implémentation du tracé d'un point à l'écran, et cette fois-ci, en assembleur.

L'avantage d'un programme écrit dans un langage de « haut niveau », comme le BASIC, est de simplifier bien des choses. Faire une division d'une variable A par 3 par exemple, peut s'écrire B = A/3. C'est simple, concis, lisible.

Traduire cela en assembleur n'est pas …

Lire la suite →

Automatisation : utilisation de Sublime Text 3

Dans les articles précédents sur l'automatisation au niveau des outils de développement, j'avais vu comment injecter un programme dans MAME en émulation VG5000µ d'abord grâce au debuggeur manuellement, puis avec un script LUA grâce aux possibilité d'extensions de MAME.

Ce n'est toujours pas suffisant pour moi. Comme je l'ai déjà écrit dans ces autres articles, je ne veux pas faire ce qu'une automatisation peut faire bien plus facilement, et sans se tromper. Lancer l'assembleur en ligne de commande, puis lancer MAME avec les bons paramètres, cela n'est pas bien compliqué avec un shell moderne (comme fish).

Un des principaux problèmes que j'y vois, outre que ce sont des opérations manuelles, c'est que ce sont des opérations non documentées. Si je fais une pause dans un projet et que j'y reviens deux mois après (ça arrive bien souvent, surtout pour du hobby), il y a de bonnes chances que je …

Lire la suite →

Scripter MAME pour explorer la machine

Puisque je suis actuellement dans l'utilisation de LUA pour scripter MAME, faisons un petit détour pour explorer quelques possibilités.

Les fonctions accessibles aux scripts LUA sont assez nombreuses. Je n'en connais pas de documentation complète si ce n'est dans les sources du programme lui-même à cet endroit : mame/src/frontend/mame/luaengine.cpp. Des groupes de commentaires indiquent les fonctions et leur usage. Reste à utiliser la console pour expérimenter un peu la façon de les appeler.

L'une des possibilités intéressantes est de pouvoir agir sur l'affichage de l'émulateur. Cela peut être assez pratique pour suivre certaines valeurs en mémoire, pour afficher des informations sur le comportement de la machine, voire d'ajouter des fonctionnalités interactives à l'émulateur facilement.

Affichage à l'écran

La première chose à faire pour afficher quelque chose à l'écran est de récupérer un objet permettant de le manipuler. Pour cela, en passant par l'objet manager, on récupère …

Lire la suite →

Injecter un programme dans un émulateur VG5000µ, partie II

La fois dernière était consacrée au lancement d'un programme sur VG5000µ avec l'émulateur MAME de manière à injecter un programme binaire directement en mémoire puis à l'appeler. Tout cela automatiquement. Pour rappel, l'idée derrière cela est d'éviter les erreurs de manipulations qui arrivent de temps en temps.

La première option utilisée dans l'article précédent était d'utiliser un script pour le debuggeur d'une part, et la capacité de MAME à entrer au clavier de la machine émulée une suite de frappes de touches.

Cette méthode fonctionne mais a ses limites : il faut régler le délai avant la frappe de touches de manière empirique, et le script est linéaire. Dans cet article, je vais utiliser une autre possibilité de MAME pour résoudre ces deux écueils.

La console

Commençons par une première manipulation.

mame64 vg5k -ramsize 48k -nomax -window -debug -debugger none -console

Dans le shell depuis lequel vous avez entré cette …

Lire la suite →

Injecter un programme dans un émulateur VG5000µ

Reprenons sur la programmation en assembleur sur VG5000µ depuis un ordinateur actuel. Car s'il est possible et tout à fait légitime, par hobby, de programmer directement sur la machine, à l'ancienne, pour « retro programmer » comme il y a du « retro gaming » en éprouvant les sensations originelles, ce n'est pas mon but ici.

Mon but, c'est de pouvoir programmer depuis un éditeur de texte simple, mais pas trop, et de pouvoir mettre au point avec certaines facilités comme un retour d'erreur d'assemblage et l'accès à un debuggeur. Et tout ceci avec une chaîne qui minimise les manipulations répétitives.

Minimiser les manipulations répétitives permet de rester concentré au maximum sur ce que je fais. Je n'ai pas envie, à chaque lancement, de taper des commandes particulières ou de faire quelques clics souris, toujours les mêmes, avec un risque de me tromper et de chasser un bug que je crois être là alors …

Lire la suite →

Travailler sur émulateur et dump de la ROM VG5000µ

Précédemment, j'ai commencé à parler d'une chaîne d'assemblage pour développer un programme depuis un ordinateur actuel vers une machine ancienne, le VG5000µ qui est l'ordinateur qui nous suit depuis le début de ces articles.

Un des avantages d'utiliser une machine de développement différente de la machine cible est de ne pas souffrir des erreurs, plantages et reboot provoquées par des erreurs. Imaginez, développer sur la machine que l'on programme elle-même, à une époque où le système d'exploitation ne protège rien du tout : une erreur, un reboot et si vous n'avez pas sauvé, il faut recommencer. Et si vous avez sauvé, les temps de chargements et de sauvegardes sont assez long, surtout sur une machine qui n'a pour mémoire externe qu'un magnétophone à cassettes !

Bref, développer sur une machine annexe et envoyer sur la machine cible, c'est plus simple, cela permet de profiter d'outils modernes mais... ça reste lent dans la …

Lire la suite →

Joyeuses fêtes en haute résolution

Puisque la fin de l'année approche et que les fêtes dites de fin d'années ainsi que le nouvel an sont d'actualités, j'ai ressorti mon convertisseur d'image vers le VG5000µ publié ici et décrit ici pour une image « haute résolution » sur la machine.

L'astuce pour que la compression passe bien a été de positionner le maximum de motifs identiques sur une grille. Pour les dates et l'adresse du site, j'ai ajouté dans le programme BASIC à la main l'affichage en texte.

91 J$="22001177--22001188"
92 CURSORX15:CURSORY17:TX6,3:PRINTJ$
93 CURSORX15:CURSORY18:TX6,3:PRINTJ$
95 CURSORX23:CURSORY23:TX6,0:PRINT"TRICERAPROG.FR"

On y voit que pour écrire en double hauteur, il faut doubler l'affichage sur la ligne suivante. Et pour écrire en largeur, il faut doubler les lettres à afficher. Le tout en précisant 3 en second paramètre de l'instruction TX.

Le dithering qu'effectue la conversion malheureusement n'a …

Lire la suite →

Les différents VG5000µ

Depuis le début de la création de ce site, la majorité des articles a été consacré à du développement sur VG5000µ. Les programmes sont testés sur du matériel réel, même si je les mets au points sur un ordinateur moderne. Les captures d'écrans sont aussi faites sur un vrai VG5000µ, en sortie sur un moniteur récent grâce à un adaptateur Peritel vers HDMI.

Le VG5000µ a cette particularité d'exister sous différentes marques : Philipps, Schneider et Radiola. Plus de détails peuvent se trouver sur des sites plus détaillés dans l'histoire de cette machine, comme je l'indiquais dans un billet en début d'année.

En attendant la suite des articles sur les outils pour programmer cette machine en assembleur, voici une petite photo de famille.

Photo de 4 VG5000µ

Lire la suite →

Des outils pour programmer en assembleur sur VG5000µ

La dernière fois, j'avais évoqué le logiciel d'assemblage, ou assembleur comme étant le programme permettant de passer d'un programme sous sa forme source, c'est-à-dire écrite sous forme lisible par un humain, dans une forme binaire, qui sera plus exactement nommée forme objet. C'est cette forme qui pourra être exécutée par la machine.

Pour programmer, quel que soit la forme que revêt cette programmation, on a besoin d'outils. Les outils primaires peuvent être une table de référence, des manuels, un stylo, des feuilles et beaucoup de patience. Rapidement, le besoin d'outils pour effectuer les tâches automatiques et répétitives qui forment la transformation d'un programme source en programme objet se fait sentir. Et quoi de mieux pour traier des tâches automatiques et répétitives de transformation qu'un... ordinateur.

Le problème de la poule et de l'œuf n'est pas le sujet ici. Le principal est qu'à l'heure de l'écriture de cet article, il y …

Lire la suite →

Du langage machine à l'assembleur sur VG5000µ

Après cette pause estivale, reprenons là où l'on était restés. Dans l'article précédent, je parlais du langage machine, une suite de signaux provoquant l'activité d'un processeur selon des directives précises.

Un inconvénient du langage machine, c'est qu'il est peu pratique à manipuler. Par exemple, sur un Z80, charger l'accumulateur (une mémoire spécifique interne au processeur) avec la valeur 1, je dois écrire : 00111110 00000001 en binaire, ou encore 3E 01 en système hexadécimal.

Écrire de cette manière n'est pas simple, prend beaucoup de temps avec un grand risque d'erreurs. Relire est encore pire. Programmez une machine de cette manière et vous ressentirez a priori rapidement le besoin de manipuler des éléments plus faciles à comprendre pour un Humain.

Et c'est ainsi que du langage machine on passe au langage d'assemblage, ou, par abus de langage, à l'assembleur.

L'assembleur

La première chose à savoir est que l'assembleur est un programme. Mais …

Lire la suite →

Z80 et VG5000µ

Lors des articles précédents sur l'affichage, un résultat était net : c'est lent ! Extrêmement lent. Les magazines ou de livres consacrés à la programmation des machines personnelles des années 1980 affirmaient tous ceci : si vous voulez quelque chose de rapide, passez à l'assembleur.

Que signifie utiliser l'assembleur, et en quoi c'est différent du BASIC ? Pourquoi est-ce que c'est plus rapide ? Était-ce vraiment la seule solution ? C'est ce que nous allons voir dans cet article et les suivants.

J'ai tenté plusieurs approches pour arriver au premier programme en assembleur dans une série d'articles. Et j'en suis arrivé à la conclusion qu'il n'y a pas moyen de passer outre quelques explications rapides des constituants de l'ordinateur et de leurs fonctionnements.

On va tout de même garder une vue large et schématique pour la plupart des composants. Pour le microprocesseur, un Z80 sur le VG5000µ, il faudra descendre un peu vers le fonctionnement …

Lire la suite →

Récréation 3D, VG5000µ version 2

Il y a deux mois, je publiais ma première récréation en 3D, une évocation d'un VG5000µ. J'avais modélisé la machine un peu au jugé et au final, il y avait pas mal d'erreurs dans les dimensions. Un peu trop à mon goût. J'ai donc refait l'exercice, cette fois avec un VG5000µ et une règle à côté de moi.

Et voici le nouveau résultat, bien plus satisfaisant.

VG5000µ en 3D, version 2

Lire la suite →

VG5000µ, haute résolution

Dans les articles précédents sur l'affichage du VG5000µ, je travaillais dans une résolution que je nomme « gros pixels », basée sur des caractères semi-graphiques. Grâce à l'implémentation d'une routine d'affichage de pixel, j'avais pu programmer un affichage de ligne et un affichage de cercle.

Avec ce mode d'affichage, on obtient une résolution de 80 pixels horizontalement par 75 pixels verticalement. Ce qui donne un total de 6000 pixels. Cependant, le manuel d'utilisation de la machine indique une définition d'image de 80 000 points. Plus de 13 fois plus. Existe-t-il une façon d'afficher des pixels plus petits et d'atteindre une haute (toute proportion gardée) définition ?

Petit rappel : je ne m'occupe pour le moment que des capacités du VG5000µ offertes par le BASIC, et se mettant à la place d'une utilisation à l'époque, avec juste le manuel de base.

Plus fin

Pour atteindre une définition plus fine depuis le BASIC, il faut …

Lire la suite →

Tracé d'un cercle en BASIC sur VG5000µ

Maintenant que nous avons un algorithme pour tracer un cercle ainsi que le moyen d'afficher un gros pixel à l'écran, nous voilà prêts pour traduire tout cela en BASIC, comme cela a été fait auparavant avec le segment de droite.

Pour rappel, voici l'implémentation en BASIC d'affichage d'un point à l'écran.

100 REM AFFICHE UN POINT DANS L'ESPACE SEMI-GRAPHIQUE
110 REM X CONTIENT L'ABSCISSE ENTRE 0 et 79
120 REM Y CONTIENT L'ABSCISSE ENTRE 0 et 74
130 ZX=INT(X/2):ZY=INT(Y/3)
140 RX=X-ZX*2:RY=Y-ZY*3
150 CH=2^(RY*2+RX)
160 DI=&"4000"+ZY*80+ZX*2
170 AT=PEEK(DI+1)
200 OL=64:IF (AT AND 128) = 128 THEN OL=PEEK(DI)
220 IF (OL AND 128) = 128 THEN OL=64
230 POKE DI,OL OR CH
240 POKE DI+1,224
250 RETURN …
Lire la suite →

VG5000µ, simplification du tracé du cercle

Avec de passer à l'implémentation en BASIC du cercle décrit dans un article précédent, passons un peu par une phase de simplification. Cet article va contenir quelques lignes de mathématiques.

L'outil mathématique le plus complexe utilisé est celui des factorisations et développements de carrés. Les identités remarquables seront d'un grand secours. Niveau de fin de collège je crois.

Pour rappel, voici l'algorithme de tracé de cercle de Bresenham :

  • initialiser cx et cy avec les coordonnées du centre du cercle, r avec son rayon
  • initialiser (x, y) à (0, r), c'est à dire le point au sommet du cercle.
  • tant que x ≤ y
    • tracer le pixel(x + cx, y + cy) et ses sept symétries.
    • calculer $m = (x+1)^2 + (y-0.5)^2 - r^2$
    • si m ≥ 0 alors $x \leftarrow x + 1$ et $y \leftarrow y - 1$
    • sinon $x \leftarrow x + 1$
  • fin

On pourrait l'implémenter tel quel. Mais je veux …

Lire la suite →

Après la ligne, le cercle

Après avoir tracé des segments de droite à l'écran grâce au BASIC du VG5000µ, passons au cercle.

Si vous avez fait un peu de trigonométrie à l'école, vous devez savoir que, pour un angle α allant de 0 à , tracer des points aux coordonnées (cos(α), sin(α)). Ces coordonnées sont multipliées par le rayon et déplacées au centre du cercle. Et c'est comme cela qu'il peut sembler de prime abord intéressant de tracer un cercle.

Cela ressemble à quelque chose comme ça.

  • initialiser cx et cy avec les coordonnées du centre du cercle, r avec son rayon
  • initialiser a à 0
  • tant que $a < 2\pi$
    • $x = cx + r.cos(a)$
    • $y = cy + r.sin(a)$
    • tracer un point en (x, y)
    • augmenter a
  • fin

Super simple.

Mais trop simple.

Dans l'algorithme ci-dessus, la ligne qui indique augmenter a n'indique pas de combien il faudrait augmenter a.

Lorsque …

Lire la suite →

VG5000µ, tracer une ligne en BASIC

Après avoir décrit un algorithme de tracé de segment de droite de manière générique, voyons un peu comment traduire ça en BASIC sur le VG5000µ. Pour ce premier article, il s'agira d'une implémentation simpliste, qui servira de base.

Pour rappel, voici l'algorithme générique :

  • En entrée, on a deux points de coordonnées (x, y) et (x', y')
  • Si x' est plus petit que x, échanger les valeurs de x et x' ainsi que de y et y'
  • Choix de l'octant en fonction de |y' - y| et de |x' - x|
  • Si on fait un balayage des x, alors
    • Calculer la pente $a = \frac{(y' - y)}{(x' - x)}$
    • Calculer $b = \frac{x'y - xy'}{x'-x}$
    • Pour tous les x'' de x à x', calculer $y'' = ax'' + b$.
    • Tracer un pixel en (x'', y'').
  • Si on fait un balayage des y, alors
    • Si y' est plus petit que y, échanger les valeurs de x …
Lire la suite →