Exemplo n.º 1
0
 public DMCUnit(APU apu, bool pal)
 {
     this.apu             = apu;
     out_silence          = true;
     DMC_RATE             = pal ? DMC_RATE_PAL : DMC_RATE_NTSC;
     timer_reload         = DMC_RATE[0];
     sample_buffer_filled = false;
     out_deltacounter     = 64;
     out_bits_remaining   = 0;
 }
Exemplo n.º 2
0
			public DMCUnit(APU apu, bool pal)
			{
				this.apu = apu;
				out_silence = true;
				DMC_RATE = pal ? DMC_RATE_PAL : DMC_RATE_NTSC;
				timer_reload = DMC_RATE[0];
				timer = timer_reload;
				sample_buffer_filled = false;
				out_deltacounter = 64;
				out_bits_remaining = 0;
				user_address = 0x8000; // even though this can't be accessed by writing, it is indeed the power up address
				user_length = 1;
			}
Exemplo n.º 3
0
		public APU(NES nes, APU old, bool pal)
		{
			this.nes = nes;
			dmc = new DMCUnit(this, pal);
			sequencer_lut = pal ? sequencer_lut_pal : sequencer_lut_ntsc;
			
			noise = new NoiseUnit(this, pal);
			triangle = new TriangleUnit(this);
			pulse[0] = new PulseUnit(this, 1);
			pulse[1] = new PulseUnit(this, 0);
			if (old != null)
			{
				m_vol = old.m_vol;
			}
		}
Exemplo n.º 4
0
 public APU(NES nes, APU old, bool pal)
 {
     this.nes = nes;
     dmc      = new DMCUnit(this, pal);
     noise    = new NoiseUnit(this, pal);
     triangle = new TriangleUnit(this);
     pulse[0] = new PulseUnit(this, 0);
     pulse[1] = new PulseUnit(this, 1);
     if (old != null)
     {
         Square1V  = old.Square1V;
         Square2V  = old.Square2V;
         TriangleV = old.TriangleV;
         NoiseV    = old.NoiseV;
         DMCV      = old.DMCV;
     }
 }
Exemplo n.º 5
0
		public APU(NES nes, APU old, bool pal)
		{
			this.nes = nes;
			dmc = new DMCUnit(this, pal);
			noise = new NoiseUnit(this, pal);
			triangle = new TriangleUnit(this);
			pulse[0] = new PulseUnit(this, 0);
			pulse[1] = new PulseUnit(this, 1);
			if (old != null)
			{
				Square1V = old.Square1V;
				Square2V = old.Square2V;
				TriangleV = old.TriangleV;
				NoiseV = old.NoiseV;
				DMCV = old.DMCV;
			}
		}
Exemplo n.º 6
0
 public TriangleUnit(APU apu)
 {
     this.apu = apu;
 }
Exemplo n.º 7
0
 public NoiseUnit(APU apu, bool pal)
 {
     this.apu    = apu;
     NOISE_TABLE = pal ? NOISE_TABLE_PAL : NOISE_TABLE_NTSC;
 }
Exemplo n.º 8
0
        public void HardReset()
        {
            cpu = new MOS6502X();
            cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);

            cpu.BCD_Enabled = false;
            cpu.OnExecFetch = ExecFetch;
            ppu             = new PPU(this);
            ram             = new byte[0x800];
            CIRAM           = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS)
                {
                    var b = Board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu               = new APU(this, apu, true);
                ppu.region        = PPU.Region.PAL;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1662607;
                cpu_sequence      = cpu_sequence_PAL;
                _display_type     = DisplayType.PAL;
                break;

            case Common.DisplayType.NTSC:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.NTSC;
                CoreComm.VsyncNum = 39375000;
                CoreComm.VsyncDen = 655171;
                cpuclockrate      = 1789773;
                cpu_sequence      = cpu_sequence_NTSC;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.DENDY:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.Dendy;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1773448;
                cpu_sequence      = cpu_sequence_NTSC;
                _display_type     = DisplayType.DENDY;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }
            if (magicSoundProvider == null)
            {
                magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);
            }

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();


            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.DB_GameInfo != null)
            {
                if (cart.DB_GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" ||              // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" ||                     // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23"                        // Camerica Pegasus 4-in-1
                    )
                {
                    ram[0x701] = 0xFF;
                }
            }
        }
