/*
  --> The Protracker Enums
   -> For MikMod 3.0
*/

#ifndef _PTFORM_H_
#define _PTFORM_H_

#ifdef __cplusplus
extern "C" {
#endif


extern UWORD  mytab[12],logtab[104];
extern UBYTE  VibratoTable[32],avibtab[128];
extern SBYTE  PanbrelloTable[256];
extern ULONG  lintab[768];
extern ULONG  fslut[32],slut[256];   // Values are 16.16 bit
extern UWORD  fsmut[16],smut[258]; // Values are 0.16 bit


// PT's UNITRK Extensions
void   UniInstrument(UBYTE ins);
void   UniNote(UBYTE note);
void   UniPTEffect(UBYTE eff, UBYTE dat);
void   UniVolEffect(UWORD eff, UBYTE dat);


enum
{   UNI_NOTE = 1,
    UNI_INSTRUMENT,
    UNI_PTEFFECT0,
    UNI_PTEFFECT1,
    UNI_PTEFFECT2,
    UNI_PTEFFECT3,
    UNI_PTEFFECT4,
    UNI_PTEFFECT5,
    UNI_PTEFFECT6,
    UNI_PTEFFECT7,
    UNI_PTEFFECT8,
    UNI_PTEFFECT9,
    UNI_PTEFFECTA,
    UNI_PTEFFECTB,
    UNI_PTEFFECTC,
    UNI_PTEFFECTD,
    UNI_PTEFFECTE,
    UNI_PTEFFECTF,
    UNI_S3MEFFECTA,
    UNI_S3MEFFECTD,
    UNI_S3MEFFECTE,
    UNI_S3MEFFECTF,
    UNI_S3MEFFECTI,
    UNI_S3MEFFECTQ,
    UNI_S3MEFFECTR,
    UNI_S3MEFFECTT,
    UNI_S3MEFFECTU, 
    UNI_KEYOFF,
    UNI_KEYFADE,
    UNI_VOLEFFECTS,
    UNI_XMEFFECT4,
    UNI_XMEFFECTA,
    UNI_XMEFFECTE1,
    UNI_XMEFFECTE2,
    UNI_XMEFFECTEA,
    UNI_XMEFFECTEB,
    UNI_XMEFFECTG,
    UNI_XMEFFECTH,
    UNI_XMEFFECTL,
    UNI_XMEFFECTP,
    UNI_XMEFFECTX1,
    UNI_XMEFFECTX2,
    UNI_ITEFFECTG,     // Porta to Note .. no kick=0;
    UNI_ITEFFECTH,     // IT specific Vibrato
    UNI_ITEFFECTI,     // IT tremor (xy not incremeneted)
    UNI_ITEFFECTM,     // Set Channel Volume
    UNI_ITEFFECTN,     // Slide / Fineslide Channel Volume
    UNI_ITEFFECTO,     // Set Sample Offset (IT Version)
    UNI_ITEFFECTP,     // Slide / Fineslide Channel Panning
    UNI_ITEFFECTU,     // IT fine vibrato
    UNI_ITEFFECTW,     // Slide / Fineslide Global volume
    UNI_ITEFFECTY,     // The Satanic Panbrello
    UNI_ITEFFECTS0,
    UNI_LAST
};


enum
{  SS_GLISSANDO = 1,
   SS_FINETUNE,
   SS_VIBWAVE,
   SS_TREMWAVE,
   SS_PANWAVE,
   SS_FRAMEDELAY,
   SS_S7EFFECTS,
   SS_PANNING,
   SS_SURROUND,
   SS_HIOFFSET,
   SS_PATLOOP,
   SS_NOTECUT,
   SS_NOTEDELAY,
   SS_PATDELAY
};


enum
{   VOL_VOLUME = 1,
    VOL_PANNING,
    VOL_VOLSLIDE,
    VOL_PITCHSLIDEDN,
    VOL_PITCHSLIDEUP,
    VOL_PORTAMENTO,
    VOL_VIBRATO
};

// Instrument format flags
#define IF_OWNPAN       1
#define IF_PITCHPAN     2

// Envelope flags:
#define EF_ON           1
#define EF_SUSTAIN      2
#define EF_LOOP         4
#define EF_VOLENV       8

// New Note Action Flags
#define NNA_CUT         0
#define NNA_CONTINUE    1
#define NNA_OFF         2
#define NNA_FADE        3

#define DCT_OFF         0
#define DCT_NOTE        1                         
#define DCT_SAMPLE      2                         
#define DCT_INST        3           

#define DCA_CUT         0
#define DCA_OFF         1
#define DCA_FADE        2

#define KEY_KICK   3
#define KEY_OFF    1
#define KEY_FADE   2


#define AV_IT   1   // IT vs. XM vibrato info


typedef struct ENVPT
{   SWORD pos;
    SWORD val;
} ENVPT;


typedef struct INSTRUMENT
{   UBYTE samplenumber[120];
    UBYTE samplenote[120];

    UBYTE flags;
    UBYTE nnatype;
    UBYTE dca;              // duplicate check action
    UBYTE dct;              // duplicate check type
    UBYTE globvol;
    UBYTE panning;          // instrument-based panning var
    
    UBYTE pitpansep;        // pitch pan separation (0 to 255)
    UBYTE pitpancenter;     // pitch pan center (0 to 119)
    UBYTE rvolvar;          // random volume varations (0 - 100%)
    UBYTE rpanvar;          // random panning varations (0 - 100%)

    UBYTE volflg;           // bit 0: on 1: sustain 2: loop
    UBYTE volpts;
    UBYTE volsusbeg;
    UBYTE volsusend;
    UBYTE volbeg;
    UBYTE volend;
    ENVPT volenv[32];

    UBYTE panflg;           // bit 0: on 1: sustain 2: loop
    UBYTE panpts;
    UBYTE pansusbeg;
    UBYTE pansusend;
    UBYTE panbeg;
    UBYTE panend;
    ENVPT panenv[32];

    UBYTE pitflg;           // bit 0: on 1: sustain 2: loop
    UBYTE pitpts;
    UBYTE pitsusbeg;
    UBYTE pitsusend;
    UBYTE pitbeg;
    UBYTE pitend;
    ENVPT pitenv[32];

    UBYTE vibtype;
    UBYTE vibsweep;
    UBYTE vibdepth;
    UBYTE vibrate;

    UWORD volfade;
    CHAR  *insname;
} INSTRUMENT;



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

typedef struct ENVPR
{   UBYTE flg;          // envelope flag
    UBYTE pts;          // number of envelope points
    UBYTE susbeg;       // envelope sustain index begin
    UBYTE susend;       // envelope sustain index end
    UBYTE beg;          // envelope loop begin
    UBYTE end;          // envelope loop end
    SWORD p;            // current envelope counter
    UWORD a;            // envelope index a
    UWORD b;            // envelope index b
    ENVPT *env;         // envelope points
} ENVPR;



//  Struct AUDOUT - Used by NNA only player (audio control.  AUDTMP is
//                  used for full effects control).
typedef struct AUDOUT
{   INSTRUMENT  *i;
    SAMPLE      *s;
    UBYTE  sample;       // which instrument number
    SWORD  handle;       // which sample-handle

    UWORD  period;       // period to play the sample at
    UWORD  panning;      // panning position
    SBYTE  chanvol;      // channel's "global" volume
    UWORD  fadevol;      // fading volume rate

    ULONG  start;        // The start byte index in the sample

    UBYTE  volflg;       // volume envelope settings
    UBYTE  panflg;       // panning envelope settings
    UBYTE  pitflg;       // pitch envelope settings

    SWORD  outvolume;    // output volume (vol + sampcol + instvol)

    UBYTE  keyon;        // if true = fade out and stuff
    UBYTE  kick;         // if true = sample has to be restarted
    UBYTE  note;         // the audible note (as heard, direct rep of period)
    UBYTE  nna;          // New note action type + master/slave flags

    // Below here is info NOT in AUDNNA!!
    // ----------------------------------

    ENVPR  venv;
    ENVPR  penv;
    ENVPR  cenv;

    UWORD  avibpos;      // autovibrato pos
    UWORD  aswppos;      // autovibrato sweep pos

    ULONG  totalvol;     // total volume of channel (before global mixings)

    BOOL   mflag;
    SWORD  masterchn;
    struct AUDNNA *master;// index of "master" effects channel
} AUDOUT;


//  Struct AUDTMP - for use in all Protracker-based players.
typedef struct AUDNNA
{   INSTRUMENT  *i;
    SAMPLE      *s;
    UBYTE  sample;       // which sample number
    SWORD  handle;       // which sample-handle

    UWORD  period;       // period to play the sample at
    UWORD  panning;      // panning position
    SBYTE  chanvol;      // channel's "global" volume
    UWORD  fadevol;      // fading volume rate

    ULONG  start;        // The start byte index in the sample

    UBYTE  volflg;       // volume envelope settings
    UBYTE  panflg;       // panning envelope settings
    UBYTE  pitflg;       // pitch envelope settings

    SWORD  outvolume;    // output volume (vol + sampcol + instvol)

    UBYTE  keyon;        // if true = fade out and stuff
    UBYTE  kick;         // if true = sample has to be restarted
    UBYTE  note;         // the audible note (as heard, direct rep of period)
    UBYTE  nna;          // New note action type + master/slave flags


    struct AUDOUT *slave;// Audio Salve of current effects control channel
 
    UBYTE anote;        // the note that indexes the audible (note seen in tracker)

    SWORD ownper;
    SWORD ownvol;

    UBYTE dca;          // duplicate check action
    UBYTE dct;          // duplicate check type

    UBYTE *row;         // row currently playing on this channel

    SBYTE retrig;       // retrig value (0 means don't retrig)
    ULONG c2spd;        // what finetune to use

    SWORD volume;       // amiga volume (0 t/m 64) to play the sample at
    SBYTE tmpvolume;    // tmp volume

    UWORD tmpperiod;    // tmp period
    UWORD wantedperiod; // period to slide to (with effect 3 or 5)

    UBYTE pansspd;      // panslide speed

    UWORD slidespeed;   //
    UWORD portspeed;    // noteslide speed (toneportamento)

    UBYTE s3mtremor;    // s3m tremor (effect I) counter
    UBYTE s3mtronof;    // s3m tremor ontime/offtime

    UBYTE s3mvolslide;  // last used volslide

    UBYTE s3mrtgspeed;  // last used retrig speed
    UBYTE s3mrtgslide;  // last used retrig slide

    UBYTE glissando;    // glissando (0 means off)
    UBYTE wavecontrol;  //

    SBYTE vibpos;       // current vibrato position
    UBYTE vibspd;       // "" speed
    UBYTE vibdepth;     // "" depth

    SBYTE trmpos;       // current tremolo position
    UBYTE trmspd;       // "" speed
    UBYTE trmdepth;     // "" depth

    UBYTE fslideupspd;
    UBYTE fslidednspd;
    UBYTE fportupspd;   // fx E1 (extra fine portamento up) data
    UBYTE fportdnspd;   // fx E2 (extra fine portamento dn) data
    UBYTE ffportupspd;  // fx X1 (extra fine portamento up) data
    UBYTE ffportdnspd;  // fx X2 (extra fine portamento dn) data

    ULONG hioffset;     // last used high order of sample offset
    UWORD soffset;      // last used low order of sample-offset (effect 9)

    UBYTE sseffect;     // last used Sxx effect
    UBYTE ssdata;       // last used Sxx data info
    UBYTE chanvolslide; // last used channel volume slide

    UBYTE panbwave;     // current panbrello waveform
    UBYTE panbpos;      // current panbrello position
    SBYTE panbspd;      // "" speed
    UBYTE panbdepth;    // "" depth

    UWORD newsamp;      // set to 1 upon a sample / inst change
    BOOL  muted;        // if set, channel not played

    UBYTE voleffect;    // Volume Column Effect Memory as used by Impulse Tracker
    UBYTE voldata;      // Volume Column Data Memory
} AUDNNA;


// =====================
// MikMod UNImod types:
// =====================
//
// Perhaps there is no such thing as the UNImod type anymore - this type is
// only universal to the ProTracker-related module type.. Mod, S3M, Mtm, XM,
// etc.

// Unimod flags
#define UF_XMPERIODS    1       // if set use XM periods/finetuning
#define UF_LINEAR       2       // if set use LINEAR periods (UF_XMPERIODS must be set as well)

typedef struct UNIMOD
{   UBYTE       numchn;         // number of channels
    UWORD       numpos;         // number of positions in this song
    UWORD       reppos;         // restart position
    UWORD       numpat;         // number of patterns in this song
    UWORD       numtrk;         // number of tracks
    UWORD       numins;         // number of instruments
    UWORD       numsmp;         // number of samples
    UBYTE       initspeed;      // initial song speed
    UBYTE       inittempo;      // initial song tempo
    UBYTE       positions[256]; // all positions
    UWORD       panning[64];    // 64 panning positions
    UBYTE       chanvol[64];    // 64 channel positions
    UBYTE       flags;          //
    CHAR       *songname;       // name of the song
    CHAR       *modtype;        // string type of module
    CHAR       *comment;        // module comments
    INSTRUMENT *instruments;    // all instruments
    SAMPLE     *samples;        // all samples
    UWORD      *patterns;       // array of PATTERN
    UWORD      *pattrows;       // array of number of rows for each pattern
    UBYTE     **tracks;         // array of pointers to tracks

    // following are the player-instance variables.  They are in no way file
    // storage related - they are for internal replay use only.

    AUDNNA     *audio;          // Audio / Effects information (pf->numchn alloc'ed)
    AUDOUT     *control;        // Audio Output information (md_numchn alloc'ed)
    UWORD       pat_reppos;     // patternloop position
    UWORD       pat_repcnt;     // times to loop
    UWORD       vbtick;         // tick counter
    UWORD       patbrk;         // position where to start a new pattern
    UBYTE       patdly;         // patterndelay counter (command memory)
    UBYTE       patdly2;        // patterndelay counter (real one)
    UWORD       numrow;         // number of rows on current pattern
    SWORD       posjmp;         // flag to indicate a position jump is needed...
                                //  changed since 1.00: now also indicates the
                                //  direction the position has to jump to:
                                //  0: Don't do anything
                                //  1: Jump back 1 position
                                //  2: Restart on current position
                                //  3: Jump forward 1 position

    UBYTE       bpm;            // beats-per-minute speed
    UWORD       patpos;         // current row number (0-255)
    SWORD       sngpos;         // current song position
    UWORD       sngspd;         // current songspeed
    BOOL        extspd;         // extended speed flag, default enabled
    BOOL        panflag;        // panning flag, default enabled
    BOOL        loop;           // loop module ?
    SWORD       volume;         // song volume (0-128) (or user volume)
    UBYTE       globalslide;    // global volume slide rate
    BOOL        forbid;         // if true, no play update!
} UNIMOD;


/***************************************************
****** Loader stuff: *******************************
****************************************************/

// loader structure:

typedef struct MLOADER
{   struct MLOADER *next;
    CHAR    *type;
    CHAR    *version;
    BOOL    (*Init)(void);
    BOOL    (*Test)(void);
    BOOL    (*Load)(void);
    void    (*Cleanup)(void);
} MLOADER;

// public loader variables:

extern CHAR  *MLERR_LOADING_PATTERN;
extern CHAR  *MLERR_LOADING_TRACK;
extern CHAR  *MLERR_LOADING_HEADER;
extern CHAR  *MLERR_NOT_A_MODULE;
extern CHAR  *MLERR_LOADING_SAMPLEINFO;

extern FILE *modfp;
extern UWORD finetune[16];
extern UNIMOD of;         // static unimod loading space
extern UWORD npertab[60]; // used by the original MOD loaders

// main loader prototypes:

void    ML_InfoLoader(void);
void    ML_RegisterLoader(MLOADER *ldr);
void    ML_UnRegisterLoader(MLOADER *ldr);
UNIMOD *ML_LoadFP(FILE *fp);
UNIMOD *ML_LoadFN(CHAR *filename, int maxchan);
void    ML_Free(UNIMOD *mf);


// other loader prototypes: (used by the loader modules)

BOOL    InitTracks(void);
void    AddTrack(UBYTE *tr);
BOOL    ReadComment(UWORD len);
BOOL    AllocPatterns(void);
BOOL    AllocTracks(void);
BOOL    AllocInstruments(void);
BOOL    AllocSamples(void);
CHAR    *DupStr(CHAR *s, UWORD len);


// Declare external loaders:

extern MLOADER  load_uni;
extern MLOADER  load_mod;
extern MLOADER  load_m15;
extern MLOADER  load_mtm;
extern MLOADER  load_s3m;
extern MLOADER  load_stm;
extern MLOADER  load_ult;
extern MLOADER  load_xm;
extern MLOADER  load_it;
extern MLOADER  load_669;
extern MLOADER  load_dsm;
extern MLOADER  load_med;
extern MLOADER  load_far;


extern BOOL   MP_Init(UNIMOD *mf);
extern void   MP_Exit(UNIMOD *mf);
extern void   MP_HandleTick(void);
extern BOOL   MP_Ready(UNIMOD *mf);
extern void   MP_PlayStart(UNIMOD *mf);
extern void   MP_PlayStop(UNIMOD *mf);
extern void   MP_TogglePause(UNIMOD *mf);
extern void   MP_NextPosition(UNIMOD *mf);
extern void   MP_PrevPosition(UNIMOD *mf);
extern void   MP_SetPosition(UNIMOD *mf, UWORD pos);
extern void   MP_Mute(UNIMOD *mf, SLONG arg1, ...);
extern void   MP_UnMute(UNIMOD *mf, SLONG arg1, ...);
extern void   MP_ToggleMute(UNIMOD *mf, SLONG arg1, ...);
extern BOOL   MP_Muted(UNIMOD *mf, int chan);
extern void   MP_HandleTick(void);

#ifdef __cplusplus
}
#endif

#endif
