int xmp_load_module(xmp_context opaque, char *path) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; HIO_HANDLE *h; struct stat st; struct list_head tmpfiles_list; D_(D_WARN "path = %s", path); if (stat(path, &st) < 0) return -XMP_ERROR_SYSTEM; #ifndef _MSC_VER if (S_ISDIR(st.st_mode)) { errno = EISDIR; return -XMP_ERROR_SYSTEM; } #endif if ((h = hio_open_file(path, "rb")) == NULL) return -XMP_ERROR_SYSTEM; INIT_LIST_HEAD(&tmpfiles_list); D_(D_INFO "decrunch"); if (decrunch(&tmpfiles_list, &h->f, &path, DECRUNCH_MAX) < 0) goto err_depack; if (hio_stat(h, &st) < 0) goto err_depack; if (st.st_size < 256) { /* get size after decrunch */ hio_close(h); unlink_tempfiles(&tmpfiles_list); return -XMP_ERROR_FORMAT; } if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); m->dirname = get_dirname(path); if (m->dirname == NULL) return -XMP_ERROR_SYSTEM; m->basename = get_basename(path); if (m->basename == NULL) return -XMP_ERROR_SYSTEM; m->filename = path; /* For ALM, SSMT, etc */ m->size = st.st_size; return load_module(opaque, h, &tmpfiles_list); err_depack: hio_close(h); unlink_tempfiles(&tmpfiles_list); return -XMP_ERROR_DEPACK; }
int xmp_load_typed_module_from_memory(xmp_context opaque, void *mem, long size, const struct format_loader* format) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; HIO_HANDLE *h; int ret; if ((h = hio_open_mem(mem, size)) == NULL) return -XMP_ERROR_SYSTEM; m->filename = NULL; m->basename = NULL; m->size = size; if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); load_prologue(ctx); D_(D_WARN "load"); ret = -XMP_ERROR_FORMAT; if (format->test(h, NULL, 0) == 0) { if ((ret = module_load(h, ctx, format))) xmp_release_module(opaque); } hio_close(h); return ret; }
int xmp_load_module_from_file(xmp_context opaque, void *file, long size) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; HIO_HANDLE *h; FILE *f = fdopen(fileno((FILE *)file), "rb"); int ret; if ((h = hio_open_file(f)) == NULL) return -XMP_ERROR_SYSTEM; if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); m->filename = NULL; m->basename = NULL; m->dirname = NULL; m->size = hio_size(h); ret = load_module(opaque, h); hio_close(h); return ret; }
int xmp_load_module_from_memory(xmp_context opaque, void *mem, long size) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; HIO_HANDLE *h; int ret; /* Use size < 0 for unknown/undetermined size */ if (size == 0) size--; if ((h = hio_open_mem(mem, size)) == NULL) return -XMP_ERROR_SYSTEM; if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); m->filename = NULL; m->basename = NULL; m->dirname = NULL; m->size = size; ret = load_module(opaque, h); hio_close(h); return ret; }
static int load_module(xmp_context opaque, HIO_HANDLE *h, struct list_head *tmpfiles_list) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; int i, ret; int test_result, load_result; load_prologue(ctx); D_(D_WARN "load"); test_result = load_result = -1; for (i = 0; format_loader[i] != NULL; i++) { hio_seek(h, 0, SEEK_SET); test_result = format_loader[i]->test(h, NULL, 0); if (test_result == 0) { hio_seek(h, 0, SEEK_SET); D_(D_WARN "load format: %s", format_loader[i]->name); load_result = format_loader[i]->loader(m, h, 0); break; } } if (test_result == 0 && load_result == 0) set_md5sum(h, m->md5); hio_close(h); if (tmpfiles_list != NULL) unlink_tempfiles(tmpfiles_list); if (test_result < 0) { free(m->basename); free(m->dirname); return -XMP_ERROR_FORMAT; } if (load_result < 0) { xmp_release_module(opaque); return -XMP_ERROR_LOAD; } str_adj(m->mod.name); load_epilogue(ctx); ret = prepare_scan(ctx); if (ret < 0) return ret; scan_sequences(ctx); ctx->state = XMP_STATE_LOADED; return 0; }
static int mtp_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j, k; uint8 buffer[25]; int blocksize; LOAD_INIT(); hio_read(buffer, 6, 1, f); if (!memcmp(buffer, "SONGOK", 6)) set_type(m, "IIgs SoundSmith"); else if (!memcmp(buffer, "IAN92a", 8)) set_type(m, "IIgs MegaTracker"); else return -1; blocksize = hio_read16l(f); mod->spd = hio_read16l(f); hio_seek(f, 10, SEEK_CUR); /* skip 10 reserved bytes */ mod->ins = mod->smp = 15; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(buffer, 1, 22, f); if (buffer[0]) { buffer[buffer[0] + 1] = 0; instrument_name(mod, i, buffer + 1, 22); } hio_read16l(f); /* skip 2 reserved bytes */ mod->xxi[i].sub[0].vol = hio_read8(f) >> 2; mod->xxi[i].sub[0].pan = 0x80; hio_seek(f, 5, SEEK_CUR); /* skip 5 bytes */ } mod->len = hio_read8(f) & 0x7f; hio_read8(f); hio_read(mod->xxo, 1, 128, f); MODULE_INFO(); hio_seek(f, start + 600, SEEK_SET); mod->chn = 14; mod->pat = blocksize / (14 * 64); mod->trk = mod->pat * mod->chn; if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); /* Load notes */ for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { event = &EVENT(i, k, j); event->note = hio_read8(f);; if (event->note) event->note += 24; } } } /* Load fx1 */ for (i = 0; i < mod->pat; i++) { for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { uint8 x; event = &EVENT(i, k, j); x = hio_read8(f);; event->ins = x >> 4; switch (x & 0x0f) { case 0x00: event->fxt = FX_ARPEGGIO; break; case 0x03: event->fxt = FX_VOLSET; break; case 0x05: event->fxt = FX_VOLSLIDE_DN; break; case 0x06: event->fxt = FX_VOLSLIDE_UP; break; case 0x0f: event->fxt = FX_SPEED; break; } } } } /* Load fx2 */ for (i = 0; i < mod->pat; i++) { for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { event = &EVENT(i, k, j); event->fxp = hio_read8(f);; switch (event->fxt) { case FX_VOLSET: case FX_VOLSLIDE_DN: case FX_VOLSLIDE_UP: event->fxp >>= 2; } } } } /* Read instrument data */ D_(D_INFO "Instruments : %d ", mod->ins); for (i = 0; i < mod->ins; i++) { HIO_HANDLE *s; char filename[1024]; if (!mod->xxi[i].name[0]) continue; strncpy(filename, m->dirname, NAME_SIZE); if (*filename) strncat(filename, "/", NAME_SIZE); strncat(filename, (char *)mod->xxi[i].name, NAME_SIZE); if ((s = hio_open_file(filename, "rb")) != NULL) { asif_load(m, s, i); hio_close(s); } #if 0 mod->xxs[i].lps = 0; mod->xxs[i].lpe = 0; mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = 0; mod->xxi[i].sub[0].pan = 0x80; #endif D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); } return 0; }
int main(int argc, char ** argv) { char * pmi_rank = getenv("PMI_RANK"); char * hio_name = getenv("STUB_NAME"); int rank = -1; int status; if (argc != 2) { printf("Usage: %s <file to open>\n", *argv); return -1; } if (pmi_rank == NULL) { printf("No PMI_RANK in env. assuming rank 0\n"); rank = 0; } else { rank = atoi(pmi_rank); } if (hio_name == NULL) { printf("No STUB_NAME in env. exiting\n"); return -1; } sleep(2); status = libhio_client_init(hio_name, rank); if (status != 0) { printf("Failed to init HIO client\n"); return -1; } /* Open/read/write/close a file */ { char * file_name = argv[1]; int fd; ssize_t bytes; off_t offset; char buf[PAGE_SIZE * 10]; fd = hio_open(file_name, O_RDONLY); if (hio_status != HIO_SUCCESS || fd < 0) { printf("Could not open file %s (fd=%d)\n", file_name, fd); goto out; } bytes = hio_read(fd, buf, PAGE_SIZE * 10); printf("Read %li bytes from fd %d\n", bytes, fd); if (bytes> 0) printf("%s\n", buf); hio_close(fd); fd = hio_open(file_name, O_WRONLY | O_TRUNC); if (hio_status != HIO_SUCCESS || fd < 0) { printf("Could not open file %s (fd=%d)\n", file_name, fd); goto out; } bytes = hio_write(fd, "Overwrite file\n", 15); printf("Wrote %li bytes to fd %d\n", bytes, fd); hio_close(fd); } /* mmap the file */ { char * file_name = argv[1]; int fd; ssize_t bytes; off_t offset; void * addr; void * at_addr; hio_segment_t seg; fd = hio_open(file_name, O_RDONLY); if (hio_status != HIO_SUCCESS || fd < 0) { printf("Could not open file %s (fd=%d)\n", file_name, fd); goto out; } addr = hio_mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0, &seg); if (hio_status != HIO_SUCCESS || addr == MAP_FAILED) { printf("failed to issue mmap to fd: %d\n", fd); goto out; } /* Linux mapped new memory to'addr'. We do not have this region * mapped in our aspace, so we need to map it in now */ status = __map_hio_segment(&seg, MY_ID); if (status != 0) { printf("Failed to target the mmap to the stub-allocated vaddr\n"); goto out; } addr = seg.vaddr; printf("at %p: %s\n", addr, (char *)addr); hio_close(fd); } out: libhio_client_deinit(); return 0; }
int xmp_load_module(xmp_context opaque, char *path) { struct context_data *ctx = (struct context_data *)opaque; struct module_data *m = &ctx->m; HIO_HANDLE *h; struct stat st; struct list_head tmpfiles_list; int test_result, load_result; int i, ret; D_(D_WARN "path = %s", path); if (stat(path, &st) < 0) return -XMP_ERROR_SYSTEM; #ifndef _MSC_VER if (S_ISDIR(st.st_mode)) { errno = EISDIR; return -XMP_ERROR_SYSTEM; } #endif if ((h = hio_open_file(path, "rb")) == NULL) return -XMP_ERROR_SYSTEM; INIT_LIST_HEAD(&tmpfiles_list); D_(D_INFO "decrunch"); if (decrunch(&tmpfiles_list, &h->f, &path, DECRUNCH_MAX) < 0) goto err_depack; if (hio_stat(h, &st) < 0) goto err_depack; if (st.st_size < 256) { /* get size after decrunch */ hio_close(h); unlink_tempfiles(&tmpfiles_list); return -XMP_ERROR_FORMAT; } if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); m->dirname = get_dirname(path); if (m->dirname == NULL) return -XMP_ERROR_SYSTEM; m->basename = get_basename(path); if (m->basename == NULL) return -XMP_ERROR_SYSTEM; m->filename = path; /* For ALM, SSMT, etc */ m->size = st.st_size; load_prologue(ctx); D_(D_WARN "load"); test_result = load_result = -1; for (i = 0; format_loader[i] != NULL; i++) { hio_seek(h, 0, SEEK_SET); test_result = format_loader[i]->test(h, NULL, 0); if (test_result == 0) { hio_seek(h, 0, SEEK_SET); D_(D_WARN "load format: %s", format_loader[i]->name); load_result = format_loader[i]->loader(m, h, 0); break; } } set_md5sum(h, m->md5); hio_close(h); unlink_tempfiles(&tmpfiles_list); if (test_result < 0) { free(m->basename); free(m->dirname); return -XMP_ERROR_FORMAT; } if (load_result < 0) { xmp_release_module(opaque); return -XMP_ERROR_LOAD; } str_adj(m->mod.name); if (!*m->mod.name) { strncpy(m->mod.name, m->basename, XMP_NAME_SIZE); } load_epilogue(ctx); ret = prepare_scan(ctx); if (ret < 0) return ret; scan_sequences(ctx); ctx->state = XMP_STATE_LOADED; return 0; err_depack: hio_close(h); unlink_tempfiles(&tmpfiles_list); return -XMP_ERROR_DEPACK; }
static int decrunch(struct list_head *head, FILE **f, char **s, int ttl) { unsigned char b[1024]; char *cmd; FILE *t; int fd, builtin, res; char *temp2, tmp[PATH_MAX]; struct tmpfilename *temp; int headersize; cmd = NULL; builtin = res = 0; if (get_temp_dir(tmp, PATH_MAX) < 0) return 0; strncat(tmp, "xmp_XXXXXX", PATH_MAX); fseek(*f, 0, SEEK_SET); if ((headersize = fread(b, 1, 1024, *f)) < 100) /* minimum valid file size */ return 0; #if defined __AMIGA__ && !defined __AROS__ if (test_xfd(b, 1024)) { builtin = BUILTIN_XFD; } else #endif if (b[0] == 'P' && b[1] == 'K' && ((b[2] == 3 && b[3] == 4) || (b[2] == '0' && b[3] == '0' && b[4] == 'P' && b[5] == 'K' && b[6] == 3 && b[7] == 4))) { /* Zip */ builtin = BUILTIN_ZIP; } else if (b[2] == '-' && b[3] == 'l' && b[4] == 'h') { /* LHa */ builtin = BUILTIN_LHA; } else if (b[0] == 31 && b[1] == 139) { /* gzip */ builtin = BUILTIN_GZIP; } else if (b[0] == 'B' && b[1] == 'Z' && b[2] == 'h') { /* bzip2 */ builtin = BUILTIN_BZIP2; } else if (b[0] == 0xfd && b[3] == 'X' && b[4] == 'Z' && b[5] == 0x00) { /* xz */ builtin = BUILTIN_XZ; #if 0 } else if (b[0] == 'Z' && b[1] == 'O' && b[2] == 'O' && b[3] == ' ') { /* zoo */ builtin = BUILTIN_ZOO; #endif } else if (b[0] == 'M' && b[1] == 'O' && b[2] == '3') { /* MO3 */ cmd = "unmo3 -s \"%s\" STDOUT"; } else if (b[0] == 31 && b[1] == 157) { /* compress */ builtin = BUILTIN_COMPRESS; } else if (memcmp(b, "PP20", 4) == 0) { /* PowerPack */ builtin = BUILTIN_PP; } else if (memcmp(b, "XPKF", 4) == 0 && memcmp(b + 8, "SQSH", 4) == 0) { /* SQSH */ builtin = BUILTIN_SQSH; } else if (!memcmp(b, "Archive\0", 8)) { /* ArcFS */ builtin = BUILTIN_ARCFS; } else if (memcmp(b, "ziRCONia", 8) == 0) { /* MMCMP */ builtin = BUILTIN_MMCMP; } else if (memcmp(b, "MUSE", 4) == 0 && readmem32b(b + 4) == 0xdeadbeaf) { /* J2B MUSE */ builtin = BUILTIN_MUSE; } else if (memcmp(b, "MUSE", 4) == 0 && readmem32b(b + 4) == 0xdeadbabe) { /* MOD2J2B MUSE */ builtin = BUILTIN_MUSE; } else if (memcmp(b, "LZX", 3) == 0) { /* LZX */ builtin = BUILTIN_LZX; } else if (memcmp(b, "Rar", 3) == 0) { /* rar */ cmd = "unrar p -inul -xreadme -x*.diz -x*.nfo -x*.txt " "-x*.exe -x*.com \"%s\""; } else if (memcmp(b, "S404", 4) == 0) { /* Stonecracker */ builtin = BUILTIN_S404; } else if (test_oxm(*f) == 0) { /* oggmod */ builtin = BUILTIN_OXM; } if (builtin == 0 && cmd == NULL && b[0] == 0x1a) { int x = b[1] & 0x7f; int i, flag = 0; long size; /* check file name */ for (i = 0; i < 13; i++) { if (b[2 + i] == 0) { if (i == 0) /* name can't be empty */ flag = 1; break; } if (!isprint(b[2 + i])) { /* name must be printable */ flag = 1; break; } } size = readmem32l(b + 15); /* max file size is 512KB */ if (size < 0 || size > 512 * 1024) flag = 1; if (flag == 0) { if (x >= 1 && x <= 9 && x != 7) { /* Arc */ builtin = BUILTIN_ARC; } else if (x == 0x7f) { /* !Spark */ builtin = BUILTIN_ARC; } } } fseek(*f, 0, SEEK_SET); if (builtin == 0 && cmd == NULL) return 0; #if defined ANDROID || defined __native_client__ /* Don't use external helpers in android */ if (cmd) return 0; #endif D_(D_WARN "Depacking file... "); temp = calloc(sizeof (struct tmpfilename), 1); if (!temp) { D_(D_CRIT "calloc failed"); return -1; } temp->name = strdup(tmp); if (temp->name == NULL || (fd = mkstemp(temp->name)) < 0) { D_(D_CRIT "failed"); return -1; } list_add_tail(&temp->list, head); if ((t = fdopen(fd, "w+b")) == NULL) { D_(D_CRIT "failed"); return -1; } if (cmd) { #define BSIZE 0x4000 int n; char line[1024], buf[BSIZE]; FILE *p; snprintf(line, 1024, cmd, *s); #ifdef WIN32 /* Note: The _popen function returns an invalid file opaque, if * used in a Windows program, that will cause the program to hang * indefinitely. _popen works properly in a Console application. * To create a Windows application that redirects input and output, * read the section "Creating a Child Process with Redirected Input * and Output" in the Win32 SDK. -- Mirko */ if ((p = popen(line, "rb")) == NULL) { #else /* Linux popen fails with "rb" */ if ((p = popen(line, "r")) == NULL) { #endif D_(D_CRIT "failed"); fclose(t); return -1; } while ((n = fread(buf, 1, BSIZE, p)) > 0) fwrite(buf, 1, n, t); pclose (p); } else { switch (builtin) { case BUILTIN_PP: res = decrunch_pp(*f, t); break; case BUILTIN_ARC: res = decrunch_arc(*f, t); break; case BUILTIN_ARCFS: res = decrunch_arcfs(*f, t); break; case BUILTIN_SQSH: res = decrunch_sqsh(*f, t); break; case BUILTIN_MMCMP: res = decrunch_mmcmp(*f, t); break; case BUILTIN_MUSE: res = decrunch_muse(*f, t); break; case BUILTIN_LZX: res = decrunch_lzx(*f, t); break; case BUILTIN_S404: res = decrunch_s404(*f, t); break; case BUILTIN_ZIP: res = decrunch_zip(*f, t); break; case BUILTIN_GZIP: res = decrunch_gzip(*f, t); break; case BUILTIN_COMPRESS: res = decrunch_compress(*f, t); break; case BUILTIN_BZIP2: res = decrunch_bzip2(*f, t); break; case BUILTIN_XZ: res = decrunch_xz(*f, t); break; case BUILTIN_LHA: res = decrunch_lha(*f, t); break; #if 0 case BUILTIN_ZOO: res = decrunch_zoo(*f, t); break; #endif case BUILTIN_OXM: res = decrunch_oxm(*f, t); break; #ifdef AMIGA case BUILTIN_XFD: res = decrunch_xfd(*f, t); break; #endif } } if (res < 0) { D_(D_CRIT "failed"); fclose(t); return -1; } D_(D_INFO "done"); fclose(*f); *f = t; if (!--ttl) { return -1; } temp2 = strdup(temp->name); res = decrunch(head, f, &temp->name, ttl); free(temp2); /* Mirko: temp is now deallocated in unlink_tempfiles() * not a problem, since unlink_tempfiles() is called after decrunch * in loader routines * * free(temp); */ return res; } /* * Windows doesn't allow you to unlink an open file, so we changed the * temp file cleanup system to remove temporary files after we close it */ static void unlink_tempfiles(struct list_head *head) { struct tmpfilename *li; struct list_head *tmp; /* can't use list_for_each when freeing the node! */ for (tmp = head->next; tmp != head; ) { li = list_entry(tmp, struct tmpfilename, list); D_(D_INFO "unlink tmpfile %s", li->name); unlink(li->name); free(li->name); list_del(&li->list); tmp = tmp->next; free(li); } } int xmp_test_module(char *path, struct xmp_test_info *info) { HIO_HANDLE *h; struct stat st; char buf[XMP_NAME_SIZE]; int i; struct list_head tmpfiles_list; int ret = -XMP_ERROR_FORMAT;; if (stat(path, &st) < 0) return -XMP_ERROR_SYSTEM; #ifndef _MSC_VER if (S_ISDIR(st.st_mode)) { errno = EISDIR; return -XMP_ERROR_SYSTEM; } #endif if ((h = hio_open_file(path, "rb")) == NULL) return -XMP_ERROR_SYSTEM; INIT_LIST_HEAD(&tmpfiles_list); if (decrunch(&tmpfiles_list, &h->f, &path, DECRUNCH_MAX) < 0) { ret = -XMP_ERROR_DEPACK; goto err; } if (hio_stat(h, &st) < 0) {/* get size after decrunch */ ret = -XMP_ERROR_DEPACK; goto err; } if (st.st_size < 256) { /* set minimum valid module size */ ret = -XMP_ERROR_FORMAT; goto err; } if (info != NULL) { *info->name = 0; /* reset name prior to testing */ *info->type = 0; /* reset type prior to testing */ } for (i = 0; format_loader[i] != NULL; i++) { fseek(h->f, 0, SEEK_SET); if (format_loader[i]->test(h, buf, 0) == 0) { int is_prowizard = 0; if (strcmp(format_loader[i]->name, "prowizard") == 0) { fseek(h->f, 0, SEEK_SET); pw_test_format(h->f, buf, 0, info); is_prowizard = 1; } fclose(h->f); unlink_tempfiles(&tmpfiles_list); if (info != NULL && !is_prowizard) { strncpy(info->name, buf, XMP_NAME_SIZE); strncpy(info->type, format_loader[i]->name, XMP_NAME_SIZE); } return 0; } } err: hio_close(h); unlink_tempfiles(&tmpfiles_list); return ret; }
static int mod_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; int smp_size, pat_size, wow, ptsong = 0; struct xmp_event *event; struct mod_header mh; uint8 mod_event[4]; char *x, pathname[PATH_MAX] = "", *tracker = ""; int detected = 0; char magic[8], idbuffer[32]; int ptkloop = 0; /* Protracker loop */ int tracker_id = TRACKER_PROTRACKER; LOAD_INIT(); mod->ins = 31; mod->smp = mod->ins; mod->chn = 0; smp_size = 0; pat_size = 0; m->quirk |= QUIRK_MODRNG; hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ mh.ins[i].size = hio_read16b(f); /* Length in 16-bit words */ mh.ins[i].finetune = hio_read8(f); /* Finetune (signed nibble) */ mh.ins[i].volume = hio_read8(f); /* Linear playback volume */ mh.ins[i].loop_start = hio_read16b(f); /* Loop start in 16-bit words */ mh.ins[i].loop_size = hio_read16b(f); /* Loop size in 16-bit words */ smp_size += 2 * mh.ins[i].size; } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); memset(magic, 0, 8); hio_read(magic, 4, 1, f); for (i = 0; mod_magic[i].ch; i++) { if (!(strncmp (magic, mod_magic[i].magic, 4))) { mod->chn = mod_magic[i].ch; tracker_id = mod_magic[i].id; detected = mod_magic[i].flag; break; } } if (!mod->chn) { if (!strncmp(magic + 2, "CH", 2) && isdigit((int)magic[0]) && isdigit((int)magic[1])) { mod->chn = (*magic - '0') * 10 + magic[1] - '0'; } else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) { mod->chn = *magic - '0'; } else { return -1; } tracker_id = mod->chn & 1 ? TRACKER_TAKETRACKER : TRACKER_FASTTRACKER2; detected = 1; m->quirk &= ~QUIRK_MODRNG; } strncpy(mod->name, (char *) mh.name, 20); mod->len = mh.len; /* mod->rst = mh.restart; */ if (mod->rst >= mod->len) mod->rst = 0; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { /* This fixes dragnet.mod (garbage in the order list) */ if (mod->xxo[i] > 0x7f) break; if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; pat_size = 256 * mod->chn * mod->pat; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; if (mod->xxs[i].lpe > mod->xxs[i].len) mod->xxs[i].lpe = mod->xxs[i].len; mod->xxs[i].flg = (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe >= 4) ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, mh.ins[i].name, 22); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; } /* * Experimental tracker-detection routine */ if (detected) goto skip_test; /* Test for Flextrax modules * * FlexTrax is a soundtracker for Atari Falcon030 compatible computers. * FlexTrax supports the standard MOD file format (up to eight channels) * for compatibility reasons but also features a new enhanced module * format FLX. The FLX format is an extended version of the standard * MOD file format with support for real-time sound effects like reverb * and delay. */ if (0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size < m->size) { int pos = hio_tell(f); hio_seek(f, start + 0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size, SEEK_SET); hio_read(idbuffer, 1, 4, f); hio_seek(f, start + pos, SEEK_SET); if (!memcmp(idbuffer, "FLEX", 4)) { tracker_id = TRACKER_FLEXTRAX; goto skip_test; } } /* Test for Mod's Grave WOW modules * * Stefan Danes <*****@*****.**> said: * This weird format is identical to '8CHN' but still uses the 'M.K.' ID. * You can only test for WOW by calculating the size of the module for 8 * channels and comparing this to the actual module length. If it's equal, * the module is an 8 channel WOW. */ if ((wow = (!strncmp(magic, "M.K.", 4) && (0x43c + mod->pat * 32 * 0x40 + smp_size == m->size)))) { mod->chn = 8; tracker_id = TRACKER_MODSGRAVE; goto skip_test; } /* Test for Protracker song files */ else if ((ptsong = (!strncmp((char *)magic, "M.K.", 4) && (0x43c + mod->pat * 0x400 == m->size)))) { tracker_id = TRACKER_PROTRACKER; goto skip_test; } /* Test Protracker-like files */ if (mod->chn == 4 && mh.restart == mod->pat) { tracker_id = TRACKER_SOUNDTRACKER; } else if (mod->chn == 4 && mh.restart == 0x78) { tracker_id = TRACKER_NOISETRACKER; } else if (mh.restart < 0x7f) { if (mod->chn == 4) { tracker_id = TRACKER_NOISETRACKER; } else { tracker_id = TRACKER_UNKNOWN; } mod->rst = mh.restart; } if (mod->chn != 4 && mh.restart == 0x7f) { tracker_id = TRACKER_SCREAMTRACKER3; m->quirk &= ~QUIRK_MODRNG; m->read_event_type = READ_EVENT_ST3; } if (mod->chn == 4 && mh.restart == 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i < 31) { tracker_id = TRACKER_CLONE; } } if (mh.restart != 0x78 && mh.restart < 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i == 31) { /* All loops are size 2 or greater */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 1 && mh.ins[i].volume == 0) { tracker_id = TRACKER_CONVERTED; goto skip_test; } } for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i == 31) { /* No st- instruments */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 0 && mh.ins[i].loop_size == 1) { switch (mod->chn) { case 4: tracker_id = TRACKER_NOISETRACKER; /* or Octalyser */ break; case 6: case 8: tracker_id = TRACKER_OCTALYSER; break; default: tracker_id = TRACKER_UNKNOWN; } goto skip_test; } } if (mod->chn == 4) { tracker_id = TRACKER_PROTRACKER; } else if (mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; /* FastTracker 1.01? */ m->quirk &= ~QUIRK_MODRNG; } else { tracker_id = TRACKER_UNKNOWN; } } } else { /* Has loops with 0 size */ for (i = 15; i < 31; i++) { if (strlen((char *)mh.ins[i].name) || mh.ins[i].size > 0) break; } if (i == 31 && is_st_ins((char *)mh.ins[14].name)) { tracker_id = TRACKER_CONVERTEDST; goto skip_test; } /* Assume that Fast Tracker modules won't have ST- instruments */ for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i < 31) { tracker_id = TRACKER_UNKNOWN_CONV; goto skip_test; } if (mod->chn == 4 || mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; m->quirk &= ~QUIRK_MODRNG; goto skip_test; } tracker_id = TRACKER_UNKNOWN; /* ??!? */ } } skip_test: switch (tracker_id) { case TRACKER_PROTRACKER: tracker = "Protracker"; ptkloop = 1; break; case TRACKER_NOISETRACKER: tracker = "Noisetracker"; ptkloop = 1; break; case TRACKER_SOUNDTRACKER: tracker = "Soundtracker"; ptkloop = 1; break; case TRACKER_FASTTRACKER: tracker = "Fast Tracker"; break; case TRACKER_FASTTRACKER2: tracker = "FastTracker 2"; break; case TRACKER_OCTALYSER: tracker = "Octalyser"; break; case TRACKER_TAKETRACKER: tracker = "TakeTracker"; break; case TRACKER_DIGITALTRACKER: tracker = "Digital Tracker"; break; case TRACKER_FLEXTRAX: tracker = "Flextrax"; break; case TRACKER_MODSGRAVE: tracker = "Mod's Grave"; break; case TRACKER_SCREAMTRACKER3: tracker = "Scream Tracker III"; break; case TRACKER_UNKNOWN_CONV: tracker = "unknown or converted"; break; case TRACKER_CONVERTEDST: tracker = "converted ST2.2 or earlier"; break; case TRACKER_CONVERTED: tracker = "converted"; break; case TRACKER_CLONE: tracker = "Protracker clone"; break; default: case TRACKER_UNKNOWN: tracker = "unknown"; break; } mod->trk = mod->chn * mod->pat; snprintf(mod->type, XMP_NAME_SIZE, "%s (%s)", tracker, magic); MODULE_INFO(); for (i = 0; i < mod->ins; i++) { D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4, ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 && mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' '); } if (pattern_init(mod) < 0) return -1; /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < (64 * mod->chn); j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); hio_read (mod_event, 1, 4, f); switch (tracker_id) { case TRACKER_NOISETRACKER: decode_noisetracker_event(event, mod_event); break; case TRACKER_PROTRACKER: default: decode_protracker_event(event, mod_event); break; } } } /* Load samples */ if (m->filename && (x = strrchr(m->filename, '/'))) strncpy(pathname, m->filename, x - m->filename); D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { int flags; if (!mod->xxs[i].len) continue; flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0; if (ptsong) { HIO_HANDLE *s; char sn[256]; snprintf(sn, XMP_NAME_SIZE, "%s%s", pathname, mod->xxi[i].name); if ((s = hio_open_file(sn, "rb"))) { if (load_sample(m, s, flags, &mod->xxs[i], NULL) < 0) { hio_close(s); return -1; } hio_close(s); } } else { if (load_sample(m, f, flags, &mod->xxs[i], NULL) < 0) return -1; } } if (mod->chn > 4) { m->quirk &= ~QUIRK_MODRNG; m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; } else if (strcmp(tracker, "Protracker") == 0) { m->quirk |= QUIRK_INVLOOP; } return 0; }
int xmp_smix_load_sample(xmp_context opaque, int num, char *path) { struct context_data *ctx = (struct context_data *)opaque; struct smix_data *smix = &ctx->smix; struct module_data *m = &ctx->m; struct xmp_instrument *xxi; struct xmp_sample *xxs; HIO_HANDLE *h; uint32 magic; int chn, rate, bits, size; int retval = -XMP_ERROR_INTERNAL; if (num >= smix->ins) { retval = -XMP_ERROR_INVALID; goto err; } xxi = &smix->xxi[num]; xxs = &smix->xxs[num]; h = hio_open_file(path, "rb"); if (h == NULL) { retval = -XMP_ERROR_SYSTEM; goto err; } /* Init instrument */ xxi->sub = calloc(sizeof(struct xmp_subinstrument), 1); if (xxi->sub == NULL) { retval = -XMP_ERROR_SYSTEM; goto err1; } xxi->vol = m->volbase; xxi->nsm = 1; xxi->sub[0].sid = num; xxi->sub[0].vol = xxi->vol; xxi->sub[0].pan = 0x80; /* Load sample */ magic = hio_read32b(h); if (magic != 0x52494646) { /* RIFF */ retval = -XMP_ERROR_FORMAT; goto err2; } hio_seek(h, 22, SEEK_SET); chn = hio_read16l(h); if (chn != 1) { retval = -XMP_ERROR_FORMAT; goto err2; } rate = hio_read32l(h); hio_seek(h, 34, SEEK_SET); bits = hio_read16l(h); hio_seek(h, 40, SEEK_SET); size = hio_read32l(h) / (bits / 8); c2spd_to_note(rate, &xxi->sub[0].xpo, &xxi->sub[0].fin); xxs->len = 8 * size / bits; xxs->lps = 0; xxs->lpe = 0; xxs->flg = bits == 16 ? XMP_SAMPLE_16BIT : 0; xxs->data = malloc(size); if (xxs->data == NULL) { retval = -XMP_ERROR_SYSTEM; goto err2; } hio_seek(h, 44, SEEK_SET); hio_read(xxs->data, 1, size, h); hio_close(h); return 0; err2: free(xxi->sub); xxi->sub = NULL; err1: hio_close(h); err: return retval; }
int xmp_load_module(xmp_context opaque, char *path) { struct context_data *ctx = (struct context_data *)opaque; #ifndef LIBXMP_CORE_PLAYER struct module_data *m = &ctx->m; long size; char *temp_name; #endif HIO_HANDLE *h; struct stat st; int ret; D_(D_WARN "path = %s", path); /* if (stat(path, &st) < 0) return -XMP_ERROR_SYSTEM; */ #ifndef _MSC_VER if (S_ISDIR(st.st_mode)) { errno = EISDIR; return -XMP_ERROR_SYSTEM; } #endif if ((h = hio_open(path, "rb")) == NULL) return -XMP_ERROR_SYSTEM; #ifndef LIBXMP_CORE_PLAYER D_(D_INFO "decrunch"); if (decrunch(&h, path, &temp_name) < 0) goto err_depack; size = hio_size(h); if (size < 256) { /* get size after decrunch */ hio_close(h); unlink_temp_file(temp_name); return -XMP_ERROR_FORMAT; } #endif if (ctx->state > XMP_STATE_UNLOADED) xmp_release_module(opaque); #ifndef LIBXMP_CORE_PLAYER m->dirname = get_dirname(path); if (m->dirname == NULL) return -XMP_ERROR_SYSTEM; m->basename = get_basename(path); if (m->basename == NULL) return -XMP_ERROR_SYSTEM; m->filename = path; /* For ALM, SSMT, etc */ m->size = size; #endif ret = load_module(opaque, h); hio_close(h); #ifndef LIBXMP_CORE_PLAYER unlink_temp_file(temp_name); #endif return ret; #ifndef LIBXMP_CORE_PLAYER err_depack: hio_close(h); unlink_temp_file(temp_name); return -XMP_ERROR_DEPACK; #endif }
int xmp_test_module(char *path, struct xmp_test_info *info) { HIO_HANDLE *h; struct stat st; char buf[XMP_NAME_SIZE]; int i; int ret = -XMP_ERROR_FORMAT; #ifndef LIBXMP_CORE_PLAYER char *temp = NULL; #endif if (stat(path, &st) < 0) return -XMP_ERROR_SYSTEM; #ifndef _MSC_VER if (S_ISDIR(st.st_mode)) { errno = EISDIR; return -XMP_ERROR_SYSTEM; } #endif if ((h = hio_open(path, "rb")) == NULL) return -XMP_ERROR_SYSTEM; #ifndef LIBXMP_CORE_PLAYER if (decrunch(&h, path, &temp) < 0) { ret = -XMP_ERROR_DEPACK; goto err; } /* get size after decrunch */ if (hio_size(h) < 256) { /* set minimum valid module size */ ret = -XMP_ERROR_FORMAT; goto err; } #endif if (info != NULL) { *info->name = 0; /* reset name prior to testing */ *info->type = 0; /* reset type prior to testing */ } for (i = 0; format_loader[i] != NULL; i++) { hio_seek(h, 0, SEEK_SET); if (format_loader[i]->test(h, buf, 0) == 0) { int is_prowizard = 0; #ifndef LIBXMP_CORE_PLAYER if (strcmp(format_loader[i]->name, "prowizard") == 0) { hio_seek(h, 0, SEEK_SET); pw_test_format(h, buf, 0, info); is_prowizard = 1; } #endif fclose(h->handle.file); #ifndef LIBXMP_CORE_PLAYER unlink_temp_file(temp); #endif if (info != NULL && !is_prowizard) { strncpy(info->name, buf, XMP_NAME_SIZE); strncpy(info->type, format_loader[i]->name, XMP_NAME_SIZE); } return 0; } } #ifndef LIBXMP_CORE_PLAYER err: hio_close(h); unlink_temp_file(temp); #else hio_close(h); #endif return ret; }
static int decrunch(HIO_HANDLE **h, char *filename, char **temp) { unsigned char b[1024]; char *cmd; FILE *f, *t; int res; int headersize; int i; struct depacker *depacker = NULL; cmd = NULL; res = 0; *temp = NULL; f = (*h)->handle.file; fseek(f, 0, SEEK_SET); headersize = fread(b, 1, 1024, f); if (headersize < 100) /* minimum valid file size */ return 0; /* Check built-in depackers */ for (i = 0; depacker_list[i] != NULL; i++) { if (depacker_list[i]->test(b)) { depacker = depacker_list[i]; D_(D_INFO "Use depacker %d", i); break; } } /* Check external commands */ if (depacker == NULL) { if (b[0] == 'M' && b[1] == 'O' && b[2] == '3') { /* MO3 */ D_(D_INFO "mo3"); cmd = "unmo3 -s \"%s\" STDOUT"; } else if (memcmp(b, "Rar", 3) == 0) { /* rar */ D_(D_INFO "rar"); cmd = "unrar p -inul -xreadme -x*.diz -x*.nfo -x*.txt " "-x*.exe -x*.com \"%s\""; } else if (test_oxm(f) == 0) { /* oggmod */ D_(D_INFO "oggmod"); depacker = &oxm_depacker; } } fseek(f, 0, SEEK_SET); if (depacker == NULL && cmd == NULL) { D_(D_INFO "Not packed"); return 0; } #if defined ANDROID || defined __native_client__ /* Don't use external helpers in android */ if (cmd) { return 0; } #endif D_(D_WARN "Depacking file... "); if ((t = make_temp_file(temp)) == NULL) return -1; /* Depack file */ if (cmd) { D_(D_INFO "External depacker: %s", cmd); if (execute_command(cmd, filename, t) < 0) { D_(D_CRIT "failed"); fclose(t); return -1; } } else if (depacker) { D_(D_INFO "Internal depacker"); if (depacker->depack(f, t) < 0) { D_(D_CRIT "failed"); fclose(t); return -1; } } D_(D_INFO "done"); fseek(t, 0, SEEK_SET); hio_close(*h); *h = hio_open_file(t); return res; }
static int alm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct alm_file_header afh; struct xmp_event *event; struct stat stat; uint8 b; char *basename; char filename[NAME_SIZE]; char modulename[NAME_SIZE]; LOAD_INIT(); hio_read(&afh.id, 7, 1, f); if (!strncmp((char *)afh.id, "ALEYMOD", 7)) /* Version 1.0 */ mod->spd = afh.speed / 2; strncpy(modulename, m->filename, NAME_SIZE); basename = strtok (modulename, "."); afh.speed = hio_read8(f); afh.length = hio_read8(f); afh.restart = hio_read8(f); hio_read(&afh.order, 128, 1, f); mod->len = afh.length; mod->rst = afh.restart; memcpy (mod->xxo, afh.order, mod->len); for (mod->pat = i = 0; i < mod->len; i++) if (mod->pat < afh.order[i]) mod->pat = afh.order[i]; mod->pat++; mod->ins = 31; mod->trk = mod->pat * mod->chn; mod->smp = mod->ins; m->c4rate = C4_NTSC_RATE; set_type(m, "Aley's Module"); MODULE_INFO(); if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < 64 * mod->chn; j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); b = hio_read8(f); if (b) event->note = (b == 37) ? 0x61 : b + 48; event->ins = hio_read8(f); } } if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ D_(D_INFO "Loading samples: %d", mod->ins); for (i = 0; i < mod->ins; i++) { HIO_HANDLE *s; if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); snprintf(filename, NAME_SIZE, "%s.%d", basename, i + 1); s = hio_open(filename, "rb"); if (s == NULL) continue; mod->xxi[i].nsm = 1; hio_stat(s, &stat); b = hio_read8(s); /* Get first octet */ mod->xxs[i].len = stat.st_size - 5 * !b; if (!b) { /* Instrument with header */ mod->xxs[i].lps = hio_read16l(f); mod->xxs[i].lpe = hio_read16l(f); mod->xxs[i].flg = mod->xxs[i].lpe > mod->xxs[i].lps ? XMP_SAMPLE_LOOP : 0; } else { hio_seek(s, 0, SEEK_SET); } mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x", i, filename, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); if (load_sample(m, s, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; hio_close(s); } /* ALM is LRLR, not LRRL */ for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = DEFPAN((i % 2) * 0xff); return 0; }
static int pw_load(struct module_data *m, HIO_HANDLE *h, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; struct mod_header mh; uint8 mod_event[4]; HIO_HANDLE *f; FILE *temp; char *name; char *temp_name; int i, j; /* Prowizard depacking */ if ((temp = make_temp_file(&temp_name)) == NULL) { goto err; } if (pw_wizardry(h, temp, &name) < 0) { fclose(temp); goto err2; } /* Module loading */ if ((f = hio_open_file(temp)) == NULL) { goto err2; } if (hio_seek(f, 0, start) < 0) { goto err3; } hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); mh.ins[i].size = hio_read16b(f); mh.ins[i].finetune = hio_read8(f); mh.ins[i].volume = hio_read8(f); mh.ins[i].loop_start = hio_read16b(f); mh.ins[i].loop_size = hio_read16b(f); } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); hio_read(&mh.magic, 4, 1, f); if (memcmp(mh.magic, "M.K.", 4)) { goto err3; } mod->ins = 31; mod->smp = mod->ins; mod->chn = 4; mod->len = mh.len; mod->rst = mh.restart; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; mod->trk = mod->chn * mod->pat; snprintf(mod->name, XMP_NAME_SIZE, "%s", (char *)mh.name); snprintf(mod->type, XMP_NAME_SIZE, "%s", name); MODULE_INFO(); if (libxmp_init_instrument(m) < 0) { goto err3; } for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) goto err3; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; mod->xxs[i].flg = mh.ins[i].loop_size > 1 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = (int8) (mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = 0xfff; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; libxmp_instrument_name(mod, i, mh.ins[i].name, 22); D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mh.ins[i].loop_size > 1 ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4); } if (libxmp_init_pattern(mod) < 0) { goto err3; } /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) goto err3; for (j = 0; j < (64 * 4); j++) { event = &EVENT(i, j % 4, j / 4); hio_read(mod_event, 1, 4, f); libxmp_decode_protracker_event(event, mod_event); } } m->period_type = PERIOD_MODRNG; /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { if (libxmp_load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) goto err3; } hio_close(f); unlink_temp_file(temp_name); return 0; err3: hio_close(f); err2: unlink_temp_file(temp_name); err: return -1; }
static int mfp_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, k, x, y; struct xmp_event *event; struct stat st; char smp_filename[PATH_MAX]; HIO_HANDLE *s; int size1, size2; int pat_addr, pat_table[128][4]; uint8 buf[1024], mod_event[4]; int row; LOAD_INIT(); set_type(m, "Magnetic Fields Packer"); MODULE_INFO(); mod->chn = 4; mod->ins = mod->smp = 31; if (instrument_init(mod) < 0) return -1; for (i = 0; i < 31; i++) { int loop_size; if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * hio_read16b(f); mod->xxi[i].sub[0].fin = (int8)(hio_read8(f) << 4); mod->xxi[i].sub[0].vol = hio_read8(f); mod->xxs[i].lps = 2 * hio_read16b(f); loop_size = hio_read16b(f); mod->xxs[i].lpe = mod->xxs[i].lps + 2 * loop_size; mod->xxs[i].flg = loop_size > 1 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = 0xfff; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %04x %04x %04x %c V%02x %+d", i, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, loop_size > 1 ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4); } mod->len = mod->pat = hio_read8(f); hio_read8(f); /* restart */ for (i = 0; i < 128; i++) mod->xxo[i] = hio_read8(f); #if 0 for (i = 0; i < 128; i++) { mod->xxo[i] = hio_read8(f); if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; #endif mod->trk = mod->pat * mod->chn; /* Read and convert patterns */ if (pattern_init(mod) < 0) return -1; size1 = hio_read16b(f); size2 = hio_read16b(f); for (i = 0; i < size1; i++) { /* Read pattern table */ for (j = 0; j < 4; j++) { pat_table[i][j] = hio_read16b(f); } } D_(D_INFO "Stored patterns: %d ", mod->pat); pat_addr = hio_tell(f); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < 4; j++) { hio_seek(f, pat_addr + pat_table[i][j], SEEK_SET); hio_read(buf, 1, 1024, f); for (row = k = 0; k < 4; k++) { for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++, row++) { event = &EVENT(i, j, row); memcpy(mod_event, &buf[buf[buf[buf[k] + x] + y] * 2], 4); decode_protracker_event(event, mod_event); } } } } } /* Read samples */ D_(D_INFO "Loading samples: %d", mod->ins); /* first check smp.filename */ if (strlen(m->basename) < 5 || m->basename[3] != '.') { fprintf(stderr, "libxmp: invalid filename %s\n", m->basename); goto err; } m->basename[0] = 's'; m->basename[1] = 'm'; m->basename[2] = 'p'; snprintf(smp_filename, sizeof(smp_filename), "%s%s", m->dirname, m->basename); if (stat(smp_filename, &st) < 0) { /* handle .set filenames like in Kid Chaos*/ char *x; if (strchr(m->basename, '-')) { if ((x = strrchr(smp_filename, '-'))) strcpy(x, ".set"); } if (stat(smp_filename, &st) < 0) { fprintf(stderr, "libxmp: missing file %s\n", smp_filename); goto err; } } if ((s = hio_open_file(smp_filename, "rb")) == NULL) { fprintf(stderr, "libxmp: can't open sample file %s\n", smp_filename); goto err; } for (i = 0; i < mod->ins; i++) { if (load_sample(m, s, SAMPLE_FLAG_FULLREP, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) return -1; } hio_close(s); m->quirk |= QUIRK_MODRNG; return 0; err: for (i = 0; i < mod->ins; i++) { mod->xxi[i].nsm = 0; memset(&mod->xxs[i], 0, sizeof(struct xmp_sample)); } return 0; }
int main(void) { fd_set master; // master file descriptor list fd_set read_fds; // temp file descriptor list for select() int fdmax; // maximum file descriptor number int listener; // listening socket descriptor int s; int newfd; // newly accept()ed socket descriptor struct sockaddr_storage remoteaddr; // client address socklen_t addrlen; int nbytes; char remoteIP[INET6_ADDRSTRLEN]; int i; int len; char *buf = NULL; #define BUF_SIZE 4096*10 buf =(char *)malloc(BUF_SIZE); int buflen = BUF_SIZE; if (buf == NULL) { perror("init malloc"); abort(); } listener = create_and_bind(); if (listener == -1) abort(); // listen s = listen(listener, SOMAXCONN); if (s == -1) { perror ("listen"); abort (); } printf("Listening at socket %d port %d\n", listener, PORTNUM); FD_ZERO(&master); // add the listener to the master set FD_SET(listener, &master); // keep track of the biggest file descriptor fdmax = listener; // so far, it's this one // main loop for(;;) { read_fds = master; // copy it if (hio_select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { perror("select"); return -1; } // run through the existing connections looking for data to read for(i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { // we got one!! if (i == listener) { // handle new connections addrlen = sizeof remoteaddr; newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen); if (newfd == -1) { perror("accept"); } else { FD_SET(newfd, &master); // add to master set if (newfd > fdmax) { // keep track of the max fdmax = newfd; } printf("[INFO] new connection from %s on " "socket %d\n", inet_ntop(remoteaddr.ss_family, &(((struct sockaddr_in*)&remoteaddr)->sin_addr), remoteIP, INET6_ADDRSTRLEN), newfd); } } else { #define HEADER_SIZE 4 // handle data from a client nbytes = recv(i, buf, HEADER_SIZE, 0); if (nbytes < HEADER_SIZE) { if (nbytes < 0 && errno != ECONNRESET) { printf("[ERROR] recv header ret %d, errno is not supported by HIO\n", i); goto out; } printf("[INFO] socket hung up in recv header: %d\n", i); hio_close(i); // bye! FD_CLR(i, &master); // remove from master set break; } len = ntohl(*(int *)buf); //printf("len %d\n", len); // dynamic heap allocation if (len > buflen) { if (buf != NULL) free(buf); buf = (char *)malloc(len*2); buflen = len * 2; printf("resizing buffer to %d\n", buflen); if (buf == NULL) { perror("malloc"); abort(); } } int left = len; nbytes = 0; while (left > 0) { //printf("%d bytes left\n", left); nbytes = recv(i, buf, left, 0); if (nbytes <= 0) { if (nbytes < 0 && errno != ECONNRESET) { printf("[ERROR] recv data ret %d, errno is not supported by HIO\n", i); goto out; } printf("[INFO] socket hung up in recv data: %d\n", i); //printf("%d: received %d bytes, nbytes %d\n", i, len+HEADER_SIZE, nbytes); hio_close(i); // bye! FD_CLR(i, &master); // remove from master set break; } left = len - nbytes; //printf("len %d, nbytes %d, %d bytes left\n", len, nbytes, left); } if (nbytes <= 0) { //printf("break %d\n", i); break; } //printf("%d: received %d bytes, nbytes %d\n", i, len+HEADER_SIZE, nbytes); nbytes = send(i, "Done", 5, 0); if (nbytes <= 0) { if (nbytes < 0) { printf("[ERROR] send ret %d, errno is not supported by HIO\n", i); goto out; } printf("[INFO] socket hung up in send: %d\n", i); hio_close(i); // bye! FD_CLR(i, &master); // remove from master set } //printf("write 5 bytes\n"); } // END handle data from client } // END got new incoming connection } // END looping through file descriptors } // END for(;;)--and you thought it would never end! out: printf("Tearing down Mutilate clint may cause errno 104 (ECONNRESET) to server read/write,\n"); printf("But the performance numbers measured are still valid.\n"); return 0; }