public static MMLCommand[] Parse(VoidPtr address) { List<MMLCommand> commands = new List<MMLCommand>(); Mml cmd; byte* addr = (byte*)address; while ((cmd = (Mml)(*addr++)) != Mml.MML_FIN) { MMLCommand mml = new MMLCommand(cmd); if (cmd == Mml.MML_WAIT || cmd == Mml.MML_PRG) { switch ((SeqArgType)(*addr++)) { case SeqArgType.SEQ_ARG_NONE: addr++; break; case SeqArgType.SEQ_ARG_RANDOM: break; case SeqArgType.SEQ_ARG_S16: break; case SeqArgType.SEQ_ARG_U8: break; case SeqArgType.SEQ_ARG_VARIABLE: break; case SeqArgType.SEQ_ARG_VMIDI: break; } } else if (cmd == Mml.MML_EX_COMMAND) { switch ((MmlEx)(*addr++)) { case MmlEx.MML_SETVAR: break; case MmlEx.MML_ADDVAR: break; case MmlEx.MML_SUBVAR: break; case MmlEx.MML_MULVAR: break; case MmlEx.MML_DIVVAR: break; case MmlEx.MML_SHIFTVAR: break; case MmlEx.MML_RANDVAR: break; case MmlEx.MML_ANDVAR: break; case MmlEx.MML_ORVAR: break; case MmlEx.MML_XORVAR: break; case MmlEx.MML_NOTVAR: break; case MmlEx.MML_MODVAR: break; case MmlEx.MML_CMP_EQ: break; case MmlEx.MML_CMP_GE: break; case MmlEx.MML_CMP_GT: break; case MmlEx.MML_CMP_LE: break; case MmlEx.MML_CMP_LT: break; case MmlEx.MML_CMP_NE: break; case MmlEx.MML_USERPROC: break; } addr += 3; } } commands.Add(new MMLCommand(Mml.MML_FIN, 0)); return commands.ToArray(); }
public static MMLCommand[] Parse(VoidPtr address) { List <MMLCommand> commands = new List <MMLCommand>(); Mml cmd; byte *addr = (byte *)address; while ((cmd = (Mml)(*addr++)) != Mml.MML_FIN) { MMLCommand mml = new MMLCommand(cmd); if (cmd == Mml.MML_WAIT || cmd == Mml.MML_PRG) { switch ((SeqArgType)(*addr++)) { case SeqArgType.SEQ_ARG_NONE: addr++; break; case SeqArgType.SEQ_ARG_RANDOM: break; case SeqArgType.SEQ_ARG_S16: break; case SeqArgType.SEQ_ARG_U8: break; case SeqArgType.SEQ_ARG_VARIABLE: break; case SeqArgType.SEQ_ARG_VMIDI: break; } } else if (cmd == Mml.MML_EX_COMMAND) { switch ((MmlEx)(*addr++)) { case MmlEx.MML_SETVAR: break; case MmlEx.MML_ADDVAR: break; case MmlEx.MML_SUBVAR: break; case MmlEx.MML_MULVAR: break; case MmlEx.MML_DIVVAR: break; case MmlEx.MML_SHIFTVAR: break; case MmlEx.MML_RANDVAR: break; case MmlEx.MML_ANDVAR: break; case MmlEx.MML_ORVAR: break; case MmlEx.MML_XORVAR: break; case MmlEx.MML_NOTVAR: break; case MmlEx.MML_MODVAR: break; case MmlEx.MML_CMP_EQ: break; case MmlEx.MML_CMP_GE: break; case MmlEx.MML_CMP_GT: break; case MmlEx.MML_CMP_LE: break; case MmlEx.MML_CMP_LT: break; case MmlEx.MML_CMP_NE: break; case MmlEx.MML_USERPROC: break; } addr += 3; } } commands.Add(new MMLCommand(Mml.MML_FIN, 0)); return(commands.ToArray()); }
public static MMLSong Parse(VoidPtr address) { MMLSong song = new MMLSong(); byte *addr = (byte *)address; int offset = 0; Dictionary <int, int> knownTracks = new Dictionary <int, int> { { 0, 0 } }; int track; while (knownTracks.TryGetValue(offset, out track)) { List <MMLCommand> commands = new List <MMLCommand>(); Mml cmd = 0x00; do { uint value = 0; uint value2 = 0; uint value3 = 0; uint value4 = 0; uint subCmd = 0; MMLCommand mmlCmd = null; byte b = (*addr++); if (b < 0x80) { value = ReadVarLen(ref addr); uint key = b; uint velocity = (*addr++); uint length = ReadVarLen(ref addr); mmlCmd = new MMLCommand(Mml.NOTE_ON, key, velocity, length); } else { cmd = (Mml)b; switch (cmd) { // 0-arg commands case Mml.MML_RET: case Mml.MML_LOOP_END: case Mml.MML_FIN: mmlCmd = new MMLCommand(cmd); break; // varlen commands case Mml.MML_WAIT: case Mml.MML_PRG: value = ReadVarLen(ref addr); mmlCmd = new MMLCommand(cmd, value); break; case Mml.MML_OPEN_TRACK: value = (*addr++); value2 = ReadUnsigned24(ref addr); mmlCmd = new MMLCommand(cmd, value, value2); if (!knownTracks.ContainsKey((int)value2)) { knownTracks.Add((int)value2, (int)value); } break; case Mml.MML_JUMP: case Mml.MML_CALL: value = ReadUnsigned24(ref addr); mmlCmd = new MMLCommand(cmd, value); break; case Mml.MML_VARIABLE: subCmd = (*addr++); if (subCmd >= 0xb0 && subCmd <= 0xbd) { value = (*addr++); } value2 = (*addr++); mmlCmd = new MMLCommand(cmd, subCmd, value, value2); break; case Mml.MML_IF: subCmd = (*addr++); if (subCmd >= 0xb0 && subCmd <= 0xbd) { value = (*addr++); } value2 = (*addr++); value3 = (*addr++); mmlCmd = new MMLCommand(cmd, subCmd, value, value2, value3); break; //case Mml.MML_TIME: //case Mml.MML_TIME_RANDOM: //case Mml.MML_TIME_VARIABLE: // break; // u8 argument commands case Mml.MML_TIMEBASE: case Mml.MML_ENV_HOLD: case Mml.MML_MONOPHONIC: case Mml.MML_VELOCITY_RANGE: case Mml.MML_BIQUAD_TYPE: case Mml.MML_BIQUAD_VALUE: case Mml.MML_PAN: case Mml.MML_VOLUME: case Mml.MML_MAIN_VOLUME: case Mml.MML_TRANSPOSE: case Mml.MML_PITCH_BEND: case Mml.MML_BEND_RANGE: case Mml.MML_PRIO: case Mml.MML_NOTE_WAIT: case Mml.MML_TIE: case Mml.MML_PORTA: case Mml.MML_MOD_DEPTH: case Mml.MML_MOD_SPEED: case Mml.MML_MOD_TYPE: case Mml.MML_MOD_RANGE: case Mml.MML_PORTA_SW: case Mml.MML_PORTA_TIME: case Mml.MML_ATTACK: case Mml.MML_DECAY: case Mml.MML_SUSTAIN: case Mml.MML_RELEASE: case Mml.MML_LOOP_START: case Mml.MML_EXPRESSION: case Mml.MML_PRINTVAR: case Mml.MML_SURROUND_PAN: case Mml.MML_LPF_CUTOFF: case Mml.MML_FXSEND_A: case Mml.MML_FXSEND_B: case Mml.MML_MAINSEND: case Mml.MML_INIT_PAN: case Mml.MML_MUTE: case Mml.MML_FXSEND_C: case Mml.MML_DAMPER: value = (*addr++); mmlCmd = new MMLCommand(cmd, value); break; // extended commands case Mml.MML_EX_COMMAND: MmlEx cmdEx = (MmlEx)(*addr++); switch (cmdEx) { case MmlEx.MML_SETVAR: break; case MmlEx.MML_ADDVAR: break; case MmlEx.MML_SUBVAR: break; case MmlEx.MML_MULVAR: break; case MmlEx.MML_DIVVAR: break; case MmlEx.MML_SHIFTVAR: break; case MmlEx.MML_RANDVAR: break; case MmlEx.MML_ANDVAR: break; case MmlEx.MML_ORVAR: break; case MmlEx.MML_XORVAR: break; case MmlEx.MML_NOTVAR: break; case MmlEx.MML_MODVAR: break; case MmlEx.MML_CMP_EQ: break; case MmlEx.MML_CMP_GE: break; case MmlEx.MML_CMP_GT: break; case MmlEx.MML_CMP_LE: break; case MmlEx.MML_CMP_LT: break; case MmlEx.MML_CMP_NE: break; case MmlEx.MML_USERPROC: break; } value = (*addr++); value2 = (*addr++); value3 = (*addr++); value4 = (*addr++); mmlCmd = new MMLCommand(cmd, (uint)cmdEx, value, value2, value3, value4); break; case Mml.MML_ALLOC_TRACK: value = ReadUnsigned16(ref addr); mmlCmd = new MMLCommand(cmd, value); break; default: byte[] arr = new byte[0x10]; Marshal.Copy((IntPtr)addr, arr, 0, 0x10); var str = PrintBytes(arr); Marshal.Copy((IntPtr)addr - 0x10, arr, 0, 0x10); var str2 = PrintBytes(arr); //throw new Exception($"Unknown MML command: 0x{b:x2}\n{str2}\n{str}"); break; } } if (mmlCmd != null) { mmlCmd._offset = offset; commands.Add(mmlCmd); } offset = (addr - address); } while (cmd != Mml.MML_FIN && !knownTracks.ContainsKey(offset)); // TODO if (!song.Tracks.ContainsKey(track)) { song.Tracks.Add(track, commands.ToArray()); } } return(song); }