A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 923 lines 25 kB view raw
1/* MikMod sound library 2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file 3 AUTHORS for complete list. 4 5 This library is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Library General Public License as 7 published by the Free Software Foundation; either version 2 of 8 the License, or (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18 02111-1307, USA. 19*/ 20 21/*============================================================================== 22 23 Amiga MED module loader 24 25==============================================================================*/ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#ifdef HAVE_UNISTD_H 32#include <unistd.h> 33#endif 34 35#include <stdio.h> 36#ifdef HAVE_MEMORY_H 37#include <memory.h> 38#endif 39#include <string.h> 40 41#include "mikmod_internals.h" 42 43#ifdef SUNOS 44extern int fprintf(FILE *, const char *, ...); 45#endif 46 47/*========== Module information */ 48 49#define MEDNOTECNT 120 50 51typedef struct MEDHEADER { 52 ULONG id; 53 ULONG modlen; 54 ULONG MEDSONGP; /* struct MEDSONG *song; */ 55 UWORD psecnum; /* for the player routine, MMD2 only */ 56 UWORD pseq; /* " " " " */ 57 ULONG MEDBlockPP; /* struct MEDBlock **blockarr; */ 58 ULONG reserved1; 59 ULONG MEDINSTHEADERPP; /* struct MEDINSTHEADER **smplarr; */ 60 ULONG reserved2; 61 ULONG MEDEXPP; /* struct MEDEXP *expdata; */ 62 ULONG reserved3; 63 UWORD pstate; /* some data for the player routine */ 64 UWORD pblock; 65 UWORD pline; 66 UWORD pseqnum; 67 SWORD actplayline; 68 UBYTE counter; 69 UBYTE extra_songs; /* number of songs - 1 */ 70} MEDHEADER; 71 72typedef struct MEDSAMPLE { 73 UWORD rep, replen; /* offs: 0(s), 2(s) */ 74 UBYTE midich; /* offs: 4(s) */ 75 UBYTE midipreset; /* offs: 5(s) */ 76 UBYTE svol; /* offs: 6(s) */ 77 SBYTE strans; /* offs: 7(s) */ 78} MEDSAMPLE; 79 80typedef struct MEDSONG { 81 MEDSAMPLE sample[63]; /* 63 * 8 bytes = 504 bytes */ 82 UWORD numblocks; /* offs: 504 */ 83 UWORD songlen; /* offs: 506 */ 84 UBYTE playseq[256]; /* offs: 508 */ 85 UWORD deftempo; /* offs: 764 */ 86 SBYTE playtransp; /* offs: 766 */ 87 UBYTE flags; /* offs: 767 */ 88 UBYTE flags2; /* offs: 768 */ 89 UBYTE tempo2; /* offs: 769 */ 90 UBYTE trkvol[16]; /* offs: 770 */ 91 UBYTE mastervol; /* offs: 786 */ 92 UBYTE numsamples; /* offs: 787 */ 93} MEDSONG; 94 95typedef struct MEDEXP { 96 ULONG nextmod; /* pointer to next module */ 97 ULONG exp_smp; /* pointer to MEDINSTEXT array */ 98 UWORD s_ext_entries; 99 UWORD s_ext_entrsz; 100 ULONG annotxt; /* pointer to annotation text */ 101 ULONG annolen; 102 ULONG iinfo; /* pointer to MEDINSTINFO array */ 103 UWORD i_ext_entries; 104 UWORD i_ext_entrsz; 105 ULONG jumpmask; 106 ULONG rgbtable; 107 ULONG channelsplit; 108 ULONG n_info; 109 ULONG songname; /* pointer to songname */ 110 ULONG songnamelen; 111 ULONG dumps; 112 ULONG reserved2[7]; 113} MEDEXP; 114 115typedef struct MMD0NOTE { 116 UBYTE a, b, c; 117} MMD0NOTE; 118 119typedef struct MMD1NOTE { 120 UBYTE a, b, c, d; 121} MMD1NOTE; 122 123typedef struct MEDINSTHEADER { 124 ULONG length; 125 SWORD type; 126 /* Followed by actual data */ 127} MEDINSTHEADER; 128 129typedef struct MEDINSTEXT { 130 UBYTE hold; 131 UBYTE decay; 132 UBYTE suppress_midi_off; 133 SBYTE finetune; 134} MEDINSTEXT; 135 136typedef struct MEDINSTINFO { 137 UBYTE name[40]; 138} MEDINSTINFO; 139 140enum MEDINSTTYPE { 141 INST_HYBRID = -2, 142 INST_SYNTH = -1, 143 INST_SAMPLE = 0, 144 INST_IFFOCT_5 = 1, 145 INST_IFFOCT_3 = 2, 146 INST_IFFOCT_2 = 3, 147 INST_IFFOCT_4 = 4, 148 INST_IFFOCT_6 = 5, 149 INST_IFFOCT_7 = 6, 150 INST_EXTSAMPLE = 7 151}; 152 153/*========== Loader variables */ 154 155#define MMD0_string 0x4D4D4430 156#define MMD1_string 0x4D4D4431 157 158static MEDHEADER *mh = NULL; 159static MEDSONG *ms = NULL; 160static MEDEXP *me = NULL; 161static ULONG *ba = NULL; 162static MMD0NOTE *mmd0pat = NULL; 163static MMD1NOTE *mmd1pat = NULL; 164 165static UBYTE medversion; 166static int decimalvolumes; 167static int bpmtempos; 168static int is8channel; 169static UWORD rowsperbeat; 170 171#define d0note(row,col) mmd0pat[((row)*(UWORD)of.numchn)+(col)] 172#define d1note(row,col) mmd1pat[((row)*(UWORD)of.numchn)+(col)] 173 174static CHAR MED_Version[] = "OctaMED (MMDx)"; 175 176/*========== Loader code */ 177 178static int MED_Test(void) 179{ 180 UBYTE id[4]; 181 182 if (!_mm_read_UBYTES(id, 4, modreader)) 183 return 0; 184 if ((!memcmp(id, "MMD0", 4)) || (!memcmp(id, "MMD1", 4))) 185 return 1; 186 return 0; 187} 188 189static int MED_Init(void) 190{ 191 if (!(me = (MEDEXP *)MikMod_malloc(sizeof(MEDEXP)))) 192 return 0; 193 if (!(mh = (MEDHEADER *)MikMod_malloc(sizeof(MEDHEADER)))) 194 return 0; 195 if (!(ms = (MEDSONG *)MikMod_malloc(sizeof(MEDSONG)))) 196 return 0; 197 return 1; 198} 199 200static void MED_Cleanup(void) 201{ 202 MikMod_free(me); 203 MikMod_free(mh); 204 MikMod_free(ms); 205 MikMod_free(ba); 206 MikMod_free(mmd0pat); 207 MikMod_free(mmd1pat); 208 me = NULL; 209 mh = NULL; 210 ms = NULL; 211 ba = NULL; 212 mmd0pat = NULL; 213 mmd1pat = NULL; 214} 215 216static UWORD MED_ConvertTempo(UWORD tempo) 217{ 218 /* MED tempos 1-10 are compatibility tempos that are converted to different values. 219 These were determined by testing with OctaMED 2.00 and roughly correspond to the 220 formula: (195 + speed/2) / speed. Despite being "tracker compatible" these really 221 are supposed to change the tempo and NOT the speed. These are tempo-mode only. */ 222 static const UBYTE tempocompat[11] = 223 { 224 0, 195, 97, 65, 49, 39, 32, 28, 24, 22, 20 225 }; 226 227 /* MEDs with 8 channels do something completely different with their tempos. 228 This behavior completely overrides normal timing when it is enabled. 229 NOTE: the tempos used for this are directly from OctaMED Soundstudio 2, but 230 in older versions the playback speeds differed slightly between NTSC and PAL. 231 This table seems to have been intended to be a compromise between the two.*/ 232 static const UBYTE tempo8channel[11] = 233 { 234 0, 179, 164, 152, 141, 131, 123, 116, 110, 104, 99 235 }; 236 237 ULONG result; 238 239 if (is8channel) { 240 tempo = tempo < 10 ? tempo : 10; 241 return tempo8channel[tempo]; 242 } 243 244 if (bpmtempos) { 245 /* Convert MED BPM into ProTracker-compatible BPM. All that really needs to be done 246 here is the BPM needs to be multiplied by (rows per beat)/(PT rows per beat = 4). 247 BPM mode doesn't have compatibility tempos like tempo mode but OctaMED does 248 something unusual with BPM<=2 that was found in electrosound 64.med. */ 249 result = (tempo > 2) ? ((ULONG)tempo * rowsperbeat + 2) / 4 : 125; 250 } else { 251 if (tempo >= 1 && tempo <= 10) 252 tempo = tempocompat[tempo]; 253 254 /* Convert MED tempo into ProTracker-compatble BPM. */ 255 result = ((ULONG)tempo * 125) / 33; 256 } 257 258 return result < 65535 ? result : 65535; 259} 260 261static void EffectCvt(UBYTE note, UBYTE eff, UBYTE dat) 262{ 263 switch (eff) { 264 /* 0x0: arpeggio */ 265 case 0x1: /* portamento up (PT compatible, ignore 0) */ 266 if (dat) 267 UniPTEffect(0x1, dat); 268 break; 269 case 0x2: /* portamento down (PT compatible, ignore 0) */ 270 if (dat) 271 UniPTEffect(0x2, dat); 272 break; 273 /* 0x3: tone portamento */ 274 case 0x4: /* vibrato (~2x the speed/depth of PT vibrato) */ 275 UniWriteByte(UNI_MEDEFFECT_VIB); 276 UniWriteByte((dat & 0xf0) >> 3); 277 UniWriteByte((dat & 0x0f) << 1); 278 break; 279 case 0x5: /* tone portamento + volslide (MMD0: old vibrato) */ 280 if (medversion == 0) { 281 /* Approximate conversion, probably wrong. 282 The entire param is depth and the rate is fixed. */ 283 UniWriteByte(UNI_MEDEFFECT_VIB); 284 UniWriteByte(0x16); 285 UniWriteByte((dat + 3) >> 2); 286 break; 287 } 288 UniPTEffect(eff, dat); 289 break; 290 /* 0x6: vibrato + volslide */ 291 /* 0x7: tremolo */ 292 case 0x8: /* set hold/decay (FIXME- hold/decay not implemented) */ 293 break; 294 case 0x9: /* set speed */ 295 /* TODO: Rarely MED modules request values of 0x00 or >0x20. In most Amiga versions 296 these behave as speed=(param & 0x1F) ? (param & 0x1F) : 32. From Soundstudio 2 297 up, these have different behavior. Since the docs/UI insist you shouldn't use 298 these values and not many modules use these, just ignore them for now. */ 299 if (dat >= 0x01 && dat <= 0x20) { 300 UniEffect(UNI_S3MEFFECTA, dat); 301 } 302 break; 303 /* 0xa: volslide */ 304 /* 0xb: position jump */ 305 case 0xc: 306 if (decimalvolumes) 307 dat = (dat >> 4) * 10 + (dat & 0xf); 308 UniPTEffect(0xc, dat); 309 break; 310 case 0xa: 311 case 0xd: /* same as PT volslide */ 312 /* if both nibbles are set, a slide up is performed. */ 313 if ((dat & 0xf) && (dat & 0xf0)) 314 dat &= 0xf0; 315 UniPTEffect(0xa, dat); 316 break; 317 case 0xe: /* synth jump (FIXME- synth instruments not implemented) */ 318 break; 319 case 0xf: 320 switch (dat) { 321 case 0: /* patternbreak */ 322 UniPTEffect(0xd, 0); 323 break; 324 case 0xf1: /* play note twice */ 325 /* Note: OctaMED 6.00d and up will not play FF1/FF3 effects when 326 they are used on a line without a note. Since MMD2/MMD3 support is 327 theoretical at this point, allow these unconditionally for now. */ 328 UniWriteByte(UNI_MEDEFFECTF1); 329 break; 330 case 0xf2: /* delay note */ 331 UniWriteByte(UNI_MEDEFFECTF2); 332 break; 333 case 0xf3: /* play note three times */ 334 UniWriteByte(UNI_MEDEFFECTF3); 335 break; 336 case 0xf8: /* hardware filter off */ 337 UniPTEffect(0xe, 0x01); 338 break; 339 case 0xf9: /* hardware filter on */ 340 UniPTEffect(0xe, 0x00); 341 break; 342 case 0xfd: /* set pitch */ 343 UniWriteByte(UNI_MEDEFFECT_FD); 344 break; 345 case 0xfe: /* stop playing */ 346 UniPTEffect(0xb, of.numpat); 347 break; 348 case 0xff: /* note cut */ 349 UniPTEffect(0xc, 0); 350 break; 351 default: 352 if (dat <= 240) 353 UniEffect(UNI_MEDSPEED, MED_ConvertTempo(dat)); 354 } 355 break; 356 case 0x11: /* fine portamento up */ 357 /* fine portamento of 0 does nothing. */ 358 if (dat) 359 UniEffect(UNI_XMEFFECTE1, dat); 360 break; 361 case 0x12: /* fine portamento down */ 362 if (dat) 363 UniEffect(UNI_XMEFFECTE2, dat); 364 break; 365 case 0x14: /* vibrato (PT compatible depth, ~2x speed) */ 366 UniWriteByte(UNI_MEDEFFECT_VIB); 367 UniWriteByte((dat & 0xf0) >> 3); 368 UniWriteByte((dat & 0x0f)); 369 break; 370 case 0x15: /* set finetune */ 371 /* Valid values are 0x0 to 0x7 and 0xF8 to 0xFF. */ 372 if (dat <= 0x7 || dat >= 0xF8) 373 UniPTEffect(0xe, 0x50 | (dat & 0xF)); 374 break; 375 case 0x16: /* loop */ 376 UniEffect(UNI_MEDEFFECT_16, dat); 377 break; 378 case 0x18: /* cut note */ 379 UniEffect(UNI_MEDEFFECT_18, dat); 380 break; 381 case 0x19: /* sample offset */ 382 UniPTEffect(0x9, dat); 383 break; 384 case 0x1a: /* fine volslide up */ 385 /* volslide of 0 does nothing. */ 386 if (dat) 387 UniEffect(UNI_XMEFFECTEA, dat); 388 break; 389 case 0x1b: /* fine volslide down */ 390 if (dat) 391 UniEffect(UNI_XMEFFECTEB, dat); 392 break; 393 case 0x1d: /* pattern break */ 394 UniPTEffect(0xd, dat); 395 break; 396 case 0x1e: /* pattern delay */ 397 UniEffect(UNI_MEDEFFECT_1E, dat); 398 break; 399 case 0x1f: /* combined delay-retrigger */ 400 /* This effect does nothing on lines without a note. */ 401 if (note) 402 UniEffect(UNI_MEDEFFECT_1F, dat); 403 break; 404 default: 405 if (eff < 0x10) 406 UniPTEffect(eff, dat); 407#ifdef MIKMOD_DEBUG 408 else 409 fprintf(stderr, "unsupported OctaMED command %u\n", eff); 410#endif 411 break; 412 } 413} 414 415static UBYTE *MED_Convert1(int count, int col) 416{ 417 int t; 418 UBYTE inst, note, eff, dat; 419 MMD1NOTE *n; 420 421 UniReset(); 422 for (t = 0; t < count; t++) { 423 n = &d1note(t, col); 424 425 note = n->a & 0x7f; 426 inst = n->b & 0x3f; 427 eff = n->c; 428 dat = n->d; 429 430 if (inst) 431 UniInstrument(inst - 1); 432 if (note) 433 UniNote(note - 1); 434 EffectCvt(note, eff, dat); 435 UniNewline(); 436 } 437 return UniDup(); 438} 439 440static UBYTE *MED_Convert0(int count, int col) 441{ 442 int t; 443 UBYTE a, b, inst, note, eff, dat; 444 MMD0NOTE *n; 445 446 UniReset(); 447 for (t = 0; t < count; t++) { 448 n = &d0note(t, col); 449 a = n->a; 450 b = n->b; 451 452 note = a & 0x3f; 453 a >>= 6; 454 a = ((a & 1) << 1) | (a >> 1); 455 inst = (b >> 4) | (a << 4); 456 eff = b & 0xf; 457 dat = n->c; 458 459 if (inst) 460 UniInstrument(inst - 1); 461 if (note) 462 UniNote(note - 1); 463 EffectCvt(note, eff, dat); 464 UniNewline(); 465 } 466 return UniDup(); 467} 468 469static int LoadMEDPatterns(void) 470{ 471 int t, row, col; 472 UWORD numtracks, numlines, maxlines = 0, track = 0; 473 MMD0NOTE *mmdp; 474 475 /* first, scan patterns to see how many channels are used */ 476 for (t = 0; t < of.numpat; t++) { 477 _mm_fseek(modreader, ba[t], SEEK_SET); 478 numtracks = _mm_read_UBYTE(modreader); 479 numlines = _mm_read_UBYTE(modreader); 480 481 if (numtracks > of.numchn) 482 of.numchn = numtracks; 483 if (numlines > maxlines) 484 maxlines = numlines; 485 /* sanity check */ 486 if (numtracks > 64) 487 return 0; 488 } 489 /* sanity check */ 490 if (! of.numchn || of.numchn > 16) /* docs say 4, 8, 12 or 16 */ 491 return 0; 492 493 of.numtrk = of.numpat * of.numchn; 494 if (!AllocTracks()) 495 return 0; 496 if (!AllocPatterns()) 497 return 0; 498 499 if (!(mmd0pat = (MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD0NOTE)))) 500 return 0; 501 502 /* second read: read and convert patterns */ 503 for (t = 0; t < of.numpat; t++) { 504 _mm_fseek(modreader, ba[t], SEEK_SET); 505 numtracks = _mm_read_UBYTE(modreader); 506 numlines = _mm_read_UBYTE(modreader); 507 508 of.pattrows[t] = ++numlines; 509 memset(mmdp = mmd0pat, 0, of.numchn * maxlines * sizeof(MMD0NOTE)); 510 for (row = numlines; row; row--) { 511 for (col = numtracks; col; col--, mmdp++) { 512 mmdp->a = _mm_read_UBYTE(modreader); 513 mmdp->b = _mm_read_UBYTE(modreader); 514 mmdp->c = _mm_read_UBYTE(modreader); 515 } 516 /* Skip tracks this block doesn't use. */ 517 for (col = numtracks; col < of.numchn; col++, mmdp++) {} 518 } 519 520 for (col = 0; col < of.numchn; col++) 521 of.tracks[track++] = MED_Convert0(numlines, col); 522 } 523 return 1; 524} 525 526static int LoadMMD1Patterns(void) 527{ 528 int t, row, col; 529 UWORD numtracks, numlines, maxlines = 0, track = 0; 530 MMD1NOTE *mmdp; 531 532 /* first, scan patterns to see how many channels are used */ 533 for (t = 0; t < of.numpat; t++) { 534 _mm_fseek(modreader, ba[t], SEEK_SET); 535 numtracks = _mm_read_M_UWORD(modreader); 536 numlines = _mm_read_M_UWORD(modreader); 537 if (numtracks > of.numchn) 538 of.numchn = numtracks; 539 if (numlines > maxlines) 540 maxlines = numlines; 541 /* sanity check */ 542 if (numtracks > 64) 543 return 0; 544 if (numlines >= 3200) /* per docs */ 545 return 0; 546 } 547 /* sanity check */ 548 if (! of.numchn || of.numchn > 16) /* docs say 4, 8, 12 or 16 */ 549 return 0; 550 551 of.numtrk = of.numpat * of.numchn; 552 if (!AllocTracks()) 553 return 0; 554 if (!AllocPatterns()) 555 return 0; 556 557 if (!(mmd1pat = (MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD1NOTE)))) 558 return 0; 559 560 /* second read: really read and convert patterns */ 561 for (t = 0; t < of.numpat; t++) { 562 _mm_fseek(modreader, ba[t], SEEK_SET); 563 numtracks = _mm_read_M_UWORD(modreader); 564 numlines = _mm_read_M_UWORD(modreader); 565 566 _mm_fseek(modreader, sizeof(ULONG), SEEK_CUR); 567 of.pattrows[t] = ++numlines; 568 memset(mmdp = mmd1pat, 0, of.numchn * maxlines * sizeof(MMD1NOTE)); 569 570 for (row = numlines; row; row--) { 571 for (col = numtracks; col; col--, mmdp++) { 572 mmdp->a = _mm_read_UBYTE(modreader); 573 mmdp->b = _mm_read_UBYTE(modreader); 574 mmdp->c = _mm_read_UBYTE(modreader); 575 mmdp->d = _mm_read_UBYTE(modreader); 576 } 577 /* Skip tracks this block doesn't use. */ 578 for (col = numtracks; col < of.numchn; col++, mmdp++) {} 579 } 580 581 for (col = 0; col < of.numchn; col++) 582 of.tracks[track++] = MED_Convert1(numlines, col); 583 } 584 return 1; 585} 586 587static int MED_Load(int curious) 588{ 589 int t, i; 590 ULONG sa[64]; 591 MEDINSTHEADER s; 592 INSTRUMENT *d; 593 SAMPLE *q; 594 MEDSAMPLE *mss; 595 596 /* try to read module header */ 597 mh->id = _mm_read_M_ULONG(modreader); 598 mh->modlen = _mm_read_M_ULONG(modreader); 599 mh->MEDSONGP = _mm_read_M_ULONG(modreader); 600 mh->psecnum = _mm_read_M_UWORD(modreader); 601 mh->pseq = _mm_read_M_UWORD(modreader); 602 mh->MEDBlockPP = _mm_read_M_ULONG(modreader); 603 mh->reserved1 = _mm_read_M_ULONG(modreader); 604 mh->MEDINSTHEADERPP = _mm_read_M_ULONG(modreader); 605 mh->reserved2 = _mm_read_M_ULONG(modreader); 606 mh->MEDEXPP = _mm_read_M_ULONG(modreader); 607 mh->reserved3 = _mm_read_M_ULONG(modreader); 608 mh->pstate = _mm_read_M_UWORD(modreader); 609 mh->pblock = _mm_read_M_UWORD(modreader); 610 mh->pline = _mm_read_M_UWORD(modreader); 611 mh->pseqnum = _mm_read_M_UWORD(modreader); 612 mh->actplayline = _mm_read_M_SWORD(modreader); 613 mh->counter = _mm_read_UBYTE(modreader); 614 mh->extra_songs = _mm_read_UBYTE(modreader); 615 616 /* Seek to MEDSONG struct */ 617 _mm_fseek(modreader, mh->MEDSONGP, SEEK_SET); 618 619 /* Load the MED Song Header */ 620 mss = ms->sample; /* load the sample data first */ 621 for (t = 63; t; t--, mss++) { 622 mss->rep = _mm_read_M_UWORD(modreader); 623 mss->replen = _mm_read_M_UWORD(modreader); 624 mss->midich = _mm_read_UBYTE(modreader); 625 mss->midipreset = _mm_read_UBYTE(modreader); 626 mss->svol = _mm_read_UBYTE(modreader); 627 mss->strans = _mm_read_SBYTE(modreader); 628 } 629 630 ms->numblocks = _mm_read_M_UWORD(modreader); 631 ms->songlen = _mm_read_M_UWORD(modreader); 632 _mm_read_UBYTES(ms->playseq, 256, modreader); 633 /* sanity check */ 634 if (ms->numblocks > 255 || ms->songlen > 256) { 635 _mm_errno = MMERR_NOT_A_MODULE; 636 return 0; 637 } 638 ms->deftempo = _mm_read_M_UWORD(modreader); 639 ms->playtransp = _mm_read_SBYTE(modreader); 640 ms->flags = _mm_read_UBYTE(modreader); 641 ms->flags2 = _mm_read_UBYTE(modreader); 642 ms->tempo2 = _mm_read_UBYTE(modreader); 643 _mm_read_UBYTES(ms->trkvol, 16, modreader); 644 ms->mastervol = _mm_read_UBYTE(modreader); 645 ms->numsamples = _mm_read_UBYTE(modreader); 646 /* sanity check */ 647 if (ms->numsamples > 64) { 648 _mm_errno = MMERR_NOT_A_MODULE; 649 return 0; 650 } 651 652 /* check for a bad header */ 653 if (_mm_eof(modreader)) { 654 _mm_errno = MMERR_LOADING_HEADER; 655 return 0; 656 } 657 658 /* load extension structure */ 659 if (mh->MEDEXPP) { 660 _mm_fseek(modreader, mh->MEDEXPP, SEEK_SET); 661 me->nextmod = _mm_read_M_ULONG(modreader); 662 me->exp_smp = _mm_read_M_ULONG(modreader); 663 me->s_ext_entries = _mm_read_M_UWORD(modreader); 664 me->s_ext_entrsz = _mm_read_M_UWORD(modreader); 665 me->annotxt = _mm_read_M_ULONG(modreader); 666 me->annolen = _mm_read_M_ULONG(modreader); 667 me->iinfo = _mm_read_M_ULONG(modreader); 668 me->i_ext_entries = _mm_read_M_UWORD(modreader); 669 me->i_ext_entrsz = _mm_read_M_UWORD(modreader); 670 me->jumpmask = _mm_read_M_ULONG(modreader); 671 me->rgbtable = _mm_read_M_ULONG(modreader); 672 me->channelsplit = _mm_read_M_ULONG(modreader); 673 me->n_info = _mm_read_M_ULONG(modreader); 674 me->songname = _mm_read_M_ULONG(modreader); 675 me->songnamelen = _mm_read_M_ULONG(modreader); 676 me->dumps = _mm_read_M_ULONG(modreader); 677 /* sanity check */ 678 if (me->annolen > 0xffff) { 679 _mm_errno = MMERR_NOT_A_MODULE; 680 return 0; 681 } 682 /* truncate insane songnamelen (fail instead?) */ 683 if (me->songnamelen > 256) 684 me->songnamelen = 256; 685 } 686 687 /* seek to and read the samplepointer array */ 688 _mm_fseek(modreader, mh->MEDINSTHEADERPP, SEEK_SET); 689 if (!_mm_read_M_ULONGS(sa, ms->numsamples, modreader)) { 690 _mm_errno = MMERR_LOADING_HEADER; 691 return 0; 692 } 693 694 /* alloc and read the blockpointer array */ 695 if (!(ba = (ULONG *)MikMod_calloc(ms->numblocks, sizeof(ULONG)))) 696 return 0; 697 _mm_fseek(modreader, mh->MEDBlockPP, SEEK_SET); 698 if (!_mm_read_M_ULONGS(ba, ms->numblocks, modreader)) { 699 _mm_errno = MMERR_LOADING_HEADER; 700 return 0; 701 } 702 703 /* copy song positions */ 704 if (!AllocPositions(ms->songlen)) 705 return 0; 706 for (t = 0; t < ms->songlen; t++) { 707 of.positions[t] = ms->playseq[t]; 708 if (of.positions[t]>ms->numblocks) { /* SANITIY CHECK */ 709 /* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],ms->numblocks);*/ 710 _mm_errno = MMERR_LOADING_HEADER; 711 return 0; 712 } 713 } 714 715 decimalvolumes = (ms->flags & 0x10) ? 0 : 1; 716 is8channel = (ms->flags & 0x40) ? 1 : 0; 717 bpmtempos = (ms->flags2 & 0x20) ? 1 : 0; 718 719 if (bpmtempos) { 720 rowsperbeat = (ms->flags2 & 0x1f) + 1; 721 of.initspeed = ms->tempo2; 722 of.inittempo = MED_ConvertTempo(ms->deftempo); 723 } else { 724 of.initspeed = ms->tempo2; 725 of.inittempo = ms->deftempo ? MED_ConvertTempo(ms->deftempo) : 128; 726 } 727 of.flags |= UF_HIGHBPM; 728 MED_Version[12] = mh->id; 729 of.modtype = MikMod_strdup(MED_Version); 730 of.numchn = 0; /* will be counted later */ 731 of.numpat = ms->numblocks; 732 of.numpos = ms->songlen; 733 of.numins = ms->numsamples; 734 of.numsmp = of.numins; 735 of.reppos = 0; 736 if ((mh->MEDEXPP) && (me->songname) && (me->songnamelen)) { 737 char *name; 738 739 _mm_fseek(modreader, me->songname, SEEK_SET); 740 name = (char *) MikMod_malloc(me->songnamelen); 741 _mm_read_UBYTES(name, me->songnamelen, modreader); 742 of.songname = DupStr(name, me->songnamelen, 1); 743 MikMod_free(name); 744 } else 745 of.songname = DupStr(NULL, 0, 0); 746 if ((mh->MEDEXPP) && (me->annotxt) && (me->annolen)) { 747 _mm_fseek(modreader, me->annotxt, SEEK_SET); 748 ReadComment(me->annolen); 749 } 750 751 /* TODO: should do an initial scan for IFFOCT instruments to determine the 752 actual number of samples (instead of assuming 1-to-1). */ 753 if (!AllocSamples() || !AllocInstruments()) 754 return 0; 755 756 of.flags |= UF_INST; 757 q = of.samples; 758 d = of.instruments; 759 for (t = 0; t < of.numins; t++) { 760 q->flags = SF_SIGNED; 761 q->volume = 64; 762 s.type = INST_SAMPLE; 763 if (sa[t]) { 764 _mm_fseek(modreader, sa[t], SEEK_SET); 765 s.length = _mm_read_M_ULONG(modreader); 766 s.type = _mm_read_M_SWORD(modreader); 767 768 switch (s.type) { 769 case INST_SAMPLE: 770 case INST_EXTSAMPLE: 771 break; 772 773 default: 774#ifdef MIKMOD_DEBUG 775 fprintf(stderr, "\rNon-sample instruments not supported in MED loader yet\n"); 776#endif 777 if (!curious) { 778 _mm_errno = MMERR_MED_SYNTHSAMPLES; 779 return 0; 780 } 781 s.length = 0; 782 } 783 784 if (_mm_eof(modreader)) { 785 _mm_errno = MMERR_LOADING_SAMPLEINFO; 786 return 0; 787 } 788 789 q->length = s.length; 790 q->seekpos = _mm_ftell(modreader); 791 q->loopstart = ms->sample[t].rep << 1; 792 q->loopend = q->loopstart + (ms->sample[t].replen << 1); 793 794 if (ms->sample[t].replen > 1) 795 q->flags |= SF_LOOP; 796 797 if(ms->sample[t].svol <= 64) 798 q->volume = ms->sample[t].svol; 799 800 /* don't load sample if length>='MMD0'... 801 such kluges make libmikmod's code unique !!! */ 802 if (q->length >= MMD0_string) 803 q->length = 0; 804 } else 805 q->length = 0; 806 807 if ((mh->MEDEXPP) && (me->exp_smp) && 808 (t < me->s_ext_entries) && (me->s_ext_entrsz >= 4)) { 809 MEDINSTEXT ie; 810 811 _mm_fseek(modreader, me->exp_smp + t * me->s_ext_entrsz, 812 SEEK_SET); 813 ie.hold = _mm_read_UBYTE(modreader); 814 ie.decay = _mm_read_UBYTE(modreader); 815 ie.suppress_midi_off = _mm_read_UBYTE(modreader); 816 ie.finetune = _mm_read_SBYTE(modreader); 817 818 q->speed = finetune[ie.finetune & 0xf]; 819 } else 820 q->speed = 8363; 821 822 if ((mh->MEDEXPP) && (me->iinfo) && 823 (t < me->i_ext_entries) && (me->i_ext_entrsz >= 40)) { 824 MEDINSTINFO ii; 825 826 _mm_fseek(modreader, me->iinfo + t * me->i_ext_entrsz, SEEK_SET); 827 _mm_read_UBYTES(ii.name, 40, modreader); 828 q->samplename = DupStr((char*)ii.name, 40, 1); 829 d->insname = DupStr((char*)ii.name, 40, 1); 830 } else { 831 q->samplename = NULL; 832 d->insname = NULL; 833 } 834 835 /* Instrument transpose tables. */ 836 for (i = 0; i < MEDNOTECNT; i++) { 837 int note = i + 3 * OCTAVE + ms->sample[t].strans + ms->playtransp; 838 839 /* TODO: IFFOCT instruments... */ 840 switch (s.type) { 841 case INST_EXTSAMPLE: 842 /* TODO: not clear if this has the same wrapping behavior as regular samples. 843 This is a MMD2/MMD3 extension so it has not been tested. */ 844 note -= 2 * OCTAVE; 845 /* fall-through */ 846 847 case INST_SAMPLE: 848 /* TODO: in MMD2/MMD3 mixing mode, these wrapping transforms don't apply. */ 849 if (note >= 10 * OCTAVE) { 850 /* Buggy octaves 8 through A wrap to 2 octaves below octave 1. 851 Technically they're also a finetune step higher but that's safe 852 to ignore. */ 853 note -= 9 * OCTAVE; 854 } else if (note >= 6 * OCTAVE) { 855 /* Octaves 4 through 7 repeat octave 3. */ 856 note = (note % 12) + 5 * OCTAVE; 857 } 858 d->samplenumber[i] = t; 859 d->samplenote[i] = note<0 ? 0 : note>255 ? 255 : note; 860 break; 861 } 862 } 863 864 q++; 865 d++; 866 } 867 868 if (mh->id == MMD0_string) { 869 medversion = 0; 870 if (!LoadMEDPatterns()) { 871 _mm_errno = MMERR_LOADING_PATTERN; 872 return 0; 873 } 874 } else if (mh->id == MMD1_string) { 875 medversion = 1; 876 if (!LoadMMD1Patterns()) { 877 _mm_errno = MMERR_LOADING_PATTERN; 878 return 0; 879 } 880 } else { 881 _mm_errno = MMERR_NOT_A_MODULE; 882 return 0; 883 } 884 return 1; 885} 886 887static CHAR *MED_LoadTitle(void) 888{ 889 ULONG posit, namelen; 890 CHAR *name, *retvalue = NULL; 891 892 _mm_fseek(modreader, 0x20, SEEK_SET); 893 posit = _mm_read_M_ULONG(modreader); 894 895 if (posit) { 896 _mm_fseek(modreader, posit + 0x2C, SEEK_SET); 897 posit = _mm_read_M_ULONG(modreader); 898 namelen = _mm_read_M_ULONG(modreader); 899 900 _mm_fseek(modreader, posit, SEEK_SET); 901 name = (CHAR*) MikMod_malloc(namelen); 902 _mm_read_UBYTES(name, namelen, modreader); 903 retvalue = DupStr(name, namelen, 1); 904 MikMod_free(name); 905 } 906 907 return retvalue; 908} 909 910/*========== Loader information */ 911 912MIKMODAPI MLOADER load_med = { 913 NULL, 914 "MED", 915 "MED (OctaMED)", 916 MED_Init, 917 MED_Test, 918 MED_Load, 919 MED_Cleanup, 920 MED_LoadTitle 921}; 922 923/* ex:set ts=4: */