mtm_load.c
1 /* Extended Module Player 2 * Copyright (C) 1996-2021 Claudio Matsuoka and Hipolito Carraro Jr 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23 #include "loader.h" 24 25 struct mtm_file_header { 26 uint8 magic[3]; /* "MTM" */ 27 uint8 version; /* MSN=major, LSN=minor */ 28 uint8 name[20]; /* ASCIIZ Module name */ 29 uint16 tracks; /* Number of tracks saved */ 30 uint8 patterns; /* Number of patterns saved */ 31 uint8 modlen; /* Module length */ 32 uint16 extralen; /* Length of the comment field */ 33 uint8 samples; /* Number of samples */ 34 uint8 attr; /* Always zero */ 35 uint8 rows; /* Number rows per track */ 36 uint8 channels; /* Number of tracks per pattern */ 37 uint8 pan[32]; /* Pan positions for each channel */ 38 }; 39 40 struct mtm_instrument_header { 41 uint8 name[22]; /* Instrument name */ 42 uint32 length; /* Instrument length in bytes */ 43 uint32 loop_start; /* Sample loop start */ 44 uint32 loopend; /* Sample loop end */ 45 uint8 finetune; /* Finetune */ 46 uint8 volume; /* Playback volume */ 47 uint8 attr; /* &0x01: 16bit sample */ 48 }; 49 50 static int mtm_test(HIO_HANDLE *, char *, const int); 51 static int mtm_load(struct module_data *, HIO_HANDLE *, const int); 52 53 const struct format_loader libxmp_loader_mtm = { 54 "Multitracker", 55 mtm_test, 56 mtm_load 57 }; 58 59 static int mtm_test(HIO_HANDLE *f, char *t, const int start) 60 { 61 uint8 buf[4]; 62 63 if (hio_read(buf, 1, 4, f) < 4) 64 return -1; 65 if (memcmp(buf, "MTM", 3)) 66 return -1; 67 if (buf[3] != 0x10) 68 return -1; 69 70 libxmp_read_title(f, t, 20); 71 72 return 0; 73 } 74 75 static int mtm_load(struct module_data *m, HIO_HANDLE *f, const int start) 76 { 77 struct xmp_module *mod = &m->mod; 78 int i, j, k; 79 struct mtm_file_header mfh; 80 struct mtm_instrument_header mih; 81 uint8 mt[192]; 82 int fxx[2]; 83 84 LOAD_INIT(); 85 86 hio_read(mfh.magic, 3, 1, f); /* "MTM" */ 87 mfh.version = hio_read8(f); /* MSN=major, LSN=minor */ 88 hio_read(mfh.name, 20, 1, f); /* ASCIIZ Module name */ 89 mfh.tracks = hio_read16l(f); /* Number of tracks saved */ 90 mfh.patterns = hio_read8(f); /* Number of patterns saved */ 91 mfh.modlen = hio_read8(f); /* Module length */ 92 mfh.extralen = hio_read16l(f); /* Length of the comment field */ 93 94 mfh.samples = hio_read8(f); /* Number of samples */ 95 if (mfh.samples > 63) { 96 return -1; 97 } 98 99 mfh.attr = hio_read8(f); /* Always zero */ 100 101 mfh.rows = hio_read8(f); /* Number rows per track */ 102 if (mfh.rows != 64) 103 return -1; 104 105 mfh.channels = hio_read8(f); /* Number of tracks per pattern */ 106 if (mfh.channels > MIN(32, XMP_MAX_CHANNELS)) { 107 return -1; 108 } 109 110 hio_read(mfh.pan, 32, 1, f); /* Pan positions for each channel */ 111 112 if (hio_error(f)) { 113 return -1; 114 } 115 116 #if 0 117 if (strncmp((char *)mfh.magic, "MTM", 3)) 118 return -1; 119 #endif 120 121 mod->trk = mfh.tracks + 1; 122 mod->pat = mfh.patterns + 1; 123 mod->len = mfh.modlen + 1; 124 mod->ins = mfh.samples; 125 mod->smp = mod->ins; 126 mod->chn = mfh.channels; 127 mod->spd = 6; 128 mod->bpm = 125; 129 130 strncpy(mod->name, (char *)mfh.name, 20); 131 libxmp_set_type(m, "MultiTracker %d.%02d MTM", MSN(mfh.version), 132 LSN(mfh.version)); 133 134 MODULE_INFO(); 135 136 if (libxmp_init_instrument(m) < 0) 137 return -1; 138 139 /* Read and convert instruments */ 140 for (i = 0; i < mod->ins; i++) { 141 struct xmp_instrument *xxi = &mod->xxi[i]; 142 struct xmp_sample *xxs = &mod->xxs[i]; 143 struct xmp_subinstrument *sub; 144 145 if (libxmp_alloc_subinstrument(mod, i, 1) < 0) 146 return -1; 147 148 sub = &xxi->sub[0]; 149 150 hio_read(mih.name, 22, 1, f); /* Instrument name */ 151 mih.length = hio_read32l(f); /* Instrument length in bytes */ 152 153 if (mih.length > MAX_SAMPLE_SIZE) 154 return -1; 155 156 mih.loop_start = hio_read32l(f); /* Sample loop start */ 157 mih.loopend = hio_read32l(f); /* Sample loop end */ 158 mih.finetune = hio_read8(f); /* Finetune */ 159 mih.volume = hio_read8(f); /* Playback volume */ 160 mih.attr = hio_read8(f); /* &0x01: 16bit sample */ 161 162 xxs->len = mih.length; 163 xxs->lps = mih.loop_start; 164 xxs->lpe = mih.loopend; 165 xxs->flg = (xxs->lpe > 2) ? XMP_SAMPLE_LOOP : 0; /* 1 == Forward loop */ 166 if (mfh.attr & 1) { 167 xxs->flg |= XMP_SAMPLE_16BIT; 168 xxs->len >>= 1; 169 xxs->lps >>= 1; 170 xxs->lpe >>= 1; 171 } 172 173 sub->vol = mih.volume; 174 sub->fin = mih.finetune; 175 sub->pan = 0x80; 176 sub->sid = i; 177 178 libxmp_instrument_name(mod, i, mih.name, 22); 179 180 if (xxs->len > 0) 181 mod->xxi[i].nsm = 1; 182 183 D_(D_INFO "[%2X] %-22.22s %04x%c%04x %04x %c V%02x F%+03d\n", i, 184 xxi->name, xxs->len, xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', 185 xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', 186 sub->vol, sub->fin - 0x80); 187 } 188 189 hio_read(mod->xxo, 1, 128, f); 190 191 if (libxmp_init_pattern(mod) < 0) 192 return -1; 193 194 D_(D_INFO "Stored tracks: %d", mod->trk - 1); 195 196 fxx[0] = fxx[1] = 0; 197 for (i = 0; i < mod->trk; i++) { 198 199 if (libxmp_alloc_track(mod, i, mfh.rows) < 0) 200 return -1; 201 202 if (i == 0) 203 continue; 204 205 if (hio_read(mt, 3, 64, f) != 64) 206 return -1; 207 208 for (j = 0; j < 64; j++) { 209 struct xmp_event *e = &mod->xxt[i]->event[j]; 210 uint8 *d = mt + j * 3; 211 212 e->note = d[0] >> 2; 213 if (e->note) { 214 e->note += 37; 215 } 216 e->ins = ((d[0] & 0x3) << 4) + MSN(d[1]); 217 e->fxt = LSN(d[1]); 218 e->fxp = d[2]; 219 if (e->fxt > FX_SPEED) { 220 e->fxt = e->fxp = 0; 221 } 222 223 /* See tempo mode detection below. */ 224 if (e->fxt == FX_SPEED) { 225 fxx[e->fxp >= 0x20] = 1; 226 } 227 228 /* Set pan effect translation */ 229 if (e->fxt == FX_EXTENDED && MSN(e->fxp) == 0x8) { 230 e->fxt = FX_SETPAN; 231 e->fxp <<= 4; 232 } 233 } 234 } 235 236 /* Read patterns */ 237 D_(D_INFO "Stored patterns: %d", mod->pat - 1); 238 239 for (i = 0; i < mod->pat; i++) { 240 if (libxmp_alloc_pattern(mod, i) < 0) 241 return -1; 242 243 mod->xxp[i]->rows = 64; 244 for (j = 0; j < 32; j++) { 245 int track = hio_read16l(f); 246 247 if (track >= mod->trk) { 248 track = 0; 249 } 250 251 if (j < mod->chn) { 252 mod->xxp[i]->index[j] = track; 253 } 254 } 255 } 256 257 /* Tempo mode detection. 258 * 259 * The MTM tempo effect has an unusual property: when speed is set, the 260 * tempo resets to 125, and when tempo is set, the speed resets to 6. 261 * Modules that use both speed and tempo effects need to emulate this. 262 * See: Absolve the Ambience by Sybaris, Soma by Ranger Rick. 263 * 264 * Dual Module Player and other DOS players did not know about this and 265 * did not implement support for it, and instead used Protracker Fxx. 266 * Many MTM authors created modules that rely on this which are various 267 * degrees of broken in the tracker they were made with! Several MTMs 268 * by Phoenix and Silent Mode expect this. The majority of them can be 269 * detected by checking for high Fxx and low Fxx on the same row. 270 */ 271 if (fxx[0] && fxx[1]) { 272 /* Both used, check patterns. */ 273 D_(D_INFO "checking patterns for MT or DMP Fxx effect usage"); 274 for (i = 0; i < mod->pat; i++) { 275 for (j = 0; j < mfh.rows; j++) { 276 fxx[0] = fxx[1] = 0; 277 for (k = 0; k < mod->chn; k++) { 278 struct xmp_event *e = &EVENT(i, k, j); 279 if (e->fxt == FX_SPEED) { 280 fxx[e->fxp >= 0x20] = 1; 281 } 282 } 283 if (fxx[0] && fxx[1]) { 284 /* Same row, no change required */ 285 D_(D_INFO "probably DMP (%d:%d)", i, j); 286 goto probably_dmp; 287 } 288 } 289 } 290 D_(D_INFO "probably MT; injecting speed/BPM reset effects"); 291 for (i = 0; i < mod->pat; i++) { 292 for (j = 0; j < mfh.rows; j++) { 293 for (k = 0; k < mod->chn; k++) { 294 struct xmp_event *e = &EVENT(i, k, j); 295 if (e->fxt == FX_SPEED) { 296 e->f2t = FX_SPEED; 297 e->f2p = (e->fxp < 0x20) ? 125 : 6; 298 } 299 } 300 } 301 } 302 } 303 probably_dmp: 304 305 /* Comments */ 306 if (mfh.extralen) { 307 m->comment = (char *)Xmalloc(mfh.extralen + 1); 308 if (m->comment) { 309 /* Comments are stored in 40 byte ASCIIZ lines. */ 310 int len = hio_read(m->comment, 1, mfh.extralen, f); 311 int line, last_line = 0; 312 313 for (i = 0; i + 40 <= len; i += 40) { 314 if (m->comment[i] != '\0') 315 last_line = i + 40; 316 } 317 for (j = 0, line = 0; line < last_line; line += 40) { 318 char *pos = m->comment + line; 319 for (i = 0; i < 39; i++) { 320 if (pos[i] == '\0') 321 break; 322 m->comment[j++] = pos[i]; 323 } 324 m->comment[j++] = '\n'; 325 } 326 m->comment[j] = '\0'; 327 } else { 328 hio_seek(f, mfh.extralen, SEEK_CUR); 329 } 330 } 331 332 /* Read samples */ 333 D_(D_INFO "Stored samples: %d", mod->smp); 334 335 for (i = 0; i < mod->ins; i++) { 336 if (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) 337 return -1; 338 } 339 340 for (i = 0; i < mod->chn; i++) 341 mod->xxc[i].pan = mfh.pan[i] << 4; 342 343 return 0; 344 }