/**********************************************/
/*  int_music.c                               */
/*  written by Raymond F. Genovese            */
/**********************************************/


#include <dos.h>

/* the note defines */
#define C    0
#define Cs   1
#define Db   1
#define D    2
#define Ds   3
#define Eb   3
#define E    4
#define F    5
#define Fs   6
#define Gb   6
#define G    7
#define Gs   8
#define Ab   8
#define A    9
#define As  10
#define Bb  10
#define B   11

/* psuedo operations defines */
#define REPEAT 12   /* repeat from begining    */
#define SO     13   /* switch octaves          */
#define R      14   /* rest (duration follows) */
#define END    15   /* end of the song         */

/* duration defines */
#define S    1
#define EI   2
#define Q    4
#define H    8
#define W   16
#define DW  32

/* the notes:frequency array */
unsigned int notes[6][12]={
  /* actually starts at octave #3 */
  {17145,17173,16209,15299,14441,13630,12865,12143,11462,10818,10211,9638},
  {9097,8586,8105,7650,7224,6816,6432,6071,5729,5409,5105,4819},
  {4548,4293,4052,3825,3610,3410,3216,3036,2867,2705,2554,2409},
  {2274,2147,2026,1912,1805,1702,1608,1518,1433,1352,1276,1205},
  {1137,1073,1013,956,903,852,804,759,716,676,638,602},
  {569,537,507,478,451,426,402,380,358,338,319,301}
  };

unsigned char taps[]={SO,1,G,W,R,EI,G,Q,R,EI,SO,2,C,DW,R,W,
   SO,1,G,W,R,EI,SO,2,C,Q,R,EI,E,DW,R,DW,
   SO,1,G,W,R,EI,SO,2,C,Q,R,EI,E,W,R,S,
   SO,1,G,W,R,EI,SO,2,C,Q,R,EI,E,W,R,S,
   SO,1,G,W,R,EI,SO,2,C,Q,R,EI,E,W,R,S,
   R,W,C,W,R,EI,E,Q,R,EI,G,W,
   R,W,E,W,R,EI,C,W,R,EI,SO,1,G,W,R,W,
   G,W,R,EI,G,Q,R,EI,SO,2,C,DW,R,DW,R,DW,
   REPEAT};

/* globals for the song routines */
  char c_note,c_duration,c_octave,*ptr,*s_song;
  char sp_on,sp_off,lsb,msb,end,save_add1c[4];

void install(),restore();
void interrupt p_song();
void interrupt (*oldvector)();

void install()
{
/* installs the p_song interrupt                               */
/* set ptr to the song data array before calling this routine! */

/* set up */
  sp_off=inportb(97);
  sp_on=sp_off|3;
  /* set up song */
  c_duration=0;
  oldvector=getvect(0x1c);
  disable();
  setvect(0x1c,&p_song);
  enable();
  /* it's playing */
}

void restore()
{
/* restores the old timer vector and speaker state               */
/* *oldvector MUST have been initialized by install()!           */
  disable();
  setvect(0x1c,oldvector);
  enable();
  outportb(97,sp_off);
}

void interrupt p_song()
{
  if(c_duration)
    c_duration--;
  else
    {
    c_note=*ptr;
    switch(c_note)
      {
      case 12: ptr=s_song;
	       break;
      case 13: ptr++;
	       c_octave=*ptr;
	       ptr++;
	       break;
      case 14: ptr++;
	       c_duration=*ptr;
               outportb(97,sp_off);
	       ptr++;
	       break;
      case 15: end=1;
	       break;
      default: ptr++;
	       c_duration=*ptr;
	       lsb=notes[c_octave][c_note]%256;
	       msb=notes[c_octave][c_note]/256;
	       outportb(67,182);
	       outportb(66,lsb);
	       outportb(66,msb);
	       outportb(97,sp_on);
	       ptr++;
               break;
       }
     }
 }

main()
{
  ptr=taps;
  s_song=ptr;
  install();
  while(!kbhit())
    printf("This is printing while playing\n");
  restore();
  
}
