SGDK
A free and open development kit for the Sega Mega Drive
Loading...
Searching...
No Matches
xgm.h File Reference

XGM sound driver. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SND_isPlaying_XGM()
 
#define SND_startPlay_XGM(song)
 
#define SND_stopPlay_XGM()
 
#define SND_pausePlay_XGM()
 
#define SND_resumePlay_XGM()
 
#define SND_isPlayingPCM_XGM(channel_mask)
 
#define SND_setPCM_XGM(id, sample, len)
 
#define SND_setPCMFast_XGM(id, sample, len)
 
#define SND_startPlayPCM_XGM(id, prio, ch)
 
#define SND_stopPlayPCM_XGM(channel)
 
#define SND_getMusicTempo_XGM()
 
#define SND_setMusicTempo_XGM(value)
 
#define SND_getManualSync_XGM()
 
#define SND_setManualSync_XGM()
 
#define SND_nextFrame_XGM()
 
#define SND_nextXFrame_XGM(num)
 
#define SND_setLoopNumber_XGM(value)
 
#define SND_set68KBUSProtection_XGM(value)
 
#define SND_getForceDelayDMA_XGM()
 
#define SND_setForceDelayDMA_XGM(value)
 
#define SND_getCPULoad_XGM()
 
#define XGM_nextFrame()
 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).

Macro Definition Documentation

◆ SND_getCPULoad_XGM

#define SND_getCPULoad_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_getCPULoad() instead.\"")

◆ SND_getForceDelayDMA_XGM

#define SND_getForceDelayDMA_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_getForceDelayDMA() instead.\"")

◆ SND_getManualSync_XGM

#define SND_getManualSync_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_getManualSync() instead.\"")

◆ SND_getMusicTempo_XGM

#define SND_getMusicTempo_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_getMusicTempo() instead.\"")

◆ SND_isPlaying_XGM

#define SND_isPlaying_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_isPlaying() instead.\"")

◆ SND_isPlayingPCM_XGM

#define SND_isPlayingPCM_XGM ( channel_mask)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_isPlayingPCM(..) instead.\"")

◆ SND_nextFrame_XGM

#define SND_nextFrame_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_nextFrame() instead.\"")

◆ SND_nextXFrame_XGM

#define SND_nextXFrame_XGM ( num)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_nextXFrame(..) instead.\"")

◆ SND_pausePlay_XGM

#define SND_pausePlay_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_pausePlay() instead.\"")

◆ SND_resumePlay_XGM

#define SND_resumePlay_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_resumePlay() instead.\"")

◆ SND_set68KBUSProtection_XGM

#define SND_set68KBUSProtection_XGM ( value)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_set68KBUSProtection(..) instead.\"")

◆ SND_setForceDelayDMA_XGM

#define SND_setForceDelayDMA_XGM ( value)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setForceDelayDMA(..) instead.\"")

◆ SND_setLoopNumber_XGM

#define SND_setLoopNumber_XGM ( value)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setLoopNumber(..) instead.\"")

◆ SND_setManualSync_XGM

#define SND_setManualSync_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setManualSync() instead.\"")

◆ SND_setMusicTempo_XGM

#define SND_setMusicTempo_XGM ( value)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setMusicTempo(..) instead.\"")

◆ SND_setPCM_XGM

#define SND_setPCM_XGM ( id,
sample,
len )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setPCM(..) instead.\"")

◆ SND_setPCMFast_XGM

#define SND_setPCMFast_XGM ( id,
sample,
len )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_setPCMFast(..) instead.\"")

◆ SND_startPlay_XGM

#define SND_startPlay_XGM ( song)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_startPlay(..) instead.\"")

◆ SND_startPlayPCM_XGM

#define SND_startPlayPCM_XGM ( id,
prio,
ch )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_startPlayPCM(..) instead.\"")

◆ SND_stopPlay_XGM

#define SND_stopPlay_XGM ( )
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_stopPlay() instead.\"")

◆ SND_stopPlayPCM_XGM

#define SND_stopPlayPCM_XGM ( channel)
Value:
_Pragma("GCC error \"This method is deprecated, use XGM_stopPlayPCM(..) instead.\"")

◆ XGM_nextFrame

#define XGM_nextFrame ( )
Value:
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

◆ XGM_getElapsed()

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()

◆ XGM_getForceDelayDMA()

bool XGM_getForceDelayDMA ( void )

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

See also
XGM_setForceDelayDMA()

◆ XGM_getManualSync()

u16 XGM_getManualSync ( void )

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

See also
XGM_setManualSync(void)

◆ XGM_getMusicTempo()

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(..)

◆ XGM_isPlayingPCM()

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.

◆ XGM_loadDriver()

void XGM_loadDriver ( const bool waitReady)

Load the XGM sound driver.

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

◆ XGM_nextXFrame()

void XGM_nextXFrame ( const u16 num)

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

See also
XGM_nextFrame(..)

◆ XGM_pausePlay()

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

◆ XGM_resumePlay()

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

◆ XGM_set68KBUSProtection()

void XGM_set68KBUSProtection ( const bool value)

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

See also
XGM_setForceDelayDMA(..)

◆ XGM_setManualSync()

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)

◆ XGM_setMusicTempo()

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)

◆ XGM_setPCM()

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

◆ XGM_setPCMFast()

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

◆ XGM_startPlay()

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

◆ 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

◆ XGM_startPlayPCM()

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

◆ XGM_stopPlay()

void XGM_stopPlay ( void )

Stop playing music (XGM music player driver).

See also
XGM_pausePlay

◆ XGM_stopPlayPCM()

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

◆ XGM_unloadDriver()

void XGM_unloadDriver ( void )

Unload the XGM sound driver.

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