Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » gint : un noyau pour développer des add-ins
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

gint : un noyau pour développer des add-ins

Posté le 20/02/2015 17:30

Ce topic fait partie de la série de topics du fxSDK.

En plus des options de programmation intégrée comme le Basic Casio ou Python, la plupart des calculatrices Casio supportent des add-ins, des programmes natifs très polyvalents avec d'excellentes performances. Les add-ins sont généralement programmés en C/C++ avec l'aide d'un ensemble d'outils appelé SDK.

Plusieurs SDK ont été utilisés par la communauté avec le temps. D'abord le fx-9860G SDK de Casio avec fxlib pour Graph monochromes (plus maintenu depuis longtemps). Puis le PrizmSDK avec libfxcg pour Prizm et Graph 90+E (encore un peu actif sur Cemetech). Et plus récemment celui que je maintiens, le fxSDK, dont gint est le composant principal.

gint est un unikernel, ce qui veut dire qu'il embarque essentiellement un OS indépendant dans les add-ins au lieu d'utiliser les fonctions de l'OS de Casio. Ça lui permet beaucoup de finesse sur le contrôle du matériel, notamment la mémoire, le clavier, l'écran et les horloges ; mais aussi de meilleures performances sur le dessin, les drivers et la gestion des interruptions, plus des choses entièrement nouvelles comme le moteur de gris sur Graph monochromes.

Les sources de gint sont sur la forge de Planète Casio : dépôt Gitea Lephenixnoir/gint

Aperçu des fonctionnalités

Les fonctionnalités phares de gint (avec le fxSDK) incluent :

  • Toutes vos images et polices converties automatiquement depuis le PNG, sans code à copier (via fxconv)
  • Un contrôle détaillé du clavier, avec un GetKey() personnalisable et un système d'événements à la SDL
  • Une bibliothèque standard C plus fournie que celle de Casio (voir fxlibc), même un peu de C++ (voir µSTL)
  • Plein de raccourcis pratiques, comme pour afficher la valeur d'une variable : dprint(1,1,"x=%d",x)
  • Des fonctions de dessin, d'images et de texte optimisées à la main et super rapides, surtout sur Graph 90+E
  • Des timers très précis (60 ns / 30 µs selon les cas, au lieu des 25 ms de l'OS), indispensables pour les jeux
  • Captures d'écran et capture vidéo des add-ins par USB, en temps réel (via fxlink)

Avec quelques mentions spéciales sur les Graph monochromes :
Un moteur de gris pour faire des jeux en 4 couleurs !
La compatibilité SH3, SH4 et Graph 35+E II, avec un seul fichier g1a
Une API Unix/POSIX et standard C pour accéder au système de fichiers (Graph 35+E II seulement)

Et quelques mentions spéciales sur les Graph 90+E :
Une nouvelle police de texte, plus lisible et économe en espace
Le dessin en plein écran, sans les bordures blanches et la barre de statut !
Un driver écran capable de triple-buffering
Une API Unix/POSIX et standard C pour accéder au système de fichiers

Galerie d'add-ins et de photos

Voici quelques photos et add-ins réalisés avec gint au cours des années !



Arena (2016)Plague (2021)



Rogue Life (2021)



Momento (2021)



Communication avec le PC (cliquez pour agrandir)


Utiliser gint pour développer des add-ins

Les instructions pour installer et utiliser gint sont données dans les divers tutoriels recensés dans le topic du fxSDK. Il y a différentes méthodes de la plus automatique (GiteaPC) à la plus manuelle (compilation/installation de chaque dépôt). Le fxSDK est compatible avec Linux, Mac OS, et marche aussi sous Windows avec l'aide de WSL, donc normalement tout le monde est couvert

Notez en particulier qu'il y a des tutoriels de développement qui couvrent les bases ; tout le reste est expliqué dans les en-têtes (fichiers .h) de la bibliothèque que vous pouvez consulter en ligne, ou dans les ajouts aux changelogs ci-dessous.

Changelog et informations techniques

Pour tester les fonctionnalités et la compatibilité de gint, j'utilise un add-in de test appelé gintctl (dépôt Gitea Lephenixnoir/gintctl). Il contient aussi une poignée d'utilitaires d'ordre général.

Ci-dessous se trouve la liste des posts indiquant les nouvelles versions de gint, et des liens vers des instructions/tutoriels supplémentaires qui accompagnent ces versions.

VersionDateInfos supplémentaires
gint 2.9.021 Août 2022
gint 2.8.017 Mai 2022Effets dynamiques sur les imagesAPI de manipulations d'images
Overclock intégré
gint 2.7.119 Mars 2022Tutoriel capture des flux standards
gint 2.7.031 Décembre 2021
gint 2.6.029 Août 2021Tutoriel de capture vidéo par USB
gint 2.5.28 Juin 2021
gint 2.5.12 Juin 2021
gint 2.5.026 Mai 2021Intégration de fxlibc (dépôt) — Tutoriel de communication par USB
gint 2.4.027 Avril 2021Api GINT_CALL() pour les callbacks
gint 2.3.12 Février 2021
gint 2.3.029 Janvier 2021
gint 2.2.112 Janvier 2021
gint 2.2.011 Janvier 2021
gint 2.1.116 Septembre 2020
gint 2.1.021 Août 2020Polices UnicodeNouvelle API du moteur de gris
gint 2.0.3-beta10 Juillet 2020Modifications de l'API timer
gint 2.0.2-beta17 Juin 2020
gint 2.0.1-beta1er Juin 2020

Anecdotes et bugs pétés

Ô amateurs de bas niveau, j'espère que vous ne tomberez pas dans les mêmes pièges que moi.


TODO list pour les prochaines versions (2022-08-21)

gint 2.10
  1. Changements de contextes CPU. À reprendre du prototype de threading de Yatis pour permettre l'implémentation d'un véritable ordonnanceur. Demandé par si pour faire du threading Java. Je vais peut-être coder des effets algébriques pour m'amuser un peu.
  2. Fignoler le driver USB. Ajouter la communication PC→calto, des pipes interruption/isochrones. Ajouter le support de descripteurs de fichiers USB. Potentiellement pousser jusqu'à avoir GDB pour debugger.

Non classé

  • Support de scanf() dans la fxlibc.
  • Regarder du côté serial (plus facile que l'USB) pour la communication inter-calculatrices (multijoueur) et ultimement l'audio (libsnd de TSWilliamson).
  • Un système pour recompiler des add-ins mono sur la Graph 90+E avec une adaptation automatique.
  • Support des fichiers en RAM pour pouvoir utiliser l'API haut-niveau sur tous les modèles et éviter la lenteur de BFile à l'écriture quand on a assez de RAM.
  • Overclock sur Graph mono.



Précédente 1, 2, 3 ··· 10 ··· 20 ··· 30 ··· 40 ··· 50 ··· 60 ··· 63, 64, 65, 66, 67, 68, 69 Suivante
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 16/05/2022 12:27 | #


OK, on pourra regarder alors. Ca devrait pas être un problème, juste peut être un peu de boulot pour remettre à plat la liste complète de tout ce qu'on peut toucher via les outils PTune/FTune pour être certains de ne rien oublier. Mais à voir si c'est vraiment nécessaire. Il serait à mon sens plus utile en priorité d'offrir ces mêmes deux fonctions aux monochromes en décortiquant les versions dédiées de PTune afin de les amener elles aussi sur cette première étape de "l'overclock facile".

J'ai deux/trois questions concernant les image_t :

- à lire le display-cg.h et image.h, ainsi que tes explications, on a perdu la compatibilité du membre "data" entre image_t et bopti_image_t, donc quand je triffouillais la palette dans MagicLight, mon code n'est donc plus portable (en soit c'est pas un problème, c'est juste pour vérifier).

- tu peux donner un exemple d'utilisation de image_create_vram() STP. J'imagine que c'est pour gagner un blit (en évitant un dimage() sur un écran complet), mais j'avoue avoir du mal à voir comment on s'en sert. Si on alloue une image en VRAM et qu'on fait un dimage() d'un sprite par exemple, on va "killer" les data de l'image de la VRAM. J'avoue que j'ai du mal à voir comment le système est pensé.

- autre question portage, du coup le resize de OutRun sur les RGB565 est opérationnel désormais et si je comprends bien il faut que je passe par image_linear() (en fait un image_linear_alloc() qui va enlever pas mal de complexité je pense) pour faire un scale up. On est bien d'accord aussi que dans le cas général, il faut passer les valeurs dans la structure image_linear_map, sauf si on utilise les fonctions individuelles (rotation, scale, translation) auquel cas on spécifie les paramètres "simples" de la transformation et on reçoit en retour le image_linear_map correspondant. (Je sais pas si ma question est claire en fait ).

En tout cas, y'a de la viande dans cette update on va pouvoir s'amuser ...
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 16/05/2022 21:16 | #


J'ai ajouté la sauvegarde/restauration du niveau d'overclock.

- à lire le display-cg.h et image.h, ainsi que tes explications, on a perdu la compatibilité du membre "data" entre image_t et bopti_image_t, donc quand je triffouillais la palette dans MagicLight, mon code n'est donc plus portable (en soit c'est pas un problème, c'est juste pour vérifier).

Oui, maintenant tu peux utiliser la nouvelle API. Le format est entièrement public au lieu d'être semi-interne comme avant.

- tu peux donner un exemple d'utilisation de image_create_vram() STP. J'imagine que c'est pour gagner un blit (en évitant un dimage() sur un écran complet), mais j'avoue avoir du mal à voir comment on s'en sert. Si on alloue une image en VRAM et qu'on fait un dimage() d'un sprite par exemple, on va "killer" les data de l'image de la VRAM. J'avoue que j'ai du mal à voir comment le système est pensé.

Pour afficher un sprite à l'envers à la position (10,10) dans la VRAM :

image_t *vram = image_create_vram();
image_hflip(my_sprite, image_at(vram, 10, 10));
// ...
image_free(vram);

Ça permet de faire toutes les transformations direct sur la VRAM.

- autre question portage, du coup le resize de OutRun sur les RGB565 est opérationnel désormais et si je comprends bien il faut que je passe par image_linear() (en fait un image_linear_alloc() qui va enlever pas mal de complexité je pense) pour faire un scale up. On est bien d'accord aussi que dans le cas général, il faut passer les valeurs dans la structure image_linear_map, sauf si on utilise les fonctions individuelles (rotation, scale, translation) auquel cas on spécifie les paramètres "simples" de la transformation et on reçoit en retour le image_linear_map correspondant. (Je sais pas si ma question est claire en fait ).

Yup t'as tout compris. Toi tu peux faire image_scale() pour obtenir la structure puis image_linear_alloc() directement.
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 16/05/2022 23:26 | #


Super, merci beaucoup Lephe.
C'est clair.

J'ai vu pour le save/restore des paramètres OC.
Je testerai sur la PRIZM à mon retour.
Parisse Hors ligne Membre Points: 374 Défis: 0 Message

Citer : Posté le 17/05/2022 12:20 | #


Le source de l'overclock peut-il facilement etre utilise en standalone? Ca serait tres utile dans la visualisation 3d de KhiCAS. Le mode F5 de Ptune3 me semble le plus rapide: rendering de plot(x^2-y^2) precis en 17s, contre 23s pour F4, et 28s en mode normal.
Sinon, il faudrait etudier le passage de la compilation de KhiCAS sur le SDK de gint.
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 17/05/2022 12:30 | #


Nouvelle version : gint 2.8.0

Une grosse release pour gint cette-fois ci, avec de gros progrès sur la gestion des images, ainsi que l'overclock intégré sur Graph 90+E.

Release associée du fxSDK : fxSDK 2.8.0
Release associée de la fxlibc : fxlibc 1.4.1

À peu près tous les points importants de cette update ont déjà été abordés en détail durant les discussions jusqu'ici ; voici les messages qui les détaillent.

Refonte du système de rendu d'images, avec des effets dynamiques.
Nouveau format d'image et API pour le manipuler à la façon de libimg.
Ajout de l'overclock intégré sur Graph 90+E.

Comme autre changement important, on notera que le triple-buffering n'est plus activé par défaut parce que le gain de performances est assez limité en pratique (s'il existe). Ça veut dire que dupdate() est synchrone et qu'on peut modifier les contenus de la VRAM après les avoir envoyés avec dupdate(), ce qui devrait résoudre quelques cas de confusion.

À la place de la seconde VRAM, gint crée du coup un tas d'environ 180 ko, ce qui peut servir aux add-ins un peu gourmands. Les gens qui veulent conserver le triple-buffering peuvent simplement allouer une nouvelle VRAM avec malloc().

En plus de ça, quelques changements mineurs et corrections de bugs :
  • drsize() renvoyait un résultat décalé d'un octet en fin de chaîne, ce qui créait parfois un résultat faux.
  • r62514_display() ignorait partiellement son paramètre start
  • Les définitions des modules CPG et BSC ont été mises à jour et ajoutées dans <gint/mpu/*.h>.
  • La gestion des répétitions du clavier est plus consistante qu'avant et élimine un cas rare de boucle infinie qui se produisait sur les programmes lents.
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 17/05/2022 12:51 | #


Parisse a écrit :
Le source de l'overclock peut-il facilement etre utilise en standalone? Ca serait tres utile dans la visualisation 3d de KhiCAS. Le mode F5 de Ptune3 me semble le plus rapide: rendering de plot(x^2-y^2) precis en 17s, contre 23s pour F4, et 28s en mode normal.
Sinon, il faudrait etudier le passage de la compilation de KhiCAS sur le SDK de gint.

J'ai failli rater ton message ! Oui la source pourrait être récupérée, et entre nous ce serait quelques ordres de grandeur moins compliqué que de tenter de compiler KhiCAS avec gint. Rien qu'avec le code que ça ajouterait et les différences d'API, brr.

Je sais que tu iras plus vite que le temps de réaction que je peux te proposer en ce moment, donc voilà comment procéder. Tu peux prendre directement le fichier src/cpg/overclock.c et le compiler dans KhiCAS.

Tu devras récupérer au passage les deux headers de <gint/mpu/*.h> qui ne poseront aucun problème (que des déclarations). Le <gint/gint.h> n'est pas nécessaire, et le <gint/hardware.h> n'est nécessaire que pour tester le modèle avec gint[HWCALC], ce pour quoi tu as certainement déjà un utilitaire à toi. De <gint/clock.h> tu peux extraire la section pertinente sans difficulté je pense, ainsi que la partie interne.

Le plus compliqué sera de voir le contexte du changement de fréquence. Il y a trois trucs importants : (1) éviter les tâches asynchrones durant le changement, comme le DMA, mais ça je ne crois pas que tu en aies ; (2) désactiver temporairement les interruptions, et (3) ajuster le délai des TMU mais je crois que tu n'utilises que les timers de l'OS qui ne sont pas affectés.

Avec ces simplifications tu devrais en arriver à :

void clock_set_speed(int level)
{
    if(level < CLOCK_SPEED_F1 || level > CLOCK_SPEED_F5)
        return;
    if(clock_get_speed() == level)
        return;

    struct cpg_overclock_setting *settings = get_settings();
    if(!settings)
        return;

    struct cpg_overclock_setting *s = &settings[level - CLOCK_SPEED_F1];

    // TODO: Désactiver les interruptions

    cpg_set_overclock_setting(s);

    // TODO: Réactiver les interruptions
}

Je pense que tu peux effectuer un test préliminaire sans désactiver les interruptions ; ce ne sera probablement pas stable mais ça devrait être suffisant pour confirmer que ça marche, moment à partir duquel tu pourras te poser la question des interruptions.
Kikoodx Hors ligne Labélisateur Points: 2979 Défis: 11 Message

Citer : Posté le 17/05/2022 13:58 | #


Lephenixnoir a écrit :
Nouvelle version : gint 2.8.0

Énorme ! J'attendais cette mise à jour avec impatience ! Praise Lephé
mi lape ala.

J'suis un méga chômeur
Parisse Hors ligne Membre Points: 374 Défis: 0 Message

Citer : Posté le 17/05/2022 17:33 | #


Merci Lephe! Ca a quand meme l'air pas completement trivial, je vais attendre d'avoir un creneau de temps suffisant pour essayer...
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 17/05/2022 21:38 | # | Fichier joint


Tiens voilà une archive déjà préparée. Ça compile presque, j'ai juste laissé des marqueurs aux endroits où il faut tester si c'est une fx-CG 10/20 ou une fx-CG 50.
Parisse Hors ligne Membre Points: 374 Défis: 0 Message

Citer : Posté le 18/05/2022 12:49 | #


Merci! Ca c'est du support!!!
Ca compile bien, je vais pouvoir tester!
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 18/05/2022 12:51 | #


Avant que j'oublie, j'ai testé que sur Graph 90+E parce que j'ai pas de Prizm (j'attends que SlyVTT ait l'occasion) donc je te conseille de tester sur Graph 90+E d'abord. Je voudrais pas qu'un paramètre assigné de travers te pose des problèmes
Parisse Hors ligne Membre Points: 374 Défis: 0 Message

Citer : Posté le 18/05/2022 13:36 | #


Je viens de tester sur graph 90, ca fonctionne tres bien. Je mets le cpu en niveau de vitesse 5 et je restore a la sortie de l'addin par le handler de fin. A priori, ce n'est actif que pour les graph 90 (et cg50, mais pas emulateur) avec le code de test

  uint32_t stack;
  __asm__("mov r15, %0" : "=r"(stack));
  if (stack<0x8c000000) {
    /* Prizm ou émulateur Graph 90+E */
    if (calculator==0)
      calculator=2;
    ram3M.name="_3M";
    ram3M.is_default=1;
    ram3M.start=0x88480000;
    ram3M.end=ram3M.start+0x80000;
    kmalloc_init_arena(&ram3M, true);
    kmalloc_add_arena(&ram3M);
  }
  else {
    if (calculator==0)
      calculator=1;
    /* Graph 90+E & FXCG50(?) */
    ram3M.name="_3M";
    ram3M.is_default=1;
    ram3M.start=0x8c480000;
    ram3M.end=ram3M.start+0x80000;
    kmalloc_init_arena(&ram3M, true);
    kmalloc_add_arena(&ram3M);
  }
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 18/05/2022 13:38 | #


