Ejemplo n.º 1
0
 private void bitwiseXorRegToReg(Generic.DataStructures.InstructionArgs args)
 {
     // 8XY3: Perform bitwise XOR between registers VX and VY.
     //       Store the result in register VX.
     Processor.V[(byte)(args[0])] ^= Processor.V[(byte)(args[1])];
     Processor.PC += 2;
 }
Ejemplo n.º 2
0
        private void addRegToI(Generic.DataStructures.InstructionArgs args)
        {
            // FX1E: Adds the value of the register VX to I.

            Processor.I  += Processor.V[(byte)(args[0])];
            Processor.PC += 2;
        }
Ejemplo n.º 3
0
 private void leftShiftRegSpillCarry(Generic.DataStructures.InstructionArgs args)
 {
     // 8XYE: Shift register VX 1 position to the left.
     //       Set VF to the MSB of VX before the shift.
     Processor.V[0xF]               = (byte)(((Processor.V[(byte)(args[0])]) & 0x80) >> 7);
     Processor.V[(byte)(args[0])] <<= 1;
     Processor.PC += 2;
 }
Ejemplo n.º 4
0
        private void rightShiftRegSpillCarry(Generic.DataStructures.InstructionArgs args)
        {
            // 8XY6: Shift register VX 1 position to the right.
            //       Set VF to the LSB of VX before the shift.
            Processor.V[0xF] = (byte)((Processor.V[(byte)(args[0])]) & 0x1);

            Processor.V[(byte)(args[0])] >>= 1;
            Processor.PC += 2;
        }
Ejemplo n.º 5
0
        private void skipIfRegNotEqualToReg(Generic.DataStructures.InstructionArgs args)
        {
            // 9XY0: If registers VX and VY are not equal, increment PC by 2.
            if (Processor.V[(byte)(args[0])] != Processor.V[(byte)(args[1])])
            {
                Processor.PC += 2;
            }

            Processor.PC += 2;
        }
Ejemplo n.º 6
0
        private void skipIfRegNotEqualToConst(Generic.DataStructures.InstructionArgs args)
        {
            // 4XKK: If register VX doesn't contain the value KK, increment PC by 2.
            if (Processor.V[(byte)(args[0])] != (byte)(args[1]))
            {
                Processor.PC += 2;
            }

            Processor.PC += 2;
        }
Ejemplo n.º 7
0
        private void loadFontSpriteStartToI(Generic.DataStructures.InstructionArgs args)
        {
            // FX29: Sets I to the start of a predefined sprite's data.
            //       Predefined sprites are hexadecimal digits 0-F.
            //       The value of register VX indicates the sprite to use.

            // As digits are 5 bytes long...
            Processor.I   = (ushort)(5 * Processor.V[(byte)(args[0])]);
            Processor.PC += 2;
        }
Ejemplo n.º 8
0
        private void drawSpriteAndDetectCollision(Generic.DataStructures.InstructionArgs args)
        {
            // DXYN: Draw a sprite on the screen.
            //       Sprite data starts at the address stored in I.
            //       "N" bytes of data are read in total.
            //       The sprite is painted at coordinates (VX, VY).
            //       The screen contents are XORed with the sprite data.
            //       If any pixels are erased, set VF = 1; otherwise, set VF = 0.
            //       Any part of the sprite going outside the screen wraps around.


            if (Processor.VideoRAM == null)
            {
                Processor.PC += 2;
                return;
            }

            byte x0 = Processor.V[(byte)(args[0])];
            byte y0 = Processor.V[(byte)(args[1])];
            byte h  = (byte)(args[2]);

            byte pixel;
            int  screen_pos;

            int xf, yf;

            Processor.V[0xF] = 0;

            for (int y = 0; y < h; y++)
            {
                pixel = Processor.MainRAM[Processor.I + y];

                for (int x = 0; x < 8; x++)
                {
                    if ((pixel & (0x80 >> x)) != 0)
                    {
                        xf = (x0 + x) % 64;
                        yf = (y0 + y) % 32;

                        screen_pos = (64 * yf) + xf;

                        if (Processor.VideoRAM[screen_pos] == 1)
                        {
                            Processor.V[0xF] = 1;
                        }

                        Processor.VideoRAM[screen_pos] ^= 1;
                    }
                }
            }

            Processor.Draw = true;
            Processor.PC  += 2;
        }
Ejemplo n.º 9
0
        private void callSubroutineAtAddress(Generic.DataStructures.InstructionArgs args)
        {
            // 2NNN: Calls the subroutine at address NNN.
            if (Processor.SP == 15)
            {
                throw new Exception("Stack overflow.");
            }

            Processor.Stack[Processor.SP++] = Processor.PC;
            Processor.PC = (ushort)(args[0]);
        }
