sgdk
xgm.h File Reference

XGM sound driver. More...

Go to the source code of this file.

Defines

#define SND_isPlaying_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_isPlaying() instead.\"")
#define SND_startPlay_XGM(song)   _Pragma("GCC error \"This method is deprecated, use XGM_startPlay(..) instead.\"")
#define SND_stopPlay_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_stopPlay() instead.\"")
#define SND_pausePlay_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_pausePlay() instead.\"")
#define SND_resumePlay_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_resumePlay() instead.\"")
#define SND_isPlayingPCM_XGM(channel_mask)   _Pragma("GCC error \"This method is deprecated, use XGM_isPlayingPCM(..) instead.\"")
#define SND_setPCM_XGM(id, sample, len)   _Pragma("GCC error \"This method is deprecated, use XGM_setPCM(..) instead.\"")
#define SND_setPCMFast_XGM(id, sample, len)   _Pragma("GCC error \"This method is deprecated, use XGM_setPCMFast(..) instead.\"")
#define SND_startPlayPCM_XGM(id, prio, ch)   _Pragma("GCC error \"This method is deprecated, use XGM_startPlayPCM(..) instead.\"")
#define SND_stopPlayPCM_XGM(channel)   _Pragma("GCC error \"This method is deprecated, use XGM_stopPlayPCM(..) instead.\"")
#define SND_getMusicTempo_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_getMusicTempo() instead.\"")
#define SND_setMusicTempo_XGM(value)   _Pragma("GCC error \"This method is deprecated, use XGM_setMusicTempo(..) instead.\"")
#define SND_getManualSync_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_getManualSync() instead.\"")
#define SND_setManualSync_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_setManualSync() instead.\"")
#define SND_nextFrame_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_nextFrame() instead.\"")
#define SND_nextXFrame_XGM(num)   _Pragma("GCC error \"This method is deprecated, use XGM_nextXFrame(..) instead.\"")
#define SND_setLoopNumber_XGM(value)   _Pragma("GCC error \"This method is deprecated, use XGM_setLoopNumber(..) instead.\"")
#define SND_set68KBUSProtection_XGM(value)   _Pragma("GCC error \"This method is deprecated, use XGM_set68KBUSProtection(..) instead.\"")
#define SND_getForceDelayDMA_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_getForceDelayDMA() instead.\"")
#define SND_setForceDelayDMA_XGM(value)   _Pragma("GCC error \"This method is deprecated, use XGM_setForceDelayDMA(..) instead.\"")
#define SND_getCPULoad_XGM()   _Pragma("GCC error \"This method is deprecated, use XGM_getCPULoad() instead.\"")
#define XGM_nextFrame()   XGM_nextXFrame(1)
 Notify the Z80 a new frame just happened (XGM music player driver).

Functions

void XGM_loadDriver (const bool waitReady)
 Load the XGM sound driver.
void XGM_unloadDriver (void)
 Unload the XGM sound driver.
bool XGM_isPlaying (void)
 Returns play music state (XGM music player driver).
void XGM_startPlay (const u8 *song)
 Start playing the specified XGM track (XGM music player driver).
void XGM_startPlay_FAR (const u8 *song, u32 size)
 Same as XGM_startPlay(..) except it supports music accessible through bank switch.
void XGM_stopPlay (void)
 Stop playing music (XGM music player driver).
void XGM_pausePlay (void)
 Pause playing music, music can be resumed by calling XGM_resumePlay (XGM music player driver).
Note that due to the nature of the music chip (FM synthesis), resume play operation will never be perfect and some notes will miss until next key-on event occurs.
void XGM_resumePlay (void)
 Resume playing music after pausing with XGM_pausePlay (XGM music player driver).
Note that due to the nature of the music chip (FM synthesis), resume play operation will never be perfect and some notes will miss until next key-on event occurs.
u8 XGM_isPlayingPCM (const u16 channel_mask)
 Return play status of specified PCM channel (XGM music player driver).
void XGM_setPCM (const u8 id, const u8 *sample, const u32 len)
 Declare a new PCM sample (maximum = 255) for the XGM music player driver.
