// 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_DXYN(byte register1, byte register2, byte number, CHIP8_Screen screen) { // Gets the sprite byte[] rows = new byte[number]; for (int i = 0; i < number; i++) { rows[i] = memory[addressRegister + i]; } // Draws the sprite registers[0xF] = screen.Draw(registers[register1], registers[register2], rows); }
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; }
/* * OP Codes: * Each method executes the corresponding OP code instruction indicated by its name */ private void OPCode_00E0(ref CHIP8_Screen screen) { screen.Clear(); }
// 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; } }