La Place des Développeurs La quête pour jouer de la musique en assembleur
Je recommence à me poser des questions sur la méthode pour jouer de la musique en assembleur. Après pas mal d'analyses sur plusieurs listings (dont l'UFO de notre Osaure national ), j'ai cru comprendre que la méthode à employer est de détourner le hook H.TIMI, qui gère une interruption liée au temps. En gros, dès qu'on a cette fameuse interruption, on saute à une routine qui incrémente un compteur, qui sert de "tempo" pour la musique. Quand ce tempo atteint une certaine valeur, on peut alors remplir les registres du PSG pour obtenir les notes voulues.
Ma question est la suivante : cette routine d'interruption a-t'elle un lien quelconque avec la fréquence d’affichage ?
En fait, à la base, j'avais réfléchi à me servir du bit VR du registre S2, sachant qu'on est en 50 Hz, donc un rafraîchissement d'écran toutes les 0,02 secondes, ce qui fait que je pourrais traiter des notes en quadruples croches en tempo 187, ce qui est TRES rapide.
En gros, je me demande si le détournement du hook aurait le même résultat que de me baser sur le bit VR. (j'espère être clair, la question est un peu... difficile à exprimer )
Ma question est la suivante : cette routine d'interruption a-t'elle un lien quelconque avec la fréquence d’affichage ?
En fait, à la base, j'avais réfléchi à me servir du bit VR du registre S2, sachant qu'on est en 50 Hz, donc un rafraîchissement d'écran toutes les 0,02 secondes, ce qui fait que je pourrais traiter des notes en quadruples croches en tempo 187, ce qui est TRES rapide.
En gros, je me demande si le détournement du hook aurait le même résultat que de me baser sur le bit VR. (j'espère être clair, la question est un peu... difficile à exprimer )
MSX un jour, MSX toujours !
Le hook H.TIMI est appelé à la même fréquence que le VDP.
Donc 50Hz ou 60Hz en fonction du paramétrage ...
Donc 50Hz ou 60Hz en fonction du paramétrage ...
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)
Fabf
Membre non connecté
Conseiller Municipal
Je confirme pour la vitesse
Pour le reste ça me dépasse
Pour le reste ça me dépasse
MSXosaure :
Il me semble que dans les jeux du commerce il y a une différence de vitesse (de musique notamment) entre MSX euro et MSX Jap.
Ceci dit, c'est facile à éviter si on le prend en compte à l'écriture de la routine.
Il suffit d'incrémenter le compteur tempo différemment en fonction de la fréquence d'affichage du VDP, en paramétrant l'incrément au démarrage.
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)
Metalion :
Ceci dit, c'est facile à éviter si on le prend en compte à l'écriture de la routine.
Il suffit d'incrémenter le compteur tempo différemment en fonction de la fréquence d'affichage du VDP, en paramétrant l'incrément au démarrage.
MSXosaure :
Il me semble que dans les jeux du commerce il y a une différence de vitesse (de musique notamment) entre MSX euro et MSX Jap.
Ceci dit, c'est facile à éviter si on le prend en compte à l'écriture de la routine.
Il suffit d'incrémenter le compteur tempo différemment en fonction de la fréquence d'affichage du VDP, en paramétrant l'incrément au démarrage.
c'est le cas du démineur fourni en exemple avec ASMSX, mais là pour un chrono.
Le MSXien le plus à l'ouest ... ou presque
OK, merci de cet éclairage qui confirme ce que j'imaginais.
Autre question maintenant : quelle est la méthode qui semble donc la plus adéquate, en terme de... qualité (place occupée en RAM, temps d'exécution...), contrainte moindre et interaction avec d'autres évènements (comme un clic de souris) ? Ou bien, là aussi, les méthodes sont équivalentes ?
Au chapitre des contraintes, en traînant sur MSX Assembly pages, j'ai cru comprendre qu'il fallait toujours remettre par défaut le registre S0 pour la méthode du test du VBlank, et par l'autre méthode, il faut sauvegarder et restaurer le hook...
Autre question maintenant : quelle est la méthode qui semble donc la plus adéquate, en terme de... qualité (place occupée en RAM, temps d'exécution...), contrainte moindre et interaction avec d'autres évènements (comme un clic de souris) ? Ou bien, là aussi, les méthodes sont équivalentes ?
Au chapitre des contraintes, en traînant sur MSX Assembly pages, j'ai cru comprendre qu'il fallait toujours remettre par défaut le registre S0 pour la méthode du test du VBlank, et par l'autre méthode, il faut sauvegarder et restaurer le hook...
MSX un jour, MSX toujours !
granced :
Autre question maintenant : quelle est la méthode qui semble donc la plus adéquate, en terme de... qualité (place occupée en RAM, temps d'exécution...), contrainte moindre et interaction avec d'autres évènements (comme un clic de souris) ? Ou bien, là aussi, les méthodes sont équivalentes ?
Au chapitre des contraintes, en traînant sur MSX Assembly pages, j'ai cru comprendre qu'il fallait toujours remettre par défaut le registre S0 pour la méthode du test du VBlank, et par l'autre méthode, il faut sauvegarder et restaurer le hook...
Au chapitre des contraintes, en traînant sur MSX Assembly pages, j'ai cru comprendre qu'il fallait toujours remettre par défaut le registre S0 pour la méthode du test du VBlank, et par l'autre méthode, il faut sauvegarder et restaurer le hook...
Le temps d'exécution sera globalement le même, car ce qui prend de la place, ce n'est pas la gestion du timer, mais bien la lecture et l'éxécution des notes (pour info, un "replayer" célèbre dont j'ai oublié le nom fait 6 Ko de code ...). La qualité dépendra de la qualité du code, point.
En ce qui concerne les contraintes que tu cites, elles sont négligeables : la remise à zéro du registre est effectivement nécessaire, mais facile à gérer, et le hook doit être sauvegardé et restauré seulement une fois, à l'initialisation.
Par contre, je pense que la gestion par interruption est mille fois plus facile que par l'autre méthode, car elle est indépendante et autonome. Tu n'as pas à t'occuper du timer ni de la lecture, et tu peux passer des arguments à ta routine et/ou déclencher des évènements par des variables placées en RAM que ta routine vient lire à chaque itération. L'autre méthode t'oblige à arrêter ton code principal à intervalle plus ou moins régulier, afin de t'inquiéter du timer et de la gestion de la lecture ... Edité par Metalion Le 19/12/2011 à 21h06
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)
Bon eh bien je me relance tout doucement dans le codage pour faire de la musique en assembleur.
Je m'oriente donc pour la gestion du temps vers l'utilisation du VBLANK : à chaque "fin d'affichage" de l'écran, j'aurai un compteur qui s'incrémentera de 1.
Pour l'exemple que je veux traiter, je pars sur le thème de Zelda (comme ça, si j'arrive au bout de mes peines, l'Osaure pourra le piquer au besoin pour son moteur ).
Sur la partition du morceau, j'ai des triolets (division d'une noire en 3), ce qui va me poser un nouveau problème pour le dénominateur commun de toutes les notes : comme j'ai aussi de la double croche, je dois tout passer en 12ème de noire... Le tempo de la partition étant de 150, la durée de la noire est de 60/150 donc 0,4 secondes. Mon "douzième" de noire est donc de 0.03333333, que je vais arrondir à 0.04.
Ma méthode de comptage de temps se base sur les 50 Hz de fréquence d'affichage français, soit 0.02 (1/50). Ce qui veut dire que j'atteindrai le douzième de noire au bout de deux incréments de mon compteur !
Par contre, le passage en douzième de notes, implique que chaque mesure fera douze notes, sur 24 mesures et 3 voies, soit la bagatelle de 864 notes
Cependant, ces notes ne changeront pas forcément à chaque double incrément (imaginons que j'ai sur le même temps 3 noires, ça me fait 12 douzièmes, donc je ne change aucun registre du PSG pendant 24 incréments du compteur).
De même, il n'est pas obligatoire de changer TOUTES mes valeurs de registre : si pendant une blanche sur une voie j'ai deux noires sur les deux autres voies, il n'y a que les registres de ces 2 voies à changer...
Bref un poil complexe, mais je pense avoir une idée, qui a nécessité du boulot en amont : lister toutes les notes en douzièmes, et calculer les intervalles pendant lesquels je n'ai aucun changement de registre. Au lieu d'avoir une alimentation des registres "statique", j'aurai alors une alimentation dynamique. Il me suffit de mettre quelque part les différentes tailles d'intervalles !
Je ne sais pas si j'ai été clair...
Je m'oriente donc pour la gestion du temps vers l'utilisation du VBLANK : à chaque "fin d'affichage" de l'écran, j'aurai un compteur qui s'incrémentera de 1.
Pour l'exemple que je veux traiter, je pars sur le thème de Zelda (comme ça, si j'arrive au bout de mes peines, l'Osaure pourra le piquer au besoin pour son moteur ).
Sur la partition du morceau, j'ai des triolets (division d'une noire en 3), ce qui va me poser un nouveau problème pour le dénominateur commun de toutes les notes : comme j'ai aussi de la double croche, je dois tout passer en 12ème de noire... Le tempo de la partition étant de 150, la durée de la noire est de 60/150 donc 0,4 secondes. Mon "douzième" de noire est donc de 0.03333333, que je vais arrondir à 0.04.
Ma méthode de comptage de temps se base sur les 50 Hz de fréquence d'affichage français, soit 0.02 (1/50). Ce qui veut dire que j'atteindrai le douzième de noire au bout de deux incréments de mon compteur !
Par contre, le passage en douzième de notes, implique que chaque mesure fera douze notes, sur 24 mesures et 3 voies, soit la bagatelle de 864 notes
Cependant, ces notes ne changeront pas forcément à chaque double incrément (imaginons que j'ai sur le même temps 3 noires, ça me fait 12 douzièmes, donc je ne change aucun registre du PSG pendant 24 incréments du compteur).
De même, il n'est pas obligatoire de changer TOUTES mes valeurs de registre : si pendant une blanche sur une voie j'ai deux noires sur les deux autres voies, il n'y a que les registres de ces 2 voies à changer...
Bref un poil complexe, mais je pense avoir une idée, qui a nécessité du boulot en amont : lister toutes les notes en douzièmes, et calculer les intervalles pendant lesquels je n'ai aucun changement de registre. Au lieu d'avoir une alimentation des registres "statique", j'aurai alors une alimentation dynamique. Il me suffit de mettre quelque part les différentes tailles d'intervalles !
Je ne sais pas si j'ai été clair...
MSX un jour, MSX toujours !
Juste une remarque : un tempo à 150 implique 150 croches à la minutes, non ?
Ce serait donc 75 noires à la minute.
La durée de ta noire serait donc de 0,8 secondes et ton 12e de noire serait à 0,0666 secondes.
Soit tu l'arrondis à 0,06 secondes (donc 3 incréments compteur), soit à 0,08 secondes (donc 4 incréments compteur).
Ce serait donc 75 noires à la minute.
La durée de ta noire serait donc de 0,8 secondes et ton 12e de noire serait à 0,0666 secondes.
Soit tu l'arrondis à 0,06 secondes (donc 3 incréments compteur), soit à 0,08 secondes (donc 4 incréments compteur).
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)
Metalion :
Juste une remarque : un tempo à 150 implique 150 croches à la minutes, non ?
Tout dépend du symbole sur la partition (ci-jointe) ! Ici j'ai bien une noire, donc a priori 150 noires à la minute.
MSX un jour, MSX toujours !
Ah OK, autant pour moi
Ne t'inquiètes pas pour l'intervalle qui te semble court (deux incréments de compteur).
Temps d'une frame x fréquence Z80 = nombre de T-states
[50Hz] 20000 µsec x 3.579545 MHz = 71590 T-states
[60Hz] 16667 µsec x 3.579545 MHz = 59659 T-states
Sur le temps d'une frame, environ 60% se passe pendant l'affichage et 40% hors affichage.
Cela veut dire qu'à 50Hz, tu disposes d'environ 23800 T-states hors affichage.
De cela, il faut déduire la gestion des interruptions en ROM, qui prend au maximum 9990 T-states (sur un MSX Turbo-R FS A1 GT).
Il te reste donc environ 13800 T-states par frame pour l'exécution d'un programme hors affichage.
Et sur deux frames (deux incréments de compteur), cela fait donc 27600 T-states, soit environ 6900 instructions simples pour le Z80 !
Et ça, c'est dans le cas ou tu veux ne pas perturber la partie affichage de ton programme (dans le cas d'un jeu par exemple).
Si ce n'est pas important, tu disposes alors d'environ 99000 T-states, soit 24750 instructions simples. Edité par Metalion Le 17/04/2012 à 16h58
Ne t'inquiètes pas pour l'intervalle qui te semble court (deux incréments de compteur).
Temps d'une frame x fréquence Z80 = nombre de T-states
[50Hz] 20000 µsec x 3.579545 MHz = 71590 T-states
[60Hz] 16667 µsec x 3.579545 MHz = 59659 T-states
Sur le temps d'une frame, environ 60% se passe pendant l'affichage et 40% hors affichage.
Cela veut dire qu'à 50Hz, tu disposes d'environ 23800 T-states hors affichage.
De cela, il faut déduire la gestion des interruptions en ROM, qui prend au maximum 9990 T-states (sur un MSX Turbo-R FS A1 GT).
Il te reste donc environ 13800 T-states par frame pour l'exécution d'un programme hors affichage.
Et sur deux frames (deux incréments de compteur), cela fait donc 27600 T-states, soit environ 6900 instructions simples pour le Z80 !
Et ça, c'est dans le cas ou tu veux ne pas perturber la partie affichage de ton programme (dans le cas d'un jeu par exemple).
Si ce n'est pas important, tu disposes alors d'environ 99000 T-states, soit 24750 instructions simples. Edité par Metalion Le 17/04/2012 à 16h58
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