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.
Citer : Posté le 05/08/2016 19:08 | #
Tu précises à la fois :
- [...] 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 ?
- 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.
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).
Ecrivez vos programmes basic sur PC avec BIDE
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.
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 ?)
Ecrivez vos programmes basic sur PC avec BIDE
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.
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 ?
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 23/08/2016 15:02 | #
D'après le prototype, il est assez évident que la forme à utiliser est :
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.
Citer : Posté le 23/08/2016 15:08 | #
Hmm, mettre l'adresse de la BCDvar ne change rien :/
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]; }.
Ecrivez vos programmes basic sur PC avec BIDE
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 :
bytes[0] = 0x10;
bytes[1] = 0x08;
SetAlphaVar('A', bytes);
Avec la fonction 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...
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 :
//...
_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.
Ecrivez vos programmes basic sur PC avec BIDE
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.
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 :
int length;
unsigned char* data;
} Str;
Mon code :
//...
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
Ecrivez vos programmes basic sur PC avec BIDE
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é.
Citer : Posté le 08/09/2016 22:22 | #
→ 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).
Ecrivez vos programmes basic sur PC avec BIDE
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.
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).
Ecrivez vos programmes basic sur PC avec BIDE
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.
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
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
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 09/01/2017 07:47 | #
Ça ne te dérange pas de comparer str2→length caractères en commençant au milieucde str2 ? x)
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
Ecrivez vos programmes basic sur PC avec BIDE