Пример #1
0
    public static void ToConsole(this IRandomAccessMemory ram, ushort start, ushort length)
    {
        var bytesBuilder     = new StringBuilder(16 * 4);
        var characterBuilder = new StringBuilder(16);

        ushort width = 16;

        for (var address = start; address <= start + length; address += width)
        {
            Console.Write($"{address:X4} ".Pastel(Color.Goldenrod));

            bytesBuilder.Clear();
            characterBuilder.Clear();
            var bytes = new byte[16];
            for (ushort column = 0; column < width; column++)
            {
                var value = ram[(ushort)(address + column)];
                bytes[column] = value;
                bytesBuilder.Append($"{value:X2} ");
                characterBuilder.Append(MockAsciiMapper.ConvertByteToChar(value));
            }

            Console.Write(bytesBuilder.ToString().Pastel(Color.Orchid));
            Console.Write(characterBuilder.ToString().Pastel(Color.Teal));

            Console.WriteLine();
        }
    }
Пример #2
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 6:
                //read jump address lsb
                _jumpAddress = mainMemory.ReadByte(cpuState.ProgramCounter++);
                break;

            case 5:
                //read jump address msb
                _jumpAddress |= (ushort)(mainMemory.ReadByte(cpuState.ProgramCounter++) << 8);
                break;

            case 3:
                //write msb of program counter to stack
                mainMemory.WriteByte(--cpuState.StackPointer, (byte)(cpuState.ProgramCounter >> 8));
                break;

            case 2:
                //write lsb of program counter to stack
                mainMemory.WriteByte(--cpuState.StackPointer, (byte)(cpuState.ProgramCounter & 0x00FF));
                break;

            case 1:
                //do the jump
                cpuState.ProgramCounter = _jumpAddress;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #3
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            //set prefix flag in cpu state
            cpuState.InstructionPrefix = true;

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #4
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 5:
                _writeAddress = mainMemory.ReadByte(cpuState.ProgramCounter++);
                break;

            case 4:
                _writeAddress |= (ushort)(mainMemory.ReadByte(cpuState.ProgramCounter++) << 8);
                break;

            case 3:
                //write lsb of stack pointer
                mainMemory.WriteByte(_writeAddress, (byte)cpuState.StackPointer);
                break;

            case 2:
                //write msb of stack pointer
                mainMemory.WriteByte((ushort)(_writeAddress + 1), (byte)(cpuState.StackPointer >> 8));
                break;

            case 1:
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #5
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 4:
                //read jump address lsb
                _jumpAddress = mainMemory.ReadByte(cpuState.StackPointer++);
                break;

            case 3:
                //read jump address msb
                _jumpAddress |= (ushort)(mainMemory.ReadByte(cpuState.StackPointer++) << 8);
                break;

            case 2:
                cpuState.ImeScheduled = true;
                break;

            case 1:
                //do the jump
                cpuState.ProgramCounter = _jumpAddress;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #6
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 3:
                //read jump address lsb
                _relativeAddress = (sbyte)mainMemory.ReadByte(cpuState.ProgramCounter++);
                break;

            case 2:
                //set last cycle if condition is not met
                if (!IsConditionMet(cpuState))
                {
                    _remainingCycles = 1;
                }
                break;

            case 1:
                //do the jump
                cpuState.ProgramCounter = (ushort)(cpuState.ProgramCounter + _relativeAddress);
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #7
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 5:
                if (!IsConditionMet(cpuState))
                {
                    _remainingCycles = 2;
                }
                break;

            case 4:
                //read jump address lsb
                _jumpAddress = mainMemory.ReadByte(cpuState.StackPointer++);
                break;

            case 3:
                //read jump address msb
                _jumpAddress |= (ushort)(mainMemory.ReadByte(cpuState.StackPointer++) << 8);
                break;

            case 2:
                //do the jump
                cpuState.ProgramCounter = _jumpAddress;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #8
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            if (!cpuState.Registers.SubtractionFlag)
            {
                if (cpuState.Registers.CarryFlag || cpuState.Registers.A > 0x99)
                {
                    cpuState.Registers.A        += 0x60;
                    cpuState.Registers.CarryFlag = true;
                }

                if (cpuState.Registers.HalfCarryFlag || (cpuState.Registers.A & 0x0f) > 0x09)
                {
                    cpuState.Registers.A += 0x6;
                }
            }
            else
            {
                if (cpuState.Registers.CarryFlag)
                {
                    cpuState.Registers.A -= 0x60;
                }

                if (cpuState.Registers.HalfCarryFlag)
                {
                    cpuState.Registers.A -= 0x6;
                }
            }

            cpuState.Registers.HalfCarryFlag = false;
            cpuState.Registers.ZeroFlag      = cpuState.Registers.A == 0;
            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #9
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                _registerBits = (byte)((_opcode >> 4) & 0x03);
                break;

            case 1:
                switch (_registerBits)
                {
                case 0b00:
                    cpuState.Registers.BC++;
                    break;

                case 0b01:
                    cpuState.Registers.DE++;
                    break;

                case 0b10:
                    cpuState.Registers.HL++;
                    break;

                case 0b11:
                    cpuState.StackPointer++;
                    break;
                }
                break;
            }
            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #10
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                _addData = mainMemory.ReadByte(cpuState.ProgramCounter++);
                break;

            case 1:
                var oldValue = cpuState.Registers.A;

                int result = cpuState.Registers.A + _addData;
                if (cpuState.Registers.CarryFlag)
                {
                    result++;
                }

                cpuState.Registers.A = (byte)result;

                cpuState.Registers.SubtractionFlag = false;
                cpuState.Registers.ZeroFlag        = cpuState.Registers.A == 0;
                cpuState.Registers.HalfCarryFlag   = (((oldValue & 0xF) + (_addData & 0xF)
                                                       + (cpuState.Registers.CarryFlag ? 1 : 0)) & 0x10) == 0x10;
                cpuState.Registers.CarryFlag = result > 0xFF;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #11
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 3:
                _currentData = mainMemory.ReadByte(cpuState.Registers.HL);
                break;

            case 2:
                _hiBit = _currentData & 0x80;
                _loBit = _currentData & 0x01;

                _writeData  = (byte)(_currentData >> 1);
                _writeData |= (byte)_hiBit;

                mainMemory.WriteByte(cpuState.Registers.HL, _writeData);

                cpuState.Registers.CarryFlag       = _loBit == 0x01;
                cpuState.Registers.ZeroFlag        = _writeData == 0;
                cpuState.Registers.HalfCarryFlag   = false;
                cpuState.Registers.SubtractionFlag = false;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #12
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 4:
                //calculate jump address
                _jumpAddress = (ushort)(_opcode & 0x38);
                break;

            case 3:
                //write msb of program counter to stack
                mainMemory.WriteByte(--cpuState.StackPointer, (byte)(cpuState.ProgramCounter >> 8));
                break;

            case 2:
                //write lsb of program counter to stack
                mainMemory.WriteByte(--cpuState.StackPointer, (byte)(cpuState.ProgramCounter & 0x00FF));
                break;

            case 1:
                //do the jump
                cpuState.ProgramCounter = _jumpAddress;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #13
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 3:
                _currentData = mainMemory.ReadByte(cpuState.Registers.HL);
                break;

            case 2:
                byte lowNibble  = (byte)(_currentData & 0x0F);
                byte highNibble = (byte)(_currentData & 0xF0);

                _writeData = (byte)((lowNibble << 4) | (highNibble >> 4));

                mainMemory.WriteByte(cpuState.Registers.HL, _writeData);

                cpuState.Registers.ZeroFlag        = _writeData == 0;
                cpuState.Registers.HalfCarryFlag   = false;
                cpuState.Registers.SubtractionFlag = false;
                cpuState.Registers.CarryFlag       = false;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
 /// <summary>
 ///     For the vast majority of instructions this base method writes the 4 bytes of
 ///     the instruction to memory, but for the storage instructions (defs, defw, defb etc)
 ///     there are a variable number of bytes to output
 /// </summary>
 /// <param name="ram"></param>
 /// <param name="address"></param>
 /// <exception cref="NotImplementedException"></exception>
 public virtual void WriteBytes(IRandomAccessMemory ram, ushort address)
 {
     ram[address++] = OpCode;
     ram[address++] = Register;
     ram[address++] = ByteHigh;
     ram[address++] = ByteLow;
 }
