public override bool Load(int curious) { INSTRUMENT d; SAMPLE q; int t, u; bool dummypat = false; char[] tracker = new char[21]; //char[] modtype = new char[60]; /* try to read module header */ mh.id = m_Reader.Read_String(17); mh.songname = m_Reader.Read_String(21); mh.trackername = m_Reader.Read_String(20); mh.version = m_Reader.Read_Intel_ushort(); if ((mh.version < 0x102) || (mh.version > 0x104)) { m_LoadError = MMERR_NOT_A_MODULE; return(false); } mh.headersize = m_Reader.Read_Intel_uint(); mh.songlength = m_Reader.Read_Intel_ushort(); mh.restart = m_Reader.Read_Intel_ushort(); mh.numchn = m_Reader.Read_Intel_ushort(); mh.numpat = m_Reader.Read_Intel_ushort(); mh.numins = m_Reader.Read_Intel_ushort(); mh.flags = m_Reader.Read_Intel_ushort(); mh.tempo = m_Reader.Read_Intel_ushort(); mh.bpm = m_Reader.Read_Intel_ushort(); if (mh.bpm == 0 || mh.songlength > 256) { m_LoadError = MMERR_NOT_A_MODULE; return(false); } m_Reader.Read_bytes(mh.orders, mh.songlength); if (!m_Reader.Seek((int)(mh.headersize + 60), SeekOrigin.Begin) || m_Reader.isEOF()) { m_LoadError = MMERR_LOADING_HEADER; return(false); } /* set module variables */ m_Module.initspeed = (byte)mh.tempo; m_Module.inittempo = mh.bpm; tracker = mh.trackername.ToCharArray(); for (t = tracker.Length - 1; (t >= 0) && (tracker[t] <= ' '); t--) { tracker[t] = (char)0; } /* some modules have the tracker name empty */ if (tracker[0] == 0) { tracker = "Unknown tracker".ToCharArray(); } String modType = String.Format("{0} (XM format {1}.{2})", tracker, mh.version >> 8, mh.version & 0xff); m_Module.modtype = modType; m_Module.numchn = (byte)mh.numchn; m_Module.numpat = mh.numpat; m_Module.numtrk = (ushort)(m_Module.numpat * m_Module.numchn); /* get number of channels */ m_Module.songname = mh.songname; m_Module.numpos = mh.songlength; /* copy the songlength */ m_Module.reppos = (ushort)(mh.restart < mh.songlength ? mh.restart : 0); m_Module.numins = mh.numins; m_Module.flags |= SharpMikCommon.UF_XMPERIODS | SharpMikCommon.UF_INST | SharpMikCommon.UF_NOWRAP | SharpMikCommon.UF_FT2QUIRKS | SharpMikCommon.UF_PANNING; if ((mh.flags & 1) != 0) { m_Module.flags |= SharpMikCommon.UF_LINEAR; } m_Module.bpmlimit = 32; m_Module.chanvol.Memset(64, m_Module.numchn); /* store channel volumes */ m_Module.positions = new ushort[m_Module.numpos + 1]; for (t = 0; t < m_Module.numpos; t++) { m_Module.positions[t] = mh.orders[t]; } /* We have to check for any pattern numbers in the order list greater than * the number of patterns total. If one or more is found, we set it equal to * the pattern total and make a dummy pattern to workaround the problem */ for (t = 0; t < m_Module.numpos; t++) { if (m_Module.positions[t] >= m_Module.numpat) { m_Module.positions[t] = m_Module.numpat; dummypat = true; } } if (dummypat) { m_Module.numpat++; m_Module.numtrk += m_Module.numchn; } if (mh.version < 0x0104) { if (!LoadInstruments()) { return(false); } if (!LoadPatterns(dummypat)) { return(false); } for (t = 0; t < m_Module.numsmp; t++) { nextwav[t] += (uint)m_Reader.Tell(); } } else { if (!LoadPatterns(dummypat)) { return(false); } if (!LoadInstruments()) { return(false); } } m_Module.AllocSamples(); sampHeader = 0; for (u = 0; u < m_Module.numsmp; u++) { q = m_Module.samples[u]; XMWAVHEADER s = wh[sampHeader++]; q.samplename = s.samplename; q.length = s.length; q.loopstart = s.loopstart; q.loopend = (uint)(s.loopstart + s.looplength); q.volume = s.volume; q.speed = (uint)s.finetune + 128; q.panning = s.panning; q.seekpos = nextwav[u]; q.vibtype = s.vibtype; q.vibsweep = s.vibsweep; q.vibdepth = s.vibdepth; q.vibrate = s.vibrate; if ((s.type & 0x10) != 0) { q.length >>= 1; q.loopstart >>= 1; q.loopend >>= 1; } q.flags |= SharpMikCommon.SF_OWNPAN | SharpMikCommon.SF_DELTA | SharpMikCommon.SF_SIGNED; if ((s.type & 0x3) != 0) { q.flags |= SharpMikCommon.SF_LOOP; } if ((s.type & 0x2) != 0) { q.flags |= SharpMikCommon.SF_BIDI; } if ((s.type & 0x10) != 0) { q.flags |= SharpMikCommon.SF_16BITS; } } sampHeader = 0; for (u = 0; u < m_Module.numins; u++) { d = m_Module.instruments[u]; for (t = 0; t < XMNOTECNT; t++) { if (d.samplenumber[t] >= m_Module.numsmp) { d.samplenote[t] = 255; } else { int note = t + wh[d.samplenumber[t]].relnote; d.samplenote[t] = (byte)((note < 0) ? 0 : note); } } } wh = null; nextwav = null; return(true); }
bool LoadInstruments() { int t, u, ck; INSTRUMENT d; uint next = 0; ushort wavcnt = 0; if (!m_Module.AllocInstruments()) { m_LoadError = MMERR_NOT_A_MODULE; return(false); } for (t = 0; t < m_Module.numins; t++) { d = m_Module.instruments[t]; XMINSTHEADER ih = new XMINSTHEADER(); long headend; d.samplenumber.Memset(0xff, SharpMikCommon.INSTNOTES); /* read instrument header */ headend = m_Reader.Tell(); ih.size = m_Reader.Read_Intel_uint(); headend += ih.size; ck = m_Reader.Tell(); m_Reader.Seek(0, SeekOrigin.End); if ((headend < 0) || (m_Reader.Tell() < headend) || (headend < ck)) { m_Reader.Seek(ck, SeekOrigin.Begin); break; } m_Reader.Seek(ck, SeekOrigin.Begin); ih.name = m_Reader.Read_String(22); ih.type = m_Reader.Read_byte(); ih.numsmp = m_Reader.Read_Intel_ushort(); d.insname = ih.name; if ((short)ih.size > 29) { ih.ssize = m_Reader.Read_Intel_uint(); if (((short)ih.numsmp > 0) && (ih.numsmp <= XMNOTECNT)) { XMPATCHHEADER pth = new XMPATCHHEADER(); m_Reader.Read_bytes(pth.what, XMNOTECNT); m_Reader.Read_Intel_ushorts(pth.volenv, XMENVCNT); m_Reader.Read_Intel_ushorts(pth.panenv, XMENVCNT); pth.volpts = m_Reader.Read_byte(); pth.panpts = m_Reader.Read_byte(); pth.volsus = m_Reader.Read_byte(); pth.volbeg = m_Reader.Read_byte(); pth.volend = m_Reader.Read_byte(); pth.pansus = m_Reader.Read_byte(); pth.panbeg = m_Reader.Read_byte(); pth.panend = m_Reader.Read_byte(); pth.volflg = m_Reader.Read_byte(); pth.panflg = m_Reader.Read_byte(); pth.vibflg = m_Reader.Read_byte(); pth.vibsweep = m_Reader.Read_byte(); pth.vibdepth = m_Reader.Read_byte(); pth.vibrate = m_Reader.Read_byte(); pth.volfade = m_Reader.Read_Intel_ushort(); /* read the remainder of the header * (2 bytes for 1.03, 22 for 1.04) */ if (headend >= m_Reader.Tell()) { for (u = (int)(headend - m_Reader.Tell()); u != 0; u--) { m_Reader.Read_byte(); } } /* we can't trust the envelope point count here, as some * modules have incorrect values (K_OSPACE.XM reports 32 volume * points, for example). */ if (pth.volpts > XMENVCNT / 2) { pth.volpts = (byte)(XMENVCNT / 2); } if (pth.panpts > XMENVCNT / 2) { pth.panpts = (byte)(XMENVCNT / 2); } if ((m_Reader.isEOF()) || (pth.volpts > XMENVCNT / 2) || (pth.panpts > XMENVCNT / 2)) { if (nextwav != null) { nextwav = null; } if (wh != null) { wh = null; } m_LoadError = MMERR_LOADING_SAMPLEINFO; return(false); } for (u = 0; u < XMNOTECNT; u++) { d.samplenumber[u] = (ushort)(pth.what[u] + m_Module.numsmp); } d.volfade = pth.volfade; XM_ProcessEnvelopeVolume(ref d, pth); XM_ProcessEnvelopePan(ref d, pth); if ((d.volflg & SharpMikCommon.EF_ON) != 0) { FixEnvelope(d.volenv, d.volpts); } if ((d.panflg & SharpMikCommon.EF_ON) != 0) { FixEnvelope(d.panenv, d.panpts); } /* Samples are stored outside the instrument struct now, so we * have to load them all into a temp area, count the m_Module.numsmp * along the way and then do an AllocSamples() and move * everything over */ if (mh.version > 0x0103) { next = 0; } for (u = 0; u < ih.numsmp; u++) { XMWAVHEADER s = null; if (wh != null && sampHeader < wh.Length) { s = wh[sampHeader]; } /* Allocate more room for sample information if necessary */ if (m_Module.numsmp + u == wavcnt) { ushort lastSize = wavcnt; wavcnt += (ushort)XM_SMPINCR; if (nextwav == null) { nextwav = new uint[wavcnt]; } else { Array.Resize(ref nextwav, wavcnt); } if (wh == null) { wh = new XMWAVHEADER[wavcnt]; } else { Array.Resize(ref wh, wavcnt); } for (ushort i = lastSize; i < wavcnt; i++) { wh[i] = new XMWAVHEADER(); } //sampHeader=(wavcnt-XM_SMPINCR); s = wh[sampHeader]; } s.length = m_Reader.Read_Intel_uint(); s.loopstart = m_Reader.Read_Intel_uint(); s.looplength = m_Reader.Read_Intel_uint(); s.volume = m_Reader.Read_byte(); s.finetune = m_Reader.Read_sbyte(); s.type = m_Reader.Read_byte(); s.panning = m_Reader.Read_byte(); s.relnote = m_Reader.Read_sbyte(); s.vibtype = pth.vibflg; s.vibsweep = pth.vibsweep; s.vibdepth = (byte)(pth.vibdepth * 4); s.vibrate = pth.vibrate; s.reserved = m_Reader.Read_byte(); s.samplename = m_Reader.Read_String(22); nextwav[m_Module.numsmp + u] = next; next += s.length; if (m_Reader.isEOF()) { nextwav = null; wh = null; m_LoadError = MMERR_LOADING_SAMPLEINFO; return(false); } sampHeader++; } if (mh.version > 0x0103) { for (u = 0; u < ih.numsmp; u++) { nextwav[m_Module.numsmp++] += (uint)m_Reader.Tell(); } m_Reader.Seek((int)next, SeekOrigin.Current); } else { m_Module.numsmp += ih.numsmp; } } else { /* read the remainder of the header */ ck = m_Reader.Tell(); m_Reader.Seek(0, SeekOrigin.End); if ((headend < 0) || (m_Reader.Tell() < headend) || (headend < ck)) { m_Reader.Seek(ck, SeekOrigin.Begin); break; } m_Reader.Seek(ck, SeekOrigin.Begin); u = (int)(headend - m_Reader.Tell()); for (; u != 0; u--) { m_Reader.Read_byte(); } if (m_Reader.isEOF()) { nextwav = null; wh = null; m_LoadError = MMERR_LOADING_SAMPLEINFO; return(false); } } } } /* sanity check */ if (m_Module.numsmp == 0) { nextwav = null; wh = null; m_LoadError = MMERR_LOADING_SAMPLEINFO; return(false); } return(true); }