/* Extended Module Player * Copyright (C) 1996-2001 Claudio Matsuoka and Hipolito Carraro Jr * * This file is part of the Extended Module Player and is distributed * under the terms of the GNU General Public License. See doc/COPYING * for more information. * * $Id: rad_load.c,v 1.9 2001/01/13 19:58:39 claudio Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "load.h" struct rad_instrument { uint8 num; /* Number of instruments that follows */ uint8 reg[11]; /* Adlib registers */ } PACKED; struct rad_file_header { uint8 magic[16]; /* 'RAD by REALiTY!!' */ uint8 version; /* Version in BCD */ uint8 flags; /* bit 7=descr,6=slow-time,4..0=tempo */ } PACKED; int rad_load (FILE * f) { int i, j; struct rad_file_header rfh; struct xxm_event *event; uint8 sid[11]; uint16 ppat[32]; uint8 b, r, c; LOAD_INIT (); fread (&rfh, 1, sizeof (rfh), f); if (strncmp ((char *) rfh.magic, "RAD by REALiTY!!", 16)) return -1; xxh->chn = 9; xxh->bpm = 125; xxh->tpo = rfh.flags & 0x1f; #warning FIXME: tempo setting in RAD modules if (xxh->tpo <= 2) xxh->tpo = 6; xxh->smp = 0; sprintf (xmp_ctl->type, "RAD %d.%d", MSN (rfh.version), LSN (rfh.version)); sprintf (tracker_name, "Reality Adlib Tracker"); MODULE_INFO (); /* Read description */ if (rfh.flags & 0x80) { if (V (1)) report ("|"); for (j = 0; fread (&b, 1, 1, f) && b;) if (V (1)) { if (!j && (b == 1)) { report ("\n|"); j = 1; } else if (b < 0x20) for (i = 0; !j && (i < b); i++) report (" "); else if (b < 0x80) j = 0, report ("%c", b); else j = 0, report ("."); } if (V (1)) report ("\n"); } if (V (1)) { report ( " Modulator Carrier Common\n" " Char Fr LS OL At De Su Re WS Char Fr LS OL At De Su Re WS Fbk Alg\n"); } /* Read instruments */ for (; fread (&b, 1, 1, f) && b;) { if (!b) break; xxh->ins = b; fread (sid, 1, 11, f); xmp_cvt_hsc2sbi (sid); if (V (1)) { report ("[%2X] ", b - 1); report ("%c%c%c%c %2d ", sid[0] & 0x80 ? 'a' : '-', sid[0] & 0x40 ? 'v' : '-', sid[0] & 0x20 ? 's' : '-', sid[0] & 0x10 ? 'e' : '-', sid[0] & 0x0f); report ("%2d %2d ", sid[2] >> 6, sid[2] & 0x3f); report ("%2d %2d ", sid[4] >> 4, sid[4] & 0x0f); report ("%2d %2d ", sid[6] >> 4, sid[6] & 0x0f); report ("%2d ", sid[8]); report ("%c%c%c%c %2d ", sid[1] & 0x80 ? 'a' : '-', sid[1] & 0x40 ? 'v' : '-', sid[1] & 0x20 ? 's' : '-', sid[1] & 0x10 ? 'e' : '-', sid[1] & 0x0f); report ("%2d %2d ", sid[3] >> 6, sid[3] & 0x3f); report ("%2d %2d ", sid[5] >> 4, sid[5] & 0x0f); report ("%2d %2d ", sid[7] >> 4, sid[7] & 0x0f); report ("%2d ", sid[9]); report ("%2d %2d\n", sid[10] >> 1, sid[10] & 0x01); } xmp_drv_loadpatch (f, b - 1, 0, 0, NULL, sid); } INSTRUMENT_INIT (); for (i = 0; i < xxh->ins; i++) { xxi[i] = calloc (sizeof (struct xxm_instrument), 1); xxih[i].nsm = 1; xxi[i][0].vol = 0x40; xxi[i][0].pan = 0x80; xxi[i][0].xpo = -1; xxi[i][0].sid = i; } /* Read orders */ fread (&b, 1, 1, f); for (i = 0, j = xxh->len = b; j--; i++) { fread (&xxo[i], 1, 1, f); xxo[i] &= 0x7f; /* FIXME: jump line */ } /* Read pattern pointers */ for (xxh->pat = i = 0; i < 32; i++) { fread (&ppat[i], 1, 2, f); L_ENDIAN16 (ppat[i]); if (ppat[i]) xxh->pat++; } xxh->trk = xxh->pat * xxh->chn; if (V (0)) { report ("Module length : %d patterns\n", xxh->len); report ("Instruments : %d\n", xxh->ins); report ("Stored patterns: %d ", xxh->pat); } PATTERN_INIT (); /* Read and convert patterns */ for (i = 0; i < xxh->pat; i++) { PATTERN_ALLOC (i); xxp[i]->rows = 64; TRACK_ALLOC (i); fseek (f, ppat[i], SEEK_SET); do { fread (&r, 1, 1, f); /* Row number */ if ((r & 0x7f) >= 64) report ("** Whoops! row = %d\n", r); do { fread (&c, 1, 1, f); /* Channel number */ if ((c & 0x7f) >= xxh->chn) report ("** Whoops! channel = %d\n", c); event = &EVENT (i, c & 0x7f, r & 0x7f); fread (&b, 1, 1, f); /* Note + Octave + Instrument */ event->ins = (b & 0x80) >> 3; event->note = 13 + (b & 0x0f) + 12 * ((b & 0x70) >> 4); fread (&b, 1, 1, f); /* Instrument + Effect */ event->ins |= MSN (b); if ((event->fxt = LSN (b))) { fread (&b, 1, 1, f); /* Effect parameter */ event->fxp = b; #warning FIXME: tempo setting in RAD modules if (event->fxt == 0x0f && event->fxp <= 2) event->fxp = 6; } } while (~c & 0x80); } while (~r & 0x80); if (V (0)) report ("."); } if (V (0)) report ("\n"); for (i = 0; i < xxh->chn; i++) { xxc[i].pan = 0x80; xxc[i].flg = XXM_CHANNEL_FM; } return 0; }