Пример #15
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 4:
                _signedValue = (sbyte)mainMemory.ReadByte(cpuState.ProgramCounter++);
                _oldValue    = cpuState.StackPointer;
                break;

            case 3:
                cpuState.StackPointer = (ushort)(cpuState.StackPointer + _signedValue);
                break;

            case 1:
                if (_signedValue >= 0)
                {
                    cpuState.Registers.CarryFlag     = ((_oldValue & 0xFF) + (_signedValue)) > 0xFF;
                    cpuState.Registers.HalfCarryFlag = ((_oldValue & 0xF) + (_signedValue & 0xF)) > 0xF;
                }
                else
                {
                    cpuState.Registers.CarryFlag     = (cpuState.StackPointer & 0xFF) <= (_oldValue & 0xFF);
                    cpuState.Registers.HalfCarryFlag = (cpuState.StackPointer & 0xF) <= (_oldValue & 0xF);
                }

                cpuState.Registers.ZeroFlag        = false;
                cpuState.Registers.SubtractionFlag = false;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #16
0
        public GameBoy(string romPath)
        {
            _logger = new Logger();

            _mainMemory    = new MainMemory();
            _dmaController = new DmaController(_mainMemory);

            _timer  = new Timer(_mainMemory);
            _joypad = new Joypad();

            _serialController = new SerialController(_mainMemory);

            _pixelProcessingUnit = new PixelProcessingUnit(_mainMemory, _logger);
            _audioProcessingUnit = new AudioProcessingUnit();

            IRandomAccessMemory mainMemoryProxy = new MainMemoryDmaProxy(_mainMemory, _dmaController);

            _cpuCore = new CpuCore(mainMemoryProxy, new CpuState(), _logger);

            IRomLoader romLoader = new FileRomLoader(romPath);

            _ramManager = new FileRamManager(Path.ChangeExtension(romPath, ".sav"));

            _memoryBankController = MBCFactory.CreateMBC(romLoader);
            _memoryBankController.LoadRam(_ramManager);

            _mainMemory.RegisterMemoryAccessDelegate(_memoryBankController as IMemoryAccessDelegate);
            _mainMemory.RegisterMemoryAccessDelegate(_pixelProcessingUnit);
            _mainMemory.RegisterMemoryAccessDelegate(_timer);
            _mainMemory.RegisterMemoryAccessDelegate(_joypad);
            _mainMemory.RegisterMemoryAccessDelegate(_audioProcessingUnit);
            _mainMemory.RegisterMemoryAccessDelegate(_serialController);
        }
