ULONG _mm_read_M_ULONG (URL reader) { ULONG result = ((ULONG) _mm_read_M_UWORD (reader)) << 16; result |= _mm_read_M_UWORD (reader); return result; }
/* Read sample information */ static BOOL OKT_doSAMP(int len) { int t; SAMPLE *q; OKTSAMPLE s; of.numins = of.numsmp = (len / 0x20); if (!AllocSamples()) return 0; for (t = 0, q = of.samples; t < of.numins; t++, q++) { _mm_read_UBYTES(s.sampname, 20, modreader); s.len = _mm_read_M_ULONG(modreader); s.loopbeg = _mm_read_M_UWORD(modreader); s.looplen = _mm_read_M_UWORD(modreader); _mm_read_UBYTE(modreader); s.volume = _mm_read_UBYTE(modreader); _mm_read_M_UWORD(modreader); if (_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } if (!s.len) q->seekpos = q->length = q->loopstart = q->loopend = q->flags = 0; else { s.len--; /* sanity checks */ if (s.loopbeg > s.len) s.loopbeg = s.len; if (s.loopbeg + s.looplen > s.len) s.looplen = s.len - s.loopbeg; if (s.looplen < 2) s.looplen = 0; q->length = s.len; q->loopstart = s.loopbeg; q->loopend = s.looplen + q->loopstart; q->volume = s.volume; q->flags = SF_SIGNED; if (s.looplen) q->flags |= SF_LOOP; } q->samplename = DupStr(s.sampname, 20, 1); q->speed = 8363; } return 1; }
/* Read "channel modes" i.e. channel number and panning information */ static void OKT_doCMOD(void) { /* amiga channel panning table */ UBYTE amigapan[4] = { 0x00, 0xff, 0xff, 0x00 }; int t; of.numchn = 0; for (t = 0; t < 4; t++) if (_mm_read_M_UWORD(modreader)) { /* two channels tied to the same Amiga hardware voice */ of.panning[of.numchn++] = amigapan[t]; of.panning[of.numchn++] = amigapan[t]; } else /* one channel tied to the Amiga hardware voice */ of.panning[of.numchn++] = amigapan[t]; }
static BOOL OKT_doPBOD(int patnum) { char *patbuf; int rows, i; int u; if (!patnum) { of.numtrk = of.numpat * of.numchn; if (!AllocTracks() || !AllocPatterns()) return 0; } /* Read pattern */ of.pattrows[patnum] = rows = _mm_read_M_UWORD(modreader); if (!(okttrk = (OKTNOTE *) _mm_calloc(rows, sizeof(OKTNOTE))) || !(patbuf = (char *)_mm_calloc(rows * of.numchn, sizeof(OKTNOTE)))) return 0; _mm_read_UBYTES(patbuf, rows * of.numchn * sizeof(OKTNOTE), modreader); if (_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } for (i = 0; i < of.numchn; i++) { for (u = 0; u < rows; u++) { okttrk[u].note = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE)]; okttrk[u].ins = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 1]; okttrk[u].eff = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 2]; okttrk[u].dat = patbuf[(u * of.numchn + i) * sizeof(OKTNOTE) + 3]; } if (!(of.tracks[patnum * of.numchn + i] = OKT_ConvertTrack(rows))) return 0; } _mm_free(patbuf); _mm_free(okttrk); return 1; }
SWORD _mm_read_M_SWORD (URL reader) { return ((SWORD) _mm_read_M_UWORD (reader)); }
/* Read pattern length information */ static void OKT_doPLEN(void) { of.numpos = _mm_read_M_UWORD(modreader); }
/* Read song length information */ static void OKT_doSLEN(void) { of.numpat = _mm_read_M_UWORD(modreader); }
/* Read speed information */ static void OKT_doSPEE(void) { int tempo = _mm_read_M_UWORD(modreader); of.initspeed = tempo; }
static BOOL UNI_Load(BOOL curious) { int t; char *modtype,*oldtype=NULL; INSTRUMENT *d; SAMPLE *q; /* read module header */ _mm_read_UBYTES(mh.id,4,modreader); if(mh.id[3]!='N') universion=mh.id[3]-'0'; else universion=0x100; if(universion>=6) { if (universion==6) { _mm_skip_BYTE(modreader); } else { universion=_mm_read_M_UWORD(modreader); } mh.flags =_mm_read_M_UWORD(modreader); mh.numchn =_mm_read_UBYTE(modreader); mh.numvoices =_mm_read_UBYTE(modreader); mh.numpos =_mm_read_M_UWORD(modreader); mh.numpat =_mm_read_M_UWORD(modreader); mh.numtrk =_mm_read_M_UWORD(modreader); mh.numins =_mm_read_M_UWORD(modreader); mh.numsmp =_mm_read_M_UWORD(modreader); mh.reppos =_mm_read_M_UWORD(modreader); mh.initspeed =_mm_read_UBYTE(modreader); mh.inittempo =_mm_read_UBYTE(modreader); mh.initvolume=_mm_read_UBYTE(modreader); /* I expect this to show up soon in APlayer 1.06 format */ if (universion >= 0x106) mh.bpmlimit=_mm_read_M_UWORD(modreader); else mh.bpmlimit=32; mh.flags &= UF_XMPERIODS | UF_LINEAR | UF_INST | UF_NNA; mh.flags |= UF_PANNING; } else { mh.numchn =_mm_read_UBYTE(modreader); mh.numpos =_mm_read_I_UWORD(modreader); mh.reppos =(universion==5)?_mm_read_I_UWORD(modreader):0; mh.numpat =_mm_read_I_UWORD(modreader); mh.numtrk =_mm_read_I_UWORD(modreader); mh.numins =_mm_read_I_UWORD(modreader); mh.initspeed =_mm_read_UBYTE(modreader); mh.inittempo =_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh.positions,256,modreader); _mm_read_UBYTES(mh.panning,32,modreader); mh.flags =_mm_read_UBYTE(modreader); mh.bpmlimit =32; mh.flags &= UF_XMPERIODS | UF_LINEAR; mh.flags |= UF_INST | UF_NOWRAP | UF_PANNING; } /* set module parameters */ of.flags =mh.flags; of.numchn =mh.numchn; of.numpos =mh.numpos; of.numpat =mh.numpat; of.numtrk =mh.numtrk; of.numins =mh.numins; of.reppos =mh.reppos; of.initspeed =mh.initspeed; of.inittempo =mh.inittempo; if(mh.bpmlimit) of.bpmlimit=mh.bpmlimit; else /* be bug-compatible with older releases */ of.bpmlimit=32; of.songname=readstring(); if(universion<0x102) oldtype=readstring(); if(oldtype) { size_t len=strlen(oldtype)+20; if(!(modtype=(char*)MikMod_malloc(len))) return 0; #ifdef HAVE_SNPRINTF snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); #else sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); #endif } else { if(!(modtype=(char*)MikMod_malloc(10))) return 0; #ifdef HAVE_SNPRINTF snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); #else sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); #endif } of.modtype=MikMod_strdup(modtype); MikMod_free(modtype);MikMod_free(oldtype); of.comment=readstring(); if(universion>=6) { of.numvoices=mh.numvoices; of.initvolume=mh.initvolume; } if(_mm_eof(modreader)) { _mm_errno=MMERR_LOADING_HEADER; return 0; } /* positions */ if(!AllocPositions(of.numpos)) return 0; if(universion>=6) { if(universion>=0x100) _mm_read_M_UWORDS(of.positions,of.numpos,modreader); else for(t=0;t<of.numpos;t++) of.positions[t]=_mm_read_UBYTE(modreader); _mm_read_M_UWORDS(of.panning,of.numchn,modreader); _mm_read_UBYTES(of.chanvol,of.numchn,modreader); } else { if((mh.numpos>256)||(mh.numchn>32)) { _mm_errno=MMERR_LOADING_HEADER; return 0; } for(t=0;t<of.numpos;t++) of.positions[t]=mh.positions[t]; for(t=0;t<of.numchn;t++) of.panning[t]=mh.panning[t]; } /* convert the ``end of song'' pattern code if necessary */ if(universion<0x106) for(t=0;t<of.numpos;t++) if(of.positions[t]==255) of.positions[t]=LAST_PATTERN; /* instruments and samples */ if(universion>=6) { of.numsmp=mh.numsmp; if(!AllocSamples()) return 0; if(!loadsmp6()) return 0; if(of.flags&UF_INST) { if(!AllocInstruments()) return 0; if(!loadinstr6()) return 0; } } else { if(!AllocInstruments()) return 0; if(!loadinstr5()) return 0; if(!AllocSamples()) { MikMod_free(wh);wh=NULL; return 0; } if(!loadsmp5()) return 0; /* check if the original file had no instruments */ if(of.numsmp==of.numins) { for(t=0,d=of.instruments;t<of.numins;t++,d++) { int u; if((d->volpts)||(d->panpts)||(d->globvol!=64)) break; for(u=0;u<96;u++) if((d->samplenumber[u]!=t)||(d->samplenote[u]!=u)) break; if(u!=96) break; } if(t==of.numins) { of.flags&=~UF_INST; of.flags&=~UF_NOWRAP; for(t=0,d=of.instruments,q=of.samples;t<of.numins;t++,d++,q++) { q->samplename=d->insname; d->insname=NULL; } } } } /* patterns */ if(!AllocPatterns()) return 0; if(universion>=6) { _mm_read_M_UWORDS(of.pattrows,of.numpat,modreader); _mm_read_M_UWORDS(of.patterns,of.numpat*of.numchn,modreader); } else { _mm_read_I_UWORDS(of.pattrows,of.numpat,modreader); _mm_read_I_UWORDS(of.patterns,of.numpat*of.numchn,modreader); } /* tracks */ if(!AllocTracks()) return 0; for(t=0;t<of.numtrk;t++) if(!(of.tracks[t]=readtrack())) { _mm_errno=MMERR_LOADING_TRACK; return 0; } return 1; }
static BOOL loadsmp6(void) { int t; SAMPLE *sptr; sptr=of.samples; for(t=0;t<of.numsmp;t++,sptr++) { int flags; flags = _mm_read_M_UWORD(modreader); sptr->flags=0; if(flags&0x0004) sptr->flags|=SF_STEREO; if(flags&0x0002) sptr->flags|=SF_SIGNED; if(flags&0x0001) sptr->flags|=SF_16BITS; /* convert flags */ if(universion>=0x104) { if(flags&0x2000) sptr->flags|=SF_UST_LOOP; if(flags&0x1000) sptr->flags|=SF_OWNPAN; if(flags&0x0800) sptr->flags|=SF_SUSTAIN; if(flags&0x0400) sptr->flags|=SF_REVERSE; if(flags&0x0200) sptr->flags|=SF_BIDI; if(flags&0x0100) sptr->flags|=SF_LOOP; if(flags&0x0020) sptr->flags|=SF_ITPACKED; if(flags&0x0010) sptr->flags|=SF_DELTA; if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN; } else if(universion>=0x102) { if(flags&0x0800) sptr->flags|=SF_UST_LOOP; if(flags&0x0400) sptr->flags|=SF_OWNPAN; if(flags&0x0200) sptr->flags|=SF_SUSTAIN; if(flags&0x0100) sptr->flags|=SF_REVERSE; if(flags&0x0080) sptr->flags|=SF_BIDI; if(flags&0x0040) sptr->flags|=SF_LOOP; if(flags&0x0020) sptr->flags|=SF_ITPACKED; if(flags&0x0010) sptr->flags|=SF_DELTA; if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN; } else { if(flags&0x400) sptr->flags|=SF_UST_LOOP; if(flags&0x200) sptr->flags|=SF_OWNPAN; if(flags&0x100) sptr->flags|=SF_REVERSE; if(flags&0x080) sptr->flags|=SF_SUSTAIN; if(flags&0x040) sptr->flags|=SF_BIDI; if(flags&0x020) sptr->flags|=SF_LOOP; if(flags&0x010) sptr->flags|=SF_BIG_ENDIAN; if(flags&0x008) sptr->flags|=SF_DELTA; } sptr->speed = _mm_read_M_ULONG(modreader); sptr->volume = _mm_read_UBYTE(modreader); sptr->panning = _mm_read_M_UWORD(modreader); sptr->length = _mm_read_M_ULONG(modreader); sptr->loopstart = _mm_read_M_ULONG(modreader); sptr->loopend = _mm_read_M_ULONG(modreader); sptr->susbegin = _mm_read_M_ULONG(modreader); sptr->susend = _mm_read_M_ULONG(modreader); sptr->globvol = _mm_read_UBYTE(modreader); sptr->vibflags = _mm_read_UBYTE(modreader); sptr->vibtype = _mm_read_UBYTE(modreader); sptr->vibsweep = _mm_read_UBYTE(modreader); sptr->vibdepth = _mm_read_UBYTE(modreader); sptr->vibrate = _mm_read_UBYTE(modreader); sptr->samplename=readstring(); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } } return 1; }
static BOOL loadinstr6(void) { int t,w; INSTRUMENT *i; i=of.instruments; for(t=0;t<of.numins;t++,i++) { i->flags = _mm_read_UBYTE(modreader); i->nnatype = _mm_read_UBYTE(modreader); i->dca = _mm_read_UBYTE(modreader); i->dct = _mm_read_UBYTE(modreader); i->globvol = _mm_read_UBYTE(modreader); i->panning = _mm_read_M_UWORD(modreader); i->pitpansep = _mm_read_UBYTE(modreader); i->pitpancenter = _mm_read_UBYTE(modreader); i->rvolvar = _mm_read_UBYTE(modreader); i->rpanvar = _mm_read_UBYTE(modreader); i->volfade = _mm_read_M_UWORD(modreader); #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define UNI_LoadEnvelope6(name) \ i-> name##flg=_mm_read_UBYTE(modreader); \ i-> name##pts=_mm_read_UBYTE(modreader); \ i-> name##susbeg=_mm_read_UBYTE(modreader); \ i-> name##susend=_mm_read_UBYTE(modreader); \ i-> name##beg=_mm_read_UBYTE(modreader); \ i-> name##end=_mm_read_UBYTE(modreader); \ for(w=0;w<(universion>=0x100?32:i-> name##pts);w++) { \ i-> name##env[w].pos=_mm_read_M_SWORD(modreader); \ i-> name##env[w].val=_mm_read_M_SWORD(modreader); \ } #else #define UNI_LoadEnvelope6(name) \ i-> name/**/flg=_mm_read_UBYTE(modreader); \ i-> name/**/pts=_mm_read_UBYTE(modreader); \ i-> name/**/susbeg=_mm_read_UBYTE(modreader); \ i-> name/**/susend=_mm_read_UBYTE(modreader); \ i-> name/**/beg=_mm_read_UBYTE(modreader); \ i-> name/**/end=_mm_read_UBYTE(modreader); \ for (w=0;w<(universion>=0x100?32:i-> name/**/pts);w++) { \ i-> name/**/env[w].pos=_mm_read_M_SWORD(modreader); \ i-> name/**/env[w].val=_mm_read_M_SWORD(modreader); \ } #endif UNI_LoadEnvelope6(vol); UNI_LoadEnvelope6(pan); UNI_LoadEnvelope6(pit); #undef UNI_LoadEnvelope6 if(universion>=0x103) _mm_read_M_UWORDS(i->samplenumber,120,modreader); else for(w=0;w<120;w++) i->samplenumber[w]=_mm_read_UBYTE(modreader); _mm_read_UBYTES(i->samplenote,120,modreader); i->insname=readstring(); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } } return 1; }
static UBYTE* readtrack(void) { UBYTE *t; UWORD len; int cur=0,chunk; if(universion>=6) len=_mm_read_M_UWORD(modreader); else len=_mm_read_I_UWORD(modreader); if(!len) return NULL; if(!(t=(UBYTE*)MikMod_malloc(len))) return NULL; _mm_read_UBYTES(t,len,modreader); /* Check if the track is correct */ while(1) { chunk=t[cur++]; if(!chunk) break; chunk=(chunk&0x1f)-1; while(chunk>0) { int opcode,oplen; if(cur>=len) { MikMod_free(t); return NULL; } opcode=t[cur]; /* Remap opcodes */ if (universion <= 5) { if (opcode > 29) { MikMod_free(t); return NULL; } switch (opcode) { /* UNI_NOTE .. UNI_S3MEFFECTQ are the same */ case 25: opcode = UNI_S3MEFFECTT; break; case 26: opcode = UNI_XMEFFECTA; break; case 27: opcode = UNI_XMEFFECTG; break; case 28: opcode = UNI_XMEFFECTH; break; case 29: opcode = UNI_XMEFFECTP; break; } } else { /* APlayer < 1.05 does not have XMEFFECT6 */ if (opcode >= UNI_XMEFFECT6 && universion < 0x105) opcode++; /* APlayer < 1.03 does not have ITEFFECTT */ if (opcode >= UNI_ITEFFECTT && universion < 0x103) opcode++; /* APlayer < 1.02 does not have ITEFFECTZ */ if (opcode >= UNI_ITEFFECTZ && universion < 0x102) opcode++; } if((!opcode)||(opcode>=UNI_LAST)) { MikMod_free(t); return NULL; } t[cur]=opcode; oplen=unioperands[opcode]+1; cur+=oplen; chunk-=oplen; } if((chunk<0)||(cur>=len)) { MikMod_free(t); return NULL; } } return t; }
static GT_CHUNK *loadChunk(void) { GT_CHUNK *new_chunk = (GT_CHUNK *) MikMod_malloc(sizeof(GT_CHUNK)); if (!new_chunk) return NULL; /* the file chunk id only use 3 bytes, others 4 */ _mm_read_UBYTES(new_chunk->id, 3, modreader); if (memcmp(new_chunk, "GT2", 3) != 0) { _mm_read_UBYTES(&new_chunk->id[3], 1, modreader); } else { new_chunk->id[3] = ' '; } #ifdef MIKMOD_DEBUG fprintf(stderr, ">> %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]); #endif if (!memcmp(new_chunk, "GT2", 3)) { _mm_read_UBYTES(&new_chunk->gt2.version, 1, modreader); _mm_read_M_ULONGS(&new_chunk->gt2.chunk_size, 1, modreader); new_chunk->gt2.module_name[32] = 0; _mm_read_UBYTES(&new_chunk->gt2.module_name, 32, modreader); new_chunk->gt2.comments_author[160] = 0; _mm_read_UBYTES(&new_chunk->gt2.comments_author, 160, modreader); _mm_read_UBYTES(&new_chunk->gt2.date_day, 1, modreader); _mm_read_UBYTES(&new_chunk->gt2.date_month, 1, modreader); _mm_read_M_UWORDS(&new_chunk->gt2.date_year, 1, modreader); new_chunk->gt2.tracker_name[24] = 0; _mm_read_UBYTES(&new_chunk->gt2.tracker_name, 24, modreader); if (new_chunk->gt2.version > 5) return new_chunk; _mm_read_M_UWORDS(&new_chunk->gt2.initial_speed, 1, modreader); _mm_read_M_UWORDS(&new_chunk->gt2.initial_tempo, 1, modreader); _mm_read_M_UWORDS(&new_chunk->gt2.initial_master_volume, 1, modreader); _mm_read_M_UWORDS(&new_chunk->gt2.num_voices, 1, modreader); new_chunk->gt2.voice_pannings = (UWORD *) MikMod_malloc(2*new_chunk->gt2.num_voices); if (new_chunk->gt2.voice_pannings == NULL) goto fail; _mm_read_M_UWORDS(new_chunk->gt2.voice_pannings, new_chunk->gt2.num_voices, modreader); return new_chunk; } if (!memcmp(new_chunk, "TVOL", 4)) { new_chunk->tvol.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->tvol.num_tracks = _mm_read_M_UWORD(modreader); new_chunk->tvol.track_volumes = (UWORD *) MikMod_malloc(new_chunk->tvol.num_tracks * 2); if (new_chunk->tvol.track_volumes == NULL) goto fail; _mm_read_M_UWORDS(new_chunk->tvol.track_volumes, new_chunk->tvol.num_tracks, modreader); return new_chunk; } if (!memcmp(new_chunk, "XCOM", 4)) { new_chunk->xcom.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->xcom.comment_len = _mm_read_M_UWORD(modreader); if (!new_chunk->xcom.comment_len) { new_chunk->xcom.comment = NULL; return new_chunk; } new_chunk->xcom.comment = (CHAR *) MikMod_malloc((ULONG)new_chunk->xcom.comment_len + 1); if (new_chunk->xcom.comment == NULL) goto fail; _mm_read_UBYTES(new_chunk->xcom.comment, new_chunk->xcom.comment_len, modreader); return new_chunk; } if (!memcmp(new_chunk, "SONG", 4)) { new_chunk->song.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->song.song_length = _mm_read_M_UWORD(modreader); new_chunk->song.song_repeat_point = _mm_read_M_UWORD(modreader); new_chunk->song.patterns = (UWORD *) MikMod_malloc(2*new_chunk->song.song_length); if (new_chunk->song.patterns == NULL) goto fail; _mm_read_M_UWORDS(new_chunk->song.patterns, new_chunk->song.song_length, modreader); return new_chunk; } if (!memcmp(new_chunk, "PATS", 4)) { new_chunk->pats.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->pats.num_tracks = _mm_read_M_UWORD(modreader); new_chunk->pats.num_patterns = _mm_read_M_UWORD(modreader); return new_chunk; } if (!memcmp(new_chunk, "PATD", 4)) { new_chunk->patd.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->patd.pattern_number = _mm_read_M_UWORD(modreader); new_chunk->patd.pattern_name[16] = 0; _mm_read_UBYTES(new_chunk->patd.pattern_name, 16, modreader); new_chunk->patd.codage_version = _mm_read_M_UWORD(modreader); new_chunk->patd.num_lines = _mm_read_M_UWORD(modreader); new_chunk->patd.num_tracks = _mm_read_M_UWORD(modreader); new_chunk->patd.notes = (GT_NOTE *) MikMod_malloc(5 * new_chunk->patd.num_lines * new_chunk->patd.num_tracks); if (new_chunk->patd.notes == NULL) goto fail; _mm_read_UBYTES(new_chunk->patd.notes, new_chunk->patd.num_lines * new_chunk->patd.num_tracks * 5, modreader); return new_chunk; } if (!memcmp(new_chunk, "ORCH", 4)) { new_chunk->orch.chunk_size = _mm_read_M_ULONG(modreader); new_chunk->orch.num_instruments = _mm_read_M_UWORD(modreader); return new_chunk; } if (!memcmp(new_chunk, "INST", 4)) { return new_chunk; } if (!memcmp(new_chunk, "SAMP", 4)) { return new_chunk; } if (!memcmp(new_chunk, "VENV", 4)) { return new_chunk; } if (!memcmp(new_chunk, "TENV", 4)) { return new_chunk; } if (!memcmp(new_chunk, "PENV", 4)) { return new_chunk; } if (!memcmp(new_chunk, "ENDC", 4)) { return new_chunk; } #ifdef MIKMOD_DEBUG fprintf(stderr, "?? %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]); #endif fail: MikMod_free(new_chunk); return NULL; /* unknown chunk */ }
static BOOL MOD_Load(void) { int t,modtype; INSTRUMENT *d; /* new sampleinfo structure */ SAMPLE *q; MSAMPINFO *s; /* old module sampleinfo */ /* try to read module header */ _mm_read_str((char *)mh_mod->songname,20); for(t=0;t<31;t++){ s=&mh_mod->samples[t]; _mm_read_str(s->samplename,22); s->length =_mm_read_M_UWORD(); s->finetune =_mm_read_UBYTE(); s->volume =_mm_read_UBYTE(); s->reppos =_mm_read_M_UWORD(); s->replen =_mm_read_M_UWORD(); } mh_mod->songlength =_mm_read_UBYTE(); mh_mod->magic1 =_mm_read_UBYTE(); _mm_read_UBYTES(mh_mod->positions,128); _mm_read_UBYTES(mh_mod->magic2,4); if(modpos > modsize){ gModPlayerErrorMessage=ERROR_LOADING_HEADER; return 0; } /* find out which ID string */ for(modtype=0;modtype<10;modtype++){ if(!memcmp(mh_mod->magic2,modtypes[modtype].id,4)) break; } if(modtype==10){ /* unknown modtype */ gModPlayerErrorMessage=ERROR_NOT_A_MODULE; return 0; } /* set module variables */ of.initspeed=6; of.inittempo=125; of.numchn=modtypes[modtype].channels; /* get number of channels */ of.modtype=strdup(modtypes[modtype].name); /* get ascii type of mod */ of.songname=DupStr(mh_mod->songname,20); /* make a cstr of songname */ of.numpos=mh_mod->songlength; /* copy the songlength */ memcpy(of.positions,mh_mod->positions,128); /* copy the position array */ /* Count the number of patterns */ of.numpat=0; for(t=0;t<128;t++){ /* <-- BUGFIX... have to check ALL positions */ if(of.positions[t] > of.numpat){ of.numpat=of.positions[t]; } } of.numpat++; of.numtrk=of.numpat*of.numchn; /* Finally, init the sampleinfo structures */ of.numins=31; if(!AllocInstruments()) return 0; s=mh_mod->samples; /* init source pointer */ d=of.instruments; /* init dest pointer */ for(t=0;t<of.numins;t++){ d->numsmp=1; if(!AllocSamples(d)) return 0; q=d->samples; /* convert the samplename */ d->insname=DupStr(s->samplename,22); /* init the sampleinfo variables and convert the size pointers to longword format */ q->c2spd=finetune[s->finetune&0xf]; q->volume=s->volume; q->loopstart=(ULONG)s->reppos<<1; q->loopend=q->loopstart+((ULONG)s->replen<<1); q->length=(ULONG)s->length<<1; q->seekpos=0; q->flags=SF_SIGNED; if(s->replen>1) q->flags|=SF_LOOP; /* fix replen if repend>length */ if(q->loopend>q->length) q->loopend=q->length; s++; /* point to next source sampleinfo */ d++; /* point to next destiny sampleinfo */ } if(!ML_LoadPatterns()) return 0; return 1; }
SWORD _mm_read_M_SWORD() { return((SWORD)_mm_read_M_UWORD()); }
ULONG _mm_read_M_ULONG() { ULONG result=((ULONG)_mm_read_M_UWORD())<<16L; result|=_mm_read_M_UWORD(); return result; }