Пример #1
0
        public CPU(Screen screen, RAM ram, Keyboard keyboard)
        {
            this.screen   = screen;
            this.ram      = ram;
            this.keyboard = keyboard;

            VX = new byte[VX_SIZE];
            SubroutineStack = new Stack <ushort>((int)STACK_SIZE);
            Randomizer      = new Random();
            instructions    = Instructions.GetInstructions();

            PC = RAM.ROM_OFFSET;
        }
Пример #2
0
        private void instruction_0x0_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
        {
            // Close the window
            if (instruction.KK == 0x00)
            {
                screen.Window.Close();
            }

            // Clear the screen
            if (instruction.KK == 0xE0)
            {
                screen.Clear();
                return;
            }

            // Return from a subroutine
            if (instruction.KK == 0xEE)
            {
                cpu.PC = cpu.SubroutineStack.Pop();
                return;
            }
        }
Пример #3
0
        static async void StartEmulating(CLIOptions options)
        {
            Keyboard keyboard = new Keyboard(options.KeyboardDelay);
            Screen   screen   = new Screen(options.Scale);
            RAM      ram      = new RAM();

            ram.LoadROM(options.RomPath);

            CPU cpu = new CPU(screen, ram, keyboard);

            timer = new Timer(60);

            timer.OnTick     += () => cpu.TimerTick();
            screen.OnResumed += () => timer.Restart();

            UpdateTimerAsync();

            while (screen.Window.IsOpen)
            {
                cpu.Tick();
                screen.Render();
            }
        }
Пример #4
0
        private void instruction_0xE_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
        {
            // Skip next instruction if key with the value of Vx is pressed.
            if (instruction.KK == 0x9E)
            {
                byte key = cpu.VX[instruction.X];
                if (keyboard.IsKeyPressed(key))
                {
                    cpu.SkipInstruction();
                }
                return;
            }

            // Skip next instruction if key with the value of Vx is not pressed.
            if (instruction.KK == 0xA1)
            {
                byte key = cpu.VX[instruction.X];
                if (!keyboard.IsKeyPressed(key))
                {
                    cpu.SkipInstruction();
                }
                return;
            }
        }
Пример #5
0
 private void instruction_0x2_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Call subroutine at nnn
     cpu.SubroutineStack.Push(cpu.PC);
     cpu.PC = instruction.NNN;
 }
Пример #6
0
 private void instruction_0x1_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Jump to location nnn
     cpu.PC = instruction.NNN;
 }
Пример #7
0
        private void instruction_0xF_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
        {
            // Set Vx = delay timer value.
            if (instruction.KK == 0x07)
            {
                cpu.VX[instruction.X] = cpu.DelayTimer;
                return;
            }

            // Wait for a key press, store the value of the key in Vx.
            // I THINK I'VE FOUND A F*****G ERROR!!!!
            if (instruction.KK == 0x0A)
            {
                /*
                 * bool pressedKey = false;
                 * while (!pressedKey)
                 * {
                 *  for (byte key = 0; key <= 0xF; ++key)
                 *  {
                 *      pressedKey = keyboard.IsKeyPressed(key);
                 *      if (pressedKey)
                 *      {
                 *          cpu.VX[instruction.X] = key;
                 *          break;
                 *      }
                 *  }
                 * }*/
                bool pressedKey = false;
                for (byte key = 0; key <= 0xF; ++key)
                {
                    pressedKey = keyboard.IsKeyPressed(key);
                    if (pressedKey)
                    {
                        cpu.VX[instruction.X] = key;
                        break;
                    }
                }

                if (!pressedKey)
                {
                    cpu.PC -= 2;
                }
                return;
            }

            // Set delay timer = Vx.
            if (instruction.KK == 0x15)
            {
                cpu.DelayTimer = cpu.VX[instruction.X];
                return;
            }

            // Set sound timer = Vx.
            if (instruction.KK == 0x18)
            {
                cpu.SoundTimer = cpu.VX[instruction.X];
                return;
            }

            // Set I = I + Vx.
            if (instruction.KK == 0x1E)
            {
                cpu.I += cpu.VX[instruction.X];
                return;
            }

            // Set I = location of sprite for digit Vx.
            if (instruction.KK == 0x29)
            {
                cpu.I = (ushort)(RAM.SPRITES_OFFSET + cpu.VX[instruction.X] * RAM.SPRITE_SIZE);
                return;
            }

            // Store BCD representation of Vx in memory locations I, I+1, and I+2.
            if (instruction.KK == 0x33)
            {
                byte number        = cpu.VX[instruction.X];
                byte hundredsDigit = (byte)(Math.Floor((double)number / 100) % 10);
                byte tensDigit     = (byte)(Math.Floor((double)number / 10) % 10);
                byte onesDigit     = (byte)(number % 10);

                byte[] data = { hundredsDigit, tensDigit, onesDigit };
                ram.LoadToMemory(data, cpu.I);

                return;
            }

            // Store registers V0 through Vx in memory starting at location I.
            if (instruction.KK == 0x55)
            {
                byte[] data = new byte[instruction.X + 1];
                for (uint i = 0; i <= instruction.X; ++i)
                {
                    data[i] = cpu.VX[i];
                }
                ram.LoadToMemory(data, cpu.I);
                return;
            }

            // Read registers V0 through Vx from memory starting at location I.
            if (instruction.KK == 0x65)
            {
                byte[] data = ram.Read(cpu.I, (uint)cpu.I + instruction.X);

                for (uint i = 0; i < data.Length; ++i)
                {
                    cpu.VX[i] = data[i];
                }

                return;
            }
        }
