NESHawk: more DMC work

This commit is contained in:
alyosha-tas 2021-12-22 20:31:23 -05:00
parent e37f580a19
commit 2dae3505d7
2 changed files with 67 additions and 34 deletions

View File

@ -664,7 +664,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
out_silence = true;
DMC_RATE = pal ? DMC_RATE_PAL : DMC_RATE_NTSC;
timer_reload = DMC_RATE[0];
timer = 1019; // 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
@ -689,8 +689,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public int out_shift, out_bits_remaining, out_deltacounter;
private bool out_silence;
public bool fill_glitch; // happens when buffer is filled and emptied at the same time
//public bool fill_glitch_2; // happens when a write triggered refill happens too prevent an automatic refill
// happens when buffer is filled and emptied at the same time
public bool fill_glitch;
// happens when a write triggered refill that sets length to zero happens too close to an automatic DMA
// (causes 1-cycle blips in dmc_dma_start_test_v2)
public bool fill_glitch_2;
public int sample => out_deltacounter /* - 64*/;
@ -715,6 +718,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
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(fill_glitch_2), ref fill_glitch_2);
ser.Sync(nameof(delay), ref delay);
@ -733,18 +737,33 @@ 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) || fill_glitch_2) && apu.dmc_dma_countdown == -1 && delay==0)
{
if (!fill_glitch)
{
if (!apu.call_from_write)
{
delay = 1;
// when called due to empty bueffer while DMC running, there is no delay
nes.cpu.RDY = false;
nes.dmc_dma_exec = true;
if (fill_glitch_2)
{
// this will only run for one cycle and not actually run a DMA
Console.WriteLine("fill glitch 2");
apu.dmc_dma_countdown = 4;
apu.DMC_RDY_check = -1;
}
else
{
apu.dmc_dma_countdown = 3;
apu.DMC_RDY_check = 2;
}
}
else
{
// when called from write, either a 2 or 3 cycle delay in activation.
if (timer % 2 == 0)
if (timer % 2 == 1)
{
delay = 2;
}
@ -757,8 +776,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
else
{
// if refill and empty happen simultaneously, do not do another refill and act as though the sample buffer was filled
//Console.WriteLine("fill glitch");
Console.WriteLine("fill glitch");
sample_buffer_filled = true;
fill_glitch = false;
}
}
@ -770,13 +790,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
delay--;
if (delay == 0)
{
/*if (fill_glitch)
{
//fill_glitch = false;
apu.dmc_dma_countdown = 1;
apu.DMC_RDY_check = -1;
}
else */if (!apu.call_from_write)
if (!apu.call_from_write)
{
apu.dmc_dma_countdown = 4;
apu.DMC_RDY_check = 2;
@ -789,8 +803,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
}
}
fill_glitch = false;
}
private void Clock()
@ -845,9 +857,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if(!en)
{
/*
if ((timer <= 3) && (out_bits_remaining == 0) && (sample_length != 0))
{
//Console.WriteLine("glitch 2");
//fill_glitch_2 = true;
}
*/
// 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
{
@ -1151,6 +1171,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if(sequencer_mode == 0) { sequencer_check_2 = sequencer_lut[0][3] - 2; }
else { sequencer_check_2 = sequencer_lut[1][4] - 2; }
dmc.fill_glitch = false;
dmc.fill_glitch_2 = false;
}
public void NESHardReset()
@ -1163,6 +1186,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (sequencer_mode == 0) { sequencer_check_2 = sequencer_lut[0][3] - 2; }
else { sequencer_check_2 = sequencer_lut[1][4] - 2; }
dmc.fill_glitch = false;
dmc.fill_glitch_2 = false;
}
public void WriteReg(int addr, byte val)

View File

@ -528,22 +528,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
do_the_reread_2007++;
}
if ((apu.dmc.sample_address & 0x1F) != 0x16)
if ((apu.dmc.sample_address & 0x401F) != 0x4016)
{
do_the_reread_cont_1++;
}
if ((apu.dmc.sample_address & 0x1F) == 0x16)
if ((apu.dmc.sample_address & 0x401F) == 0x4016)
{
reread_opp_4016++;
}
if ((apu.dmc.sample_address & 0x1F) != 0x17)
if ((apu.dmc.sample_address & 0x401F) != 0x4017)
{
do_the_reread_cont_2++;
}
if ((apu.dmc.sample_address & 0x1F) == 0x17)
if ((apu.dmc.sample_address & 0x401F) == 0x4017)
{
reread_opp_4017++;
}
@ -553,24 +553,31 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
dmc_dma_exec = false;
apu.dmc_dma_countdown = -1;
/*
if (apu.dmc.timer == 3 && apu.dmc.out_bits_remaining == 0)
if ((apu.dmc.timer == 2) && (apu.dmc.out_bits_remaining == 0))
{
Console.WriteLine("close 3 " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length + " " + cpu.opcode + " " + cpu.mi);
Console.WriteLine("close " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length + " " + cpu.opcode + " " + cpu.mi);
if (apu.dmc.sample_length != 0)
{
apu.dmc.fill_glitch = true;
}
}
if (apu.dmc.timer == (apu.dmc.timer_reload-1) && apu.dmc.out_bits_remaining == 7)
/*
if ((apu.dmc.timer == 3) && (apu.dmc.out_bits_remaining == 0) && (apu.dmc.sample_length == 0))
{
Console.WriteLine("close 2 " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length + " " + cpu.opcode + " " + cpu.mi);
//Console.WriteLine("close 2 " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length + " " + cpu.opcode + " " + cpu.mi);
//apu.dmc.fill_glitch_2 = true;
}
*/
if (apu.dmc.timer == 1 && apu.dmc.out_bits_remaining == 0)
{
//Console.WriteLine("close " + cpu.TotalExecutedCycles + " " + apu.dmc.timer + " " + apu.dmc.sample_length + " " + cpu.opcode + " " + cpu.mi);
apu.dmc.fill_glitch = true;
}
}
}
/*
if (apu.dmc.fill_glitch_2 && (apu.dmc_dma_countdown == 3))
{
apu.dmc_dma_countdown = -1;
dmc_dma_exec = false;
apu.dmc.fill_glitch_2 = false;
}
*/
}
/////////////////////////////
@ -804,7 +811,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
sprdma_countdown--;
if (sprdma_countdown == 0)
{
if (apu.dmc.timer % 2 == 1)
if (apu.dmc.timer % 2 == 0)
{
cpu_deadcounter = 2;
}