Seuls les membres ayant 30 points peuvent parler sur le chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » gint : un noyau pour développer des add-ins
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

gint : un noyau pour développer des add-ins

Posté le 20/02/2015 17:30

Les SDKs classiques pour écrire des add-ins sont le fx-9860G SDK de Casio avec fxlib (pour Graph monochrome) et le PrizmSDK avec libfxcg (pour Prizm et Graph 90+E). Voici mon alternative : le fxSDK avec gint, pour toutes les plateformes.

Contrairement à fxlib et libfxcg, qui appellent les fonctions de l'OS pour faire leur travail, gint est un noyau indépendant de l'OS qui exploite seul le matériel et le met à disposition de votre add-in. Il vous offre plus de finesse sur le contrôle du matériel, notamment le clavier, l'écran et les horloges, de meilleurs performances sur le dessin, les drivers et la gestion de interruptions, et des choses entièrement nouvelles comme le moteur de gris.

Toutes les sources de gint sont publiques et accessibles sur la forge de Planète Casio :

» Dépôt Gitea Lephenixnoir/gint «

Voici plus précisément ce que gint vous offre de nouveau :

• Un contrôle détaillé du clavier pour les jeux, parfait pour les combos !
• Des timers avec une précision de 60 ns, d'autres à 30 µs
• Toutes vos images converties automatiquement sans code à copier (plus de Sprite Coder)
• Des polices personnalisées
• Des fonctions de dessin, d'images et de texte fulgurantes et optimisées la main
• Mesurer les performance de votre code à la microseconde près (avec libprof)
• Le contrôle du matériel et des interruptions
• Plein de petites choses pratiques comme dprint(1, 1, "x=%d", x)

• (Graph monochrome) Un moteur de gris pour faire des jeux en 4 couleurs !
• (Graph monochrome) La compatibilité SH3 et SH4, avec le même fichier g1a.

• (Graph 90+E) Une nouvelle police de texte, plus lisible et économe en espace
• (Graph 90+E) Le dessin en plein écran, sans les bordures blanches et la barre de statut !
• (Graph 90+E) Un driver écran capable de triple-buffering

Le coût de tout ceci, c'est que vous avez une copie du code de gint dans votre add-in. Cela prend environ 20 ko de place (selon la quantité de fonctions que vous utilisez), soit à peu près comme le sprintf() de fxlib qui fait 18 ko !

Et voici quelques photos et captures d'écran !





Tester gint sur votre machine

La fin du portage vers la Graph 90+E signera la sortie de gint v2. L'add-in de test de l'application est désormais gintctl :

» Dépôt Gitea Lephenixnoir/gintctl «

En plus de tester les fonctionnalités de gint, cet add-in contient quelques outils permettant d'inspecter la machine, la mémoire, et les registres. Je le développe au fur et à mesure, et je posterai un protocole de test complet avec la sortie de la v2 !

Utiliser gint pour développer des add-ins

Normalement, vous avez besoin du fxSDK pour développer avec gint. Le fxSDK est compatible avec Linux et Mac OS, et on peut réfléchir à un portage sous Windows s'il y a vraiment des intéressés. Il faut l'installer en premier (et avoir un cross-compilateur GCC).

La procédure de compilation et d'installation de gint est décrite sur le README du dépôt, c'est du configure - make tout à fait banal.

Une fois que gint est installé sur votre système, voyez les tutoriels de développement pour avoir un aperçu de son fonctionnement. La plupart des choses sont expliquées dans les en-têtes (fichiers .h) de la bibliothèque que vous pouvez consulter en ligne, sur votre copie locale du dépôt, ou dans les dossiers d'installation du compilateur.

Obtenir la dernière version de gint après une mise à jour

Je pousse régulièrement des mises à jour de gint sur le dépôt du projet. Pour les télécharger, tapez git pull, puis recompilez et réinstallez gint avec make et make install.


Fichier joint


Pages : Précédente1 ... , 20, 21, 22, 23, 24, 25, 26, 27, 28Suivante
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 08/09/2019 17:38 | #


Excellent ! Tout devrait tomber en place rapidement.
Max1trucHors ligneMembrePoints: 17 Défis: 0 Message

Citer : Posté le 08/09/2019 17:59 | #


En fait, je rencontre un nouveau problème, en incluant respectivement les dossiers include et lib avec -I et -L.
$ fxsdk build-fx

:: Making into build-fx