Пример #17
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            cpuState.InterruptMasterEnable = false;
            cpuState.ImeScheduled          = false;

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #18
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                _subData = mainMemory.ReadByte(cpuState.ProgramCounter++);
                break;

            case 1:
                var oldValue = cpuState.Registers.A;

                cpuState.Registers.A -= _subData;

                if (cpuState.Registers.CarryFlag)
                {
                    cpuState.Registers.A--;
                }

                cpuState.Registers.SubtractionFlag = true;
                cpuState.Registers.ZeroFlag        = cpuState.Registers.A == 0;
                cpuState.Registers.HalfCarryFlag   = ((_subData & 0x0F)
                                                      + (cpuState.Registers.CarryFlag ? 1 : 0)) > (oldValue & 0xF);
                cpuState.Registers.CarryFlag = (_subData + (cpuState.Registers.CarryFlag ? 1 : 0)) > oldValue;

                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #19
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            cpuState.Registers.CarryFlag       = true;
            cpuState.Registers.HalfCarryFlag   = false;
            cpuState.Registers.SubtractionFlag = false;

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #20
0
 public Cpu(IRandomAccessMemory memory, IRegisters registers, IFlags flags,
            IEmulatorInstructionFactory instructionFactory)
 {
     Memory    = memory ?? throw new ArgumentNullException(nameof(memory));
     Registers = registers;
     this.instructionFactory = instructionFactory;
     Flags = flags;
 }
Пример #21
0
    public static void Load(this IRandomAccessMemory ram, string filename)
    {
        var bytes = File.ReadAllBytes(filename);

        for (int idx = 0; idx < bytes.Length; idx++)
        {
            ram[(ushort)idx] = bytes[idx];
        }
    }
Пример #22
0
 public override void WriteBytes(IRandomAccessMemory ram, ushort address)
 {
     for (ushort i = 0; i < Size; i++)
     {
         // we might add defs 32, 7 in future to initialize 32 bytes with the value 7
         // for now we zero out the space
         ram[(ushort)(address + i)] = 0;
     }
 }
Пример #23
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            //decode register and bit
            var bitIndex      = (_opcode & 0x38) >> 3;
            var registerIndex = _opcode & 0x07;

            cpuState.Registers[registerIndex] = (ushort)(cpuState.Registers[registerIndex] & ~(0x01 << bitIndex));

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #24
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                cpuState.Registers.A = mainMemory.ReadByte((ushort)((0xFF << 8) | cpuState.Registers.C));
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #25
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                mainMemory.WriteByte(cpuState.Registers.BC, cpuState.Registers.A);
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #26
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            var registerIndex = _opcode & 0x07;

            cpuState.Registers.SubtractionFlag = true;
            cpuState.Registers.ZeroFlag        = cpuState.Registers.A - (byte)cpuState.Registers[registerIndex] == 0;
            cpuState.Registers.HalfCarryFlag   = ((cpuState.Registers.A & 0xF) - (cpuState.Registers[registerIndex] & 0xF)) < 0;
            cpuState.Registers.CarryFlag       = (byte)cpuState.Registers[registerIndex] > cpuState.Registers.A;

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #27
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            //register decoding
            var sourceIndex = _opcode & 0x07;
            var targetIndex = (_opcode >> 3) & 0x07;

            //load
            cpuState.Registers[targetIndex] = cpuState.Registers[sourceIndex];

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #28
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 1:
                cpuState.StackPointer = cpuState.Registers.HL;
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #29
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            var registerIndex = _opcode >> 3;
            var oldValue      = cpuState.Registers[registerIndex]--;

            cpuState.Registers.SubtractionFlag = true;
            cpuState.Registers.ZeroFlag        = cpuState.Registers[registerIndex] == 0;
            cpuState.Registers.HalfCarryFlag   = (oldValue & 0x0F) == 0;

            base.ExecuteCycle(cpuState, mainMemory);
        }
Пример #30
0
        public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory)
        {
            switch (_remainingCycles)
            {
            case 2:
                var registerIndex = _opcode & 0x07;
                mainMemory.WriteByte(cpuState.Registers.HL, (byte)cpuState.Registers[registerIndex]);
                break;
            }

            base.ExecuteCycle(cpuState, mainMemory);
        }