Prenons un cas concret.
On suppose que x est chargé avec l'adresse des données du morceau de musique.
A l'adresse de x on retrouve donc le header:
Code:
| 05 f1 | 06 | 03 | 01 | b6 | 05 c6 | 00 00 | 01 e2 | 00 | 08 | ...
-- -- -- -- -- -- -- -- -- -- -- -- -- --
| | | | | | | | | |_ volume piste FM0
| | | | | | | | |
| | | | | | | | |_ transposition piste FM0
| | | | | | | |
| | | | | | | |_ offset des données de la piste FM0
| | | | | | |
| | | | | | |_ identifiant de piste DAC (valeur 0000)
| | | | | |
| | | | | |_ offset des données de la piste DAC
| | | | |
| | | | |_ delay
| | | |
| | | |_ tempo
| | |
| | |_ nb de pistes PSG
| |
| |_ nb de pistes FM
|
|_ offset des données de définition des instruments
en position $01e2,x on retrouve les données de la piste FM0 :
Code:
ef 05 80 30 80 9b 0c a7 a5 08 a7 04
Les données sont encodées dans un octet de la manière suivante :
Code:
$00-7F : Durée
$80 : Pause
$81-$DF : Note
$E0-$FF : Commande (Coordination flag)
Les octets de commande peuvent être suivis de plusieurs octets de paramètres.
Si on décode les données on a :
Code:
$EF $05 : SetVoice 05 => Sélection de l'instrument pour cette piste
$80 : Pause
$30 : durée 48 frames (démultiplié par le tempo)
$80 : Pause
- pas de durée - : on reprend la dernière durée lue soit 48 frames
$9b : Note C#2
$0c : Durée 12 frames (démultiplié par le tempo)
...
SubtilitéSi on a : Une note, une durée, une durée
On jouera deux fois la même note avec des durées différentes
Si on a : Une note, une durée, une note, une note
On jouera trois notes différentes de la même durée
Fréquences et Notes de musiqueLe tableau ci dessous est une synthèse des notes et fréquences pour les puces YM2612 et YM2413 que j'ai réalisé et posté sur le forum de SonicRetro.
On y retrouve les paramètres FNum et Block qui sont envoyés à la puce son pour paramétrer une fréquence d'instrument.
Le driver smps gère les 95 notes C0-A#7 ce qui correspond aux notes midi 12-106
Fichier(s) joint(s):
YM2612-YM2413 Freq&Notes.png [ 84.48 Kio | Vu 9729 fois ]
Dans le code quand on lit les données de musique, on transforme donc une note en données FNum et Block à l'aide du code suivant :
Code:
FMSetFreq
subb #$80 ; Test for a rest
bne @a
lda PlaybackControl,y ; Set bit 1 (track is at rest)
ora #$02
sta PlaybackControl,y
bra @b
@a addb Transpose,y ; Add current channel transpose (coord flag E9)
aslb ; Transform note into an index...
ldu #Frequencies
lda #0
ldd d,u
std NextData,y ; Store Frequency
@b ldb ,x ; Get next byte
...
; 95 notes (Note value $81=C0 $DF=A#7)
Frequencies
fdb $0000 ; padding for ($80=rest), saves a dec instruction
fdb $00AD,$00B7,$00C2,$00CD,$00DA,$00E6,$00F4,$0102,$0112,$0122,$0133,$0146 ; C0 - B0
fdb $0159,$016D,$0183,$019A,$01B3,$01CC,$01E8,$0302,$0312,$0322,$0333,$0346 ; C1 - B1
fdb $0359,$036D,$0383,$039A,$03B3,$03CC,$03E8,$0502,$0512,$0522,$0533,$0546 ; C2 - B2
fdb $0559,$056D,$0583,$059A,$05B3,$05CC,$05E8,$0702,$0712,$0722,$0733,$0746 ; C3 - B3
fdb $0759,$076D,$0783,$079A,$07B3,$07CC,$07E8,$0902,$0912,$0922,$0933,$0946 ; C4 - B4
fdb $0959,$096D,$0983,$099A,$09B3,$09CC,$09E8,$0B02,$0B12,$0B22,$0B33,$0B46 ; C5 - B5
fdb $0B59,$0B6D,$0B83,$0B9A,$0BB3,$0BCC,$0BE8,$0D02,$0D12,$0D22,$0D33,$0D46 ; C6 - B6
fdb $0D59,$0D6D,$0D83,$0D9A,$0DB3,$0DCC,$0DE8,$0F02,$0F12,$0F22,$0F33 ; C7 - A#7
L'envoi d'une nouvelle fréquence à la puce YM2413 se fait ainsi :
Code:
FMUpdateFreq
ldb Detune,y
sex
addd NextData,y ; apply detune but don't update stored frequency
addd ModulationVal,y ; add modulation effect
sta @dyn+1
lda #$10 ; set LSB Frequency Command
adda VoiceControl,y ; get channel number
ldu #YM2413_A0
sta ,u ; send Fnum update Command
adda #$10 ; set Sus/Key/Block/FNum(MSB) Command(and used as 2 cycles tempo)
nop ; total wait 4 cycles
stb 1,u ; send FNum (b0-b7)
_YMBusyWait17 ; total wait 24 cycles
ldb NoteControl,y ; load current value (do not erase FNum MSB) (and used as 5 cycles tempo)
sta ,u ; send command
andb #$F0 ; clear FNum MSB (and used as 2 cycles tempo)
@dyn addb #0 ; (dynamic) Set Fnum MSB (and used as 2 cycles tempo)
stb 1,u ; send FNum (b8) and Block (b0-b2)
stb NoteControl,y
rts
Il faut envoyer l'information en deux mises à jour de registre.
Chaque mise à jour est composée :
- d'un envoi de commande
- d'une attente de 4 cycles (6809)
- d'un envoi de valeur
- d'une attente de 24 cycles (6809) avant de pouvoir envoyer une nouvelle commande
Pour référence :
Fichier(s) joint(s):
YM2413 Freq Reg.png [ 35.51 Kio | Vu 9729 fois ]