sh4eb-nofpu-elf-gcc -o build-fx/src/Piles.elf build-fx/src/main.o  -mb -ffreestanding -nostdlib -Wall -Wextra -fstrict-volatile-bitfields -std=c11 -Os -I/home/user/Documents/src/casio/include -L/home/user/Documents/src/casio/lib -m4-nofpu -DFX9860G -Tfx9860g.ld -lgint-fx  -lgcc -Wl,-Map=build-fx/map
/home/user/Documents/src/casio/lib/gcc/sh4eb-nofpu-elf/8.3.0/../../../../sh4eb-nofpu-elf/bin/ld: cannot open linker script file fx9860g.ld: No such file or directory
collect2: error: ld returned 1 exit status
Makefile:73: recipe for target 'Test.g1a' failed
make: *** [Test.g1a] Error 1

Visiblement il ne trouve pas le fichier fx9860g.ld

EDIT: "fx9860g.ld" est dans le dossier bin de mon préfix custom, le même dossier que "libgint-fx.a"

Ajouté le 08/09/2019 à 18:06 :
En fait, c'est bon il suffisait d'utiliser le dossier "bin" au lieu du dossier "lib" pour l'option "-L"
Niveau de curiosité:
   99%
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 08/09/2019 18:06 | #


Ah, intéressant ! Il faut visiblement spécifier explicitement -L au linker pour ajouter un répertoire personnalisé à la recherche du linker script. Essaie avec -Xlinker -L -Xlinker <folder> en plus.

Edit : Okay, tant mieux !
Max1trucHors ligneMembrePoints: 17 Défis: 0 Message

Citer : Posté le 08/09/2019 21:37 | #


Une petite question, comment puis-je faire des syscalls avec fxsdk, gint et gcc? La méthode pour le SDK casio ne fonctionne pas...
Niveau de curiosité:
   99%
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 08/09/2019 21:56 | #


On les fait proprement en assembleur. La méthode utilisée en C avec le SDK est une aberration...

Il y a plein d'exemples ici : https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/compat/src/core/syscalls.S

Fais gaffe à ce que tu appelles ; s'il y a un équivalent gint alors il faut définitivement utiliser cet équivalent. Si tu arrives ou n'arrives pas à utiliser des syscalls, je veux bien savoir ; les limites de ce qui est compatible sont encore floues.
Max1trucHors ligneMembrePoints: 17 Défis: 0 Message

Citer : Posté le 08/09/2019 22:10 | #


En fait j'ai créé un fichier "syscalls.S" avec ce code:
.global _battery

.section ".pretext"

#define syscall(id)                     \
        mov.l   syscall_table, r2       ;\
        mov.l   1f, r0                  ;\
        jmp     @r2                     ;\
        nop                             ;\
1:      .long   id

_battery:
        syscall(0x39C)

Mais à la compilation il ne trouve pas le fichier en assembleur.
Niveau de curiosité:
   99%
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 08/09/2019 22:18 | #


Ah, mais c'est que j'ai pas mis les règles assembleur. Fiouh...

J'ai poussé sur le dépôt du fxSDK une nouvelle version du Makefile avec les règles appropriées. Pour l'utiliser, il suffit normalement (mais pas pour toi) de pull le dépôt et réinstaller le fxSDK, puis taper fxsdk update dans le dossier de ton projet.

Sauf que tu as modifié le Makefile, et la dernière commande l'écraserait. Tu veux certainement pas repartir de zéro. Tu peux faire la dernière étape à la main en récupérant les nouvelles règles ici : https://gitea.planet-casio.com/Lephenixnoir/fxsdk/commit/4f145cb202ae7104e12ba2e1f6d49e93dc2e6fa0

Je réalise que mon Makefile n'est pas vraiment flexible, il est issu de celui de gintctl et ne permet pas du tout de changer de toolchain facilement. Il faut que j'en fasse un plus souple.
Max1trucHors ligneMembrePoints: 17 Défis: 0 Message

Citer : Posté le 08/09/2019 22:19 | #


Ok merci !
Niveau de curiosité:
   99%
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 09/09/2019 09:26 | #


Max1Truc a écrit :
- A la compilation de gint, j'ai dû changer le fichier fxconv.py qui est dans le PATH en modifiant la déclaration de la fonction "elf" en ligne 673:
def elf(data, output, symbol, section=None, arch="sh4"):

