La Place des Développeurs Appeler des fonctions du Bios dans le hook H.TIMI
Reprise du message précédent
Sector28 :
Pourquoi ne pas faire tourner ton programme entièrement sous interruptions vbl, et transformer ta boucle principale en séquence de sous-routines ?
C'est la technique utilisée par Konami dans ses jeux sur MSX.
aoineko :
Ca peut être utile, mais dans mon cas particulier, je pensais plutôt essayer de mettre en place un système de deferred hook. L'idée c'est d'utiliser la boucle principale pour synchroniser les hooks. En gros, au lieu de s'exécuter, les hooks vont s'enregistrer dans une liste, puis dans la boucle principale je vais dépiler la liste et exécuter les fonctions en série.
Très intéressant cette technique ...
Tu peux développer ?
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
Metalion :
Très intéressant cette technique ...
Tu peux développer ?
Tu peux développer ?
En fait, ça rentre pas dans les 5 octets de la table de Hook, mais l'idée ça aurait été d'y mettre un :
Code TEXT :
LD HL, #MaListeDeHookATraiter LD (HL),#MonHook INC (HL)
Comme ça, à chaque Hook, on aurait juste un tableau qui se remplis, et dans la boucle principal on pourrait dépiler en série la liste des fonctions à appeler.
Il faudrait utiliser un ring buffer pour pouvoir vider d'un coté pendant que les interruptions remplissent de l'autre.
Même si c'est faisable en passant par une fonction, au final j'ai trouvé que l'intérêt était limité quand j'ai compris que pendant le déroulement d'un jeu, on a besoin de gérer que les interruptions du VDP.
La meilleure solution me semble donc plutôt de remplacer la routine 38h avec un code optimiser pour ne gérer que le V-Blank et le H-Blank.
Par contre, je pense utiliser le même genre de technique pour le rendu des commandes VDP. Au lieu de les envoyer au moment où on veut les dessiner, on les stock dans un buffer et on continue le code du jeu sans attendre. Régulièrement, on check si le VDP est dispo, et si c'est le cas, on envoi une commande de la frame précédente. Ainsi, le CPU n'est jamais en attente de libération du VDP.
On est toujours ignorant avant de savoir.
aoineko :
Par contre, je pense utiliser le même genre de technique pour le rendu des commandes VDP. Au lieu de les envoyer au moment où on veut les dessiner, on les stock dans un buffer et on continue le code du jeu sans attendre. Régulièrement, on check si le VDP est dispo, et si c'est le cas, on envoi une commande de la frame précédente. Ainsi, le CPU n'est jamais en attente de libération du VDP.
Je travaille justement sur un jeu dans lequel il y a beaucoup de commandes VDP réalisées par frame. Ce que j'ai déjà fait pour optimiser les choses, c'est de figer le registre de statut à 2 entre deux appels VBLANK, ce qui permet d'éviter de devoir changer le registre de statut de 0 à 2 (puis l'inverse) pour toute vérification de l'état des commandes du VDP.
Ceci dit, je ne vois pas très bien comment ta technique fonctionne, car lorsque tu as empilé plusieurs commandes, et que tu les dépiles, tu dois quand même vérifier l'état du VDP entre deux commandes ?
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
Généralement, une fonction d'envoie de commande VDP commence par un wait du CPU jusqu'à ce que le VDP soit disponible.
Pour limiter cette attente, la solution classique c'est de faire du "sandwitch" : j'envoie une commande, je fais du code gameplay, j'envoie une commande, je fais du code gameplay, etc.
Ca permet souvent de limiter (voir retirer) les temps d'attente.
Mais, dans de nombreux cas, découper notre code pour faire ce "sandwitch" n'est pas optimal et on aimerait pouvoir s'affranchir de cette contrainte.
C'est là que ma technique est intéressante : ne pas créer de contrainte sur le code gameplay tout en évitant tous les wait.
L'idée, c'est qu'on a une fonction SendCommand() qui va s'occuper d'envoyer les commandes de la frame précédente pendant que le CPU s'occupe de la frame courante.
Tout ce qu'elle fait c'est vérifier si le VDP est dispo et si oui, envoyer une commande. Dans tous les cas, la fonction return sans attente.
Ensuite, on a juste à placer cette fonction à des endroits stratégiques du code pour qu'elle soit appelé régulièrement et voilà, plus de contrainte, plus d'attente.
Bon, après, si tu en es à optimiser la lecture des registres de statut, j'imagine que tu as déjà réglé les problèmes de temps d'attente d'une façon ou d'une autre.
Pour limiter cette attente, la solution classique c'est de faire du "sandwitch" : j'envoie une commande, je fais du code gameplay, j'envoie une commande, je fais du code gameplay, etc.
Ca permet souvent de limiter (voir retirer) les temps d'attente.
Mais, dans de nombreux cas, découper notre code pour faire ce "sandwitch" n'est pas optimal et on aimerait pouvoir s'affranchir de cette contrainte.
C'est là que ma technique est intéressante : ne pas créer de contrainte sur le code gameplay tout en évitant tous les wait.
L'idée, c'est qu'on a une fonction SendCommand() qui va s'occuper d'envoyer les commandes de la frame précédente pendant que le CPU s'occupe de la frame courante.
Tout ce qu'elle fait c'est vérifier si le VDP est dispo et si oui, envoyer une commande. Dans tous les cas, la fonction return sans attente.
Ensuite, on a juste à placer cette fonction à des endroits stratégiques du code pour qu'elle soit appelé régulièrement et voilà, plus de contrainte, plus d'attente.
Bon, après, si tu en es à optimiser la lecture des registres de statut, j'imagine que tu as déjà réglé les problèmes de temps d'attente d'une façon ou d'une autre.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
bon, heu, comment dire...
Qui veut bien me faire un dessin pour que mon esprit puisse assimiler tout ça ?
J'ai du mal à comprendre quand on détecte une interruption de ce qu'il faut faire au juste ... Et comment coder ça ?
Bon je sais, je vous force à redescendre d'un niveau là
Qui veut bien me faire un dessin pour que mon esprit puisse assimiler tout ça ?
J'ai du mal à comprendre quand on détecte une interruption de ce qu'il faut faire au juste ... Et comment coder ça ?
Bon je sais, je vous force à redescendre d'un niveau là
aoineko :
L'idée, c'est qu'on a une fonction SendCommand() qui va s'occuper d'envoyer les commandes de la frame précédente pendant que le CPU s'occupe de la frame courante
OK, mais comment tu t'assures que l'ensemble des commandes empilée a été réalisée ? Car tu peux très bien avoir appelé 10 fois SendCommand() sur une frame mais n'avoir exécuté qu'une seule commande par manque de disponibilité du VDP.
Oui, je travaille en "sandwich" également (commande/code/commande - ...), mais je voudrais justement réussir à l'optimiser, ce sandwich. Dans l'idéal, j'aurais une pile de routines à effectuer, avec comme donnée d'entrée le nombre de cycles nécessaire. Après chaque envoi d'une commande VDP, je choisirai la/les routine(s) à lancer en fonction du nombre de cycles estimé pour la réalisation de la commande VDP. Ce qui permettrai d'être sûr qu'à la prochaine commande VDP, il n'y aurai pas d'attente. Une espèce de "task manager", en quelque sorte ...
Maintenant, tout dépend du nombre de commandes VDP par frame. En ce qui me concerne, j'ai besoin d'en réaliser environ 64 sur l'espace de 3 frames, donc une moyenne de 21 commandes par frame ...
ericb59 :
J'ai du mal à comprendre quand on détecte une interruption de ce qu'il faut faire au juste ... Et comment coder ça ?
Qu'est-ce que tu veux faire au juste, Eric ? Edité par Metalion Le 14/01/2021 à 10h12
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
Metalion :
OK, mais comment tu t'assures que l'ensemble des commandes empilée a été réalisée ? Car tu peux très bien avoir appelé 10 fois SendCommand() sur une frame mais n'avoir exécuté qu'une seule commande par manque de disponibilité du VDP.
Oui, à la fin de ma frame, il me faut un Flush() pour vider mes dernières commandes VDP et là, le CPU devra attendre qu'une se finisse avant de lancer la suivante.
Mais bon, si c'est la fin de ma frame gameplay, c'est pas grave si le CPU attends.
Le trick c'est de mettre suffisamment de SendCommand() mais pas trop non plus.
Simplement, algorithmiquement, c'est beaucoup plus simple d'optimiser un code sans la contrainte du sandwitch.
Mais bon, ça dépend aussi des cas.
Metalion :
Oui, je travaille en "sandwich" également (commande/code/commande - ...), mais je voudrais justement réussir à l'optimiser, ce sandwich. Dans l'idéal, j'aurais une pile de routines à effectuer, avec comme donnée d'entrée le nombre de cycles nécessaire. Après chaque envoi d'une commande VDP, je choisirai la/les routine(s) à lancer en fonction du nombre de cycles estimé pour la réalisation de la commande VDP. Ce qui permettrai d'être sûr qu'à la prochaine commande VDP, il n'y aurai pas d'attente. Une espèce de "task manager", en quelque sorte ...
Oui, j'y ai pensé aussi mais dans le cas sur lequel je suis, il y a trop de contrainte sur les tâches entre-elle pour que ce soit rentable.
Par contre, si elles sont suffisamment indépendante, ça pourrait être optimal comme méthode.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Citation :
Qu'est-ce que tu veux faire au juste, Eric ?
Comprendre, dans le cas de la realisation d'un jeu, comment correctement utiliser les interruptions, et aménager son code en conséquence.
Le béaba de la gestion d'interruption sur MSX ca serait déjà pas mal.
(Je comprend vite, mais faut m'expliquer lentement ) Edité par ericb59 Le 14/01/2021 à 10h29
aoineko
Membre non connecté
Conseiller Municipal
La discussion actuel, c'était plutôt comment tirer parti des commandes VDP qui laisse le CPU libre de continuer d'autres tâches.
Voici déjà une explication de la méthode du "sandwitch".
L'idée est juste d'intercaler du code gameplay -- Compute() dans l'exemple -- entre le lancement des commandes au VDP pour éviter d'avoir à mettre le CPU en attente avant de pouvoir envoyer la commande suivante.
A gauche "sans sandwitch", à droite, avec :
Pour ce qui est des interruptions, ça dépend vraiment de ce que tu souhaites faire.
La fonctionnalité de base, c'est la Synchronisation verticale (v-synch) qui consiste juste faire en sorte que ta boucle de gameplay soit synchronisé avec la boucle d'affichage du VDP.
Je peux te mettre un exemple de comment ça marche.
Voici déjà une explication de la méthode du "sandwitch".
L'idée est juste d'intercaler du code gameplay -- Compute() dans l'exemple -- entre le lancement des commandes au VDP pour éviter d'avoir à mettre le CPU en attente avant de pouvoir envoyer la commande suivante.
A gauche "sans sandwitch", à droite, avec :
Pour ce qui est des interruptions, ça dépend vraiment de ce que tu souhaites faire.
La fonctionnalité de base, c'est la Synchronisation verticale (v-synch) qui consiste juste faire en sorte que ta boucle de gameplay soit synchronisé avec la boucle d'affichage du VDP.
Je peux te mettre un exemple de comment ça marche.
On est toujours ignorant avant de savoir.
Oui, aoineko a raison, là on dérive du sujet initial. Je vais créer un sujet séparé
Edité par Metalion Le 14/01/2021 à 11h31
Edité par Metalion Le 14/01/2021 à 11h31
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie