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

Forum Casio - Projets de programmation


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

B2C : Convertisseur Basic en C

Posté le 02/07/2016 11:24

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

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

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

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

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

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

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

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

Fonctions actuellement implémentées :

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

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

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

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

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

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

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

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

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

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



Précédente 1, 2, 3, 4, 5, 6
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 05/08/2016 19:08 | #


Tu précises à la fois :
Zezombye a écrit :
- [...] des listes ayant la même taille n'ont pas cet octet identique
- Il ne dépend pas du nombre d'éléments
- Il semble dépendre du contenu

La première information est une conséquence des deux autres, à condition que tes listes diffèrent. T'as regardé si déplacer des listes dans les numéros affectait la valeur ?

Zezombye a écrit :
- Il ne dépend pas du nombre d'éléments [...] : des listes avec le même nombre d'éléments n'ont pas cet octet identique

Ça ne veut pas dire que la valeur est indépendante du nombre d'éléments ! Ça veut dire qu'elle ne peut pas dépendre uniquement du nombre d'éléments.

Puisque c'est après le nombre d'éléments ce serait plutôt quelque chose qui ne dépend que des contenus de la liste (nom, nombre d'éléments et valeur des éléments) et indépendant de son numéro.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 14/08/2016 20:21 | #


Bon, après les CPC je reprends ce projet

Comme j'ai dit dans le topic (j'ai édité) j'ai surtout besoin d'aide au niveau des formats de fichiers. Etant donné que maintenant je me base sur mon précieux syscall calcExp() pour calculer les expressions (donc nul besoin de parser toutes les fonctions bizarres genre 1kAB qui se retrouvent dans les jeux de neotux ) ça veut dire que j'utilise la mémoire alpha, et donc les fichiers (parce que pour les calculs, je dois stocker les variables dans la mémoire alpha, donc les listes, matrices, et variables de récursion).
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 15/08/2016 18:33 | #


Hésite pas à écrire un add-in qui sauvegarde la mémoire principale dans un fichier puis qui fait les diffs quand on le rappelle, pour voir ce qui change lorsqu'on exécute un programme Basic.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 16/08/2016 19:36 | #


J'ai réussi à trouver assez d'infos sur les formats g1m (merci simlo )

Là où je suis bloqué pour l'instant, c'est le stockage des pictures. Le format des pictures est le même que celui de ML_bmp_or, donc pour afficher une picture je fais un ML_bmp_or sur les 1024 premiers octets à partir de la picture sélectionnée, puis un autre sur les 1024 octets d'après. Ceci pour respecter l'affichage des pictures permis par Picture 1024 (et utilisé par exemple dans Clonelab, donc je peux pas ignorer ça).

Comment faire pour stocker les pictures côte à côte dans la mémoire ? En imaginant que j'aie un tableau de pointeurs {pict1, pict2, pict3...}, pour RclPict 1 je n'aurais qu'à faire "ML_bmp_or(pict1, 0, 0, 128, 64); ML_bmp_or(pict1+1024, 0, 0, 128, 64)". Mais comment faire lorsque les pictures changent (par exemple, la picture 1 faisait au début du programme 512 octets, mais le programme la replace ensuite par une autre de 2048 octets, je dois donc décaler les pointeurs et leurs données). Ou alors est ce que je ne fais pas cette technique de prendre les 2048 octets après le pointeur correspondant à la picture, et je fais une fonction spéciale qui prend les octets de la picture suivante si on est arrivé à la fin de la picture actuelle alors qu'il reste des octets ?

D'ailleurs, est ce que le programme crashe si la picture suivante est inexistante (par exemple, si la picture 6 mesure 512 octets et que la picture 7 n'existe pas, est ce que faire RclPict 6 fera crasher le programme ?)
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 16/08/2016 20:06 | #


Tu ne peux pas pré-disposer les Picture dans la mémoire. À chaque accès, tu dois faire appel au MCS pour la localiser, à moins de tenir les données en cache en admettant qu'elles ne sont pas modifiées pendant l'exécution de B2C.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 17/08/2016 19:43 | #


Bon, donc là je suis complètement bloqué au niveau d'écrire des fichiers dans la mémoire.