Sample id < 64 are reserved for music while others are used for SFX so if you want to declare a new SFX PCM sample use an id >= 64.
void XGM_setPCMFast (const u8 id, const u8 *sample, const u32 len)
 Same as XGM_setPCM but fast version.
This method assume that XGM driver is loaded and that 68000 has access to Z80 bus.
void XGM_setPCM_FAR (const u8 id, const u8 *sample, const u32 len)
 Same as XGM_setPCM(..) allowing PCM access through bank switch.
void XGM_setPCMFast_FAR (const u8 id, const u8 *sample, const u32 len)
 Same as XGM_setPCMFast(..) allowing PCM access through bank switch.
void XGM_startPlayPCM (const u8 id, const u8 priority, const SoundPCMChannel channel)
 Play a PCM sample on specified channel (XGM music player driver).
If a sample was currently playing on this channel then priority of the newer sample should be are compared then it's stopped and the new sample is played instead.
Note that music may use the first PCM channel so it's better to use channel 2 to 4 for SFX.
void XGM_stopPlayPCM (const SoundPCMChannel channel)
 Stop play PCM on specified channel (XGM music player driver).
No effect if no sample was currently playing on this channel.
u32 XGM_getElapsed (void)
 Return the elapsed play time since the last XGM_startPlay(..) call.
The returned value is in music frame which can be 50/60 per second depending the base music play rate (NTSC/PAL).
u16 XGM_getMusicTempo (void)
 Get the current music tempo (in tick per second).
Default value is 60 or 50 depending the system is NTSC or PAL.
This method is meaningful only if you use the automatic music sync mode (see XGM_setManualSync() method) which is the default mode.
Note that using specific tempo (not 60 or 50) will affect performance of DMA contention and external command parsing so it's recommended to stand with default one.
void XGM_setMusicTempo (const u16 value)
 Set the music tempo (in tick per second).
Default value is 60 or 50 depending the system is NTSC or PAL. This method is meaningful only if you use the automatic music sync mode (see XGM_setManualSync() method) which is the default mode.
Note that using specific tempo (not 60 or 50) can completely distord FM instruments sound and affect performance of DMA contention and external command parsing so it's recommended to stand with default one.
u16 XGM_getManualSync (void)
 Returns manual sync mode state of XGM driver (by default auto sync is used).
void XGM_setManualSync (const bool value)
 Set manual sync mode of XGM driver (by default auto sync is used).
void XGM_nextXFrame (const u16 num)
 Same as XGM_nextFrame() except you can specify the numer of frame.
void XGM_setLoopNumber (const s8 value)
 Set the loop number for music with loop command.
Default value is -1 for pseudo unfinite (255) loops plays. A value of 0 means single play without any loop, 1 = single play + 1 loop...
void XGM_set68KBUSProtection (const bool value)
 Same as Z80_setBusProtection(..) (generic version of the method)
bool XGM_getForceDelayDMA (void)
 Same as Z80_getForceDelayDMA() (generic version of the method)
void XGM_setForceDelayDMA (const bool value)
 Same as Z80_setForceDelayDMA(..) (generic version of the method)
u32 XGM_getCPULoad (void)
 Returns an estimation of the Z80 CPU load (XGM driver).
The low 16 bits returns the estimated Z80 CPU load where the high 16 bits returns the part spent waiting in the DMA contention (see XGM_set68KBUSProtection method).
The method computes CPU load mean over 32 frames and so it's important to call it at each frame (on VInt for instance) to get meaningful value.
Note that it returns CPU load only for the XGM music parsing part as PCM channel mixing is always ON.
Idle usage is 40% on NTSC and 30% on PAL, 100% usage usually mean overrun and may result in music slowdown and incorrect PCM operations.

Detailed Description

XGM sound driver.

Author:
Stephane Dallongeville
Date:
08/2015

This unit provides methods to use the XGM (eXtended Genesis Music) sound driver.
This driver takes VGM (or XGM) file as input to play music.
It supports 4 PCM channels at a fixed 14 Khz and allows to play SFX through PCM with 16 level of priority.
The driver is designed to avoid DMA contention when possible (depending CPU load).