Voilà, j'ai poussé sur le dépot du fxSDK un nouveau commit introduisant les options appropriées pour fxconv :

--toolchain pour spécifier la toolchain à utiliser (eg. sh3eb-elf)
--arch pour spécifier l'architecture cible (eg. sh3 ou sh4-nofpu)
--section pour spécifier la section cible (eg. .rodata)

Ça devrait résoudre ton problème de façon plus élégante.

Ajouté le 13/09/2019 à 08:21 :
Encore une modification importante aujourd'hui !

Après avoir ajouté les gestionnaires d'exceptions (les System ERROR si vous voulez), on m'a suggéré de permettre au programmeur d'afficher les infos qu'il voulait. J'ai donc ajouté une fonction gint_panic_set() que l'on peut appeler pour choisir sa propre fonction pour debugger en cas d'erreur. Typiquement vous voudrez afficher plein d'infos à l'écran... voire scroller avec getkey().

(Détail technique : l'ancien panic tournait dans le gestionnaire d'exceptions, et ne pouvait donc pas utiliser d'interruptions. Donc pas de getkey(), pas de sleep(), plein de trucs limitants. Désormais je rte directement dans le panic, ce qui signifie que le panic peut utiliser toutes les fonctions. Techniquement parlant c'est une bonne avancée !)

En plus de ça, j'ai ajouté un mécanisme permettant de rattraper les exceptions. J'en ai besoin pour mon inspecteur de mémoire dans gintctl. En effet, dès qu'on se met sur une adresse invalide, ça fait une TLB error et l'add-in plante. Ce mécanisme permet d'être informé que l'erreur s'est produite et de continuer quand même l'exécution. Ainsi, l'add-in reprend, réalise qu'il a été informé d'une erreur, et affiche "TLB error" à toutes les adresses invalides.
MilangHors ligneMembrePoints: 325 Défis: 2 Message

Citer : Posté le 13/09/2019 11:29 | #


Lephenixnoir a écrit :

En plus de ça, j'ai ajouté un mécanisme permettant de rattraper les exceptions. J'en ai besoin pour mon inspecteur de mémoire dans gintctl. En effet, dès qu'on se met sur une adresse invalide, ça fait une TLB error et l'add-in plante. Ce mécanisme permet d'être informé que l'erreur s'est produite et de continuer quand même l'exécution. Ainsi, l'add-in reprend, réalise qu'il a été informé d'une erreur, et affiche "TLB error" à toutes les adresses invalides.


Rattraper des exceptions ?
Mais, c'est à dire que à terme, même après une exception un addin pourra continuer à s'exécuter ? Mais c'est fantastique ça

Par contre, sinon, j'ai toujours quelques problèmes autour du DMA, lorsque je lance DMA memset, ma calculatrice freeze (G 35 ++ 2.05.2201 donc bien sh4)
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 13/09/2019 11:32 | #


Milang a écrit :
Mais, c'est à dire que à terme, même après une exception un addin pourra continuer à s'exécuter ? Mais c'est fantastique ça

Ben, pas vraiment. Si l'add-in fait un accès mémoire illégal et qu'on continue l'exécution, le registre de destination contiendra une valeur complètement arbitraire. Ça ne marche que si l'add-in prévoit que l'accès peut échouer et le détecte. C'est donc très marginal.

Par contre, sinon, j'ai toujours quelques problèmes autour du DMA, lorsque je lance DMA memset, ma calculatrice freeze (G 35 ++ 2.05.2201 donc bien sh4)

Fichtre, va falloir que je regarde tout ça en détail.

Ajouté le 14/09/2019 à 10:12 :
Milang a écrit :
Par contre, sinon, j'ai toujours quelques problèmes autour du DMA, lorsque je lance DMA memset, ma calculatrice freeze (G 35 ++ 2.05.2201 donc bien sh4)

Je peux reproduire sur ma Graph 75+E en 02.05.2201, je vais enquêter.

Ajouté le 14/09/2019 à 16:21 :
J'ai implémenté un outil de visualisation pour le DMA dans gintctl, et le freeze se produit dès que j'utilise un transfert sans interruptions. Par ailleurs j'ai du mal à lire/écrire correctement dans les registres du DMA.

Ajouté le 14/09/2019 à 17:36 :
Tous les registres sont à 0, je commence à me demander s'il y a un DMA. Ce qui expliquerait pourquoi ça freeze en mode sans interruption vu qu'il attend immédiatement explicitement la fin du transfert qui de toute façon n'existe pas.
MilangHors ligneMembrePoints: 325 Défis: 2 Message