Dans les syscalls (http://media.taricorp.net/prizm/simon_chm/fx_legacy_MCShandles.htm ) j'utilise le putInternalItem car il prend en paramètre l'ID du dossier (5 pour les listes, par exemple). Toutefois une ID autre que 1 (dans le dossier "main") n'est comptée que pour les fonctions (id 2). Je peux mettre 5, 7, 2, le seul fichier créé sera "Y=DATA" qui contient les fonctions graphiques. Il est à noter que j'arrive parfaitement à créer des programmes dans le dossier "system" qui contient les programmes basic (si je mets l'ID 1, alors ce ne sera pas dans Y=DATA mais dans le dossier "PROGRAM").

Utiliser le MCSPutVar2 donne le même résultat (on ne peut écrire que dans PROGRAM ou Y=DATA), ce qui est logique car on ne peut pas contrôler l'ID du dossier (il faut PutInternalItem), mais là je ne sais absolument pas quoi faire.

Ajouté le 23/08/2016 à 14:36 :
J'arrive pas du tout à assigner une valeur à une variable alpha (avec Alpha_SetData). Je fais Alpha_SetData('A', _8_) mais à chaque fois ça fait la même erreur : le SDK me dit "CPU address error exception by data write access at 0x00000016" puis "nonexisting memory by data write access at 0xFFFFFFE4".

Pourtant j'ai testé toutes les manières de déclarer le nombre BCD : constante globale, globale, tableau local (un char[] au lieu d'un BCDvar) et dans la heap avec un calloc(24, 1) qui devrait m'afficher 0. Ca ne peut pas être le fait que la variable ne soit pas 'A' car dans ce cas ça devrait retourner 0, or ça plante dès l'appel à la fonction. J'ai aussi essayé de faire &_8_ mais ça plante aussi.

Est ce qu'il y a un exemple d'appel à Alpha_SetData pour voir comment on appelle cette fonction ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 23/08/2016 15:02 | #


D'après le prototype, il est assez évident que la forme à utiliser est :
BCDVar var = ...;
Alpha_SetData('A', &var);

Cela est aussi évident d'un point de vue conceptuel... maintenant pour tes erreurs, ça va être facile :

CPU address error exception by data write access at 0x00000016
Tentative d'utiliser un pointeur pour écrire une adresse dont la valeur est 22. Ça ressemble beaucoup à un entier utilisé comme pointeur. Ça peut s'expliquer si tu a passé la BCDVar au lieu de son adresse (typiquement).
Nonexisting memory by data write access at 0xFFFFFFE4
À peu près la même chose, mais cette fois c'est le MMU qui envoie l'erreur. L'idée est la même ; ça pourrait être un registre, mais si c'était le cas cette erreur n'aurait pas lieu d'être...

Si t'as des doutes, n'hésite pas à lire le tutoriel d'initiation à l'assembleur de Ziqumu et à programmer un peu d'assembleur pour préparer du désassemblage de syscalls. SimLo n'a visiblement pas tout documenté en détail ; c'est peut-être une bonne occasion de le faire.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 23/08/2016 15:08 | #


