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 - Autres questions


Index du Forum » Autres questions » Portage du malical sur calculatrice sh4 [Done]
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Portage du malical sur calculatrice sh4 [Done]

Posté le 12/05/2018 13:48

Ce projet est d'ors et déjà terminé, n'hésitez pas à télécharger le résultat en pièce jointe
(les fonctions d'overclock n'ont pas été portés pour des raisons principalement d'ordre technique)



Je me suis lancé il y a peu dans la rédaction d'un tutoriel pour le langage de programmation nommé Malical et développé il y a quelques années spécifiquement pour les calculatrices graphique monochrome de chez Casio.

À ma grande surprise, l'add-ins développé pour les sh3 s'est avéré marcher à merveille sur sh4, a un détail près, en effet les fonctions interagissant avec le RTC ne marche pas sur sh4 (d'après ce que j'ai compris des paroles de Lephé, l'adresse du syscall pour la RTC est différente sur sh4), et donc par extension, la seed pour l'aléatoire est toujours la même (donc c'est plus trop de l'aléatoire ^^  ), car cette seed (comme sur de nombreux programmes) est généré via des appels à la RTC.

Ainsi, me voyant mal faire un tuto sur un langage assez simple et idéal pour passer du Basic vers le C uniquement pour les propriétaires d'une calculatrice datant d'avant 2012, j'ai pour intention de porter le Malical pour les sh4.

J'ai donc téléchargé les sources, puis commencé à analyser le code source. Après avoir compris la structure de fonctionnement du programme, j'ai été en mesure de localiser les endroits ou ça coince. Le principe de fonctionnement de ce langage est donc d’interpréter des fichiers texte avec un parser, puis appeler les fonctions en C correspondante avec les bons arguments, lorsque l'on trouve le nom d'une fonction (ya un passage par une sorte de dico qui associe les chaines de caractères censé appeler une fonction à la fonction en elles même,sans doute pour pouvoir utiliser les même noms de fonction que le SDK sans les appeler directement).

Les fonctions qui posent problème sont donc toutes celles qui interagissent avec le RTC:


void mcl_rtcreset    (ObjectStack *,Object *);
void mcl_setyear    (ObjectStack *,Object *);
void mcl_setmonth    (ObjectStack *,Object *);
void mcl_setdomonth    (ObjectStack *,Object *);
void mcl_setdoweek    (ObjectStack *,Object *);
void mcl_sethour    (ObjectStack *,Object *);
void mcl_setminute    (ObjectStack *,Object *);
void mcl_setsecond    (ObjectStack *,Object *);
void mcl_readyear    (ObjectStack *,Object *);
void mcl_readmonth    (ObjectStack *,Object *);
void mcl_readdomonth(ObjectStack *,Object *);
void mcl_readdoweek    (ObjectStack *,Object *);
void mcl_readhour    (ObjectStack *,Object *);
void mcl_readminute    (ObjectStack *,Object *);
void mcl_readsecond    (ObjectStack *,Object *);

void mcl_cpuspeed    (ObjectStack *,Object *);

//Un exemple de à quoi ressemble les fonctions, attention, c'est condensé.

void mcl_setyear(ObjectStack *arg_stk,Object *objr)
{
    int i;
    if (arg_stk->size!=4) MalicalError(NUM_ERROR);
    for (i=0;i<4;++i) if (!o_is_num(arg(i))) MalicalError(ARG_ERROR);
    RTCSetYear (    value(0).d,value(1).d,
                    value(2).d,value(3).d);
    obj_create(objr,VT_NIL,0);
}



Dans ces fonctions, ce qui pose problème, sont les fonctions CPUSpeed, RTCSet et RTCRead, toutes issues de la bibliothèque Revolution-FX.
Je me suis donc ensuite lancé dans l'exploration des sources de Revolution-FX, et effectivement j'ai pu retrouver lesdites fonctions qui utilise belle et bien un syscall pour utiliser la RTC.Toutes ces fonctions sont écrite en C++ en utilisant la même 'structure': RTC


/*
    Functions for accessing the RTC. The SuperH sees these values
    as BCD (binary coded decimals).
    Example:
        thousands = 2;
        hundreds = 0;
        tens = 0;
        ones = 7;
    Will give you: 2007 in decimal
*/

struct st_rtc {                                         /* struct RTC   */
              unsigned char     R64CNT;                 /* R64CNT       */
              char              wk1;                    /*              */
              union {                                   /* RSECCNT      */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char    :1;         /*              */
                           unsigned char S10:3;         /*    10sec     */
                           unsigned char S1 :4;         /*     1sec     */
                           }      BIT;                  /*              */
                    }           RSECCNT;                /*              */
              char              wk2;                    /*              */
              union {                                   /* RMINCNT      */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char    :1;         /*              */
                           unsigned char M10:3;         /*    10min     */
                           unsigned char M1 :4;         /*     1min     */
                           }      BIT;                  /*              */
                    }           RMINCNT;                /*              */
              char              wk3;                    /*              */
              union {                                   /* RHRCNT       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char    :2;         /*              */
                           unsigned char H10:2;         /*    10sec     */
                           unsigned char H1 :4;         /*     1sec     */
                           }      BIT;                  /*              */
                    }           RHRCNT;                 /*              */
              char              wk4;                    /*              */
              union {                                   /* RWKCNT       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char   :5;          /*              */
                           unsigned char WK:3;          /*    week      */
                           }      BIT;                  /*              */
                    }           RWKCNT;                 /*              */
              char              wk5;                    /*              */
              union {                                   /* RDAYCNT      */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char    :2;         /*              */
                           unsigned char D10:2;         /*    10day     */
                           unsigned char D1 :4;         /*     1day     */
                           }      BIT;                  /*              */
                    }           RDAYCNT;                /*              */
              char              wk6;                    /*              */
              union {                                   /* RMONCNT      */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char    :3;         /*              */
                           unsigned char M10:1;         /*    10mon     */
                           unsigned char M1 :4;         /*     1mon     */
                           }      BIT;                  /*              */
                    }          RMONCNT;                 /*              */
              char             wk7;                     /*              */
              union {                                   /* RYRCNT       */
                    unsigned short WORD;                /*  Word Access */
                    struct {                            /*  Bit  Access */
                           unsigned short Y1000:4;      /*   1000year   */
                           unsigned short Y100 :4;      /*    100year   */
                           unsigned short Y10  :4;      /*     10year   */
                           unsigned short Y1   :4;      /*      1year   */
                           }       BIT;                 /*              */
                    }           RYRCNT;                 /*              */
              union {                                   /* RSECAR       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char S10:3;         /*    10sec     */
                           unsigned char S1 :4;         /*     1sec     */
                           }      BIT;                  /*              */
                    }           RSECAR;                 /*              */
              char              wk8;                    /*              */
              union {                                   /* RMINAR       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char M10:3;         /*    10min     */
                           unsigned char M1 :4;         /*     1min     */
                           }      BIT;                  /*              */
                    }           RMINAR;                 /*              */
              char              wk9;                    /*              */
              union {                                   /* RHRAR        */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char    :1;         /*              */
                           unsigned char H10:2;         /*    10sec     */
                           unsigned char H1 :4;         /*     1sec     */
                           }      BIT;                  /*              */
                    }           RHRAR;                  /*              */
              char              wk10;                   /*              */
              union {                                   /* RWKAR        */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char    :4;         /*              */
                           unsigned char WK :3;         /*    week      */
                           }      BIT;                  /*              */
                    }           RWKAR;                  /*              */
              char              wk11;                   /*              */
              union {                                   /* RDAYAR       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char    :1;         /*              */
                           unsigned char D10:2;         /*    10day     */
                           unsigned char D1 :4;         /*     1day     */
                           }      BIT;                  /*              */
                    }           RDAYAR;                 /*              */
              char              wk12;                   /*              */
              union {                                   /* RMONAR       */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char ENB:1;         /*    ENB       */
                           unsigned char    :2;         /*              */
                           unsigned char M10:1;         /*    10mon     */
                           unsigned char M1 :4;         /*     1mon     */
                           }      BIT;                  /*              */
                    }           RMONAR;                 /*              */
              char              wk13;                   /*              */
              union {                                   /* RCR1         */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char CF :1;         /*    CF        */
                           unsigned char    :2;         /*              */
                           unsigned char CIE:1;         /*    CIE       */
                           unsigned char AIE:1;         /*    AIE       */
                           unsigned char    :2;         /*              */
                           unsigned char AF :1;         /*    AF        */
                           }      BIT;                  /*              */
                    }           RCR1;                   /*              */
              char              wk14;                   /*              */
              union {                                   /* RCR2         */
                    unsigned char BYTE;                 /*  Byte Access */
                    struct {                            /*  Bit  Access */
                           unsigned char PEF  :1;       /*    PEF       */
                           unsigned char PES  :3;       /*    PES       */
                           unsigned char RTCEN:1;       /*    RTCEN     */
                           unsigned char ADJ  :1;       /*    ADJ       */
                           unsigned char RESET:1;       /*    RESET     */
                           unsigned char START:1;       /*    START     */
                           }      BIT;                  /*              */
                    }           RCR2;                   /*              */
};

