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; }
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; }
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; } }
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; } }
public TriangleUnit(APU apu) { this.apu = apu; }
public NoiseUnit(APU apu, bool pal) { this.apu = apu; NOISE_TABLE = pal ? NOISE_TABLE_PAL : NOISE_TABLE_NTSC; }
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; } } }
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; } } } }
public PulseUnit(APU apu, int unit) { this.unit = unit; this.apu = apu; }
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; }
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; }
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; }
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; } } }