/*
 *  mod.h - Main header file
 *
 *  (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
 */

#ifndef _MOD_H
#define _MOD_H

#include <limits.h>

/*
 *  Name of the mixer device-file.
 */

#define MIXER_NAME "/dev/mixer"

/*
 *  Decompressing commands
 */

#define GZIP_COMMAND     "gzip -cd "
#define LHA_COMMAND      "lharc xqf "
#define LHA_COMMAND_LIST "lharc l "
#define ZIP_COMMAND      "unzip -xq "
#define ZIP_COMMAND_LIST "unzip -lq "
#define ARJ_COMMAND      "unarj e "
#define ARJ_COMMAND_LIST "unarj l "

#define TMP_DIR          "/tmp/.modtmp"

/*
 *  Global environment variable
 */

#define ENV_VAR_NAME "MOD_OPTIONS"

/*
 *  Format of modules
 */

#define MODFORMAT_MOD 1
#define MODFORMAT_ULT 2
#define MODFORMAT_MTM 3
#define MODFORMAT_S3M 4

/*
 *  Constants for effects
 */

/* PT-effects */

#define EFX_ARPEGGIO           0x00
#define EFX_PORTAUP            0x01
#define EFX_PORTADOWN          0x02
#define EFX_PORTANOTE          0x03
#define EFX_VIBRATO            0x04
#define EFX_PORTANOTEVOLSLIDE  0x05
#define EFX_VIBRATOVOLSLIDE    0x06
#define EFX_TREMOLO            0x07
#define EFX_UNUSED1            0x08 /* Unused EFX # */
#define EFX_SAMPLEOFFSET       0x09
#define EFX_VOLSLIDE           0x0a
#define EFX_JUMP               0x0b
#define EFX_VOLUME             0x0c
#define EFX_BREAK              0x0d
#define EFX_EXTENDED           0x0e /* should never appear in code */
#define EFX_PTSPEED            0x0f

#define EFX_FILTER             0x10 /* NOT SUPPORTED */
#define EFX_FINEPORTAUP        0x11
#define EFX_FINEPORTADOWN      0x12
#define EFX_GLISSANDO          0x13
#define EFX_VIBWAVEFORM        0x14
#define EFX_FINETUNE           0x15
#define EFX_LOOP               0x16
#define EFX_TREMWAVEFORM       0x17
#define EFX_UNUSED2            0x18 /* KarplusStrong in PT3.0; NOT SUPPORTED */
#define EFX_RETRIGGER          0x19
#define EFX_FINEVOLSLIDEUP     0x1a
#define EFX_FINEVOLSLIDEDOWN   0x1b
#define EFX_NOTECUT            0x1c
#define EFX_NOTEDELAY          0x1d
#define EFX_PATTERNDELAY       0x1e
#define EFX_INVERTEDLOOP       0x1f /* NOT SUPPORTED */

/* New effects for ULT (EFX_BALANCE is used with MTM's too) */

#define EFX_BALANCE            0x20
#define EFX_VIBDEPTH           0x21
#define EFX_SAMPLEOFFSET_ULT   0x22

/* New effects for S3M */

#define EFX_EXTRAFINEPORTAUP   0x23
#define EFX_EXTRAFINEPORTADOWN 0x24
#define EFX_TREMOR             0x25
#define EFX_SAMPLEOFFSET_S3M   0x26
#define EFX_RETRIGGERVOLSLIDE  0x27
#define EFX_SPEED              0x28
#define EFX_TEMPO              0x29
#define EFX_GLOBALVOLUME       0x2a
#define EFX_PORTAUPCONTINUE    0x2b
#define EFX_PORTADOWNCONTINUE  0x2c
#define EFX_VOLSLIDECONTINUE   0x2d

#define NR_EFX                 0x2e
#define NR_OCTAVES               10

#define WAVEFORM_SINE    0
#define WAVEFORM_RAMP    1
#define WAVEFORM_SQUARE  2
#define WAVEFORM_RANDOM  3

#define LOOP_FORWARD     1
#define LOOP_BIDIR       2

#define S3M_ORDER_SKIP     254
#define S3M_ORDER_SONGEND  255

/*
 *  Structures used to store the module in memory.
 *  Notes are accessed with the GET_EVENT() macro below.
 *
 *  Track = pattern for one voice (64 events).
 */

#define GET_EVENT_PTR(voice, pattern, line) \
        (&M.tracks[M.track_idx[voice][pattern]][line])

struct event {
    unsigned char note;
    unsigned char sample;
    unsigned char effect;
    unsigned char arg;
    unsigned char effect2;  /* The second effect is for ULT */
    unsigned char arg2;
};


struct sample_info {
    char           name[33];    /* PT=22, ULT=32 */
    char           dosname[13]; /* ULT */
    char           finetune;
    char           bits_16;     /* True if 16 bit sample (ULT) */
    char           unsigned_data; /* True if unsigned data */
    char           looped;
    int            length;
    unsigned char  volume;
    char           valid;
    int            repeat_start;
    int            repeat_end;
    char           *data;
    int            c2freq;
};

