Tant pis pour Arnold !
Crocodiliens, crocodiliennes, je jette l'éponge ! Je me suis cassé les dents pendant trop de temps sur un sujet technique qui tenait plus de l'impasse que d'autre chose ! Alors je vous rassure tout de suite, je n'abandonne pas le projet Felgon ! A environ 90% du projet terminé, le scénario bouclé, le moteur qui fonctionne et seulement 15 écrans à terminer, ça serait idiot ! Non ce que j'abandonne, c'est encore un des objectifs que je m'étais fixé au début du projet à savoir la compatibilité avec le 464 !
Comme je l'ai indiqué dans mon précédent billet, j'ai remarqué que le jeu ne fonctionnait pas correctement sur CPC 464 old. Non seulement, il était sensiblement plus lent, mais il finissait même par planter au bout d'une grosse douzaine d'écrans chargés ! J'ai donc analysé finement mon code, en me disant que la gestion de la pile d'appel était différente en Basic 1.0, et connue pour être moins souple.
J'ai effectivement trouvé, au fil de mes recherches, plusieurs erreurs dans mon code, ainsi que des optimisations possibles en supprimant des utilisations de boucles while, des appels à gosub remplacés par des goto. Mais rien n'y faisait, le programme plantait toujours. L'utilisation de defint à la place des suffixes "%" n'a rien changé non plus. Et même en ajoutant un système pour tracer l'évolution de la pile des appels aux appels des derniers gosubs du code et leur return correspondant, je n'ai trouvé aucune erreur, aucun débordement. D'ailleurs le message bad command aurait du me mettre la puce à l'oreille puisque le message d'erreur du basic quand la pile d'appel (de 512 octets) du basic déborde est memory full, exactement comme quand on sature la mémoire de données ! C'est bien dommage d'ailleurs qu'ils aient repris le même message je trouve.
Lors du crocofest, j'ai pu constater sur le 464 de TotoCool, que je remercie au passage, que le bug arrivvait bien sur un vrai CPC, et que donc ce n'était pas un problème d'émulation ! Et j'ai donc constaté sur son CPC, comme sur l'émulateur qu'après le "bad command", l'interpréteur rame et un appel à l'instruction CAT, mets un temps extrêmement long à répondre ! Les pros de l'amstrad CPC présents ont eu le même conseil, il faut passer à des fichiers binaires, et si possible les compresser. Mais cela impliquait de réécrire un bon quart de mon moteur, et cela sans véritable garantie de succès au final.
Dans le même temps, BreizTiger m'a donné la référence d'un utilitaire CPC qui s'appelle BStack, paru dans CPC infos et qui permets de relocaliser la pile d'appels du basic et éventuellement l'agrandir. Ca avait l'air intéressant, et mine de rien, cette documentation m'a permis de mieux comprendre comment fonctionne cette pile. Je ne me serais pas douté que les instructions WHILE/WEND empilait 7 octets sur cette pile et qu'une boucle for en empilait 22 ! Mais malheureusement, l'expérience montrait que ce n'était pas un problème de la pile d'appel.
Donc avant de me lancer, dans une refonte complète de la partie chargement du moteur, je me suis dit qu'il fallait que je tente à nouveau d'isoler le comportement défectueux sur 464. Donc après un test où je chargeais en boucle, un fichier de données Ascii et un fichier binaire d'image en boucle, j'ai pu constaté qu'en basic 1.0, l'interpréteur se mettait à ramer après quelques dizaines de passage. Il n'y avait donc aucun problème de mémoire à ce moment là, et pourtant même si je n'avais pas encore l'erreur bad command, j'avais déjà la lenteur constatée auparavant dans le jeu. Je me dis alors qu'il faut supprimer le chargement du fichier ascii, et je fais donc une simple boucle pour charger un fichier binaire en mémoire :
9010 BORDER 0:MEMORY &8B9F 10020 LOAD "14.win",&8BA0 10030 ii=ii+1 10040 goto 10000
Et là, le résultat tombe, en basic 1.0, au bout de quelques dizaines de chargement, l'interpréteur se mets à ramer. Si j'arrête la boucle avec escape et que je fais CAT, l'interpréteur mets un temps fou à répondre ! Donc, même avec des fichiers binaires, l'interpréteur basic 1.0 finira par ramer. Alors peut-être qu'en chargeant des données binaires et des images compressées, le problème arriverait plus tard, mais vu que j'ai 77 images et 66 fichiers de données à charger, il est clair que je ne peux pas garantir que l'on puisse terminer le jeu. La solution pour le faire fonctionner sur un 464, c'est soit de récupérer une ROM de basic 1.1 (d'un 664 je pense, il me semble que celle du 6128 est différente). soit d'utiliser une carte M4 pour surcharger la ROM standard. A noté, que les 464+ n'auront quant à eux aucun soucis.
Une autre solution pour moi, serait de remplacer mon couple moteur / fichier de données par un ensemble de programmes basic indépendants que j'aurai généré à partir de mon éditeur de scénarios. C'est une perspective intéressante, mais là encore, je n'ai aucune garantie que cela va fonctionner au final. Je n'ai pas envisager cette solution au départ du projet, car j'ignorais que l'on pouvait conserver des données en mémoire entre deux run de programmes basic.
Je m'excuse donc auprès des possesseurs de CPC 464 old, que j'abandonne encore une fois sur un de mes projets, mais cette fois j'ai pourtant vraiment fait tout ce que j'ai pu pour que cela fonctionne !
PS : Je me suis trompé, j'avais laissé dans mon code, un chargement unique d'un fichier texte et son stockage dans un tableau. Comme il n'y avait qu'un chargement de ce type pour des dizaines de load, j'ai négligé leur impact et supprimé du résumé...Donc c'est encore à analyser !
PS du PS : Après analyse, je n'ai pas réussi à reproduire sur un petit programme, le bug du "bad command" sur le basic 1.0. J'ai cependant remarqué un détail intéressant. Comme dans le cas de mon moteur de jeu, lorsque je charge des données dans 10 tableaux 14 lignes de données textes pour un volume total de seulement 800 octets et qu'ensuite je charge 150 fois le même fichier binaire d'environ 5000 octets, au sortir du programme, avec le basic 1.0, il me faut 19 secondes pour exécuter la commande CAT. Sur le basic 1.1, il me faut moins de 4 secondes !
J'ai alors tenté un truc, au lieu de charger les 800 octets dans 10 tableaux, j'en ai chargé 400 dans 5 tableaux ! Et là, surprise, la commande cat s'exécute en 12,8 secondes au lieu de 19 sur 464 ! Je me dis alors que le soucis vient de mes 10 inputs #9 faits pour remplir les 10 tableaux. Et j'avais aussi remarqué que lorsque je chargeais toutes les lignes de mon fichier via un seul line input et en les stockant bêtement dans un seul tableau de chaines je n'avais aucun soucis non plus !
Donc plein d'espoir, je tente de lire toutes mes lignes avec un seul line input #9 et ensuite je récupère les données à coups de instr, mid$ et val pour les données entières. Un peu de débugage, sur un programme de test indépendant et ça fonctionne, j'obtiens alors un temps d'exécution de la commande CAT dans les mêmes conditions de 14 secondes avec tous mes tableaux chargés.
Je me dis alors que vu le progrès, ça vaut le coup, d'intégrer cette "optimisation" dans le moteur. Après quelques péripéties dues au cache de l'émulateur, je finis enfin par faire marcher le truc, je le teste d'abord sur 6128, tout fonctionne, je termine le jeu avec. Je refais le test sur 464 et patatra, le même message d'erreur sur le même écran !
Mais bon sang qu'est ce qu'ils ont pu fabriquer sur ce basic 1.0 ?
PS du PS du PS : Cet après-midi, j'ai profité d'une pause, pour poser à Gemini l'ia de google pourquoi mon programme faisait tant ramer la commande cat sur CPC 464. L'ia m'a répondu que le système parcourait la liste de toutes les variables pour trouver où il pouvait trouver une zone de buffer disponible pour faire la liste des fichiers sur la disquette. Comme je lui avais précisé que je chargeais les données dans 10 tableaux, il m'a conseillé de charger les données dans un seul tableau à 10 dimensions.
J'ai fait le test dans mon bout de code pour tester avec un seule line input et on passe de 12 secondes à de nouveau 19 secondes ! Et quand j'ai fait le test avec 10 input différents, on passe de 19 secondes à 26 !! Bref, l'ia avait indiqué ça au conditionnel mais clairement c'était encore une perte de temps !
Commentaires
Enregistrer un commentaire