Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » B2C : Convertisseur Basic en C
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

B2C : Convertisseur Basic en C

Posté le 02/07/2016 11:24

Mon nouveau projet est donc de faire un convertisseur basic -> C

Ce serait possible parce que toutes les fonctions du basic sont transposables en C (même les gotos), par exemple Locate(x, y, str) est remplacé par locate(x,y);Print(str), F-line remplacé par ML_line(), etc.

Par contre là où ça diffère de AldeBasicLib c'est que ce sera un convertisseur total. Par exemple si le programme voit "Mat M" il génèrera une matrice M adéquate. Le but étant de lancer le programme, de sélectionner un .g1r, et d'avoir un fichier .c prêt à compiler.

Cela pourrait être utile pour les gros jeux qui prennent toutes la mémoire principale et qui seraient mieux en C (je pense à CloneLab, Arkenstone, peut être Calcraft...)

Utilisation
Nécessite : Java, le SDK casio (ou un truc permettant de compiler des addins)

Clonez le repo http://git.planet-casio.com/Zezombye/B2C/ et exécutez B2C.java en remplaçant les arguments si besoin.
À noter que B2C n'étant pas fini, il est très probable que le programme que vous essayez de convertir vous fasse plein d'erreurs, que ce soit de B2C ou du SDK.

Programmes basic déjà convertis
NOTE: Ces programmes sont compatibles SH3. Si vous voulez les tester, convertissez les en SH4 si besoin !
Je n'ai absolument rien changé dans ces programmes (à part l'icône et le nom) donc le code est celui qu'on obtient avec B2C.

Démineur de Cakeisalie5 : http://www.mediafire.com/file/z6t5jmfh72wfnag/DEMNR.G1A (original)
Puissance 4 de Zezombye : http://www.mediafire.com/file/i1ucweo66ibjy67/PUISS4.G1A (original)

Fonctions actuellement implémentées :

