Exemple #1
0
        public HITTVOn(uint ID)
        {
            m_ID = ID;

            m_SoundInstance = new SoundPlayer();

            if (ID == 5) //Loadloop, play the sound directly.
            {
                ISoundCodec Loadloop = FileManager.GetSound(0x00004f85);
                m_IsMusic       = true;
                m_MusicInstance = new SoundPlayer(Loadloop.DecompressedWav(), Loadloop.GetSampleRate());
                m_MusicInstance.PlaySound(true, true);
            }
            else
            {
                m_SoundInstance = new SoundPlayer();
                m_MusicInstance = new SoundPlayer();

                string StrID = "";
                HitVM.MusicModes.TryGetValue((int)ID, out StrID);
                string Path = HitVM.GetStationPath(StrID);

                if (Path != "")
                {
                    LoadMusicFromPath(Path);
                }
            }
        }
        private int GetVariable(int Location)
        {
            if (Location < 5)
            {
                return((int)m_Args[(byte)Location]);
            }
            else if (Location < 0x10)
            {
                return(m_Registers[(byte)Location]);
            }
            else if (Location < 0x46)
            {
                return(m_LocalVars[(byte)(Location - 0x10)]);
            }
            else if (Location < 0x88)
            {
                return(HitVM.GetGlobalVar(Location - 0x64));
            }
            else if (Location < 2736)
            {
                return(m_ObjectVars[(short)(Location - 0x271a)]);
            }

            return(0);
        }
 /// <summary>
 /// Sets a register to a specific value.
 /// </summary>
 /// <param name="Location">Which register to set.</param>
 /// <param name="Value">The value to set.</param>
 private void SetVariable(short Location, int Value)
 {
     if (Location < 5)
     {
         m_Args[(byte)Location] = (uint)Value;
     }
     if (Location < 0x10)
     {
         m_Registers[(byte)Location] = Value;
     }
     else if (Location < 0x46)
     {
         SetLocal(Location, Value);
         m_LocalVars[(byte)(Location - 0x10)] = Value;
     }
     else if (Location < 88)
     {
         HitVM.SetGlobalVar(Location - 0x64, Value);
     }
     else if (Location < 2736)
     {
         m_ObjectVars[Location - 0x271a] = Value;
     }
 }
        /// <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);
            }
        }