Ejemplo n.º 10
0
 private void loadBCDOfRegToStartI(Generic.DataStructures.InstructionArgs args)
 {
     // FX33: Store the BCD representation of VX in memory.
     //       The hundreds digit is stored at address I.
     //       The tens digit is stored at address I, +1.
     //       The units digit is stored at address I, +2.
     Processor.MainRAM[Processor.I]     = (byte)(Processor.V[(byte)(args[0])] / 100);
     Processor.MainRAM[Processor.I + 1] = (byte)((Processor.V[(byte)(args[0])] / 10) % 10);
     Processor.MainRAM[Processor.I + 2] = (byte)(Processor.V[(byte)(args[0])] % 10);
     Processor.PC += 2;
 }
Ejemplo n.º 11
0
        private void bitwiseAndRandomNumberAndConst(Generic.DataStructures.InstructionArgs args)
        {
            // CXKK: Generate a random number between 0x00 and 0xFF.
            //       Perform a bitwise AND between this number and the value KK.
            //       Store the result in register VX.
            int randNum = Processor.RandomGenerator.Next(256);

            Processor.V[(byte)(args[0])] = (byte)(randNum & (byte)(args[1]));

            Processor.PC += 2;
        }
Ejemplo n.º 12
0
        private void clearScreen(Generic.DataStructures.InstructionArgs args)
        {
            // 00E0: Clears the screen.
            if (Processor.VideoRAM != null)
            {
                Processor.VideoRAM.Clear();
            }

            Processor.Draw = true;
            Processor.PC  += 2;
        }
Ejemplo n.º 13
0
        private void returnFromSubroutine(Generic.DataStructures.InstructionArgs args)
        {
            // 00EE: Returns from subroutine.
            if (Processor.SP == 0)
            {
                throw new Exception("Stack underflow.");
            }

            Processor.PC  = Processor.Stack[--Processor.SP];
            Processor.PC += 2;
        }
Ejemplo n.º 14
0
        private void subtractRegToTegWithBorrow(Generic.DataStructures.InstructionArgs args)
        {
            // 8XY5: Subtract the value of register VY from register VX.
            //       Store the result in register VX.
            //       If VX > VY, set VF = 1; otherwise, set VF = 0.
            if (Processor.V[(byte)(args[0])] > Processor.V[(byte)(args[1])])
            {
                Processor.V[0xF] = 1;
            }
            else
            {
                Processor.V[0xF] = 0;
            }

            Processor.V[(byte)(args[0])] -= Processor.V[(byte)(args[1])];
            Processor.PC += 2;
        }
Ejemplo n.º 15
0
        private void skipIfKeypressNameInRegIsNotPressed(Generic.DataStructures.InstructionArgs args)
        {
            // EXA1: Checks if the key with name in register VX is NOT pressed.
            //       If so, the next instruction is skipped.
            if (Processor.Keyboard == null)
            {
                Processor.PC += 2;
                return;
            }

            if (!Processor.Keyboard.GetKeyState(Processor.V[(byte)(args[0])]))
            {
                Processor.PC += 2;
            }

            Processor.PC += 2;
        }
Ejemplo n.º 16
0
        private void skipIfKeypressNameInRegIsPressed(Generic.DataStructures.InstructionArgs args)
        {
            // EX9E: Checks if a key is pressed and its name is in register VX.
            //       If so, the next instruction is skipped.
            if (Processor.Keyboard == null)
            {
                Processor.PC += 2;
                return;
            }

            if (Processor.Keyboard.GetKeyState(Processor.V[(byte)(args[0])]))
            {
                Processor.PC += 2;
            }

            Processor.PC += 2;
        }
Ejemplo n.º 17
0
        private void addRegToRegWithCarry(Generic.DataStructures.InstructionArgs args)
        {
            // 8XY4: Add the values of registers VX and VY.
            //       Store the result in register VX.
            //       If VX + VY > 0xFF, set VF = 1; otherwise, set VF = 0.
            if ((ushort)Processor.V[(byte)(args[0])] + Processor.V[(byte)(args[1])] > 0xFF)
            {
                Processor.V[0xF] = 1;
            }
            else
            {
                Processor.V[0xF] = 0;
            }

            Processor.V[(byte)(args[0])] += Processor.V[(byte)(args[1])];
            Processor.PC += 2;
        }
Ejemplo n.º 18
0
        private void invertedSubtractRegToRegWithBorrow(Generic.DataStructures.InstructionArgs args)
        {
            // 8XY7: Subtract the value of register VX from register VY.
            //       Store the result in register VX.
            //       If VY > VX, set VF = 1; otherwise, set VF = 0.
            if (Processor.V[(byte)(args[1])] > Processor.V[(byte)(args[0])])
            {
                Processor.V[0xF] = 1;
            }
            else
            {
                Processor.V[0xF] = 0;
            }

            Processor.V[(byte)(args[0])] = (byte)(Processor.V[(byte)(args[1])] - Processor.V[(byte)(args[0])]);
            Processor.PC += 2;
        }
