home *** CD-ROM | disk | FTP | other *** search
- /*
- * load.c - Handles uncompressing and calls loaders for different formats.
- *
- * (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 <sys/stat.h>
- #include <fcntl.h>
- #include <sys/soundcard.h>
- #include <sys/ultrasound.h>
- #include <limits.h>
- #include <string.h>
- #include <ctype.h>
- #include <assert.h>
-
- #include "mod.h"
-
- /* External global variables */
-
- SEQ_DECLAREBUF();
- extern int seqfd, gus_dev;
-
- extern struct mod_info M;
- extern struct options opt;
-
- extern int periodtable[NR_OCTAVES*12];
- extern char effect_used[NR_EFX], *effectnames[NR_EFX], workdir[PATH_MAX+1];
-
- /* Constants */
-
- #define COMPRESSED_GZIP 1
- #define COMPRESSED_LHA 2
- #define COMPRESSED_ZIP 3
- #define COMPRESSED_ARJ 4
-
- /* Loads a module and returns nonzero if M is valid after loading
- * Directory may or may not be equal to workdir upon exit.
- */
-
- int load_module(void)
- {
- int fd, i, tmp, suffix, filetype;
- char buf[PATH_MAX+1]; /* Should actually be a little long but... */
-
- suffix=filetype=0;
-
- /* Set M.filename to modname w/o path */
- tmp=strlen(M.real_filename);
- for(i=tmp-1; i >= 0 && M.real_filename[i] != '/'; )
- --i;
-
- strcpy(M.filename, &M.real_filename[++i]);
- tmp=strlen(M.filename);
-
- if(tmp > 2) {
- if(!strcmp(M.filename+tmp-2, ".z") ||
- !strcmp(M.filename+tmp-2, ".Z")) {
- filetype=COMPRESSED_GZIP;
- suffix=2;
- }
- }
- if(tmp > 3) {
- if(!strcmp(M.filename+tmp-3, ".gz")) {
- filetype=COMPRESSED_GZIP;
- suffix=3;
- }
- }
- if(tmp > 4) {
- if(!strcmp(M.filename+tmp-4, ".lha") ||
- !strcmp(M.filename+tmp-4, ".lzh")) {
- filetype=COMPRESSED_LHA;
- suffix=4;
- }
- else if(!strcmp(M.filename+tmp-4, ".zip")) {
- filetype=COMPRESSED_ZIP;
- suffix=4;
- }
- else if(!strcmp(M.filename+tmp-4, ".arj")) {
- filetype=COMPRESSED_ARJ;
- suffix=4;
- }
- }
-
- M.filename[tmp-suffix]=0; /* Remove suffix */
-
- /* Make sure the file exists by opening and closing the file */
- if(!(fd=open(M.real_filename, O_RDONLY, 0))) {
- print_status("File does not exist");
- info("Unable to open file '%s'.\n", M.real_filename);
- sleep(1);
- return 0;
- }
- close(fd);
-
- /* Print status if we are uncompressing */
- switch(filetype) {
- case COMPRESSED_GZIP:
- case COMPRESSED_LHA:
- case COMPRESSED_ZIP:
- case COMPRESSED_ARJ:
- print_status("Uncompressing module");
- info("Uncompressing module... ");
- break;
- default:
- }
-
- /* Prepare uncompress command */
- switch(filetype) {
- case COMPRESSED_GZIP:
- sprintf(buf, GZIP_COMMAND "%s > " TMP_DIR "/%s 2>/dev/null "
- "< /dev/null",
- escape_name(M.real_filename, 0), escape_name(M.filename, 1));
- break;
- case COMPRESSED_LHA:
- guess_lha_filename();
- chdir(TMP_DIR);
- sprintf(buf, LHA_COMMAND "%s/%s %s >& /dev/null < /dev/null",
- workdir, escape_name(M.real_filename, 0),
- escape_name(M.filename, 1));
- break;
- case COMPRESSED_ZIP:
- guess_zip_filename();
- chdir(TMP_DIR);
- sprintf(buf, ZIP_COMMAND "%s/%s %s >& /dev/null < /dev/null",
- workdir, escape_name(M.real_filename, 0),
- escape_name(M.filename, 1));
- break;
- case COMPRESSED_ARJ:
- guess_arj_filename();
- chdir(TMP_DIR);
- sprintf(buf, ARJ_COMMAND "%s/%s >& /dev/null < /dev/null",
- workdir, escape_name(M.real_filename, 0));
- break;
- default:
- }
-
- /* Uncompress and open file */
- switch(filetype) {
- case COMPRESSED_GZIP:
- case COMPRESSED_LHA:
- case COMPRESSED_ZIP:
- case COMPRESSED_ARJ:
- tmp=my_system(buf);
- sprintf(buf, TMP_DIR "/%s", M.filename);
- if(tmp) {
- unlink(buf);
- if(tmp > 0) {
- print_status("Error uncompressing");
- sleep(1);
- }
- return 0;
- }
-
- /* Open uncompressed module */
- if((fd=open(buf, O_RDONLY, 0)) == -1) {
- info("Unable to open file '%s'.\n", buf);
- return 0;
- }
- break;
- default: /* Assume non-compressed module */
- if((fd=open(M.real_filename, O_RDONLY, 0)) == -1) {
- print_status("File does not exist");
- info("Unable to open file '%s'.\n", M.real_filename);
- sleep(1);
- return 0;
- }
- }
-
- /* Here and forward buf should contain the name of the temp-file */
- chmod(buf, 0777); /* a+rwx */
-
- /* Try to determine module-format from the filename if needed */
- if(!opt.format) {
- if(strlen(M.filename) > 4) {
- if(is_modtype("mod") || is_modtype("nst"))
- opt.format=MODFORMAT_MOD;
- else if(is_modtype("ult"))
- opt.format=MODFORMAT_ULT;
- else if(is_modtype("mtm"))
- opt.format=MODFORMAT_MTM;
- else if(is_modtype("s3m"))
- opt.format=MODFORMAT_S3M;
- }
- if(!opt.format)
- opt.format=MODFORMAT_MOD; /* Default to MOD-format */
- }
-
- M.format=opt.format;
- M.sample=0;
-
- switch(opt.format) {
- case MODFORMAT_MOD:
- tmp=load_mod(fd); /* MOD */
- break;
- case MODFORMAT_ULT:
- tmp=load_ult(fd); /* ULT */
- break;
- case MODFORMAT_MTM:
- tmp=load_mtm(fd); /* MTM */
- break;
- case MODFORMAT_S3M:
- tmp=load_s3m(fd); /* S3M */
- break;
- default:
- error("Error selecting format.\n");
- }
- close(fd);
-
- if(M.nr_samples && M.sample)
- M.sample[0].valid=0; /* Make sure sample 0 is invalid */
-
- if(filetype) { /* Remove temp-file if module was compressed */
- unlink(buf);
- }
-
- info("\nTracks stored: %d/%d.\n", M.nr_tracks, M.nr_voices*M.nr_patterns);
-
- return tmp; /* Return status from load_xxx */
- }
-
-
- int is_modtype(char *type)
- {
- char buf[5], name[256];
- int i;
-
- strcpy(name, M.filename);
- for(i=0; name[i]; ++i)
- if(isalpha(name[i]) && isupper(name[i]))
- name[i]=tolower(name[i]);
-
- i=strlen(name)-4;
-
- buf[0]='.';
- strcpy(buf+1, type);
- if(!strncmp(name+i, buf, 4)) /* .xxx */
- return 1;
- buf[0]='_';
- if(!strncmp(name+i, buf, 4)) /* _xxx */
- return 1;
-
- strcpy(buf, type);
- strcat(buf, ".");
- if(!strncmp(name, buf, 4)) /* xxx. */
- return 1;
- buf[3]='_';
- if(!strncmp(name, buf, 4)) /* xxx_ */
- return 1;
-
- return 0;
- }
-
-
- void guess_lha_filename(void)
- {
- char buf[PATH_MAX+1], name[PATH_MAX+1];
- int size;
- FILE *fp;
-
- sprintf(buf, LHA_COMMAND_LIST "%s/%s < /dev/null",
- workdir, M.real_filename);
- if(!(fp=popen(buf, "rb")))
- return;
-
- strcpy(name, M.filename); /* Default to name minus suffix */
- size=0;
-
- /* Find the largest file */
- if(fgets(buf, PATH_MAX, fp) && fgets(buf, PATH_MAX, fp)) {
- while(!feof(fp)) {
- if(!fgets(buf, PATH_MAX, fp))
- break;
- if(strlen(buf) <= 1 || *buf == '-')
- break;
-
- buf[strlen(buf)-1]=0; /* Remove lf */
- if(atoi(&buf[18]) > size) {
- size=atoi(&buf[18]);
- strcpy(name, &buf[46]);
- }
- }
- }
- pclose(fp);
- strcpy(M.filename, name);
- }
-
-
- void guess_zip_filename(void)
- {
- char buf[PATH_MAX+1], name[PATH_MAX+1];
- int size;
- FILE *fp;
-
- sprintf(buf, ZIP_COMMAND_LIST "%s/%s 2> /dev/null < /dev/null",
- workdir, M.real_filename);
- if(!(fp=popen(buf, "rb")))
- return;
-
- strcpy(name, M.filename); /* Default to name minus suffix */
- size=0;
-
- /* Find the largest file */
- if(fgets(buf, PATH_MAX, fp) && fgets(buf, PATH_MAX, fp)) {
- while(!feof(fp)) {
- if(!fgets(buf, PATH_MAX, fp))
- break;
- if(strlen(buf) <= 3 || !strncmp(buf, " -", 2))
- break;
-
- buf[strlen(buf)-1]=0; /* Remove lf */
- if(atoi(&buf[0]) > size) {
- size=atoi(&buf[0]);
- strcpy(name, &buf[27]);
- }
- }
- }
- pclose(fp);
- strcpy(M.filename, name);
- }
-
-
- void guess_arj_filename(void)
- {
- char buf[PATH_MAX+1], name[PATH_MAX+1];
- int size, i;
- FILE *fp;
-
- sprintf(buf, ARJ_COMMAND_LIST "%s/%s 2> /dev/null < /dev/null",
- workdir, M.real_filename);
- if(!(fp=popen(buf, "rb")))
- return;
-
- strcpy(name, M.filename); /* Default to name minus suffix */
- size=0;
- /* Find the largest file */
- if(fgets(buf, PATH_MAX, fp) && fgets(buf, PATH_MAX, fp) &&
- fgets(buf, PATH_MAX, fp) && fgets(buf, PATH_MAX, fp) &&
- fgets(buf, PATH_MAX, fp) && fgets(buf, PATH_MAX, fp)) {
- while(!feof(fp)) {
- if(!fgets(buf, PATH_MAX, fp))
- break;
- if(strlen(buf) <= 14 || !strncmp(buf, "------------ -", 14))
- break;
-
- buf[strlen(buf)-1]=0; /* Remove lf */
- if(atoi(&buf[13]) > size) {
- size=atoi(&buf[13]);
-
- /* Fix filename, dos-way (8.3) + lowercase for unix unarj */
- strncpy(name, &buf[0], 12);
- for(i=11; i >= 0 && name[i] == ' '; --i)
- ;
- name[++i]=0;
- for(i=0; name[i]; ++i)
- if(isalpha(name[i]) && isupper(name[i]))
- name[i]=tolower(name[i]);
- }
- }
- }
- pclose(fp);
- strcpy(M.filename, name);
- }
-
-
- void print_used_effects(void)
- {
- int v, l;
-
- if(!opt.verbose)
- return;
-
- printf("\nEFX: ");
- l=0;
- for(v=0; v < NR_EFX; ++v)
- if(effect_used[v]) {
- printf("%s ",effectnames[v]);
- ++l;
- }
- printf("\n(# of EFX: %d)\n",l);
- }
-
-
- /* Returns the note corresponding to the supplied period. Not the closest,
- * but the same that PT finds.
- */
-
- unsigned char period2note(unsigned int period)
- {
- int i;
-
- if(period > periodtable[0]) {
- info("Forced to take C-0. PerDiff: %d ", period-periodtable[0]);
- return BASE_NOTE;
- }
-
- if(period < periodtable[NR_OCTAVES*12-1]) {
- info("Forced to take B-9. PerDiff: %d ",
- period-periodtable[NR_OCTAVES*12-1]);
- return BASE_NOTE+NR_OCTAVES*12-1;
- }
-
- for(i=0; i < NR_OCTAVES*12; ++i)
- if(period >= periodtable[i])
- return BASE_NOTE+i;
-
- assert(0); /* never reached */
- return 0; /* removes warning */
- }
-
-
- void free_module(void)
- {
- int i;
-
- for(i=0; i < MAX_VOICES; ++i)
- if(M.track_idx[i])
- free(M.track_idx[i]);
-
- if(M.tracks) {
- for(i=0; i < M.nr_tracks; ++i)
- free(M.tracks[i]);
- free(M.tracks);
- }
-
- if(opt.format == MODFORMAT_ULT && M.songtext)
- free(M.songtext);
-
- if(M.sample)
- free(M.sample);
-
- zero_resources();
- }
-
-
- void zero_resources(void)
- {
- int v;
-
- for(v=0; v < MAX_VOICES; ++v)
- M.track_idx[v]=0;
-
- M.tracks=0;
- M.sample=0;
- M.songtext=0;
- }
-