diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs
index d03264872f..3e00eec2cb 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs
@@ -660,7 +660,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 			public DMCUnit(APU apu, bool pal)
 			{
 				this.apu = apu;
-				this.nes = apu.nes;
+				nes = apu.nes;
 				out_silence = true;
 				DMC_RATE = pal ? DMC_RATE_PAL : DMC_RATE_NTSC;
 				timer_reload = DMC_RATE[0];
@@ -668,26 +668,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 				sample_buffer_filled = false;
 				out_deltacounter = 64;
 				out_bits_remaining = 7; //confirmed in VisualNES
-				user_address = 0x8000; // even though this can't be accessed by writing, it is indeed the power up address
+				user_address = 0xC000; // even though this can't be accessed by writing, it is indeed the power up address
+				sample_address = 0xC000;
 				user_length = 1;
 			}
 
 			private bool irq_enabled;
 			private bool loop_flag;
-			private int timer_reload;
+			public int timer_reload;
 
 			// dmc delay per visual 2a03
-			private int delay;
+			public int delay;
 
 			// this timer never stops, ever, so it is convenient to use for even/odd timing used elsewhere
 			public int timer;
 			private int user_address;
 			public uint user_length, sample_length;
-			private int sample_address, sample_buffer;
+			public int sample_address, sample_buffer;
 			private bool sample_buffer_filled;
 
-			private int out_shift, out_bits_remaining, out_deltacounter;
+			public int out_shift, out_bits_remaining, out_deltacounter;
 			private bool out_silence;
+			public bool fill_glitch;
 
 			public int sample => out_deltacounter /* - 64*/;
 
@@ -711,6 +713,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 				ser.Sync(nameof(out_bits_remaining), ref out_bits_remaining);
 				ser.Sync(nameof(out_deltacounter), ref out_deltacounter);
 				ser.Sync(nameof(out_silence), ref out_silence);
+				ser.Sync(nameof(fill_glitch), ref fill_glitch);
 
 				ser.Sync(nameof(delay), ref delay);
 
@@ -729,15 +732,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 
 				// Any time the sample buffer is in an empty state and bytes remaining is not zero, the following occur: 
 				// also note that the halt for DMC DMA occurs on APU cycles only (hence the timer check)
-				if (!sample_buffer_filled && sample_length > 0  && apu.dmc_dma_countdown == -1 && delay==0)
+				if (!sample_buffer_filled && sample_length > 0 && apu.dmc_dma_countdown == -1 && delay==0)
 				{
 					if (!apu.call_from_write)
 					{
 						// when called due to empty bueffer while DMC running, there is no delay
-						delay = 0;
+						//delay = 1;
 						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_dma_countdown = 3;
 						apu.DMC_RDY_check = 2;
 					}
 					else
@@ -750,7 +753,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 						else
 						{
 							delay = 3;
-						}
+						}					
 					}
 				}
 
