Prev: AF8F Up: Map Next: AFDC
AF9A: Play Note
Used by the routines at PlayMusicOnce and PlayMusic.
Plays a note of a tune, or a rest. Bits 0 to 5 of the byte are the number of the note (00 is a rest), and bits 6 and 7 are one less than the length of the note in beats. The pitch of each note comes from the table at NoteTable, in which a note has three bytes: the low and high bytes of the length of each half of a pulse, and the number of pulses in a beat.
Input
DE The address of the note
Output
DE The address of the next note
PlayNote AF9A AND %00111111 Keep the number of the note.
AF9C JR Z,PlayRest Play a rest if there is no note.
Look up the delays and the number of cycles in the table at NoteTable.
AF9E LD L,A Set HL to the note number.
AF9F LD H,$00
AFA1 ADD HL,HL Double the number.
AFA2 CALL AddAToHL Add the number again to treble it.
AFA5 LD BC,$AFF2 Point HL at the entry for the note.
AFA8 ADD HL,BC
AFA9 LD B,(HL) Fetch the low byte of the half-period.
AFAA INC HL Move on to the high byte.
AFAB LD C,(HL) Fetch the high byte of the half-period.
AFAC INC HL Move on to the number of pulses in a beat.
AFAD LD L,(HL) Fetch the number of pulses in a beat.
AFAE LD H,$00 Clear H.
Bits 6 and 7 of the note are the length, less one.
AFB0 LD A,(DE) Fetch the note again.
AFB1 RLCA Rotate the length bits into the bottom of the byte.
AFB2 RLCA
AFB3 AND %00000011 Keep them.
AFB5 INC A Add one to get the length in beats.
AFB6 PUSH DE Stash the address of the note on the stack.
AFB7 LD E,L Copy the number of pulses into DE.
AFB8 LD D,H
Multiply the number of cycles by the length of the note.
PlayNote_Multiply AFB9 DEC A Count down the beats.
AFBA JR Z,PlayNote_MultiplyDone Finish multiplying when the beats are used up.
AFBC ADD HL,DE Add the number of pulses for another beat.
AFBD JR PlayNote_Multiply Go back to count the next beat.
The number of cycles now matches the length of the note.
PlayNote_MultiplyDone AFBF POP DE Retrieve the address of the note.
Each pass of this loop makes one cycle of the note, so the length of the note is the number of cycles.
PlayNote_Cycle AFC0 PUSH BC Stash the half-period on the stack.
AFC1 XOR A Clear the speaker bit.
AFC2 OUT ($FE),A Turn the speaker off.
PlayNote_OffDelay AFC4 DJNZ PlayNote_OffDelay Wait for the low half of the pulse.
AFC6 DEC C Count down the high byte of the half-period.
AFC7 JR NZ,PlayNote_OffDelay Loop back until the low half is over.
AFC9 POP BC Retrieve the half-period.
AFCA PUSH BC Stash the half-period on the stack again.
AFCB LD A,$10 Set the speaker bit.
AFCD OUT ($FE),A Turn the speaker on.
PlayNote_OnDelay AFCF DJNZ PlayNote_OnDelay Wait for the high half of the pulse.
AFD1 DEC C Count down the high byte of the half-period.
AFD2 JR NZ,PlayNote_OnDelay Loop back until the high half is over.
AFD4 POP BC Retrieve the half-period.
AFD5 DEC HL Count down the pulses.
AFD6 LD A,H Jump to PlayNote_Cycle if any pulses are left.
AFD7 OR L
AFD8 JR NZ,PlayNote_Cycle
AFDA INC DE Move on to the next note.
AFDB RET Return.
Prev: AF8F Up: Map Next: AFDC