#define RTC   (*(volatile struct st_rtc   *)0xFFFFFEC0) /* RTC     Address*/


//Et un petit exemple d'utilisation de cette structure:

void RTCSetYear(unsigned char thousands, unsigned char hundreds, unsigned char tens, unsigned char ones)
{
    RTC.RYRCNT.BIT.Y1000 = thousands;
    RTC.RYRCNT.BIT.Y100 = hundreds;
    RTC.RYRCNT.BIT.Y10 = tens;
    RTC.RYRCNT.BIT.Y1 = ones;
}



Cette énorme structure semble permettre d’accéder a chaque valeur du temps (années, mois, jour, ... ), stocké sous forme de BCD (j'avoue, sans les commentaires j'airais pas trouvé...).

maintenant, c'est là que j'ai besoin de votre aide, car si comprendre un code est une chose, le réécrire en est une autre... Et je ne sais pas par où commencer (corriger revolution-FX, réécrire l'add-ins...).

– Ai-je été clair, est-ce que je dois réexpliquer une partie?

– Est-ce que ma maigre compréhension du sujet est correct ? ou ai-je raté des trucs?

- Pour corriger le truc est-ce que remplacer l'adresse de la RTC sh3 par celle de la sh4 suffirait? (je me doute que non, ce serait trop simple, mais bon qui ne tente rien n'a rien )

