![]() |
Routines |
| Prev: AF8F | Up: Map | Next: AFDC |
|
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.
|
||||||||||||
| 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. | ||||||||||
|
View the equivalent code in;
|
||||||||||||
| Prev: AF8F | Up: Map | Next: AFDC |