Impeccable ! Content que ça marche. Ton code de détection est bon oui, avec calculator=1 tu es sur une Graph 90+E, avec calculator=2 sur une Prizm.
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 22/05/2022 18:44 | #


Hello,
comme promis j'ai testé les paramètres d'overclock sur la Prizm.
Je n'ai pas détecté de problème, donc ça me semble OK.
Je ferai des tests plus approfondis au fur et à mesure des développements.
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 22/05/2022 19:35 | #


Merci ! Je voulais te donner quelques instructions, mais j'ai oublié - il faut d'abord que les modes de Ptune soient bien détectés par gintctl qund tu lances l'add-in avec l'overclock actif (pour vérifier que je n'ai pas mal programmé certains paramètres, ce qui pourrait être gênant) puis tester que les perfs varient et que le timer est consistent en termes de vitesse. Mais je suppose que tu as deviné tout ça.

Impeccable du coup, merci beaucoup !
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 22/05/2022 20:49 | #


Bon j'ai poussé un peu plus les tests.
Je confirme que les niveaux changent bien et l'overclock fonctionne (le FPS d'un jeu bouge).
Les timers sont bien respectés (une pause de 5s dure effectivement bien 5s sur un chrono externe) quand on change de mode.

Par contre, j'ai systématiquement un CLOCK_SPEED_UNKNOWN en retour de clock_get_speed() (même quand je teste juste après avoir changé de mode).