- Commentaires
- Gotos&Lbls (heureusement que ça marche exactement de la même façon en C qu'en basic)
- If, Then, Else, IfEnd, ⇒
- Do, LpWhile
- While, WhileEnd
- For, To, Step, Next
- Prog, Return, Break, Stop
- Locate
- GetKey
- -> (assignement de variable/matrice/liste/dim)
- Dim, Mat, List
- L'opérateur '~'
- Variables A-Z, r, theta, Ans
- Opérateurs de calcul : + (unaire et binaire), - (unaire et binaire), *, /, ^, sqrt, racine n-ième
- Multiplication implicite (normalement)
- Opérateurs de comparaison : <, >, ≤, ≥, =, ≠
- Opérateurs logiques : And, Not, Or, Xor
- Ran# (fonction de la libc), RanInt# (par l'interpréteur casio actuellement, à changer)
- Int
- Fill(), ClrMat, ClrText
- Str, StrCmp, StrInv, StrJoin, StrLeft, StrRight, StrLen, StrLwr, StrUpr, StrMid, StrRotate, StrSrc, StrShift

Fonctions à implémenter :
- Nombres complexes
- Fonctions graphiques
- Gestion des pictures et captures
- Sauvegarde des variables

Note : les 3 fonctions suivantes ne seront pas implémentées fidèlement, il n'y aura qu'une implémentation rudimentaire.
- Les strings sans assignement (écrire "TEST" puis une nouvelle ligne)
- La fonction disp (◢)
- L'opérateur ?-> pour l'input de l'utilisateur

Fonctions qui ne seront peut être pas implémentées :
- L'écriture d'un nombre via la console (par exemple écrire "2+3" comme seule instruction affiche "5" sur l'interpréteur basic, mais il est difficile de savoir s'il faut l'afficher ou seulement la mettre dans Ans)

Comment B2C optimise le programme (autre qu'en compilant au lieu d'interpréter) par rapport à Casio

- Les opérations sont implémentées (enfin pour l'instant il n'y a que l'addition et la soustraction pour les nombres non complexes) nativement au lieu de passer par l'interpréteur; ainsi, additionner 10000x des nombres prend 1.5s pour l'implémentation de l'addition, et 4.4s si on passe par l'interpréteur.

- Les listes de Casio séparent les parties imaginaires et réelles. Par exemple, pour la liste {3, 1+2i, -4i, 6}, Casio la stockera en {3, 1, 0, 6, ?, 2, -4, ?} avec '?' 12 octets de padding. B2C ne fait pas cette séparation et stocke la partie imaginaire à côté de la partie réelle, ce qui fait qu'une fonction peut appeler directement "list_1" au lieu de passer par une fonction intermédiaire qui recolle les 2 parties.
L'inconvénient est que les listes ne possédant pas de complexes sont 2 fois plus grandes. (en fait, si le programme possède des nombres complexes, la taille du BCDvar est de 24 octets, et sinon 12)

- Pour les matrices : même chose qu'avec les listes.

- Les strings de Casio implémentent des caractères, qui peuvent être sur 1 ou 2 octets. Cette différence fait qu'on ne peut pas avoir un accès en O(1) car on ne peut pas savoir directement la position du i-ème caractère du string en calculant. Si on veut accéder à str_1[255], l'interpréteur casio doit itérer sur tout le string.
B2C permet un accès beaucoup plus rapide en stockant chaque caractère, multi-byte ou non, sur 2 octets. Ainsi, les fonctions des strings qui travaillent sur les caractères casio (toutes sauf StrCmp) sont plus rapides. StrCmp est possiblement plus lent que si B2C implémentait les strings comme le fait casio, mais la différence est négligeable.

Pour résumer : B2C bouffe un peu plus de RAM, mais il est beaucoup plus rapide.



Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 27/07/2016 22:27 | #


Détailles le typedef de List ?
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 27/07/2016 22:29 | #


typedef struct {
    int nbElements;
    BCDvar *data;
} List;


Mais je vois pas le rapport par contre ça s'applique aussi à n'importe quel type (retourner un int vs retourner un *int) non ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 27/07/2016 22:32 | #


Retourner un int et retourner un *int, ce n'est clairement pas la même chose :')
Je voulais voir ton typedef parce qu'on peut typedef un pointeur -- en l'occurrence, ce n'est pas ce que tu as fait.
IMO, il vaut mieux que tu renvoies un pointeur vers la liste (puisque la taille de la structure liste est plus grande que la taille d'un pointeur), mais ce n'est pas une gigantesque perte si tu ne le fais pas.
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Fife86 Hors ligne Membre Points: 839 Défis: 0 Message

Citer : Posté le 27/07/2016 22:49 | #


Mmm, si tu déclare ta liste comme ça

List createNewList(int nbElements, ...) {
    List list;    
    //...
    return list;
}

ou
List *createNewList(int nbElements, ...) {
    List list;
    //...
    return &list;
}


Il y aura un problème avec List list car list sera détruit et la mémoire déalloué à la fin de la fonction.

Il vaut mieux faire


List *createNewList(int nbElements, ...) {
    List * list = new list(nbElements,....);
    //...
    return list;


Et penser à déallouer plus tard.
It's Show Time !!!
Mes Jeux :
- Street Fighter : Pour les accrocs du free-fight.
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".


< Le recoin du C-Engine >
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 28/07/2016 20:08 | #


J'ai (encore) un problème avec la fonction de conversion BCD -> int :/

int B2C_convToUInt(BCDvar nb) {
    int result = 0;
    int power = (nb.bytes[1]>>4) + 1; //prend l'exposant
    for (i = 1; i <= power; i++) { //lit les chiffres de gauche à droite en appliquant la puissance de 10 adéquate
        if (i%2) {
            result += (nb.bytes[i/2+1]&0xF) * pow(10, power-i); //lit le chiffre à gauche de l'octet
        } else {
            result += (nb.bytes[i/2+1]>>4) * pow(10, power-i); //lit le chiffre à droite de l'octet
        }
    }
    return result;
}


Ca me retourne des erreurs mémoire à tout va, or je ne comprends pas o_o ça pourrait peut être me retourner un nombre bizarre, mais je vois pas pourquoi ça provoque des erreurs mémoires. (sachant que BCDvar est une struct avec un char[24] et que power vaut bien 0)
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 28/07/2016 20:18 | #


En C, appliquer du bit shifting sur des types signés n'est pas forcément une bonne idée : essaies de mettre "unsigned char" au lieu de "char" dans la déclaration de ta structure.

Remarque annexe : pourquoi une fonction "to uint" renvoie un int et non un unsigned int ?
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 28/07/2016 21:12 | #


Bon, après une heure de recherche, il apparaîtrait que je n'ai pas inclus <math.h> et que le SDK s'en fout totalement et compile quand même. u_u

Ajouté le 29/07/2016 à 20:39 :
Apparemment, le SDK ne reconnaît pas exit(), ce qui est bizarre parce que d'après ce que j'ai vu c'est dans le C89. (j'ai bien inclus <stdlib.h>, et je ne vois pas non plus exit() dans la liste des fonctions)

Est ce qu'il y a une alternative pour quitter le programme et revenir au menu ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 29/07/2016 20:43 | #


Tu injectes une key puis tu lis avec GetKey en activant le retour au menu ?
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 29/07/2016 22:42 | #


Y'a un syscall pour injecter une key, je testerai (c'est quand même bizarre qu'il y ait pas de fonction exit o_o)

Ajouté le 30/07/2016 à 10:26 :
Bon, après beaucoup de débuggage, j'ai réussi à faire fonctionner mon puissance 4

(d'ailleurs, j'ai tellement mal optimisé que l'IA tourne à peu près à la même vitesse qu'en basic, c'est un bug ou une feature ?)

Encore une fois merci beaucoup à lephé et à SimLo, ça n'aurait pas été possible sans vous
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 30/07/2016 12:13 | #


Je peux pas deviner out of nowhere si c'est un bug ou une feature, va falloir que tu nous montres le code généré là. x)

Qui plus est, il est possible de reproduire le exit, mais c'est pas évident. (j'ai un code de lephé où il l'a refait en fait, je sais pas si c'est public)
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 30/07/2016 12:52 | #


Ouais pour l'exit j'ai pas réussi à le reproduire avec la méthode de simlo, du coup j'ai fait une popup similaire au basic. D'ailleurs est ce que c'est possible de pouvoir quitter à n'importe quel moment en appuyant sur ac/on ?

Pour le lag je me demandais juste si je le gardais pour être fidèle au basic ou si je l'optimisais (même si je vois pas trop comment on peut l'optimiser plus) d'ailleurs je pense pas que tu comprendrais grand chose au code, par exemple
Do
Getkey
LpWhile Ans≠31 And Ans≠71

se transforme en
do {
Ans = B2C_Getkey();
} while (B2C_and(B2C_notEqualTo(Ans, B2C_convToBCD("31")), B2C_notEqualTo(Ans, B2C_convToBCD("71"))).bytes[0]);

Ce qui est assez difficile à lire, surtout que j'ai pas encore implémenté l'indentation.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 30/07/2016 13:00 | #


Beh question simple du coup : pourquoi avoir fait un convertisseur Basic -> C si c'est pour garder la lenteur du Basic ?
Et si ça va, ton code est assez clair quand même x) (j'ai déjà fait du lisp hein )
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 31/07/2016 08:39 | #


Faudrait tester si c'est pas un problème de compilateur d'ailleurs. Sur l'émulateur du SDK ça prend 0.69 secondes pour un tour d'IA, faudrait compiler ça avec GCC et regarder s'il y a une grande différence de vitesse. (j'arrive pas à compiler avec mingw perso, il fait des trucs bizarres)

Après quelques optimisations je suis passé à 0.48 secondes, je vois pas du tout comment optimiser mieux :/

D'ailleurs, est ce que c'est mieux d'utiliser le AND logique ou bitwise ? (même question pour le OR)
BCDvar B2C_and(BCDvar a, BCDvar b) {
        if (a.bytes[1] && b.bytes[1])
            return ONE;
        return ZERO;
}

Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 31/07/2016 09:42 | #


Le AND logique et le AND bitwise ne produisent pas du tout le même effet.
On pourrait se dire simplement que "ouais le AND logique ça produit 0 ou 1 et le AND bitwise ça produit pas que 1", sauf qu'il y a un cas particulier (parmi d'autres) à considérer: 0b10000000 et 0b01000000. Les deux sont non nuls, pourtant, le AND logique produira 1 où le AND bitwise produira 0.
Et il existe le même genre de cas pour OR. Le seul cas où on peut utiliser les deux AND et les deux OR de la même façon exactement, c'est quand tu es sûr de ne tomber que sur des zéros (0b00000000) et des uns (0b00000001).
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 31/07/2016 12:44 | #


