La Place des Développeurs Assembleur MSX pour les noobs cours en ligne
TurboSEB
Membre non connecté
Conseiller Municipal
"- cadencement d'un programme par l'interruption graphique du passage à 0 vertical"
Ça, ca semble pas mal pour un Début
(juste en aparté, c'est quoi ? J'ai bien une petite idée, mais je suis pas sûre )
En définitive, faudra bien commencer par qque chose et tous les paragraphes semblent très intéressant, commençons par le premier Edité par TurboSEB Le 06/10/2018 à 20h18
Ça, ca semble pas mal pour un Début
(juste en aparté, c'est quoi ? J'ai bien une petite idée, mais je suis pas sûre )
En définitive, faudra bien commencer par qque chose et tous les paragraphes semblent très intéressant, commençons par le premier Edité par TurboSEB Le 06/10/2018 à 20h18
MSX 1&2 + Moniteurs+divers (environ 0.70Tonnes)
Je suis très chaud pour un article sur la musique en assembleur. J'avais bien des idées (voir ici) mais jamais eu trop l'opportunité de mettre en pratique.
@Turboseb
Le VBLANK (c'est son petit nom), je crois que c'est le moment (interruption) où ton MSX a fini d'afficher la dernière ligne horizontale, avant de passer à l'image suivante. Sur ce que j'a compris, comme ça se fait à fréquence constante, on s'en sert pour donner un "tempo" à un programme... ou une musique d'ailleurs. Par exemple, si tu ne ralentis pas en assembleur l'affichage des sprites lors d'un déplacement, celui-ci sera bien trop rapide !
N'hésitez pas à me corriger si je me fourvoie
@Turboseb
Le VBLANK (c'est son petit nom), je crois que c'est le moment (interruption) où ton MSX a fini d'afficher la dernière ligne horizontale, avant de passer à l'image suivante. Sur ce que j'a compris, comme ça se fait à fréquence constante, on s'en sert pour donner un "tempo" à un programme... ou une musique d'ailleurs. Par exemple, si tu ne ralentis pas en assembleur l'affichage des sprites lors d'un déplacement, celui-ci sera bien trop rapide !
N'hésitez pas à me corriger si je me fourvoie
MSX un jour, MSX toujours !
Sector28_3 :
le cadencement-d'un-programme-par-l'interruption-graphique-du-passage-à-0-vertical se résume à ceci:
EI
HALT
EI
HALT
Non. Et pour deux raisons :
1) il y a d'autres interruptions que le VBLANK qui peuvent réveiller le Z80 après un HALT, notamment celles provenant des lecteurs de disquette, mais aussi de la prise RS232, ...
2) c'est un peu inefficace de stopper complètement le processeur en attendant une interruption, on perd du temps utile
La seule vraie façon de faire consiste à utliser le hook prévu à cet effet, appelé par le BIOS à chaque VBLANK.
Sector28_3 :
le vblank se déclenche à la dernière ligne en mode pal, et à la première ligne en mode NTSC
Pas sûr de ça.
Pour moi le VBLANK se déclenche après l'affichage de la dernière ligne, dans les deux cas.
granced :
Je suis très chaud pour un article sur la musique en assembleur. J'avais bien des idées (voir ici) mais jamais eu trop l'opportunité de mettre en pratique.
Granced, j'ai écrit un replayer PSG en assembleur, basé sur les interruptions.
Plus court que ce que je pensais à l'origine (un peu plus d'un 1Ko).
Si tu veux, on peut échanger sur le sujet ?
Edité par Metalion Le 08/10/2018 à 11h57
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)
Sector28_3 :
peux-tu me dire comment tu ferais pour éviter cette perte de temps utile ?
après tout, ce n'est qu'une façon comme une autre de programmer
après tout, ce n'est qu'une façon comme une autre de programmer
Quand tu utilises HALT, le processeur s'arrête et attend une interruption.
Et pendant ce temps, il ne fait strictement rien !
Si tu utilises le hook du VBLANK, ton code principal se déroule jusqu'au moment de l'interruption.
Il n'y a donc aucun arrêt du processeur.
granced :
Avec plaisir. Tu as le code source commenté ? Histoire que je comprenne comment il fonctionne ?
Oui, il est commenté, bien sûr.
Code :
;===========================================================
; Librairie SFX v2.50 - Replayer PSG/SCC sur ISR
; taille : octets
;-----------------------------------------------------------
; History:
; v1.00 : single channel
; v2.00 : three channels
; v2.10 : direct note decoder
; v2.20 : new format of note decoder
; v2.30 : ADSR with Bresenham
; v2.31 : ADSR with value field
; v2.32 : Eight is now the master length
; v2.33 : ADSR with number of frames
; v2.40 : Track made with sequences
; v2.50 : SCC
;-----------------------------------------------------------
; Routines:
; SFX_START : Initialisation du lecteur
; SFX_LOAD : Ajout d'une séquence au lecteur
; SFX_PLAY : Lecture (appelé à chaque interruption VBLANK)
; SFX_PAUSE : Pause du lecteur
; SFX_RESUME : Reprise du lecteur
; SFX_STOP : Arrêt du lecteur
;-----------------------------------------------------------
; Espace à réserver en RAM (154 octets)
;-----------------------------------------------------------
;sound_status: ds 2
;PSG1: ds 19
;PSG2: ds 19
;PSG3: ds 19
;SCC1: ds 19
;SCC2: ds 19
;SCC3: ds 19
;SCC4: ds 19
;SCC5: ds 19
voice_mix equ 0
eight equ 1
volume equ 2
frame_number equ 3
note_length equ 4
silence equ 5
first_sequence equ 6 ; 2 octets
current_sequence equ 8 ; 2 octets
note equ 10 ; 2 octets
attack_dx equ 12
attack_dy equ 13
decay_dx equ 14
decay_dy equ 15
sustain_level equ 16
release_dx equ 17
release_dy equ 18
last equ 19
;-----------------------------------------------------------
; Données pour chaque voix
;-----------------------------------------------------------
; Entête
; - voice_mix : paramétrage inverse du R#7 PSG pour cette séquence
; - tempo : en nombre de noires par minute
; - volume : volume principal
; - attack : en nombre de frames
; - decay : en nombre de frames
; - sustain : niveau de volume de soutien
; - release : en nombre de frames
; Enchainement des séquences
; - adresse séquence #1
; - adresse séquence #2
; - ...
; - $FFFF : fin des séquence (arrêt de la voix)
; ou
; - $FFxx : recommence à la séquence #1
; Séquence
; Pour chaque son :
; - longueur de note en double croches
; - note
; - octave
; - $FF : fin de séquence
;===========================================================
;===========================================================
; SFX_START : Initialisation du lecteur
;===========================================================
SFX_START:
; Mise à zéro des pointeurs et variables
ld hl,sound_status
ld de,sound_status+1
ld bc,2+3*last
ld [hl],0
ldir
; raz du PSG et sortie
jp SFX_STOP
;===========================================================
; SFX_LOAD : Chargement d'une voix dans le lecteur
; [in] hl : adresse de la voix
;===========================================================
SFX_LOAD:
; choix du canal de la séquence
ld a,[hl]
and 001001b ; canal A ?
ld ix,PSG1
jp nz,init_voice
ld a,[hl]
and 010010b ; canal B ?
ld ix,B_voice
jp nz,init_voice
ld a,[hl]
and 100100b ; canal C ?
ld ix,C_voice
; sortie si aucun son
ret z
ld de,19
ld ix,PSG1
ld b,1
ld a,[hl]
loop: and b
jp nz,init_voice
sla b
add ix,de
jp loop
init_voice:
; voice mix
ld [ix+voice_mix],a
; mise à jour du sound status et du registre 7
ld b,a
ld a,[sound_status]
or b
ld [sound_status],a
; inversion de la valeur et écriture dans le registre 7
cpl
and 00111111b
or 10000000b ; protection PSG
ld e,a
ld a,7
call WRTPSG
; calcul de la durée d'une double croche
inc hl
ld a,[hl] ; tempo
call EIGHT
ld [ix+eight],a
; volume principal
inc hl
ld a,[hl] ; volume principal
ld [ix+volume],a
ld [ix+attack_dy],a
; préparation de l'enveloppe ADSR
; attack
inc hl
ld a,[hl]
ld [ix+attack_dx],a
; decay
inc hl
ld a,[hl]
ld [ix+decay_dx],a
; sustain
inc hl
ld a,[hl]
ld [ix+sustain_level],a
ld b,a
ld a,[ix+volume]
sub b
ld [ix+decay_dy],a ; dy = |sustain - volume|
; release
inc hl
ld a,[hl]
ld [ix+release_dx],a
ld a,b
ld [ix+release_dy],a ; dy = |0 - sustain|
; pointeur sur l'adresse de la première séquence
; (et donc la séquence en cours)
inc hl
ld [ix+first_sequence+1],h
ld [ix+first_sequence],l
ld [ix+current_sequence+1],h
ld [ix+current_sequence],l
; pointeur sur l'adresse de la première note de la première séquence
ld e,[hl]
inc hl
ld d,[hl]
ld [ix+note+1],d
ld [ix+note],e
; durée de son à 1 et frame number à zéro, pour le
; chargement automatique de la première note par SFX_PLAY
ld [ix+frame_number],0
ld [ix+note_length],1
; sortie
ret
;-----------------------------------------------------------
; calcul de la durée d'une double croche
; [in] a: tempo de la séquence
; [out] a: durée en frames d'une noire
;-----------------------------------------------------------
; constante BIOS
BASRVN equ 002Bh ; BASIC ROM version number
EIGHT: ex af,af'
exx
; détermination de la fréquence du VBLANK
ld a,[BASRVN]
rla ; récupération du bit 7 dans carry
ld hl,60*50/4 ; base de calcul 50Hz (60 secondes x 50 Hz / 4)
jp c,vdp50Hz
ld hl,60*60/4 ; base de calcul 60Hz (60 secondes x 60 Hz / 4)
; calcul de la durée d'une noire = 60 x fréquence / 4 / tempo
vdp50Hz:ex af,af'
ld c,a
call DIV_HL_BY_C
ld a,l ; a=résultat de la division
exx
ret
;===========================================================
; SFX_PLAY : Lecture (appelé à chaque interruption VBLANK)
;===========================================================
SFX_PLAY:
; sortie si aucun son en cours
ld a,[sound_status]
and a
ret z
; traitement des voix
; voix & noise A
and 001001b
ld ix,PSG1
ld d,0
call nz,play_channel
; voix & noise B
ld a,[sound_status]
and 010010b
ld ix,PSG2
ld d,1
call nz,play_channel
; voix & noise C
ld a,[sound_status]
and 100100b
ld ix,PSG3
ld d,2
; sortie si plus de canal à traiter
ret z
;-----------------------------------------------------------
; traitement du canal
;-----------------------------------------------------------
play_channel:
; incrémentation du numéro de frame
inc [ix+frame_number]
ld a,[ix+frame_number]
; comparaison avec la longueur de la note
cp [ix+note_length]
; si fin du son, chargement d'un nouveau son
jp z,new_sound
; si c'est un silence en cours, sortie
ex af,af'
ld a,[ix+silence]
and a
ret nz
; sinon, récupération du volume de l'enveloppe ADSR
ex af,af'
call ADSR
; écriture si valeur différente et sortie
ld e,a
ld a,d
add 8
ld b,a
call RDPSG
cp e
ret z
ld a,b
jp WRTPSG
;-----------------------------------------------------------
; nouveau son
;-----------------------------------------------------------
new_sound:
; chargement dans 'hl' de la position de note
ld h,[ix+note+1]
ld l,[ix+note]
; si 'FF', alors fin de séquence
ld a,[hl]
cp 0FFh
jp z,sequence_end
new_sound2:
; sinon, c'est la longueur de note, ajustement
call NOTE_LENGTH
ld [ix+note_length],a
; et numéro de frame à zéro
ld [ix+frame_number],0
; et ensuite la note en elle-même
inc hl
ld a,[hl]
cp 82 ; "R" silence
jp z,rest
ld [ix+silence],0 ; flag de silence à zéro
sub 65 ; "A"
add a
add a ; x4
ld c,a ; c = 4.note
; altérations éventuelles ou octave
inc hl
ld a,[hl]
; altérations du ton de la note
cp 35 ; "#" dièse
call z,DIESE
cp 98 ; "b" bémol
call z,BEMOL
; altérations de la longueur de note
cp 46 ; "." pointée
call z,DOTTED
cp 58 ; ":" double pointée
call z,DOUBLE_DOTTED
; calcul de l'octave
dec a
add a
add a ; x4
ld e,a
add a
add a
add a ; x32
sub e ; x28
add a,c
ld b,0
ld c,a ; bc = 28.octave + 4.note (+/- 2.demi-note)
; fréquence de la note
push hl
ld hl,frequencies
add hl,bc
; partie basse
ld e,[hl]
ld a,d
add a ; x2
call WRTPSG
; partie haute
inc hl
ld e,[hl]
ld a,d
add a
inc a ; x2+1
call WRTPSG
; volume initial de l'enveloppe : ADSR(0)
xor a
call ADSR
ld e,a
ld a,d
add 8
call WRTPSG
; préparation du pointeur de note pour la prochaine note
pop hl
inc hl
ld [ix+note+1],h
ld [ix+note],l
ret
;-----------------------------------------------------------
; silence
;-----------------------------------------------------------
rest: ; volume à zéro
ld e,0
ld a,d
add 8
call WRTPSG
; flag de silence à 1
ld [ix+silence],1
; préparation du pointeur de note pour la prochaine note
inc hl
ld [ix+note+1],h
ld [ix+note],l
; sortie
ret
;-----------------------------------------------------------
; fin de séquence
;-----------------------------------------------------------
sequence_end:
; chargement du pointeur sur l'adresse de la séquence suivante
ld h,[ix+current_sequence+1]
ld l,[ix+current_sequence]
inc hl
inc hl
ld [ix+current_sequence+1],h
ld [ix+current_sequence],l
; fin du track ?
ld e,[hl]
inc hl
ld d,[hl]
ld a,0FFh
cp d
jp z,track_end
; sinon, chargement adresse première note séquence suivante et reprise
ld [ix+note+1],d
ld [ix+note],e
ld a,[de]
jp new_sound2
;-----------------------------------------------------------
; fin de track
;-----------------------------------------------------------
track_end:
cp e
jp z,track_stop ; $FFFF
; répétition de la voix ($FFxx)
; reprise de la première séquence
ld h,[ix+first_sequence+1]
ld l,[ix+first_sequence]
ld [ix+current_sequence+1],h
ld [ix+current_sequence],l
; chargement adresse première note séquence suivante et reprise
ld e,[hl]
inc hl
ld d,[hl]
ld [ix+note+1],d
ld [ix+note],e
ld a,[de]
jp new_sound2
track_stop:
; arrêt du canal note & noise
ld a,[ix+voice_mix]
cpl
ld b,a
ld a,[sound_status]
and b
ld [sound_status],a
; et mise à jour du registre 7 du PSG
cpl
and 00111111b
or 10000000b
ld e,a
ld a,7
jp WRTPSG
;-----------------------------------------------------------
; Enveloppe ADSR
; [in] a: numéro de frame de la note en cours
; [out] a: volume de l'enveloppe
;-----------------------------------------------------------
ADSR: ld b,a
ld a,[ix+attack_dx]
cp b ;
jp c,decay ; frame >= temps d'attaque
; -- Attack --
ld h,b
ld e,[ix+attack_dy]
call MUL_H_BY_E
ld c,[ix+attack_dx]
call DIV_HL_BY_C
ld a,l
ret
; -- Decay --
decay: add a,[ix+decay_dx]
cp b
jp c,sustain ; frame >= temps de decay
ld a,b
sub [ix+attack_dx]
ld h,a
ld e,[ix+decay_dy]
call MUL_H_BY_E
ld c,[ix+decay_dx]
call DIV_HL_BY_C
ld a,l
neg
add [ix+volume]
ret
; -- Sustain --
sustain:ld a,[ix+note_length]
sub [ix+release_dx]
cp b
jp c,release ; frame >= longueur note - temps de release
ld a,[ix+sustain_level]
ret
; -- Release --
release:sub b ; a = frame - (longueur de note - temps de release)
ret c ; sortie si négatif
ld h,a
ld e,[ix+release_dy]
call MUL_H_BY_E
ld c,[ix+release_dx]
call DIV_HL_BY_C
ld a,l
neg
add [ix+sustain_level]
ret
;-----------------------------------------------------------
; Calcul de la longueur de note
; [in] a: longueur de note en nombre de quadruple croches
; [out] a: longueur de note en frames (max 255, pas de protection !)
;-----------------------------------------------------------
NOTE_LENGTH:
ld b,a
cp 4 ; 4 = valeur d'une double croche
ld a,[ix+eight]
ret z ; c'est une double croche
jp c,@@less
; c'est plus long
@@more: add a ; a=ax2
srl b ; b=b/2
bit 2,b
ret nz
jp @@more
; c'est plus court
@@less: srl a ; a=a/2
sla b ; b=bx2
bit 2,b
ret nz
jp @@less
;-----------------------------------------------------------
; altérations chromatiques
;-----------------------------------------------------------
DIESE: inc c
inc c ; bc = 4.note + 2.demi-note
inc hl
ld a,[hl] ; élément suivant
ret
BEMOL: dec c
dec c ; bc = 4.note - 2.demi-note
inc hl
ld a,[hl] ; élément suivant
ret
;-----------------------------------------------------------
; altérations de la longueur de note
;-----------------------------------------------------------
DOTTED: ex af,af'
ld a,[ix+note_length]
ld b,a
srl b ; b=a/2
add b ; a=1.5xa
ld [ix+note_length],a
ex af,af'
inc hl
ld a,[hl] ; élément suivant
ret
DOUBLE_DOTTED:
ex af,af'
ld a,[ix+note_length]
ld b,a
srl b ; b=a/2
ld e,b
srl e ; e=a/4
add b
add e ; a=1.75xa
ld [ix+note_length],a
ex af,af'
inc hl
ld a,[hl] ; élément suivant
ret
;===========================================================
; SFX_PAUSE : Pause du lecteur
;===========================================================
SFX_PAUSE:
; sauvegarde du sound_status
ld a,[sound_status]
ld [sound_status+1],a
; arrêt du traitement SFX
xor a
ld [sound_status],a
; toutes les canaux 'off' et sortie
ld a,7
ld e,10111111b
jp WRTPSG
;===========================================================
; SFX_RESUME : Reprise du lecteur
;===========================================================
SFX_RESUME:
; récupération de la sauvegarde
ld a,[sound_status+1]
ld [sound_status],a
; reparamétrage du PSG
cpl
and 00111111b
or 10000000b ; protection PSG
ld e,a
ld a,7
jp WRTPSG
;===========================================================
; SFX_STOP : Arrêt du lecteur
;===========================================================
SFX_STOP:
; toutes les canaux 'off'
ld a,7
ld e,10111111b
call WRTPSG
; mise à zéro du volume canal A
ld a,8
ld e,0
call WRTPSG
; mise à zéro du volume canal B
ld a,9
call WRTPSG
; mise à zéro du volume canal C
ld a,10
jp WRTPSG
;===========================================================
; Module SCC
;===========================================================
SCC_waveform equ 9800h
SCC_register equ 9880h
;===========================================================
; WRTSCC : écriture dans les registres SCC
; [in] a: numéro de registre
; e: valeur
;===========================================================
WRTSCC: ex af,af'
ld a,e
exx
; sélection de la page SCC
ld hl,9000h
ld [hl],03Fh
; écriture
ex af,af'
ld hl,SCC_register
ld c,a
ld b,0
add hl,bc
ex af,af'
ld [hl],a
exx
ret
;===========================================================
; RDSCC : lecture des registres SCC
; [in] a: numéro de registre
; [out] a: valeur
;===========================================================
RDSCC: exx
; sélection de la page SCC
ld hl,9000h
ld [hl],03Fh
; écriture
ld hl,SCC_register
ld c,a
ld b,0
add hl,bc
ld a,[hl]
exx
ret
;===========================================================
; LOAD_WAVE : chargement d'une waveform
; [in] a: numéro de canal
; hl: adresse des données
;===========================================================
LOAD_WAVE:
push hl
; sélection de la page SCC
ld hl,9000h
ld [hl],03Fh
add a,a
add a,a
add a,a
add a,a
add a,a ; a = 32.canal
; transfert des données
ld hl,SCC_waveform
ld e,a
ld d,0
add hl,de
ex de,hl ; de = SCC_waveform + 32.canal
ld bc,32 ; bc = 32
pop hl ; hl = adresse des données
ldir
ret
;===========================================================
; Multiplication de 'h' par 'e'
; [in] h: donnée
; e: multiplicateur
; [out] hl: résultat
;===========================================================
MUL_H_BY_E:
ld a,d ; sauvegarde de 'd'
ld d,0
ld l,d
ld b,8
Mloop: add hl,hl
jr nc,NoAdd
add hl,de
NoAdd: djnz Mloop
ld d,a ; récupération de 'd'
ret
;===========================================================
; Division de 'hl' par 'c'
; [in] hl: dividende
; c: diviseur
; [out] l: résultat
; h: reste
;===========================================================
DIV_HL_BY_C:
ld b,8
@@next: add hl,hl
ld a,h
sub c
jr c,@@next_b
ld h,a
inc l
@@next_b:
djnz @@next
ret
;===========================================================
; Table des fréquences de notes
;===========================================================
;---------------------------------------------------------------
;| Octave | | | | | | | | |
;| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
;| Note | | | | | | | | |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| C | D5D | 6AF | 357 | 1AC | D6 | 6B | 35 | 1B |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| C# | C9C | 64E | 327 | 194 | CA | 65 | 32 | 19 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| D | BE7 | 5F4 | 2FA | 17D | BE | 5F | 30 | 18 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| D# | B3C | 59E | 2CF | 168 | 84 | 5A | 2D | 16 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| E | A9B | 54E | 2A7 | 153 | AA | 55 | 2A | 15 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| F | A02 | 501 | 281 | 140 | A0 | 50 | 28 | 14 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| F# | 973 | 4BA | 25D | 12E | 97 | 4C | 26 | 13 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| G | 8EB | 476 | 23B | 11D | 8F | 47 | 24 | 12 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| G# | 88B | 436 | 21B | 10D | 87 | 43 | 22 | 11 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| A | 7F2 | 3F9 | 1FD | FE | 7F | 40 | 20 | 10 |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| A# | 780 | 3C0 | 1E0 | F0 | 78 | 3C | 1E | F |
;|-------------+-----+-----+-----+-----+-----+-----+-----+-----|
;| B | 714 | 38A | 1C5 | E3 | 71 | 39 | 1C | E |
;---------------------------------------------------------------
frequencies:
; table de 224 octets
; A,A#,B,-,C,C#,D,D#,E,-,F,F#,G,G#
dw 07F2h,0780h,0714h,0,0D5Dh,0C9Ch,0BE7h,0B3Ch,0A9Bh,0,0A02h,0973h,08EBh,088Bh ; octave 1
dw 03F9h,03C0h,038Ah,0,06AFh,064Eh,05F4h,059Eh,054Eh,0,0501h,04BAh,0476h,0436h ; octave 2
dw 01FDh,01E0h,01C5h,0,0357h,0327h,02FAh,02CFh,02A7h,0,0281h,025Dh,023Bh,021Bh ; octave 3
dw 00FEh,00F0h,00E3h,0,01ACh,0194h,017Dh,0168h,0153h,0,0140h,012Eh,011Dh,010Dh ; octave 4
dw 007Fh,0078h,0071h,0,00D6h,00CAh,00BEh,0084h,00AAh,0,00A0h,0097h,008Fh,0087h ; octave 5
dw 0040h,003Ch,0039h,0,006Bh,0065h,005Fh,005Ah,0055h,0,0050h,004Ch,0047h,0043h ; octave 6
dw 0020h,001Eh,001Ch,0,0035h,0032h,0030h,002Dh,002Ah,0,0028h,0026h,0024h,0022h ; octave 7
dw 0010h,000Fh,000Eh,0,001Bh,0019h,0018h,0016h,0015h,0,0014h,0013h,0012h,0011h ; octave 8
Edité par Metalion Le 08/10/2018 à 18h45
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)
Ah ouais, quand même... Bon eh bien, à dans 2 ans, le temps que je décortique tout ça !
Blague à part, je vois que tu as intégré la gestion de la SCC (perso j'en demandais pas autant ! ), aurais-tu une version plus condensée avec la gestion du PSG seul ? Et si tu peux nous détailler un peu la méthode que tu emploies (quelle est la forme des datas, comment tu gères les durées de notes comme les triolets ou sextolets ? )
En te remerciant
MSX un jour, MSX toujours !
@Granced
Le module SCC intégré n'est pas encore opérationnel, il y a juste pour l'instant les routines de base. En fait j'aurai du poster la version précédente (v2.40) car cette version n'est pas encore terminée.
Pour répondre à tes questions :
- la forme des datas est précisées dans l'entête du code
- la longueur de note minimale (et l'unité de mesure de toutes les autres) est la quadruple croche (1/16e de noire), je ne gère pas pour l'instant les triolets ou les sextolets
EDIT : mais il faudrait peut-être déplacer cette discussion dans l'autre post que tu avais ouvert sur ce sujet. Edité par Metalion Le 09/10/2018 à 14h29
Le module SCC intégré n'est pas encore opérationnel, il y a juste pour l'instant les routines de base. En fait j'aurai du poster la version précédente (v2.40) car cette version n'est pas encore terminée.
Pour répondre à tes questions :
- la forme des datas est précisées dans l'entête du code
- la longueur de note minimale (et l'unité de mesure de toutes les autres) est la quadruple croche (1/16e de noire), je ne gère pas pour l'instant les triolets ou les sextolets
EDIT : mais il faudrait peut-être déplacer cette discussion dans l'autre post que tu avais ouvert sur ce sujet. Edité par Metalion Le 09/10/2018 à 14h29
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)
TurboSEB
Membre non connecté
Conseiller Municipal
Je comprend pas tout, mais j'observe un langage structurer qui peu manifestement être compris avec un peu de connaissances, mais perso,je ne maîtrise déjà pas cela en Basic.
J'ai une question
Quand on parle de routine genre SFX_STOP, cela s'entend par une commande Basic ?
Genre, si Igal voudrait synthétiser son programme de scrolling, ça serait possible de "Routiner" le tout en quelques commande Basic ?
Si ce n'est pas le cas ici est-ce possible ? Edité par TurboSEB Le 09/10/2018 à 20h36
J'ai une question
Quand on parle de routine genre SFX_STOP, cela s'entend par une commande Basic ?
Genre, si Igal voudrait synthétiser son programme de scrolling, ça serait possible de "Routiner" le tout en quelques commande Basic ?
Si ce n'est pas le cas ici est-ce possible ? Edité par TurboSEB Le 09/10/2018 à 20h36
MSX 1&2 + Moniteurs+divers (environ 0.70Tonnes)
TurboSEB :
J'ai une question
Quand on parle de routine genre SFX_STOP, cela s'entend par une commande Basic ?
Quand on parle de routine genre SFX_STOP, cela s'entend par une commande Basic ?
Non, c'est une routine en assembleur, identifiée par son point d'entrée matérialisé par un label SFX_STOP.
En pratique, ailleurs dans le code assembleur, elle pourra être appelé par un "call SFX_STOP"
TurboSEB :
Genre, si Igal voudrait synthétiser son programme de scrolling, ça serait possible de "Routiner" le tout en quelques commande Basic ?
Si ce n'est pas le cas ici est-ce possible ?
Si ce n'est pas le cas ici est-ce possible ?
Oui l'interaction entre le BASIC et l'assembleur est possible.
Soit par un appel USR(x), c'est le plus simple, soit par la définition d'une nouvelle instruction que l'on peut appeler par CALL XXX.
"CALL MUSIC" est en un exemple, lorsque MSX-Music est présent sur un ordinateur.
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)
en assembleur il n'y a pas de lignes numérotées comme sur le basic
donc on marche avec des étiquettes
; SFX_STOP : Arrêt du lecteur [ commentaire car ; devant ]
jp SFX_STOP [ saut a la routine ]
; SFX_STOP : Arrêt du lecteur
;===========================================================
SFX_STOP: [ début routine en LM ]
; toutes les canaux 'off'
ld a,7
ld e,10111111b
call WRTPSG
; mise à zéro du volume canal A
ld a,8
ld e,0
call WRTPSG
; mise à zéro du volume canal B
ld a,9
call WRTPSG
; mise à zéro du volume canal C
ld a,10
jp WRTPSG
donc quand on fait jp SFX_STOP c'est comme un goto en basic
donc on marche avec des étiquettes
; SFX_STOP : Arrêt du lecteur [ commentaire car ; devant ]
jp SFX_STOP [ saut a la routine ]
; SFX_STOP : Arrêt du lecteur
;===========================================================
SFX_STOP: [ début routine en LM ]
; toutes les canaux 'off'
ld a,7
ld e,10111111b
call WRTPSG
; mise à zéro du volume canal A
ld a,8
ld e,0
call WRTPSG
; mise à zéro du volume canal B
ld a,9
call WRTPSG
; mise à zéro du volume canal C
ld a,10
jp WRTPSG
donc quand on fait jp SFX_STOP c'est comme un goto en basic
Visiteur
Vagabond
Message : 0
@TurboSEB
Pour débuter je conseille la lecture de "Assembleur et périphériques des MSX" de Pierre BRANDEIS et Frédéric BLANC Éditions du PSI 1985.
Cet ouvrage contient des explications claires ainsi que des exemples et des exercices. Je pense que c'est un prérequis pour s'y mettre vraiement. Il est disponible dans le village ici.
Pour débuter je conseille la lecture de "Assembleur et périphériques des MSX" de Pierre BRANDEIS et Frédéric BLANC Éditions du PSI 1985.
Cet ouvrage contient des explications claires ainsi que des exemples et des exercices. Je pense que c'est un prérequis pour s'y mettre vraiement. Il est disponible dans le village ici.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie