home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 August / IMM0895.ISO01.iso / share / os2 / track061 / read.c < prev    next >
Text File  |  1992-11-01  |  11KB  |  505 lines

  1. /* read.c */
  2.  
  3. /* modified by David Nichols for PM MOD player */
  4.  
  5. /* $Author: espie $
  6.  * $Id: read.c,v 2.7 1991/12/03 23:03:39 espie Exp $
  7.  * $Revision: 2.7 $
  8.  * $Log: read.c,v $
  9.  * Revision 2.7  1991/12/03  23:03:39  espie
  10.  * Added transpose feature.
  11.  *
  12.  * Revision 2.6  1991/12/03  21:24:53  espie
  13.  * Feature fix: length 1 sample should be empty.
  14.  *
  15.  * Revision 2.5  1991/12/03  17:10:11  espie
  16.  * Corrected repeat length problems concerning badly formed files,
  17.  * added signature checking for new tracker files.
  18.  *
  19.  * Revision 2.4  1991/11/19  16:07:19  espie
  20.  * Added comments, moved minor stuff around.
  21.  *
  22.  * Revision 2.3  1991/11/18  14:10:30  espie
  23.  * Corrected small problem with repeat being too short.
  24.  *
  25.  * Revision 2.2  1991/11/18  01:10:45  espie
  26.  * Minor corrections.
  27.  *
  28.  * Revision 2.1  1991/11/17  23:07:58  espie
  29.  * Coded error types. More amiga specific stuff.
  30.  *
  31.  * Revision 2.0  1991/11/17  21:42:08  espie
  32.  * New version.
  33.  *
  34.  * Revision 1.17  1991/11/17  16:30:48  espie
  35.  * Forgot to return a song_info from new_song_info
  36.  *
  37.  * Revision 1.16  1991/11/16  15:50:34  espie
  38.  * Tabs.
  39.  *
  40.  * Revision 1.15  1991/11/16  15:42:43  espie
  41.  * Rationnalized error recovery.
  42.  * There was a bug: you could try to deallocate
  43.  * stuff in no-noland. Also, strings never got
  44.  * to be freed.
  45.  *
  46.  * Revision 1.14  1991/11/15  20:57:34  espie
  47.  * Centralized error control to error_song.
  48.  *
  49.  * Revision 1.13  1991/11/15  18:22:10  espie
  50.  * Added a new test on length, aborts most modules now.
  51.  * Maybe should say it as well.
  52.  *
  53.  * Revision 1.12  1991/11/10  16:26:14  espie
  54.  * Nasty bug regarding evaluation order in getulong.
  55.  * Bitten on the sparc.
  56.  *
  57.  * Revision 1.11  1991/11/09  17:47:33  espie
  58.  * Added checkpoints for early return if file too short.
  59.  *
  60.  * Revision 1.10  1991/11/08  13:35:57  espie
  61.  * Added memory recovery and error control.
  62.  *
  63.  * Revision 1.9  1991/11/08  12:37:37  espie
  64.  * Bug in checkfp: should return an int
  65.  * because characters are signed on some machines,
  66.  * and we want to use it as un unsigned value
  67.  * for computing short values.
  68.  *
  69.  * Revision 1.8  1991/11/07  23:29:09  espie
  70.  * Suppressed ! warning for bad note.
  71.  *
  72.  * Revision 1.7  1991/11/07  21:40:16  espie
  73.  * Added note support.
  74.  *
  75.  * Revision 1.6  1991/11/07  20:12:34  espie
  76.  * Minor problem with version id.
  77.  *
  78.  * Revision 1.5  1991/11/07  20:11:10  espie
  79.  * Added embedded version id.
  80.  *
  81.  * Revision 1.4  1991/11/07  15:27:02  espie
  82.  * Added some error control, essentially checkgetc.
  83.  *
  84.  * Revision 1.3  1991/11/05  22:49:03  espie
  85.  * Modified the format of the dump slightly for
  86.  * a better readability.
  87.  *
  88.  * Revision 1.2  1991/11/04  20:27:05  espie
  89.  * Corrected length and rep_length/rep_offset
  90.  * which are given in words and should be converted to
  91.  * bytes.
  92.  *
  93.  * Revision 1.1  1991/11/04  13:23:59  espie
  94.  * Initial revision
  95.  *
  96.  *
  97.  */
  98.  
  99. #include <stdio.h>
  100.  
  101. #define INCL_DOS
  102. #include <os2.h>
  103. #include <string.h>
  104. #include <stdlib.h>
  105.  
  106. #include "defs.h"
  107.  
  108. static int transpose;
  109.  
  110. int find_note (int pitch)
  111. {
  112.   int a, b, i;
  113.  
  114.   if (pitch == 0)
  115.     return -1;
  116.   a = 0;
  117.   b = NUMBER_NOTES - 1;
  118.   while (b - a > 1)
  119.     {
  120.       i = (a + b) / 2;
  121.       if (pitch_table[i] == pitch)
  122.     return i + transpose;
  123.       if (pitch_table[i] > pitch)
  124.     a = i;
  125.       else
  126.     b = i;
  127.     }
  128.   if (pitch_table[a] - FUZZ <= pitch)
  129.     return a + transpose;
  130.   if (pitch_table[b] + FUZZ >= pitch)
  131.     return b + transpose;
  132.   return NO_NOTE;
  133. }
  134.  
  135. /* c = checkgetc(f):
  136.  * gets a character from file f.
  137.  * Aborts program if file f is finished
  138.  */
  139.  
  140. int checkgetc (FILE *f)
  141. {
  142.   int c;
  143.  
  144.   if ((c = fgetc (f)) == EOF)
  145.     error = FILE_TOO_SHORT;
  146.   return c;
  147. }
  148.  
  149. /* s = getstring(f, len):
  150.  * gets a soundtracker string from file f.
  151.  * I.e, it is a fixed length string terminated
  152.  * by a 0 if too short
  153.  */
  154.  
  155. #define MAX_LEN 50
  156.  
  157. char *getstring (FILE *f, int len)
  158. {
  159.   static char s[MAX_LEN];
  160.   char *new = NULL;
  161.   int i;
  162.  
  163.   for (i = 0; i < len; i++)
  164.     s[MIN (i, MAX_LEN - 1)] = checkgetc (f);
  165.   s[MIN (len, MAX_LEN - 1)] = '\0';
  166.    DosAllocMem((PVOID) &new, strlen(s) + 1, PAG_READ|PAG_WRITE|PAG_COMMIT);
  167. /*  new = malloc (strlen (s) + 1); */
  168.  
  169.   return strcpy (new, s);
  170. }
  171.  
  172. /* byteskip(f, len)
  173.  * same as fseek, xcpt it works on stdin
  174.  */
  175.  
  176. void byteskip (FILE *f, int len)
  177. {
  178.   int i;
  179.  
  180.   for (i = 0; i < len; i++)
  181.     checkgetc (f);
  182. }
  183.  
  184. /* v = getushort(f)
  185.  * reads an unsigned short from f
  186.  */
  187.  
  188. int getushort (FILE *f)
  189. {
  190.   int i;
  191.  
  192.   i = checkgetc (f) << 8;
  193.   return i | checkgetc (f);
  194. }
  195.  
  196. void fill_sample_info (struct sample_info *info, FILE *f)
  197. {
  198.   info->name = getstring (f, 22);
  199.   info->length = getushort (f);
  200.   info->finetune = checkgetc (f);
  201.   info->volume = checkgetc (f);
  202.   info->volume = MIN (info->volume, MAX_VOLUME);
  203.   info->rp_offset = getushort (f);
  204.   info->rp_length = getushort (f);
  205.  
  206.   /* the next check is for old modules for which
  207.    * the sample data types are a bit confused, so
  208.    * that what we were expecting to be #words is #bytes.
  209.    */
  210.   /* not sure I understand the -1 myself, though it's
  211.    * necessary to play kawai-k1 correctly
  212.    */
  213.   if (info->rp_length + info->rp_offset - 1 > info->length)
  214.     info->rp_offset /= 2;
  215.  
  216.   if (info->rp_length + info->rp_offset > info->length)
  217.     info->rp_length = info->length - info->rp_offset;
  218.  
  219.   info->length *= 2;
  220.   info->rp_offset *= 2;
  221.   info->rp_length *= 2;
  222.   /* in all logic, a 2-sized sample could exist,
  223.    * but this is not the case, and even so, some
  224.    * trackers output empty instruments as being 2-sized.
  225.    */
  226.   if (info->length <= 2)
  227.     return;
  228.  
  229.   info->start = (SAMPLE *) calloc (info->length, 1);
  230.  
  231.   if (info->rp_length > 2)
  232.     info->rp_start = info->start + info->rp_offset;
  233.   else
  234.     info->rp_start = NULL;
  235.  
  236.   if (info->length > MAX_SAMPLE_LENGTH)
  237.     error = CORRUPT_FILE;
  238. }
  239.  
  240. void fill_song_info (struct song_info *info, FILE *f)
  241. {
  242.   int i;
  243.   int p;
  244.  
  245.   info->length = checkgetc (f);
  246.   checkgetc (f);
  247.   info->maxpat = -1;
  248.   for (i = 0; i < NUMBER_PATTERNS; i++)
  249.     {
  250.       p = getc (f);
  251.       if (p >= NUMBER_PATTERNS)
  252.     p = 0;
  253.       if (p > info->maxpat)
  254.     info->maxpat = p;
  255.       info->patnumber[i] = p;
  256.     }
  257.   info->maxpat++;
  258.   if (info->maxpat == 0 || info->length == 0)
  259.     error = CORRUPT_FILE;
  260. }
  261.  
  262. void fill_event(struct event *e, FILE *f)
  263. {
  264.   int a, b, c, d;
  265.  
  266.   a = checkgetc (f);
  267.   b = checkgetc (f);
  268.   c = checkgetc (f);
  269.   d = checkgetc (f);
  270.   e->sample_number = (a & 0x10) | (c >> 4);
  271.   e->effect = c & 0xf;
  272.   e->parameters = d;
  273.   e->pitch = ((a & 15) << 8) | b;
  274.   e->note = find_note (e->pitch);
  275. }
  276.  
  277. void fill_pattern (struct block *pattern, FILE *f)
  278. {
  279.   int i, j;
  280.  
  281.   for (i = 0; i < BLOCK_LENGTH; i++)
  282.     for (j = 0; j < NUMBER_TRACKS; j++)
  283.       fill_event (&(pattern->e[j][i]), f);
  284. }
  285.  
  286. void read_sample (struct sample_info *info, FILE *f)
  287. {
  288.   if (info->start)
  289.     {
  290.       fread (info->start, 1, info->length, f);
  291.     }
  292. }
  293.  
  294. /***
  295.  *
  296.  *  new_XXX: allocates a new structure for a song.
  297.  *  clears each and every field as appropriate.
  298.  *
  299.  ***/
  300.  
  301. struct song *new_song (void)
  302. {
  303.   struct song *new;
  304.   int i;
  305.  
  306.    DosAllocMem((PVOID)&new, sizeof (struct song), PAG_READ|PAG_WRITE|PAG_COMMIT);
  307. /*  new = (struct song *) malloc (sizeof (struct song)); */
  308.  
  309.   new->title = NULL;
  310.   new->info = NULL;
  311.   for (i = 0; i < NUMBER_SAMPLES; i++)
  312.     new->samples[i] = NULL;
  313.   return new;
  314. }
  315.  
  316. struct sample_info *new_sample_info (void)
  317. {
  318.   struct sample_info *new;
  319.  
  320.    DosAllocMem((PVOID)&new, sizeof(struct sample_info), PAG_READ|PAG_WRITE|PAG_COMMIT);
  321. /*  new = (struct sample_info *) malloc (sizeof (struct sample_info)); */
  322.  
  323.   new->name = NULL;
  324.   new->length = NULL;
  325.   new->start = NULL;
  326.   new->rp_start = NULL;
  327.   return new;
  328. }
  329.  
  330. struct song_info *new_song_info (void)
  331. {
  332.   struct song_info *new;
  333.  
  334.    DosAllocMem((PVOID)&new, sizeof(struct song_info), PAG_READ|PAG_WRITE|PAG_COMMIT);
  335. /*  new = (struct song_info *) malloc (sizeof (struct song_info)); */
  336.  
  337.   new->length = 0;
  338.   new->maxpat = -1;
  339.   new->pblocks = NULL;
  340.   return new;
  341. }
  342.  
  343. /* release_song(song): gives back all memory
  344.  * occupied by song. Assume that each structure
  345.  * has been correctly allocated by a call to the
  346.  * corresponding new_XXX function.
  347.  */
  348. void release_song (struct song *song)
  349. {
  350.   int i;
  351.  
  352.   for (i = 0; i < 31; i++)
  353.     {
  354.       if (song->samples[i])
  355.     {
  356.       if (song->samples[i]->start)
  357.         DosFreeMem(song->samples[i]->start);
  358. /*        free (song->samples[i]->start); */
  359.       if (song->samples[i]->name)
  360.           DosFreeMem(song->samples[i]->name);
  361. /*        free (song->samples[i]->name); */
  362.       DosFreeMem(song->samples[i]);
  363. /*      free (song->samples[i]); */
  364.     }
  365.     }
  366.   if (song->info)
  367.     {
  368.       if (song->info->pblocks)
  369.     DosFreeMem(song->info->pblocks);
  370. /*    free (song->info->pblocks); */
  371.       DosFreeMem(song->info);
  372. /*      free (song->info); */
  373.     }
  374.   if (song->title)
  375.       DosFreeMem(song->title);
  376. /*    free (song->title); */
  377.    DosFreeMem(song);
  378. /*  free (song); */
  379. }
  380.  
  381. /* error_song(song): what we should return
  382.  * if there was an error. Actually, is mostly
  383.  * useful for its side effects.
  384.  */
  385. struct song *error_song (struct song *song)
  386. {
  387.   release_song (song);
  388.   return NULL;
  389. }
  390.  
  391. /* bad_sig(f): read the signature on file f
  392.  * and returns !0 if it is not a known sig.
  393.  */
  394. int bad_sig (FILE *f)
  395. {
  396.   char a, b, c, d;
  397.  
  398.   a = fgetc (f);
  399.   b = fgetc (f);
  400.   c = fgetc (f);
  401.   d = fgetc (f);
  402.   if (a == 'M' && b == '.' && c == 'K' && d == '.')
  403.     return 0;
  404.   if (a == 'M' && b == '&' && c == 'K' && d == '!')
  405.     return 0;
  406.   if (a == 'F' && b == 'L' && c == 'T' && d == '4')
  407.     return 0;
  408.   return 1;
  409. }
  410.  
  411. /* s = read_song(f, type): tries to read a song s
  412.  * of type NEW/OLD in file f. Might fail, i.e.,
  413.  * returns NULL if file is not a mod file of the
  414.  * correct type.
  415.  */
  416. struct song *read_song (FILE *f, int type, int tr)
  417. {
  418.   struct song *song;
  419.   int i;
  420.   int ninstr;
  421.  
  422.   error = NONE;
  423.   transpose = tr;
  424.   if (type == NEW || type == NEW_NO_CHECK)
  425.     ninstr = 31;
  426.   else
  427.     ninstr = 15;
  428.  
  429.   song = new_song ();
  430.   song->title = getstring (f, 20);
  431.   if (error != NONE)
  432.     return error_song (song);
  433.  
  434.   for (i = 0; i <= 31; i++)
  435.     song->samples[i] = new_sample_info ();
  436.  
  437.   for (i = 1; i <= ninstr; i++)
  438.     {
  439.       fill_sample_info (song->samples[i], f);
  440.       if (error != NONE)
  441.     return error_song (song);
  442.     }
  443.   song->info = new_song_info ();
  444.  
  445.   fill_song_info (song->info, f);
  446.  
  447.   if (error != NONE)
  448.     return error_song (song);
  449.  
  450.   if (type == NEW && bad_sig (f))
  451.     return error_song (song);
  452.  
  453.   if (type == NEW_NO_CHECK)
  454.     byteskip (f, 4);
  455.  
  456.  
  457.   DosAllocMem((PVOID)&song->info->pblocks, sizeof (struct block) * song->info->maxpat,
  458.     PAG_READ|PAG_WRITE|PAG_COMMIT);
  459. /* song->info->pblocks = (struct block *)malloc(sizeof(struct block) * song->info->maxpat); */
  460.   for (i = 0; i < song->info->maxpat; i++)
  461.     {
  462.       fill_pattern (song->info->pblocks + i, f);
  463.       if (error != NONE)
  464.     return error_song (song);
  465.     }
  466.  
  467.   for (i = 1; i <= ninstr; i++)
  468.     read_sample (song->samples[i], f);
  469.  
  470.   if (error != NONE)
  471.     return error_song (song);
  472.   return song;
  473. }
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.