Planète Casio - Vos tutoriels et astuces - Flux RSS http://www.planet-casio.com Programmes Casio, Jeux, Cours pour Calculatrices Casio fr-FR https://www.planet-casio.com/images/logo.gif Planète Casio - Vos tutoriels et astuces - Flux RSS http://www.planet-casio.com 55 50 Programmes Casio, Jeux, Cours pour Calculatrices Casio. Thu, 28 Oct 2021 10:59:33 GMT Thu, 28 Oct 2021 10:59:33 GMT contact@planet-casio.com (Planet Casio) contact@planet-casio.com (Planet Casio) 5 Vector Calculations on Version 2.09 https://www.planet-casio.com/Fr/forums/topic16912--.html Recently, I have flashed my fx-9750GII with fx-9860GII OS Version 2.09. When I flashed it from 2.05, it still had vector calculations. Ti-Planet says that 2.09 has no vector calculations. Thu, 21 Oct 2021 04:42:58 +0200 Gérer et éviter les Erreurs Math d'une fonction https://www.planet-casio.com/Fr/forums/topic16880--.html Mon tout premier "tuto" ! :) Vous en avez marre que la calculatrice renvoie à tout bout de champ une Erreur Math en Basic Casio, que ce soit une division par 0 ou un dépassement arithmétique ? Alors lisez ce qui suit ! Il est en effet possible de s'affranchir de ces erreurs, et pour cela un peu de programmation pré-traitement est nécessaire. Finis les programmes qui s'arrêtent sans prévenir ! Par souci de compréhension, la lettre Y fera référence à toute fonction pour laquelle on ne voudrait plus avoir de message d'erreur. À ce jour, je connais 3 fonctions Basic Casio gérant les Erreurs Math sans nous déranger (et oui, j'allais quand même pas partir de rien :p ) - et pour lesquelles il serait possible de déduire en quels points Y ne pose pas problème : Les fonctions du menu Sketch, traçant les graphiques La fonction SolveN() Les fonctions de récurrence Je ne continuerai ce tutoriel qu'avec les fonctions de récurrence, étant la solution la plus rapide, viable, efficace, et de loin. Par contre, cela nous contraint en une chose : il est absolument nécessaire d'utiliser les chaînes de caractères (Strings) - vu depuis le temps qu'elles existent sur Casio il ne devrait pas y avoir de problème ^^ . Ça peut sûrement vous surprendre, mais il existe dans les fonctions de récurrence un moyen d'entrer une fonction tout à fait normale, ne contenant pas d'appel à ses précédantes valeurs... Non seulement je pense que le tutoriel est plutôt intéressant, mais peut-être la récurrence est trop peu connue par les utilisateurs Casio ? Dans ce tutoriel-ci, je montrerai seulement comment éviter les erreurs de dépassement arithmétique (≥1ᴇ100). Une fois cette méthode comprise, il est plutôt facile de la modifier un peu afin de gérer les éventuelles divisions par 0 ;) . Bon j'en ai marre de parler, donc essayez d'avaler ça pour voir >:) anType 0→R Start 209→R End R SelOn an //Y étant stockée dans la première chaîne de caractères, et supposant que l'abscisse de Y est la variable X StrLen(Str 1)→A StrSrc(Str1,"X" While Ans StrLeft(Str 1, Ans-1) + "(S^n)" + StrRight(Str 1, A-Ans→Str 1 A+4→A StrSrc(Str1,"X" WhileEnd Str 1→an 3→S DispR-Tbl R Result Dim Mat Ans S^Mat Ans[List Ans[1],1 //Ans est maintenant l'abscisse maximale pouvant être donnée à Y Les "n" présents dans ce code sont des caractères spéciaux ! Sélectionnez bien "n(RECUR)" dans votre catalogue de fonctions (+[4]) ! Ce serait bête de se tromper, surtout qu'il y a 4 différents "n" en Basic Casio.... Un peu trop brut ? Bon d'accord je veux bien expliquer tout ce que nous avons là :lol: - Tout d'abord, il faut savoir que les fonctions de récurrence calculent tout d'une traite, et les résultats peuvent être enregistrés dans une matrice. Il est donc obligatoire de fixer les bornes au préalable. La fonction de récurrence que nous allons construire se trouvera dans an, mais peut aussi se trouver dans bn ou encore cn. À noter que R Start et R End sont des caractères spéciaux, malgré l'espace qu'ils contiennent chacun. R SelOn an est quant à lui composé de 2 caractères spéciaux : "R SelOn " et an. Je vous recommande franchement de désélectionner bn et cn si ce n'est déjà fait (R SelOff ), et par la même occasion de désactiver la somme des éléments (ΣdispOff). Le poids utilisé par les récurrences monte très vite, et le code ci-dessus utilise déjà 10 ko, 5 ko dans l'application "RECUR" et 5 ko - ou moins, en fonction de si Y a un dépassement arithmétique ou non - dans Mat Ans. La phase "d'initialisation" est terminée ;) - Malheureusement, les fonctions de récurrence renvoient une Erreur Syntaxe si on fait un appel à une fonction graphique (par ex "Y1(n)"). On doit donc changer tous ces X par la variable n. Lors du calcul des images d'une onction de récurrence, il faut aussi savoir que le pas des abscisses (n) est fixe, et vaut 1. Imaginez le nombre d'entrées dans un tableau nécessaires pour arriver à l'abscisse 9ᴇ99 ! Tout simplement impossible. De plus, vu qu'on aimerait avoir l'abscisse maximale avant que Y ne donne d'erreur de dépassement arithmétique, il serait judicieux d'avoir une plus grande précision pour des petites abscisses que pour les grandes (10^X donne une erreur à partir de 100, ce serait mieux dans un cas comme celui-ci de s'en rapprocher le plus). Voilà pourquoi une progression exponentielle est intéressante ! La base choisie est arbitraire, et dépend aussi de la borne supérieure R End. Je ne m'attarde pas plus sur le code pour remplacer les "X" par des "(S ^ n)". Une seule chose à noter ici : ce remplacement pourrait changer l'ordre des opérations de Y ! Ajoutez donc bien des parenthèses dès qu'il y a ambiguïté ! C'est un cas assez spécifique, mais ça l'est si Y possède une multiplication sans opérateur explicite. Par exemple "Int 10X" - 10X sera d'abord calculé, et ensuite Int - donnera "Int 10(S ^ n)", et cette fois-ci la calto verra ce calcul comme suit : "(Int 10) * (S ^ n)". Autant dire que ce n'est pas exactement ce que vous vouliez... Comme quoi des parenthèses peuvent sauver la mise :D - DispR-Tbl va calculer absolument tous les points. N'hésitez pas à ajouter un Disp juste après cette instruction (◢), et vous verrez une matrice pouvant contenir des éléments "ERROR" dedans. Voilà donc l'utilité de la prochaine instruction : R Result. Elle transforme le précédant tableau en matrice en enlevant tous les éléments "ERROR". S'il n'y a que des "ERROR" dans ce tableau, la matrice ne pourra être créée et une Erreur Dimension sera renvoyée. Il ne nous reste plus qu'à obtenir l'abscisse maximale que la fonction de récurrence a réussi à passer, et vous obtenez maintenant un seuil à ne pas dépasser lors de votre étude de fonction - ou que sais-je 0_0 . Une précision d'un facteur 3 peut vous paraître trop grande - et à moi aussi - , j'ai donc essayé de pousser le bouchon à la précision maximale que je pouvais avoir : une base 1.26 avec une borne supérieure R End valant 996 (une Erreur Plage serait renvoyée si R End ≥ 1000). Mais 38 ko libres n'ont pas l'air de suffire :oops: Pour ceci je vous conseillerais donc (si vous voulez être plus précis) de redéfinir les bornes et de réitiérer grâce à la dernière abscisse maximale acceptée. Comme vous l'aurez compris, cette méthode sert à éviter les Erreurs Math, mais peut passer par dessus une erreur ponctuelle sans s'en rendre compte - comme une division par 0. Certains points de ce tutoriel peuvent être bien évidemment superflus - tout comme des fonctions Basic Casio - et par conséquent n'hésitez vraiment pas à poser des questions, ou même écrire vos commentaires ;) En espérant que tout ceci est pu au moins être intelligible, merci de votre lecture ! Mon, 13 Sep 2021 00:22:25 +0200 [Tutoriel] Accélérer les Graph avec l'overclock de Ftune et Ptune https://www.planet-casio.com/Fr/forums/topic16868--.html Salut à tous ! Ce tutoriel concerne les programmes Ftune et Ptune de Sentaro21. Ftune et Ptune sont des utilitaires d'overclock : ils accélèrent les horloges du matériel pour tirer plus de performances et accélérer toute la calculatrice ! :D :here: Page originale du programme (anglais/japonais) Quelles sont les calculatrices concernées ? Toutes les modèles Graph sur lesquels on peut installer des add-ins sont concernés ! Pour certains modèles (les 35 sauf la Graph 35+E II), il faut modifier l'OS avant de pouvoir installer des add-ins. Dans tous les cas, vous pouvez trouver sur la page Tout sur ta CASIO ! les instructions détaillées pour installer des add-ins. Avec Ftune (premier fichier) : g35+usb3 Graph 35+, Graph 35+USB (SH3) g75 Graph 75 g85 Graph 85 et Graph 85 SD g95 Graph 95 (SD) Avec Ftune2 (second fichier) : g35+usb4 Graph 35+USB (SH4), Graph 35+E g75+ Graph 75+, Graph 75+E Avec Ftune3 : g35+e2 Graph 35+E II Avec Ptune2 : cg20 fx-CG 10, fx-CG 20 («Prizm») Avec Ptune3 : g90+e Graph 90+E Quels sont les risques ? Résumé : si vous utilisez uniquement les préréglages F1...F5, aucun ; ça consomme juste davantage les piles. Le principe de l'overclock est d'accélérer les horloges qui cadencent le travail des circuits électroniques. L'idée en elle-même ne présente de risque que si on va tellement vite que les circuits n'arrivent plus à suivre, auquel cas le matériel panique. Sur un ordinateur, l'overclock est un sujet relativement sensible : chacun a des combinaisons de processeur/mémoires/etc différentes, donc il est difficile de savoir jusqu'où on peut aller ; le matériel peut surchauffer ; et les valeurs d'usine sont généralement assez proches des limites donc il n'y a pas grand-chose à gagner. Sur la calculatrice c'est beaucoup plus simple et beaucoup moins risqué. D'abord sur la calculatrice l'autonomie est une priorité pour le constructeur, donc autant que possible les horloges sont ralenties dans la configuration par défaut. Il y a donc de la marge avant d'atteindre les limites du matériel. Ensuite, toutes les copies d'un même modèle sont identiques, et toutes ces versions de Ftune et Ptune ont servi pendant des années sans jamais casser de calculatrice. Très honnêtement, si vous utilisez des paramètres préréglés (sur les touches F1...F5, j'y reviendra) vous n'avez rien à craindre. Si vous avez une Graph 35+E II ou une Graph 90+E, faites plutôt attention à ne pas débrancher intempestivement votre calculatrice durant un transfert par USB, c'est plutôt ça qui risque de vous la casser. Les autres modèles sont pratiquement incassables, il n'y a pas grand-chose qu'un appui sur le bouton RESET au dos de la machine ne réparera pas. ^^ Les préréglages F1...F5 Quand vous entrez dans Ftune/Ptune, vous êtes accueilli·e par l'écran suivant (ou une popup proposant un test mémoire, que vous pouvez refuser) : https://www.planet-casio.com/storage/program-images/3872-Ftune3.png https://www.planet-casio.com/storage/program-images/3710-Ptune3.gif Il y a beaucoup d'informations qui sont expliquées dans les sections suivantes, mais vous pouvez repérer tout simplement la fréquence du processeur sur la deuxième ligne (IFC). En général, plus elle est élevée plus la calculatrice va vite, et vous n'avez rien besoin de savoir d'autre pour profiter de l'overclock. Les touches F1 à F5 permettent de sélectionner 5 préréglages : Normal, F1, F2, F3, F4 et F5. Le préréglage «Normal» est la configuration par défaut de la calculatrice. En appuyant sur F1 vous remettez tous les paramètres à la valeur d'usine. ;) Les préréglages F2, F3, F4 et F5 sont d'autres préréglages qui sont sensiblement du plus lent au plus rapide. Si vous les activez vous verrez les différentes fréquences à l'écran changer, dont la fréquence du CPU. Après avoir choisi un réglage, quittez Ftune/Ptune en appuyant sur MENU et observez la calculatrice sous sa forme accélérée ! Les réglages restent si vous éteignez la calculatrice (SHIFT+AC/ON) mais sont réinitialisés si la calculatrice redémarre (bouton RESET au dos, changement de piles, ou crash). ^^ Si vous pensez avoir fait une mauvaise manipulation, appuyez sur F1 pour revenir à la configuration par défaut. Si ce n'est pas possible (parce qu'un programme se comporte mal à cause de l'overclock, par exemple), redémarrez la calculatrice en appuyant sur le bouton RESET au dos et tout sera réinitialisé. Et c'est tout ! Vous pouvez changer de préréglage à loisir et ne jamais toucher au reste de l'application, ça vous emmènera très loin. Si vous êtes un peu méfiant·e, vous ne prenez pas de risque avec les préréglages. :) Configuration pour obtenir les meilleurs performances La fréquence CPU la plus élevée que Ftune/Ptune propose avec les préréglages est la suivante : Pour Ftune : 117.96 MHz (F5) Pour Ftune2 : 235.93 MHz (F5) Pour Ptune2 : 191.69 MHz (F5) Pour Ptune3 : 232.31 MHz (F4) Si vous voulez pousser un peu plus loin, vous avez quelques options. Sur tous les modèles, vous pouvez pousser PLL et FLL un peu plus loin que les valeurs par défaut pour gagner quelques pourcents supplémentaires. Sur les modèles couleur (Prizm et Graph 90+E), la fréquence CPU n'est pas toujours le facteur limitant. Le préréglage F4 vous donne la meilleure fréquence processeur, mais le préréglage F5 donne la meilleure vitesse pour la mémoire et l'écran. Selon ce que vous faites avec la calculatrice, l'un ou l'autre peut être plus favorable, n'hésitez pas à tester les deux. ;) Sur Graph 90+E, il est possible d'installer Ptune2 et d'utiliser le préréglage F5. Ptune2 est moins prudent que Ptune3 et pousse les paramètres sensiblement plus loin. Attention cependant, il n'y a pas de garanties de fonctionnement parce que ce n'est pas la version normale (le préréglage F4 de Ptune2 fait crasher ma Graph 90+E par exemple parce qu'il pousse la mémoire et l'écran trop loin). On n'a jamais eu de rapport de problèmes durables causés par Ftune/Ptune. Au pire, un redémarrage/RESET réinitialise la calculatrice. Vous pouvez donc librement faire des essais, mais ne modifiez que les paramètre dont vous comprenez le rôle. Si ça vous tente, voyez les explications ci-dessous pour plus de détails. ^^ Annexe 1 : explication des différentes horloges Le reste de ce tutoriel est assez technique, n'hésitez pas à demander des détails dans les commentaires ! Les signaux d'horloge sur l'écran principal sont ceux générés par le CPG, le module du microprocesseur qui est chargé de cadencer à peu près tout le monde (pour une référence proche, voyez le manuel SH7724, section 17). Je ne détaille que pour les SH4 ici, les SH3 sont quasiment disparus. Le signal d'origine provient de l'oscillateur de la RTC et s'appelle `RTCCLK`, il est fixé à 32768 Hz. Il passe dans deux multiplieurs de constantes `FLL/2` et `PLL`, avant de générer les 4 signaux principaux : `Iϕ` est la fréquence du processeur. `Sϕ` est la fréquence du SuperHyway, le bus principal du MPU. `Bϕ` est la fréquence du bus externe qui accède entre autres à la mémoire et à l'écran. `Pϕ` est la fréquence du bus périphérique qui contrôle notamment les timers. Vous pouvez voir la valeur de FLL en appuyant sur SHIFT,↑ après avoir sélectionné PLL (c'est une option cachée). `Iϕ`, `Sϕ`, `Bϕ` et `Pϕ` sont obtenus en divisant la sortie de PLL, et Ftune/Ptune montre la valeur du diviseur à côté du nom (généralement 1/2, 1/4, 1/8 ou 1/16). Tout est lié, mais les deux gros acteurs sont `Iϕ` qui détermine la vitesse de calcul, et `Bϕ` qui détermine la vitesse des accès à la mémoire et des affichages à l'écran (qui sont assez lents sur la Prizm et Graph 90+E). Avec ça, vous pouvez déchiffrer tout l'écran principal de Ftune/Ptune. ;) Vous pouvez modifier les paramètres individuellement. Les diviseurs ont beaucoup de contraintes, et Ftune/Ptune ajustera automatiquement pour rester dans les valeurs valides. PLL et FLL sont des cibles classiques pour ajuster finement la performance. Si vous configurez les signaux de façon fautive ou trop rapide des fonds noirs/rouges apparaissent pour signaler les déviations. Annexe 2 : explication des cycles d'attente Un des éléments limitants pour les performances est la vitesse de la mémoire. En effet, il est inutile de calculer très vite si on ne peut pas écrire les résultats tout aussi vite dans la mémoire... Ftune/Ptune permet donc de modifier les cycles d'attente durant les accès mémoire, qui sont des délais supplémentaires que le MPU laisse à la mémoire pour faire ses affaires. Vous pouvez voir les paramètres en question en tapant sur VARS puis en sélectionnant F3, F4, F5 ou F6. Chaque écran présente les délais appliqués dans 5 situations différentes pour la ROM (CS0) et la RAM (CS2). Essentiellement en réduisant ces délais on interagit plus rapidement avec la mémoire, si tenté bien sûr qu'il reste assez de temps pour que la mémoire arrive à terminer chaque opérations avant qu'on commence la suivante. L'explication du rôle de chaque valeur est détaillé dans la documentation du contrôleur de bus (BSC, voir le manuel SH7724, section 14). Vous pouvez voir comment chaque préréglage modifie les délais en consultant ces écrans après avoir changé de configuration. Par contre l'ajustement fin de ces valeurs est réservé aux plus expérimentés, je déconseille d'y toucher sans savoir exactement ce qu'elles font et comment ! Conclusion Ftune/Ptune est un utilitaire presque incontournable qui est installé en permanence sur toutes mes calculatrices. Le bénéfice de l'overclock vient avec zéro compromis de stabilité, ce qui en fait instantanément un outil très appréciable à utiliser. Je le recommande vivement pour accélérer calculs, programmes et jeux. :) Sun, 05 Sep 2021 15:24:51 +0200 quel logiciel d'édition utiliser pour les programmes en .g1m https://www.planet-casio.com/Fr/forums/topic16852--.html Bonsoir, j'ai une question : j'ai téléchargé un programme en .g1m et j'aimerais le convertir en .cat, or le logiciel casform exige que je copie le code source dans la zone de texte gauche et le logiciel casiocom ne reconnais pas le format .g1m, j'aimerais donc savoir quel logiciel télécharger pour copier le code source de ce programme sur le presse-papier et le coller dans la zone de texte de gauche du convertisseur casform, s.v.p. ? Merci d'avance, David (A.K.A. Sniperking ou Solid Snake, même si, honnêtement, je préfèrerais que vous m'appeliez David...) Sat, 14 Aug 2021 21:33:26 +0200 Interface Graphique Textuel pour Graph 35+ et 90 https://www.planet-casio.com/Fr/forums/topic16832--.html Bonjour les amis ! Je créé ce nouveau Topic pour proposer une partie précise des sources de mon projet que j'ai soumis pour le Jam Python #1 Comme certains l'ont remarqué python (que ça soit sur Graph 35 ou 90) n'est pas le langage le plus adapté pour créer des jeux sous calculatrice. Malgré tout, j'ai tenté de créer une "Moteur Graphique Textuel" conçu pour python. Il sera donc utilisable normalement pour Graph 35 ou 90. Je vais donc détailler son fonctionnement ici. Voici tout d'abord le code au complet : import math dim = [30,8] def Clear(): print(""" """*(dim[1]+1)) class Curseur: def __init__(self): self.LstBoutons=[] self.index = 0 class Bouton: def __init__(self,curseur,Txt): curseur.LstBoutons.append(self) self.curseur = curseur self.text = Txt def GetString(self): if self.curseur.LstBoutons[self.curseur.index]==self: return self.text else: return self.text.replace("["," ").replace("]"," ") class Image: def __init__(self,data): self.data=data def GetWidth(name): w=0 for i in name.split("\n"): if len(i)>w: w=len(i) return w def GetHeight(name): return len(name.split("\n")) def GetImage(name): if name[0]=="\n": name=name[1:] w,h=GetWidth(name),GetHeight(name) Lst = name.split("\n") Screen=[] for i in range(h): temp=[] for o in range(w): temp.append(" ") Screen.append(temp) for Y,i in enumerate(Lst): for X,o in enumerate(i): (Screen)=o return Screen class StringVar: def __init__(self,data): self.data=data class Interface: def __init__(self): self.curseur = Curseur() self.Widgets = [] self._lastCmd="" def FindIndexOfWidget(self,adress): for i in range(len(self.Widgets)): if (self.Widgets)[0]==adress: return i def Clear(self): self.Widgets = [] self._lastCmd="" self.curseur.index = 0 self.curseur.LstBoutons=[] def Print(self): Screen=[] for i in range(dim[1]): temp=[] for o in range(dim[0]): temp.append(" ") Screen.append(temp) for i in self.Widgets: Text = "" try: if type(i[0])==Image: x,y=i[3],i[2] for indY,y1 in enumerate(i[0].data): for indX,x1 in enumerate(y1): try: (Screen[indY+y])[indX+x]=x1 except:pass else: if type(i[0])==str: Text=i[0] elif type(i[0])==StringVar: Text=str(i[0].data) elif type(i[0])==Bouton: Text=i[0].GetString() if i[1]=="PlaceCenter": x=int((dim[0]/2)-math.ceil(len(Text)/2)) for x1,lettre in enumerate(Text): (Screen[i[2]])[x+x1]=lettre elif i[1]=="Locate": x=i[3] for x1,lettre in enumerate(Text): (Screen[i[2]])[x+x1]=lettre except: pass for i in Screen: line = "" for o in i: line+=o print(line) def Draw(self): self.Print() cmd = input() self._lastCmd = cmd if cmd=="": return self.curseur.index,cmd,self.curseur.LstBoutons[self.curseur.index] else: return None,cmd,None def RemoveWidget(self,adress): if type(adress)==Bouton: self.curseur.LstBoutons.remove(adress) self.curseur.index=0 for i in range(len(self.Widgets)): if (self.Widgets)[0]==adress: del self.Widgets return def PlaceCenter(self,obj,Ln): self.Widgets.append([obj,"PlaceCenter",Ln]) def Locate(self,obj,Ln,Col): self.Widgets.append([obj,"Locate",Ln,Col]) def UpdateCursor(self): if self._lastCmd in ["8","4","6","2"]: x,y=0,0 for i in self.Widgets: if type(i[0])!=Bouton: continue Text = i[0].GetString() if i[0]==self.curseur.LstBoutons[self.curseur.index]: if i[1]=="PlaceCenter": x=int((dim[0]/2)-math.ceil(len(Text)/2)) y=i[2] elif i[1]=="Locate": x=i[3] y=i[2] direction=[None,100] for i in self.Widgets: if type(i[0])!=Bouton: continue dis = 100 x1,y1=0,0 Text = i[0].GetString() if i[1]=="PlaceCenter": x1,y1= int((dim[0]/2)-math.ceil(len(Text)/2)),i[2] elif i[1]=="Locate" : x1,y1= i[3],i[2] dis = math.sqrt(((y1-y)**2)+ (x1-x)**2) if self._lastCmd=="8": if y1<y and dis<direction[1]: direction=[i[0],dis] if self._lastCmd=="2": if y1>y and dis<direction[1]: direction=[i[0],dis] if self._lastCmd=="4": if x1<x and dis<direction[1]: direction=[i[0],dis] if self._lastCmd=="6": if x1>x and dis<direction[1]: direction=[i[0],dis] if direction[0]!=None: self.curseur.index = self.curseur.LstBoutons.index(direction[0]) def WaitBouttonInput(self): retour = None while retour == None: retour , _ , _ = self.Draw() if retour == None: self.UpdateCursor() return retour def BoiteConfirmValide(txt): interface = Interface() txt = txt.split(" ") interface.Locate("#"*dim[0],0,0) y=1 while len(txt)>0: msg="" while len(txt)>0 and len(msg)+len(txt[0])<dim[0]-3: msg+=" "+txt.pop(0) interface.Locate(msg,y,0) y+=1 interface.Locate("#"*dim[0],dim[1]-1,0) interface.Locate(Bouton(interface.curseur," "),dim[1]-1,int((dim[0]/4)-math.ceil(7/2))+1) interface.Locate(Bouton(interface.curseur," "),dim[1]-1,int((3*dim[0]/4)-math.ceil(7/2))) return interface.WaitBouttonInput() == 0 def BoiteConfirmOK(txt): interface = Interface() txt = txt.split(" ") interface.Locate("#"*dim[0],0,0) y=1 while len(txt)>0: msg="" while len(txt)>0 and len(msg)+len(txt[0])<dim[0]-3: msg+=" "+txt.pop(0) interface.Locate(msg,y,0) y+=1 interface.Locate("#"*dim[0],dim[1]-1,0) interface.PlaceCenter(Bouton(interface.curseur," "),dim[1]-1) interface.Draw() return True def MainMenu(Titre): Clear() interface = Interface() interface.PlaceCenter((len(Titre)+2)*"=",0) interface.PlaceCenter(" "+Titre+" ",1) interface.PlaceCenter((len(Titre)+2)*"=",2) interface.PlaceCenter(Bouton(interface.curseur,"[Commencer une partie]"),4) interface.PlaceCenter(Bouton(interface.curseur,"[Entrer un code] "),5) interface.PlaceCenter(Bouton(interface.curseur," "),7) return interface.WaitBouttonInput() La variable Dim est très importante, comme vos aurez pus le deviner c'est les dimensions de l'écran. (pour Graph 35 les dimensions sont 30x8) La fonction Clear permet de "nettoyer" l'écran. Pour être précis, l'écran n'est jamais nettoyé, il défile plutôt, c'est-à-dire que si vous appuyez sur la flèche du haut, vous vos apercevrez qu'il y a les anciens affichages. La Class Curseur sert à pointer un Bouton (c'est comme une souris d'ordinateur) La Class Bouton est comme son nom l'indique permet de créer un bouton, on lui donne un curseur et son texte en entrée. Il est obligatoire de mettre entre crochets le texte que vous souhaitez (exemple : "") Exemple de bouton : curseur = Curseur() Bouton(curseur,"[Commencer une partie]") Mais jusqu'à présent tout ça ne sert a rien sans la Class "Interface". Cette Class permet de manipuler facilement les éléments présentés ci-dessus. C'est à dire qu'elle permet de se balader facilement sur un menu par exemple et se charge de l'affichage ainsi que l'ordre de déplacement du curseur sur les Boutons. Pour placer un élément on peut utiliser les fonctions PlaceCenter et Locate. PlaceCenter permet de placer au centre d'une ligne l'élément voulu. (PlaceCenter(élément,ligne) Exemple : interface = Interface() interface.PlaceCenter("Tire du jeu",0) interface.PlaceCenter(Bouton(interface.curseur,"[Commencer une partie]"),4) Quant à Locate, cette fonction permet de placer un élément à des coordonnées exactes. (Locate(élément,ligne,colonne) Exemple : interface = Interface() interface.Locate("Coucou",0,0)#place "coucou" sur le coin supérieur gauche interface.Locate("Coucou",dim[1]-1,0)#place "coucou" sur le coin inférieur gauche Maintenant qu'on a placé les éléments, on peut les afficher, et il existe 3 manières de le faire. -Print -Draw -WaitBouttonInput Print affiche juste l'interface. (cette fonction renvoie None) Quant à Draw, cette fonction effectue un Print puis attend une entrée de l'utilisateur. (cette fonction renvoie l'index du curseur,l'entrée brut et le bouton qui est sélèctionné par le curseur. Pour finir, la fonction WaitBouttonInput (qui est la plus conseillé) attent que l'utilisateur valide sont choix (renvoie l'index du bouton sélèctionner). Exemple: def Confirm(): interface = Interface() interface.PlaceCenter("Voulez-vous quittez ?",0) interface.PlaceCenter(Bouton(interface.curseur," "),3)#index = 0 car initialisé en premier interface.PlaceCenter(Bouton(interface.curseur," "),4)#index = 1 car initialisé en second etc... return interface.WaitBouttonInput() == 0#renvoie True si est sélectionné Comme python est capricieux, il n'existe pas de GetKey, il a fallu créer un système pour contrôler l'interface. Tout d'abord, oubliez la croix directionnelle de votre calculatrice ! La croix directionnelle est remplacée par les touches 2,4,6,8. 8 : Haut 4 : gauche 6 : droite 2 : bas Chaque action doit être validée par la touche EXE (par exemple si vous voulez aller en haut appuyez sur 8 puis EXE) Autrement dit, pour effectuer une action vous devez appuyer sur au moins deux touches. Vous pouvez aussi supprimer les éléments d'une interface en utilisant RemoveWidget. Exemple : interface = Interface() interface.PlaceCenter("coucou",0) interface.RemoveWidget("coucou") Exemple 2 : interface = Interface() btn=Bouton(interface.curseur,"[Commencer une partie]") interface.PlaceCenter(btn,4) interface.RemoveWidget(btn) Maintenant je vais vous présenter d'autre type qui existe : Image et StringVar Oui c'est possible d'afficher des images faites en caractère ascii Exemple : un coffre __________ /\____;;___\ | / / ./_________/ |\ \ | |---------| \ | )) | \|_________| Exemple 2 : Un soldat | _|_ o __ I /|\)_) / \ Le double slash est indispensable donc les images ci-dessus devrai être : player1=""" | _|_ o __ I /|\\)_) / \\ """ chest=""" __________ /\\____;;___\\ | / / ./_________/ |\\ \\ | |---------| \\ | )) | \\|_________| """ Ensuite, il faut transformer cette chaine de caractère en Image donc pour faire ça voici le code : player1_Image=Image(GetImage(player1)) Puis on peut l'afficher sur l'interface avec Locate (PlaceCenter ne fonctionne pas pour les Images) Exemple : player1_Image=Image(GetImage(player1)) interface = Interface() interface.Locate(player1_Image,0,0) Pour finir, la Class StringVar permet de changer le texte de l'interface. Exemple sans StringVar: interface = Interface() interface.PlaceCenter("test",0) interface.RemoveWidget("test") interface.PlaceCenter("test 2",0) Exemple avec StringVar: interface = Interface() txt = StringVar("test") interface.PlaceCenter(txt,0) txt.data = "test 2" Une interface doit toujour contenir au moins un bouton même s'il est invisible Exemple de bouton invisible : interface = Interface() interface.Locate(Bouton(interface.curseur,""),-1,-1) Dans le code intégral vous trouverez trois fonctions supplémentaire : BoiteConfirmValide et BoiteConfirmOK et MainMenu Dont je vous laisse le soin de découvrir leur utilité par vous même. Bug que vous allez sûrement rencontrer : "Maximum recursion depth exceeded" Ce bug arrive quand vous faites trop d'appel d'initiation de class à la suite. Exemple où ça risque de planter : Class A: def __init__(self): pass Class B: def __init__(self): self.a = a() Class C: def __init__(self): self.b = B() Class D: def __init__(self): self.c = C() d= D() Donc pour palier à cela, vous pouvez transformer ce code : class Fight: def __init__(self,plateau,monster): self.interface = Interface() etc... class PlateauDeJeu: def __init__(self,x,y): self.fight = Fight(self,"Monstre1") etc... pdj = PlateauDeJeu(0,0) en : interfaceFight=Interface() class Fight: def __init__(self,plateau,monster): interfaceFight.Clear() self.interface = interfaceFight etc... class PlateauDeJeu: def __init__(self,x,y): self.fight = Fight(self,"Monstre1") etc... pdj = PlateauDeJeu(0,0) Voilà, j'espère que cela vous sera utile. Sat, 24 Jul 2021 19:56:55 +0200 Ma calculatrice ne se mets pas en mode examen https://www.planet-casio.com/Fr/forums/topic16783--.html Je fais comme on nous dit partout de le faire, pour ma graph 35+E, je clique sur cos, 7 et AC/ON en même temps et ça ne fonctionne pas. Problème récurrent avec l'informatique ou je fais exactement ce qu'on me dit de faire mais ça ne marche pas par pure magie. Donc auriez vous s'il vous plaît une explication de ce qui cause ma calculatrice à être dissidente comme ça ? edit : j'ai du censuré le mot examen dans le titre car casio prends pour acquis que tout et chacun des posts faits concernant le mode examen vise a tricher, ce qui est à mon avis completement con et une présomption dangereuse. En vous remerciant d'avance pour votre aide. Tue, 18 May 2021 21:43:13 +0200 [90+E/35+E II] La réinitialisation mémoire c'est bien https://www.planet-casio.com/Fr/forums/topic16702--.html Bonsoir, Voici quelques comparaisons des différences de performances avant et après réinitialisation complète de ma 90+E (les valeurs sont indicatives et varient selon différents critères). Ce document de pseudo-science a juste le but de passer ce conseil à mes compatriotes casionautes avec une calto bordélique : faire une réinitialisation complète de votre calto changera votre vie de voyou et vous rendra attractif et sociable. Et surtout, cela rendra votre expérience de développement d'add-ins extrêmement plus fluide. :here: Démarrage de la calto : 4 secondes avant, 0.5 secondes après :here: Sortie d'un add-in ou retour au menu : 4 secondes avant, 0 secondes après :here: Préparation au transfer par USB : 25 secondes avant, 2 secondes après :here: Terminaison du transfer par USB : 25 secondes avant, 0 secondes après :here: Utilisation du programme « Mémoire » en navigation : 15 secondes avant, 0 après :here: Bien d'autres choses, just do it. Je devine que Casio charge les icones et informations des add-ins à chaque appel au menu (donc au démarrage et à la sortie d'un programme), et que lors des transfers un scan complet des mémoires principales et secondaires est effectué ce qui prend beaucoup de temps. Si vous sentez des ralentissements, essayez de tout réinitialiser. Garantie Kikoo®. Je ne serai pas tenu responsable de vos pertes de données, duh. C'était mon topic inutile de la semaine. Tue, 30 Mar 2021 23:49:48 +0200 [Tutoriel] Compiler des add-ins avec CMake (fxSDK) https://www.planet-casio.com/Fr/forums/topic16647--.html Ce tutoriel explique les bases de CMake et montre comment l'utiliser avec le fxSDK pour compiler des add-ins. L'objectif de ce tutoriel est de donner aux développeurs d'add-ins une compréhension minimale de la compilation de projets, pour vous permettre de maintenir le code lors des évolutions du fxSDK. C'est à la fois un tutoriel à lire de haut en bas et une référence à venir consulter quand vous aurez un doute dans la gestion de vos programmes. :) Le fxSDK a longtemps utilisé un Makefile simple pour compiler les projets. Mais cela avait plusieurs inconvénients, essentiellement parce que les personnes débutant avec les add-ins n'avaient (à juste titre) pas envie ou pas le temps d'apprendre à le maîtriser, ce qui rendait son utilisation et sa mise à jour difficile. Le support de CMake a été introduit avec le fxSDK 2.3 pour résoudre ce problème, car il est plus accessible pour vous et bien plus pratique à maintenir pour moi. Dans ce tutoriel, nous allons voir : • Les fichiers et commandes utilisées pour compiler avec CMake • La syntaxe du langage CMake • Les sources, cibles et dépendances d'un système de compilation • Utiliser des options de compilation et des bibliothèques • La gestion des assets avec fxconv, les g1a et g3a • Un système minimal fonctionnel • L'add-in par défaut du fxSDK, pas-à-pas • Conclusion C'est parti ! :D Les fichiers et commandes utilisées pour compiler avec CMake Le fichier principal qui décrit comment votre add-in doit être compilé est `CMakeLists.txt`. Tout comme le Makefile qu'il remplace, c'est un fichier qui décrit quelles sont les sources, les cibles, et les options. :) La commande `cmake` lance CMake, qui va lire `CMakeLists.txt` et générer un dossier de compilation avec un Makefile contenant les instructions (CMake ne compile pas lui-même). Une fois que c'est fait, on peut lancer `make` dans ce dossier pour compiler le projet. Le dossier de compilation doit absolument être séparé, et du coup le dossier d'un add-in ressemblera généralement à ça (c'est par exemple le cas du projet par défaut du fxSDK) : MonAddIn ├── assets-cg │   └── ... (les assets) ├── assets-fx │   └── ... (les assets) ├── build-cg │   └── ... (les fichiers compilés) ├── build-fx │   └── ... (les fichiers compilés) ├── CMakeLists.txt └── src └── ... (les sources) Le dossier `build-fx` est créé par CMake quand on compile pour Graph mono, et le dossier `build-cg` quand on compile pour Graph 90+E. En principe, on peut lancer CMake avec la commande « `cmake . -B build` » pour compiler le projet situé dans le dossier courant (`.`) et stocker les fichiers compilés dans le dossier `build`. Mais, dans le cas de la calculatrice, il faut ajouter quelques informations en plus : • D'abord il faut indiquer que le compilateur est `sh-elf-gcc`, avec quelques options ; • Et ensuite comme le fxSDK fournit des modules pour vous faciliter la tâche, il faut indiquer où les trouver. Le fxSDK est programmé pour appeler `cmake` avec les bonnes options dans la commande `fxsdk build-fx`. S'il remarque que vous avez un `CMakeLists.txt` mais pas de dossier de compilation, il lance CMake puis make (pour les curieux, la commande complète est là). Si le dossier de compilation existe déjà, il lance juste make. Du coup dans vos projets vous n'aurez souvent besoin que de ces deux commandes. # Compiler pour Graph mono % fxsdk build-fx # Compiler pour Graph 90+E % fxsdk build-cg Sur ce, voyons voir comment `CMakeLists.txt` fonctionne et comment on peut compiler un projet avec. La syntaxe du langage CMake `CMakeLists.txt` est une sorte de programme qui décrit votre projet en appelant des fonctions ou des modules. La syntaxe est la même pour tous les appels, et c'est quelque chose comme ça : nom_de_la_fonction(arg1 arg2 OPTION ARGUMENT valeur OPTION ...) Par exemple, la fonction `install()` permet de spécifier des fichiers à installer. Un appel peut ressembler à ça : install(FILES lib1.h lib2.h DESTINATION "${FXSDK_COMPILER_INSTALL}/include") Il y a deux arguments dans cet appel : • D'abord `FILES lib1.h lib2.h`, qui indique la liste des fichiers à installer. • Et ensuite `DESTINATION "${FXSDK_COMPILER_INSTALL}/include"`, qui indique où on les installe. L'équivalent en Python aurait des arguments nommés et ressemblerait à ça : install(files=["lib1.h","lib2.h"], destination=f"{FXSDK_COMPILER_INSTALL}/include") `FILES` et `DESTINATION` sont des « mots-clés » de la fonction `install()`. Pour pouvoir lire la commande, il faut savoir quels sont les mots-clés pour découper au bon endroit. En général ce n'est pas difficile c'est les mots tout en majuscules ; la liste exacte est donnée dans la documentation de `install()`. Si vous avez un bon éditeur de texte, il les colorera automatiquement pour vous aider. ^^ Pour prendre un autre exemple, la fonction `find_package()` permet de rechercher une bibliothèque ou un outil sur l'ordinateur qui effectue la compilation. Un appel ressemblera à ça : find_package(Gint 2.1 REQUIRED) Ici il y a trois arguments : • D'abord le nom du paquet, « `Gint` », qui est toujours à la première place ; • Ensuite la version « 2.1 », qui doit être à la deuxième place si on l'indique ; • Et enfin l'option `REQUIRED`, indiquant que si gint n'est pas trouvé on veut émettre une erreur. En Python, ça ressemblerait à ça : find_package("Gint", "2.1", required=True) Ces deux exemples montrent les quatre types d'arguments qu'on peut trouver dans les fonctions : • Les arguments positionnels sont à une position fixe, et on donne directement la valeur : « `Gint` ». • Les options sont des mots-clés pour activer ou désactiver des options : « `REQUIRED` ». • Les arguments simples sont formés d'un mot-clé suivis d'une seule valeur : « `DESTINATION un_dossier` ». • Les arguments multiples sont formés d'un mot-clé suivi d'une ou plusieurs valeurs : « `FILES lib1.h lib2.h` ». Toutes les données sont des chaînes de caractères, mais quand il n'y pas de caractères spéciaux on n'est pas obligés de mettre les guillemets. On pourrait écrire `"FILES"` par exemple mais c'est plus léger d'éliminer les guillemets et d'écrire `FILES`. Les points, slashs et autre caractères qu'on trouve habituellement dans les noms de fichiers peuvent être utilisés sans guillemets. Personnellement j'en mets surtout quand il y a des variables à substituer dans la chaîne de caractères, par exemple dans `"${FXSDK_COMPILER_INSTALL}/include"`. La notation `${VAR}` sert à insérer la valeur d'une variable. Au passage, on peut utliser `#` pour ajouter des commentaires qui continuent jusqu'à la fin de la ligne. Avec ça vous devriez pouvoir déchiffrer les CMakeLists.txt sans trop de problèmes. On peut du coup s'attaquer au plat de résistance. ;) Les sources, cibles et dépendances d'un système de compilation Les sources, les cibles (“targets” en anglais), et les dépendances sont trois grands concepts de tout système de compilation. Le but de la compilation est de compiler les sources pour produire les cibles, et de surveiller les dépendances pour recompiler le projet quand des changements sont faits. Typiquement, dans un add-in écrit en C : • La cible est l'add-in final (le fichier .g1a ou .g3a). • Les sources sont les fichiers C que l'on veut compiler. • Les dépendances sont les fichiers C ainsi que les fichiers d'en-tête (les `.h`). Le processus complet consiste à compiler les fichiers C pour produire l'add-in, et si une dépendance (un fichier C ou un en-tête) change, on recompile les fichiers C impactés (ceux qui ont changé ou qui incluent un en-tête qui a changé). ;) Déclarer les cibles, les sources et les dépendances est le travail principal de votre `CMakeLists.txt`. En général vous n'avez pas besoin d'indiquer comment appeler GCC pour compiler puisque CMake sait déjà faire et le fxSDK a fourni les détails spécifiques à la calculatrice : il vous suffit de nommer les fichiers à compiler. Déclarer les cibles et les sources Dans CMake, il y a trois types de cibles et chacun a une fonction servant à le déclarer. • Des exécutables : typiquement des logiciels ou des add-ins. On en crée avec `add_executable()`. • Des bibliothèques que vous pouvez réutiliser dans des exécutables. On en crée avec `add_library()`. • Des cibles personnalisées, pour tout le reste. On en crée avec `add_custom_target()`. Vous pouvez voir que le prototype de `add_executable()`, si on ignore les options utilisées plus rarement, est le suivant. add_executable(<name> [source1] [source2 ...]) Le `<name>` est le nom de votre cible, il vous permet d'identifier la cible dans le reste de `CMakeLists.txt`. Par défaut, c'est aussi le nom du fichier exécutable. Il est entre chevrons donc c'est un argument obligatoire. Ensuite, il y a les sources ; les noms sont entre crochets donc elles sont facultatives (mais un exécutable vide ne sert à rien). Tous ces arguments sont positionnels, il n'y a pas de mot-clé ici. Dans un add-in tout simple, on créerait le fichier exécutable avec une commande comme ci-dessous. add_executable(MonAddin src/main.c) Quasiment tout le système de compilation est contenu dans cette seule commande ! Pour que ça marche, il ne manque à indiquer que le fait de lier avec gint ou fxlib, et de générer le g1a/g3a (ce qui est fait par le fxSDK parce que CMake ne connaît pas ces formats). Je reviens sur ces points bientôt. ^^ Pour une bibliothèque, c'est presque pareil. Voici par exemple ce que fait libprof pour Graph mono : add_library(prof-fx STATIC libprof.c) Ici j'ai utilisé l'option `STATIC` pour créer une « bibliothèque statique ». Sinon CMake serait tenté de créer une « bibliothèque dynamique », un autre genre courant sur ordinateur mais bien plus compliqué et qu'on n'a pas sur la calculatrice. Dans l'ensemble le principe est le même, et là aussi CMake gère toute la suite. Si vous regardez le prototype de `add_custom_target()` vous verrez que c'est un peu plus compliqué, c'est parce que cette fois vous devez indiquer les commandes à lancer pour produire la cible. Vous n'en aurez que rarement voire jamais besoin. ^^ Déclarer les dépendances Les dépendances ce sont les fichiers qui impactent le résultat de la compilation (on dit que le résultat de la compilation dépend de ces fichiers). Chaque fois qu'une dépendance change, il faut recompiler pour s'assurer que le résultat est à jour. Il y a plusieurs types de dépendances, souvent vous aurez affaire à une de celles-là : • Les dépendances qui affectent la compilation d'un fichier C sont ce fichier C, les en-têtes qu'il incluent, les en-têtes que ces en-têtes incluent, et ainsi de suite. • Les dépendances qui affectent la conversion d'un asset sont l'asset lui-même et ses métadonnées pour fxconv (j'y reviendrai). • Les dépendances qui affectent l'add-in final, en plus des sources et des assets, sont les bibliothèques, le `CMakeLists.txt`, et quelques autres détails. La bonne nouvelle c'est que CMake s'occupe tout seul de déclarer la plupart de ces dépendances ! On n'a que très rarement besoin de le faire à la main. En particulier, le mécanisme un peu compliqué utilisé dans les Makefile pour rechercher les en-têtes inclus et obtenir les dépendances est géré tout seul par CMake. Dans votre `CMakeLists.txt` vous n'aurez quasiment jamais besoin de mentionner vos fichiers d'en-tête, car CMake va automatiquement les rechercher lorsqu'il liste les dépendances. Si jamais vous avez besoin de déclarer des dépendances supplémentaires, jetez un oeil à `set_source_files_properties()` et `set_target_properties()`. Comme vous pouvez le voir, la déclaration des sources, cible et dépendances ne demande pas beaucoup d'efforts en général. On va quand même s'attarder sur les options de compilation dont vous pourrez avoir besoin si votre projet grandit. Utiliser des options de compilation et des bibliothèques Lorsque vous compilez un programme, vous pouvez modifier le comportement de GCC de différentes façons : afficher plus de warnings ou moins de warnings, activer des optimisations, choisir la version exacte du langage C que vous utilisez... tout cela se fait avec des options de compilation. Dans CMake, les options de compilation sont définies pour une cible à l'aide de la fonction `target_compile_options()` qui a le prototype (simplifié) suivant : target_compile_options(<cible> <PUBLIC|PRIVATE|INTERFACE> <options...>) Le premier arguent est la cible à laquelle les options vont s'appliquer. Le deuxième indique dans quel contexte les options doivent être utilisées : • `PRIVATE` active les options durant la compilation de la cible (le cas de base) ; • `INTERFACE` active les options durant la compilation de fichiers qui utilisent la cible (quand la cible est une bibliothèque) ; • `PUBLIC` fait les deux à la fois. Et enfin, viennent les options sous la forme d'arguments en ligne de commande, par exemple `-Wall` pour activer (presque) tous les warnings, ou `-O2` pour optimiser le vitesse du programme au niveau 2. Dans le projet par défaut du fxSDK, on a les options suivantes : target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) Cela active les options `-Wall`, `-Wextra` et `-Os`, qui activent un bon paquet de warnings et l'optimisation vitesse/taille du programme. `myaddin` est le nom de la cible, celui qui est donné comme premier argument à `add_executable()`. ;) Pour les bibliothèques, c'est similaire. La différence est qu'il faut commencer par les trouver, ce qu'on fait avec la fonction `find_package()`. Son prototype (simplifié) est le suivant : find_package(<name> ) Le premier argument est le nom de l'outil qu'on cherche ; le second (optionnel) est la version qu'on l'on souhaite utiliser, et si l'option `REQUIRED` est activée mais l'outil n'est pas trouvé CMake échouera avec une erreur. Si une version plus récente mais compatible avec celle demandée est trouvée, elle sera utilisée. Par exemple, un add-in qui utilise gint avec des fonctionnalités de la version 2.1 pourra indiquer : find_package(Gint 2.1 REQUIRED) Le paquet fournit ses propres cibles, dans le cas de gint il fournit une cible `Gint` que l'on désigne en la préfixant du nom du paquet, ce qui donne `Gint::Gint`. Pour compiler votre programme avec, utilisez `target_link_libraries()` : target_link_libraries(<cible> <bibliothèques...>) Un exemple tout simple pour lier avec gint serait donc : target_link_libraries(myaddin Gint::Gint) Vous pouvez spécifier plus d'une bibliothèque d'un coup, et vous n'êtes pas obligés d'utiliser des cibles CMake : vous pouvez écrire directement `-lsomelib` ou donner le nom d'un fichier `.a`, ça convient aussi tout à fait. ^^ Avec ça vous êtes parés pour accomplir à peu près toutes les tâches usuelles. Il nous reste un seul point supplémentaire spécifique aux add-ins sur la calculatrice à voir : la gestion des assets et la génération des fichiers g1a et g3a. La gestion des assets avec fxconv, les g1a et g3a Les assets (images, polices, maps, dialogues, et autres données de votre application) ne sont pas gérés par CMake d'une façon aussi directe que `add_executable()`. Le fxSDK fournit des outils pour que ça reste transparent pour vous, mais je vais profiter de l'occasion pour détailler un peu comment créer des parties personnalisées dans le système de compilation. ;) Un concept très utile de CMake des ces situations est les modules. Vous pouvez inclure des fichiers externes dans votre `CMakeLists.txt`, y compris des fichiers distribués hors du projet. Le fxSDK fournit notamment : • `Fxconv.cmake` pour déclarer des assets à convertir avec fxconv. • `GenerateG1A.cmake` et `GenerateG3A.cmake` pour générer des fichiers g1a et g3a pour des exécutables. On inclut un module avec la fonction `include()` qui est aussi simple que : include(<file|module>) Par exemple, le module `Fxconv.cmake` peut être inclus de la façon suivante (parce que le fxSDK indique à CMake que le dossier où `Fxconv.cmake` est stocké contient des modules). include(Fxconv) Actuellement ce module définit un nouveau langage `FXCONV` pour les assets, dont la commande de compilation appelle fxconv, et fournit une fonction `fxconv_declare_assets()` qui vous permet de lister vos fichiers d'assets pour qu'ils soient traités correctement par CMake. Concrètement, pour traiter un fichier d'asset il faut faire deux choses : • Indiquer que son langage est `FXCONV` pour qu'il soit compilé avec fxconv et pas GCC ; • Indiquer une dépendance de l'asset vers le `fxconv-metadata.txt` du même dossier. La dépendence existe car `fxconv-metadata.txt` (le fichier qui remplace le système bancal utilisé dans `project.cfg`) modifie les paramètres de la conversion, donc le résultat. Si on change les métadonnées, il faut reconvertir l'asset même si le fichier source (par exemple une image ou une police) n'a pas changé. Ces deux informations (le langage et les dépendances d'un fichiers source) sont des propriétés du fichier source dans CMake, et on peut les modifier avec `set_source_files_properties()`. Si vous êtes curieux, voici comment le module `Fxconv` modifie le langage et la dépendance. Et en fait c'est tout ! Les assets sont maintenant traités dans des fichiers sources dans `add_executable()` ou `add_library()` et seront simplement compilés avec fxconv au lieu de GCC. On peut donc mélanger les fichiers C et les assets et écrire : fxconv_declare_assets(assets-fx/example.png WITH_METADATA) add_executable(myaddin src/main.c assets-fx/example.png) La fonction `fxconv_declare_assets()` prend en paramètre une liste de fichiers d'assets. L'option `WITH_METADATA` ajoute la dépendance (c'est ce que vous voulez la plupart du temps). Pour les fichiers g1a et g3a, c'est à peu près la même histoire, vous incluez le module et appelez la fonction qui convient pour générer un fichier g1a ou g3a après la compilation de votre exécutable. include(GenerateG1A) generate_g1a(TARGET <cible> [OUTPUT <fichier>] ...) La cible est le nom de votre cible exécutable (le premier argument de `add_executable()`). `OUTPUT` permet de choisir le nom du fichier de sortie ; et ensuite viennent les options du g1a, toutes facultatives : • `NAME <nom>` pour indiquer le nom de l'add-in dans le menu SYSTEM ; • `INTERNAL <nom interne>` pour indiquer le nom interne (en général vous n'avez pas besoin de l'indiquer) ; • `VERSION <MM.mm.pppp>` pour donner la version du programme ; • `DATE <YYYY.mmdd.hhmm>` pour la date de compilation (la valeur par défaut est la date du jour) ; • `ICON <image>` pour choisir l'icône (qui doit être un fichier PNG de 30x19 pixels). include(GenerateG3A) generate_g3a(TARGET <cible> [OUTPUT <fichier>] ...) Le fonctionnement pour les g3a est identique. Il y a un peu moins d'options car mkg3a ne donne pas accès à tous les détails : • `NAME <nom>` pour indiquer le nom de l'add-in. Le nom est aussi affiché sur le menu principal, mais parfois on n'en veut pas. Vous pouvez indiquer un nom vide en écrivant « `NAME ""` » pour que l'icône soit affichée sans texte par dessus. • `ICONS <icone-unselected> <icon-selected>` pour donner les icônes (deux images PNG de 92x64 pixels). Voilà ce que ça donne dans le projet par défaut. :) # Pour Graph mono generate_g1a(TARGET myaddin OUTPUT "MyAddin.g1a" NAME "MyAddin" ICON assets-fx/icon.png) # Pour Graph 90+E generate_g3a(TARGET myaddin OUTPUT "MyAddin.g3a" NAME "MyAddin" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) Un système minimal fonctionnel Avec ça, on peut maintenant compiler un add-in pour de vrai ! Voici le plus petit système de compilation d'add-in pour Graph mono avec CMake. ;) cmake_minimum_required(VERSION 3.18) project(MyAddin) include(GenerateG1A) include(Fxconv) find_package(Gint 2.1 REQUIRED) fxconv_declare_assets(assets-fx/example.png) add_executable(myaddin src/main.c assets-fx/example.png) target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) target_link_libraries(myaddin Gint::Gint) generate_g1a(TARGET myaddin OUTPUT "MyAddin.g1a" NAME "MyAddin" ICON assets-fx/icon.png) Comme vous pouvez le voir, c'est simplement un combinaison de tout ce qu'on a vu jusqu'ici. Il n'y a que deux nouveautés dont il faut s'occuper au début de `CMakeLists.txt` : d'abord `cmake_minimum_required()` pour indiquer la version de CMake que vous suivez (les fonctions ont changé au cours du temps), et puis `project()` pour nommer le projet (on peut aussi donner sa version et indiquer les langages si besoin). Vous pouvez coller ça dans votre `CMakeLists.txt` et lancer `fxsdk build-fx`, vous aurez votre `MyAddin.g1a`. :) L'add-in par défaut du fxSDK, pas-à-pas Le `CMakeLists.txt` que le fxSDK vous donne dans les nouveaux projets est un poil plus compliqué (il permet notamment de compiler pour Graph mono et Graph 90+E), alors voici les détails pas-à-pas ! Le début commence exactement comme on l'attend, en incluant les modules et gint. # Configure with [fxsdk build-fx] or [fxsdk build-cg], which provide the # toolchain file and module path of the fxSDK cmake_minimum_required(VERSION 3.18) project(MyAddin) include(GenerateG1A) include(GenerateG3A) include(Fxconv) find_package(Gint 2.1 REQUIRED) Ensuite on définit quelques variables pour spécifier les fichiers sources, les assets communs Graph mono/Graph 90+E, les assets spécifiques à la Graph mono, et les assets spécifiques à la Graph 90+E. set(SOURCES src/main.c # ... ) # Shared assets, fx-9860G-only assets and fx-CG-50-only assets set(ASSETS # ... ) set(ASSETS_fx assets-fx/example.png # ... ) set(ASSETS_cg assets-cg/example.png # ... ) Je n'ai pas encore parlé des variables même si quelques-unes sont utilisées dans les exemples précédents. C'est assez direct : • On peut créer ou modifier une variable avec `set()` : `set(<nom> <valeur>)`. • On peut obtenir la valeur d'une variable avec `${nom}` (en général entre guillemets pour ne pas être embêté s'il y a des espaces ou points-virgules dans les contenus). Voici un exemple tout simple. `message()` est juste un print, c'est utile pour debugger : set(MA_VARIABLE "du texte") message("MA_VARIABLE contient ${MA_VARIABLE}") Ce code affiche "MA_VARIABLE contient du texte" quand CMake est lancé. Dans le projet, on utilise une fonctionnalité de `set()` qui permet de spécifier plusieurs valeurs pour faire une « liste » ; c'est une fausse liste, les valeurs sont juste séparées par des points-virgules. set(SOURCES src/main.c src/game.c) message("${SOURCES}") # -> affiche "src/main.c;src/game.c" Ensuite on déclare les assets, comme précédemment. fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA) Ici on ne met pas de guillemets autour des variables, c'est fait exprès : comme ça la liste sera « déroulée » en une liste d'arguments (un peu comme `fonction(*liste)` en Python). Si ça vous échappe ne vous inquiétez pas trop. ^^ Ensuite, on crée la cible exécutable. C'est là qu'on voit apparaître des différences entre Graph mono et Graph 90+E. Ce dont il faut se souvenir c'est que le `CMakeLists.txt` sera exécuté deux fois : une fois pour Graph mono quand on utilise `fxsdk build-fx`, et une fois pour Graph 90+E quand on utilise `fxsdk build-cg`. Il n'y a donc besoin de se soucier que d'une seule plateforme à la fois, et le fxSDK indique laquelle avec deux variables : • `FXSDK_PLATFORM` vaut « `fx` » quand on compile pour Graph mono et « `cg` » quand on compile pour Graph 90+E. • `FXSDK_PLATFORM_LONG` vaut « `fx9860G` » quand on compile pour Graph mono et « `fxCG50` » quand on compile pour Graph 90+E. La deuxième est plus lisible mais la première est pratique dans certains cas. Par exemple, dans la cible exécutable qu'est notre add-in, on veut ajouter uniquement les assets de la platforme courante, ce qu'on peut faire élegamment avec `FXSDK_PLATFORM`. add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) target_link_libraries(myaddin Gint::Gint) Tout comme dans `fxconv_declare_assets()`, on passe les listes de sources et assets en argument (donc sans guillemets). `${ASSETS_${FXSDK_PLATFORM}}` devient `${ASSETS_fx}` ou `${ASSETS_cg}` selon la plateforme pour laquelle on compile, ce qui permet de choisir élégamment la bonne liste d'assets. Les sources de la cible sont donc les fichiers C, les assets communs, et les assets spécifiques à la plateforme à laquelle on est en train de s'intéresser. Ensuite on ajoute les options de compilation et on linke avec gint, rien d'inattendu ici. if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) generate_g1a(TARGET myaddin OUTPUT "MyAddin.g1a" NAME "MyAddin" ICON assets-fx/icon.png) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) generate_g3a(TARGET myaddin OUTPUT "MyAddin.g3a" NAME "MyAddin" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) endif() Et enfin on génère un fichier g1a ou g3a. On utilise `if()` pour tester la plateforme, et on utilise `generate_g1a()` ou `generate_g3a()` selon le cas. La syntaxe du if n'est pas vraiment intuitive, on ne peut pas écrire des conditions avec `==`, `<=` ou `!=` comme dans les langages de programmation ; à la place il faut tester avec des mots-clés comme `STREQUAL`. C'est un peu comme `test` en bash (pour ceux qui connaissent). Dans l'ensemble, consultez la documentation en cas de doute. Et voilà, vous savez maintenant comment `CMakeLists.txt` fonctionne dans votre add-in, et vous êtes équipé·e pour aborder sereinement sa modification pour répondre à vos besoins futurs. ;) Conclusion CMake est un système de compilation riche et avec sa part de complexité, mais qui présente aux débutants des moyens simples et directs pour gérer la compilation de programmes. Dans ce tutoriel, on a vu comment un add-in pour la calculatrice pouvait se compiler avec CMake et le fxSDK, en couvrant tant le code source que les assets, les options de compilation, et l'utilisation de bibliothèques. J'espère que ce tutoriel vous aura permis de comprendre et maîtriser votre système de compilation, et ainsi de vous faciliter la gestion de projet au cours des évolutions à la fois de vos programmes et des outils comme le fxSDK. ;) Fri, 29 Jan 2021 15:29:51 +0100 TDM 20 : Comprendre et utiliser le PATH sous Linux https://www.planet-casio.com/Fr/forums/topic16644--.html Le Tutoriel du Mercredi (TDM) est une idée proposée par Ne0tux, qui recouvre tous les usages de la calculatrice - des applications de Casio à la conception de jeux en passant par la production artistique. Aujourd'hui, on explique le fonctionnement du PATH et son rôle dans l'installation de logiciels sous Linux. Niveau ★ ☆ ☆ ☆ ☆ Tags : Linux, Shell Les membres réguliers du forum sont divisés grossièrement 50%-50% entre Windows et Linux comme système principal. Il n'est donc pas rare de croiser des logiciels à installer sous Linux, et dans mon expérience l'utilisation du PATH est un des points qui pose le plus souvent problème durant ces installations. Je pense qu'il est largement temps d'avoir un petit tutoriel pour expliquer de quoi il retourne et comment s'en servir. ^^ Comme à mon habitude, j'essaie d'expliquer les raisons de fond donc n'hésitez pas à parcourir le tuto même si vous connaissez le PATH, vous pourriez y apprendre quelque chose d'autre. :) Introduction au terminal et au shell Lorsque vous lancez un terminal sous Linux, vous vous retrouvez face à un shell. Le shell est un programme qui vous permet de manipuler des fichiers, lancer des programmes, les faire communiquer... c'est une interface texte qui vous permet d'utiliser tout ce qui est installé sur l'ordinateur. On utilise le shell en tapant des commandes, ce qui donne par exemple le résultat ci-dessous : [el@realm ~]$ ls -l ~/Documents/PC/Tutoriels total 36 -rw-r--r-- 1 el el 20337 May 10 2020 compilation-gcc.txt drwxr-xr-x 2 el el 4096 Oct 24 2019 exclude -rw-r--r-- 1 el el 1363 Jan 26 14:52 fxsdk-cmake.txt -rw-r--r-- 1 el el 764 Jan 26 14:56 linux-path.txt drwxr-xr-x 2 el el 4096 May 21 2020 mumble [el@realm ~]$ Dans cet exemple, le shell a commencé par afficher un « prompt » (ou « invite de commandes »), c'est le « `[el@realm ~]$` ». Le prompt indique qui je suis (l'utilisateur `el` sur la machine `realm`) et où je suis (`~`, c'est-à-dire mon dossier personnel). On dit « invite de commandes » parce que le shell m'invite à taper une commande pour travailler. J'ai ensuite tapé la commande « `ls -l ~/Documents/PC/Tutoriels` », que l'on peut découper en deux parties : • Le premier mot `ls` est le nom d'un programme à lancer. `ls` est un programme qui affiche les contenus d'un répertoire. • Les autres mots sont des arguments, qui disent au programme ce qu'on veut faire exactement. Ici j'ai indiqué l'option `-l` (qui signifie long et demande à `ls` d'afficher des détails) et `~/Documents/PC/Tutoriels`, le chemin du dossier dont je veux connaître les contenus. Le programme `ls` a ensuite répondu en affichant les contenus du dossier souhaité. `ls` a généré tout le texte de la ligne « total 36 » à la fin de la ligne « mumble » puis s'est arrêté. La commande étant finie, le shell a affiché de nouveau le prompt pour m'inviter à saisir une autre commande. Les programmes du shell sont des fichiers `ls` n'est pas une commande intégrée au shell. C'est un programme installé indépendamment sur l'ordinateur, et qui dans une situation extrême pourrait ne pas être installé. Et donc une question naturelle se pose : comment le shell a-t-il déterminé si `ls` était installé, et si oui comment l'a-t-il trouvé ? Pour répondre à ces questions, il faut comprendre ce que `ls` est exactement. En fait, `ls` est un fichier exécutable. Sous Windows, il s'appelerait probablement `ls.exe`, mais sous Linux les fichiers exécutables n'ont traditionnellement pas d'extension, donc il s'appelle juste `ls`. C'est un fichier qui contient du code qui affiche les contenus d'un répertoire. Comme tout fichier, `ls` est quelque part dans un répertoire. On peut demander au shell où il l'a trouvé avec `command -v`. [el@realm ~]$ command -v ls /usr/bin/ls [el@realm ~]$ Ici la commande complète est « `command -v ls` ». Le shell a donc lancé le programme `command` avec l'option `-v` et l'argument `ls`. Lorsque l'option `-v` est donnée, `command` cherche un programme et affiche le dossier dans lequel il se trouve. Ici, le chemin complet vers le fichier exécutable `ls` est donc `/usr/bin/ls`. (Note pour les curieux : contrairement à `ls`, `command` est un programme intégré au shell et n'est pas donc pas dans un fichier.) Il en va de même pour tous les programmes, et je peux par exemple trouver le répertoire dans lequel le programme `sh-elf-gcc` est installé. [el@realm ~]$ command -v sh-elf-gcc /home/el/.local/bin/sh-elf-gcc [el@realm ~]$ Cette fois c'est dans mon dossier personnel (`/home/el` est mon dossier personnel), dans un sous-dossier caché (le `.` devant `.local` en fait un dossier caché). Maintenant que l'on sait que la plupart des programmes sont des fichiers, on va pouvoir comprendre le PATH. Le shell cherche les programmes dans les dossiers du PATH Le PATH (littéralement « chemin » en anglais) est une liste de dossiers. Plus précisément, c'est la liste des dossiers dans laquelle le shell va chercher les programmes. On peut consulter cette liste à l'aide de la commande « `echo $PATH` » (que j'expliquerai ensuite). [el@realm ~]$ echo $PATH /home/el/opt/i686-elf-2.32-8.3.0/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/home/el/bin:/home/el/opt/bin:/home/el/.local/bin [el@realm ~]$ Les noms des dossiers sont séparés par des deux-points « `:` ». Il y a 7 dossiers dans mon PATH, ce qui signifie que si je tape une commande « `sh-elf-gcc` » le shell va regarder si un des 7 fichiers suivants existe (et si oui lancer le premier qui existe) : • `/home/el/opt/i686-elf-2.32-8.3.0/bin/sh-elf-gcc` • `/usr/local/sbin/sh-elf-gcc` • `/usr/local/bin/sh-elf-gcc` • `/usr/bin/sh-elf-gcc` • `/home/el/bin/sh-elf-gcc` • `/home/el/opt/bin/sh-elf-gcc` • `/home/el/.local/bin/sh-elf-gcc` Sur mon ordinateur, les 6 premiers fichiers n'existent pas, et le 7ème existe, donc lorsque je tape `sh-elf-gcc` dans une commande le shell lance le fichier exécutable `/home/el/.local/bin/sh-elf-gcc`. ;) À l'aide de ces nouvelles informations, on peut répondre aux questions de tout à l'heure. Comment le shell a-t-il déterminé si `ls` était installé ? Le shell a simplement cherché `ls` dans chaque dossier du PATH. Le shell ne cherche pas vraiment à savoir si `ls` est installé, c'est plutôt à `ls` de s'assurer que son dossier est dans le PATH pour que le shell le trouve. Si, comment l'a-t-il trouvé ? La valeur du PATH contenait le dossier où se trouve le fichier exécutable `ls` (c'est-à-dire `/usr/bin`) et donc le shell a pu trouver `ls`. Le dossier d'installation des programmes du forum n'est souvent pas dans le PATH Le dossier où se trouve `ls`, `/usr/bin`, est un dossier système quel seul l'administrateur peut modifier. Normalement il n'y a que le gestionnaire de paquets, un programme chargé de superviser l'installation et la mise à jour de tous les programmes sur l'ordinateur, qui est supposé ajouter des fichiers dans `/usr/bin`. C'est parce que sous Linux, on n'installe pas des logiciels en téléchargeant un `setup.exe` sur son site web (ce qui est sauvage). À la place, les logiciels sont distribués sous la forme de « paquets » et installés par le gestionnaire de paquets. ^^ Lorsque quelqu'un crée un programme sur le forum, on pourrait à chaque fois le partager sous forme de paquet pour que les autres membres du forum l'installent avec leur gestionnaire de paquets. Le problème c'est qu'il existe plusieurs genres de paquets et que distribuer des paquets demande beaucoup de temps et d'effort, parfois plus que d'écrire le programme qu'on veut partager ! Certains comme Dark Storm prennent ce temps, d'autres comme moi pensent que ça n'en vaut pas la peine. En pratique, la plupart des logiciels du forum ne sont pas empaquetés ; du coup on ne peut pas les installer avec le gestionnaire de paquets, et donc on ne peut pas les installer dans le répertoire `/usr/bin`. Il faut donc les installer ailleurs, et ce que j'ai vu de plus courant c'est de les installer dans `~/.local/bin`. (Rappelez-vous que `~` représente votre dossier personnel, donc c'est dans un sous-dossier `.local` à côté de `Documents`, `Images`, etc. Il est juste caché parce que son nom commence par un point.) C'est un dossier approprié et plus ou moins standardisé pour permettre d'installer des logiciels en-dehors du `/usr/bin` réservé au gestionnaire de paquets. Si ce n'est pas exactement `~/.local/bin` alors ça peut être un autre endroit dans votre dossier personnel. Il y a cependant un petit problème : lorsque vous installez Linux (ou WSL sous Windows), en général le PATH ne contient pas `~/.local/bin`. Ça veut dire que le shell ne trouvera pas les programmes installés là-bas ! À la place, vous aurez une erreur de ce style : [el@realm ~]$ sh-elf-gcc bash: sh-elf-gcc: command not found [el@realm ~]$ Et `command -v` aussi vous indiquera que le fichier est introuvable en n'affichant rien. [el@realm ~]$ command -v sh-elf-gcc [el@realm ~]$ Dans cette situation, il est nécessaire d'ajouter le nouveau dossier d'installation au PATH. Voyons tout de suite comment faire ! :) Modifier une variable d'environnement, `.bashrc` et `.profile` Pour comprendre comment modifier le PATH, il est utile de comprendre d'abord ce que c'est exactement. Le PATH est une variable d'environnement. Les variables d'environnement indiquent aux programmes lancés sur l'ordinateur dans quel contexte ils sont lancés. Par exemple, la variable d'environnement USER indique qui a lancé le programme, et la variable HOME indique où est le dossier personnel de USER. Les variables d'environnement ont traditionnellement des noms en majuscules, et les valeurs sont juste des chaînes de caractères. PATH est une de ces variables. Chaque processus a son propre environnement, donc si on veut modifier PATH de façon pérenne il faut le faire d'une façon qui affecte tous les shells. On dispose de deux outils pour ça : • Le fichier `~/.bashrc` est lu par le shell au démarrage d'un terminal, et affecte tous les terminaux ; • Le fichier `~/.profile` est lu par le shell au démarrage de la session, et affecte toute la session, même les programmes lancés hors d'un terminal. (Note : ces deux fichiers sont utilisés par le shell le plus courant sous Linux, bash. Si vous utilisez un autre shell les noms peuvent varier, mais dans ce cas vous savez certainement déjà vous y prendre.) Ces deux fichiers sont juste une suite de commandes shell (ça ressemble à un programme). Ce qui nous intéresse, c'est d'y ajouter une commande qui rajoute un dossier au PATH pour que les programmes qu'on installe puissent être trouvés quand on voudra les lancer. La commande qui permet de faire ça est `export`. export PATH="$PATH:$HOME/.local/bin" La syntaxe de la commande est `export VARIABLE="VALEUR"`. Ici, on change la variable d'environnement `PATH`, et on lui donne la valeur `$PATH:$HOME/.local/bin`. Lorsque la commande sera lancée `$PATH` sera remplacé par la valeur actuelle du chemin (comme dans « `echo $PATH` » tout à l'heure) et donc la nouvelle valeur sera la valeur actuelle à laquelle on ajoute `$HOME/.local/bin`. (Dans ce tutoriel, j'ai utilisé de façon interchangeable pour désigner mon dossier personnel « `~` », « `$HOME` » et « `/home/el` ». Le troisième est le nom exact et ne marchera pas chez vous (votre nom d'utilisateur est certainement différent). `$HOME` est la « bonne » façon de désigner le dossier personnel, et elle marche partout. « `~` » est un raccourci pratique mais pour différentes raisons il ne marchera pas dans `export`. Il faut donc bien utiliser `$HOME`.) Je vous conseille de mettre les commandes concernant le PATH dans `~/.profile`, car dans de rares occasions vous pouvez vouloir appeler un programme sans ouvrir un terminal, et dans ce cas il faut avoir modifié le PATH au niveau de la session. Vous pouvez le faire en ouvrant le fichier dans un éditeur de texte (si votre explorateur de fichiers ou éditeur de texte ne le montre pas, vous pouvez essayer le raccourci `Ctrl+H` qui affiche les fichiers cachés dans certains outils). Sinon, comme pour tout, vous pouvez le faire dans un terminal avec la commande suivante. echo "export PATH=\"\$PATH:MON_DOSSIER\"" >> $HOME/.profile Remplacez « `MON_DOSSIER` » par le chemin absolu du dossier, par exemple « `$HOME/.local/bin` ». • Si vous modifiez `~/.bashrc`, le nouveau PATH sera utilisé automatiquement dans tous les nouveaux terminaux (les terminaux déjà ouverts ne sont pas affectés). • Si vous modifiez `~/.profile`, le nouveau PATH sera utilisé à la prochaine connexion. Fermez votre session ou redémarrez l'ordinateur. Vous pouvez à tout moment utiliser la commande « `echo $PATH` » pour inspecter le PATH, et `command -v` pour rechercher le fichier correspondant à n'importe quel programme. :) Conclusion Le PATH est une liste de dossiers dans lesquels le shell recherche les programmes lorsqu'on exécute des commandes. Lorsqu'on installe des programmes, il faut s'assurer que le dossier d'installation soit dans le PATH, sinon le shell ne trouvera pas les programmes. Le PATH est une variable d'environnement, que l'on peut modifier à l'échelle de tous les terminaux à l'aide de `~/.bahsrc` ou à l'échelle de toute la session à l'aide de `~/.profile`. La commande qui ajoute un dossier `MON_DOSSIER` avec `export` est la suivante. export PATH="$PATH:$HOME/.local/bin" J'espère que ce tutoriel vous aura aidé à comprendre le PATH pour bien gérer l'installation de nouveaux logiciels. o/ Et à bientôt sur Planète Casio ! ;) Consulter le TDM précédent : TDM 19 : Appréhender la mémoire pour éclairer le bas niveau Consulter l'ensemble des TDM Wed, 27 Jan 2021 14:27:02 +0100 Moteur physique: Simuler les frottements https://www.planet-casio.com/Fr/forums/topic16598--.html Lorsque l'on crée un platformer ou tout autre jeu utilisant des notions de mécanique, lorsqu'on arrive à la gestion des frottements, c'est souvent avec un peu de bidouille que l'on arrive à de bons réglages. :E Comme les frottements sont une notion en physique que l'on ne voit pas au lycée, j'ai poussé un script python (initialement réalisé pour KikooDX) permettant de simuler et visualiser les résultats en fonction des différents paramètres (masse, coefficient de friction, vitesse initiale etc) Le code est ici : https://gitea.planet-casio.com/Milang/simulation-frottements/ Il suffit d'appeler la fonction `simul(alpha,accel,masse)` où `alpha` représente le coefficient de friction (strictement positif, plus il est petit plus les frottements sont faibles), et `accel` l'accélération que subirait l'objet s'il n'y avait pas de frottements. La masse peut être mise à 1 pour simplifier le problème surtout si on ne s’intéresse qu'à un seul objet ;) Le script est la pour vous donner une idée du résultat en fonction des différents paramètres, et peut aussi servir dans l'autre sens pour mesurer la précision du moteur physique. :) Voila, si vous avez des questions sur les connaissances physiques mises en jeu derrière je suis la pour répondre (ou bien pour me corriger la dessus car je ne suis pas celui qui a le plus de connaissances la dessus ici :E ) Tue, 22 Dec 2020 18:23:02 +0100