Exemplo n.º 9
0
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS)
                {
                    var b = Board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // Add in the reset timing float control for subneshawk
            if (using_reset_timing && (ControllerDefinition.FloatControls.Count() == 0))
            {
                ControllerDefinition.FloatControls.Add("Reset Cycle");
                ControllerDefinition.FloatRanges.Add(new ControllerDefinition.FloatRange(0, 0, 500000));
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                VsyncNum      = 50;
                VsyncDen      = 1;
                cpuclockrate  = 1662607;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case Common.DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                VsyncNum     = 39375000;
                VsyncDen     = 655171;
                cpuclockrate = 1789773;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                VsyncNum      = 50;
                VsyncDen      = 1;
                cpuclockrate  = 1773448;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.DB_GameInfo != null)
            {
                if (cart.DB_GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" ||              // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" ||                     // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23"                        // Camerica Pegasus 4-in-1
                    )
                {
                    ram[0x701] = 0xFF;
                }

                if (cart.DB_GameInfo.Hash == "68ABE1E49C9E9CCEA978A48232432C252E5912C0")                 // Dancing Blocks
                {
                    ram[0xEC] = 0;
                    ram[0xED] = 0;
                }

                if (cart.DB_GameInfo.Hash == "00C50062A2DECE99580063777590F26A253AAB6B")                 // Silva Saga
                {
                    for (int i = 0; i < Board.WRAM.Length; i++)
                    {
                        Board.WRAM[i] = 0xFF;
                    }
                }
            }
        }
Exemplo n.º 10
0
			public PulseUnit(APU apu, int unit) { this.unit = unit; this.apu = apu; }
Exemplo n.º 11
0
			public DMCUnit(APU apu, bool pal)
			{
				this.apu = apu;
				out_silence = true;
				DMC_RATE = pal ? DMC_RATE_PAL : DMC_RATE_NTSC;
				timer_reload = DMC_RATE[0];
				sample_buffer_filled = false;
				out_deltacounter = 64;
				out_bits_remaining = 0;
			}
Exemplo n.º 12
0
			public TriangleUnit(APU apu) { this.apu = apu; }
Exemplo n.º 13
0
			public NoiseUnit(APU apu, bool pal)
			{
				this.apu = apu;
				NOISE_TABLE = pal ? NOISE_TABLE_PAL : NOISE_TABLE_NTSC;
			}
Exemplo n.º 14
0
        public void HardReset()
        {
            cpu = new MOS6502X();
            cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);

            cpu.BCD_Enabled = false;
            cpu.OnExecFetch = ExecFetch;
            ppu             = new PPU(this);
            ram             = new byte[0x800];
            CIRAM           = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (board is FDS)
                {
                    var b = board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu               = new APU(this, apu, true);
                ppu.region        = PPU.Region.PAL;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1662607;
                cpu_sequence      = cpu_sequence_PAL;
                _display_type     = DisplayType.PAL;
                break;

            case Common.DisplayType.NTSC:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.NTSC;
                CoreComm.VsyncNum = 39375000;
                CoreComm.VsyncDen = 655171;
                cpuclockrate      = 1789773;
                cpu_sequence      = cpu_sequence_NTSC;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.DENDY:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.Dendy;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1773448;
                cpu_sequence      = cpu_sequence_NTSC;
                _display_type     = DisplayType.DENDY;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }
            if (magicSoundProvider == null)
            {
                magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);
            }

            BoardSystemHardReset();

            //check fceux's PowerNES and FCEU_MemoryRand function for more information:
            //relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
            for (int i = 0; i < 0x800; i++)
            {
                if ((i & 4) != 0)
                {
                    ram[i] = 0xFF;
                }
                else
                {
                    ram[i] = 0x00;
                }
            }

            SetupMemoryDomains();

            //in this emulator, reset takes place instantaneously
            cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
            cpu.P  = 0x34;
            cpu.S  = 0xFD;
        }
Exemplo n.º 15
0
 public PulseUnit(APU apu, int unit)
 {
     this.unit = unit; this.apu = apu;
 }