#define MAX_VOICES 32

struct mod_info {
    char           format;                  /* What type of module it is  */
    char           name[32];                /* Mod 20+1, ult 32+0         */
    char           filename[NAME_MAX];      /* uncompressed name w/o path */ 
    char           real_filename[PATH_MAX]; /* name of the file w/ path   */
    unsigned short  nr_voices;
    unsigned char  restartpos;
    unsigned short songlength;
    unsigned short nr_patterns;
    unsigned short nr_tracks;   /* nr_patterns*nr_voices if uncompressed */
    unsigned short nr_samples;

    unsigned char  panning[MAX_VOICES];  /* Panning of the voices  */
    struct sample_info *sample;          /* sample[0] not used     */
    unsigned char  patterntable[256];    /* order to play patterns
					  * PT=128, ULT=256
					  */

    int            *track_idx[MAX_VOICES];
    struct event   **tracks;    
    char           *songtext;   /* Only used for Ultratracker modules */
    unsigned char  volrange;    /* MOD 64, ULT 255 */
};

/*
 *  Structures used to play module
 */

struct voice {
    int sample;                /* Current sample    */
    char finetune;             /* Current finetune  */
    unsigned char volume;      /* Current volume    */
    unsigned char real_volume; /* Current volume used to play note */

    unsigned char note;        /* Current note(midi)*/

    int pitchbend;        /* Current pitchbend */
    int real_period;      /* Period used to calculate pitchbend */
    int period;           /* Period used to calculate effects   */

    int period_goal;      /* Period goal during toneportamento  */
    int toneporta_speed;  /* Speed of toneportamento            */
    char glissando;       /* True if glissando is on   */

    char vibrato;         /* True if we have vibrato   */
    char vibrato_retrig;  /* True if waveform is retriggered */
    int vibrato_amplitude;/* Amplitude of vibrato      */
    int vibrato_speed;    /* Speed of vibrato          */
    int vibrato_pos;      /* Position in vibratotable  */
    int vibrato_waveform; /* Waveform used for vibrato */

    char tremolo;         /* True if we have tremolo */
    char tremolo_retrig;  /* True if waveform is retriggered */
    int tremolo_amplitude;/* Amplitude of tremolo      */
    int tremolo_speed;    /* Speed of tremolo          */
    int tremolo_pos;      /* Position in vibratotable  */
    int tremolo_waveform; /* Waveform used for tremolo */

    unsigned int sampleoffset;      /* Current sample offset        */
    unsigned int last_sampleoffset; /* Last specified sample offset */
    int last_volumeslide;               /* Used for S3M's */
    unsigned char last_volumeslidetype; /* Used for S3M's */
    int last_portamento;                /* Used for S3M's */
    unsigned char last_portamentotype;  /* Used for S3M's */

    unsigned int loopcount;         /* Remaining iterations  */
    unsigned char loopstartpos;     /* Loop restart position */
};

struct effects {
    /* The following 3 variables have the same names as in pt-replay.s to make
     * it easier for me to mimic it's behaviour. 
     */

    char PosJumpFlag; /* True when a new pattern should be activated at
		       * position PBreakPos (EFX_JMP|BREAK).
		       */
    char PBreakFlag;  /* True when we should jump back in pattern (EFX_LOOP) */
    
    char PBreakPos;   /* Line to start with in next pattern (EFX_JMP|BREAK) OR
		       * Line to jump to in current pattern (EFX_LOOP)
		       */

    char pattern_delay;

    char set_volume, set_finepitch, set_balance;
    char note_delay, dont_trigger_note, kill_voice;
    unsigned char retrig_note;
};

/*
 *  Structure handling options for the current module
 */

struct options {
    char
	noscroll,
	nobpm,
	speed0stop,
        mono,
	ntsc_samples,
	break_loops,
	tolerant,

	verbose,
	interactive,
	quiet,

	auto_next,
	random_mode,
	loop_module,
	replay_forever,
	play_list;

    int 
	speed,
	tempo,
	start_pos,
	active_voices,
	maxtime,
	click_removal,
	max_lines,
	voice_detail,

	format,
	low_note,
	high_note;
};

/*
 *  Structure used to store current files
 */

struct mod_file {
    char *name;
    int size;
    char dir;     /* True if this is a directory */
    char options; /* True if there are options (play_list) */
};

/*
 *  Various constants
 */

#define BASE_NOTE (1*12)
#define NOTE_OFF  (NR_OCTAVES*12+BASE_NOTE)

#define QUIT_QUIT   1
#define QUIT_SIGNAL 2

#define PIPE_READ  0
#define PIPE_WRITE 1

/*
 *  MIN - MAX macros
 */

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)

#include "protos.h"

#endif /* _MOD_H */
