/* Extended Module Player * Copyright (C) 1996-1999 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. */ /* Zen Packer loader based on the desciption written by Sylvain Chipaux. * Tested with ZEN-dif-prty.exe sent by Martin Jeppesen. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "load.h" struct zen_ins { uint16 finetune; /* Finetune (*48h) */ uint16 volume; /* Volume (0-63) */ uint16 len; /* Sample length / 2 */ uint16 loop_size; /* Loop size / 2 */ uint32 addr; /* Sample address in file */ uint32 loop_start; /* Sample loop start in file */ } PACKED; struct zen_header { uint32 pataddr; /* Address of the pattern table */ uint8 pat; /* Number of patterns (-1) */ uint8 len; /* Size of the pattern list */ struct zen_ins ins[31]; /* Instruments */ } PACKED; int zen_load (FILE *f) { int i, j; struct xxm_event *event; struct zen_header zh; uint8 ev[4]; uint32 x, *pataddr; int smp_size; LOAD_INIT (); fread (&zh, 1, sizeof (zh), f); B_ENDIAN32 (zh.pataddr); fseek (f, zh.pataddr + 4 * zh.len, SEEK_SET); fread (&x, 1, 4, f); B_ENDIAN32 (x); if (x != 0xffffffff) return -1; xxh->ins = 31; xxh->smp = xxh->ins; xxh->pat = zh.pat + 1; xxh->len = zh.len; xxh->trk = xxh->pat * xxh->chn; for (smp_size = i = 0; i < xxh->ins; i++) { B_ENDIAN16 (zh.ins[i].finetune); B_ENDIAN16 (zh.ins[i].volume); B_ENDIAN16 (zh.ins[i].len); B_ENDIAN16 (zh.ins[i].loop_size); B_ENDIAN32 (zh.ins[i].addr); B_ENDIAN32 (zh.ins[i].loop_start); if (zh.ins[i].len > 8) smp_size += 2 * zh.ins[i].len; } if (abs (zh.pataddr + 4 * zh.len + 4 + smp_size - xmp_ctl->size) > 16) return -1; pataddr = calloc (4, xxh->len); fseek (f, zh.pataddr, SEEK_SET); for (i = 0; i < xxh->len; i++) { fread (&pataddr[i], 1, 4, f); B_ENDIAN32 (pataddr[i]); } strcpy (xmp_ctl->type, "Zen Packer"); MODULE_INFO (); INSTRUMENT_INIT (); if (V (1)) report (" Len LBeg LEnd L Vl Ft\n"); for (i = 0; i < xxh->ins; i++) { xxi[i] = calloc (sizeof (struct xxm_instrument), 1); xxih[i].nsm = !!(xxs[i].len = 2 * zh.ins[i].len); xxs[i].lps = zh.ins[i].loop_start - zh.ins[i].addr; xxs[i].lpe = xxs[i].lps + 2 * zh.ins[i].loop_size; xxs[i].flg = zh.ins[i].loop_size > 1 ? WAVE_LOOPING : 0; xxi[i][0].vol = zh.ins[i].volume; xxi[i][0].fin = ((int16)zh.ins[i].finetune / 0x48) << 4; xxi[i][0].pan = 0x80; xxi[i][0].sid = i; if (V (1) && xxs[i].len > 2) report ("[%2X] %04x %04x %04x %c %02x %+01x\n", i, xxs[i].len, xxs[i].lps, xxs[i].lpe, xxs[i].flg & WAVE_LOOPING ? 'L' : ' ', xxi[i][0].vol, xxi[i][0].fin >> 4); } fseek (f, 502, SEEK_SET); PATTERN_INIT (); if (V (0)) report ("Stored patterns: %d ", xxh->pat); for (i = 0; i < xxh->pat; i++) { PATTERN_ALLOC (i); xxp[i]->rows = 64; TRACK_ALLOC (i); x = ftell (f); for (j = 0; j < xxh->len; j++) if (pataddr[j] == x) xxo[j] = i; do { fread (ev, 1, 4, f); event = &EVENT(i, ev[0] % xxh->chn, ev[0] / xxh->chn); if ((event->note = (ev[1] & 0x7e) >> 1)) event->note += 36; event->ins = ((ev[1] & 0x01) << 4) | (ev[2] >> 4); event->fxt = LSN (ev[2]); event->fxp = ev[3]; } while (ev[0] != 0xff || ev[1] || ev[2] || ev[3]); if (V (0)) report ("."); } free (pataddr); xxh->flg |= XXM_FLG_MODRNG; /* Read samples */ fseek (f, zh.pataddr + 4 * zh.len + 4, SEEK_SET); if (V (0)) report ("\nStored samples : %d ", xxh->smp); for (i = 0; i < xxh->ins; i++) { if (xxs[i].len <= 4) continue; fseek (f, zh.ins[i].addr, SEEK_SET); xmp_drv_loadpatch (f, i, xmp_ctl->c4rate, 0, &xxs[i], NULL); if (V (0)) report ("."); } if (V (0)) report ("\n"); return 0; }