private static void PlayAsync(object filename) { try { SoundPlayer player = new SoundPlayer(filename as string); player.PlaySync(); player.Dispose(); } catch { } mBusy = false; }
/// <summary> /// Stops playing the last sound playing/that was played. /// </summary> private void StopLastSound() { if (m_IsMusic) { if (m_MusicInstance != null) { m_MusicInstance.StopSound(); m_MusicInstance.Dispose(); } } else { if (m_SoundInstance != null) { m_SoundInstance.StopSound(); m_SoundInstance.Dispose(); } } m_SoundInstance = null; m_MusicInstance = null; }
/// <summary> /// This runs one HIT instruction, and should be run once every frame for every subroutine. /// </summary> /// <returns>True if still running, otherwise yields.</returns> public override IEnumerable <object> process() { byte Var1 = 0, Var2 = 0; //Used by waiteq, waitne byte Datafield = 0; //Used by set/getsrcdatafield. byte TrackID = 0, Dest = 0; int Src = 0; if (!SimpleMode) { while (true) { byte Opcode = ReadByte(); switch (Opcode) { case 0x2: //note_on - play a note, whose ID resides in the specified variable. Dest = ReadByte(); if (m_SoundID == 0) { m_SoundID = m_Track.SoundID; } ISoundCodec Snd = FileManager.GetSound(m_SoundID); if (Snd != null) { m_Notes.Add(new HITNoteEntry(m_SoundID, Snd)); SetVariable(Dest, m_Notes.Count - 1); m_Player = new SoundPlayer(Snd.DecompressedWav(), Snd.GetSampleRate()); m_Player.PlaySound(); } else { Debug.WriteLine("SubRoutine.cs: Couldn't find sound " + m_SoundID); } break; case 0x4: //loadb - sign-extend a 1-byte constant to 4 bytes and write to a variable. Dest = ReadByte(); var Constant = (sbyte)ReadByte(); SetVariable(Dest, Constant); m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); //TODO: When to set this to false again? break; case 0x5: //loadl - write a 4-byte constant to a variable. Dest = ReadByte(); Src = ReadInt32(); SetVariable(Dest, Src); break; case 0x6: //set/settt - copy the contents of one variable into another. Dest = ReadByte(); Src = GetVariable(ReadByte()); SetVariable(Dest, Src); m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); //TODO: When to set this to false again? break; case 0x7: //call - push the instruction pointer and jump to the given address. m_Stack.Push(m_InstCounter); m_InstCounter = (uint)ReadInt32(); break; case 0x8: //return - kill this thread. m_Player.StopSound(); m_Player.Dispose(); m_Player = null; YieldComplete(); yield return(false); break; case 0x9: //wait - wait for a length of time in milliseconds, specified by a variable. Src = ReadByte(); if (m_WaitRemaining == -1) { m_WaitRemaining = m_Registers[(byte)Src]; } m_WaitRemaining -= 16; //assuming tick rate is 60 times a second if (m_WaitRemaining > 0) { m_InstCounter -= 2; yield return(false); } else { m_WaitRemaining = -1; yield return(false); } break; case 0xb: //wait_samp - wait for the previously selected note to finish playing. break; case 0xc: //end - return from this function; pop the instruction pointer from the stack and jump. YieldComplete(); //Not sure if this is correct? yield return(true); break; case 0xd: //jump - jump to a given address. byte JmpAddress = ReadByte(); if (JmpAddress > 15) { m_InstCounter--; m_InstCounter = ReadUInt32(); } else { m_InstCounter = (uint)GetVariable(JmpAddress); if (ReadByte() == 0) { m_InstCounter += 2; } else { m_InstCounter--; } } break; case 0xe: //test - examine the variable and set the flags. Dest = ReadByte(); m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0xf: //nop - no operation. break; case 0x10: //add - increment a "dest" variable by a "src" variable m_Registers[ReadByte()] += m_Registers[ReadByte()]; m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0x11: //sub - decrement a "dest" variable by a "src" variable. m_Registers[ReadByte()] -= m_Registers[ReadByte()]; m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0x12: //div - divide a "dest" variable by a "src" variable. m_Registers[ReadByte()] /= m_Registers[ReadByte()]; m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0x13: //mul - multiply a "dest" variable by a "src" variable. m_Registers[ReadByte()] *= m_Registers[ReadByte()]; m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0x14: //cmp - compare two variables and set the flags. m_Registers[ReadByte()] -= m_Registers[ReadByte()]; m_ZeroFlag = (Dest == 0); m_SignFlag = (Dest < 0); break; case 0x18: //rand - generate a random number between "low" and "high" variables, inclusive, and store //the result in the "dest" variable. SetVariable(ReadByte(), m_Rand.Next((int)ReadByte(), (int)ReadByte())); break; case 0x20: //loop - jump back to the loop point (start of track subroutine by default). if (m_LoopPoint != 0) { m_InstCounter = m_LoopPoint; } else { m_InstCounter = Address; } break; case 0x021: //set_loop - set the loop point to the current position. m_LoopPoint = m_InstCounter; break; case 0x27: //smart_choose - Set the specified variable to a random entry from the selected hitlist. Dest = ReadByte(); int Max = m_Hitlist.SoundsAndHitlists.Count; SetVariable(Dest, (int)m_Hitlist.SoundsAndHitlists[m_Rand.Next(Max)]); break; case 0x2d: //max - find the higher of a "dest" variable and a "src" constant and store the result //in the variable. Dest = ReadByte(); Src = ReadInt32(); if (Src > Dest) { SetVariable(Dest, Src); } break; case 0x32: //play_trk - play a track (by sending it the kSndobPlay event), whose ID resides in the //specified variable. TrackID = ReadByte(); if (HitVM.IsInitialized) { HitVM.PlayTrack((uint)GetVariable(TrackID)); } break; case 0x33: //kill_trk - kill a track (by sending it the kSndobKill event), whose ID resides in the //specified variable. TrackID = ReadByte(); if (HitVM.IsInitialized) { HitVM.KillTrack((uint)GetVariable(TrackID)); } break; case 0x3a: //test1 - unknown break; case 0x3b: //test2 - unknown break; case 0x3c: //test3 - unknown break; case 0x3d: //test4 - unknown break; case 0x3e: //ifeq - if the zero flag is set, jump to the given address. Src = ReadInt32(); if (m_ZeroFlag) { m_InstCounter = (uint)Src; } break; case 0x3f: //ifne - if the zero flag is not set, jump to the given address. Src = ReadInt32(); if (!m_ZeroFlag) { m_InstCounter = (uint)Src; } break; case 0x40: //ifgt - if the sign flag is not set and the zero flag is not set, jump to the given address. Src = ReadInt32(); if (!m_ZeroFlag && !m_SignFlag) { m_InstCounter = (uint)Src; } break; case 0x41: //iflt - if the sign flag is set, jump to the given address. Src = ReadInt32(); if (m_SignFlag) { m_InstCounter = (uint)Src; } break; case 0x42: //ifge - if the sign flag is not set, jump to the given address. Src = ReadInt32(); if (!m_SignFlag) { m_InstCounter = (uint)Src; } break; case 0x43: //ifle - if the sign flag is set or the zero flag is set, jump to the given address. Src = ReadInt32(); if (m_ZeroFlag || m_SignFlag) { m_InstCounter = (uint)Src; } break; case 0x44: //smart_setlist - choose a global hitlist, or 0 for the one local to the track. Src = ReadByte(); if (Src != 0) { m_Hitlist = FileManager.GetHLS((uint)GetVariable(Src)); } else { uint SoundID = FileManager.GetTRK(TrackID).SoundID; try { FileManager.GetSound(SoundID); } catch { m_Hitlist = FileManager.GetHLS(SoundID); } } break; case 0x45: //seqgroup_kill - kill all sounds belonging to the sequence group specified by the "group" //variable. Src = ReadByte(); break; case 0x47: //seqgroup_return - unknown. byte Group = ReadByte(); break; case 0x48: //getsrcdatafield - Read an object variable (whose ID is specified by the "field" //variable) of a source object (whose object ID is specified by the "source" variable), //store it in the "dest" variable, and update the flags. Dest = ReadByte(); Src = ReadByte(); Datafield = ReadByte(); int ObjectVar = GetVariable(Src); SetVariable(Dest, ObjectVar); m_ZeroFlag = (ObjectVar == 0); m_SignFlag = (ObjectVar < 0); break; case 0x49: //seqgroup_trkid - unknown. Dest = ReadByte(); Src = ReadByte(); break; case 0x4a: //setll - Copy the contents of one variable into another (equivalent to set and settt; //defaultsyms.txt says "ISN'T THIS THE SAME AS SET TOO?") Dest = ReadByte(); Src = ReadByte(); SetVariable(Dest, Src); break; case 0x4b: //setlt - unknown. Dest = ReadByte(); Src = ReadByte(); break; case 0x4d: //waiteq - wait until two variables are equal. Var1 = ReadByte(); Var2 = ReadByte(); if (GetVariable(Var1) != GetVariable(Var2)) { m_InstCounter -= 3; yield return(false); } break; case 0x53: //duck - unknown. break; case 0x54: //unduck - unknown. break; case 0x56: //setlg - set global = local (source: defaultsyms.txt). Dest = ReadByte(); Src = ReadInt32(); HitVM.SetGlobalVar(Src, GetVariable(Dest)); break; case 0x57: //setgl - read globally, set locally (source: defaultsyms.txt). Dest = ReadByte(); Src = ReadInt32(); SetVariable(Dest, HitVM.GetGlobalVar(Src)); break; case 0x59: //setsrcdatafield - set an object variable (whose ID is specified by the "field" variable) of //a source object (whose object ID is specified by the "source" variable) to the value //specified by the "value" variable. Dest = ReadByte(); Src = ReadByte(); Datafield = ReadByte(); break; case 0x5f: //smart_index - find the entry at the index specified by the "index" variable in the hitlist //specified by the "dest" variable and store that entry in the "dest" variable. Dest = ReadByte(); byte Index = ReadByte(); uint HitlistID = (uint)GetVariable(Index); uint TRKID = SetTrack(HitlistID); SetVariable(Dest, (int)TRKID); break; case 0x60: //note_on_loop - play a note, whose ID resides in the specified variable, and immediately loop //it indefinitely. Dest = ReadByte(); HITNoteEntry Note = new HITNoteEntry(m_SoundID, FileManager.GetSound(m_SoundID)); m_Notes.Add(Note); SetVariable(Dest, m_Notes.Count - 1); m_Player = new SoundPlayer(Note.Sound.DecompressedWav(), Note.Sound.GetSampleRate()); m_Player.PlaySound(); break; } } } else { ISoundCodec Snd = FileManager.GetSound(m_SoundID); m_Player = new SoundPlayer(Snd.DecompressedWav(), Snd.GetSampleRate()); m_Player.PlaySound(); yield return(true); } }