- Avez-vous réussi à lire jusqu'ici sans vous endormir ?

-A-t-on une librairie pour gérer le temps sur sh4? Sinon, comment utiliser le syscall de la RTC avec le sh4? (j'ai commencé à regarder comment c'était fais avec gint, mais les sources sont immenses et la partie que je recherche probablement en assembleur..)

Merci d'avoir pris le temps de me lire
Et merci d'avance pour la moindre piste que vous pourriez m'apporter.


Fichier joint


Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 25/05/2018 21:11 | #


un idiot a écrit :
J'ai finalement décidé de ne pas porter la fonction IskeyDown(), car getkey() et Waitkey() fonctionne à merveille. Cela serait redondant


En fait c'est faux, Iskeydown est le seul moyen de vérifier les touches enfoncé sans mettre en pause le programme, contrairement aux Waitkey (ça c'est évident), et au Getkey. Au final, celui qui est redondant serait plutôt Waitkey.

Ajouté le 25/05/2018 à 21:12 :
Donc je m'y remets ce weekend...

Ajouté le 26/05/2018 à 11:13 :
Donc j'ai déjà trouvé comment je vais m'y prendre, en effet je vais créer une fonction Iskeydown custom qui reprend celle du patch proposé par DS et rajouter un switch pour faire correspondre les anciennes code de touche avec les nouveaux.
Cependant je me posais la question sur la vitesse d'un telle switch, qui contiendrait donc 50 case, en langage interprété, nul doute que le code s'en trouverait ralentit, qu'en est-t-il en C? mais peur sont-elles fondées
Lephenixnoir En ligne Administrateur Points: 24670 Défis: 170 Message

Citer : Posté le 26/05/2018 11:21 | #


Le temps qu'il faut pour chercher le bon case dans un switch n'augmente pas proportionnellement au nombre de case : typiquement, chaque fois que tu vas doubler le nombre de cas, il faudra une étape de plus (et pas le double d'étapes) pour trouver le bon. C'est donc rapide.

En revanche comme les codes renvoyées par le IsKeyDown() du patch ont tous des petites valeurs (inférieures à 100) tu peux carrément faire un tableau
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Nemhardy Hors ligne Grand maître des Traits d'Esprit Points: 1243 Défis: 54 Message

Citer : Posté le 26/05/2018 11:26 | #


Au delà de la question de la vitesse, il serait peut être plus élégant, suivant la teneur des valeurs des touches que tu veux convertir (quitte à les normaliser un peu), d'utiliser un tableau qui te permettrait de faire la correspondance.

Sinon, tu as quelques éléments concernant les performances du langage (j'ai peut être raté ça quelque part ceci dit…), du type quelques benchmark de programmes «simples» mais qui permettent de voir comment le langage et l'interpréteur se comportent dans différents domaines (calcul, graphismes, etc) ? Ce n'est sans doute pas prioritaire, mais ça serait intéressant je pense.
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 11:31 | #



Un tableau comme celui déjà utilisé pour faire correspondre les fonctions mcl avec leur équivalent en C, excellente idée.

Pour le benchmark, je n'ai rien à te proposer, en revanche dans les sources il y a une miriade de petit programmes en Malical (les .mcl) qui permettent de voir les possibilités de ce langage, je te conseille notamment 3Dfunc et periodique.

Ajouté le 26/05/2018 à 13:57 :
En fait, non j'ai pas compris l'histoire de tableau, pourrait tu m'expliquer?

Et en suite,, je rencontre un problème avec le patch, en effet la touche [X,θ,T] semble manquer à l'appel et la touche [AC/On] et moins on toute les deux le même code. est ce normale? est-ce un oublie?
Nemhardy Hors ligne Grand maître des Traits d'Esprit Points: 1243 Défis: 54 Message

Citer : Posté le 26/05/2018 14:54 | #


Ce que je veux dire c'est que par exemple, si tu voulais faire le schéma d'association suivant (juste un exemple pour voir le principe) : 1 → 4, 2 → 1, 3 → 3, 4 → 2, tu pourrais par exemple utiliser un tableau int association[] = {0, 4, 1, 3, 2}; alors, association[2] te donnera la valeur 1, et ainsi de suite.
Après suivant la tête des valeurs que tu as en entrée (sont-elles grandes ? sont-elles proches ? etc), ça peut nécessiter plus ou moins de travail de «normalisation» des valeurs (les ramener dans un petit intervalle pour un ne pas avoir un tableau trop grand), voire ne pas être très intéressant…
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 14:56 | # | Fichier joint


Bonne nouvelle, le switch marche, sauf que la touche [X,θ,T] ne marche pas (logique) et la touche moins se comporte comme la touche [AC/On] (encore une fois, c'etait prévisible).

Ajouté le 26/05/2018 à 15:11 :
Effectivement, cela pourrait être intéressant si l'intervalle de départ n’était pas [40, 30016] a la limite l'inverse pourrait être possible en faisant un keycodebasic = association.index(keycode) (enfin l'équivalent en C) on aurait alors un tableau de 80 short ou l'on utiliserait seulement les valeurs de 25 à 79, donc un petit offset pour avoir un tableau de 65, mais est-ce réellement plus élégant?
Lephenixnoir En ligne Administrateur Points: 24670 Défis: 170 Message

Citer : Posté le 26/05/2018 15:13 | #


Tu as inversé je pense : ton objectif est de convertir les valeurs Basic (25 - 79) fournies par le patch en les valeurs usuelles (autour de 30000).

Et oui, le tableau est réellement plus élégant que le switch. Meilleur en temps, meilleur en espace, il n'y a pas à hésiter.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 15:19 | #


Dans le but de simuler la fonction Iskeydown des SH3, je dois belle et bien récupérer une valeur usuelle pour la convertir en la valeur Basic pour la donner à la fonction KeyDown du patch.

au passage, ai-je le droit de dire que j'ai vachement l'impression que le patch est incomplet? et ce sans paraitre arrogant?

Ajouté le 26/05/2018 à 16:19 :
Du coup, j'ai rajouter la ligne manquante pour KEY_CTRL_XTT, il me reste à trouvé le code pour [AC/On] et le confirmation que parcourir un tableau pour comparer une a une ces valeurs pour renvoyer l'index est belle et bien plus rapide qu'un switch et ce sera bon (je suppose que non, la complexité d'un switch est en O(n) comme le parcours d'une liste, à moins de trier mon tableau et faire une recherche dichotomique qui est en O(log(n)), mais est-ce encore le cas après compilation?)

Lephenixnoir En ligne Administrateur Points: 24670 Défis: 170 Message

Citer : Posté le 26/05/2018 16:37 | #


Tu n'as pas tout saisi. Le switch est en O(log n) parce qu'il le peut (recherche dichotomique parmi les entiers associés aux case), mais ton tableau il est en O(1). Tu ne cherches pas : tu lis tableau[patch_code] et tu obtiens fxlib_code.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 16:44 | #


certe, l'acces directe est ideal, sauf qu'encore une fois je souhaite avoir tableau[fxlib_code] pour obtenir patch_code, créer une simple liste n'est donc pas envisageable, d’où mon idée de parcourir une liste qui contienne les fxlib_code pour renvoyer l'index qui sera patch_code.

Mais si cette solution est équivalente à un switch, il faut que je trouve autre chose.
Lephenixnoir En ligne Administrateur Points: 24670 Défis: 170 Message

Citer : Posté le 26/05/2018 16:51 | #


Si la performance est vraiment un souci tu ferais tout aussi bien de remplacer les macros KEY_* de fxlib par les valeurs renvoyées par le patch (tout en vérifiant que le code de Malical n'utilise pas les valeurs explicites), et le coût en temps et en espace sera de 0, tout étant calculé à la compilation.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 17:01 | #


Le problème, c'est que le Malical ne gère pas ces macros, donc l'utilisateur va rentrer un truc du genre Iskeydown[30015], donc si je veux que les valeurs soit les mêmes sur SH3 ou SH4,
je dois faire une conversion. La performance n'est en soit pas un problème, j'essaie juste d'être le plus rapide possible pour approcher la fonction Iskeydown originale qui elle n'a pas cette conversion.

Je suis donc arrivé a une solution intermédiaire qui est de faire plusieurs petites liste patch_code = tableau[fxlib_code] (5 ou 6) avec des if pour encadrer ces listes et sélectionner la bonne
Hackcell En ligne Maître du Puzzle Points: 1532 Défis: 11 Message

Citer : Posté le 26/05/2018 18:40 | # | Fichier joint


Au final, j'hésite vraiment, car au final le switch et cette méthode auront donc le même nombre d'étapes, quand à savoir ce qu'il y a de plus lisible entre un switch et une suite de comparaison puis de récupération dans des listes...

Donc je viens de finir la version avec des switchs, j'annonce donc que le Malical supporte la fonction Iskeydown sur SH4.
Lephenixnoir En ligne Administrateur Points: 24670 Défis: 170 Message

Citer : Posté le 26/05/2018 19:03 | #


Très bonne nouvelle !

On atteint avec impatience les tutoriels pour mettre un peu plus de sucre dans les yeux des lecteurs.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)

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 166 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