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 - Autres questions


Index du Forum » Autres questions » Comment ce calcul peut être plus rapide ?!!
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Comment ce calcul peut être plus rapide ?!!

Posté le 25/09/2016 19:17

Bonsoir,
Pour mon moteur 3D je suis en train d'optimiser un peu partout, et là j'ai une question concernant une optimisation cachée faite par le compilateur.
A la base j'ai ce calcul
int tx = wx * h / point1.z / (wx / point1.z + (1-wx) / point0.z);
Avec h int et wx, point1.z, point0.z float
Je mets ça sur papier, je me dis ce truc est quand même bien dégeu il y a moyen de simplifier et je trouve
int tx = h / ( 1.0 + c1/wx - c1);

avec c1 précalculé : float c1 = point1.z / point0.z;
Et à ma grande surprise. C'est très légèrement moins rapide... Là je saisis pas
Comment est-ce possible ?


1, 2 Suivante
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 25/09/2016 19:30 | #


Et même "On calc" le calcul pourri est plus rapide de 1% C'est faible, mais ça reste quand même plus rapide...
Cakeisalie5 En ligne Ancien administrateur Points: 1959 Défis: 11 Message

Citer : Posté le 25/09/2016 19:31 | #


De toute façon, les flottants sur des systèmes embedded, ça a toujours été le yolo absolu.
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Dark storm En ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 26/09/2016 12:47 | #


Tu compiles avec quoi ? Parce que GCC est très très fort au niveau de l'optimisation du code (bien plus que toi )
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 26/09/2016 18:15 | #


Avec le sdk
Lephenixnoir En ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 26/09/2016 21:29 | #


Vérifie que c'est pas un problème de conversions. Si tu peux m'isoler le code assembleur de ces deux calculs, je devrais pouvoir en dire quelque chose
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 26/09/2016 22:27 | #


Tu parles de conversion float to int et inversement ?
Je vais regarder si je peux isoler l'assembleur
Lephenixnoir En ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 27/09/2016 15:37 | #


C'est ça. En principe la division est extrêmement lente (70 cycles pour la division entière, sans doute bien plus pour la flottante étant donné qu'il n'y a pas de FPU -- faudra que je mesure ça avec gint), fuyez-la autant que possible (en comparaison la multiplication c'est 3 à 5 cycles en entier donc voilà quoi).

Pendant que j'y pense, il y a une non-explication plus fondamentale ; la première formule équivaut (optimisation triviale) à
int tx = wx * h / (point1.z * (wx / point1.z + (1-wx) / point0.z));

Il n'y a pas plus de divisions à calculer (toujours 3) donc la nouvelle formule peut ne rien apporter (il faut stocker une variable, etc).
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 27/09/2016 17:45 | #


En effet ça serait bien que tu mesures le nombre de cylce proco pour chaque opération, y compris les conversions et tout, ça permetrait de mieux se rendre compte.
Pour l'assembleur ça donne ça
Render3DOp   218        int ty = current_wall->texture_height / (c2 + c1/wy);
000008F0 D313                   MOV.L       L588+2,R3  ; __itos
000008F2 6403                   MOV         R0,R4
000008F4 E019                   MOV         #25,R0
000008F6 430B                   JSR         @R3
000008F8 00EC                   MOV.B       @(R0,R14),R0
000008FA 2F06                   MOV.L       R0,@-R15
000008FC 51FB                   MOV.L       @(44,R15),R1
000008FE D211                   MOV.L       L588+6,R2  ; __divs
00000900 420B                   JSR         @R2
00000902 6043                   MOV         R4,R0
00000904 D310                   MOV.L       L588+10,R3 ; __adds
00000906 61F3                   MOV         R15,R1
00000908 7148                   ADD         #72,R1
0000090A 430B                   JSR         @R3
0000090C 6112                   MOV.L       @R1,R1
0000090E D30D                   MOV.L       L588+6,R3  ; __divs
00000910 430B                   JSR         @R3
00000912 61F6                   MOV.L       @R15+,R1
00000914 D20D                   MOV.L       L588+14,R2 ; __stoi
00000916 420B                   JSR         @R2
00000918 0009                   NOP
0000091A 6403                   MOV         R0,R4