Citer : Posté le 14/09/2019 18:28 | #


Peut être que les adresses du dma ne sont pas les mêmes
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 14/09/2019 18:31 | #


J'ai tenté toutes les adresses connues de modules DMA de SimLo sans succès.

Ce serait la première différence majeure découverte entre les SH7305 qui équipent les Graph mono et les Graph 90+E.

D'un côté, la doc de SimLo ne concerne que des SH3 et la Prizm. Or, la Prizm a définitivement besoin d'un DMA sinon l'écran ne tient pas la performance. Il n'est pas impossible que Casio ait éliminé le DMA du design des Graph mono pour économiser.

J'ai en tête une idée pour détecter expérimentalement les registres dans l'espace d'adressage, mais c'est tordu et ça pourrait être dangereux sur les bords. Pour l'instant je ne vois pas où aller d'autre.

Ajouté le 15/09/2019 à 12:29 :
J'ai continué d'enquêter avec le DMA sur Graph 90.

Jusqu'ici je n'arrive pas à exécuter dma_memcpy() proprement, le transfert se conclut sans erreur mais les données à l'arrivée sont fausses. De plus, on ne gagne quasiment rien.

Pour vous donner une idée, afficher une image en R5G6B5 (le format le plus rapide à afficher mais le moins compact) prend 24.7 ms en processeur pur, et le transfert équivalent (mais qui produit des mauvaises données pour l'instant) prend 21.3 ms. En montant l'overclock au maximum, ces temps descendent à 16.5 ms et 14.8 ms.

C'est assez décevant. J'aimerais comprendre plus finement les relations entre les fréquences des différentes mémoires présentes, et tenter d'exploiter des techniques un peu plus tordues pour l'accélérer. 40 FPS avec triple-buffering juste pour une image en plein écran, c'est vraiment pas extraordinaire.

Pour référence, je pense actuellement à utiliser les mémoires IL (4k), X (8k) et Y (8k) qui sont des bouts de mémoire normalement plus rapides que la RAM. Ça peut pas faire des miracles car il y a 170k de VRAM en tout. Mais on peut s'en servir pour le code très chaud en calcul, et j'envisage de m'en servir pour des données graphiques lorsque le rendu est compliqué (eg. alpha blending). Je ne sais pas à quel point on va gagner toutefois, parce qu'il y a déjà le cache dans la partie, et il est possiblement encore plus rapide...

J'ai en tête un certain type d'affichage de jeu (à trois lettres, cough cough) que j'aimerais pouvoir faire à une fréquence raisonnable. Notamment un HUD, une map tilée en plein écran avec possiblement deux calques, des entités sur la map et quelques effets spéciaux possiblement avec alpha blending. Pour l'instant les performances ne permettent pas de jouer à ça.

Ajouté le 15/09/2019 à 14:48 :
J'ai mis le doigt sur les deux défauts de comportement qui me restaient encore à éclairer.

D'abord, le fait que les données soient invalides quand j'exécute un dma_memcpy(). Avec tous les transferts de VRAM que j'ai faits, j'ai fini par oublier que les images sont dans la ROM et virtualisées dans l'espace d'adressage. Or le DMA utilise des adresses physiques, ce qui pose un énorme problème. Il est facile de trouver l'adresse physique qui est virtualisée à chaque endroit de l'espace d'adressage, mais les données virtualisées ne sont pas continues dans la mémoire physique.

Autrement dit, à cause de la fragmentation du système de fichiers, il est impossible d'afficher de façon générale des images prises dans la ROM avec le DMA. Et si les images tiennent dans la RAM alors elles sont assez petites pour que ça ne vale pas la peine d'utiliser le DMA.

Ensuite, le fait que j'aie des freezes et des différences de comportement quand ma source est la mémoire IL. J'ai fini par mettre la main dessus dans la doc :

10.5.4 - Sleep Mode
The SuperHyway bus master module, such as DMAC, cannot access IL memory in sleep mode.

Pris autrement, cela signifie qu'on ne peut pas endormir le processeur pendant un transfert DMA dont la source ou la destination est la mémoire IL. Ce n'est pas un problème en soi. Seulement, lors de mes tests j'attendais toujours que le transfert DMA se termine avant de rendre la main au programme pour éviter des effets tordus. Lorsque les interruptions sont activées, mon driver effectue cette attente en endormissant la calculatrice, ce qui arrête aussi la mémoire IL, et donc le transfert DMA, et donc la calculatrice ne se réveille jamais.

Avec ça, mon driver contient maintenant toutes les fonctions que j'envisageais initialement, il n'y a plus aucun bug connu, et je peux même accéder à la mémoire IL. Par contre le gain de performance est très modeste, et loin d'être satisfaisant.
Dark stormEn ligneMembre d'honneurPoints: 10831 Défis: 176 Message

Citer : Posté le 15/09/2019 19:02 | #


Seulement, lors de mes tests j'attendais toujours que le transfert DMA se termine avant de rendre la main au programme pour éviter des effets tordus.


Dans le cas d'un affichage de VRAM, les cas tordus dont tu parles ce sont des read/write after read/write ? Dans ce cas, le seul problème qui peut avoir lieu, c'est que quelques octets de la VRAM soient corrompus, et dans ce cas on a quelques pixel qui sont pas de la bonne couleur, pour une frame uniquement.

L'intérêt que je vois du DMA, c'est justement de pouvoir paralléliser le calcul physique et de rendu avec le transfert de la VRAM. Si on attend que le DMA ait fini sa copie, je vois moins l'intérêt.

Et avec un système de flag/lock, y'a pas moyen de paralléliser ce qui est possible, puis ensuite attendre que le DMA ai fini pour relancer une copie ? Ou alors j'ai pas tout à fait compris que ce tu faisais…
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 15/09/2019 19:09 | #


En effet, pour l'instant je me place dans un cadre où corrompre une partie de la VRAM n'est pas acceptable. En plus, continuer l'exécution pendant que le DMA tourne peut donner des surprises très déplaisantes comme freezer n'importe comment si tu réutilises le DMA avant que le transfert ne soit fini. Mon application de test en serait capable...

Ici, il ne s'agit pas d'utiliser le DMA pour faire le transfert à l'écran (qui marche déjà tout seul) mais carrément pour dessiner ou transférer de la mémoire. Dans ce cas, l'intérêt était que l'opération était plus rapide. Je ne parle même pas encore de paralléliser. (En effet, dans le cas VRAM → DD, paralléliser est facile car il suffit de changer de VRAM. Mais dans le cas dessin c'est moins évident.)

