private static void ExecuteInstruction(MemoryContext mem, bool soundMode) { var insn = mem.Instructions[mem.InstructionIndex]; var instructionIndexOffset = 1; switch (insn.Type) { case InstructionType.Snd when soundMode: mem.LastPlayedFrequency = mem.Read(insn.Value1); break; case InstructionType.Rcv when soundMode: if (mem.Read(insn.Value1) != 0) { mem.HitRcv = true; } break; case InstructionType.Snd /* when !soundMode */: mem.OutputQueue.Enqueue(mem.Read(insn.Value1)); mem.SendCount++; break; case InstructionType.Rcv /* when !soundMode */: if (mem.InputQueue.Count == 0) { instructionIndexOffset = 0; // wait for input } else { mem.Store(insn.Value1, mem.InputQueue.Dequeue()); } break; case InstructionType.Set: mem.Store(insn.Value1, mem.Read(insn.Value2)); break; case InstructionType.Add: mem.Store(insn.Value1, mem.Read(insn.Value1) + mem.Read(insn.Value2)); break; case InstructionType.Mul: mem.Store(insn.Value1, mem.Read(insn.Value1) * mem.Read(insn.Value2)); break; case InstructionType.Mod: mem.Store(insn.Value1, mem.Read(insn.Value1) % mem.Read(insn.Value2)); break; case InstructionType.Jgz: if (mem.Read(insn.Value1) > 0) { instructionIndexOffset = (int)mem.Read(insn.Value2); } break; default: throw new InvalidOperationException(); } mem.InstructionIndex += instructionIndexOffset; }