//////////////

Render3DOp   220        int ty = wy * current_wall->texture_height / point1.z / (wy / point1.z + (1-wy) / point0.z);
000008B8 D31C                   MOV.L       L589+4,R3  ; __itos
000008BA E019                   MOV         #25,R0
000008BC 430B                   JSR         @R3
000008BE 00EC                   MOV.B       @(R0,R14),R0
000008C0 D21C                   MOV.L       L589+12,R2 ; __muls
000008C2 420B                   JSR         @R2
000008C4 6143                   MOV         R4,R1
000008C6 63F3                   MOV         R15,R3
000008C8 D219                   MOV.L       L589+8,R2  ; __divs
000008CA 6103                   MOV         R0,R1
000008CC 7378                   ADD         #120,R3
000008CE 6532                   MOV.L       @R3,R5
000008D0 420B                   JSR         @R2
000008D2 6053                   MOV         R5,R0
000008D4 2F06                   MOV.L       R0,@-R15
000008D6 6143                   MOV         R4,R1
000008D8 D315                   MOV.L       L589+8,R3  ; __divs
000008DA 430B                   JSR         @R3
000008DC 6053                   MOV         R5,R0
000008DE 2F06                   MOV.L       R0,@-R15
000008E0 D115                   MOV.L       L589+16,R1 ; H'3F800000
000008E2 D216                   MOV.L       L589+20,R2 ; __subs
000008E4 420B                   JSR         @R2
000008E6 6043                   MOV         R4,R0
000008E8 D311                   MOV.L       L589+8,R3  ; __divs
000008EA 6103                   MOV         R0,R1
000008EC 901C                   MOV.W       L589,R0    ; H'008C
000008EE 430B                   JSR         @R3
000008F0 00FE                   MOV.L       @(R0,R15),R0
000008F2 D313                   MOV.L       L589+24,R3 ; __adds
000008F4 430B                   JSR         @R3
000008F6 61F6                   MOV.L       @R15+,R1
000008F8 D20D                   MOV.L       L589+8,R2  ; __divs
000008FA 420B                   JSR         @R2
000008FC 61F6                   MOV.L       @R15+,R1
000008FE D311                   MOV.L       L589+28,R3 ; __stoi
00000900 430B                   JSR         @R3
00000902 0009                   NOP
Je viens de retester ce calcul et maintenant c'est peu moins rapide (7%)... J'y comprends plus rien...

Ajouté le 27/09/2016 à 17:52 :
D'ailleurs, comment est ce que je pourrais optimiser cette ligne de commande ?
Elle permet de savoir un pixel d'un sprite est noir (color!=0) ou blanc (color=0)
unsigned char mask = 128 >> (ty % 8 );
unsigned char y_8 = ty >> 3;
for(...)
{
    char color = (current_wall->texture[y_8 + ((wx >> 10)<<2)] & mask);
Avec wx qui évolue entre 0 et 1, je l'ai multiplié par 1024 (=2^10) pour travailler avec les entiers
Render3DOp   234                                                            char color = (current_wall->texture[y_8 + ((wx >>
                         +10)<<2)] & mask);
    000009A4 54F4                   MOV.L       @(16,R15),R4
    000009A6 E3F6                   MOV         #-10,R3
    000009A8 443C                   SHAD        R3,R4
    000009AA 4408                   SHLL2       R4
    000009AC E030                   MOV         #48,R0
    000009AE 03FC                   MOV.B       @(R0,R15),R3
    000009B0 50E5                   MOV.L       @(20,R14),R0
    000009B2 633C                   EXTU.B      R3,R3
    000009B4 343C                   ADD         R3,R4
    000009B6 044C                   MOV.B       @(R0,R4),R4
    000009B8 E02C                   MOV         #44,R0
    000009BA 03FC                   MOV.B       @(R0,R15),R3
    000009BC 2439                   AND         R3,R4
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 27/09/2016 17:53 | #


Après peut être que les variations ne sont que des erreurs de mesures, tu as mesuré plusieurs fois de suite ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 27/09/2016 17:58 | #


J'execute mon code 300 fois et je moyenne. Je lance même le code 100 fois avant juste "pour éviter un hypothétique regime transitoire" mdr
Mais je remarque que j'ai deux type de mesures. les "lentes" et les "normales" (ou normales et rapide, j'en sais rien)
C'est à dire que une fois sur X j'obtiens une moyenne plus basse, et des fois une plus haute pour le même code.

