home *** CD-ROM | disk | FTP | other *** search
- /*
- * load_mod.c - Loads standard Protracker modules.
- *
- * (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
- */
-
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/soundcard.h>
- #include <sys/ultrasound.h>
- #include <limits.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "mod.h"
-
- /* External global variables */
-
- SEQ_DECLAREBUF();
- extern int seqfd, gus_dev;
-
- extern struct mod_info M;
- extern struct options opt;
-
- extern char quit;
-
- extern int periodtable[NR_OCTAVES*12];
- extern char effect_used[NR_EFX];
-
- /* Local functions */
- static int process_header(char *);
- static int read_patterndata(int);
-
- /* Defines and variables used while loading module */
-
- #define MOD31_NAME 0
- #define MOD31_SAMPLEINFO 20
- #define MOD31_SONGLENGTH 950
- #define MOD31_RESTARTPOS 951
- #define MOD31_PATTERNTABLE 952
- #define MOD31_MAGIC 1080
- #define MOD31_PATTERNDATA 1084
-
- #define MOD31_SAMPLEINFO_SIZE 30
-
- static int expected_length, OS15;
-
-
- int load_mod(int fd)
- {
- unsigned char buf[MOD31_PATTERNDATA];
- char tmpbuf[80];
-
- int i, diff, fatalerr, tmp;
-
- /* The following might fail if the total length of a 15 instrument
- * module is less than MOD31_PATTERNDATA, but that is very
- * unlikely.
- */
- if(read(fd, buf, MOD31_PATTERNDATA) != MOD31_PATTERNDATA) {
- info("Unable to read header from file.\n");
- return 0;
- }
-
- if(!process_header(buf))
- return 0;
-
- /* As a 15 instrument modules has no tag, a -4 offset is needed in
- * that case.
- */
- if(lseek(fd, MOD31_PATTERNDATA+OS15+(OS15 ? -4 : 0), SEEK_SET)
- == -1) {
- info("Unable to read patterndata.\n");
- return 0;
- }
-
- if(!read_patterndata(fd)) {
- info("Unable to read patterndata.\n");
- return 0;
- }
-
- ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev);
-
- tmp=0;
- for(i=1; i <=M.nr_samples; ++i)
- if(M.sample[i].length > 4)
- tmp++;
-
- info("\nUploading instruments to GUS...\n");
-
- fatalerr=0;
- for(i=1; i <= M.nr_samples; ++i) {
- if(M.sample[i].length > 4) { /* Only load non-silent samples */
- if(!read_and_upload_sample(fd, i)) {
- fatalerr=1;
- break;
- }
- }
- else { /* Skip sample */
- if(lseek(fd, M.sample[i].length, SEEK_CUR) == -1){
- fatalerr=1;
- break;
- }
- }
- if(quit == QUIT_SIGNAL) /* Bail out if we got QUIT_SIGNAL */
- return 0;
- }
-
- if(fatalerr) {
- diff=expected_length-lseek(fd, 0, SEEK_CUR);
- sprintf(tmpbuf, "File %d bytes short", diff);
- print_status(tmpbuf);
- info("\nShort file (%d bytes missing).\n", diff);
- sleep(1);
- return 0;
- }
-
- /* Check if filelength was as expected. This is done with two
- * statements to make sure we don't move the filepointer to the
- * end before checking current position.
- */
-
- diff=-lseek(fd, 0, SEEK_CUR);
- diff+=lseek(fd, 0, SEEK_END);
-
- if(diff) {
- if(diff > 1024*64) {
- print_status("Too many garbagebytes");
- sleep(1);
- return 0;
- }
- else {
- sprintf(tmpbuf, "Found %d garbagebytes", diff);
- print_status(tmpbuf);
- sleep(1);
- }
-
- info("\nFound %d garbagebytes after samples. Ignoring.\n", diff);
- }
-
- print_songname(M.name);
- print_samples(1);
- print_songinfo(M.nr_voices, tmp, "MOD", expected_length,
- M.songlength, M.nr_patterns);
-
- return 1;
- }
-
-
- static int process_header(char *buf)
- {
- char tmpch, *p, typebuf[16], tmpbuf[80];
- int i, tmp;
- struct sample_info *s;
-
- M.nr_tracks=0;
- M.nr_voices=4; /* Default to 4-channel 31 sample module */
- M.nr_samples=31;
- OS15=0;
-
-
- if(!strncmp((char *)&buf[MOD31_MAGIC], "M.K.", 4)) {
- sprintf(typebuf, "M.K.");
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "M!K!", 4)) {
- sprintf(typebuf, "M!K!");
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "FLT4", 4)) {
- sprintf(typebuf, "FLT4");
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "4CHN", 4)) {
- sprintf(typebuf, "4CHN");
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "6CHN", 4)) {
- sprintf(typebuf, "6CHN");
- M.nr_voices=6;
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "8CHN", 4)) {
- sprintf(typebuf, "8CHN");
- M.nr_voices=8;
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "16CH", 4)) {
- sprintf(typebuf, "16CH"); /* Take Tracker */
- M.nr_voices=16;
- }
- else if(!strncmp((char *)&buf[MOD31_MAGIC], "32CH", 4)) {
- sprintf(typebuf, "32CH"); /* Take Tracker */
- M.nr_voices=32;
- }
- else {
- sprintf(typebuf, "15 sample");
- info("No known tag found, trying 15 instrument module.\n");
- M.nr_samples=15;
- OS15=-16*MOD31_SAMPLEINFO_SIZE; /* Modifier for 15 instrument module */
- }
-
- sprintf(tmpbuf, "Loading MOD (%s)", typebuf);
- print_status(tmpbuf);
- info("Type: '%s'\n", typebuf);
-
- M.sample=(struct sample_info *)malloc((1+M.nr_samples)*
- sizeof(struct sample_info));
-
- strncpy(M.name, &buf[MOD31_NAME], 20);
- M.name[20]=0;
- fix_string(M.name);
-
- M.songlength=buf[MOD31_SONGLENGTH+OS15];
- M.restartpos=buf[MOD31_RESTARTPOS+OS15];
-
- if(!M.songlength || M.songlength > 127)
- return 0;
-
- memcpy(M.patterntable, &buf[MOD31_PATTERNTABLE+OS15], 128);
-
- print_sample_info_header();
-
- expected_length=0; /* Start counting expected filesize */
- p=&buf[MOD31_SAMPLEINFO];
-
-
- /* Here we make extra checks for 15 instrument modules, as this is where
- * we get if we try to load something not supported, or something not
- * a module.
- */
-
- for(i=1; i <= M.nr_samples; ++i) {
- s=&M.sample[i];
- s->valid=0; /* Valid isn't set to TRUE until it's
- * sampledata has been read.
- */
- strncpy(s->name, p, 22);
- s->name[22]=0;
- p+=22;
- fix_string(s->name);
-
- s->length=SWAPSHORT(p)*2;
- p+=2;
-
- tmpch=(*p++&0x0f);
- s->finetune=(tmpch > 7 ? tmpch|0xf0 : tmpch);
-
- s->volume=*(unsigned char *)p++;
-
- if(s->volume > 64 && M.nr_samples == 15 && !opt.tolerant)
- return 0; /* Bail */
-
- tmp=SWAPSHORT(p)*2; /* Repeat start */
- p+=2;
- if(s->length && (tmp < 0 || tmp >= s->length)) {
- tmp=0;
- }
- s->repeat_start=tmp;
-
- /* -1 as the sample at repeat_end is played */
- tmp+=SWAPSHORT(p)*2-1;
- p+=2;
-
- if(tmp < s->repeat_start+2)
- tmp=s->repeat_start+1; /* turn off looping */
- else if(tmp >= s->length)
- tmp=s->length-1; /* truncate loop-end */
-
- s->repeat_end=tmp;
-
- if(s->repeat_end > s->repeat_start+1)
- s->looped=LOOP_FORWARD;
- else
- s->looped=0;
-
- s->bits_16=0;
- s->unsigned_data=0;
-
- expected_length+=s->length;
-
- s->c2freq=-1; /* Use PAL/NTSC */
-
- print_sample_info(i);
- }
-
- p=&buf[MOD31_PATTERNTABLE+OS15];
- for(i=0, tmp=0; i <= 127; ++i) {
- M.patterntable[i]=p[i];
- if(p[i] > tmp)
- tmp=p[i];
- }
- M.nr_patterns=++tmp;
-
- if(M.nr_patterns > 127)
- return 0;
-
- if(M.restartpos >= M.songlength)
- M.restartpos=0;
-
- info("\nVoices: %d Patterns: %d Songlength: %d",
- M.nr_voices, M.nr_patterns, M.songlength);
- if(M.restartpos)
- info(" Restartpos: %d\n", M.restartpos);
- else
- info("\n");
-
- for(i=0; i < M.nr_voices; ++i)
- M.panning[i]=get_voice_balance(i);
-
- expected_length+=MOD31_PATTERNDATA+OS15+(OS15 ? -4 : 0)+
- M.nr_patterns*1024;
-
- M.volrange=64;
-
- if(expected_length > 2*1024*1024) /* Sanity check */
- return 0;
-
- return 1;
- }
-
-
- static int read_patterndata(int fd)
- {
- unsigned char buf[4*64*32]; /* 4 bytes, 64 lines, MAX 32 channels */
- unsigned char tmp;
- unsigned int period;
- struct event *e;
- int p, l, v, pos, hinote, lonote;
- struct event events[64*32]; /* 64 lines, 32 channels = 1 pattern */
- struct event *track;
-
- hinote=0;
- lonote=255;
-
- for(v=0; v < NR_EFX; ++v)
- effect_used[v]=0;
-
- for(v=0; v < M.nr_voices; ++v)
- M.track_idx[v]=(int *)malloc(M.nr_patterns*sizeof(int));
-
- /* Allocate for worst case (no identical tracks) */
- M.tracks=(struct event **)malloc(M.nr_patterns*M.nr_voices*
- sizeof(struct event *));
-
- for(p=0; p < M.nr_patterns; ++p) {
- if(read(fd, buf, 4*64*M.nr_voices) != 4*64*M.nr_voices)
- return 0;
- pos=0;
- track=events;
- for(l=0; l < 64; ++l, track++) {
- for(v=0; v < M.nr_voices; ++v) {
- e=&track[v*64];
-
- e->sample=
- (buf[pos]&0xf0)|((buf[pos+2]>>4)&0x0f);
- tmp=buf[pos+2]&0x0f;
- if(tmp != 0x0e) {
- e->arg=buf[pos+3];
- }
- else {
- tmp=0x10|((buf[pos+3]>>4)&0x0f);
- e->arg=buf[pos+3]&0x0f;
- }
- e->effect=tmp;
-
- if(tmp || e->arg)
- effect_used[tmp]=1;
-
- period=((buf[pos]&0x0f)<<8)|buf[pos+1];
- /* period*4 as we convert X-2 >= X-4 */
- e->note=
- (period ? period2note(period*4) : 0);
-
- if(e->note < BASE_NOTE+2*12 || e->note >= BASE_NOTE+7*12)
- e->note=0; /* Catch any garbage notes */
-
- /* Clear the second effect */
- e->effect2=e->arg2=0;
-
- if(e->note) {
- hinote=MAX(hinote, e->note);
- lonote=MIN(lonote, e->note);
- }
- pos+=4;
- }
- }
- /* Convert pattern to tracks */
- for(v=0; v < M.nr_voices; ++v)
- M.track_idx[v][p]=get_track_idx(&events[v*64]);
- }
-
- if(!opt.low_note) { /* Determine if we should allow octave 0 and 4 */
- if(lonote < BASE_NOTE+3*12 || hinote > BASE_NOTE+6*12-1) {
- opt.low_note=BASE_NOTE+2*12;
- opt.high_note=BASE_NOTE+7*12-1;
- }
- else {
- opt.low_note=BASE_NOTE+3*12;
- opt.high_note=BASE_NOTE+6*12-1;
- }
- }
- else { /* Warn user if he made an invalid choice */
- if(hinote > opt.high_note || lonote < opt.low_note)
- info("Warning: Module contains notes in other octaves than"
- " the allowed.\n It might be played"
- " incorrectly.\n");
- }
-
- print_used_effects();
-
- return 1;
- }
-
-
- /* Balance: 0 is left, 15 is right.
- */
-
- int get_voice_balance(int v)
- {
- static char bal[]={1, 14, 14, 1};
-
- if(M.format == MODFORMAT_ULT)
- return 7;
- else if(M.format == MODFORMAT_MTM)
- return (v%2 ? 12 : 4);
- else if(opt.mono || (M.nr_voices%4))
- return 7; /* Default to centered */
- else
- return bal[v%4];
- }
-