Planète Casio - Projets de programmation - 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 - Projets de programmation - Flux RSS http://www.planet-casio.com 55 50 Programmes Casio, Jeux, Cours pour Calculatrices Casio. Mon, 27 Jun 2022 05:13:18 GMT Mon, 27 Jun 2022 05:13:18 GMT contact@planet-casio.com (Planet Casio) contact@planet-casio.com (Planet Casio) 5 BUILDER - Un jeu de construction comme minecraft et terraria. https://www.planet-casio.com/Fr/forums/topic17108--.html Je me suis dit qu'il n'y avait pas beaucoup de jeux de construction stables en add-in sur Graph, donc je me suis dit d'en faire un moi-même. https://gitea.planet-casio.com/mibi88/Builder Un terrain généré : https://www.planet-casio.com/storage/forums/gentest4-17108.png 24/06/2022 : Générateur de terrain fonctionnel. 26/06/2022 : Générateur de terrain amélioré. Fri, 24 Jun 2022 20:07:30 +0200 Sujet à polémique et discussion - les pointeurs en C/C++ https://www.planet-casio.com/Fr/forums/topic17096--.html Hello, grave question existentielle que celle qui va suivre : comment déclarer "proprement" les pointeurs en C/C++ ? Quelle syntaxe faut il utiliser ? Ne vous êtes vous jamais demandés lors de vos lectures de code pourquoi certains déclarent leurs pointeurs ainsi : int* p; alors que d'autres les déclarent ainsi : int *p; et que les moins téméraires les déclarent tels l'ONU, sans prendre de position, ainsi : int * p; bref, qui a tord, qui a raison ?!? D'un point de vue fonctionnel, c'est Ok quand on a une simple déclaration d'une seule variable de type pointeur, mais il y a des subtilités. Ainsi écrire : int* p, q; laisse penser que p et q sont tous les deux des pointeurs vers des int, car l'operateur de déréférencement (*) est accolé au type int, donc en toute logique on déclare deux variables de type (int*), et bien non, perdu !!! Dans les fait, on obtient p de type pointeur vers int et q de type int (pas pointeur vers int) ... la bonne blague (et la source de bug). Il s'emblerait donc que la syntaxe à utiliser soit plutôt type *variable1, variable2, *variable3; Qu'en pensez vous ? Sly Thu, 09 Jun 2022 14:56:22 +0200 Essai de communication via port Serial 3-pins CG10/20/50 https://www.planet-casio.com/Fr/forums/topic17077--.html Hello, ayant juste un petit peu de temps, cette fin de semaine avant d'être une semaine off-line, je voulais regarder un peu la libsnd et le port serial 3-pins. Je me suis donc imprégné de la documentation que j'ai pu trouver ici et là. Mes recherches m'ont permis d'identifier les sources suivantes : - les sources de la libsnd de Thomas Williamson (utilisée dans l'excellentissime Nesizm) et du PrizmSDK - la doc de la bible PC collectée par Simon Lothar (partie CG20 - Serial) dispo ici : serial CG20 - l'explication de texte des syscalls correspondants dans le Wiki de Cemetech ici : wiki Serial A partir de cela, je me suis fait une mini-librairie (je sais, c'est maladif en ce moment :E ) appelée libserial (original, vous ne trouvez pas) qui reprend les syscalls suivants directement liés au port serial 3-pins, ainsi que le header correspondant (serial.h) : - Serial_ClearRX - Serial_ClearTX - Serial_Close - Serial_IsOpen - Serial_Open - Serial_Peek - Serial_PollRX - Serial_PollTX - Serial_Read - Serial_ReadSingle - Serial_Write - Serial_WriteSingle - Serial_WriteUnbuffered ainsi que les suivants, plus ou moins éloignés, mais repris dans le prizmSDK (je les virerais si il ne servent effectivement pas) : - App_LINK_GetDeviceInfo - App_LINK_GetReceiveTimeout_ms - App_LINK_Send_ST9_Packet - App_LINK_SetReceiveTimeout_ms - App_LINK_SetRemoteBaud - App_LINK_TransmitInit - App_LINK_Transmit - Comm_Close - Comm_Open - Comm_Terminate - Comm_TryCheckPacket Pour vérifier que tout fonctionne, j'ai fait un simple petit programme pour vérifier l'état du port serial (ouvert et / ou fermé), puis procéder à son ouverture et à sa fermeture, tout cela sur ma CG50 (Graph 90+E) et ma CG20 pour vérifier que les syscalls sont toujours bien utilisables. Ok, ça compile, ça link et surtout ça fonctionne. Voici le code utilisé : #include <gint/display.h> #include <gint/keyboard.h> #include <serial.h> int main(void) { dclear(C_WHITE); dtext(1, 1, C_BLACK, "Sample fxSDK Communication add-in."); if (Serial_IsOpen() != 1) { dtext(1,21, C_RED, "Serial port is CLOSED !!!" ); dtext(1,31, C_RGB( 31, 24, 0), "Trying to Open it ..." ); unsigned char mode[6]={0,9,0,0,0,0}; Serial_Open( mode ); } if (Serial_IsOpen() == 1) dtext(1,41, C_GREEN, "Serial port is now OPEN !!!" ); else { dtext(1,41, C_RED, "Failed to open the Serial port : STILL CLOSED !!!" ); dtext(1,51, C_BLACK, "Press a key to exit back to OS ..." ); dupdate(); getkey(); return 0; } if (Serial_IsOpen() == 1) { dtext(1,121, C_RED, "Now closing the Serial Port !!!" ); Serial_Close( 1 ); } if (Serial_IsOpen() != 1) dtext(1,141, C_GREEN, "Serial port is now Closed !!!" ); dupdate(); getkey(); return 1; } C'est donc un début vraiment encourageant, dans le sens où la gestion du port se fait correctement et la mini librairie semble bien fonctionner de son côté. Bon, donc plein d'espoir, j'essaie de passer à l'étape suivante : - sur une des 2 machines, envoyer un paquet de char dans le buffer de transmission (donc transmettre, en langage décodé), - sur l'autre machine, recevoir un paquet de char dans le buffer de réception (donc recevoir :) ). Le but étant ici juste d'envoyer d'un côté et de lire de l'autre côté, sans contrôle d'erreur et tout ce qu'il faudrait faire pour avoir des vraies communications "sérieuses" (donc pas taper merci :E ) ... on reste dans le très très expérimental par un gars qui découvre :D . Ceci étant réalisé par le code suivant (enfin, l'expression adéquate serait plutôt : "ceci devant être réalisé par le code suivant" :( ) : * #include <gint/display.h> #include <gint/keyboard.h> #include <serial.h> #include <stdio.h> #include <string.h> int main(void) { dclear(C_WHITE); dtext(1, 1, C_BLACK, "Sample fxSDK Communication add-in."); if (Serial_IsOpen() != 1) { dtext(1,21, C_RED, "Serial port is CLOSED !!!" ); dtext(1,31, C_RGB( 31, 24, 0), "Trying to Open it ..." ); unsigned char mode[6]={0,9,0,0,0,0}; Serial_Open( mode ); } if (Serial_IsOpen() == 1) dtext(1,41, C_GREEN, "Serial port is now OPEN !!!" ); else { dtext(1,41, C_RED, "Failed to open the Serial port : STILL CLOSED !!!" ); dtext(1,51, C_BLACK, "Press a key to exit back to OS ..." ); getkey(); return 0; } dtext(1,210, C_BLACK, "SEND"); dtext(60, 210, C_BLACK, "RECV"); dtext(1, 61, C_BLACK, "Press F1 to set Send mode and F2 to set Receive mode" ); dupdate(); if (getkey().key == KEY_F1) { char MessageToSend[256]; strcpy( MessageToSend, "Hello World !!!" ); int CountSend = 15; dprint(1, 81, C_BLUE, "Will send a message %s ", MessageToSend ); dupdate(); getkey(); // int result = Serial_Write( (unsigned char*) MessageToSend, CountSend ); // Fait Crash la babasse int result = Serial_WriteSingle( (unsigned char) 'Y' ); // idem, fait aussi crash la babasse if (result==0) { dprint(1, 101, C_GREEN, "Message sent" ); } else if (result==2) { dprint(1, 101, C_RED, "buffer is full" ); } dupdate(); getkey(); } else if (getkey().key == KEY_F2) { unsigned char MessageRead[256]; int MaxCountRead = 256; short int CountRead = 0; dtext(1, 81, C_BLUE, "Will receive a message " ); dupdate(); int result = Serial_Read( MessageRead, MaxCountRead, &CountRead ); if (result==0) { dprint(1, 101, C_GREEN, "%s", MessageRead ); } else if (result==1) { dprint(1, 101, C_RED, "buffer is empty" ); } dupdate(); getkey(); } if (Serial_IsOpen() == 1) { dtext(1,121, C_RED, "Now closing the Serial Port !!!" ); Serial_Close( 1 ); } if (Serial_IsOpen() != 1) dtext(1,141, C_GREEN, "Serial port is now Closed !!!" ); dupdate(); getkey(); return 1; } En mode réception (appui sur F2 sur une des machines, cela semble fonctionner (sauf qu'il y a rien à lire donc j'ai le message correspondant affiché), par contre en émission (sur l'autre machine, après appui sur F1), j'ai systématiquement un crash avec reboot de la machine sur la ligne du Serial_Write/Serial_WriteSingle. J'ai bien entendu testé chacune des machines en réception ET en émission, et c'est bien le même comportement sur chacune d'elle. L'émission fait systématiquement crasher et rebooter la machine. Auriez-vous une idée ou un semblant d'idée pouvant expliquer ce comportement ? Je précise que les syscalls sont bien ceux de la page ici (avec leur code respectifs) : serial CG20 Ciao Sly Wed, 11 May 2022 08:22:32 +0200 libJPEG pour Casio prizm/G90+E https://www.planet-casio.com/Fr/forums/topic17074--.html Hello, Comme annoncé dans l'update de la SDL_image, il est désormais possible d'importer des images JPG (ou JPEG) dans les addins gint grâce à la libJPG recompilée pour nos chères Casio CG10/20/50 (PRIZM et G90+E). Cette librairie a pour but de permettre la lecture des fichiers JPG et de rendre les données du fichiers accessible sous une forme facilement exploitable (en gros un tableau de pixels (R,G,B,A) associé à une structure d'entête contenant diverses infos utiles telles que la largeur et la hauteur de l'image lue). Cette librairie est utilisée par la SDL_image mais il peut s'avérer utile le l'utiliser en dehors de la SDL, par exemple pour un addin gint avec dimage(). L'un des principaux avantage du format JPG étant d'offrir des ratios de compression d'images très importants, avec ou sans perte de qualité. Ceci est tout à fait possible et je vous prépare la version "standalone" que vous pourrez utiliser pour créer une image bopti_image_t (format utilisé par gint via les méthodes dimage et dsubimage). Il faudra bien penser à disposer de cette lib pour pouvoir utiliser le code joint, ainsi que de mettre les options de linkage adhoc dans le Makefile ou CMakeLists.txt (Je ferai un tuto quand tout sera fignolé aux petits oignons :lol: , je commence à avoir pas mal de taf pour écrire les tutos qui vont bien, coder c'est bien, mais documenter c'est mieux). #include <gint/gint.h> #include <gint/display.h> #include <gint/keyboard.h> #include <stdio.h> #include <stdlib.h> #include <jpeglib.h> #include <jerror.h> struct imgRawImage { unsigned int numComponents; unsigned long int width, height; unsigned char* lpData; }; struct imgRawImage* loadJpegImageFile(char* lpFilename) { struct jpeg_decompress_struct info; struct jpeg_error_mgr err; struct imgRawImage* lpNewImage; unsigned long int imgWidth, imgHeight; int numComponents; unsigned long int dwBufferBytes; unsigned char* lpData; unsigned char* lpRowBuffer[1]; FILE* fHandle; fHandle = fopen(lpFilename, "rb"); if(fHandle == NULL) { #ifdef DEBUG fprintf(stderr, "%s:%u: Failed to read file %s\n", __FILE__, __LINE__, lpFilename); #endif return NULL; /* ToDo */ } info.err = jpeg_std_error(&err); jpeg_create_decompress(&info); jpeg_stdio_src(&info, fHandle); jpeg_read_header(&info, TRUE); jpeg_start_decompress(&info); imgWidth = info.output_width; imgHeight = info.output_height; numComponents = info.num_components; dwBufferBytes = imgWidth * imgHeight * 3; /* We only read RGB, not A */ lpData = (unsigned char*)malloc(sizeof(unsigned char)*dwBufferBytes); lpNewImage = (struct imgRawImage*)malloc(sizeof(struct imgRawImage)); lpNewImage->numComponents = numComponents; lpNewImage->width = imgWidth; lpNewImage->height = imgHeight; lpNewImage->lpData = lpData; /* Read scanline by scanline */ while(info.output_scanline < info.output_height) { lpRowBuffer[0] = (unsigned char *)(&lpData[3*info.output_width*info.output_scanline]); jpeg_read_scanlines(&info, lpRowBuffer, 1); } jpeg_finish_decompress(&info); jpeg_destroy_decompress(&info); fclose(fHandle); return lpNewImage; } size_t image_size_profile(int width, int height) { size_t size = sizeof(bopti_image_t); size += width * height * 2; return size; } void set_pixel(bopti_image_t *img, int x, int y, int color) { if((unsigned)x >= img->width || (unsigned)y >= img->height) return; uint8_t *bytes = (void *)img->data; img->data[y * img->width + x] = color; } bopti_image_t *convert_jpg_to_bopti( char *filename ) { struct imgRawImage* myJPEG; myJPEG = (struct imgRawImage*) gint_world_switch( GINT_CALL( loadJpegImageFile, "testimg.jpg" ) ); if (myJPEG==NULL) return NULL; int Wmax = myJPEG->width; if (myJPEG->width%2==1) Wmax++; // si largeur impaire, on rajoute un pixel transparent size_t size = image_size_profile(Wmax, myJPEG->height); bopti_image_t *image_temp = malloc( size ); if(!image_temp) return NULL; image_temp->profile = 0; // par defaut on a pas la transparence (on updatera si besoin après) image_temp->alpha = 0x0001; image_temp->width = Wmax; image_temp->height = myJPEG->height; uint16_t color; for (long unsigned int v=0; v<myJPEG->height; v++ ) { for( long unsigned int u=0; u<myJPEG->width; u++ ) { if (myJPEG->numComponents == 1) { unsigned char Grey = myJPEG->lpData[v*myJPEG->width+u]>>3; set_pixel(image_temp, u, v, C_RGB( Grey, Grey, Grey ) ); } else if (myJPEG->numComponents == 3) { unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*3+0]>>3; unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*3+1]>>3; unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*3+2]>>3; color = C_RGB( R, G, B ); if (color!=0x0001) set_pixel(image_temp, u, v, color); else set_pixel(image_temp, u, v, 0x0000); } else if (myJPEG->numComponents == 4) { unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*4+0]>>3; unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*4+1]>>3; unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*4+2]>>3; unsigned char A = myJPEG->lpData[(v*myJPEG->width+u)*4+3]; if (A>=128) set_pixel(image_temp, u, v, C_RGB( R, G, B ) ); else { set_pixel(image_temp, u, v, 0x0001); // set transparency image_temp->profile = 1; // on mets à jour le profil car il y a de la transparence } } } if (Wmax!=myJPEG->width) // si on doit ajouter un pixel supplémentaire sur la largeur { set_pixel(image_temp, Wmax, v, 0x0001); } } free(myJPEG->lpData); free(myJPEG); return image_temp; } bopti_image_t *image = NULL; bopti_image_t *image2 = NULL; int main(void) { // Jute ici pour désactiver le triple buffering par défaut uint16_t *vram1, *vram2; dgetvram(&vram1, &vram2); dsetvram(vram1, vram1); dclear(C_WHITE); dtext(1, 190, C_BLACK, "Sample libcJPG to bopti test :"); dupdate(); image = convert_jpg_to_bopti( "testimg.jpg" ); image2 = convert_jpg_to_bopti( "nofile.jpg" ); // fichier qui n'existe pas, controle de la stabilité dimage( 0, 0, image ); dimage( 0, 0, image2 ); // ne doit pas planter dsubimage( 200, 50, image, 21,15, 120, 88, DIMAGE_NONE ); dsubimage( 200, 50, image2, 21,15, 120, 88, DIMAGE_NONE ); // idem, sans plantage dupdate(); getkey(); if (image!=NULL) free(image); if (image2!=NULL) free(image2); return 1; } et ce qui donne sur l'écran (la grosse image de rose est un dimage() obtenu depuis une image externe en JPG et la petite est obtenue via un dsubimage() ). https://imgur.com/xH4UFHj.png On peut donc bien utiliser les fonctions usuelles de gint avec la librairie. Par contre attention, contrairement à l'habitude, les images ne sont pas allouée en statique, il faut donc bien penser à libérer la mémoire avec un free() et surtout attention à ne pas dépasser la taille maxie de RAM !!! Pour info cette image de rose, de dimension 227x149 pixels en RGB888 pèse : - 49,3ko en PNG - 5,8ko en JPG on comprend vite l'intérêt de ce format. Le dépôt gitea est en cours de fabrication. Je passerai les infos asap. Ciao Sly Sun, 08 May 2022 21:17:41 +0200 libPNG pour Casio prizm/G90+E https://www.planet-casio.com/Fr/forums/topic17071--.html Voici cette fois quelques news concernant la libPNG recompilée pour nos chères Casio CG10/20/50 (PRIZM et G90+E). Cette librairie a pour but de permettre la lecture des fichiers PNG et de rendre les données du fichiers accessible sous une forme facilement exploitable (en gros un tableau de pixels (R,G,B,A) associé à une structure d'entête contenant diverses infos utiles telles que la largeur et la hauteur de l'image lue). Cette librairie est utilisée par la SDL_image et repose sur la librairie Zlib (le format PNG est un format compressé sans perte), mais il peut s'avérer utile le l'utiliser en dehors de la SDL, par exemple pour un addin gint avec dimage(). Ceci est tout à fait possible et je vous prépare la version "standalone" que vous pourrez utiliser pour créer une image bopti_image_t (format utilisé par gint via les méthodes dimage et dsubimage). Il faudra bien penser à disposer de cette lib ainsi que zlib pour pouvoir utiliser le code joint, ainsi que de mettre les options de linkage adhoc dans le Makefile ou CMakeLists.txt (Je ferai un tuto quand tout sera fignolé au petit oignons :lol: ) #include <gint/gint.h> #include <gint/display.h> #include <gint/keyboard.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdarg.h> #include <zlib.h> #define PNG_DEBUG 3 #include <png.h> int currentline = 0; void abort_(const char * s, ...) { #if(0) va_list args; va_start(args, s); dprint(1, 1+currentline*10, C_BLACK, s, args ); currentline++; va_end(args); abort(); #endif } int x, y; int width, height; png_byte color_type; png_byte bit_depth; png_structp png_ptr; png_infop info_ptr; int number_of_passes; png_bytep *row_pointers; //Return 0 on success and -1 on error int read_png_file(char* file_name) { char header[8]; // 8 is the maximum size that can be checked FILE *fp = fopen(file_name, "rb"); if (!fp) { abort_("[read_png_file] File %s could not be opened for reading", file_name); return -1; } fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); return -1; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { abort_("[read_png_file] png_create_read_struct failed"); return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { abort_("[read_png_file] png_create_info_struct failed"); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { abort_("[read_png_file] Error during init_io"); return -1; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); if (setjmp(png_jmpbuf(png_ptr))) { abort_("[read_png_file] Error during read_image"); return -1; } row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); for (y=0; y<height; y++) row_pointers = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr)); png_read_image(png_ptr, row_pointers); fclose(fp); return 0; } void process_file(void) { if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) abort_("[process_file] input file is PNG_COLOR_TYPE_RGB but must be PNG_COLOR_TYPE_RGBA " "(lacks the alpha channel)"); if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA) abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (%d) (is %d)", PNG_COLOR_TYPE_RGBA, png_get_color_type(png_ptr, info_ptr)); for (y=0; y<height; y++) { png_byte* row = row_pointers; for (x=0; x<width; x++) { png_byte* ptr = &(row[x*4]); dprint( 1, 200, C_WHITE, "Pixel at position [ %d - %d ] has RGBA values: %d - %d - %d - %d\n", x, y, ptr[0], ptr[1], ptr[2], ptr[3]); ptr[0] = 0; ptr[1] = ptr[2]; } } } size_t image_size_profile(int width, int height) { size_t size = sizeof(bopti_image_t); size += width * height * 2; return size; } void set_pixel(bopti_image_t *img, int x, int y, int color) { if((unsigned)x >= img->width || (unsigned)y >= img->height) return; uint8_t *bytes = (void *)img->data; img->data[y * img->width + x] = color; } bopti_image_t *convert_png_to_bopti( char *filename ) { if (gint_world_switch(GINT_CALL(read_png_file, filename ))==-1) // qq chose s'est mal passé durant la lecture return NULL; int Wmax = width; if (width%2==1) Wmax++; // si largeur impaire, on rajoute un pixel transparent size_t size = image_size_profile(Wmax, height); bopti_image_t *image_temp = malloc( size ); if(!image_temp) return NULL; image_temp->profile = 0; // par defaut on a pas la transparence (on updatera si besoin après) image_temp->alpha = 0x0001; image_temp->width = Wmax; image_temp->height = height; uint16_t color; for(int v=0; v<height; v++) { png_byte* row = row_pointers; for(int u=0; u<width; u++) { png_byte* ptr = &(row[u*4]); if (ptr[3]>128) { color = C_RGB( ptr[0]>>3, ptr[1]>>3, ptr[2]>>3 ); if (color!=0x0001) set_pixel(image_temp, u, v, color); else set_pixel(image_temp, u, v, 0x0000); // si par manque de chance on tombe sur la couleur transparente à la conversion, on met du noir } else { set_pixel(image_temp, u, v, 0x0001); // set transparency image_temp->profile = 1; // on mets à jour le profil car il y a de la transparence } } if (Wmax!=width) // si on doit ajouter un pixel supplémentaire sur la largeur { set_pixel(image_temp, Wmax, v, 0x0001); } } for (y=0; y<height; y++) free(row_pointers); free(row_pointers); return image_temp; } bopti_image_t *image = NULL; bopti_image_t *image2 = NULL; int main(void) { // Jute ici pour désactiver le triple buffering par défaut uint16_t *vram1, *vram2; dgetvram(&vram1, &vram2); dsetvram(vram1, vram1); dclear(C_WHITE); dtext(1, 1, C_BLACK, "Sample libcPNG to bopti test :"); dupdate(); image = convert_png_to_bopti( "mario.png" ); image2 = convert_png_to_bopti( "nofile.png" ); // fichier qui n'existe pas, controle de la stabilité dimage( 0, 0, image ); dimage( 0, 0, image2 ); // ne doit pas planter dsubimage( 200, 50, image, 21,15, 120, 88, DIMAGE_NONE ); dsubimage( 200, 50, image2, 21,15, 120, 88, DIMAGE_NONE ); // idem, sans plantage dupdate(); getkey(); if (image!=NULL) free(image); // IMPORTANT : contrairement à l'habitude avec fxconv, il faut libérer la mémoire, on est ici en allocation dynamique if (image2!=NULL) free(image2); return 1; } et ce qui donne sur l'écran (le grand Mario est un dimage() obtenu depuis une image externe en PNG et la tête est obtenu via un dsubimage() ). https://imgur.com/tePoNFA.png On peut donc bien utiliser les fonctions usuelles de gint avec la librairie. Par contre attention, contrairement à l'habitude, les images ne sont pas allouée en statique, il faut donc bien penser à libérer la mémoire avec un free() et surtout attention à ne pas dépasser la taille maxie de RAM !!! Le dépôt gitea est en cours de fabrication. Je passerai les infos asap. Ciao Sly @RDP (j'en ai fini pour cette semaine :whistle: ) Thu, 05 May 2022 15:58:38 +0200 libSDL_image pour Casio Prizm / G90+E (fx-CG 10/20/50) https://www.planet-casio.com/Fr/forums/topic17070--.html Hello, voici une autre lib en cours de dev pour nos chères Casio : la libSDL_image, basée sur la SDL_image 1.2.12. Petit pitch : cette librairie est une extension de la SDL (dont le portage pour nos machines est discuté ici : SDL 1.2.15 pour Casio PRIZM ) et qui a pour finalité d'offrir la capacité d'importer des images externes pour les utiliser sous forme de SDL_Surface dans la SDL. La SDL offre en standard seulement la capacité d'importer des BMP, via la fonction SDL_LoadBMP, mais ce format, bien qu'intéressant et très répandu, souffre de deux problèmes majeurs : - peu (ou pas de compression) donc taille des fichiers assez grosses en comparaison d'autres formats, - pas de gestion officielle de la transparence (canal alpha), donc même si on peut ruser, cela nécessite des ajustements. Bref, une lib d'import d'image pour la SDL est plus qu'utile, et c'est là le but de la SDL_image. La librairie se divise en deux volets : - d'une part les formats dont l'import se fait directement (les routines sont directement codées dans la libraire ). - d'autre part les formats dont l'import repose sur l'utilisation de librairies tierces (et donc il faut avoir la lib dispo sur la plateforme de portage) Dans la première catégorie se trouvent les formats BMP, ICO, CUR, PCX, PNM, LBM, GIF, TGA, XCF, ... Dans la seconde catégorie se trouvent les formats qu'on aime bien : PNG, JPG, TIF, WEBP, ... En particulier les formats PNG et JPG nécessitent des librairies "filles" : - pour le PNG : la libPNG est nécessaire qui demande elle même la Zlib (ça y est, je pense que le cheminement de mes post prend forme, et voici le pourquoi du comment) - pour le JPG : la libJPG est nécessaire (cette librairie est autoporteuse) Voici un état des lieux (sachant qu'il s'agit d'une photographie à l'instant "t" et que j'espère pouvoir faire bouger les lignes dans le futur): Pour les formats intégrés directement à la lib, voici mon retour d'expérience avec la version en cours de développement : - format BMP : testé et validé via la fonction IMG_Load de la SDL_image et via SDL_LoadBMP de la SDL - format ICO : testé mais gros glitchs (couleurs pas OK en 16couleurs et visiblement problème d'import avec les autres mode (a priori pas utile comme format) - format CUR : [pas testé] je sais même pas quel logiciel utilise ce format - format TGA : testé et validé via IMG_Load - format PNM : testé et validé via IMG_Load - format LBM : [pas testé] je sais pas quel logiciel utilise ce format - format XCF : format trop instable, ne correspond plus au format XCF de GIMP - format PCX : à regarder de plus près pour comprendre (notamment utile via ASprite) Pour les formats "externes" : - format PNG : testé et validé via IMG_Load, libPNG et libZlib fonctionnelle - format JPG : la libJPG est compilée, linkée mais à ce stade rien n'arrive dans la SDL_image donc rien ne s'affiche (bon déjà ça crashe pas). Je vais regarder cela pour essayer d'avoir ce format. - format TIFF : pas regardé et a priori pas très utilisé de nos jours (nécessite la libTIFF) - format WEBP : pas regardé et a priori pas très utilisé de nos jours (nécessite une lib aussi) Donc en bonne nouvelle, c'est le support du PNG qui est clairement un super format qu'on aime bien. Le support du JPG serait un gros gros plus, mais je ne peux pas promettre à ce stade (mais j'y travaille). Voila pour le bilan A ce stade c'est très expérimental : voici juste un screen pris à la volée : https://imgur.com/1NfDgXq.png @+ Sly et @RDP (on va faire une session librairies :D ) Thu, 05 May 2022 11:10:24 +0200 Frozen Frenzy® 2 https://www.planet-casio.com/Fr/forums/topic17069--.html new frozen frenzy U deluxe.png Sautez, glissez et fuyez en quête de pancakes et d'identité ! Frozen Frenzy 2 est la suite directe du premier opus. Développé en dehors d'un CPC, je peux prendre le temps de faire un jeu qui me plaît : J'ai l'ambition de faire le meilleur platformer sur le site. (derrière wehfou). Au programme ? Des graphismes et des environnements urbains et industriels entièrement conçus par mes soins. Un gameplay travaillé, qui se veut plus précis, flexible et simple d'accès que le premier. Une grande variété de pièges, mécaniques centrées autour du feu et de la glace, ainsi que différents objectifs de niveaux (tout geler, mais aussi fuir, s'infiltrer, aller chercher un pancake et revenir...) Un level design intelligent où s'entremêlent voies simples d'accès et passages hardus mais récompensant les speedrunners. Un système à la Celeste/Super Meat Boy avec des niveaux optionnels plus complexes et remplis de pics ! Une mini bande-dessinée dont chaque fragment est dévoilé en début de chapitre, racontant l'odyssée de δ. delta_run.gif J'ai l'intention de placer l'histoire de Frozen Frenzy 2 directement après celle de l'original. Je n'en dis pas plus... En terme de gameplay, le jeu reste assez simple : Un saut, la possibilité de walljump, et le pouvoir de geler des blocs au contact, ce qui joue en votre (dé)faveur. https://youtu.be/wPDJPOkCHf4 Tue, 03 May 2022 22:11:08 +0200 Debugger à travers gint_world_switch ... ou comment transpirer sans faire de sport :D https://www.planet-casio.com/Fr/forums/topic17068--.html Alors voilà, par une belle journée ensoleillée, l'idée est venu de convertir la SDL_image pour la prizm, cool, mais pas simple... et surtout ça ne marche pas comme prévu (voir pas du tout en fait), et il faut désormais comprendre pourquoi chaque morceau pris individuellement (zlib, libpng, libSDL) fonctionne, mais une fois assemblé, niet, nada ketchi, bref ... rien sur l'écran !!! Oh, séance de débogage pour comprendre ce qui se passe !!! Euh, oui, mais, pas de dprint (car pas de dupdate) car on est dans les fonctions entrée sorties dans les fichiers, donc encapsulé dans un gint_world_switch ... bref, pénible à souhait. Donc l'idée : créer une fonction dans la libSDL qui va logger dans un fichier, sachant que l'Addin de test appelle à la fois la libSDL_image et la libSDL et que la libSDL_image appelle la libSDL, lui offrant les fonctions de base. Donc si je me mets dans la libSDL, a priori je fais d'une pierre deux coups (en fait trois) et je saurais logger tout ce qui se passe dans l'Adddin, la libSDL et la libSDL_image. donc je commence par créer une fonction dans le header principal de la SDL et un fichier source : dans SDL.h extern DECLSPEC void SDLCALL cSDL_LogToFile(const char *fmt, ... ); et dans SDL.c #include <gint/gint.h> #include <stdarg.h> #include <stdio.h> void cSDL_LogToFile(const char *fmt, ... ) { FILE * fp = fopen( "OutLog.txt", "a" ); if (fp==NULL) return; va_list args; va_start( args, fmt ); fprintf( fp, fmt, args ); fprintf( fp, "\n"); va_end( args ); fclose( fp ); } Je recompile la libSDL, tout va bien (c'est pas trop sauvage, donc tout roule). désormais l'Addin je mets seulement une portion de code, et vire ce qui n'est pas important #include <gint/gint.h> #include <SDL/SDL.h> void testfunc2( int temp ) { cSDL_LogToFile( "Hello ceci est un troisième test dans une fonction interne avec parametre : ici temp = %d.", temp ); } void testfunc(void) { cSDL_LogToFile( "Hello ceci est un autre test dans une fonction interne sans parametre." ); testfunc2( 25 ); } int main(void){ ... gint_world_switch( GINT_CALL( cSDL_LogToFile, "Hello ceci est un test dans un GWS isolé" ) ); // test direct dans un giint_world_switch car on trippote dans les fichiers gint_world_switch( GINT_CALL( testfunc ) ); // test via une fonction (qui fera un appel à une sous fonction) ... Donc en terme de résultat je m'attends à obtenir un fichier "OutLog.txt" contenant ceci Hello ceci est un test dans un GWS isolé Hello ceci est un autre test dans une fonction interne sans paramètre. Hello ceci est un troisième test dans une fonction interne avec paramètre : ici temp = 25. mais j'obtiens Hello ceci est un test dans un GWS isolé Hello ceci est un autre test dans une fonction interne sans paramètre. Hello ceci est un troisième test dans une fonction interne avec paramètre : ici temp = -1944191212. Et la question : pourquoi mon call à testfunc2( 25 ), où temp vaut 25 donc devient ce -1944191212 ? Ça sent l’adresse mémoire plutôt que le contenu de la variable cette histoire. Mon, 02 May 2022 19:05:09 +0200 Zlib pour Casio fx/cg (développement et benchmark) https://www.planet-casio.com/Fr/forums/topic17066--.html Hello à Toutes et Tous Dans le long voyage qui nous amènera peut-être (enfin j'espère bien) à avoir une librairie SDL complète (avec SDL_image), il y a un certain nombre de prérogatives à passer, notamment pour le support des ressources externes en format PNG. En effet la SDL_image s'appuie sur la libPNG, qui elle même repose sur la zlib. Donc il faut prendre les choses les unes après les autres et je vous ai créé un dépôt avec la zlib fonctionnelle pour les Casio (fx/cg). La zlib, mais kézako ? Pour ceux qui ne connaissent pas, il s'agit d'une bibliotheque de fonctions visant à offrir des algorithmes de compression / décompression sans perte de données. Cette bibliothèque est très largement utilisée par de nombreux logiciels (sur à peu près toutes les plateformes existantes), y compris par l'OS de nos Casio chéries. En effet, l'OS contient quelques syscall faisant référence à cette zlib, mais hélas à ce stade nous ne savons pas les utiliser car peu ou prou documentés. Donc notre zlib opérationnelle se nomme cZlib (contraction de "Casio Zlib") et repose sur la zlib version 1.2.5. Le dépôt Gitea de la bête se trouve ici : cZlib1.2.5 Comme d'habitude il est possible d'installer la libczlib via GiteaPC par la commande suivante giteapc install Slyvtt/cZlib1_2_5la compilation se faisant à la volée ainsi que l'installation dans les répertoires adhoc du compilateur contenant les headers et les librairies. La encore, si vous avez des soucis, passer sur fxlibc@dev, car il se peut que certaines features récentes soit nécessaires et pas encore dans la branche master. Pour les plus aventuriers, il y a aussi un Makefile à lancer dans le répertoire racine d'extraction via un make -f Makefile.prizmIl vous faudra alors copier manuellement libczlib.a dans le répertoire d'installation de vos lib de votre compilateur et les deux fichiers headers zlib.h et zconf.h contenus dans le répertoire racine dans le sous dossier include de votre compilateur. Là encore comme d'hab', vous pourrez commencer à créer un programme avec la zlib très simplement. Créer un nouveau projet via fxsdk new SDLprojectpuis vous devrez ouvrir le fichier CMakeLists.txt contenu dans le projet pour éditer la ligne target_link_libraries(myaddin Gint::Gint)et la remplacer par target_link_libraries(myaddin Gint::Gint -lczlib) (bref ajouter la librairie qui va bien). voici un code exemple pour utiliser : #include <gint/gint.h> #include <gint/display.h> #include <stdio.h> #include <string.h> // for strlen #include <assert.h> #include "zlib.h" int main() { // original string to be compressed char a[50] = "Hello Hello Hello Hello Hello Hello !!!!!!"; // placeholder for the compressed (deflated) version of "a" char b[50]; // placeholder for the UNcompressed (inflated) version of "b" char c[50]; dclear( 0xFFFF ); dprint(1,10,0x0000, "Uncompressed size is: %lu", strlen(a)); dprint(1,20,0x0000, "Uncompressed string is:"); dprint(1,30,C_BLUE, "%s", a); // STEP 1 : deflate a into b. (that is, compress a into b) // zlib struct z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; // setup "a" as the input and "b" as the compressed output defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator defstream.next_in = (Bytef *)a; // input char array defstream.avail_out = (uInt)sizeof(b); // size of output defstream.next_out = (Bytef *)b; // output char array // the actual compression work. deflateInit(&defstream, Z_BEST_COMPRESSION); deflate(&defstream, Z_FINISH); deflateEnd(&defstream); dprint(1,50,0x0000, "Compressed size is: %lu", strlen(b)); dprint(1,60,0x0000, "Compressed string is:" ); dprint(1,70, C_BLUE, "%s", b); dprint(1,80,C_RED, "Don't worry if not all char are visible :"); dprint(1,90,C_RED, "may contain non printable ones" ); // STEP 2 : inflate b into c (should return to string a) // zlib struct z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; infstream.opaque = Z_NULL; // setup "b" as the input and "c" as the compressed output infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input infstream.next_in = (Bytef *)b; // input char array infstream.avail_out = (uInt)sizeof(c); // size of output infstream.next_out = (Bytef *)c; // output char array // the actual DE-compression work. inflateInit(&infstream); inflate(&infstream, Z_NO_FLUSH); inflateEnd(&infstream); dprint(1,110,0x0000, "Uncompressed size is: %lu", strlen(c)); dprint(1,120,0x0000, "Uncompressed string is:" ); dprint(1,130,C_BLUE, "%s", c); // make sure uncompressed is exactly equal to original. if(strcmp(a,c)==0) dprint(1,150, C_GREEN, "Everything is OK" ); else dprint(1,150, C_RED, "There is a problem somewhere" ); dupdate(); getkey(); return 0; } Et voici deux screenshots pris sur ma G90+E pour montrer que ça marche : https://imgur.com/2bwR1LT.png https://imgur.com/NaZRZE7.png Fun fact : vous noterez l'efficacité de la compression dans le premier cas :E Cela pourra toujours vous servir pour des utilitaires à un moment ou à un autre. Attention, comme d’habitude avec les flux dans les fichiers : bien penser au gint_world_switch qui va bien !!! Afin de mesurer les performances de la cZlib sur nos machines, j'ai testé différentes configurations sur divers fichiers. Le protocole de test est le suivant : - ouverture du fichier et stockage de l'ensemble des données contenues dans celui-ci en mémoire dans un flux (stream au sens de la zlib) d'entrée ("inputStream"). - compression de ce flux d'entrée via la fonction "compress()" de la zlib et stockage dans un flux intermédiaire ("outputStrean") avec mesure du temps de compression et la taille du flux compressé / du ratio de compression. - décompression du flux intermédiaire vers le flux final ("secondOutputStream") via la fonction "uncompress()" de la zlib, là encore avec mesure du temps de décompression et la taille du flux décompressé (qui doit retomber sur la taille initiale, sinon il y a un problème). - validation octet par octet de la similitude de "inputStream" et de "secondOutputStream" (on regarde que le cycle compression/décompression est sans erreur). - écriture sur disque du flux decompressé finale pour vérifier que l'on peut utiliser le fichier sans soucis (a priori redondant avec étape précédente, mais on est jamais assez prudent :E ). A ce stade les tests sont réalisés sur une fx-CG 50 (ou Graph 90+E) sans overclock. Je pense complèter par d'autres essais plus tard. Les temps sont mesurés avec la LibProf. Les fichiers tests sont : - 3 fichiers Addins (des ".g3a") de diverses tailles : Conv.g3a (~29ko) et PicPlot.g3a (~83ko) de Casio et Afterburner de Lephé (~172ko) - 1 fichier texte (".txt") créé en ligne par un générateur de phrases aléatoires en français : texte0.txt (~36ko) - 3 fichiers images (".bmp") sans compression : image0.bmp (~873ko) photo 660x441pix en 24bpp, image1.bmp (~265ko) image de fond de mon jeu OutRun 396x224pix en 24bpp, et image2.bmp (~57ko) convertie depuis une fonte fxconv, image en N&B, - 3 fichiers photos (".png") avec compression : photo0.png (~26ko), photo1.png (~194ko), photo3.png (~579ko) Et sans plus attendre voici les résultats obtenus : https://imgur.com/OqnbqfT.png Il est intéressant de voir les niveaux de compression et surtout les temps de décompression qui sont vraiment pas mauvais du tout et pourrait laisser envisager quelques trucs sympas dans Gint. #include <gint/gint.h> #include <gint/display.h> #include <gint/keyboard.h> #include <gint/hardware.h> #include <gint/kmalloc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // for strlen #include <assert.h> #include <sys/stat.h> #include "zlib.h" #include <libprof.h> char *filesin[10] = { "photo0.png", "photo1.png", "photo2.png", "Conv.g3a", "PictPlot.g3a", "Afterbur.g3a", "texte0.txt", "image0.bmp", "image1.bmp", "image2.bmp" }; char *filesout[10] = { "Z_photo0.png", "Z_photo1.png", "Z_photo2.png", "Z_Conv.g3a", "Z_PictPlot.g3a", "Z_Afterbur.g3a", "Z_texte0.txt", "Z_image0.bmp", "Z_image1.bmp", "Z_image2.bmp" }; struct stat sb; uint32_t time_compress=0, time_decompress=0; uint32_t sizeStream; char *inputStream = NULL; char *outputStream = NULL; char *secondOutputStream = NULL; int OpenFileAndLoadStream( int which ) { if (inputStream!=NULL) { free( inputStream ); inputStream = NULL; } if (outputStream!=NULL) { free(outputStream ); outputStream = NULL; } if (secondOutputStream!=NULL) { free( secondOutputStream ); secondOutputStream = NULL; } if (stat(filesin, &sb) == -1) { return -1; } sizeStream = (uint32_t) sb.st_size; inputStream = (char*) malloc( sb.st_size ); if (inputStream == NULL) { return -2; } outputStream = (char*) malloc( sb.st_size+10000 ); if (outputStream == NULL) { free(inputStream); inputStream = NULL; return -3; } secondOutputStream = (char*) malloc( sb.st_size ); if (secondOutputStream == NULL) { free(outputStream); inputStream = NULL; free(outputStream); inputStream = NULL; return -4; } FILE* fp = fopen(filesin, "rb" ); if (fp==NULL) { return -5; } fread( inputStream, sb.st_size, 1, fp ); fclose ( fp ); return 1; } int SaveOutputFile( int which ) { FILE* fp = fopen(filesout, "wb" ); if (fp==NULL) { return -5; } fwrite( secondOutputStream, sizeStream, 1, fp ); fclose ( fp ); return 1; } void CloseAndFree( void ) { if (inputStream!=NULL) { free( inputStream ); inputStream = NULL; } if (outputStream!=NULL) { free( outputStream ); outputStream = NULL; } if (secondOutputStream!=NULL) { free( secondOutputStream ); secondOutputStream = NULL; } exit(0); } bool canWeAllocate3Mb = false; static kmalloc_arena_t extended_ram = { 0 }; void increaseRAM( void ) { char const *osv = (char*) 0x80020020; //kmalloc_gint_stats_t *extram_stats; if((!strncmp(osv, "03.", 3) && osv[3] <= '6') && gint == HWCALC_FXCG50) // CG-50 { extended_ram.name = "extram"; extended_ram.is_default = true; extended_ram.start = (void *)0x8c200000; extended_ram.end = (void *)0x8c500000 ; kmalloc_init_arena(&extended_ram, true); kmalloc_add_arena(&extended_ram ); canWeAllocate3Mb = true; } else if (gint == HWCALC_PRIZM) // CG-10/20 { extended_ram.name = "extram"; extended_ram.is_default = true; uint16_t *vram1, *vram2; dgetvram(&vram1, &vram2); dsetvram(vram1, vram1); extended_ram.start = vram2; extended_ram.end = (char *)vram2 + 396*224*2; kmalloc_init_arena(&extended_ram, true); kmalloc_add_arena(&extended_ram ); canWeAllocate3Mb = false; } else if (gint == HWCALC_FXCG_MANAGER) // CG-50 EMULATOR { extended_ram.name = "extram"; extended_ram.is_default = true; extended_ram.start = (void *)0x88200000; extended_ram.end = (void *)0x88500000 ; kmalloc_init_arena(&extended_ram, true); kmalloc_add_arena(&extended_ram ); canWeAllocate3Mb = true; } else abort(); } int main() { uint16_t *vram1, *vram2; dgetvram(&vram1, &vram2); dsetvram(vram1, vram1); increaseRAM(); prof_init(); prof_t perf_compress, perf_decompress; int file=9; int retour = (int) gint_world_switch( GINT_CALL(OpenFileAndLoadStream, file) ); if (retour<=0) CloseAndFree(); uint32_t ucompSize = sizeStream; // "Hello, world!" + NULL delimiter. uint32_t compSize = compressBound(ucompSize); uint32_t reucompSize = sizeStream; // "Hello, world!" + NULL delimiter. perf_compress = prof_make(); prof_enter(perf_compress); // Deflate compress((Bytef *)outputStream, &compSize, (Bytef *)inputStream, ucompSize); prof_leave(perf_compress); time_compress = prof_time(perf_compress); perf_decompress = prof_make(); prof_enter(perf_decompress); // Inflate uncompress((Bytef *)secondOutputStream, &reucompSize, (Bytef *)outputStream, compSize); prof_leave(perf_decompress); time_decompress = prof_time(perf_decompress); dclear( 0xFFFF ); dprint(1,10,0x0000, "Uncompressed size is: %lu", ucompSize ); dprint(1,20,0x0000, "Compressed size is: %lu", compSize ); dprint(1,30,0x0000, "Uncompressed size is: %lu", reucompSize ); dprint(1,40, C_GREEN, "time to compress: %lu", time_compress/1000 ); dprint(1,50, C_GREEN, "time to decompress: %lu", time_decompress/1000 ); dupdate(); for( uint32_t k=0; k<sizeStream; k++ ) { if (inputStream!=secondOutputStream) { dprint(1,70,C_RED, "Error at byte %d", k ); break; } } dprint(1,90,C_BLUE, "End of comparison" ); dprint(1,100, 0x0000, "Now Saving Ouput ... " ); dupdate(); retour = (int) gint_world_switch( GINT_CALL(SaveOutputFile, file ) ); dprint(1,110, 0x0000, " ... Done :-) " ); dprint(1,130, 0x0000, "Press a key to exit" ); dupdate(); getkey(); // We set back zeros at the end of the program memset(extended_ram.start, 0, (char *)extended_ram.end - (char *)extended_ram.start); return 0; } Ciao Sly Et zou, @RDP Sun, 01 May 2022 11:20:21 +0200 fxtran -- Codez en Fortran pour votre Casio ! https://www.planet-casio.com/Fr/forums/topic17064--.html Bonjour à tous.tes ! Lundi dernier je me suis levé avec une (mauvaise) idée : coder en Fortran pour ma Casio. Une semaine plus tard est né fxtran, qui réalise ce rêve (rêve hum hum) ! Le projet utilise le fxsdk de Lephenixnoir ainsi que f2c, un programme permettant de transformer du code Fortran 77 en code C. Une petite démo tout de suite : Je crée un nouveau projet fxsdk : $ fxsdk new demo Je le configure pour fxtran : $ fxtran configure Dans le dossier src j'ai donc un fichier main.f qui contient un programme d'exemple. Let's programming something ! Je fais une petite démo, voici donc le code : INTEGER FUNCTION FIBO(n) INTEGER n INTEGER FIBO IF (n .EQ. 0) THEN FIBO=0 RETURN ELSE IF (n .EQ. 1) THEN FIBO=1 RETURN ELSE FIBO=FIBO(n-1) + FIBO (n-2) END IF END PROGRAM DEMO INTEGER FIBO,a REAL b PRINT *,"Suite de Fibonacci :" DO a = 1,16 PRINT *,FIBO(a) WAIT END DO b=sqrt(9.00) PRINT *,"Racine de 9 :",int(b) WAIT PRINT *,"Racine de 2 :", sqrt(2.00) PI=4.D0*DATAN(1.D0) WAIT PRINT *,"Pi :",PI END Ici je déclare une fonction FIBO(n) qui me renvoie le terme de rang n de la suite de Fibonacci (j'utilise l'algorithme récursif naïf), puis dans le programme principal j'affiche les 16 premiers termes de la suite de Fibonacci. Entre chaque terme j'utilise la fonction WAIT qui n'existe pas en Fortran, elle est crée par fxtran et met en pause le programme jusqu'à l'appui d'une touche (équivalent de la fonction getkey() avec Gint). Ensuite j'affiche différentes racines, puis le nombre π. Le code est vraiment typique du Fortran 77. Compilons ceci : fxtran build-fx Voilà, le g1a est généré dans MyAddin.g1a ! On se retrouve après le transfert, pour une petite vidéo : fxtran_demo.gif Et voilà ! Installation Pour installer fxtran, il faut : - Installer le fxsdk de Lephenixnoir - Puis : git clone https://github.com/harrypotter360/fxtran.git && cd fxtran chmod +x install && sudo ./install Et voilà, fxtran est installé ! Utilisation Pour utiliser fxtran : - On crée un projet fxsdk : fxsdk new demo && cd demo - On le rend compatible fxtran : fxtran configure Et ensuite, on peut coder en Fortran 77 dans le fichier src/main.f ! Pour build : fxtran build-fx (build-cg existe mais ne marche pas encore) Et on transfère le g1a sur la calto ! Voilà, j'espère que ça vous plaira ! Enjoy ! @RDP Sun, 24 Apr 2022 15:15:24 +0200