Ejemplo n.º 19
0
        private void loadSoundTimerWithReg(Generic.DataStructures.InstructionArgs args)
        {
            // FX18: Sets the sound timer to the value stored in register VX.
            Processor.SoundTimer = Processor.V[(byte)(args[0])];

            // The sound should immedately start playing,
            // BUT only if the value is different from zero.
            if (Processor.SoundTimer != 0)
            {
                Processor.Playing = true;

                if (Processor.Buzzer != null)
                {
                    Processor.Buzzer.Play();
                }
            }

            Processor.PC += 2;
        }
Ejemplo n.º 20
0
        private void populateRegsFromMemoryStartingAtI(Generic.DataStructures.InstructionArgs args)
        {
            // FX65: Populate registers V0 through VX with data in memory.
            //       The source starts at the address stored in I.
            int noRegs = (byte)(args[0]);

            for (int r = 0; r <= noRegs; r++)
            {
                Processor.V[r] = Processor.MainRAM[Processor.I + r];
            }

            // Per mattmik, I reg. should reflect the counting.
            // BEWARE: Game TICTAC doesn't work if counting is reflected!
            if (Processor.ModifyI)
            {
                Processor.I += (ushort)(noRegs + 1);
            }

            Processor.PC += 2;
        }
Ejemplo n.º 21
0
        private void waitForKeypressAndStoreNameInReg(Generic.DataStructures.InstructionArgs args)
        {
            // FX0A: Wait for a key press, then store its name in register VX.
            if (Processor.Keyboard == null)
            {
                Processor.PC += 2;
                return;
            }

            int last_keycode;

            if ((last_keycode = Processor.Keyboard.LastKeyIndex) == Processor.Keyboard.NoKeyPress)
            {
                return; //break;
            }
            Processor.V[(byte)(args[0])] = (byte)last_keycode;

            // Avoid getting the key "stuck" for an entire display refresh!
            Processor.Keyboard.ClearLastIndex();

            Processor.PC += 2;
        }
Ejemplo n.º 22
0
 private void loadIWithAddress(Generic.DataStructures.InstructionArgs args)
 {
     // ANNN: Sets I to the address NNN.
     Processor.I   = (ushort)(args[0]);
     Processor.PC += 2;
 }
Ejemplo n.º 23
0
 private void jumpToAddress(Generic.DataStructures.InstructionArgs args)
 {
     // 1NNN: Jump to location NNN.
     Processor.PC = (ushort)(args[0]);
 }
Ejemplo n.º 24
0
 private void unrecognizedInstruction(Generic.DataStructures.InstructionArgs args)
 {
     Processor.PC += 2;
 }
Ejemplo n.º 25
0
 private void jumpToAddressWithOffsetInReg0(Generic.DataStructures.InstructionArgs args)
 {
     // BNNN: Jump to location NNN + the value of register V0.
     Processor.PC = (ushort)((ushort)(args[0]) + Processor.V[0]);
 }
Ejemplo n.º 26
0
 private void loadRegToReg(Generic.DataStructures.InstructionArgs args)
 {
     // 8XY0: Stores the value of register VY in register VX.
     Processor.V[(byte)(args[0])] = Processor.V[(byte)(args[1])];
     Processor.PC += 2;
 }
Ejemplo n.º 27
0
 private void loadRegWithDelayValue(Generic.DataStructures.InstructionArgs args)
 {
     // FX07: Sets register VX to the current delay timer value.
     Processor.V[(byte)(args[0])] = Processor.DelayTimer;
     Processor.PC += 2;
 }
Ejemplo n.º 28
0
 private void loadConstToReg(Generic.DataStructures.InstructionArgs args)
 {
     // 6XKK: Put the value KK into register VX.
     Processor.V[(byte)(args[0])] = (byte)(byte)(args[1]);
     Processor.PC += 2;
 }
Ejemplo n.º 29
0
 private void addConstToRegNoCarry(Generic.DataStructures.InstructionArgs args)
 {
     // 7XKK: Add the value KK to register VX. (No carry generated.)
     Processor.V[(byte)(args[0])] += (byte)(byte)(args[1]);
     Processor.PC += 2;
 }
Ejemplo n.º 30
0
 private void loadDelayValueWithReg(Generic.DataStructures.InstructionArgs args)
 {
     // FX15: Sets the delay timer to the value stored in register VX.
     Processor.DelayTimer = Processor.V[(byte)(args[0])];
     Processor.PC        += 2;
 }