Define Documentation

#define SND_getCPULoad_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_getCPULoad() instead.\"")
Deprecated:
use XGM_getCPULoad(..) instead
#define SND_getForceDelayDMA_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_getForceDelayDMA() instead.\"")
Deprecated:
use XGM_getForceDelayDMA(..) instead
#define SND_getManualSync_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_getManualSync() instead.\"")
Deprecated:
use XGM_getManualSync(..) instead
#define SND_getMusicTempo_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_getMusicTempo() instead.\"")
Deprecated:
use XGM_getMusicTempo(..) instead
#define SND_isPlaying_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_isPlaying() instead.\"")
#define SND_isPlayingPCM_XGM (   channel_mask)    _Pragma("GCC error \"This method is deprecated, use XGM_isPlayingPCM(..) instead.\"")
Deprecated:
use XGM_isPlayingPCM(..) instead
#define SND_nextFrame_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_nextFrame() instead.\"")
Deprecated:
use XGM_nextFrame(..) instead
#define SND_nextXFrame_XGM (   num)    _Pragma("GCC error \"This method is deprecated, use XGM_nextXFrame(..) instead.\"")
Deprecated:
use XGM_nextXFrame(..) instead
#define SND_pausePlay_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_pausePlay() instead.\"")
Deprecated:
use XGM_pausePlay(..) instead
#define SND_resumePlay_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_resumePlay() instead.\"")
Deprecated:
use XGM_resumePlay(..) instead
#define SND_set68KBUSProtection_XGM (   value)    _Pragma("GCC error \"This method is deprecated, use XGM_set68KBUSProtection(..) instead.\"")
Deprecated:
use XGM_set68KBUSProtection(..) instead
#define SND_setForceDelayDMA_XGM (   value)    _Pragma("GCC error \"This method is deprecated, use XGM_setForceDelayDMA(..) instead.\"")
Deprecated:
use XGM_setForceDelayDMA(..) instead
#define SND_setLoopNumber_XGM (   value)    _Pragma("GCC error \"This method is deprecated, use XGM_setLoopNumber(..) instead.\"")
Deprecated:
use XGM_setLoopNumber(..) instead
#define SND_setManualSync_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_setManualSync() instead.\"")
Deprecated:
use XGM_setManualSync(..) instead
#define SND_setMusicTempo_XGM (   value)    _Pragma("GCC error \"This method is deprecated, use XGM_setMusicTempo(..) instead.\"")
Deprecated:
use XGM_setMusicTempo(..) instead
#define SND_setPCM_XGM (   id,
  sample,
  len 
)    _Pragma("GCC error \"This method is deprecated, use XGM_setPCM(..) instead.\"")
Deprecated:
use XGM_setPCM(..) instead
#define SND_setPCMFast_XGM (   id,
  sample,
  len 
)    _Pragma("GCC error \"This method is deprecated, use XGM_setPCMFast(..) instead.\"")
Deprecated:
use XGM_setPCMFast(..) instead
#define SND_startPlay_XGM (   song)    _Pragma("GCC error \"This method is deprecated, use XGM_startPlay(..) instead.\"")
Deprecated:
use XGM_startPlay(..) instead
#define SND_startPlayPCM_XGM (   id,
  prio,
  ch 
)    _Pragma("GCC error \"This method is deprecated, use XGM_startPlayPCM(..) instead.\"")
Deprecated:
use XGM_startPlayPCM(..) instead
#define SND_stopPlay_XGM ( )    _Pragma("GCC error \"This method is deprecated, use XGM_stopPlay() instead.\"")
Deprecated:
use XGM_stopPlay(..) instead
#define SND_stopPlayPCM_XGM (   channel)    _Pragma("GCC error \"This method is deprecated, use XGM_stopPlayPCM(..) instead.\"")
Deprecated:
use XGM_stopPlayPCM(..) instead
#define XGM_nextFrame ( )    XGM_nextXFrame(1)

