diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs index 801dc4d726..d03264872f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs @@ -652,17 +652,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } } // class TriangleUnit - private sealed class DMCUnit + public sealed class DMCUnit { private readonly APU apu; + private readonly NES nes; private readonly int[] DMC_RATE; public DMCUnit(APU apu, bool pal) { this.apu = apu; + this.nes = apu.nes; out_silence = true; DMC_RATE = pal ? DMC_RATE_PAL : DMC_RATE_NTSC; timer_reload = DMC_RATE[0]; - timer = 1021; // confirmed in VisualNES although aligning controller read glitches still doesn't work + timer = 1020; // confirmed in VisualNES although aligning controller read glitches still doesn't work sample_buffer_filled = false; out_deltacounter = 64; out_bits_remaining = 7; //confirmed in VisualNES @@ -732,7 +734,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES if (!apu.call_from_write) { // when called due to empty bueffer while DMC running, there is no delay - delay = 1; + delay = 0; + nes.cpu.RDY = false; + nes.dmc_dma_exec = true; + apu.dmc_dma_countdown = 3; // 3 here but this actually stops 4 cpu cycles because it starts before the cpu is run + apu.DMC_RDY_check = 2; } else { @@ -763,7 +769,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } else { - apu.dmc_dma_countdown = 3; apu.DMC_RDY_check = 2; apu.call_from_write = false; @@ -945,7 +950,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public PulseUnit[] pulse = new PulseUnit[2]; public TriangleUnit triangle; public NoiseUnit noise; - private readonly DMCUnit dmc; + public readonly DMCUnit dmc; private bool irq_pending; private bool dmc_irq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs index 53bcff66ce..c657f0e41d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs @@ -282,6 +282,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private bool resetSignal; private bool hardResetSignal; + public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; @@ -454,7 +455,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { if (cpu_deadcounter == 0) { - if (oam_dma_index % 2 == 0) { oam_dma_byte = ReadMemory(oam_dma_addr); @@ -465,8 +465,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES WriteMemory(0x2004, oam_dma_byte); } oam_dma_index++; - if (oam_dma_index == 512) oam_dma_exec = false; - + if (oam_dma_index == 512) + { + oam_dma_exec = false; + } } else { @@ -495,7 +497,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES // By this point the cpu should be frozen, if it is not, then we are in a multi-write opcode, add another cycle delay if (!cpu.RDY && !cpu.rdy_freeze && (apu.dmc_dma_countdown == apu.DMC_RDY_check)) { - //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + apu.call_from_write + " " + cpu.opcode + " " + oam_dma_exec); + //Console.WriteLine("dmc double " + cpu.TotalExecutedCycles + " " + cpu.opcode + " " + cpu.mi); apu.dmc_dma_countdown += 2; apu.DMC_RDY_check = -1; } @@ -509,9 +511,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES dmc_dma_exec = false; apu.dmc_dma_countdown = -1; do_the_reread = true; - } - - //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + apu.call_from_write + " " + cpu.opcode); + + //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + (apu.dmc.timer & 1)); + } + //Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + cpu.opcode + " " + cpu.mi + " " + apu.dmc_dma_countdown); } ///////////////////////////// @@ -598,14 +601,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { // special hardware glitch case ret_spec = read_joyport(addr); + if (do_the_reread && ppu.region==PPU.Region.NTSC) { ret_spec = read_joyport(addr); - do_the_reread = false; - Console.WriteLine("DMC glitch player 1"); + do_the_reread = false; + Console.WriteLine("DMC glitch player 1 "); } - return ret_spec; + return ret_spec; } case 0x4017: if (_isVS) @@ -617,7 +621,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ret = (byte)(ret | (VS_dips[2] << 2) | (VS_dips[3] << 3) | (VS_dips[4] << 4) | (VS_dips[5] << 5) | (VS_dips[6] << 6) | (VS_dips[7] << 7)); return ret; - } else { @@ -714,7 +717,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES sprdma_countdown--; if (sprdma_countdown == 0) { - if (cpu.TotalExecutedCycles % 2 == 0) + if (apu.dmc.timer % 2 == 0) { cpu_deadcounter = 2; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs index ea5102cb26..b0489acbff 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs @@ -288,8 +288,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private Bit Reg2002_objoverflow; //Sprite overflow. The PPU can handle only eight sprites on one scanline and sets this bit if it starts drawing sprites. private Bit Reg2002_objhit; //Sprite 0 overlap. Set when a nonzero pixel of sprite 0 is drawn overlapping a nonzero background pixel. Used for raster timing. - private Bit Reg2002_vblank_active; //Vertical blank start (0: has not started; 1: has started) - private bool Reg2002_vblank_active_pending; //set if Reg2002_vblank_active is pending + public Bit Reg2002_vblank_active; //Vertical blank start (0: has not started; 1: has started) + public bool Reg2002_vblank_active_pending; //set if Reg2002_vblank_active is pending private bool Reg2002_vblank_clear_pending; //ppu's clear of vblank flag is pending public PPUREGS ppur; public Reg_2000 reg_2000; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs index 606f014f6c..e80233da8c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs @@ -133,7 +133,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private bool nmi_destiny; private bool evenOddDestiny; - private int start_up_offset; + public int start_up_offset; private int NMI_offset; private int yp_shift; private int sprite_eval_cycle; @@ -532,7 +532,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { if (ppu_was_on_spr && !PPUON) { - Console.WriteLine("oam addr glitch " + ppur.status.sl + " " + ppur.status.cycle); + //Console.WriteLine("oam addr glitch " + ppur.status.sl + " " + ppur.status.cycle); reg_2003++; } }