public Note(SPCCommand command) { this.Command = command; this.Octave = 6; this.Percussive = false; this.Sample = 0; }
// constructors public Note(SPCCommand command, int octave, bool percussive, int sample) { this.Command = command; this.Octave = percussive ? 5 : octave; this.Percussive = percussive; this.Sample = sample; }
private void RepeatLoop(int c, ref int i, int start, int count, ref int octave, ref bool percussive, ref int sample) { int end = i; int thisOctave = octave; while (count > 0 && i < channels[c].Count) { SPCCommand ssc = channels[c][i++]; // if at last repeat, and first section begins, skip the rest if (ssc.Opcode == 0xD6 && count == 1) { while (i < channels[c].Count && i < end) { i++; } break; } switch (ssc.Opcode) { case 0xC4: thisOctave++; break; case 0xC5: thisOctave--; break; case 0xC6: thisOctave = ssc.Param1; break; case 0xD4: RepeatLoop(c, ref i, i, ssc.Param1, ref thisOctave, ref percussive, ref sample); break; case 0xD5: end = i; count--; if (count > 0) { i = start; thisOctave = octave; } break; case 0xD6: break; case 0xDE: sample = ssc.Param1; goto default; case 0xEE: percussive = true; goto default; case 0xEF: percussive = false; goto default; default: if (ssc.Opcode < 0xC4 || ssc.Opcode == 0xD7 || ssc.Opcode == 0xDE || ssc.Opcode == 0xEE || ssc.Opcode == 0xEF) { notes[c].Add(new Note(ssc, thisOctave, percussive, sample)); } break; } } octave = thisOctave; }
// notation functions public override void CreateNotes() { notes = new List <Note> [8]; for (int c = 0; c < notes.Length; c++) { if (channels[c] == null) { continue; } notes[c] = new List <Note>(); int i = 0; int thisOctave = 6; int sample = 0; bool percussive = false; while (i < channels[c].Count) { SPCCommand ssc = channels[c][i++]; switch (ssc.Opcode) { case 0xC4: thisOctave++; break; case 0xC5: thisOctave--; break; case 0xC6: thisOctave = ssc.Param1; break; case 0xD4: RepeatLoop(c, ref i, i, ssc.Param1, ref thisOctave, ref percussive, ref sample); break; case 0xD5: break; case 0xDE: sample = ssc.Param1; goto default; case 0xEE: percussive = true; goto default; case 0xEF: percussive = false; goto default; default: if (ssc.Opcode < 0xC4 || ssc.Opcode == 0xD7 || ssc.Opcode == 0xDE || ssc.Opcode == 0xEE || ssc.Opcode == 0xEF) { notes[c].Add(new Note(ssc, thisOctave, percussive, sample)); } break; } } } }
private void DecompToMMLLoop(ref List <SPCCommand>[] commands, NativeSPC nativeFormat, int c, ref int i, int start, int count, bool nested, ref int octave, ref bool percussive, ref int sample) { int end = i; int thisOctave = octave; while (count > 0 && i < channels[c].Count) { int maxOctave = 6; if (nativeFormat == NativeSPC.SMWLevel || nativeFormat == NativeSPC.SMWOverworld) { maxOctave = Lists.SMWOctaveLimits[Lists.SMRPGtoSMWSamples[sample]]; } SPCCommand ssc = channels[c][i++].Copy(); // if at last repeat, and first section begins, skip the rest if (ssc.Opcode == 0xD6 && count == 1) { while (i < channels[c].Count && i < end) { i++; } break; } switch (ssc.Opcode) { case 0xC4: thisOctave++; if (thisOctave > maxOctave) { thisOctave = maxOctave; } else { goto default; } break; case 0xC5: thisOctave--; if (thisOctave < 1) { thisOctave = 1; } else { goto default; } break; case 0xC6: if (ssc.Param1 < 1) { ssc.Param1 = 1; } if (ssc.Param1 > maxOctave) { ssc.Param1 = (byte)maxOctave; } thisOctave = ssc.Param1; goto default; case 0xD4: commands[c].Add(new SPCCommand(new byte[] { 0xC6, (byte)thisOctave }, this, c)); DecompToMMLLoop(ref commands, nativeFormat, c, ref i, i, ssc.Param1, true, ref thisOctave, ref percussive, ref sample); break; case 0xD5: end = i; count--; if (nested && count > 0) { i = start; thisOctave = octave; } else if (!nested) { commands[c].Add(ssc); octave = thisOctave; return; } break; case 0xD6: break; case 0xDE: sample = ssc.Param1; goto default; case 0xEE: percussive = true; goto default; case 0xEF: percussive = false; goto default; default: thisOctave = Math.Max(1, Math.Min(6, thisOctave)); commands[c].Add(ssc); break; } } octave = thisOctave; }
// conversion functions public List <SPCCommand>[] DecompToMML(NativeSPC nativeFormat) { List <SPCCommand>[] commands = new List <SPCCommand> [8]; for (int c = 0; c < commands.Length; c++) { if (channels[c] == null) { continue; } commands[c] = new List <SPCCommand>(); int i = 0; int thisOctave = 6; int sample = 0; bool percussive = false; while (i < channels[c].Count) { int maxOctave = 6; if (nativeFormat == NativeSPC.SMWLevel || nativeFormat == NativeSPC.SMWOverworld) { maxOctave = Lists.SMWOctaveLimits[Lists.SMRPGtoSMWSamples[sample]]; } SPCCommand ssc = channels[c][i++].Copy(); switch (ssc.Opcode) { case 0xC4: thisOctave++; if (thisOctave > maxOctave) { thisOctave = maxOctave; } else { goto default; } break; case 0xC5: thisOctave--; if (thisOctave < 1) { thisOctave = 1; } else { goto default; } break; case 0xC6: if (ssc.Param1 < 1) { ssc.Param1 = 1; } if (ssc.Param1 > maxOctave) { ssc.Param1 = (byte)maxOctave; } thisOctave = ssc.Param1; goto default; case 0xD4: //commands[c].Add(ssc); commands[c].Add(new SPCCommand(new byte[] { 0xC6, (byte)thisOctave }, this, c)); DecompToMMLLoop(ref commands, nativeFormat, c, ref i, i, ssc.Param1, false, ref thisOctave, ref percussive, ref sample); break; case 0xD5: break; case 0xDE: sample = ssc.Param1; goto default; case 0xEE: percussive = true; goto default; case 0xEF: percussive = false; goto default; default: thisOctave = Math.Max(1, Math.Min(6, thisOctave)); commands[c].Add(ssc); break; } } } return(commands); }
// class functions public int Length() { int length = 0; // first make sure each channel ends with a termination command for (int i = 0; i < 2; i++) { if (channels[i] != null && channels[i].Count > 0) { SPCCommand lastSSC = channels[i][channels[i].Count - 1]; if (lastSSC.Opcode != 0xD0 && lastSSC.Opcode != 0xCD && lastSSC.Opcode != 0xCE) { length++; } } } // int channelSize1 = 0; int channelSize2 = 0; if (channels[0] != null && activeChannels[0]) { foreach (SPCCommand ssc in channels[0]) { channelSize1 += ssc.Length; } } if (channels[1] != null && activeChannels[1]) { foreach (SPCCommand ssc in channels[1]) { channelSize2 += ssc.Length; } } // bool channel2in1 = true; if (channels[0] != null && channels[1] != null && activeChannels[0] && activeChannels[1] && channelSize2 <= channelSize1) { for (int a = channels[0].Count - 1, b = channels[1].Count - 1; a >= 0 && b >= 0; a--, b--) { if (!Bits.Compare(channels[0][a].CommandData, channels[1][b].CommandData)) { channel2in1 = false; } } } else { channel2in1 = false; } // if (channel2in1) { length += channelSize1; } else { length += channelSize1 + channelSize2; } return(length); }
public void Assemble(ref int offset) { // first make sure each channel ends with a termination command for (int i = 0; i < 2; i++) { if (channels[i] != null && channels[i].Count > 0) { SPCCommand lastSSC = channels[i][channels[i].Count - 1]; if (lastSSC.Opcode != 0xD0 && lastSSC.Opcode != 0xCD && lastSSC.Opcode != 0xCE) { channels[i].Add(new SPCCommand(new byte[] { 0xD0 }, this, 0)); } } } // int channelSize1 = 0; int channelSize2 = 0; if (channels[0] != null && activeChannels[0]) { foreach (SPCCommand ssc in channels[0]) { channelSize1 += ssc.Length; } } if (channels[1] != null && activeChannels[1]) { foreach (SPCCommand ssc in channels[1]) { channelSize2 += ssc.Length; } } // int offsetStart1 = offset; int offsetStart2 = offset + channelSize1; if (channels[0] == null || !activeChannels[0]) { offsetStart1 = 0; } if (channels[1] == null || !activeChannels[1]) { offsetStart2 = 0; } // bool channel2in1 = true; if (offsetStart1 != 0 && offsetStart2 != 0 && channelSize2 <= channelSize1) { for (int a = channels[0].Count - 1, b = channels[1].Count - 1; a >= 0 && b >= 0; a--, b--) { if (!Bits.Compare(channels[0][a].CommandData, channels[1][b].CommandData)) { channel2in1 = false; } } } else { channel2in1 = false; } if (channel2in1) { offsetStart2 -= channelSize2; } // if (type == 0) { if (offsetStart1 == 0) { Bits.SetShort(rom, index * 4 + 0x042826, 0); } else { Bits.SetShort(rom, index * 4 + 0x042826, offsetStart1 - 0x042C26 + 0x3400); } if (offsetStart2 == 0) { Bits.SetShort(rom, index * 4 + 0x042826 + 2, 0); } else { Bits.SetShort(rom, index * 4 + 0x042826 + 2, offsetStart2 - 0x042C26 + 0x3400); } } else { if (offsetStart1 == 0) { Bits.SetShort(rom, index * 4 + 0x043E26, 0); } else { Bits.SetShort(rom, index * 4 + 0x043E26, offsetStart1 - 0x044226 + 0x3400); } if (offsetStart2 == 0) { Bits.SetShort(rom, index * 4 + 0x043E26 + 2, 0); } else { Bits.SetShort(rom, index * 4 + 0x043E26 + 2, offsetStart2 - 0x044226 + 0x3400); } } if (channels[0] != null && activeChannels[0]) { foreach (SPCCommand ssc in channels[0]) { Bits.SetBytes(rom, offsetStart1, ssc.CommandData); offsetStart1 += ssc.Length; } } if (channels[1] != null && activeChannels[1]) { foreach (SPCCommand ssc in channels[1]) { Bits.SetBytes(rom, offsetStart2, ssc.CommandData); offsetStart2 += ssc.Length; } } if (channel2in1) { offset += channelSize1; } else { offset += channelSize1 + channelSize2; } }