if (1)
    {
        for (int i=0; i<100; i++)
        {
            render_draw(camera_x, camera_y, camera_z);
        }
        int t1 = time_get_ticks();
        for (int i=0; i<300; i++)
        {
            render_draw(camera_x, camera_y, camera_z);
        }
        int t2 = time_get_ticks();
        float dt = (t2-t1) / 128.0 / 300.0;
        debug_pop(1/dt); // affiche le nombre de hertz
    }
Cakeisalie5 En ligne Ancien administrateur Points: 1959 Défis: 11 Message

Citer : Posté le 27/09/2016 18:00 | #


Tu recompiles pour chaque test ? (on ne sait jamais, avec les IDE...)
EDIT: ah je suis aveugle lol
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/09/2016 18:03 | #


Dans ce cas je dirais que c'est des erreurs de mesures si parfois c'est plus rapide et parfois plus lent, ça peut dépendre de ton PC qui pourrait faire une tâche en même temps, etc. Faudrait essayer sur la calto.

Cake, il recompile pas pour chaque test, il fait un for
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 27/09/2016 18:33 | #


On dirait que tu n'as pas isolé ce calcul dans une fonction, Ninestars ? Au final, en extrapolant un peu, on s'en sort facilement. Il suffit de savoir que le suffixe « s » signifie « simple » (par opposition à « double ») et donc les flottants. Je vous mets le code annoté (i.e., lisible x)) :
/*
    int ty = current_wall->texture_height / (c2 + c1/wy);
    [1]  int -> float
    [1]  float + float
    [2]  float / float
    [1]  float -> int
*/

    mov.l    __itos,    r3        // Conversion vers float
    mov    r0, r4
    mov    #25, r0
    jsr    @r3
    mov.b    @(r0, r14), r0
    mov.l    r0, @-r15
    mov.l    @(44, r15), r1
    mov.l    __divs, r2        // Calcul de c1 / wy
    jsr    @r2
    mov    r4, r0
    mov.l    _adds, r3        // Calcul de c2 + ...
    mov    r15, r1
    add    #72, r1
    jsr    @r3
    mov.l    @r1, r1
    mov.l    __divs, r3        // Calcul de cw / ...
    jsr    @r3
    mov.l    @r15+, r1
    mov.l    __stoi, r2        // Conversion vers int
    jsr    @r2
    nop
    mov    r0,r4

/*
    int ty = wy * current_wall->texture_height / point1.z / (wy / point1.z + (1-wy) / point0.z);
    [1]  int -> float
    [1]  float -> int
    [1]  float * float
    [4]  float / float
    [1]  float - float
    [1]  float + float
*/

    mov.l    __itos, r3        // Conversion int -> float
    mov    #25, r0
    jsr    @r3
    mov.b    @(r0, r14), r0
    mov.l    __muls, r2        // Calcul de wy * cw
    jsr    @r2
    mov    r4, r1
    mov    r15, r3
    mov.l    __divs, r2        // Calcul de ... / p1.z
    mov    r0, r1
    add    #120, r3
    mov.l    @r3, r5
    jsr    @r2
    mov    r5, r0
    mov.l    r0, @-r15
    mov    r4, r1
    mov.l    __divs, r3        // Calcul de wy / p1.z
    jsr    @r3
    mov    r5, r0
    mov.l    r0, @-r15
    mov.l    0x3f800000, r1
    mov.l    __subs, r2        // Calcul de 1 - wy
    jsr    @r2
    mov    r4, r0
    mov.l    __divs, r3        // Calcul de ... / p0.z
    mov    r0, r1
    mov.w    0x008c, r0
    jsr    @r3
    mov.l    @(r0, r15), r0
    mov.l    _adds, r3        // Calcul du barycentre
    jsr    @r3
    mov.l    @r15+, r1
    mov.l    __divs, r2        // Calcul de ty (float)
    jsr    @r2
    mov.l    @r15+, r1
    mov.l    __stoi, r3        // Conversion float -> int
    jsr    @r3
    nop