Hmm, j'y avais pas pensé à ça. Et le xor bitwise, il marche aussi ou je suis obligé d'utiliser celui de casio ?
(et c'est quoi les pièges pour le or, je vois pas :o)
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Cakeisalie5 Hors ligne Ancien administrateur Points: 1962 Défis: 11 Message

Citer : Posté le 31/07/2016 12:47 | #


Joues avec des cas particuliers
0b10 XOR 0b01 = 0b11

Donc il fonctionne, mais pas de la façon dont tu veux, à mon avis.
Pourquoi ne pas faire tout simplement "(A and not B) or (B and not A)" ?
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 31/07/2016 12:54 | #


Faudrait voir si c'est plus rapide que faire calculer ça au syscall, ou alors tester d'autres combinaisons genre "(A or B) and not (A and B)" sachant que le not est une fonction externe (je peux pas utiliser '!') et donc plus lente. Y'a pas une manière simple de faire des benchmarks autre que prendre en vidéo l'émulateur ? :/

Ajouté le 31/07/2016 à 13:20 :
J'ai des trucs très bizarres là. o_o

Les fonctions de comparaison sont de la forme :
BCDvar B2C_lessOrEqualThan(BCDvar a, BCDvar b) {
    BCDvar result;
    char *function = "A""\x10""B";
    setAlphaVar('A', &a);
    setAlphaVar('B', &b);
    calcExp(&function, dummyOpCode, &result, 1);
    return result;
}

Du coup je me suis dit que ce serait plus rapide si je déclarais le string en globale et que j'y faisais référence, mais quand je le fais ça bug à fond :
const char *function_lessOrEqualThan = "A""\x10""B";
//...
BCDvar B2C_lessOrEqualThan(BCDvar a, BCDvar b) {
    BCDvar result;
    setAlphaVar('A', &a);
    setAlphaVar('B', &b);
    calcExp(&function_lessOrEqualThan, dummyOpCode, &result, 1);
    return result;
}


Une idée de pourquoi ? Sachant que la présence ou non du const ne change rien, ça bug quand c'est en globale et ça marche quand c'est déclaré dans la fonction.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Dark storm En ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 01/08/2016 06:08 | #


Vu que j'ai pas suivi toute l'histoire, je comprend pas si ce que t'as là est du code généré ou non, et si c'est le cas pourquoi passer par setAlphaVar.

Enfin, pour ce qui est de quitter à tout moment en appuyant sur Ac/on c'est tout à fait possible : au lancement de l'addin, tu lances un timer dans lequel avec un isKeyDown tu regarde si Ac/on est enfoncé. Suivant ce que tu veux faire, tu joues sur les injections getkey ou les temporisations pour afficher un message ou quitter le jeu. Attention dans ce cas à bien désactiver le timer le temps de faire tout ça, quitte à le réactiver si l'utilisateur décidé de revenir dans le jeu.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 01/08/2016 06:51 | #


Dark storm a écrit :
Vu que j'ai pas suivi toute l'histoire, je comprend pas si ce que t'as là est du code généré ou non, et si c'est le cas pourquoi passer par setAlphaVar.


C'est du code généré, en fait pour les fonctions de comparaison je fais faire le boulot à la calto, je mets les valeurs des variables dans A et B et je calcule "A<=B" (dans cet exemple).

Dark storm a écrit :
Enfin, pour ce qui est de quitter à tout moment en appuyant sur Ac/on c'est tout à fait possible : au lancement de l'addin, tu lances un timer dans lequel avec un isKeyDown tu regarde si Ac/on est enfoncé. Suivant ce que tu veux faire, tu joues sur les injections getkey ou les temporisations pour afficher un message ou quitter le jeu. Attention dans ce cas à bien désactiver le timer le temps de faire tout ça, quitte à le réactiver si l'utilisateur décidé de revenir dans le jeu.


Je pensais que le timer ne s'activait que quand elapse était fini par contre pour les injections getkey j'ai un problème : j'arrive à injecter la touche menu (donc ça revient au menu) mais elle reste injectée (donc ça oscille entre le menu et l'addin jusqu'à ce que j'appuie sur une autre touche). Mais je vais faire ça, merci
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Dark storm En ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 01/08/2016 22:41 | #


