/*
 * This program loads the microcode to the SoundScape card.
 * You will have to edit the DSPDEV and CODEFILE macros before compiling.
 *
 * The DSPDEV tells the /dev/dsp# device which is the soundscape.
 * (use cat /dev/sndstat to see the device numbering).
 * Usually the proper device is /dev/dsp0 buut it may be something
 * else if you have other soundcards on the same system.
 * 
 * The CODEFILE is name of the file containing the microcode. In the
 * v3.0-proto versions (at least) there is a bug which prevents from
 * using the original sndscape.cod file. The recent sndscape.co0 and
 * sndscape.co1 files work (latest DOS drivers in ftp.ensoniq.com
 * contains the right version). The difference between sndscape.co0 and
 * sndscape.co1 is that they work with different models of SoundScape
 * cards (.co0 works with S-2000 and the .co1 is for Spea/Reveal I guess).
 *
 * There is a serious limitation in the current driver. You have to
 * cold boot the machine and to run ssinit (this program) before
 * attempting to access the sound driver. Otherwise the ssinit program
 * will fail.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>

#define DSPDEV "/dev/dsp0"
#define CODEFILE "/sndscape.co0"

int fd;

void
reload (void)
{
  int f, i, len;

  copr_buffer buf;
  unsigned char localbuf[256 * 1024];

  if ((f = open (CODEFILE, O_RDONLY, 0)) == -1)
    {
      perror (CODEFILE);
      exit (-1);
    }

  if ((len = read (f, localbuf, sizeof (localbuf))) == -1)
    {
      perror ("/C/sndscape/sndscape.cod");
      exit (-1);
    }

  if (len == sizeof (localbuf))
    {
      fprintf (stderr, "Error: Code too long\n");
      exit (-1);
    }

  close (f);

  i = 0;
  while (i < len)
    {
      int l = len - i;

      if (l > sizeof (buf.data))
	l = sizeof (buf.data);

      buf.flags = 0;
      if (i==0) buf.flags = CPF_FIRST;
      if (len <=(i+l))buf.flags = CPF_LAST;

      memcpy(buf.data, &localbuf[i], l);
      buf.len=l;
      if (ioctl (fd, SNDCTL_COPR_LOAD, &buf) == -1)
	{
	  perror ("Code load " DSPDEV);
	  exit (-1);
	}
      i+=l;
    }
}

int
main (int argc, char *argv[])
{
  int i, blk;

  if ((fd = open (DSPDEV, O_RDWR, 0)) == -1)
    {
      perror (DSPDEV);
      exit (-1);
    }

  reload ();

  close (fd);
  exit (-1);
}