@@ -762,7 +765,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 					delay--;
 					if (delay == 0)
 					{
-						if (!apu.call_from_write)
+						if (fill_glitch)
+						{
+							//fill_glitch = false;
+							apu.dmc_dma_countdown = 1;
+							apu.DMC_RDY_check = -1;
+						}
+						else if (!apu.call_from_write)
 						{
 							apu.dmc_dma_countdown = 4;
 							apu.DMC_RDY_check = 2;
@@ -825,11 +834,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 
 			public void set_lenctr_en(bool en)
 			{
-				if (!en)
+				// should this be delayed by two/three cycles?
+
+				if(!en)
 				{
 					// If the DMC bit is clear, the DMC bytes remaining will be set to 0 
 					// and the DMC will silence when it empties.
-					sample_length = 0;
+					sample_length = 0;					
 				}
 				else
 				{
@@ -892,6 +903,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 					sample_buffer = apu.nes.ReadMemory((ushort)sample_address);
 					sample_buffer_filled = true;
 					sample_address = (ushort)(sample_address + 1);
+
+					//sample address wraps to 0xC000
+					if (sample_address == 0) { sample_address = 0xC000;}
 					// Console.WriteLine(sample_length);
 					// Console.WriteLine(user_length);
 					sample_length--;
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 c657f0e41d..769503c9d7 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs
@@ -442,7 +442,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 		public bool dmc_realign;
 		public bool IRQ_delay;
 		public bool special_case_delay; // very ugly but the only option
-		public bool do_the_reread;
+		public bool reread_trigger;
+		public int do_the_reread_2002, do_the_reread_2007, do_the_reread_cont_1, do_the_reread_cont_2;
 		public byte DB; //old data bus values from previous reads
 
 		internal void RunCpuOne()
@@ -489,7 +490,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 
 			if (apu.dmc_dma_countdown > 0)
 			{
-				if (apu.dmc_dma_countdown == 1)
+				if (apu.dmc_dma_countdown == 1 && !apu.dmc.fill_glitch)
 				{
 					dmc_realign = true;
 				}
@@ -507,14 +508,47 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 				apu.dmc_dma_countdown--;
 				if (apu.dmc_dma_countdown == 0)
 				{
-					apu.RunDMCFetch();
+					if (!apu.dmc.fill_glitch)
+					{
+						reread_trigger = true;
+						// if the DMA address has the same bits set as the re-read address, they don't occur
+						if ((apu.dmc.sample_address & 0x2007) != 0x2002)
+						{
+							do_the_reread_2002++;
+						}
+
+						if ((apu.dmc.sample_address & 0x2007) != 0x2007)
+						{
+							do_the_reread_2007++;
+						}
+
+						if ((apu.dmc.sample_address & 0x401F) != 0x4016)
+						{
+							do_the_reread_cont_1++;
+						}
+
+						if ((apu.dmc.sample_address & 0x401F) != 0x4017)
+						{
+							do_the_reread_cont_2++;
+						}
+				
+						apu.RunDMCFetch();
+					}
+
 					dmc_dma_exec = false;
 					apu.dmc_dma_countdown = -1;
-					do_the_reread = true;
-					
-					//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);
+					apu.dmc.fill_glitch = false;
+					/*
+					//if (apu.dmc.timer == (apu.dmc.timer_reload-0) && apu.dmc.out_bits_remaining == 7)							
+					//if (apu.dmc.timer == 2 && apu.dmc.out_bits_remaining == 0)
+					{
+						Console.WriteLine("close " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length);
+						apu.dmc.fill_glitch = true;
+						apu.dmc.delay = 3;
+					}
+					*/
+					//Console.WriteLine("dmc RDY false " + cpu.TotalExecutedCycles + " " + cpu.opcode + " " + cpu.mi + " " + apu.dmc.timer);
+				}				
 			}
 
 			/////////////////////////////
@@ -528,7 +562,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 			}
 			else if (special_case_delay || apu.dmc_dma_countdown == 3)
 			{
+				
 				cpu.IRQ = _irq_apu || Board.IrqSignal;
+				//if (cpu.IRQ) { Console.WriteLine("something IRQ"); }
 				special_case_delay = false;
 			}
 
@@ -546,8 +582,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 
 			apu.RunOneLast();
 
-			if (do_the_reread && cpu.RDY)
-				do_the_reread = false;
+			if (reread_trigger && cpu.RDY)
+			{
+				do_the_reread_2002 = 0;
+				do_the_reread_2007 = 0;
+				do_the_reread_cont_1 = 0;
+				do_the_reread_cont_2 = 0;
+				reread_trigger = false;
+			}
+				
 
 			IRQ_delay = false;
 
@@ -602,11 +645,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 						// special hardware glitch case
 						ret_spec = read_joyport(addr);
 
-						if (do_the_reread && ppu.region==PPU.Region.NTSC)
+						//if (reread_trigger && (do_the_reread_cont_1 == 0)) { Console.WriteLine("same 1 " + (apu.dmc.sample_address - 1)); }
+
+						if ((do_the_reread_cont_1 > 0) && ppu.region==PPU.Region.NTSC)
 						{
 							ret_spec = read_joyport(addr);
-							do_the_reread = false;	
-							Console.WriteLine("DMC glitch player 1 ");
+							do_the_reread_cont_1--;
+							if (do_the_reread_cont_1 > 0) { ret_spec = read_joyport(addr); }
+							//Console.WriteLine("DMC glitch player 1 " + cpu.TotalExecutedCycles + " addr " + (apu.dmc.sample_address - 1));
 						}
 
 						return ret_spec;
@@ -626,12 +672,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 					{
 						// special hardware glitch case
 						ret_spec = read_joyport(addr);
-						if (do_the_reread && ppu.region == PPU.Region.NTSC)
+
+						//if (reread_trigger && (do_the_reread_cont_2 == 0)) { Console.WriteLine("same 2 " + (apu.dmc.sample_address - 1)); }
+
+						if ((do_the_reread_cont_2 > 0) && ppu.region == PPU.Region.NTSC)
 						{
 							ret_spec = read_joyport(addr);
-							do_the_reread = false;
-							Console.WriteLine("DMC glitch player 2");
+							do_the_reread_cont_2--;
+							if (do_the_reread_cont_2 > 0) { ret_spec = read_joyport(addr); }
+							//Console.WriteLine("DMC glitch player 2 " + cpu.TotalExecutedCycles + " addr " + (apu.dmc.sample_address - 1));
 						}
+
 						return ret_spec;
 					}
 				default:
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs
index f3c0d2f973..ff198a874c 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs
@@ -31,7 +31,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 			ser.Sync(nameof(dmc_realign), ref dmc_realign);
 			ser.Sync(nameof(IRQ_delay), ref IRQ_delay);
 			ser.Sync(nameof(special_case_delay), ref special_case_delay);
-			ser.Sync(nameof(do_the_reread), ref do_the_reread);
+			ser.Sync(nameof(reread_trigger), ref reread_trigger);
+			ser.Sync(nameof(do_the_reread_2002), ref do_the_reread_2002);
+			ser.Sync(nameof(do_the_reread_2007), ref do_the_reread_2007);
+			ser.Sync(nameof(do_the_reread_cont_1), ref do_the_reread_cont_1);
+			ser.Sync(nameof(do_the_reread_cont_2), ref do_the_reread_cont_2);
 
 			// VS related
 			ser.Sync("VS", ref _isVS);
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 b0489acbff..27be45d8ce 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs
@@ -345,12 +345,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 		private byte read_2002()
 		{
 			byte ret = peek_2002();
-
+			
+			if (nes.do_the_reread_2002 > 0)
+			{
+				if (Reg2002_vblank_active || Reg2002_vblank_active_pending)
+					Console.WriteLine("reread 2002");
+			}
+			
 			// reading from $2002 resets the destination for $2005 and $2006 writes
 			vtoggle = false;
 			Reg2002_vblank_active = 0;
 			Reg2002_vblank_active_pending = false;
 
+			if (nes.do_the_reread_2002 > 0)
+			{
+				ret = peek_2002();
+				// could be another reread, but no other side effects, so don't bother
+			}
+
 			// update the open bus here
 			ppu_open_bus = ret;
 			PpuOpenBusDecay(DecayType.High);
@@ -679,11 +691,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
 							double_2007_read = nes.cpu.TotalExecutedCycles + 1;
 						}
 						
-						if (nes.do_the_reread)
+						if (nes.do_the_reread_2007 > 0)
 						{
 							ret_spec = read_2007();
 							ret_spec = read_2007();
-							nes.do_the_reread = false;
+							// always 2?
 						}
 						return ret_spec;
 					}