Tous | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graphs 35 à 100
Graph 25
Graphs 75/85/95 (SD)
Graph 100(+)
Classpad 300/330 (+)
Fx-CG 10/20
Fx-CP 400

Retour à la liste des tutoriels
Tutoriel Casio : Maitrisez le temps avec RTC_getTicks()
Tutoriel rédigé le : 2014-02-27 22:03  par Dark storm  Catégorie : C/C++/ASM  Calculatrice : Graphs 75/85/95 (SD)

Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (42 commentaires)

Maitrisez le temps avec RTC_getTicks()
Un des meilleurs atouts que possède la programmation d'addins en C/C++, c'est de bénéficier du système Real Time Clock (RTC), et surtout du syscall RTC_getTicks(). Dans ce tutoriel, nous verrons en détail les différentes façon d'utiliser RTC_getTicks(), comme régulateur de FPS, compte à rebours, etc.

Sommaire :
1) Rappels sur les sycalls
2) Appeler RTC_getTicks()
3) Réguler ses FPS
4) Afficher les FPS
5) Chronométrer du temps
6) Régulariser des opérations avec les timers (n'utilise pas RTC_getTicks)
7) Générer des nombres aléatoires
Conclusion



1) Rappels sur les syscalls :

RTC_getTicks() est un syscall ("System Call" ou "Appel système"), c'est à dire une fonction déjà présente dans l'OS de la calculatrice. Il suffit donc de sauter à l'endroit où elle est stockée pour l'exécuter.
Pour cela, la meilleure méthode est de créer un fichier contenant les instructions en assembleur (ASM), puis de compiler le tout. Toutefois, cette méthode est lourde, et pas forcément très compréhensible par un programmeur lambda, d'autant plus que l'assembleur est un langage de bas niveau, c'est à dire très abstrait. Nous utiliserons donc une astuce plus ou moins correcte et valide, mais qui reste intégralement fonctionnelle.

Voici le code commenté pour appeler un syscall (ici RTC_getTicks) :
static int SysCallCode[] = {0xD201422B,0x60F20000,0x80010070}; // déclaration en global des adresses
static int (*SysCall)(int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode; // et des registres
// à ne placer dans votre code qu'une seule fois

int RTC_getTicks(void)
{
     return (*SysCall)(0, 0, 0, 0, 0x3B); // on déclare la fonction voulue selon son numéro (ici 0x3B)
}

// on peut répéter l'opération avec d'autres syscalls (ceci est un exemple sûrement non fonctionnel) :
int SYS_call(void)
{
     return (*SysCall)(0, 0, 0, 0, 0x42);
}

Vous pouvez placer ces fonctions n'importe où tant que vous avez mis un prototype avant le "main"


2) Appeler RTC_getTicks() :

Maintenant que nous avons déclaré RTC_getTicks, nous allons l'utiliser.
La fonction retourne le nombre de "ticks", des périodes durant 1/128ème de seconde, mesurées par l'horloge interne de la calculatrice depuis sa mise en service (ou une autre date, Casio n'ayant jamais fourni de renseignements sur ce point).
Pour cela, prévoyez un int pour récupérer la valeur :
int ticks = 0;
ticks = RTC_getTicks();



3) Réguler ses FPS :

Les Frames Per Second (FPS), en français "images par seconde", sont un élément important d'un jeu. En effet, si ceux-ci ne sont pas régulés, il peut et y aura des différences d'exécution entre différents modèles, particulièrement entre les SH3 et les SH4. De plus, certaines fonctions comme IsKeyDown() provoquent des ralentissements lorsque des touches sont enfoncées, et peuvent fortement modifier la vitesse d'exécution du jeu, le rendant moins agréable à utiliser.
Heureusement, nous avons à notre disposition en C/C++ la fonction RTC_getTicks(). Grace à celle-ci, nous allons réguler de manière dynamique le nombre de FPS de notre jeu.
Nous allons donc créer une fonction qui retiendra le nombre de ticks écoulés depuis le dernier appel de la fonction. Du coup, si le programme est en avance, nous le mettons en pause jusqu'à ce qu'il soit à l'heure. Nous définissons donc un nombre précis de ticks qu'il faudra laisser écouler par frame.
Sachant que 1 tick = 1/128 seconde, nous pouvons en déduire que laisser 1 tick s'écouler équivaut à 128 / 1 = 128 FPS, 2 ticks = 128 / 2 = 64 FPS, 3 ticks = 128 / 3 = 42 FPS, etc.
Nous donnerons donc en argument à la fonction le nombre de ticks à laisser tourner. Voici un récapitulatif des valeurs les plus utilisées :
Spoiler
1 = 128 FPS
2 = 64 FPS
3 = 42 FPS
4 = 32 FPS
5 = 25 FPS
6 = 21 FPS
7 = 18 FPS
...
128 / x = y FPS