Heu, pour le coup de l'injection pour quitter, c'est bidon. Si elle reste injectée, c'est que tu l'as trop injectée, ou que tu l'injecte en continu.
void callback_exit(void)
{
    unsigned int key;

    if (isKeyUp(key_acon)) return; // si on appuie pas sur Ac/on, on quitte le callback

    KillTimer(1); // sinon, on commence par tuer le timer

    PopUpWin(3); // on ouvre éventuellement une popup
    locate(1, 1); Print("Quitter : <KEY>"); // on affiche un petit mot

    GetKey(&key); // on récupère l'entrée utilisateur

    if (key == <KEY>)
    {
        key_inject(key_menu); // utiliser le syscall correspondant
        GetKey(&key); // on revient au menu
    }

    SetTimer(1, 50, callback_exit); // sinon, on retourne au jeu en remettant le timer d'aplomb
}

Et dans le main :
int main(int args, void **argv)
{
    SetTimer(1, 50, callback_exit); // on lance le timer

    … // faire ce que t'as à faire
}




C'est du code généré, en fait pour les fonctions de comparaison je fais faire le boulot à la calto, je mets les valeurs des variables dans A et B et je calcule "A≤B" (dans cet exemple).

J'en vois pas l'intérêt pour le coup, un double suffit amplement… Et puis c'est plus facile à manipuler, sûrement beaucoup, beaucoup, beaucoup plus rapide.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 01/08/2016 22:50 | #


