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(); } }
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); }
public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory) { //set prefix flag in cpu state cpuState.InstructionPrefix = true; base.ExecuteCycle(cpuState, mainMemory); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory) { cpuState.InterruptMasterEnable = false; cpuState.ImeScheduled = false; base.ExecuteCycle(cpuState, mainMemory); }
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); }
public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory) { cpuState.Registers.CarryFlag = true; cpuState.Registers.HalfCarryFlag = false; cpuState.Registers.SubtractionFlag = false; base.ExecuteCycle(cpuState, mainMemory); }
public Cpu(IRandomAccessMemory memory, IRegisters registers, IFlags flags, IEmulatorInstructionFactory instructionFactory) { Memory = memory ?? throw new ArgumentNullException(nameof(memory)); Registers = registers; this.instructionFactory = instructionFactory; Flags = flags; }
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]; } }
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; } }
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); }
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); }
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); }
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); }
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); }
public override void ExecuteCycle(ICpuState cpuState, IRandomAccessMemory mainMemory) { switch (_remainingCycles) { case 1: cpuState.StackPointer = cpuState.Registers.HL; break; } base.ExecuteCycle(cpuState, mainMemory); }
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); }
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); }