Re: Tutoriel coroutines

Top Page

Reply to this message
Author: Frédéric
Date:  
To: Guilde
Subject: Re: Tutoriel coroutines
Le mercredi 08 décembre 2021, Yves a écrit :

> Que de nostalgie... DJNZ 0x10... toute mon adolescence ! mais à
> l'époque j'étais plutôt sur le demo-making que sur le micro-kernel.


Cool :o) Sur CPC ? Je ne sais pas si tu as vu, mais il y a encore pas mal
de choses qui se font dans ce domaine. Et des choses plutôt balaises, en
plus ! Et comme le CPC était surtout populaire en France, il y a beaucoup
de français dans le coup.

> Ton mini-scheduler de tâches est simple et efficace. Bravo.


Merci ! Je me souviens l'avoir utilisé avec des circuits I²C, avec un CTC
qui se chargeait de générer les interruptions.

> Une coroutine est (aujourd'hui) souvent conçue pour un langage de
> programmation haut-niveau qui tourne déjà sur une système multi-
> threads. Sa particularité vient de la méthode "yield" qui permet de
> rendre la main "provisoirement" https://en.wikipedia.org/wiki/Coroutine
>
> En partant de ton scheduler de tâches, je verrai bien simplement un
> équivalent de "yield" après l'affichage d'un caractère (pour ton
> exemple de print) qui consisterait en la séquence:
> - écrire (ps + x octets) dans la stack associée au processus
> - jump vers la logique de bascule de tâche qui tu factorises dans une
> méthode
>
> En calculant le "x octets" correspondant au décalage requis pour que le
> retour du sp arrive juste après le jump.


C'était ce que j'avais en tête. En gros, d'après ce que tu dis et de ce
que je lis sur Wikipedia, ce yield est donc en fait le seul truc à mettre
en oeuvre ?

> Ton gestionnaire d'interruption réutilisera alors la méthode factorisée
> de changement de tâches.


Ah, alors en fait, dans le jeu, il n'y a pas d'interruption : du fait de
l'utilisation d'une astuce pour afficher plus de couleurs que prévu par le
mode graphique, je dois me synchroniser sur la VBL (Vertical BLanking), et
garder la main pendant l'affichage de l'image pour modifier la palette à
chaque ligne, de manière synchrone. Ensuite, il me reste un peu de temps à
la fin de l'écran, et avant le retour faisceau, pour faire autre chose.

Du coup, tout le code ne doit pas prendre plus de temps qu'une frame,
sinon, ça clignote merdiquement :o/

Il y a 2 choses que je dois faire impérativement à chaque frame : changer
les couleurs pendant le balayage des 200 premières lignes (ça bouffe les
3/4 du temps), et rafraîchir le chip son pour jouer la musique (sinon,
glitchs sonores et vidéo). Ensuite, ce sont les diverses routines de
gestion du jeu, qui, comme je le disais, sont exécutées via une FSM, une à
la fois (pas assez de temps pour faire plus). Et dont certaines sont trop
longue pour tenir dans le reste de la frame, d'où la nécessité d'en faire
des coroutines pour morceler leur exécution (comme tu le disais, pour
afficher un caractère à la fois par frame ; ça tombe bien, je voulais de
toute façon faire un effet lent, avec éventuellement petit bruitage
associé ;o) ).

Je n'aurai donc qu'une seule coroutine appelée depuis la boucle de la
frame, et qui ne s'interrompra que pour revenir dans cette boucle. On ne
passera pas de coroutine en coroutine, la FSM switchera la coroutine
uniquement quand la précédente aura fini. Ça simplifie un peu les choses,
puisqu'il ne faut gérer qu'un seul contexte (celui de la coroutine).

> Pour faire "joli" et éviter du copier/coller, il faudrait que une macro
> "yield" pour ce changement de contexte programmatique et une autre
> macro pour générer la pile des processus et son entrée dans la table...
> mais d'un autre côté tu n'es plus très loin d'écrire le code nécessaire
> à la création un processus à la volée dans un espace mémoire réservé à
> cet effet.


Yep, bonne idée, les macros ! J'en utilise déjà quelques unes avec RASM.

> Ensuite viendra peut-être la nécessité d'un gestionnaire de mémoire
> heap avec malloc. Pour un jeu, probablement pas besoin de free ou de
> suppression de processus. Mais si tu veux te simplifier la vie, même si
> c'est beaucoup moins fun, il suffirait juste de coder au-dessus de
> CP/M, je pense que pour le paiement de license, il y a prescription.


Du fait des ces timings serrés, par possible d'utiliser CP/M... Pour tout
te dire, comme j'étends l'écran verticalement, pour avoir la place de
mettre les icônes sous l'image, ça bouffe plus de RAM, et, pire, ça
écrase la zone mémoire utilisée par le système ! Du coup, il faut tout
ré-écrire from scratch : affichage graphique, texte, gestion clavier,
gestion de fichiers, musique, etc ;o)

> C'était l'épique époque des peeks et des pokes !


Bien tourné :o)

C'est pour ça que je me replonge dedans : c'est vraiment satisfaisant de
toute maîtriser de A à Z ! Et, surtout, de sortir les trippes du hardware
pour faire plus que ce qui était prévu à l'origine.

En tout cas, merci pour ton retour et les conseils :o)

--------------------------------

PS : pour info, voici l'écran de présentation du jeu original, recodé avec
RASM (mais en gardant le code d'origine) :

https://rasmlive.amstrad.info/edit/HbEN8Z3sTin32RjMA

Le jitter (parfois) visible en bas à droite ne l'est pas sur un vrai CPC.
C'était dû à une mauvaise synchro sur la VBL (les divers émulos ne sont
pas tous calés de la même façon) ; aujourd'hui, toujours grâce aux
démo-makers, plus de jitter ;o)
Si ça vous intéresse, je posterai une version plus actualisée, avec écran
rasterisé, musique, et gestion clavier. Puis affichage texte dès que
j'aurai implémenté la coroutine.

-- 
    Frédéric