En tous cas, oui on peut sans problème bosser un moment selon les possibilités plus attendre le DMA plus tard. Il suffit d'appeler dma_transfer(), bosser, puis appeler dma_transfer_wait(). Actuellement je fais les deux d'un coup parce que mon add-in de test s'en fout royalement, il a déjà des perfs très larges.
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 15/09/2019 19:35 | # | Fichier joint


Je viens de pousser une série de commits qui ajoute dma_memcpy() et trois macros GILRAM, GXRAM et GYRAM qui permettent de placer des données dans les trois mémoires on-chip de la calculatrice, les mémoires IL, X et Y.

J'ai également construit une expérience dans gintctl permettant de mesurer la taille de ces zones ; elles font 4k, 8k et 8k respectivement.

MilangHors ligneMembrePoints: 325 Défis: 2 Message

Citer : Posté le 15/09/2019 20:25 | #


Du coup, il y a finalement un dma sur les graph monochromes ou non ?
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 15/09/2019 21:33 | #


Milang a écrit :
Du coup, il y a finalement un dma sur les graph monochromes ou non ?

Pour l'instant non, il n'y en a pas.

Ajouté le 28/09/2019 à 20:47 :
Je viens de pousser une mise à jour importante : l'ajout de keydown() et la finalisation du clavier.

Je m'explique. Jusque-là le fonctionnement du clavier était meh car il n'était pas compatible avec une fonction keydown(). Tout comme je raconte souvent que GetKey() et IsKeyDown() ne peuvent pas être utilisés ensemble dans fxlib, ajouter keydown() posait problème à gint : cela donnait plusieurs façons incompatibles de lire les informations du clavier.

Heureusement, ce problème est maintenant résolu ! J'ai trouvé une façon de les faire marcher ensemble. Il s'agit de synchroniser keydown() avec les événements.

Dans gint, l'information primaire sur le clavier est une file d'événements qui disent qu'une touche a été appuyée ou relâchée à un certain moment du temps. Imaginons que j'appuie puis que je relâche EXE après une seconde, ça donnera deux événements qui ressembleront à ça :