Пример #8
0
 private void instruction_0xB_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Jump to location nnn + V0
     cpu.PC = (ushort)(instruction.NNN + cpu.VX[0]);
 }
Пример #9
0
 private void instruction_0xA_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Set I = nnn
     cpu.I = instruction.NNN;
 }
Пример #10
0
        private void instruction_0x8_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
        {
            // Set Vx = Vy
            if (instruction.N == 0x0)
            {
                cpu.VX[instruction.X] = cpu.VX[instruction.Y];
                return;
            }

            // Set Vx = Vx OR Vy.
            if (instruction.N == 0x1)
            {
                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] | cpu.VX[instruction.Y]);
                return;
            }

            // Set Vx = Vx AND Vy
            if (instruction.N == 0x2)
            {
                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] & cpu.VX[instruction.Y]);
                return;
            }

            // Set Vx = Vx XOR Vy.
            if (instruction.N == 0x3)
            {
                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] ^ cpu.VX[instruction.Y]);
                return;
            }

            // Set Vx = Vx + Vy, set VF = carry.
            if (instruction.N == 0x4)
            {
                if (cpu.VX[instruction.X] + cpu.VX[instruction.Y] > 255)
                {
                    cpu.VX[0xF] = 1;
                }
                else
                {
                    cpu.VX[0xF] = 0;
                }

                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] + cpu.VX[instruction.Y]);
                return;
            }

            // Set Vx = Vx - Vy, set VF = NOT borrow.
            if (instruction.N == 0x5)
            {
                if (cpu.VX[instruction.X] > cpu.VX[instruction.Y])
                {
                    cpu.VX[0xF] = 1;
                }
                else
                {
                    cpu.VX[0xF] = 0;
                }

                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] - cpu.VX[instruction.Y]);
                return;
            }

            // Set Vx = Vx SHR 1
            if (instruction.N == 0x6)
            {
                if ((cpu.VX[instruction.X] & 0x1) == 0x1)
                {
                    cpu.VX[0xF] = 1;
                }
                else
                {
                    cpu.VX[0xF] = 0;
                }

                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] / 2);
                return;
            }

            // Set Vx = Vy - Vx, set VF = NOT borrow.
            if (instruction.N == 0x7)
            {
                if (cpu.VX[instruction.Y] > cpu.VX[instruction.X])
                {
                    cpu.VX[0xF] = 1;
                }
                else
                {
                    cpu.VX[0xF] = 0;
                }

                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.Y] - cpu.VX[instruction.X]);
                return;
            }

            // Set Vx = Vx SHL 1.
            if (instruction.N == 0xE)
            {
                if ((cpu.VX[instruction.X] & 0x80) == 0x80)
                {
                    cpu.VX[0xF] = 1;
                }
                else
                {
                    cpu.VX[0xF] = 0;
                }

                cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] * 2);
                return;
            }
        }
Пример #11
0
 private void instruction_0x7_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Set Vx = Vx + kk
     cpu.VX[instruction.X] = (byte)(cpu.VX[instruction.X] + instruction.KK);
 }
Пример #12
0
 private void instruction_0x6_handler(CPUInstruction instruction, CPU cpu, RAM ram, Screen screen, Keyboard keyboard)
 {
     // Set Vx = kk
     cpu.VX[instruction.X] = instruction.KK;
 }