feck -- framework fe pour 90+E et Linux
Posté le 18/11/2021 00:27
Warning topic-de-minuit ! je me relirai demain (:
Salut ! Ça fait un bail que je n'ai pas commencé un projet stupide, mais je suis bien dans le mood. Et cette fois-ci, je pourrais arriver à quelque chose sur un malentendu. Je vais commencer par vous présenter le langage, puis l'idée qui me trotte dans le cranounet avant de terminer sur l'organisation que j'ai en tête pour les masos. Lezgo!
TL;DR : je veux créer un framework minimaliste qui fonctionnerait de la même manière sur calto et Linux.
Barre de progression pour faire joli
fe est un langage Lispique créé par
rxi (un dieu ce type), conçu pour le minimalisme et l'inclusion dans des projets C. Vous pouvez trouver toutes les informations sur le langage et l'API C sur
le github du projet, c'est très rapide à lire et facile à intégrer.
Mon objectif est de créer un framework qui partagera son API sous Linux et Casio 90+E -- fxCG50 pour nos membres étrangers, permettant de créer de petits jeux et prototypes sur Linux avant de les tester et exporter sur calto -- ou l'inverse, soyons fous. Pour les connaisseurs, ce serait un LOVE2D de clodo. La librairie fe est si bien conçue que j'ai pu l'intégrer avec raylib (de manière crade) très rapidement pour un prototype. Et n'oubliez pas que je suis un imbécile heureux !
Vous vous dites alors -- ou pas, réagissez dans les com's -- que je n'y arriverai jamais. Seul c'est certain, c'est pour ça que j'abuserai de votre aide dès que l'occasion se présentera ! Je sais, je suis génial. Premier exemple, fe (le langage) ne compile pas encore avec le fxsdk, à cause de fonctions IO manquantes (ou non trouvées). Je vous demanderai demain de me backseat avec affection et blackmail
Je prendrai tous les mérites une fois que ce sera terminé, comme tout cadre qui se respecte /s
Pour l'organisation, je prévois de garder la majorité du code spécifique aux plateformes dans mon projet
raygint, et le code commun dans
feck pour que le cross platform bricolé soit utilisable par d'autres add-ins. C'est pour le geste, raygint est claqué au sol.
Les fonctions présentement implémentées sont :
(dblock [...])
(dcolor r g b)
(dclear)
(drect x y w h)
Au moment où j'écris ce post, absolument rien ne fonctionne sur calto.
Merci pour les applaudissements !
Rah je sais pas si c'était une bonne idée. Feck it. Kamehamehamehamehamehame-
https://gitea.planet-casio.com/KikooDX/feck
PS : l'objectif est d'obtenir des résultats rapidement, j'aimerais dans l'idéal que le MVP soit prêt d'ici la fin de semaine. Je peux rêver, ça me fait vivre.
Citer : Posté le 18/11/2021 06:43 | #
Ha ha tu t'amuses c'est pas mal. Faudra penser à mettre à jour le topic des langages de Cake.
J'aime bien l'approche simultanée calto/PC. Ce que je fais de mon côté est plus... bourrin (moteur TLT vs. OpenGL, et c'est expérimental), donc je pense que ça peut pas faire de mal.
Dans ce genre de situation, n'hésite jamais à me harceler pour intégrer ce qu'il faut à la fxlibc. La lib standard doit être supportée, et la flemme n'est pas une excuse de mon côté.
J'aime bien tes topics comme d'habitude, c'est assez marrant. xD
Citer : Posté le 18/11/2021 11:17 | #
Merci Lephé !
Dans ce genre de situation, n'hésite jamais à me harceler pour intégrer ce qu'il faut à la fxlibc. La lib standard doit être supportée, et la flemme n'est pas une excuse de mon côté.
Et je commence maintenant (: Voici les erreurs. J'ai supprimé quelques warnings d'arguments non utilisés dans le main pour que ce soit plus lisible, ils n'ont aucun rapport.
rm -Rf out/
rm -Rf build/
rm -Rf build-cg/
rm -f *.g3a
clang-format -style=file -i src/**.c inc/**.h || true
No such file or directory
fxsdk build-cg
-- The C compiler identification is GNU 11.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/kdx/.local/bin/sh-elf-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found Gint: TRUE (found suitable version "2.6.0", minimum required is "2.6.0")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kdx/projects/feck/build-cg
[ 20%] Building C object CMakeFiles/target.dir/src/main.c.obj
[ 40%] Building C object CMakeFiles/target.dir/raygint/src/display.c.obj
[ 60%] Building C object CMakeFiles/target.dir/raygint/src/keyboard.c.obj
[ 80%] Building C object CMakeFiles/target.dir/fe/src/fe.c.obj
/home/kdx/projects/feck/fe/src/fe.c: Dans la fonction « writefp »:
/home/kdx/projects/feck/fe/src/fe.c:401:3: attention: déclaration implicite de la fonction « fputc » [-Wimplicit-function-declaration]
401 | fputc(chr, udata);
| ^~~~~
/home/kdx/projects/feck/fe/src/fe.c: Dans la fonction « readfp »:
/home/kdx/projects/feck/fe/src/fe.c:550:17: attention: déclaration implicite de la fonction « fgetc » [-Wimplicit-function-declaration]
550 | return (chr = fgetc(udata)) == EOF ? '\0' : chr;
| ^~~~~
[100%] Linking C executable target
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : CMakeFiles/target.dir/fe/src/fe.c.obj : dans la fonction « _writefp » :
fe.c:(.text+0x8) : référence indéfinie vers « _fputc »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : CMakeFiles/target.dir/fe/src/fe.c.obj : dans la fonction « _readfp » :
fe.c:(.text+0x24) : référence indéfinie vers « _fgetc »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : CMakeFiles/target.dir/fe/src/fe.c.obj : dans la fonction « _fe_write.constprop.0 » :
fe.c:(.text+0xc8) : référence indéfinie vers « _fputc »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : fe.c:(.text+0x234) : référence indéfinie vers « _fputc »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : CMakeFiles/target.dir/fe/src/fe.c.obj : dans la fonction « _fe_error » :
fe.c:(.text+0x610) : référence indéfinie vers « _stderr »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : CMakeFiles/target.dir/fe/src/fe.c.obj : dans la fonction « _eval.part.0 » :
fe.c:(.text+0x1c40) : référence indéfinie vers « _stdout »
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libc.a(printf.c.obj) : dans la fonction « _printf » :
printf.c:(.text+0x44) : référence indéfinie vers « _stdout »
collect2: erreur: ld a retourné le statut de sortie 1
make[3]: *** [CMakeFiles/target.dir/build.make:148 : target] Erreur 1
make[2]: *** [CMakeFiles/Makefile2:83 : CMakeFiles/target.dir/all] Erreur 2
make[1]: *** [Makefile:91 : all] Erreur 2
make: *** [Makefile:2 : all] Erreur 2
Le code source dont il est question : https://github.com/rxi/fe/blob/master/src/fe.c
Merci d'avance. Les erreurs de printf je peux les corriger avec une macro de bourrin, mais le reste j'en suis moins certain.
Citer : Posté le 18/11/2021 11:38 | #
Alors y'a deux parties là-dedans quand même : d'un côté il y a la gestion des fichiers (et ça je crois qu'on peut la coder vu que la Graph 35+E II et Graph 90+E se comportent bien), et y'a la gestion du "terminal" (stdin, stdout, stderr).
Je pense faire comme ça : par défaut la fxlibc jettera les contenus de ces flux, et proposera des callbacks pour brancher des fonctions maisons à la place (pour faire un terminal maison avec un écran graphique etc. ce qui est pas le job de la libc). Éventuellement on peut l'accompagner avec une lib gint qui fournit une implémentation raisonnable.
Citer : Posté le 18/11/2021 12:30 | #
Alright merci Lephé pour l'explication ! ça sonne comme quelque chose qui prend pas mal de temps et il y a d'autres problèmes que je peux régler de mon coté, alors pour le contourner l'IO temporairement j'ai fork fe et désactivé les fonctions problématiques, en plus d'embarquer le fichier directement dans l'exécutable avec cembed (un projet de rxi, il est partout). Le comportement du langage est absolument identique sans ces appels, j'y ai fait attention. Ceci n'est qu'un workaround en attendant que la fxlibc supporte l'IO !
Bonne nouvelle, l'add-in compile désormais avec une grâce inégalée ! et un TLB miss au lancement Je pense savoir d'où ça peut venir, rxi a conçu fe pour les systèmes little endian, et je crois me souvenir que la 90+E est big endian. Si quelqu'un peut confirmer, ça m'éviterait de chercher l'erreur au mauvais endroit. Merci d'avance !
Citer : Posté le 18/11/2021 12:58 | #
Ok ! Pour cembed c'est presque une trivialité, tu peux faire pareil avec objcopy :
# Le fichier contient les symbols _binary_FILE_{start,end,size}
Oui la calto est big endian, à voir comment tu peux modifier les sources pour prendre ça en compte.
Pour la fxlibc j'arrive, je fais un début de jet ce soir
Citer : Posté le 18/11/2021 22:48 | #
Je vais garder cembed pour le moment, merci pour l'info.
J'ai essayé de modifier les sources, mais j'ai beaucoup de mal à comprendre comment et où le type d'endian affecte le code malgrès deux bonnes heures de tentatives.
rxi indique "The storage of an object's type and GC mark assumes a little-endian system and will not work correctly on systems of other endianness".
Le type d'object et le marqueur pour le garbage collector sont déclarés de cette manière :
/* `fe_CFunc` est un pointeur de fonction et `fe_Number` un `float` */
typedef union { fe_Object *o; fe_CFunc f; fe_Number n; char c; } Value;
struct fe_Object { Value car, cdr; };
/* GC mark */
#define GCMARKBIT ( 0x2 )
#define car(x) ( (x)->car.o )
#define tag(x) ( (x)->car.c )
#define type(x) ( tag(x) & 0x1 ? tag(x) >> 2 : FE_TPAIR )
/* en action */
void fe_mark(fe_Context *ctx, fe_Object *obj) {
fe_Object *car;
begin:
if (tag(obj) & GCMARKBIT) { return; }
car = car(obj); /* store car before modifying it with GCMARKBIT */
tag(obj) |= GCMARKBIT;
/* ... */
}
Mon idée était de changer le type du char c dans fe_Object pour aligner les bits correctement, mais je n'ai pas trouvé comment
Si quelqu'un peut aider ou donner des pistes pour je serais très reconnaissant, mon cerveau saigne de la tambouille.
Les sources entières si quelqu'un veut voir dans le contexte.
Merci d'avance (et encore).
Citer : Posté le 18/11/2021 23:14 | #
Donc là l'histoire de l'endianness c'est qu'il suppose que char c va se trouver sur l'octet de poids faible des trois autres éléments (alors que sur un système big-endian le premier octet c'est celui de poids fort).
Tu peux voir que deux bits de cet octet servent de tag() et que type() s'appuie dessus pour déterminer le type, avec le bit 0x01 qui indique les TPAIR et le bit 0x02 qui contient la marque du GC. Ces deux bits ne gênent pas le fe_Object *o parce qu'un pointeur de ce type est toujours sur une adresse multiple de 4. Sauf que là tu touches pas aux bits de poids faible mais aux bits 24 et 25 qui eux sont bien importants.
Tu peux modifier la structure pour que c devienne le dernier octet :
fe_Object *o;
fe_CFunc f;
fe_Number n;
struct { char _[3]; char c };
} Value;
(Compiler avec -std=c11 pour avoir la sous-structure anonyme)
Par contre ça cassera la supposition derrière strbuf(), qui suppose que c est le premier octet et utilise les trois autres :
Tu peux à la place utiliser les trois premiers :
À vue de nez ça devrait suffire.
Le proto pour fxlibc est encore dans ma tête sorry, mais ça arrive (j'ai toujours pas envoyé les lots du concours de rentrée je suis obligé de prioriser x_x).
Citer : Posté le 19/11/2021 12:19 | #
Merci encore Lephé !
Je pense que ta solution fonctionne, mais l'add-in crash dès fe_Context *ctx = fe_open(data, size);.
void *data = malloc(size);
fe_Context *ctx = fe_open(data, size);
Je suis perplexus, en lisant la fonction je ne vois pas d'où ça pourrait venir. J'ai essayé avec une allocation mémoire sur le stack et ça ne règle pas l'erreur.
L'erreur en question
040 TLB miss (nonexisting address) on read
PC = 74304506 (Error location)
TEA = 74304506 (Offending location)
TRA = 0x0 (Trap number)
Merci d'avanciacado
Citer : Posté le 19/11/2021 13:05 | #
Il faudrait aligner ton buffer déjà pour être sûr.
static GALIGNED(4) char buf[64000];
// ou alors mettre un type aligné de base
int buf[16000]; // sizeof(buf) = 64000
Sinon je vois pas de bug évident comme ça, à approfondir peut-être.
Citer : Posté le 19/11/2021 13:27 | #
GALIGNED ne règle pas le problème. Je vais faire une pause et essayer de réduire le problème plus tard.
Citer : Posté le 19/11/2021 15:58 | #
Une connerie d'ailleurs, ça devrait être ça :
Ça ne change rien mais c'est important quand même. Tu peux aussi mettre (x)->car._ ou &(x)->car.c - 3 ou d'autres variations à loisir.
En tous cas y'a pas à dire le modèle de stockage mémoire de ce mini-langage est vraiment extraordinaire. J'imaginais pas qu'on pouvait abuser du système de Lisp comme ça (surtout pour les chaînes de caractère), ce qui me fascine à la fois parce qu'il met un GC dessus mais aussi parce que c'est vraiment mauvais en termes de compacité et de performance. x)
Du coup deuxième passe je vois toujours rien de problématique. C'est peut-être pas le changement d'endianness qui pose ce problème.
Citer : Posté le 19/11/2021 16:25 | #
Ça ne change rien
Après ce changement, l'add-in se lance avec succès sur la calculatrice ! avant de quitter immédiatement, mais bon c'est beaucoup mieux qu'un TLB miss. Mercit
Citer : Posté le 19/11/2021 16:30 | #
Aaaah mais oui quel con c'est (char *)(x) qui aurait été équivalent à (char *)&(x)->car. Y'a un & en trop pour ce raccourci. xD
Voilà bon du coup le GC et l'endianness je pense que c'est bon, cool.
Les fichiers j'ai commencé à coder, je posterai sur le topic de la libc et de gint dès qu'il y aura quelque chose.