La Place des Développeurs FUSION-C Codez en C pour MSX les doigts dans le nez !
aoineko
Membre non connecté
Conseiller Municipal
Reprise du message précédent
Ah... une dernière chose !J'ai pas vérifié si c'était bien le cas avec SDCC, mais la norme C99 demande qu'une variable static soit initialisé automatiquement à 0.
Du coup, si dans ton programme tu as un " static char a; " par ex., le compilo/linker va le traiter comme une variable initialisé donc si tu fais pas la copie de _INITIALIZER vers _INITIALIZED , tu vas avoir une variable avec une valeur indéterminée (alors qu'avec la version du crt0 de Konamiman que tu utilises pour les binaires Basic, cette variable sera bien initialisée à 0).
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Devenez ingénieur grâce à Fusion-C
C'est maintenant comme cela que je vais faire connaitre Fusion-C...
Mais non, je ne rigole pas !
Frederic Garcia Nieto, élève de l'école Technique supérieur d'ingénierie informatique à Valence (Espagne) à rédiger son mémoire sous la forme d'un Tutorial sur la création d'un jeu sur MSX.
Et pour se faire, il utilise ... Fusion-C bien entendu.
Son mémoire expose de A à Z, comment réaliser un Bomb Jack sur MSX avec Fusion-C.
Des travaux préparatoires au code, tests, avec une grosse partie sur le MSX et sur Fusion-C.
Si ca vous branche vous trouverez le mémoire, le jeu, les sources du projet ici :
https://m.riunet.upv.es/handle/10251/145214?fbclid=IwAR0NBQ4lNfduBfP6XNkzIV3cWa3DfYtKmOywnkIsk8C5CSTPZaydH4YDLcA Edité par ericb59 Le 16/12/2020 à 19h06
C'est maintenant comme cela que je vais faire connaitre Fusion-C...
Mais non, je ne rigole pas !
Frederic Garcia Nieto, élève de l'école Technique supérieur d'ingénierie informatique à Valence (Espagne) à rédiger son mémoire sous la forme d'un Tutorial sur la création d'un jeu sur MSX.
Et pour se faire, il utilise ... Fusion-C bien entendu.
Son mémoire expose de A à Z, comment réaliser un Bomb Jack sur MSX avec Fusion-C.
Des travaux préparatoires au code, tests, avec une grosse partie sur le MSX et sur Fusion-C.
Si ca vous branche vous trouverez le mémoire, le jeu, les sources du projet ici :
https://m.riunet.upv.es/handle/10251/145214?fbclid=IwAR0NBQ4lNfduBfP6XNkzIV3cWa3DfYtKmOywnkIsk8C5CSTPZaydH4YDLcA Edité par ericb59 Le 16/12/2020 à 19h06
aoineko
Membre non connecté
Conseiller Municipal
Félicitations à lui... et à toi.
EDIT : J'ai survolé son rapport ; ça semble du super boulot (même si je maitrise pas la langue de Konamiman)
EDIT : J'ai survolé son rapport ; ça semble du super boulot (même si je maitrise pas la langue de Konamiman)
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Il me semble qu'il y a un problème dans ta fonction HMMC dans Fusion-C 1.3.
A la fin, tu fais un " in a,(#0x99) " après avoir sélectionner S#0 (Status Register 0).
En faisant ça, tu risques de rater un V-Blank !
Quelques autres remarques moins importantes :
- Ton initialisation des registres R#36-R#46 serait plus rapide via l'écriture séquentielle sur le port 9Bh (Indirect register access port).
- Tu bloques les interruptions pendant toute la durée de la copie...
-- Si tu veux utiliser cette fonction in-game (durant l'affichage du jeu) c'est un problème pour tout ce qui dépend des interruptions (musique, H-Blank, RS232, etc.). Si j'ai bien compris, tu as juste besoin de mettre des DI/EI sur les pairs de out .
-- Si tu considères (comme moi) que c'est une fonction uniquement pre-game (durant l'initialisation/chargement du jeu) alors tu peux laisser le blocage des interruptions, mais dans ce cas, sort l'initialisation du registre S#2 de ta boucle, ça ira plus vite.
- C'est du pinaillage de haut vol, mais tu peux aussi passer de 14 à 12 T-states sur le check des flags CE et TR en utilisant un sra suivi d'un rla plutôt que des and .
A la fin, tu fais un " in a,(#0x99) " après avoir sélectionner S#0 (Status Register 0).
En faisant ça, tu risques de rater un V-Blank !
Quelques autres remarques moins importantes :
- Ton initialisation des registres R#36-R#46 serait plus rapide via l'écriture séquentielle sur le port 9Bh (Indirect register access port).
- Tu bloques les interruptions pendant toute la durée de la copie...
-- Si tu veux utiliser cette fonction in-game (durant l'affichage du jeu) c'est un problème pour tout ce qui dépend des interruptions (musique, H-Blank, RS232, etc.). Si j'ai bien compris, tu as juste besoin de mettre des DI/EI sur les pairs de out .
-- Si tu considères (comme moi) que c'est une fonction uniquement pre-game (durant l'initialisation/chargement du jeu) alors tu peux laisser le blocage des interruptions, mais dans ce cas, sort l'initialisation du registre S#2 de ta boucle, ça ira plus vite.
- C'est du pinaillage de haut vol, mais tu peux aussi passer de 14 à 12 T-states sur le check des flags CE et TR en utilisant un sra suivi d'un rla plutôt que des and .
On est toujours ignorant avant de savoir.
TurboSEB
Membre non connecté
Conseiller Municipal
Moi j'aime bien les explications de aoineko car il sait de quoi il parle et c'est marrant car même si au début je me dis "Je vais rien comprendre.... Ils sont fou ces MSXiens "
Et bien fait non, je comprend dans le principe (même si j'ignorais même l'existence jusque la de la fonction HMMC ), et comme votre dualité est enrichissante, enfin pour ceux qui suivent hein (Franck : ). En définitive, c'est pas du pinaillage, c'est de l'optimisation
Sinon, félicitations à Frederic Garcia Nieto,.... Comme quoi le Msx n'est pas mort Edité par TurboSEB Le 28/12/2020 à 04h02
Et bien fait non, je comprend dans le principe (même si j'ignorais même l'existence jusque la de la fonction HMMC ), et comme votre dualité est enrichissante, enfin pour ceux qui suivent hein (Franck : ). En définitive, c'est pas du pinaillage, c'est de l'optimisation
Sinon, félicitations à Frederic Garcia Nieto,.... Comme quoi le Msx n'est pas mort Edité par TurboSEB Le 28/12/2020 à 04h02
MSX 1&2 + Moniteurs+divers (environ 0.70Tonnes)
ericb59
Membre non connecté
Conseiller Municipal
@TurboSeb : HMMC est une commande interne au VDP du MSX2, qui permet le transfert rapide d'un bloc de données de la RAM vers la VRAM.
Le VDP dispose d'un certain nombre de commandes, pour accélérer certains traitements. Il "suffit" de donner les paramètres que la commande attends, puis d'appeler celle-ci.
Ici en effet, je pense pouvoir enlever le in a,(#0x99) de fin, qui ne sert à rien.
Toute fois, dans bon nombre d'exemples de code que j'ai trouvé, c'est la routine GetVDPStatus qui sert à terminer les commandes VDP pour faire un RESET du VDP, et ça n'a pas l'air de poser un problème.
il y a un exemple ici et là
Oui, mais il faudrait que mes variables soient accessibles. Si je mes mettait dans une structure par exemple.
Ce qui m'ennui, c'est la lisibilité du code et de la fonction dans ce cas, et le fait de devoir faire 2 étapes pour appeler la fonction.
-1, attribuer les variables
-2, appeler la commande
A moins que tu n'ai une autre solution ?
Alors oui, en théorie seuls certains OUT 99,a nécessiterai d'être sans interruption. J'ai essayé de ne mettre des DI/EI qu'à des endroits stratégiques, mais tous mes essais on toujours plantés.
Et tu remarqueras que dans les examples, cités plus haut, tout la fonction est sous un DI.
donc ? Je donne ma langue au chat sur la possibilité de faire autrement.
Ca à le même effet sur le flag Z ?
Edité par ericb59 Le 28/12/2020 à 09h29
Le VDP dispose d'un certain nombre de commandes, pour accélérer certains traitements. Il "suffit" de donner les paramètres que la commande attends, puis d'appeler celle-ci.
Citation :
A la fin, tu fais un " in a,(#0x99) " après avoir sélectionner S#0 (Status Register 0).
En faisant ça, tu risques de rater un V-Blank !
En faisant ça, tu risques de rater un V-Blank !
Ici en effet, je pense pouvoir enlever le in a,(#0x99) de fin, qui ne sert à rien.
Toute fois, dans bon nombre d'exemples de code que j'ai trouvé, c'est la routine GetVDPStatus qui sert à terminer les commandes VDP pour faire un RESET du VDP, et ça n'a pas l'air de poser un problème.
Code ASM :
ReadReg: out ($99),a ld a,15+128 out ($99),a in a,($99) ret
il y a un exemple ici et là
Citation :
Ton initialisation des registres R#36-R#46 serait plus rapide via l'écriture séquentielle sur le port 9Bh
Oui, mais il faudrait que mes variables soient accessibles. Si je mes mettait dans une structure par exemple.
Ce qui m'ennui, c'est la lisibilité du code et de la fonction dans ce cas, et le fait de devoir faire 2 étapes pour appeler la fonction.
-1, attribuer les variables
-2, appeler la commande
A moins que tu n'ai une autre solution ?
Citation :
Tu bloques les interruptions pendant toute la durée de la copie
Alors oui, en théorie seuls certains OUT 99,a nécessiterai d'être sans interruption. J'ai essayé de ne mettre des DI/EI qu'à des endroits stratégiques, mais tous mes essais on toujours plantés.
Et tu remarqueras que dans les examples, cités plus haut, tout la fonction est sous un DI.
donc ? Je donne ma langue au chat sur la possibilité de faire autrement.
Citation :
tu peux aussi passer de 14 à 12 T-states sur le check des flags CE et TR en utilisant un sra suivi d'un rla plutôt que des and
Ca à le même effet sur le flag Z ?
Edité par ericb59 Le 28/12/2020 à 09h29
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
Toute fois, dans bon nombre d'exemples de code que j'ai trouvé, c'est la routine GetVDPStatus qui sert à terminer les commandes VDP pour faire un RESET du VDP, et ça n'a pas l'air de poser un problème.
Citation :
A la fin, tu fais un " in a,(#0x99) " après avoir sélectionner S#0 (Status Register 0).
En faisant ça, tu risques de rater un V-Blank !
En faisant ça, tu risques de rater un V-Blank !
Toute fois, dans bon nombre d'exemples de code que j'ai trouvé, c'est la routine GetVDPStatus qui sert à terminer les commandes VDP pour faire un RESET du VDP, et ça n'a pas l'air de poser un problème.
Quelques remarques :
- Après avoir modifié la valeur du registre de status (R#15), il faut toujours le remettre à 0 car la routine du Bios qui gère les interruptions check S#0 sans initialiser cette valeur (héritage du MSX1).
- Si tu veux attendre la fin de l'exécution de ta commande, tu vas avoir besoin de lire S#2 puis de réinitialiser le registre de status sur S#0, mais PAS de lire S#0.
- A moins que tu souhaites utiliser la fonction de détection automatique de collision/superposition de sprites ET que tu es sûr que tu te trouves suffisamment avant ou après le V-Blank, il ne faut surtout pas lire S#0 ou le Bios risque de ne pas pouvoir détecter le prochain V-Blank (ce qui est un GROS problème ).
- Pour ce qui est de l'attente de fin de commande VDP, il vaut toujours mieux le faire juste avant la commande suivante. Comme ça, tu laisses du temps au CPU pour faire d'autres tâches avant de se mettre en attente.
ericb59 :
A moins que tu n'ai une autre solution ?
Citation :
Ton initialisation des registres R#36-R#46 serait plus rapide via l'écriture séquentielle sur le port 9Bh
A moins que tu n'ai une autre solution ?
Actuellement, c'est la triple peine : le compilo doit charger tous tes paramètres dans la pile avant le call de ta fonction, puis il doit tout décharger avec le couteux registre IX, puis initialiser les registres du VDP un à un.
Si tu passes par une structure, tu auras toujours le cout du chargement des paramètres (dans la RAM (heap) plutôt que dans la pile), mais tu élimines le passage des paramètres sur la pile et tu peux utiliser un otir (ou mieux, une série de outi) pour écrire séquentiellement dans les registres du VDP depuis ta structure.
Ce soir je vais essayer de finir le clean de ma lib VDP ; je te dirai quand ça sera dispo sur GitHub si tu veux jeter un œil.
ericb59 :
Ca à le même effet sur le flag Z ?
Citation :
tu peux aussi passer de 14 à 12 T-states sur le check des flags CE et TR en utilisant un sra suivi d'un rla plutôt que des and
Ca à le même effet sur le flag Z ?
Nop, dans ce cas il faut utiliser le flag C (retenu).
Code ASM :
// Read to check CE & TR flags in a, (P_VDP_STAT) sra a // check CE (bit#0) jp nc, write_finished // CE==0 ? command finished rla // check TR (bit#7) jp nc, write_loop // TR==0 ? VDP not ready
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Code ASM :
in a,(#0x99) and #1 jp z, exitHMMC ; if CE = 1 Exit and #128 jp nz, loopHMMC ; if TR = 0 Loop
D'ailleurs, ton deuxième test est toujours faux car le premier AND met le bit#7 (TR) à 0.
Si ça marche quand même, c'est que ta boucle est plus lente que le temps d'écriture du VDP (29 cycles dans le pire des cas) donc en fait, il n'est pas nécessaire de check TR.
Donc tu peux laisser le premier AND (plus rapide qu'un SRA) et supprimer le second (qui ne sert à rien dans ton cas).
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Je viens de que dans ma fonction LMMC
j'ai ceci pour mes check !!
j'ai ceci pour mes check !!
Code C :
loopLMMC: ld a,#2 call statusLMMC rra jp nc, exitLMMC ; is CE finish ? rla rla jp nc, loopLMMC ; TR? transferring? inc hl ld a,(hl) out (#0x9b),a jp loopLMMC exitLMMC: xor a call statusLMMC ei pop ix ret statusLMMC: out (#0x99),a ld a,#0x8f out (#0x99),a in a,(#0x99) ret
aoineko
Membre non connecté
Conseiller Municipal
Elle me semble très bizarre cette fonction
Elle fonctionne bien ?
Je comprends pas l'intérêt de lire S#0 dans la boucle ; ça me semble super dangereux.
Elle fonctionne bien ?
Je comprends pas l'intérêt de lire S#0 dans la boucle ; ça me semble super dangereux.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Je voulais te montrer les RRA et RLA à la place du AND #1
Oui elle fonctionne.
aoineko :
Elle me semble très bizarre cette fonction
Elle fonctionne bien ?
Je comprends pas l'intérêt de lire S#0 dans la boucle ; ça me semble super dangereux.
Elle fonctionne bien ?
Je comprends pas l'intérêt de lire S#0 dans la boucle ; ça me semble super dangereux.
Tu parles de la partie Exit ?
Comme je te disais plus haut, la plupart des routines que j'ai trouvées font comme ça. Sans doute pour économiser de la place ?
Car c'est vrai que le denier IN ne sert à rien.
aoineko
Membre non connecté
Conseiller Municipal
Ca me semble ni court ni performant, mais peut-être que je rate un truc...
Tous ces calls au milieu d'une boucle qui se veux rapide, c'est un contre-sens pour moi, mais bon.
Tous ces calls au milieu d'une boucle qui se veux rapide, c'est un contre-sens pour moi, mais bon.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
@aoineko :
Tu m’avais indiqué dans un autre sujet que tu avais réglé le bug des sons AYFX qui ne terminaient pas avec le player PT3.
J’ai oublié de te demander ce que tu avais fait au code...
Est-ce que tu as encore en tête la modif du code que tu as appliqué ?
Tu m’avais indiqué dans un autre sujet que tu avais réglé le bug des sons AYFX qui ne terminaient pas avec le player PT3.
J’ai oublié de te demander ce que tu avais fait au code...
Est-ce que tu as encore en tête la modif du code que tu as appliqué ?
aoineko
Membre non connecté
Conseiller Municipal
ayFX et PT3 sont complètement indépendant pour leur update et n'entrent en concurrence que pour écrire dans le buffer qui sera envoyé aux registres du PSG à chaque frame.
Donc ton problème est certainement spécifique à ayFX.
De mon coté, j'ai ajouté une fonction callback (un hook) qui est appelé à la fin d'un son. Par défaut, c'est la fonction de Mute qui est appelé.
(cf. https://github.com/aoineko-fr/CMSX/blob/master/cmsx/src/ayFX/ayfx_player.c ligne 229)
Donc ton problème est certainement spécifique à ayFX.
De mon coté, j'ai ajouté une fonction callback (un hook) qui est appelé à la fin d'un son. Par défaut, c'est la fonction de Mute qui est appelé.
(cf. https://github.com/aoineko-fr/CMSX/blob/master/cmsx/src/ayFX/ayfx_player.c ligne 229)
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Ami du soir, bonsoir,
J'ai enfin retravaillé sur FUSION-C 1.3 la suite, après plusieurs mois de black-out.
J'ai finalisé ma première ROM viable en 48K que je vous partage ici ...
Alors c'est rien du tout d'interessant, c'est une compilation de deux jeux 16K que j'ai réunit en une seule ROM de 48K. Mais comme j'suis content je vous la poste !
Cela m'a permis de mieux comprendre le mécanisme des slots, et d'ajouter les routines qui vont avec.
pitfall48.ROM
A la prochaine Étienne. Edité par ericb59 Le 15/01/2022 à 11h34
J'ai enfin retravaillé sur FUSION-C 1.3 la suite, après plusieurs mois de black-out.
J'ai finalisé ma première ROM viable en 48K que je vous partage ici ...
Alors c'est rien du tout d'interessant, c'est une compilation de deux jeux 16K que j'ai réunit en une seule ROM de 48K. Mais comme j'suis content je vous la poste !
Cela m'a permis de mieux comprendre le mécanisme des slots, et d'ajouter les routines qui vont avec.
pitfall48.ROM
A la prochaine Étienne. Edité par ericb59 Le 15/01/2022 à 11h34
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie