/* mkmidi.c - by Gary Snethen (xeno@iastate.edu) 11/11/93     */
/* This program takes a raw midi data dump, extracts all      */
/* system exclusive messages, and saves these to a MID midi   */
/* file.  This version is poorly documented.                  */

#include <stdio.h>

#define MAX_BUFFER 20000
#define MAX_SYSEX 20000

main(int argc, char *argv[])
{
  int i=0, j=0, imax=0, jmax=0, c, k, count=0;
  int num[4];
  FILE *in, *out;
  char buffer[MAX_BUFFER];
  char sysex[MAX_SYSEX];
  static char header[] =
  { 'M','T','h','d', 0,0,0,6, 0,0, 0,1, 0,0x60,
    'M','T','r','k', 0, 0, 0, 0 };
  static char trailer[] =
  { 0x00, 0xff, 0x2f, 0x00 };

  if (argc != 3) {
    printf("usage: %s <sys-ex file in> <MIDI file out>\n",argv[0]);
    exit(0);
  }

  in = fopen(argv[1], "rb");
  out = fopen(argv[2],"wb");
  if (!in || !out) {
    printf("error:  cannot open file(s)!\n");
    exit(0);
  }

  for (i=0; i<22; i++) {
    buffer[i] = header[i];
  }

  do {
    c = fgetc(in);
    if (c == 0xf0) {
      buffer[i++] = 0x00;
      buffer[i++] = 0xf0;
      j = 0;
      do {
        c = fgetc(in);
        sysex[j++] = c;
        if (j >= MAX_SYSEX) {
          printf("error: input sys-ex exceeded maximum size of %d bytes!\n",
                 MAX_SYSEX);
          exit(0);
        }
      } while (c != 0xf7 && c != EOF);
      jmax = j;
      num[3] = j & 0x7f;
      j = j >> 7;
      k = 2;
      while (j) {
        num[k] = (j & 0x7f) | 0x80;
        j = j >> 7;
        k--;
      }
      if (c == 0xf7) {
        if (i+4+jmax >= MAX_BUFFER) {
          printf("error: output file exceeded maximum size of %d bytes!\n",
                 MAX_BUFFER);
          exit(0);
        }
        for (k++;k<4;k++)
          buffer[i++] = num[k];
        for (j=0;j<jmax;j++)
          buffer[i++] = sysex[j];
        printf("system exclusive found: %d bytes.\n",jmax+1);
        count++;
      } else {
        printf("warning: incomplete system exclusive found -- ignored.\n");
      }
    }
  } while (c != EOF);

/* End of track */
  buffer[i++] = 0;
  buffer[i++] = 0xff;
  buffer[i++] = 0x2f;
  buffer[i++] = 0x00;

  j = 21;
  imax = i;
  i = i - 22;
  for (;i;j--) {
    buffer[j] = i;
    i = i >> 8;
  }
  fwrite(buffer,1,imax,out);
  if (count) {
    printf("%d system exclusives found and successfully converted.\n", count);
  } else {
    printf("warning: no complete system exclusives found.\n");
  }
  fclose(in);
  fclose(out);
}
