/* SndBreak by Jesse Burneko
*
* This utility takes files which are already converted to infocom sound
* format but which exceed 65535 bytes in length and breaks them up into
* multiple sound files of 65535 bytes in length or shorter so that they may
* be played in succession.  This utility is useful in conjunction with SOX a
* copy of which may be found at
* ftp://ftp.gmd.de/if-archive/infocom/utilities.  SOX will take many popular
* sound formats such as .WAV and .AU files and convert them into infocom
* format.  However, if the original .wav or .au file exceeds 65535 bytes the
* data will be properly translated but the header info on the resulting .snd
* file will be incorrect.  SndBreak will take the converted file and break it
* up into multiple files attaching a corrected header.
*
* This program is free in so much as that it may be modified and distributed
* freely provided that I, Jesse Burneko, am identified as the original
* author and any modifications are clearly noted.
*
* The syntax of sndbreak is as follows:
*                     sndbreak sndfile
*
* where:
*         sndfile is the .snd file to be broken up and is required.
*
* The output will be placed in a series of files named sound1.snd, sound2.snd
* sound3.snd...soundn.snd.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DATA_LENGTH 0xfff5
#define MAX_FILE_LENGTH 0xffff
#define true 1
#define false 0

void extractfrequency(short *freq, FILE *snd)
{
 char *skip;

 skip = malloc(sizeof(char) * 4);

 fread(skip, 1, 4, snd);
 fread(freq, 1, 2, snd);
 fread(skip, 1, 4, snd);
}

void nextfile(char *filename)
{
 static int count = 0;
 char num[4];

 count++;
 strcpy(filename, "sound");
 sprintf(num, "%d", count);
 strcat(filename, num);
 strcat(filename, ".snd");
}

void writebytes(short freq, unsigned size, char *data)
{
 const char REPEATS = 1;
 const char BASE_NOTE = 60;
 const short DUMMY = 0;

 FILE *tmp;
 char filename[13];
 short flen, dlen;


 nextfile(filename);
 tmp = fopen(filename, "w");
 flen = ((short) size) + 8;
 dlen = (short) size;

 fwrite(&flen, 2, 1, tmp);
 fwrite(&REPEATS, 1, 1, tmp);
 fwrite(&BASE_NOTE, 1, 1, tmp);
 fwrite(&freq, 2, 1, tmp);
 fwrite(&DUMMY, 2, 1, tmp);
 fwrite(&dlen, 2, 1, tmp);
 fwrite(data, 1, size, tmp);
}

FILE *openfile(char *filename)
{
 FILE *tmp;
 char *ptr;

 if((tmp = fopen(filename, "r")) == NULL)
   {
     fprintf(stderr, "Error: Can not open file %s for input.\n", filename);
     exit(1);
   }
 ptr = strrchr(filename, '.');
 if(ptr == NULL || strcmp(ptr, ".snd") != 0)
   {
     fprintf(stderr, "Error: File %s does not have .snd extension.\n", filename);
     exit(1);
   }
 return tmp;
}

void extractparameters(char **infile, int argc, char *argv[])
{
 if(argc == 1)
   {
     fprintf(stderr, "Error: No input file specified.\n");
     exit(1);
   }
 else
   if(argc == 2)
     *infile = argv[1];
   else
   {
     fprintf(stderr, "Error: Too many parameters specified.\n");
     exit(1);
   }
}

int containssnd(char *filename)
{
 char *ptr;

 ptr = strrchr(filename, '.');
 if(ptr == NULL || strcmp(ptr, ".snd") != 0)
   return false;
 else
   return true;
}

void main(int argc, char *argv[])
{
 FILE *snd;
 short frequency;
 unsigned bread;
 char *data;
 char *infile;

 extractparameters(&infile, argc, argv);
 snd = openfile(infile);
 data = malloc(sizeof(char) * MAX_DATA_LENGTH);
 extractfrequency(&frequency, snd);
 while((bread = fread(data, 1, MAX_DATA_LENGTH, snd)) != 0)
   writebytes(frequency, bread, data);
}