
#ifndef MIKMOD_H
#define MIKMOD_H

#include "mmio.h"

#ifdef __cplusplus
extern "C" {
#endif


#define MUTE_EXCLUSIVE  32000
#define MUTE_INCLUSIVE  32001

#define SFX_CRITICAL  1



/**************************************************************************
****** Unitrack stuff: ****************************************************
**************************************************************************/

// prototypes:

extern void    UniSetRow(UBYTE *t);
extern UBYTE   UniGetByte(void);
extern UBYTE  *UniFindRow(UBYTE *t,UWORD row);
extern void    UniReset(void);
extern void    UniWrite(UBYTE data);
extern void    UniNewline(void);
extern UBYTE  *UniDup(void);
extern void    UniSkipOpcode(UBYTE op);
extern BOOL    UniInit(void);
extern void    UniCleanup(void);
extern UWORD   TrkLen(UBYTE *t);
extern BOOL    MyCmp(UBYTE *a,UBYTE *b,UWORD l);


/**************************************************************************
****** mikmod types: ******************************************************
**************************************************************************/

// Sample format flags:
#define SF_16BITS       1
#define SF_SIGNED       2
#define SF_DELTA        4
#define SF_BIG_ENDIAN   8
#define SF_LOOP         16
#define SF_BIDI         32
#define SF_SUSTAIN      64
#define SF_OWNPAN       128
#define SF_REVERSE      256

typedef struct SAMPLE
{   ULONG  c2spd;            // finetune frequency
    UBYTE  divfactor;        // for sample scaling (maintains proper period slides)
    UBYTE  volume;           // volume 0-64
    UBYTE  globvol;          // global volume
    UBYTE  panning;          // panning
    ULONG  length;           // length of sample (in samples!)
    ULONG  loopstart;        // repeat position (relative to start, in samples)
    ULONG  loopend;          // repeat end
    ULONG  susbegin;         // sustain loop begin (in samples)
    ULONG  susend;           // sustain loop end

    UBYTE  vibflags;         // autovibrato flag stuffs
    UBYTE  vibtype;          // Vibratos moved from INSTRUMENT to SAMPLE
    UBYTE  vibsweep;
    UBYTE  vibdepth;
    UBYTE  vibrate;
    UWORD  avibpos;          // autovibrato pos

    UWORD  flags;            // sample format in memory
    ULONG  seekpos;          // seek position in file
    CHAR   *samplename;      // name of the sample
    SWORD  handle;           // sample handle
} SAMPLE;



// --> Struct : SAMPLOAD
// This is a handle of sorts attached to any sample registered with
// SL_RegisterSample.  Generally, this only need be used or changed by the
// loaders and drivers of mikmod.

#define SL_16BITS       1
#define SL_SIGNED       2
#define SL_DELTA        4
#define SL_BIG_ENDIAN   8

typedef struct SAMPLOAD
{   struct SAMPLOAD *next;

    ULONG  length;           // length of sample (in samples!)
    ULONG  loopstart;        // repeat position (relative to start, in samples)
    ULONG  loopend;          // repeat end

    UBYTE   infmt, outfmt;
    int     scalefactor;
    SAMPLE  *sample;
    FILE    *fp;
} SAMPLOAD;

extern void SL_HalveSample(SAMPLOAD *s);
extern void SL_Sample8to16(SAMPLOAD *s);
extern void SL_Sample16to8(SAMPLOAD *s);
extern void SL_SampleSigned(SAMPLOAD *s);
extern void SL_SampleUnsigned(SAMPLOAD *s);
extern BOOL SL_LoadSamples(void);                      // Returns 1 on error!
extern SAMPLOAD *SL_RegisterSample(SAMPLE *s, FILE *fp);    // Returns 1 on error!
extern void SL_Load(void *buffer, SAMPLOAD *smp, int length);
extern BOOL SL_Init(SAMPLOAD *s);
extern void SL_Exit(SAMPLOAD *s);
extern void SL_FreeSampleList(void);


/**************************************************************************
****** Wavload stuff: *****************************************************
**************************************************************************/

SAMPLE *MW_LoadWavFP(FILE *fp);
SAMPLE *MW_LoadWavFN(CHAR *filename);
void MW_FreeWav(SAMPLE *si);


#include "ptform.h"


/**************************************************************************
****** Driver stuff: ******************************************************
**************************************************************************/

// max. number of handles a driver has to provide. (not strict)

#define MAXSAMPLEHANDLES 128


enum
{   MD_MUSIC = 0,
    MD_SNDFX
};

enum
{   MD_HARDWARE = 0,
    MD_SOFTWARE
};

// possible mixing mode bits:

#define DMODE_STEREO       1         // enable stereo output
#define DMODE_16BITS       2         // enable 16 bit output
#define DMODE_INTERP       4         // enable interpolation (not yet supported)
#define DMODE_SURROUND     8         // enable Dolby surround sound (not yet supported)
#define DMODE_REVERSE     16         // reverse stereo
#define DMODE_SOFT_SNDFX  32         // Process sound effects via software mixer (not yet supported)
#define DMODE_SOFT_MUSIC  64         // Process music via software mixer (not yet supported)


#define PAN_SURROUND     512         // panning value for Dolby Surround


// driver structure:

typedef struct MDRIVER
{   struct MDRIVER *next;
    CHAR    *Name;
    CHAR    *Version;
    BOOL    (*IsPresent)          (void);
    SWORD   (*SampleLoad)         (SAMPLOAD *s, FILE *fp);
    void    (*SampleUnLoad)       (SWORD handle);
    ULONG   (*FreeSampleSpace)    (int type);
    ULONG   (*RealSampleLength)   (int type, SAMPLE *s);
    BOOL    (*Init)               (void);
    void    (*Exit)               (void);
    BOOL    (*SetNumChannels)     (void);
    void    (*PlayStart)          (void);
    void    (*PlayStop)           (void);
    void    (*Update)             (void);
    void    (*VoiceSetVolume)     (UBYTE voice, UWORD vol);
    void    (*VoiceSetFrequency)  (UBYTE voice, ULONG frq);
    void    (*VoiceSetPanning)    (UBYTE voice, ULONG pan);
    void    (*VoicePlay)          (UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags);
    void    (*VoiceStop)          (UBYTE voice);
    BOOL    (*VoiceStopped)       (UBYTE voice);
    void    (*VoiceReleaseSustain)(UBYTE voice);
    SLONG   (*VoiceGetPosition)   (UBYTE voice);
    ULONG   (*RealVolume)         (UBYTE voice);
} MDRIVER;


// public driver variables:

extern CHAR  *MDERR_OUT_OF_HANDLES;
extern CHAR  *MDERR_SAMPLE_TOO_BIG;


// These variables can be changed at ANY time:

extern UBYTE md_bpm;            // current song / hardware BPM rate
extern UBYTE md_volume;         // Global sound volume (0-128)
extern UBYTE md_musicvolume;    // volume of song
extern UBYTE md_sndfxvolume;    // volume of sound effects
extern UBYTE md_stereodelay;    // 0 = none;  15 = chaos
extern UBYTE md_reverb;         // 0 = none;  15 = chaos
extern UBYTE md_pansep;         // 0 = mono;  128 == 100% (full left/right)
extern BOOL  md_noloopeffect;	// forbid execution of ProTracker effect 0x0B
								// e.g. Module will always finish

// Variables below can be changed via the "MD_SetNumChannels()" procedure
// at any time.  However, a call to MD_SetNumChannels while the driver
// is active will cause the sound to pop for a split second.

extern UBYTE md_numchn;         // number of song channels
extern UBYTE md_sfxchn;         // number of sound effects channels


// The variables below can only be changed before MD_Init() is called.

extern UWORD md_device;         // Device.  0 = autodetect, other # depend on driver register order.
extern UWORD md_mixfreq;        // mixing frequency.  Valid 5000 -> 44100
extern UWORD md_dmabufsize;     // DMA buffer size.  Valid 512 -> 32000
extern UWORD md_mode;           // Mode.  See DMODE_? flags above
extern UBYTE md_stereodelay;    // Stereo Delay (range 0->15)
extern UBYTE md_reverb;         // Reverb (range 0->15)


// Following variables should not be changed!
extern MDRIVER *md_driver;      // Current driver in use.  See MDRIVER struct
                                // above for structure info contents.

// This is for use by the hardware drivers only.  It points to the
// registered tickhandler function.
extern void (*md_player)(void);


// main driver prototypes:

extern UWORD  MD_SecsToBytes(int secs);
extern BOOL   MD_Active(void);
extern void   MD_InfoDriver(void);
extern void   MD_RegisterDriver(MDRIVER *drv);
extern void   MD_RegisterPlayer(void (*plr)(void));
extern SWORD  MD_SampleLoad(SAMPLOAD *s, FILE *fp);
extern void   MD_SampleUnLoad(SWORD handle);
extern BOOL   MD_Init(void);
extern void   MD_Exit(void);
extern BOOL   MD_SetNumChannels(int music, int sndfx);
extern void   MD_PlayStart(void);
extern void   MD_PlayStop(void);
extern void   MD_SetBPM(UBYTE bpm);
extern void   MD_Update(void);
extern void   MD_VoiceSetVolume(UBYTE voice, UWORD ivol);
extern void   MD_VoiceSetFrequency(UBYTE voice,ULONG frq);
extern void   MD_VoiceSetPanning(UBYTE voice,ULONG pan);
extern void   MD_VoicePlay(UBYTE voice,SAMPLE *s,ULONG start);
extern void   MD_VoiceStop(UBYTE voice);
extern BOOL   MD_VoiceStopped(UBYTE voice);
extern void   MD_VoiceReleaseSustain(UBYTE voice);
extern SLONG  MD_VoiceGetPosition(UBYTE voice);
extern ULONG  MD_RealVolume(UBYTE voice);
extern ULONG  MD_SampleSpace(int type);
extern ULONG  MD_SampleLength(int type, SAMPLE *s);
extern void   MD_Mute(void);
extern void   MD_UnMute(void);


// Declare external drivers:

extern MDRIVER drv_gus;      // gravis ultrasound driver
extern MDRIVER drv_ultra;    // ultra driver for linux
extern MDRIVER drv_sb;       // soundblaster 1.5 / 2.0 DSP driver
extern MDRIVER drv_sbpro;    // soundblaster Pro DSP driver
extern MDRIVER drv_sb16;     // soundblaster 16 DSP driver
extern MDRIVER drv_ss;       // ensoniq soundscape driver
extern MDRIVER drv_pas;      // PAS16 driver
extern MDRIVER drv_wss;      // Windows Sound System driver
extern MDRIVER drv_nos;      // nosound driver
extern MDRIVER drv_raw;      // file output driver
extern MDRIVER drv_w95;      // win95 driver
extern MDRIVER drv_awe;      // experimental SB-AWE driver
extern MDRIVER drv_vox;      // linux voxware driver
extern MDRIVER drv_AF;       // Dec Alpha AudioFile driver
extern MDRIVER drv_sun;      // Sun driver
extern MDRIVER drv_os2;      // Os2 driver
extern MDRIVER drv_hp;       // HP-UX /dev/audio driver
extern MDRIVER drv_aix;      // AIX audio-device driver
extern MDRIVER drv_sgi;      // SGI audio-device driver
extern MDRIVER drv_tim;      // timing driver
extern MDRIVER drv_be;       // BeOS driver


/**************************************************************************
****** Player stuff: ******************************************************
**************************************************************************/

extern int    forbid;        // forbidflag (prevents lost notes at player start)
extern int    isfirst;       // isfirst count (number of ticks to skip)


/**************************************************************************
****** Virtual channel stuff: *********************************************
**************************************************************************/

extern BOOL    VC_Init(void);
extern void    VC_Exit(void);
extern BOOL    VC_SetNumChannels(void);
extern ULONG   VC_SampleSpace(int type);
extern ULONG   VC_SampleLength(int type, SAMPLE *s);

extern void    VC_PlayStart(void);
extern void    VC_PlayStop(void);

extern SWORD   VC_SampleLoad(SAMPLOAD *sload, FILE *fp);
extern void    VC_SampleUnload(SWORD handle);

extern void    VC_WriteSamples(SBYTE *buf,UWORD todo);
extern UWORD   VC_WriteBytes(SBYTE *buf,UWORD todo);
extern void    VC_SilenceBytes(SBYTE *buf,UWORD todo);

extern void    VC_VoiceSetVolume(UBYTE voice, UWORD vol);
extern void    VC_VoiceSetFrequency(UBYTE voice, ULONG frq);
extern void    VC_VoiceSetPanning(UBYTE voice, ULONG pan);
extern void    VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags);

extern void    VC_VoiceStop(UBYTE voice);
extern BOOL    VC_VoiceStopped(UBYTE voice);
extern void    VC_VoiceReleaseSustain(UBYTE voice);
extern SLONG   VC_VoiceGetPosition(UBYTE voice);
extern ULONG   VC_RealVolume(UBYTE voice);

#ifdef __cplusplus
} 
#endif

#endif