Voici la fonction complète :
void setFps(int fpsWish)
{
    static unsigned int fps = 0, fps_count = 0; // "static" permet de garder les valeurs en mémoire entre les différents appels

    do
    {
        fps = RTC_getTicks(); // on enregistre les ticks
                Sleep(1); // permet d'économiser de la batterie
    }
    while(fps < fps_count+fpsWish); // tant que ceux-ci ne se sont pas suffisamment écoulés
    fps_count = RTC_getTicks(); // on met à jour les dernières valeurs
}


Pour l'utiliser, rien de plus simple :
while(1)// boucle principale
{
    ... // instructions
    
    setFps( 5 ); // pour réguler à 25 FPS
}



4) Afficher les FPS :

Réguler les FPS, c'est cool, mais dans le cas d'un jeu qui demande beaucoup de ressources, il est intéressant de connaitre le nombre de FPS maximal que l'on peut avoir. Pour cela, nous allons une fois de plus utiliser RTC_getTicks(). La fonction que nous allons créer retournera un int, le nombre de FPS de la dernière seconde écoulée.
int getFps()
{
    // variables utilisées (en static, pour pouvoir garder en mémoire les valeurs)
    static int disp_fps=0, fps=1, time=0;

    if(RTC_getTicks() - time > 128) // si il s'est écoulé une seconde complète
    {
        disp_fps = fps; // alors on récupère le nombre de FPS
        fps = 0; // on remet à 0 le compteur
        time = RTC_getTicks(); // et on se rappelle du nombre de ticks de la dernière seconde écoulée
    }

    fps++; // on monte la valeur des FPS

    return disp_fps;
}


Vous n'avez plus qu'à appeler la fonction dans votre boucle principale pour récupérer le nombre de FPS:

int fps = 0
;
while(1)// boucle principale
{
    ... // instructions

    fps = getFps();
    PrintVariable(fps);
}


NB 1 : La fonction PrintVariable( int variable ) sert à afficher une variable à l'écran. Vous devez donc adapter ce code en fonction de vos besoins.
NB 2 : Vous trouverez dans les commentaires de ce tutoriel une autre méthode, tout aussi valable. A vous de choisir


5) Chronométrer du temps :

Dans le cas d'un jeu qui a besoin de savoir combien de temps s'est écoulé depuis une action, vous pouvez enregistrer un temps de référence, puis calculer le temps écoulé en ticks en faisant une simple soustraction, puis convertir le résultat en secondes, minutes et autres unités de temps.
Par exemple, pour indiquer le temps écoulé depuis le lancement de la boucle :
... // instructions

temps_reference = RTC_getTicks(); // on enregistre le temps de référence

while(1)
{
    ... // instructions
    
    temps_actuel = RTC_getTicks(); // on récupère le temps actuel
    temps_ecoule = (int)((temps_actuel - temps_reference) / 128); // le cast (int) permet d'avoir un code plus propre et d'éviter des (W) lors de la compilation
    
    PrintVariable(temps_ecoule); // on affiche le temps en secondes

    ... // instructions
}



6) Régulariser des opérations avec les timers (n'utilise pas RTC_getTicks) :

En construction...
Vous pouvez déjà aller voir la documentation française de fxlib.
Je pense créer un tutoriel entier sur les timers, puisque nombreuses sont les astuces et utilisations que l'on peut en faire.



7) Générer des nombres aléatoires :

Un tutoriel à déjà été écrit sur ce sujet, vous trouverez ici des explicitons sur l'utilisation de RTC_getTicks() dans la création de nombres aléatoires.


Conclusion :

Avec ces quelques explications, vous devriez pouvoir maitriser le temps sur votre calculatrice, même si, bien entendu, ces quelques exemples ne sont pas représentatifs de toutes les possibilités offertes par le système RTC. Vous pouvez par exemple créer un jeu qui lance des quêtes qu'à des horaires réguliers, des succès à débloquer si on a joué plus de 1 heure, etc.

Si toutefois vous avez encore des questions, n'hésitez pas à les poser-ci dessous, dans ce topic dédié.


A bientôt sur Planète Casio !


Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (42 commentaires)

Publicité et partenaires
Casio Education
Casio éducation

TI-Planet
Casiopeia
Casiopeia
CasioFan, la communauté ClassPad
CasioFan
CodeWalrus
CodeWalrus

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2015 | Il y a 83 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Rugby Manager | Jeu de basket | Jeu de handball | Jeu de tennis | Nova Raider | Réparation téléphone | Soccer Rush | Tasty Tale

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd