private void OPCode_EXA1(byte register, CHIP8_Keyboard keyboard) { if (registers[register] < 0x10 && !keyboard.keys[registers[register]]) { programCounter += 2; } }
// Starts the interpreter private void StartInterpreteter() { // Ends any previous interpreter session interpreting = false; // Initialises the interpreter interpreter = InitialiseInterpreter(); if (interpreter == null) { return; } // Initialises the interpreter output screen = InitialiseScreen(); if (screen == null) { return; } // Initialises the interpreter keyboard keyboard = InitialiseKeyboard(); if (keyboard == null) { return; } // Sets up the clock to output at frameRate Hz (processes at clockSpeed Hz) and starts the interpreter interpreting = true; clockTimer = new Timer(); clockTimer.Interval = 1000 / frameRate; clockTimer.Tick += new System.EventHandler(ClockTick); clockTimer.Start(); }
private void OPCode_FX0A(byte register, CHIP8_Keyboard keyboard) { // Starts the process of awaiting for a key press awaitingKeyPress = true; keyboard.StartAwaitKeyPress(); // Gets the register to store the key press in registerForKey = register; }
// Checks if a new key has been pressed and, if it has, puts its value into the appropriate register private void AwaitKey(CHIP8_Keyboard keyboard) { // Awaits a key press if necessary byte keyPress = keyboard.GetKeyPress(); if (keyPress != 0x10) { registers[registerForKey] = keyPress; awaitingKeyPress = false; } }
public Window() { InitializeComponent(); // Sets the resolution this.ClientSize = new Size(InterpreterOutput.ClientRectangle.Width, MenuStrip.ClientRectangle.Height + InterpreterOutput.ClientRectangle.Height); // Sets CHIP-8 Objects to null interpreter = null; screen = null; keyboard = null; }
// Performs a single clock cycle public void PerformCycle(ref CHIP8_Screen screen, ref CHIP8_Keyboard keyboard) { // Doesn't perform an operation if waiting for a key press if (awaitingKeyPress) { AwaitKey(keyboard); return; } // Gets an OP code from memory byte byte1 = memory[programCounter++]; byte byte2 = memory[programCounter++]; // Processes the OP code ProcessOPCode(byte1, byte2, ref screen, ref keyboard); return; }
// Processes an OP code instruction private void ProcessOPCode(byte byte1, byte byte2, ref CHIP8_Screen screen, ref CHIP8_Keyboard keyboard) { // Finds the function to execute for the current OP code, gets its arguments, then calls the function switch ((byte1 & 0xF0) >> 4) // Filters through the first nibble { case 0x0: switch (byte1 & 0x0F) // Filters through the second nibble { case 0x0: switch (byte2) // Filters through the second byte { case 0xE0: // 00E0 OPCode_00E0(ref screen); break; case 0xEE: // 00EE OPCode_00EE(); break; } break; } break; case 0x1: // 1NNN OPCode_1NNN((UInt16)(((UInt16)(byte1 & 0x0F) << 8) + (UInt16)byte2)); break; case 0x2: // 2NNN OPCode_2NNN((UInt16)(((UInt16)(byte1 & 0x0F) << 8) + (UInt16)byte2)); break; case 0x3: // 3XNN OPCode_3XNN((byte)(byte1 & 0x0F), byte2); break; case 0x4: // 4XNN OPCode_4XNN((byte)(byte1 & 0x0F), byte2); break; case 0x5: switch (byte2 & 0x0F) // Filters through the fourth nibble { case 0x0: // 5XY0 OPCode_5XY0((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; } break; case 0x6: // 6XNN OPCode_6XNN((byte)(byte1 & 0x0F), byte2); break; case 0x7: // 7XNN OPCode_7XNN((byte)(byte1 & 0x0F), byte2); break; case 0x8: switch (byte2 & 0x0F) // Filters through the fourth nibble { case 0x0: // 8XY0 OPCode_8XY0((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x1: // 8XY1 OPCode_8XY1((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x2: // 8XY2 OPCode_8XY2((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x3: // 8XY3 OPCode_8XY3((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x4: // 8XY4 OPCode_8XY4((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x5: // 8XY5 OPCode_8XY5((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x6: // 8XY6 OPCode_8XY6((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0x7: // 8XY7 OPCode_8XY7((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; case 0xE: // 8XYE OPCode_8XYE((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; } break; case 0x9: switch (byte2 & 0x0F) // Filters through the fourth nibble { case 0x0: // 9XY0 OPCode_9XY0((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4)); break; } break; case 0xA: // ANNN OPCode_ANNN((UInt16)(((UInt16)(byte1 & 0x0F) << 8) + (UInt16)byte2)); break; case 0xB: // BNNN OPCode_BNNN((UInt16)(((UInt16)(byte1 & 0x0F) << 8) + (UInt16)byte2)); break; case 0xC: // CXNN OPCode_CXNN((byte)(byte1 & 0x0F), byte2); break; case 0xD: // DXYN OPCode_DXYN((byte)(byte1 & 0x0F), (byte)((byte2 & 0xF0) >> 4), (byte)(byte2 & 0x0F), screen); break; case 0xE: switch (byte2) // Filters through the second byte { case 0x9E: // EX9E OPCode_EX9E((byte)(byte1 & 0x0F), keyboard); break; case 0xA1: // EXA1 OPCode_EXA1((byte)(byte1 & 0x0F), keyboard); break; } break; case 0xF: switch (byte2) // Filters through the second byte { case 0x07: // FX07 OPCode_FX07((byte)(byte1 & 0x0F)); break; case 0x0A: // FX0A OPCode_FX0A((byte)(byte1 & 0x0F), keyboard); break; case 0x15: // FX15 OPCode_FX15((byte)(byte1 & 0x0F)); break; case 0x18: // FX18 OPCode_FX18((byte)(byte1 & 0x0F)); break; case 0x1E: // FX1E OPCode_FX1E((byte)(byte1 & 0x0F)); break; case 0x29: // FX29 OPCode_FX29((byte)(byte1 & 0x0F)); break; case 0x33: // FX33 OPCode_FX33((byte)(byte1 & 0x0F)); break; case 0x55: // FX55 OPCode_FX55((byte)(byte1 & 0x0F)); break; case 0x65: // FX65 OPCode_FX65((byte)(byte1 & 0x0F)); break; } break; } }