Mon impression (j'ai juste regardé vite fait, donc à vérifier), c'est que pour que tu retournes le niveau détecté, il faut que tu aies tout qui matche parfaitement dans la structure de données cpg_overclock_setting, mais pour la Prizm, tu me consideres pas BSC.CS3BCR et BSC.CS3WCR dans cpg_get_overclock_setting() dans overclock.c. Donc a priori le test suivant ne passe pas :


int clock_get_speed(void)
{
    struct cpg_overclock_setting *settings = get_settings();
    if(!settings)
        return CLOCK_SPEED_UNKNOWN;

    for(int i = 0; i < 5; i++) {
        struct cpg_overclock_setting *s = &settings[i];

        if(CPG.FLLFRQ.lword == s->FLLFRQ
            && CPG.FRQCR.lword == s->FRQCR
            && BSC.CS0BCR.lword == s->CS0BCR
            && BSC.CS2BCR.lword == s->CS2BCR
            && BSC.CS3BCR.lword == s->CS3BCR    // sur prizm je pense que cela n'arrive jamais car s->CS3BCR n'est pas rempli
            && BSC.CS5ABCR.lword == s->CS5aBCR
            && BSC.CS0WCR.lword == s->CS0WCR
            && BSC.CS2WCR.lword == s->CS2WCR
            && BSC.CS3WCR.lword == s->CS3WCR   // sur prizm je pense que cela n'arrive jamais car s->CS3WCR n'est pas rempli
            && BSC.CS5AWCR.lword == s->CS5aWCR)
            return CLOCK_SPEED_F1 + i;
    }

    return CLOCK_SPEED_UNKNOWN; // donc on a toujours ça
}


Qu'en penses tu ?
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 22/05/2022 21:01 | #


Exact, c'est le genre de trucs que j'oublie vite et qu'il faut tester...

J'ai poussé un fix pour ça.
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 22/05/2022 21:06 | #


Yep c'est bon cette fois
Tout fonctionne bien
C'était pas très grave

cela dit, je sais pas pourquoi tu t’embêtes avec ce test, car les deux registres ont aussi des valeurs par défaut pour la prizm, tout comme sur la CG50.
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 22/05/2022 21:08 | #


On ne sait pas ce qu'il y a comme mémoire branchée sur CS3 (probablement rien) donc par principe les registres sont "pas à nous"
Slyvtt Hors ligne Community Manager Points: 834 Défis: 0 Message

Citer : Posté le 23/05/2022 14:03 | #


Ok je comprends. Tu vas dire que je suis chi..t, mais sur la CG50, mais sauf erreur de ma part (ce qui n'est pas impossible), on est dans la même configuration, on injecte toujours les valeurs par défaut dans CS3, donc alors autant ne pas faire cette injection et laisser CS3 tranquille sur les 2 types de machines. Non ??
Seuls les CS2 sont manipulés avec des valeurs autres que les valeurs par défaut.
Ce qui me gene c'est d'avoir cette "asymétrie de traitement" alors qu'à priori le fonctionnement est le même pour cette partie.
Lephenixnoir Hors ligne Administrateur Points: 22599 Défis: 149 Message

Citer : Posté le 23/05/2022 14:45 | #


Sur la Graph 90+E CS3 est bien utilisé, pour la RAM. Souviens-toi que l'adresse de la RAM change sur Graph 90+E (c'est d'ailleurs comme ça qu'on la détecte) ; ça provient du fait qu'un autre type de RAM est utilisé, et donc un autre espace mémoire du BSC (CS3 au lieu de CS2). C'est un peu de la spéculation parce qu'on n'a pas la doc réelle du BSC, mais c'est l'hypothèse la plus raisonnable pour l'instant. Je soupçonne que CS2 ne soit pas utilisé sur Graph 90+E, mais Ptune reste la référence et Ptune modifie CS2, donc je suis Ptune.

L'asymétrie de traitement provient donc d'une asymétrie sur la configuration matérielle, ce qui est pas aberrant.

Et de façon beaucoup plus pragmatique, Ptune2 ne modifie pas CS3, et on suit Ptune.
Précédente 1, 2, 3 ··· 10 ··· 20 ··· 30 ··· 40 ··· 50 ··· 60 ··· 63, 64, 65, 66, 67, 68, 69 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 v42 © créé par Neuronix et Muelsaco 2004 - 2022 | Il y a 73 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