Exemplo n.º 16
0
		public void HardReset()
		{
			cpu = new MOS6502X();
			cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);

			cpu.BCD_Enabled = false;
			cpu.OnExecFetch = ExecFetch;
			ppu = new PPU(this);
			ram = new byte[0x800];
			CIRAM = new byte[0x800];
			
			// wire controllers
			// todo: allow changing this
			ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
			// set controller definition first time only
			if (ControllerDefinition == null)
			{
				ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition());
				ControllerDefinition.Name = "NES Controller";
				// controls other than the deck
				ControllerDefinition.BoolButtons.Add("Power");
				ControllerDefinition.BoolButtons.Add("Reset");
				if (Board is FDS)
				{
					var b = Board as FDS;
					ControllerDefinition.BoolButtons.Add("FDS Eject");
					for (int i = 0; i < b.NumSides; i++)
						ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
				}
			}

			// don't replace the magicSoundProvider on reset, as it's not needed
			// if (magicSoundProvider != null) magicSoundProvider.Dispose();

			// set up region
			switch (_display_type)
			{
				case Common.DisplayType.PAL:
					apu = new APU(this, apu, true);
					ppu.region = PPU.Region.PAL;
					CoreComm.VsyncNum = 50;
					CoreComm.VsyncDen = 1;
					cpuclockrate = 1662607;
					cpu_sequence = cpu_sequence_PAL;
					_display_type = DisplayType.PAL;
					break;
				case Common.DisplayType.NTSC:
					apu = new APU(this, apu, false);
					ppu.region = PPU.Region.NTSC;
					CoreComm.VsyncNum = 39375000;
					CoreComm.VsyncDen = 655171;
					cpuclockrate = 1789773;
					cpu_sequence = cpu_sequence_NTSC;
					break;
				// this is in bootgod, but not used at all
				case Common.DisplayType.DENDY:
					apu = new APU(this, apu, false);
					ppu.region = PPU.Region.Dendy;
					CoreComm.VsyncNum = 50;
					CoreComm.VsyncDen = 1;
					cpuclockrate = 1773448;
					cpu_sequence = cpu_sequence_NTSC;
					_display_type = DisplayType.DENDY;
					break;
				default:
					throw new Exception("Unknown displaytype!");
			}
			if (magicSoundProvider == null)
				magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);

			BoardSystemHardReset();

			//check fceux's PowerNES and FCEU_MemoryRand function for more information:
			//relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
			for(int i=0;i<0x800;i++) if((i&4)!=0) ram[i] = 0xFF; else ram[i] = 0x00;

			SetupMemoryDomains();

			//in this emulator, reset takes place instantaneously
			cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
			cpu.P = 0x34;
			cpu.S = 0xFD;
		}
Exemplo n.º 17
0
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                cpuclockrate  = 1662607;
                VsyncNum      = cpuclockrate * 2;
                VsyncDen      = 66495;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                cpuclockrate = 1789773;
                VsyncNum     = cpuclockrate * 2;
                VsyncDen     = 59561;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                cpuclockrate  = 1773448;
                VsyncNum      = cpuclockrate;
                VsyncDen      = 35464;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.
            var hash = cart.GameInfo?.Hash;             // SHA1 or MD5 (see NES.IdentifyFromGameDB)

            if (hash is null)
            {
                // short-circuit
            }
            else if (hash is RomChecksums.CamericaGolden5 or RomChecksums.CamericaGolden5Overdump or RomChecksums.CamericaPegasus4in1)
            {
                ram[0x701] = 0xFF;
            }
Exemplo n.º 18
0
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition())
                {
                    Name = "NES Controller"
                };

                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS b)
                {
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // Add in the reset timing axis for subneshawk
            if (using_reset_timing && ControllerDefinition.Axes.Count == 0)
            {
                ControllerDefinition.AddAxis("Reset Cycle", 0.RangeTo(500000), 0);
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                cpuclockrate  = 1662607;
                VsyncNum      = cpuclockrate * 2;
                VsyncDen      = 66495;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                cpuclockrate = 1789773;
                VsyncNum     = cpuclockrate * 2;
                VsyncDen     = 59561;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                cpuclockrate  = 1773448;
                VsyncNum      = cpuclockrate;
                VsyncDen      = 35464;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.GameInfo != null)
            {
                if (cart.GameInfo.Hash is RomChecksums.CamericaGolden5 or RomChecksums.CamericaGolden5Overdump or RomChecksums.CamericaPegasus4in1)
                {
                    ram[0x701] = 0xFF;
                }
                else if (cart.GameInfo.Hash == RomChecksums.DancingBlocks)
                {
                    ram[0xEC] = 0;
                    ram[0xED] = 0;
                }
                else if (cart.GameInfo.Hash == RomChecksums.SilvaSaga)
                {
                    for (int i = 0; i < Board.Wram.Length; i++)
                    {
                        Board.Wram[i] = 0xFF;
                    }
                }
            }