©2000-2001 Aleksi Eeben (email: aleksi@cncd.fi)
http://www.cncd.fi/aeeben
Carillon Player Routines
Fade In/Fade Out
Player Variables in Work RAM
Using Your Own Sound FX Routines
Note that any registers may change during any of these calls. If you are using interrupts don't forget to store all the registers. Also be sure to use proper banking!
Player_Initialize |
Initializes hardware sound registers and player variables at $c7c0-$c7ef. Call this at program startup before using any other Carillon Player or FX Hammer routines. Example: ld a,MusicBank ;
Any of the Music Banks This routine is not needed at later time except for that if you need to disable all the sound circuits (by writing $00 to rNR52) for example during pause mode. |
Player_MusicStart |
Starts playing song number 0. Call Player_SongSelect right after this call to select another song. Example: ld a,MusicBank |
Player_MusicStop |
Stops playing the current song. Any sound FX currently playing are not affected. Example: ld a,[CurrentMusicBank] Note: Calling this routine is not necessary when switching to a different song or Music Bank. |
Player_SongSelect |
Call this to select a song other than song number zero. Load register A with song number (0 - 7). Always call Player_MusicStart before calling this routine. Example: ld a,MusicBank |
Player_MusicUpdate |
This must be called once every frame to keep the music playing. (After all your VBlank routines is usually fine.) Example: ld a,[CurrentMusicBank] The routine takes only 0 - 3 LCD lines of raster time (Less than 2% CPU usage). |
Player_SampleUpdate |
If the song is using samples (ie. there is a sample bank for that song) you must call this routine four times every frame. For example at LCD lines $10, $36, $5d and $83. This way no VBlank time is wasted ever. Example: ld a,[CurrentSampleBank] ;
Get active Sample Bank number Each call takes less than 1 LCD line of raster time. The most working solution for timing is to use a series of LYC-interrupts. You can also use a simple LCD line wait if that works with the program (maybe for title and menu screens). |
SoundFX_Trig |
Call this to start playing a sound FX. Load register A with sound FX number (0 - 59). This can be done at any point in your game program. Example: ld a,SoundFXBank |
SoundFX_Stop |
Call this if you need to stop a sound FX currently playing. Remember that calling Player_MusicStop doesn't affect sound FX. Example: ld a,SoundFXBank |
SoundFX_Update |
This must be called once every frame to keep the sound FX playing. Right after Player_MusicUpdate is fine. Example: ld a,SoundFXBank The routine takes less than 1 LCD line of raster time. |
Important note: If you cannot (for any reason) call Player_MusicUpdate and SoundFX_Update once every frame you should turn off the music and sound FX during that period to avoid any unwanted bleeps.
Carillon sets the master volume register (rNR50) to maximum ($77) in Player_Initialize but doesn't change that value afterwards. You can use this register for fading sound ($77, $66, $55, $44, $33, $22, $11, $00 at desired rate, then call Player_MusicStop and SoundFX_Stop). Do not forget to restore the maximum level ($77) before starting another song or trigging sound FX.
$c7c0 |
MusicFlag |
New music note data is read at the current tempo (Speed) when MusicFlag
= $00. MusicFlag is set to $01 when the end of music data is reached (Some channels may still be active). |
$c7c1 |
Speed |
Current Tempo Default = $07, changed using command TMPx in block data. |
$c7c2 |
StepP |
Step time counter Starts at value in Speed, decremented by one every frame. One step is advanced when StepP = Speed/2 or StepP = $00. |
$c7c3 |
PatternP |
Current step (n * $08) |
$c7c4 |
PatternH |
Current block (block number + $50) |
$c7c5
|
SequencerP
|
Current position in Block Order List In Player_MusicSelect SequencerP is set to (actual song starting position - 1) and PatternP is set to $00. |
$c7c6
|
Ch1Flags |
Bit 1: Ch1 reserved for sound FX routines (1 = yes, 0 = no) When Ch1Flags is not $00, no instrument sound data is read and all Ch1 sound registers (rNR1x) remain intact. |
$c7c7 |
Ch1Count |
Countdown (in frames) before moving to next step in sound data |
$c7c8 |
Ch1SndP |
High nybble: CH1-2 Sound number |
$c7c9 |
Ch1Note |
Current Ch1 Note (before arpeggiato) |
$c7ca |
Ch1FreqL |
Ch1 Frequency Low-order byte (before modulation/slide) |
$c7cb |
Ch1FreqH |
Ch1 Frequency High-order byte (before modulation/slide) |
$c7cc
|
Ch2Flags
|
Bit 1: Ch2 reserved for sound FX routines (1 = yes, 0 = no) When Ch2Flags is not $00, no instrument sound data is read and all Ch2 sound registers (rNR2x) remain intact. |
$c7cd |
Ch2Count |
Countdown (in frames) before moving to next step in sound data |
$c7ce |
Ch2SndP |
High nybble: CH1-2 Sound number |
$c7cf |
Ch2Note |
Current Ch2 Note (before arpeggiato) |
$c7d0 |
Ch2FreqL |
Ch2 Frequency Low-order byte (before modulation/slide) |
$c7d1 |
Ch2FreqH |
Ch2 Frequency High-order byte (before modulation/slide) |
$c7d2
|
Ch3Flags
|
Bit 2: Ch3 reserved for playing a sample trigged in music data (1 = yes,
0 = no) When Ch3Flags is not $00, no instrument sound data is read and all Ch3 sound registers (rNR3x) remain intact. |
$c7d3 |
Ch3Count |
Countdown (in frames) before moving to next step in sound data |
$c7d4 |
Ch3Wave |
Current Waveform (n * $10) in Waveform RAM |
$c7d5 |
Ch3SndP |
High nybble: WAV3 Sound number |
$c7d6 |
Ch3Note |
Current Ch3 Note (before arpeggiato) |
$c7d7 |
Ch3FreqL |
Ch3 Frequency Low-order byte (before modulation/slide) |
$c7d8 |
Ch3FreqH |
Ch3 Frequency High-order byte (before modulation/slide) |
$c7d9 |
Ch4Flags |
Bit 1: Ch4 reserved for sound FX routines (1 = yes, 0 = no) When Ch4Flags is not $00, no instrument sound data is read and all Ch4 sound registers (rNR4x) remain intact. |
$c7da |
Ch4Count |
Countdown (in frames) before moving to next step in sound data |
$c7db |
Ch4SndP |
High nybble: PRC4 Sound number |
$c7dc |
Ch3Init |
Internally set when Waveform RAM is reloaded |
$c7dd |
Modulate |
Bit 7: Vibrato/Slide |
$c7de |
VibratoP |
Vibrato Phase (and Width) |
$c7df |
VibSpeed |
Vibrato Speed |
$c7e0 |
ModLAdd |
Slide Add Low-order byte |
$c7e1 |
ModL |
Current Slide Amount Low-order byte |
$c7e2 |
ModHAdd |
Slide Add High-order byte |
$c7e3 |
ModH |
Current Slide Amount High-order byte |
$c7e4 |
SampleL |
Sample address Low-order byte |
$c7e5 |
SampleH |
Sample address High-order byte |
$c7e6 |
SamCount |
Sample blocks left to play |
$c7e7 |
TrigCount |
Used for timing |
$c7e8 |
NewPanMask |
Pan position for trigged sample |
$c7e9 |
NewSampleL |
Temporary storage for trigging sample |
$c7ea |
NewSampleH |
Temporary storage for trigging sample |
$c7eb |
NewSamCount |
Sample length in blocks |
$c7ec |
FXCurrentPri |
FX Hammer: Priority of current Sound FX playing ($00 = lowest) |
$c7ed |
FXSoundCount |
FX Hammer: Countdown (in frames) before moving to next step in Sound FX |
$c7ee |
FXSoundP |
FX Hammer: Current Step |
$c7ef |
FXSoundH |
FX Hammer: Current Sound FX (FX number + $44) |
Before using your own routines to play a sound FX you must first reserve the corresponding channel or channels:
Reserving Channel 1 - Write $03 to Ch1Flags ($c7c6) |
Reserving Channel 2 - Write $03 to Ch2Flags ($c7cc) |
Reserving Channel 3* - Write $03 to Ch3Flags - If using samples in the music, write $00 to both TrigCount ($c7e7) and SamCount ($c7e6) - Note that Waveform RAM may contain any waveform (or if using samples even some "random" buzz), so you must immediately reload the Waveform RAM |
Reserving Channel 4 - Write $03 to Ch4Flags ($c7d9) |
Since the sound registers may contain any values at this time, you should start playing the sound FX immediately.
* Important note on Channel 3 usage: If using samples in the music (Sample Player add-on), you must skip all Sample_Update calls while playing a sound FX on Channel 3.
After your sound FX is finished the used channels must be released:
Releasing Channel 1 - Write $00 to rNR10 (FX might have used the Ch1 slide function) - Write $08 to rNR12, then write $80 to rNR14 (Cuts any FX tail) - Write $01 to Ch1Flags ($c7c6) |
Releasing Channel 2 - Write $08 to rNR22, then write $80 to rNR14 (Cuts any FX tail) - Write $01 to Ch2Flags ($c7cc) |
Releasing Channel 3* - Write $00 to rNR32 (Cuts any FX tail) - Write $ff to Ch3Wave ($c7d4) to make sure the Waveform RAM is reloaded by the music player - If using samples in the music, again write $00 to both TrigCount ($c7e7) and SamCount ($c7e6) - Write $01 to Ch3Flags |
Releasing Channel 4 - Write $08 to rNR42, then write $80 to NR44 (Cuts any FX tail) - Write $01 to Ch4Flags ($c7d9) |
Note: If using FX Hammer you shouldn't use channels 2 and 4 in your own sound FX routines.