Le timer n'a pas l'air de marcher :/

int AddIn_main(int isAppli, unsigned short OptionNum) {
    installTimer(INTERRUPTION_TIMER, (void*)&exitTimerHandler, INT_MAX);
    startTimer(INTERRUPTION_TIMER);
    //...
}
void exitTimerHandler() {
    if (IsKeyDown(KEY_CTRL_EXIT)) {
        uninstallTimer(INTERRUPTION_TIMER);
        B2C_exit(NO_ERROR);
    }
}

Ca ne fait tout simplement rien quand j'appuie sur exit.

Ajouté le 01/08/2016 à 22:56 :
Dark storm a écrit :

C'est du code généré, en fait pour les fonctions de comparaison je fais faire le boulot à la calto, je mets les valeurs des variables dans A et B et je calcule "A≤B" (dans cet exemple).

J'en vois pas l'intérêt pour le coup, un double suffit amplement… Et puis c'est plus facile à manipuler, sûrement beaucoup, beaucoup, beaucoup plus rapide.

En fait non parce que je dois faire des calculs exacts, par exemple "A = 0.1; if (A+0.2 == 0.3)". Ce serait impossible avec des doubles, du coup je fais avec les variables BCD.

Pour l'injection c'est plus ou moins ce que je fais :

void B2C_exit() {
    installTimer(6, (void*)&timerHandler, 1);
    startTimer(6);
    GetKey(&key);
    uninstallTimer(6);
}
void timerHandler() {
    short menuCode = 0x0308;
    putMatrixCode(&menuCode);
}

En fait faudrait que je trouve un moyen d'injecter une autre touche, mais je pense que c'est impossible parce que le programme s'arrête dès que j'appuie sur menu.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 99 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd