/*
	songs.C

	A collection of songs for the IC v2.0+ SND API.

	Version 1.0

	Copyright (C) 1992, Geoff Friesen B.Sc.
	All rights reserved.

	Developed with: Borland C++ 2.0
*/

#include <conio.H>
#include <ctype.H>
#include <dos.H>
#include <process.H>
#include <stdio.H>
#include <string.H>

int	Busy		(void);
int	Found		(void);
void	NoSound		(void);
void	Pause		(unsigned ticks);
void	PlaySong	(int *song);
void	Sound		(unsigned frequency);
int	Version		(void);

int stars [] =		/* Stars and Stripes Forever */
{
   589, 6, 589, 6, 525, 3, 495, 3, 495, 6, 467, 3, 495, 3, 495, 16,
   32767, 2, 467, 3, 495, 3, 495, 6, 467, 3, 495, 3, 589, 6, 495, 3,
   589, 3, 525, 12, 441, 6, 32767, 3, 441, 3, 441, 6, 416, 3, 441, 3,
   441, 6, 416, 3, 441, 3, 525, 16, 32767, 2, 495, 3, 441, 3, 495, 3,
   589, 9, 661, 9, 661, 3, 441, 16, 32767, 2, 589, 6, 589, 6, 525, 3,
   495, 3, 495, 6, 467, 3, 495, 3, 495, 16, 32767, 2, 467, 3, 495, 3,
   495, 6, 467, 3, 495, 3, 525, 3, 495, 3, 441, 5, 371, 1, 441, 12,
   393, 6, 32767, 3, 393, 3, 393, 6, 371, 3, 393, 3, 467, 6, 441, 3,
   393, 3, 786, 15, 32767, 3, 393, 3, 441, 3, 495, 3, 589, 1, 32767, 2,
   393, 3, 441, 3, 495, 3, 589, 1, 32767, 2, 294, 3, 330, 5, 495, 1,
   441, 12, 393, 1, -1
};

int cucaracha [] =	/* La Cucaracha - Mexican Folk Song */
{
   294, 1, 32767, 1, 294, 1, 32767, 1, 294, 1, 32767, 1, 393, 1, 32767, 5,
   495, 1, 32767, 3, 294, 1, 32767, 1, 294, 1, 32767, 1, 294, 1, 32767, 1,
   393, 1, 32767, 5, 495, 1, 32767, 5, 147, 1, 32767, 1, 147, 1, 32767, 1,
   196, 1, 32767, 3, 393, 1, 32767, 1, 393, 1, 32767, 1, 371, 1, 32767, 1,
   371, 1, 32767, 1, 330, 1, 32767, 1, 330, 1, 32767, 1, 294, 8, 32767, 2,
   294, 1, 32767, 1, 294, 1, 32767, 1, 294, 1, 32767, 1, 371, 1, 32767, 5,
   441, 1, 32767, 3, 294, 1, 32767, 1, 294, 1, 32767, 1, 294, 1, 32767, 1,
   371, 1, 32767, 5, 441, 1, 32767, 5, 221, 1, 32767, 1, 221, 1, 32767, 1,
   147, 1, 32767, 3, 589, 2, 661, 2, 589, 2, 525, 2, 441, 2, 393, 8, -1
};

int danube [] =		/* Blue Danube Waltz - J.S. Strauss */
{
   294, 4, 371, 4, 441, 4, 441, 4, 32767, 4, 882, 2, 32767, 2, 882, 2,
   32767, 6, 742, 2, 32767, 2, 742, 2, 32767, 6, 294, 4, 294, 4, 371, 4,
   441, 4, 441, 4, 32767, 4, 882, 2, 32767, 2, 882, 2, 32767, 6, 786, 2,
   32767, 2, 786, 2, 32767, 6, 278, 4, 278, 4, 330, 4, 495, 4, 495, 4,
   32767, 4, 990, 2, 32767, 2, 990, 2, 32767, 6, 786, 2, 32767, 2, 786, 2,
   32767, 6, 278, 4, 278, 4, 330, 4, 495, 4, 495, 4, 32767, 4, 990, 2,
   32767, 2, 990, 2, 32767, 6, 742, 2, 32767, 2, 742, 2, 32767, 6, 294, 4,
   294, 4, 371, 4, 441, 4, 589, 4, 32767, 4, 1178, 2, 32767, 2, 1178, 2,
   32767, 6, 882, 2, 32767, 2, 882, 2, 32767, 6, 294, 4, 294, 4, 371, 4,
   441, 4, 589, 4, 32767, 4, 1178, 2, 32767, 2, 1178, 2, 32767, 6, 990, 2,
   32767, 2, 990, 2, 32767, 6, 330, 4, 330, 4, 393, 4, 495, 2, 32767, 2,
   495, 14, 32767, 2, 416, 4, 441, 4, 742, 16, 589, 4, 371, 4, 371, 8,
   330, 4, 495, 8, 441, 4, 294, 4, 32767, 2, 294, 2, 294, 4, 32767, 8,
   441, 2, 32767, 2, 393, 2, 32767, 6, 441, 2, 32767, 2, 393, 2, 32767, 6,
   441, 4, 742, 16, 661, 4, 441, 2, 32767, 2, 371, 2, 32767, 6, 441, 2,
   32767, 2, 371, 2, 32767, 6, 441, 4, 661, 16, 589, 4, 441, 2, 32767, 2,
   393, 2, 32767, 6, 441, 2, 32767, 2, 393, 2, 32767, 6, 441, 4, 742, 16,
   661, 4, 441, 4, 589, 4, 661, 4, 742, 4, 882, 8, 786, 4, 742, 2, 742, 2,
   742, 4, 661, 2, 32767, 2, 589, 4, 32767, 8, -1
};

int funeral [] =	/* Funeral March of a Marionette - Gounod */
{
   221, 1, 32767, 2, 147, 1, 32767, 5, 294, 3, 294, 3, 278, 3, 248, 3,
   278, 3, 32767, 3, 294, 3, 330, 3, 32767, 3, 221, 1, 32767, 2, 147, 1,
   32767, 5, 294, 3, 294, 3, 278, 3, 248, 3, 278, 3, 32767, 3, 294, 3,
   330, 3, 32767, 3, 221, 3, 294, 3, 32767, 3, 350, 3, 441, 6, 393, 3,
   350, 3, 32767, 3, 441, 3, 525, 6, 467, 3, 441, 3, 32767, 3, 556, 3,
   661, 6, 589, 3, 556, 3, 467, 3, 441, 3, 393, 3, 350, 3, 330, 3, 147, 1,
   32767, 5, 294, 3, 294, 3, 278, 3, 248, 3, 278, 3, 32767, 3, 294, 3,
   330, 3, 32767, 3, 221, 1, 32767, 2, 147, 1, 32767, 5, 294, 3, 294, 3,
   278, 3, 248, 3, 278, 3, 32767, 3, 294, 3, 330, 3, 32767, 3, 221, 3,
   350, 3, 32767, 3, 441, 3, 525, 6, 467, 3, 441, 3, 393, 3, 350, 3,
   312, 3, 393, 3, 467, 3, 294, 3, 278, 3, 294, 3, 330, 3, 32767, 3,
   350, 1, 32767, 2, 330, 9, 294, 1, -1
};

int humoresque [] =	/* Humoresque - Dvorak */
{
   393, 3, 32767, 2, 441, 1, 393, 3, 32767, 2, 441, 1, 495, 3, 32767, 2,
   589, 1, 661, 3, 32767, 2, 589, 1, 786, 3, 32767, 2, 742, 1, 882, 3,
   32767, 2, 786, 1, 742, 3, 32767, 2, 882, 1, 786, 3, 32767, 2, 661, 1,
   589, 3, 32767, 2, 589, 1, 661, 3, 32767, 2, 589, 1, 786, 3, 32767, 2,
   661, 1, 589, 3, 32767, 2, 495, 1, 441, 24, 393, 3, 32767, 2, 441, 1,
   393, 3, 32767, 2, 441, 1, 495, 3, 32767, 2, 589, 1, 661, 3, 32767, 2,
   589, 1, 786, 3, 32767, 2, 742, 1, 882, 3, 32767, 2, 786, 1, 742, 3,
   32767, 2, 882, 1, 786, 3, 32767, 2, 661, 1, 589, 3, 32767, 2, 589, 1,
   786, 3, 32767, 2, 393, 1, 441, 6, 589, 6, 393, 18, -1
};

int symphony40 [] =	/* Symphony # 40 - Mozart */
{
   624, 2, 589, 2, 589, 4, 624, 2, 589, 2, 589, 4, 624, 2, 589, 2, 589, 4,
   935, 4, 32767, 4, 935, 2, 882, 2, 786, 4, 786, 2, 700, 2, 624, 4,
   624, 2, 589, 2, 525, 4, 525, 4, 32767, 4, 589, 2, 525, 2, 525, 4,
   589, 2, 525, 2, 525, 4, 589, 2, 525, 2, 525, 4, 882, 4, 32767, 4,
   882, 2, 786, 2, 742, 4, 742, 2, 624, 2, 589, 4, 589, 2, 525, 2, 467, 4,
   467, 4, 32767, 4, 935, 2, 882, 2, 882, 4, 1049, 4, 742, 4, 882, 4,
   786, 4, 589, 4, 32767, 4, 935, 2, 882, 2, 882, 4, 1049, 4, 742, 4,
   882, 4, 786, 4, 935, 4, 882, 2, 786, 2, 700, 2, 624, 2, 589, 4, 371, 4,
   393, 4, 441, 4, 467, 4, 525, 2, 467, 2, 441, 4, 393, 4, 589, 4,
   32767, 4, 1112, 8, 1178, 2, 32767, 6, 1112, 8, 1178, 2, 32767, 6,
   1112, 8, 1178, 4, 1112, 4, 1178, 4, 1112, 4, 1178, 4, -1
};

void main (int argc, char **argv)
{
   fprintf (stderr, "ÉÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
   fprintf (stderr, "º SONGS v1.0 º\n");
   fprintf (stderr, "ÈÍÍÍÍÍÍÍÍÍÍÍÍ¼\n\n");

   if (argc != 2 || strlen (argv [1]) != 1 ||
       *argv [1] < '0' || *argv [1] > '5')
   {
       fprintf (stderr, "songs: bad command line\n"
			"usage: songs 0\n"
			"       songs 1\n"
			"       songs 2\n"
			"       songs 3\n"
			"       songs 4\n"
			"       songs 5\n"
			"\n"
			"0 - Stars and Stripes Forever\n"
			"1 - La Cucaracha\n"
			"2 - Blue Danube Waltz\n"
			"3 - Funeral March of a Marionette\n"
			"4 - Humoresque\n"
			"5 - Symphony #40\n");

       exit (1);
   }

   if (!Found ())
   {
       fprintf (stderr, "songs: SND API not installed\n");
       exit (1);
   }

   fprintf (stderr, "songs: SND API version %d installed\n\n", Version ());

   if (Busy ())
   {
       fprintf (stderr, "songs: SND API is busy\n");
       exit (1);
   }

   switch (*argv [1])
   {
      case '0': puts ("þ Stars and Stripes Forever þ");
		PlaySong (stars);
		break;

      case '1': puts ("þ La Cucaracha þ");
		PlaySong (cucaracha);
		break;

      case '2': puts ("þ Blue Danube Waltz þ");
		PlaySong (danube);
		break;

      case '3': puts ("þ Funeral March of a Marionette þ");
		PlaySong (funeral);
		break;

      case '4': puts ("þ Humoresque þ");
		PlaySong (humoresque);
		break;

      case '5': puts ("þ Symphony # 40 þ");
		PlaySong (symphony40);
   }

   exit (0);
}

int Busy (void)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 0;
   int86 (0x1a, &regs, &regs);

   return regs.h.ah;
}

int Found (void)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 0;
   int86 (0x1a, &regs, &regs);

   return regs.h.ah != 0xff;
}

void NoSound (void)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 3;
   int86 (0x1a, &regs, &regs);
}

void Pause (unsigned ticks)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 1;
   regs.x.dx = ticks;
   int86 (0x1a, &regs, &regs);
}

void PlaySong (int *song)
{
   int frequency, i = 0, rest;

   do
   {
      if ((frequency = song [i++]) == -1)
	  break;

      if (kbhit ())
      {
	  if (!getch ())
	      (void) getch ();
	  break;
      }

      Sound (frequency);
      Pause (rest = song [i++]);

      if (frequency != 32767 || rest != 1)
      {
	  Sound (32767);
	  Pause (1);
      }

      printf (".");
   }
   while (1);

   NoSound ();

   puts ("");
}

void Sound (unsigned frequency)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 2;
   regs.x.dx = frequency;
   int86 (0x1a, &regs, &regs);
}

int Version (void)
{
   union REGS regs;

   regs.h.ah = 0xff;
   regs.h.al = 0;
   int86 (0x1a, &regs, &regs);

   return regs.h.al;
}