using System.Collections.Generic; using Emux.GameBoy.Audio; using Emux.GameBoy.Cartridge; using Emux.GameBoy.Cpu; using Emux.GameBoy.Graphics; using Emux.GameBoy.Input; using Emux.GameBoy.Memory; using Emux.GameBoy.Timer; namespace Emux.GameBoy { /// /// Represents an emulated game boy device. This includes the processor chip, the graphics chip, the memory controller /// public class GameBoy { public GameBoy(ICartridge cartridge, IClock clock, bool preferGbcMode) { Cartridge = cartridge; GbcMode = preferGbcMode && (cartridge.GameBoyColorFlag & GameBoyColorFlag.SupportsColor) != 0; Components = new List { (Memory = new GameBoyMemory(this)), (Cpu = new GameBoyCpu(this, clock)), (Gpu = new GameBoyGpu(this)), (Spu = new GameBoySpu(this)), (KeyPad = new GameBoyPad(this)), (Timer = new GameBoyTimer(this)) }.AsReadOnly(); foreach (var component in Components) component.Initialize(); Reset(); IsPoweredOn = true; } public ICollection Components { get; } /// /// Gets a value indicating whether the GameBoy device is in GameBoy Color (GBC) mode, enabling specific features only GameBoy Color devices have. /// public bool GbcMode { get; } /// /// Gets the central processing unit of the emulated GameBoy device. /// public GameBoyCpu Cpu { get; } /// /// Gets the graphics processing unit of the emulated GameBoy device. /// public GameBoyGpu Gpu { get; } /// /// Gets the sound processing unit of the emulated GameBoy device. /// public GameBoySpu Spu { get; } /// /// Gets the memory controller of the emulated GameBoy device. /// public GameBoyMemory Memory { get; } /// /// Gets the cartridge that is inserted into the GameBoy. /// public ICartridge Cartridge { get; } /// /// Gets the keypad driver of the GameBoy device. /// public GameBoyPad KeyPad { get; } /// /// Gets the timer driver of the GameBoy device. /// public GameBoyTimer Timer { get; } /// /// Gets a value indicating whether the GameBoy device is powered on. /// public bool IsPoweredOn { get; private set; } /// /// Resets the state of the GameBoy to the bootup state. /// public void Reset() { foreach (var component in Components) component.Reset(); Cpu.Registers.A = GbcMode ? (byte) 0x11 : (byte) 0x01; Cpu.Registers.F = 0xB0; Cpu.Registers.BC = 0x0013; Cpu.Registers.DE = 0x00D8; Cpu.Registers.HL = 0x014D; Cpu.Registers.PC = 0x100; Cpu.Registers.SP = 0xFFFE; Cpu.Registers.IE = 0; Cpu.Registers.IF = (InterruptFlags) 0xE1; Cpu.Registers.IME = false; Memory.WriteByte(0xFF05, 0x00); Memory.WriteByte(0xFF06, 0x00); Memory.WriteByte(0xFF07, 0x00); Memory.WriteByte(0xFF10, 0x80); Memory.WriteByte(0xFF11, 0xBF); Memory.WriteByte(0xFF12, 0xF3); Memory.WriteByte(0xFF14, 0xBF); Memory.WriteByte(0xFF16, 0x3F); Memory.WriteByte(0xFF17, 0x00); Memory.WriteByte(0xFF19, 0xBF); Memory.WriteByte(0xFF1A, 0x7F); Memory.WriteByte(0xFF1B, 0xFF); Memory.WriteByte(0xFF1C, 0x9F); Memory.WriteByte(0xFF1E, 0xBF); Memory.WriteByte(0xFF20, 0xFF); Memory.WriteByte(0xFF21, 0x00); Memory.WriteByte(0xFF22, 0x00); Memory.WriteByte(0xFF23, 0xBF); Memory.WriteByte(0xFF24, 0x77); Memory.WriteByte(0xFF25, 0xF3); Memory.WriteByte(0xFF26, 0xF1); Memory.WriteByte(0xFF40, 0x91); Memory.WriteByte(0xFF42, 0x00); Memory.WriteByte(0xFF43, 0x00); Memory.WriteByte(0xFF45, 0x00); Memory.WriteByte(0xFF47, 0xFC); Memory.WriteByte(0xFF48, 0xFF); Memory.WriteByte(0xFF49, 0xFF); Memory.WriteByte(0xFF4A, 0x00); Memory.WriteByte(0xFF4B, 0x00); Memory.WriteByte(0xFFFF, 0x00); } /// /// Shuts down the GameBoy device. /// public void Terminate() { foreach (var component in Components) component.Shutdown(); IsPoweredOn = false; } } }