Notify the Z80 a new frame just happened (XGM music player driver).

Sound synchronization was initially 100% done by Z80 itself using the V-Interrupt but if the Z80 is stopped right at V-Int time (bus request from 68000 or DMA stall) then the V-Int can be missed by the Z80 and music timing affected.
To fix that issue and also to offer more flexibility the music timing should now be handled by the 68k.
By default this method is called automatically by SGDK at V-Int time but you can decide to handle sync manually (see XGM_setManualSync(..) method).
When you are in manual sync you normally should call this method once per frame (in the V-Int callback for instance) but you are free to play with it to increase or decrease music tempo.
Note that it's better to call this method a bit before (3/4 scanlines should be fine) doing DMA operation for best main bus contention protection (see XGM_set68KBUSProtection() and XGM_setForceDelayDMA() methods).

See also:
XGM_setManualSync(..)
XGM_nextXFrame(..)
XGM_set68KBUSProtection(..)
XGM_setForceDelayDMA(..)

Function Documentation

u32 XGM_getElapsed ( void  )

Return the elapsed play time since the last XGM_startPlay(..) call.
The returned value is in music frame which can be 50/60 per second depending the base music play rate (NTSC/PAL).

See also:
XGM_startPlay(..)
XGM_setMusicTempo()
bool XGM_getForceDelayDMA ( void  )

Same as Z80_getForceDelayDMA() (generic version of the method)

See also:
XGM_setForceDelayDMA()
u16 XGM_getManualSync ( void  )

Returns manual sync mode state of XGM driver (by default auto sync is used).

See also:
XGM_setManualSync(void)
u16 XGM_getMusicTempo ( void  )

Get the current music tempo (in tick per second).
Default value is 60 or 50 depending the system is NTSC or PAL.
This method is meaningful only if you use the automatic music sync mode (see XGM_setManualSync() method) which is the default mode.
Note that using specific tempo (not 60 or 50) will affect performance of DMA contention and external command parsing so it's recommended to stand with default one.

See also:
XGM_setManualSync(..)
XGM_setMusicTempo(..)
u8 XGM_isPlayingPCM ( const u16  channel_mask)

Return play status of specified PCM channel (XGM music player driver).

Parameters:
channel_maskChannel(s) we want to retrieve play state.
SOUND_PCM_CH1_MSK = channel 1
SOUND_PCM_CH2_MSK = channel 2
SOUND_PCM_CH3_MSK = channel 3
SOUND_PCM_CH4_MSK = channel 4

You can combine mask to retrieve state of severals channels at once:
XGM_isPlayingPCM(SOUND_PCM_CH1_MSK | SOUND_PCM_CH2_MSK)
will actually return play state for channel 1 and channel 2.
Returns:
Return the channel mask of current playing channel(s).
For instance it returns (SOUND_PCM_CH1_MSK | SOUND_PCM_CH3_MSK) if channels 1 and 3 are currently playing.
void XGM_loadDriver ( const bool  waitReady)

Load the XGM sound driver.

Don't use this method directly, use Z80_loadDriver(..) instead.

void XGM_nextXFrame ( const u16  num)

Same as XGM_nextFrame() except you can specify the numer of frame.

See also:
XGM_nextFrame(..)
void XGM_pausePlay ( void  )

Pause playing music, music can be resumed by calling XGM_resumePlay (XGM music player driver).
Note that due to the nature of the music chip (FM synthesis), resume play operation will never be perfect and some notes will miss until next key-on event occurs.

See also:
XGM_resumePlay
XGM_stopPlay
void XGM_resumePlay ( void  )

Resume playing music after pausing with XGM_pausePlay (XGM music player driver).
Note that due to the nature of the music chip (FM synthesis), resume play operation will never be perfect and some notes will miss until next key-on event occurs.

See also:
XGM_pausePlay
XGM_nextFrame
void XGM_set68KBUSProtection ( const bool  value)

Same as Z80_setBusProtection(..) (generic version of the method)

See also:
XGM_setForceDelayDMA(..)
void XGM_setManualSync ( const bool  value)