Niveau performance, il ne doit pas y avoir de doute. L'optimisation classique au niveau de la série de divisions n'ayant pas été faite, l'analyse pure laisse prévoir un réel gain de vitesse avec le second calcul.

Tu utilises la RTC pour tes tests ? Le compteur R64CNT ne délivre que des signaux à 64 Hz (on peut compter à 128 Hz si on compte les deux fronts, il me semble, mais le registre de la RTC ne donne pas la valeur) ; tu es sûr que le code est assez lent pour ça ?

Sur l'émulateur ça peut être trompeur. Pour être sûr, il faudrait mesurer sur la machine... et avec gint, histoire de pouvoir compter le nombre de cycles proco -- la cerise, comme certains appellent ça.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Cakeisalie5 En ligne Ancien administrateur Points: 1959 Défis: 11 Message

Citer : Posté le 27/09/2016 18:42 | #



Et puis bon, je veux pas faire mon relou, mais pourquoi ne pas utiliser un vrai compilateur (et même une vraie plateforme :P), surtout pour les gros projets comme ça ? Ouais, on n'a pas d'émulateur, mais on a une calculatrice et on voit vraiment ce que ça va donner dessus (et des utilitaires de transfert CLI qui font que tester c'est rapide)...
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 27/09/2016 19:11 | #


Lephenixnoir a écrit :
On dirait que tu n'as pas isolé ce calcul dans une fonction, Ninestars ?
Je n'ai pas créée une fonction "juste" pour ce calcul, il est dans la fonction render_draw(). Pourquoi ?

Pour mesurer les perfs j'utilise la lib de Dark Storm il me semble, code c'est ça
#define SCA 0xD201D002
#define SCB 0x422B0009
#define SCE 0x80010070

typedef int(*sc_iv) (void);
const unsigned int sc003ba[] = {SCA, SCB, SCE, 0x3B};

#define RTC_GetTicks (*(sc_iv)sc003ba)

int time_get_ticks()
{
    return RTC_GetTicks();
}

Lephenixnoir a écrit :
tu es sûr que le code est assez lent pour ça ?
J'execute 300 fois mon moteur de rendu, j'ai bien 3-4 secondes d'attente avant que ma boucle se finisse.

Le problème c'est que c'est hyper long les transferts par FA-124, c'est pour ça que j'utilise le SDK, que pour compiler, sinon j'ai Sublime Text 2 pour l'édition.
Cake, tu supposes Linux je parie, et qu'est-ce que c'est ce CLI ?
Lephenixnoir En ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 27/09/2016 20:44 | #


Ninestars a écrit :
Je n'ai pas créée une fonction "juste" pour ce calcul, il est dans la fonction render_draw(). Pourquoi ?

Ça saute aux yeux, en fait. Le code est fondamentalement indéchiffrable parce que la distribution des variables dans la pile et les registres est complètement inconnue ; si tu wrappes le tout dans une fonction, on sait précisément quel paramètre est où. C'est essentiel quand il s'agit d'interpréter le comportement d'un morceau de code en assembleur

Il s'agit bien (0x03b) de RTC_GetTicks(). Je n'ai jamais eu l'occasion de le désassembler (et là mon soft est HS pour des raisons obscures), mais j'ai toujours eu des doutes sur la manière dont on obtenait un tick de 128 Hz... enfin peu importe à la limite.

S'il s'agissait d'un processeur moderne je ferais le coup du cache, mais c'est pas bon. Écoute, si tu veux une mesure précise, t'as qu'à utiliser un timer du proco et le programmer de sorte qu'il n'atteigne pas son terme. En lisant la valeur du compteur à la fin de l'exécution, tu dois pouvoir en déduire une mesure autrement plus précise de la vitesse de ton code qu'avec la RTC. (Du genre, un compteur au MHz au lieu d'un compteur à 100 Hz.)

Je te mets un bout de code là pour SH3 (je crois que t'as pas de SH4 ?), à utiliser sur la machine par contre. Je ne peux pas tester (les maths m'attendent), il faut juste appeler cette fonction avec en paramètre une fonction void → void. Note que le résultat est une affine du temps d'exécution, il y a un overhead à cause du temps d'appel et de récupération du compteur. Essaie d'abord d'appeler une seule fois ta fonction avec ça, si le délai est trop court (inférieur à 1000 unités), essaie de boucler.

struct Timer
{
    unsigned int TCOR;
    unsigned int TCNT;
    union
    {
        unsigned short WORD;
        struct
        {
            unsigned    :7;
            unsigned UNF    :1;
            unsigned    :2;
            unsigned UNIE    :1;
            unsigned CKEG    :2;
            unsigned TPSC    :3;
        };
    } TCR;
};

int execution_time(void (*function)(void))
{
    volatile struct Timer *tmu = (volatile struct Timer *)0xfffffe94;
    volatile unsigned char *tstr = (volatile unsigned char *)0xfffffe92;

    tmu->TCOR = 0xffffffff;
    tmu->TCNT = 0xffffffff;
    tmu->TCR.TPSC = 0;

    tmu->TCR.UNF = 0;
    tmu->TCR.UNIE = 0;
    tmu->TCR.CKEG = 0;

    *tstr |= 1;

    function();

    unsigned int counter = tmu->TCNT;
    *tstr &= ~1;

    return 0xffffffff - counter;
}

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 29/09/2016 17:12 | #


Très bien, merci je vais essayer ce bout de code

Ajouté le 29/09/2016 à 17:16 :
En fait il a pas trop aimé la compilation le sdk haha !
C:\Casio Projets\Render3D\Main.cpp(120) : C5144 (E) A value of type "volatile void *" cannot be used to initialize an entity of type "struct <unnamed> *"
C:\Casio Projets\Render3D\Main.cpp(121) : C5144 (E) A value of type "volatile void *" cannot be used to initialize an entity of type "unsigned char *"
C:\Casio Projets\Render3D\Main.cpp(123) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(124) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(125) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(127) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(128) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(129) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(131) : C5349 (E) No operator "|=" matches these operands
            Operand types are: Struct <unnamed> |= int
C:\Casio Projets\Render3D\Main.cpp(135) : C5131 (E) Expression must have pointer-to-class type
C:\Casio Projets\Render3D\Main.cpp(136) : C5349 (E) No operator "&=" matches these operands
            Operand types are: Struct <unnamed> &= int
C:\Casio Projets\Render3D\Main.cpp(138) : C5131 (E) Expression must have pointer-to-class type

Ton code commence à la ligne 100
Cakeisalie5 En ligne Ancien administrateur Points: 1959 Défis: 11 Message

Citer : Posté le 29/09/2016 17:23 | #


- Ajoutes "volatile" avant "struct" à ta ligne 103 et avant "unsigned char" à ta ligne 122
- Ligne 132, remplaces "*tstr" par "tstr->TCOR"
- Ligne 137, remplaces "*tstr" par "tstr->TCOR"

Pour les deux dernières corrections par contre, je suis pas sûr que ce soit ce que lephé avait en tête et j'ai pas RTFM.
Ca devrait résoudre tes autres erreurs aussi.
Respirateur d'air, BDFL de Cahute, des utilitaires de communication pour calculatrices CASIO.


Mon blogMes autres projets
Lephenixnoir En ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 29/09/2016 18:06 | #


Ok pour la première correction avec le volatile, mais non pour le reste. Il faut juste échanger les noms des deux variables à la déclaration (et pas la valeur).

Edit : j'ai modifié mon message du coup.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ninestars Hors ligne Membre Points: 2462 Défis: 24 Message

Citer : Posté le 29/09/2016 18:13 | #


Merci les gars, c'est un peu miuex mais j'ai toujours ça
C:\Casio Projets\Render3D\Main.cpp(120) : C5144 (E) A value of type "volatile void *" cannot be used to initialize an entity of type "volatile struct <unnamed> *"
C:\Casio Projets\Render3D\Main.cpp(121) : C5144 (E) A value of type "volatile void *" cannot be used to initialize an entity of type "unsigned char *"
1, 2 Suivante

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 246 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