#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <dos.h>
#include <i86.h>


typedef unsigned short int word;
typedef unsigned int dword;
typedef unsigned char uchar;
typedef signed char schar;

struct xmheader  {
  char                xm_id[17];
  char                module_name[20];
  char                One_a;
  char                tracker_name[20];
  uchar               version_number_lo; 
  uchar               version_number_hi; 
  dword               header_size;
  word                song_length;
  word                restart_position;
  word                num_channels;
  word                num_patterns;
  word                num_instruments;
  word                flags;
  word                default_tempo;
  word                default_bpm;
  char                pat_table[256];
};


void (__interrupt __far *prev_int_1c)();

extern char  BPM,Speed;
extern char  Row,Pattern;
extern struct xmheader      xmh;

double ticks_to_wait;
double wticks;
double TBPM;

short int Actual_Tick;
char  Pause_Timer_Var;
char  volticks;

int env_ticks;

void Process_TickEffects()
{
 unsigned int i;
 char *scrn;

 for (i = 0; i < xmh.num_channels; i++) {
   process_effects(i);
 }
}


void Process_Row()
{
  process_patternrow();
}

void Process_Envelopes()
{
 Process_Pan_Env();
 if (volticks < 1) {
   volticks ++;
 }
 else
 {
   volticks = 0;
   Process_Vol_Env();
 }
}

void __interrupt __far timer_rtn()
{
  if (Pause_Timer_Var != 1) {
    Process_Envelopes();
    wticks++;
    if (wticks > ticks_to_wait) {
      wticks -= ticks_to_wait;                     
      Process_TickEffects();          // Process Tick - Effects
      Actual_Tick++;
      if (Actual_Tick > Speed) {
        Actual_Tick = 0;
        Process_Row();                // Next row
      }
    }
  }
}

void init_timer()
{
  wticks = 0;
  volticks = 0;
  env_ticks = 0;
  prev_int_1c = _dos_getvect(0x1c);
  _disable;
  outp(0x43,0x36);
  outp(0x40,177);
  outp(0x40,45);
  _dos_setvect(0x1c, timer_rtn);
  _enable;
}

void reset_timer()
{
  _disable;
  outp(0x43,0x36);
  outp(0x40,0);
  outp(0x40,0);
  _dos_setvect(0x1c, prev_int_1c);
  _enable;
}

void Pause_Timer()
{
  Pause_Timer_Var = 1;
}

void Continue_Timer()
{
  Pause_Timer_Var = 0;
}

void Set_Timer_Defaults()
{
 BPM = 125;
 Speed = 6;
 Actual_Tick = 0;
 Row = 0;
 Pattern = 0;

 TBPM = BPM;
// ticks_to_wait = (96,5*5) / (TBPM * 2);
 ticks_to_wait = 510 / (TBPM * 2);
}

void SetTimer(unsigned short int bpms,unsigned short int speedy)
{
 BPM = bpms;
 Speed = speedy;

 TBPM = BPM;
 ticks_to_wait = 510 / (TBPM * 2);
}

void Set_BPM(unsigned short int bpms)
{
 BPM = bpms;

 TBPM = BPM;
 ticks_to_wait = 510 / (TBPM * 2);
}

void Set_Speed(unsigned short int speedy)
{
 Speed = speedy;

 TBPM = BPM;
 ticks_to_wait = 510 / (TBPM * 2);
}