Set manual sync mode of XGM driver (by default auto sync is used).

Parameters:
valueTRUE or FALSE
See also:
XGM_getManualSync(void)
XGM_nextFrame(void)
void XGM_setMusicTempo ( const u16  value)

Set the music tempo (in tick per second).
Default value is 60 or 50 depending the system is NTSC or PAL. This method is meaningful only if you use the automatic music sync mode (see XGM_setManualSync() method) which is the default mode.
Note that using specific tempo (not 60 or 50) can completely distord FM instruments sound and affect performance of DMA contention and external command parsing so it's recommended to stand with default one.

See also:
XGM_setManualSync(..)
XGM_getMusicTempo(void)
void XGM_setPCM ( const u8  id,
const u8 sample,
const u32  len 
)

Declare a new PCM sample (maximum = 255) for the XGM music player driver.
Sample id < 64 are reserved for music while others are used for SFX so if you want to declare a new SFX PCM sample use an id >= 64.

Parameters:
idSample id:
value 0 is not allowed
values from 1 to 63 are used for music values from 64 to 255 are used for SFX
sampleSample address, should be 256 bytes boundary aligned
SGDK automatically align sample resource as needed
lenSize of sample in bytes, should be a multiple of 256
SGDK automatically adjust resource size as needed
void XGM_setPCMFast ( const u8  id,
const u8 sample,
const u32  len 
)

Same as XGM_setPCM but fast version.
This method assume that XGM driver is loaded and that 68000 has access to Z80 bus.

Parameters:
idSample id:
value 0 is not allowed
values from 1 to 63 are used for music values from 64 to 255 are used for SFX
sampleSample address, should be 256 bytes boundary aligned
SGDK automatically align sample resource as needed
lenSize of sample in bytes, should be a multiple of 256
SGDK automatically adjust resource size as needed
void XGM_startPlay ( const u8 song)

Start playing the specified XGM track (XGM music player driver).

Parameters:
songXGM track address.
See also:
XGM_stopPlay
XGM_pausePlay
XGM_nextFrame
XGM_startPlay_FAR
void XGM_startPlay_FAR ( const u8 song,
u32  size 
)

Same as XGM_startPlay(..) except it supports music accessible through bank switch.

Parameters:
songXGM track address.
sizeXGM track size (in byte)
See also:
XGM_startPlay
XGM_stopPlay
XGM_pausePlay
XGM_nextFrame
void XGM_startPlayPCM ( const u8  id,
const u8  priority,
const SoundPCMChannel  channel 
)

Play a PCM sample on specified channel (XGM music player driver).
If a sample was currently playing on this channel then priority of the newer sample should be are compared then it's stopped and the new sample is played instead.
Note that music may use the first PCM channel so it's better to use channel 2 to 4 for SFX.

Parameters:
idSample id (use XGM_setPCM(..) method first to set id)
priorityValue should go from 0 to 15 where 0 is lowest priority and 15 the highest one.
If the channel was already playing the priority is used to determine if the new SFX should replace the current one (new priority >= old priority).
channelChannel where we want to play sample, accepted values are:
SOUND_PCM_CH1 = channel 1 (usually used by music)
SOUND_PCM_CH2 = channel 2
SOUND_PCM_CH3 = channel 3
SOUND_PCM_CH4 = channel 4
void XGM_stopPlay ( void  )

Stop playing music (XGM music player driver).

See also:
XGM_pausePlay
void XGM_stopPlayPCM ( const SoundPCMChannel  channel)

Stop play PCM on specified channel (XGM music player driver).
No effect if no sample was currently playing on this channel.

Parameters:
channelChannel we want to stop, accepted values are:
SOUND_PCM_CH1 = channel 1
SOUND_PCM_CH2 = channel 2
SOUND_PCM_CH3 = channel 3
SOUND_PCM_CH4 = channel 4
void XGM_unloadDriver ( void  )

Unload the XGM sound driver.

Don't use this method directly, use Z80_unloadDriver(..) instead.

 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines