From a14d427359438248e18b15a05b15bb2af3d2d720 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Sun, 15 Oct 2017 23:09:55 +0000 Subject: [PATCH] libxmp-lite: Import mtm_load.c git-svn-id: https://svn.eduke32.com/eduke32@6474 1a8010ca-5511-0410-912e-c29ae57300e0 --- source/libxmp-lite/src/mtm_load.c | 264 ++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 source/libxmp-lite/src/mtm_load.c diff --git a/source/libxmp-lite/src/mtm_load.c b/source/libxmp-lite/src/mtm_load.c new file mode 100644 index 000000000..1b482e716 --- /dev/null +++ b/source/libxmp-lite/src/mtm_load.c @@ -0,0 +1,264 @@ +/* Extended Module Player + * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "loader.h" + +struct mtm_file_header { + uint8 magic[3]; /* "MTM" */ + uint8 version; /* MSN=major, LSN=minor */ + uint8 name[20]; /* ASCIIZ Module name */ + uint16 tracks; /* Number of tracks saved */ + uint8 patterns; /* Number of patterns saved */ + uint8 modlen; /* Module length */ + uint16 extralen; /* Length of the comment field */ + uint8 samples; /* Number of samples */ + uint8 attr; /* Always zero */ + uint8 rows; /* Number rows per track */ + uint8 channels; /* Number of tracks per pattern */ + uint8 pan[32]; /* Pan positions for each channel */ +}; + +struct mtm_instrument_header { + uint8 name[22]; /* Instrument name */ + uint32 length; /* Instrument length in bytes */ + uint32 loop_start; /* Sample loop start */ + uint32 loopend; /* Sample loop end */ + uint8 finetune; /* Finetune */ + uint8 volume; /* Playback volume */ + uint8 attr; /* &0x01: 16bit sample */ +}; + +static int mtm_test(HIO_HANDLE *, char *, const int); +static int mtm_load(struct module_data *, HIO_HANDLE *, const int); + +const struct format_loader libxmp_loader_mtm = { + "Multitracker", + mtm_test, + mtm_load +}; + +static int mtm_test(HIO_HANDLE *f, char *t, const int start) +{ + uint8 buf[4]; + + if (hio_read(buf, 1, 4, f) < 4) + return -1; + if (memcmp(buf, "MTM", 3)) + return -1; + if (buf[3] != 0x10) + return -1; + + libxmp_read_title(f, t, 20); + + return 0; +} + +static int mtm_load(struct module_data *m, HIO_HANDLE *f, const int start) +{ + struct xmp_module *mod = &m->mod; + int i, j; + struct mtm_file_header mfh; + struct mtm_instrument_header mih; + uint8 mt[192]; + + LOAD_INIT(); + + hio_read(&mfh.magic, 3, 1, f); /* "MTM" */ + mfh.version = hio_read8(f); /* MSN=major, LSN=minor */ + hio_read(&mfh.name, 20, 1, f); /* ASCIIZ Module name */ + mfh.tracks = hio_read16l(f); /* Number of tracks saved */ + mfh.patterns = hio_read8(f); /* Number of patterns saved */ + mfh.modlen = hio_read8(f); /* Module length */ + mfh.extralen = hio_read16l(f); /* Length of the comment field */ + + mfh.samples = hio_read8(f); /* Number of samples */ + if (mfh.samples > 63) { + return -1; + } + + mfh.attr = hio_read8(f); /* Always zero */ + + mfh.rows = hio_read8(f); /* Number rows per track */ + if (mfh.rows != 64) + return -1; + + mfh.channels = hio_read8(f); /* Number of tracks per pattern */ + if (mfh.channels > XMP_MAX_CHANNELS) { + return -1; + } + + hio_read(&mfh.pan, 32, 1, f); /* Pan positions for each channel */ + + if (hio_error(f)) { + return -1; + } + +#if 0 + if (strncmp((char *)mfh.magic, "MTM", 3)) + return -1; +#endif + + mod->trk = mfh.tracks + 1; + mod->pat = mfh.patterns + 1; + mod->len = mfh.modlen + 1; + mod->ins = mfh.samples; + mod->smp = mod->ins; + mod->chn = mfh.channels; + mod->spd = 6; + mod->bpm = 125; + + strncpy(mod->name, (char *)mfh.name, 20); + libxmp_set_type(m, "MultiTracker %d.%02d MTM", MSN(mfh.version), + LSN(mfh.version)); + + MODULE_INFO(); + + if (libxmp_init_instrument(m) < 0) + return -1; + + /* Read and convert instruments */ + for (i = 0; i < mod->ins; i++) { + struct xmp_instrument *xxi = &mod->xxi[i]; + struct xmp_sample *xxs = &mod->xxs[i]; + struct xmp_subinstrument *sub; + + if (libxmp_alloc_subinstrument(mod, i, 1) < 0) + return -1; + + sub = &xxi->sub[0]; + + hio_read(&mih.name, 22, 1, f); /* Instrument name */ + mih.length = hio_read32l(f); /* Instrument length in bytes */ + + if (mih.length > MAX_SAMPLE_SIZE) + return -1; + + mih.loop_start = hio_read32l(f); /* Sample loop start */ + mih.loopend = hio_read32l(f); /* Sample loop end */ + mih.finetune = hio_read8(f); /* Finetune */ + mih.volume = hio_read8(f); /* Playback volume */ + mih.attr = hio_read8(f); /* &0x01: 16bit sample */ + + xxs->len = mih.length; + xxs->lps = mih.loop_start; + xxs->lpe = mih.loopend; + xxs->flg = xxs->lpe ? XMP_SAMPLE_LOOP : 0; /* 1 == Forward loop */ + if (mfh.attr & 1) { + xxs->flg |= XMP_SAMPLE_16BIT; + xxs->len >>= 1; + xxs->lps >>= 1; + xxs->lpe >>= 1; + } + + sub->vol = mih.volume; + sub->fin = mih.finetune; + sub->pan = 0x80; + sub->sid = i; + + libxmp_instrument_name(mod, i, mih.name, 22); + + if (xxs->len > 0) + mod->xxi[i].nsm = 1; + + D_(D_INFO "[%2X] %-22.22s %04x%c%04x %04x %c V%02x F%+03d\n", i, + xxi->name, xxs->len, xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', + xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', + sub->vol, sub->fin - 0x80); + } + + hio_read(mod->xxo, 1, 128, f); + + if (libxmp_init_pattern(mod) < 0) + return -1; + + D_(D_INFO "Stored tracks: %d", mod->trk - 1); + + for (i = 0; i < mod->trk; i++) { + + if (libxmp_alloc_track(mod, i, mfh.rows) < 0) + return -1; + + if (i == 0) + continue; + + if (hio_read(&mt, 3, 64, f) != 64) + return -1; + + for (j = 0; j < 64; j++) { + struct xmp_event *e = &mod->xxt[i]->event[j]; + uint8 *d = mt + j * 3; + + if ((e->note = d[0] >> 2)) { + e->note += 37; + } + e->ins = ((d[0] & 0x3) << 4) + MSN(d[1]); + e->fxt = LSN(d[1]); + e->fxp = d[2]; + if (e->fxt > FX_SPEED) { + e->fxt = e->fxp = 0; + } + + /* Set pan effect translation */ + if (e->fxt == FX_EXTENDED && MSN(e->fxp) == 0x8) { + e->fxt = FX_SETPAN; + e->fxp <<= 4; + } + } + } + + /* Read patterns */ + D_(D_INFO "Stored patterns: %d", mod->pat - 1); + + for (i = 0; i < mod->pat; i++) { + if (libxmp_alloc_pattern(mod, i) < 0) + return -1; + + mod->xxp[i]->rows = 64; + for (j = 0; j < 32; j++) { + int track = hio_read16l(f); + + if (track >= mod->trk) { + track = 0; + } + + if (j < mod->chn) { + mod->xxp[i]->index[j] = track; + } + } + } + + /* Comments */ + hio_seek(f, mfh.extralen, SEEK_CUR); + + /* Read samples */ + D_(D_INFO "Stored samples: %d", mod->smp); + + for (i = 0; i < mod->ins; i++) { + if (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) + return -1; + } + + for (i = 0; i < mod->chn; i++) + mod->xxc[i].pan = mfh.pan[i] << 4; + + return 0; +}