<t=12s, pressed EXE>
<t=13s, released EXE>

Maintenant si j'appelle pollevent() je récupérerai le premier (<t=12s, pressed EXE>). Si je recommence, j'aurai le suivant (<t=13s, released EXE>), et si je continue j'aurai un événement vide avec le temps actuel (par exemple <t=18s nothing>).

Comme vous pouvez le voir, avec ce système je dois lire les événements pour comprendre ce qui s'est passé. Tant que je n'appelle pas pollevent(), même si la touche a été pressée puis relâchée 10 fois je n'en saurai rien. Implémenter keydown() comme dans fxlib casserait ce principe. Donc à la place, je fais renvoyer à keydown() l'état de la touche selon les événements qui ont été lus. Voilà un exemple de ce qui se passerait dans le programme :

(J'appuie sur EXE, le driver génère <t=12s, pressed EXE>.)
keydown(KEY_EXE) -> 0
(Je relâche EXE, le driver génère <t=13s, released EXE>.)
keydown(KEY_EXE) -> 0

pollevent() -> <t=12s, pressed EXE>
keydown(KEY_EXE) -> 1
pollevent() -> <t=13s, released EXE>
keydown(KEY_EXE) -> 0
pollevent() -> <t=18s, nothing>
keydown(KEY_EXE) -> 0

Comme vous pouvez le voir, il faut lire les événements pour que keydown() suive. C'est en fait la bonne réponse dans ce modèle, et cela permet de combiner les différentes approches. En particulier, dans un jeu, on voudra lire les événements un par un pour reconstituer tout ce que le joueur a tapé depuis le dernier frame, et au fur et à mesure de la simulation on pourra utiliser keydown() pour analyser le clavier.

Si vous voulez juste utiliser keydown() tout seul, il suffit de lire tous les événements chaque fois que vous analysez le clavier, ce pour quoi il existe une fonction raccourcie clearevents(). De plus, vous pouvez de façon fiable appelez keydown() plusieurs fois d'affilée, car même si une touche est pressée pendant que vous faites des tests, la valeur ne changera qu'une fois que vous aurez relu les événements.

Avec tout ça, je suis enfin satisfait de mon modèle clavier, et je pense que ça va rester comme ça jusqu'à la v2 et au-delà !
HackcellHors ligneMembrePoints: 1147 Défis: 10 Message

Citer : Posté le 28/09/2019 22:06 | #


Nyace ♥

Hâte de voir ce qu'on peut faire avec
I usually spend meow time cosplaying as a diligent student...
So it can get pretty stressful.
That's exactly why PC is such a happy place for meow to be ⭐
LephenixnoirHors ligneAdministrateurPoints: 15998 Défis: 140 Message

Citer : Posté le 29/09/2019 11:37 | #


Essentiellement on peut tout faire avec !

La vraie propriété utile c'est que le clavier peut profiter de sa précision complète (128 FPS par défaut, 256 si tu veux) même si l'application n'a pas ce niveau de performance.

En particulier, si on l'utilise bien, on peut avoir un jeu qui tourne à 10 FPS graphiquement mais qui est capable de traiter des combos de façon bien plus fluide que 10 FPS. Même en un moment de lag, les événements sont enregistrés et tous les combos seront exécutés proprement une fois que le jeu retournera dans le moteur physique.

De plus, la durée mesurée des pressions sera aussi plus précise que le framerate de l'application, donc par exemple dans un jeu où l'on déplace le personnage avec les touches fléchées, on pourra avoir une meilleure fluidité. Surtout, encore une fois, si l'application lagge. Et je pense que ça se produira sur Graph 90.
MilangHors ligneMembrePoints: 325 Défis: 2 Message

Citer : Posté le 24/10/2019 14:56 | #


J'ai une question :
Est-il possible d'associer une fonction qui doit être obligatoirement exécutée à la fin d'un callback ?
Je sais qu'il est possible de forcer le programmeur à la mettre, mais existe-t-il plus raffiné ?

En fait j'aimerais qu'une fonction remette une variable dans un état particulier à la fin de l'interruption, en l'occurence se placer dans une vram particulière, sans que la personne ait à se soucier de ce détail. (ici c'est pour faire du double buffering)
Pages : Précédente1 ... , 20, 21, 22, 23, 24, 25, 26, 27, 28Suivante

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2019 | Il y a 89 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