Hmm, mettre l'adresse de la BCDvar ne change rien :/

    const BCDvar _8_ = {0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    locate(1, 1); Print((unsigned char*)"TEST"); ML_display_vram();
    locate(1, 2); Print((unsigned char*)"TEST2"); ML_display_vram();
    if (setAlphaVar('A', &_8_)) {
        locate(1,7); Print("Erreur !");
        GetKey(&key);
    }

Pareil pour la déclaration en tableau au lieu de BCDvar, pour le calloc(), etc.
Sachant que BCDvar est une struct { unsigned char bytes[24]; }.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 23/08/2016 15:15 | #


Tu dois déconner. J'ai exécuté sur SH3 le code suivant avec succès... modifiant la valeur de A à 8 :

unsigned char bytes[24] = { 0 };
bytes[0] = 0x10;
bytes[1] = 0x08;
SetAlphaVar('A', bytes);

Avec la fonction SetAlphaVar() :
    .global    _SetAlphaVar
_SetAlphaVar:
    mov.l    syscall_table, r2
    mov.l    1f, r0
    jmp    @r2
    nop
1:    .long    0x4e0

T'as dû te tromper sur le numéro de syscall ou quelque chose dans le genre...
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 23/08/2016 15:40 | #


Hmm, c'est bizarre là, parce que ton code provoque le même problème. J'ai aussi testé sur l'autre émulateur et sur ma vraie calto, ça provoque une TLB error.

Pour définir la fonction SetAlphaVar je fais pas ça, je fais :
    .export    _setAlphaVar
//...
_setAlphaVar:
    mov.l    syscall_table, r2
    mov.l    _setAlphaVar_code, r0
    jmp    @r2
    nop
_setAlphaVar_code:
    .data.l    H'4E0
//...
syscall_table:
    .data.l    H'80010070

    .end


Et ton code assembleur ne compile pas sous le SDK (erreur à la ligne 4 "SYNTAX ERROR IN SOURCE STATEMENT" et ligne 7 "ILLEGAL SYMBOL OR SECTION NAME" et "ILLEGAL MNEMONIC") donc je peux même pas tester si c'est ça qui fait buger. Mais le code que j'utilise a marché jusque là pour tous les syscalls (d'ailleurs c'est toi qui me l'avait passé ) donc je vois pas pourquoi ça marcherait pas pour ce syscall précis.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 23/08/2016 15:46 | #


Le code fonctionne aussi sur ma SH4. T'as utilisé exactement mon code (j'entends par là un tableau d'octets et pas la structure) ? Voilà qui est étrange.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 31/08/2016 13:31 | #


Bon, en fait ça a servi à rien parce que ça tourne encore plus lentement qu'avant (1,43 seconde pour un tour d'IA). Je me souviens plus du benchmark que j'ai fait, mais si je me souviens bien ça allait 33% plus vite que le basic, alors que là ça va que 25% plus vite (sachant que pour le basic ça prend 1,90 seconde).

La solution serait de revenir à l'état où c'était avant (c'est à dire en ayant les variables dans l'addin, et en ne touchant pas au MCS) mais implémenter nous-même les fonctions de calcul (la lenteur de la première version venant du fait qu'il faille, pour chaque opération, mettre les valeurs dans A et B, puis faire le calcul avec calcExp()). Toutefois je vais laisser comme ça pour l'instant, pour deux raisons :
1 : j'ai la flemme (ce projet est en cours depuis 2 mois et je sais pas parser plus que mon puissance 4, du coup je vais avancer, et quand j'aurai fini je reviendrai sur ce point)
2 : parser les calculs est assez compliqué (il faut connaître toutes les fonctions, leur précédence, etc)

Pour les autres trucs (pictures, captures, etc) je toucherai plus au MCS par contre. Les strings en particulier seront, je pense, beaucoup plus rapides qu'en basic, car il y a un accès en O(1) aux caractères (mais ça prendra plus de mémoire), ce qui est permis en faisant des arrays de shorts.

Ajouté le 07/09/2016 à 13:17 :
Je n'arrive pas du tout à faire un StrMid() correct :/

Le format des strings est un array de char, et chaque caractère tient sur deux octets. Ce qui fait que le string "tést" est encodé en :
{XX, XX, 0, 't', 0xE6, 0x0A, 0, s, 0, t, 0, XX} avec une longueur de 4. Les deux octets du début sont pour préserver l'index 1.

Le type du string est :
typedef struct {
    int length;
    unsigned char* data;
} Str;


Mon code :
Str strings[20];
//...
void prog_LOCATE() {

    B2C_setStr(B2C_charArrayToStr("ABCD\xE6\xA6\xE6\xA7\xE6\xA5S"), FALSE, 0);
    //B2C_setStr(B2C_charArrayToStr("ABCDEF"), FALSE, 0);
    
    locate(1,2); Print(B2C_strToCharArray(&strings[0], TRUE));
    locate(1,1); Print(B2C_strToCharArray(B2C_strMid(&strings[0], TRUE, 5, 4), FALSE));
}
void B2C_setStr(Str *value, int isString, int strNum) {
    free(strings[strNum].data);
    strings[strNum].length = value->length;
    strings[strNum].data = malloc((value->length+2)*sizeof(short));
    strings[strNum].data[(value->length+1)*sizeof(short)] = 0x00;
    memcpy(strings[strNum].data + sizeof(short), value->data + sizeof(short), value->length * sizeof(short));
    if (!isString) free(value);
}
unsigned char* B2C_strToCharArray(Str *str, int isString) {
    int j = 0;
    //Initialize the buffer
    memset(stringBuffer, 0x00, 256);
    //Goes through the string, starting at 2
    for (i = sizeof(short); i <= (str->length+1) * sizeof(short) + 1; i++) {
        //Skip null bytes
        if (str->data[i]) {
            stringBuffer[j] = str->data[i];
            j++;
        }
    }
    if (!isString) free(str);
    return stringBuffer;
}
Str *B2C_charArrayToStr(unsigned char* charArray) {
    int strPos = sizeof(short);
    Str *result = malloc(sizeof(Str));
    result->data = calloc(257, sizeof(short));
    for (i = 0; charArray[i]; i++) {
        if (charArray[i] != 0xE5 &&
                charArray[i] != 0xE6 &&
                charArray[i] != 0xE7 &&
                charArray[i] != 0xF7 &&
                charArray[i] != 0xF9 &&
                charArray[i] != 0x7F) {
            strPos++;
        }
        result->data[strPos] = charArray[i];
        strPos++;
    }
    result->length = i+1;
    return result;
}
Str *B2C_strMid(Str *str, int isString, int start, int offset) {
    Str *result = malloc(sizeof(Str));
    if (!offset) {
        offset = str->length-start;
    }
    result->data = malloc((offset+2) * sizeof(short));
    //Set null byte at the end
    result->data[(offset+1) * sizeof(short)] = 0x00;
    result->length = offset;
    //Copy the substring
    memcpy(result->data + sizeof(short), str->data + start*sizeof(short), sizeof(short)*offset);
    if (!isString) free(str);
    return result;
}


Le StrMid() marche parfaitement avec les caractères normaux, mais il bug sur les caractères multi-bytes ; il semble arrêter le string lorsqu'il rencontre un caractère multi-byte pas suivi d'un autre multi-byte. Je ne sais absolument pas la raison, car les caractères multi-bytes devraient être traités comme les normaux, et strMid() ne fait pas de différence entre les deux vu qu'il copie les octets. Cela viendrait donc de strToCharArray, mais pourquoi il bugerait alors qu'il arrive très bien à m'afficher le string complet ? o_O
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 08/09/2016 22:07 | #


Ça ne te pose pas de problème de free() n'importe quoi dans B2C_setStr() ? Le tableau de strings n'est pas initialisé, chaque fois que tu affectes une valeur initiale à une Str tu free() un pointeur aléatoire. Un peu de retenue : on initialise le tableaux avec des { 0, NULL }, et on ne libère que les pointeurs valides.

Tu pourrais au moins initialiser les XX aussi. Et placer un vrai caractère terminal { 0x00, 0x00 }, plutôt que de te reposer uniquement sur la longueur. Bien sûr en théorie ce n'est pas nécessaire, mais c'est comme ça qu'on écrit du code stable.

Et donc, à la fin de B2C_setStr(), si le paramètre n'est pas un string (donc alloué temporairement depuis une chaîne littérale, si j'ai bien suivi), tu le libères... ou pas. Il y a deux pointeurs alloués (value et value→data), un seul libéré (cherchez l'erreur).

Pas la peine de se voiler la face non plus : sizeof(short) c'est 2, rien d'autre. Je ne suis pas sûr que ton code fonctionne sur un système où le short fait 4 octets, et de toute façon tu y perdrais tout avantage parce que les caractères de Casio font 16 octets (et rien d'autre, oui, je me répète). Autant remplacer la valeur, ce sera plus lisible.

Pourquoi dans B2C_setStr() tu alloues juste la taille nécessaire et dans B2C_charArrayToStr() tu alloues bourrinement 257 shorts ? Prends le temps d'appeler strlen().

Et puis, B2C_charArrayToStr() ne peut pas marcher. Tu dois garantir qu'à chaque tour de boucle on écrit un caractère dans la chaîne résultante, soit deux octets (et donc strPos doit augmenter de 2 à chaque passage). Voici un exemple pour mettre en évidence le problème. Considérons la chaîne "a\xe7b". Les opérations suivantes vont être effectuées :
→ Au début, strPos = 2.
→ 'a' est rencontré. La condition est validée, strPos est pré-incrémenté à 3, data[3] = 'a', strPos = 4.
→ 0xe7 est rencontré. La condition n'est pas validée, data[4] = 0xe7, strPos = 5.
→ 'b' est rencontré. La condition est validée, strPos est pré-incrémenté à 6, data[6] = 'b', strPos = 7.
Tu vois bien que l'écriture de 0xe7 a laissé strPos à une valeur impaire, ce qui est un problème vu que l'incrémentation dans la condition va passer au tour suivant. Une solution est d'ajouter à la condition la parité de strPos.

Comment ça se fait que dans B2C_strMid() il y ait deux paramètres "start" et "offset", et que tu écrives sans sourciller quelque chose comme "result→length = offset" ? Tu penses pas qu'il y a quelque chose à renommer ? Même remarque pour l'oubli de la libération du pointeur de données.

En espérant t'avoir aidé.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 08/09/2016 22:22 | #


et puis, B2C_charArrayToStr() ne peut pas marcher. Tu dois garantir qu'à chaque tour de boucle on écrit un caractère dans la chaîne résultante, soit deux octets (et donc strPos doit augmenter de 2 à chaque passage). Voici un exemple pour mettre en évidence le problème. Considérons la chaîne "a\xe7b". Les opérations suivantes vont être effectuées :
→ Au début, strPos = 2.
→ 'a' est rencontré. La condition est validée, strPos est pré-incrémenté à 3, data[3] = 'a', strPos = 4.
→ 0xe7 est rencontré. La condition n'est pas validée, data[4] = 0xe7, strPos = 5.
→ 'b' est rencontré. La condition est validée, strPos est pré-incrémenté à 6, data[6] = 'b', strPos = 7.
Tu vois bien que l'écriture de 0xe7 a laissé strPos à une valeur impaire, ce qui est un problème vu que l'incrémentation dans la condition va passer au tour suivant. Une solution est d'ajouter à la condition la parité de strPos.


Lephé tu as solutionné tout mon problème (enfin j'espère mais ça me paraît être le problème, le décalage fait que c'est mal découpé mais ça passe nickel quand je convertit en char array parce qu'il enlève juste les 0)

Pour le " result->length = offset " c'est parce que la longueur du résultat est tout simplement l'offset (donc strmid("abcdef", 3, 2) produit "cd" qui est de longueur 2).
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 09/09/2016 16:29 | #


Un offset est a priori un décalage. StrMid prend des paramètres « début » et « longueur ». En général on parlerait plutôt d'offset pour désigner le paramètre « début », parce que c'est un décalage initial du pointeur effectué avant tout traitement.

Bon après c'est pas ce qu'il y a de plus pertinent dans mon message mais vraiment, int start, int offset ça fait bizarre.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 22/12/2016 08:16 | #


Bon, en reprenant B2C (après 3 mois de glandage) je me suis rendu compte que je vais encore devoir réécrire le moteur de calcul è_é

Le premier moteur de calcul transformait les instructions en fonctions. Par exemple "3+4*2" devenait "add(multiply(3, 2), 4)". Toutefois ça laguait car ce que ces fonctions faisaient était de mettre les deux valeurs dans les variables A et B, et de demander à l'interpréteur de les multiplier.

Du coup j'ai refait le calcul, cette fois en passant directement par l'interpréteur. Donc je demandais directement à l'interpréteur de me calculer "3+4*2". Ca a requis que je passe par la mémoire alpha pour tout, pour les variables, listes, matrices... Et c'est là que je suis bloqué en fait, les strings (que je gère moi même pour un système plus rapide) ne passent pas par la mémoire alpha et il est donc impossible de les évaluer (avec StrLen).

La solution serait de revenir au premier moteur de calcul, mais en gérant les calculs sans l'interpréteur. Bien sûr j'ai aucune sauvegarde de la première version de B2C (ça m'apprendra à pas utiliser git) et donc ça va me prendre un p'tit bout de temps pour remettre comme avant.

Là où vous pouvez m'aider c'est tout simplement de faire les fonctions de calcul, sachant qu'il y en a certaines que je sais pas faire (racine carrée, trigo...) vu que je suis en terminale. Je gèrerai seulement les opérations basiques, donc pas d'intégrale, de dérivée, de nCr, etc (c'pas souvent qu'on utilise ces fonctions là dans un jeu).
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 22/12/2016 10:34 | #


Pour le calcul des fonctions, il y a essentiellement des approximations par des polynômes ou des suites convergentes. flo a fait du super boulot sur les fonctions trigos là-dessus, je pense qu'il en parlera mieux que moi

Dans l'ensemble tant que tu sais implémenter les quatre opérations il n'y a pas de problème pour écrire les fonctions classiques.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

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


J'ai fini les fonctions d'addition et de soustraction, c'est sur le gitlab : http://git.planet-casio.com/Zezombye/B2C/blob/master/B2C/src/B2CFunctions.c

Est ce qu'il y a des algorithmes plus performants que ceux qu'on apprend en primaire ? J'ai cherché sur google mais je trouve pas grand chose.
(ah et aussi, toute optimisation de ces fonctions est la bienvenue, vu qu'elles risquent d'être utilisées tout le temps )

Ajouté le 07/01/2017 à 19:53 :
J'ai updaté le topic avec l'avancement du projet, il avance assez vite depuis que je l'ai repris (et surtout depuis que j'ai appris à coder proprement )

Si vous voulez m'aider il y a 2 choses que vous pouvez faire :

- Des algorithmes pour les opérations (multiplication, division, peut être puissance, racine carrée et racine n-ième), actuellement je passe par l'interpréteur pour les calculer, mais un petit benchmark a fait 1.5s pour un algo implémenté contre 4.4s si on passe par l'interpréteur (pour calculer 10000 additions) donc ça augmenterait la vitesse.

- Trouver des programmes afin que je puisse les tester. Les programmes ne doivent pas être très compliqués (pas de ninestars/ne0tux/remiweb ) et ne doivent pas inclure les fonctions que je n'implémenterai pas (disp, strings standalone, input console).

Ajouté le 09/01/2017 à 07:25 :
J'ai un problème avec la fonction StrSrc qui ne fonctionne pas du tout... Je suis sûr que c'est un truc tout con mais je vois absolument pas o_o

typedef struct {
    int length;
    unsigned short* data;
} Str;

BCDvar *B2C_strSrc(BCDvar *buffer, Str *str1, int isString1, Str *str2, int isString2, int n) {
    int isString = isString1;
    n--;
    for (i = n; i < str1->length-str2->length+1; i++) {
        if (!memcmp(str1->data+i, str2->data+i, str2->length*2)) {
            intToBCD(i+1, buffer);
            goto freestrs;
        }
    }
    
    //str_not_found:
    buffer = &_0_;
    
    freestrs:
    free_str(str1);
    isString = isString2;
    free_str(str2);
    return buffer;
}


(oubliez les gotos et les freeStr, le problème ne vient pas de là)
Donc l'algorithme parcourt Str1 en vérifiant si Str2 matche Str1 à partir de i. Ca ne marche que pour le premier caractère (si str1 = "abcdefghij", chercher "a" retourne 1, chercher "ab" retourne 1, mais chercher "b" retourne 0)

Franchement je vois pas le problème :o
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir En ligne Administrateur Points: 24146 Défis: 170 Message

Citer : Posté le 09/01/2017 07:47 | #


memcmp(str1→data+i, str2→data+i, str2→length*2)

Ça ne te dérange pas de comparer str2→length caractères en commençant au milieucde str2 ? x)
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 11/01/2017 17:32 | #


J'ai updaté le topic avec 2 programmes convertis, je suis en train de convertir Gold Road (des CPC) mais sur l'émulateur le jeu m'a l'air de buger un peu, donc je le mettrai pas.

Actuellement je fais les fonctions graphiques, donc si vous avez des infos sur le fonctionnement de la ViewWindow et comment elle affecte les paramètres des diverses fonctions graphiques, ça m'aiderait beaucoup
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Précédente 1, 2, 3, 4, 5, 6

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

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

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

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

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