public void Advance() { //advance the program by one cycle //check if reached end of memory; if (pc >= 4095) { Debug.WriteLine("ERR: reached end of memory"); } else if (currentInstruction == "0000") { Debug.WriteLine("ERR: empty opcode"); } //parse current instruction and set it to a variable currentInstruction = String.Format("{0:X2}", memory[pc]) + String.Format("{0:X2}", memory[pc + 1]); byteInstruction = memory[pc]; Debug.WriteLine("Instruction as byte: " + byteInstruction); //parse x x = Convert.ToInt16(Convert.ToString(currentInstruction[1]), 16); //parsy y y = Convert.ToInt16(Convert.ToString(currentInstruction[2]), 16); //parse n n = Convert.ToInt16(Convert.ToString(currentInstruction[3]), 16); //parse kk kk = Convert.ToInt16(currentInstruction.Substring(2), 16); //parse nnn nnn = Convert.ToInt16(currentInstruction.Substring(1), 16); Debug.WriteLine($"\npc={pc}"); Debug.WriteLine($"The current instruction is:{currentInstruction} "); //set drawflag to false by default drawFlag = false; //switch for all possible instructions //TODO: replace this switch (currentInstruction) { case "00E0": Debug.WriteLine("00E0"); if (!usedInstructions.Contains("00E0")) { usedInstructions.Add("00E0"); } Instructions.clr(this); return; case "00EE": Debug.WriteLine("00EE"); if (!usedInstructions.Contains("00EE")) { usedInstructions.Add("00EE"); } Instructions.ret(this); return; case var dummy when One_addr.IsMatch(dummy): Debug.WriteLine("1nnn"); if (!usedInstructions.Contains("1nnn")) { usedInstructions.Add("1nnn"); } Instructions.jmp(this); return; case var dummy when Two_addr.IsMatch(dummy): Debug.WriteLine("2nnn"); if (!usedInstructions.Contains("2nnn")) { usedInstructions.Add("2nnn"); } Instructions.call(this); return; case var dummy when Three.IsMatch(dummy): Debug.WriteLine("3xkk"); if (!usedInstructions.Contains("3xkk")) { usedInstructions.Add("3xkk"); } Instructions.skp_if_kk(this); return; case var dummy when Four.IsMatch(dummy): Debug.WriteLine("4xkk"); if (!usedInstructions.Contains("4xkk")) { usedInstructions.Add("4xkk"); } Instructions.skp_not_kk(this); return; case var dummy when Five.IsMatch(dummy): Debug.WriteLine("5xy0"); if (!usedInstructions.Contains("5xy0")) { usedInstructions.Add("5xy0"); } Instructions.skp_if_x_y(this); return; case var dummy when Six.IsMatch(dummy): Debug.WriteLine("6xkk"); if (!usedInstructions.Contains("6xkk")) { usedInstructions.Add("6xkk"); } Instructions.ld_vx_kk(this); return; case var dummy when Seven.IsMatch(dummy): Debug.WriteLine("7xkk"); if (!usedInstructions.Contains("7xkk")) { usedInstructions.Add("7xkk"); } Instructions.add_vx_kk(this); return; case var dummy when Eight_load.IsMatch(dummy): Debug.WriteLine("8xy0"); if (!usedInstructions.Contains("8xy0")) { usedInstructions.Add("8xy0"); } Instructions.ld_vx_vy(this); return; case var dummy when Eight_or.IsMatch(dummy): Debug.WriteLine("8xy1"); if (!usedInstructions.Contains("8xy1")) { usedInstructions.Add("8xy1"); } Instructions.or_vx_vy(this); return; case var dummy when Eight_and.IsMatch(dummy): Debug.WriteLine("8xy2"); if (!usedInstructions.Contains("8xy2")) { usedInstructions.Add("8xy2"); } Instructions.and_vx_vy(this); return; case var dummy when Eight_xor.IsMatch(dummy): Debug.WriteLine("8xy3"); if (!usedInstructions.Contains("8xy3")) { usedInstructions.Add("8xy3"); } Instructions.xor_vx_vy(this); return; case var dummy when Eight_add.IsMatch(dummy): Debug.WriteLine("8xy4"); if (!usedInstructions.Contains("8xy4")) { usedInstructions.Add("8xy4"); } Instructions.add_vx_vy(this); return; case var dummy when Eight_sub.IsMatch(dummy): Debug.WriteLine("8xy5"); if (!usedInstructions.Contains("8xy5")) { usedInstructions.Add("8xy5"); } Instructions.sub_vx_vy(this); return; case var dummy when Eight_shr.IsMatch(dummy): Debug.WriteLine("8xy6"); if (!usedInstructions.Contains("8xy6")) { usedInstructions.Add("8xy6"); } Instructions.shr_vx_vy(this); return; case var dummy when Eight_subn.IsMatch(dummy): Debug.WriteLine("8xy7"); Instructions.subn_vy_vx(this); return; case var dummy when Eight_shl.IsMatch(dummy): Debug.WriteLine("8xyE"); if (!usedInstructions.Contains("8xyE")) { usedInstructions.Add("8xyE"); } Instructions.shl_vx_vy(this); return; case var dummy when Nine.IsMatch(dummy): Debug.WriteLine("9xy0"); if (!usedInstructions.Contains("9xy0")) { usedInstructions.Add("9xy0"); } Instructions.skp_not_equal(this); return; case var dummy when A_addr.IsMatch(dummy): if (!usedInstructions.Contains("Annn")) { usedInstructions.Add("Annn"); } Debug.WriteLine($"Annn where nnn = {currentInstruction.Substring(1, 3)}"); Instructions.ld_i_nnn(this); return; case var dummy when B_addr.IsMatch(dummy): Debug.WriteLine("Bnnn"); if (!usedInstructions.Contains("Bnnn")) { usedInstructions.Add("Bnnn"); } Instructions.jmp_v0_nnn(this); return; case var dummy when C_addr.IsMatch(dummy): Debug.WriteLine("Cxkk"); if (!usedInstructions.Contains("Cxkk")) { usedInstructions.Add("Cxkk"); } Instructions.ld_vx_rand(this); return; #region draw_func //huomionarvoista: // optimoinnin vuoksi voisi olla fiksua keksiä tapa vähentää type conversioneita // huom. mahdolliset bugit jotka mainittu edellisissä kommenteissa case var dummy when D_addr.IsMatch(dummy): stopwatch.Start(); Debug.WriteLine("Dxyn"); if (!usedInstructions.Contains("Dxyn")) { usedInstructions.Add("Dxyn"); } Instructions.drw(this); stopwatch.Stop(); Debug.WriteLine($"draw function elapsed ms = {stopwatch.ElapsedMilliseconds}"); stopwatch.Reset(); break; #endregion case var dummy when E_skp.IsMatch(dummy): Debug.WriteLine("Ex9E"); if (!usedInstructions.Contains("Ex9E")) { usedInstructions.Add("Ex9E"); } Instructions.skp_vx(this); return; case var dummy when E_sknp.IsMatch(dummy): Debug.WriteLine("ExA1"); if (!usedInstructions.Contains("ExA1")) { usedInstructions.Add("ExA1"); } Instructions.sknp_vx(this); return; case var dummy when F_load_from_dt.IsMatch(dummy): Debug.WriteLine("Fx07"); if (!usedInstructions.Contains("Fx07")) { usedInstructions.Add("Fx07"); } Instructions.ld_vx_dt(this); Debug.WriteLine($"registers[{x}] = {registers[x]}"); return; case var dummy when F_load_key.IsMatch(dummy): Debug.WriteLine("Fx0A"); if (!usedInstructions.Contains("Fx0A")) { usedInstructions.Add("Fx0"); } Instructions.ld_vx_key(this); return; case var dummy when F_load_to_dt.IsMatch(dummy): Debug.WriteLine("Fx15"); if (!usedInstructions.Contains("Fx15")) { usedInstructions.Add("Fx15"); } Instructions.ld_dt_vx(this); Debug.WriteLine($"delayTimer has been set to {delayTimer}"); return; case var dummy when F_load_to_st.IsMatch(dummy): Debug.WriteLine("Fx18"); if (!usedInstructions.Contains("Annn")) { usedInstructions.Add("Annn"); } Instructions.ld_st_vx(this); return; case var dummy when Add_i_vx.IsMatch(dummy): Debug.WriteLine("Fx1E"); if (!usedInstructions.Contains("Fx1E")) { usedInstructions.Add("Fx1E"); } Instructions.add_i_vx(this); return; case var dummy when Load_f_vx.IsMatch(dummy): Debug.WriteLine("Fx29"); if (!usedInstructions.Contains("Fx29")) { usedInstructions.Add("Fx29"); } Instructions.ld_f_vx(this); return; case var dummy when Load_b_vx.IsMatch(dummy): Debug.WriteLine("Fx33"); if (!usedInstructions.Contains("Fx33")) { usedInstructions.Add("Fx33"); } Instructions.ld_bcd(this); return; case var dummy when Load_i_vx.IsMatch(dummy): Debug.WriteLine("Fx55"); if (!usedInstructions.Contains("Fx55")) { usedInstructions.Add("Fx55"); } Instructions.ld_i_vx(this); return; case var dummy when Load_vx_i.IsMatch(dummy): Debug.WriteLine("Fx65"); if (!usedInstructions.Contains("Fx65")) { usedInstructions.Add("Fx65"); } Instructions.ld_vx_i(this); return; default: Debug.WriteLine("Unknown instruction"); pc += 2; return; } }