NesHawk: Single Tick PPU
Should allow for breaking out into a debugger.
This commit is contained in:
parent
6f021653aa
commit
40ec613982
|
@ -366,7 +366,43 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
VS_coin_inserted &= 1;
|
VS_coin_inserted &= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu.FrameAdvance();
|
FrameGo = true;
|
||||||
|
ppu.ppu_tick_counter = 0;
|
||||||
|
|
||||||
|
if (ppu.ppudead > 0)
|
||||||
|
{
|
||||||
|
while (ppu.ppudead > 0)
|
||||||
|
{
|
||||||
|
ppu.NewDeadPPU();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ppu.ppu_init_frame();
|
||||||
|
|
||||||
|
ppu.do_vbl = true;
|
||||||
|
ppu.do_active_sl = true;
|
||||||
|
ppu.do_pre_vbl = true;
|
||||||
|
|
||||||
|
// do the vbl ticks seperate, that will save us a few checks that don't happen in active region
|
||||||
|
while (ppu.do_vbl)
|
||||||
|
{
|
||||||
|
ppu.TickPPU_VBL();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do the rest of the frame
|
||||||
|
while (ppu.do_active_sl)
|
||||||
|
{
|
||||||
|
ppu.TickPPU_active();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do the pre-NMI lines
|
||||||
|
while (ppu.do_pre_vbl)
|
||||||
|
{
|
||||||
|
ppu.TickPPU_preVBL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lagged)
|
if (lagged)
|
||||||
{
|
{
|
||||||
_lagcount++;
|
_lagcount++;
|
||||||
|
@ -385,6 +421,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
num_cheats = 0;
|
num_cheats = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool FrameGo;
|
||||||
|
|
||||||
//PAL:
|
//PAL:
|
||||||
//0 15 30 45 60 -> 12 27 42 57 -> 9 24 39 54 -> 6 21 36 51 -> 3 18 33 48 -> 0
|
//0 15 30 45 60 -> 12 27 42 57 -> 9 24 39 54 -> 6 21 36 51 -> 3 18 33 48 -> 0
|
||||||
//sequence of ppu clocks per cpu clock: 3,3,3,3,4
|
//sequence of ppu clocks per cpu clock: 3,3,3,3,4
|
||||||
|
|
|
@ -194,7 +194,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
}
|
}
|
||||||
|
|
||||||
//state
|
//state
|
||||||
int ppudead; //measured in frames
|
public int ppudead; //measured in frames
|
||||||
bool idleSynch;
|
bool idleSynch;
|
||||||
int NMI_PendingInstructions;
|
int NMI_PendingInstructions;
|
||||||
byte PPUGenLatch;
|
byte PPUGenLatch;
|
||||||
|
@ -253,6 +253,51 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
ser.Sync("xbuf", ref xbuf, false);
|
ser.Sync("xbuf", ref xbuf, false);
|
||||||
|
|
||||||
ser.Sync("_totalCycles", ref _totalCycles);
|
ser.Sync("_totalCycles", ref _totalCycles);
|
||||||
|
|
||||||
|
ser.Sync("do_vbl", ref do_vbl);
|
||||||
|
ser.Sync("do_active_sl", ref do_active_sl);
|
||||||
|
ser.Sync("do_pre_vbl", ref do_pre_vbl);
|
||||||
|
ser.Sync("ppu_tick_counter", ref ppu_tick_counter);
|
||||||
|
|
||||||
|
ser.Sync("scanline_counter", ref scanline_counter);
|
||||||
|
ser.Sync("nmi_destiny", ref nmi_destiny);
|
||||||
|
ser.Sync("yp_shift", ref yp_shift);
|
||||||
|
ser.Sync("sprite_eval_cycle", ref sprite_eval_cycle);
|
||||||
|
ser.Sync("xt", ref xt);
|
||||||
|
ser.Sync("xp", ref xp);
|
||||||
|
ser.Sync("xstart", ref xstart);
|
||||||
|
ser.Sync("rasterpos", ref rasterpos);
|
||||||
|
ser.Sync("renderspritenow", ref renderspritenow);
|
||||||
|
ser.Sync("renderbgnow", ref renderbgnow);
|
||||||
|
ser.Sync("hit_pending", ref hit_pending);
|
||||||
|
ser.Sync("s", ref s);
|
||||||
|
ser.Sync("ppu_aux_index", ref ppu_aux_index);
|
||||||
|
ser.Sync("junksprite", ref junksprite);
|
||||||
|
ser.Sync("line", ref line);
|
||||||
|
ser.Sync("patternNumber", ref patternNumber);
|
||||||
|
ser.Sync("patternAddress", ref patternAddress);
|
||||||
|
ser.Sync("temp_addr", ref temp_addr);
|
||||||
|
ser.Sync("sl_sprites", ref sl_sprites, false);
|
||||||
|
|
||||||
|
byte bg_byte;
|
||||||
|
for (int i = 0; i < 34; i++)
|
||||||
|
{
|
||||||
|
bg_byte = bgdata[i].at; ser.Sync("bgdata", ref bg_byte); bgdata[i].at = bg_byte;
|
||||||
|
bg_byte = bgdata[i].nt; ser.Sync("bgdata", ref bg_byte); bgdata[i].nt = bg_byte;
|
||||||
|
bg_byte = bgdata[i].pt_0; ser.Sync("bgdata", ref bg_byte); bgdata[i].pt_0 = bg_byte;
|
||||||
|
bg_byte = bgdata[i].pt_1; ser.Sync("bgdata", ref bg_byte); bgdata[i].pt_1 = bg_byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte oam_byte;
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
oam_byte = t_oam[i].oam_y; ser.Sync("bgdata", ref oam_byte); t_oam[i].oam_y = oam_byte;
|
||||||
|
oam_byte = t_oam[i].oam_ind; ; ser.Sync("bgdata", ref oam_byte); t_oam[i].oam_ind = oam_byte;
|
||||||
|
oam_byte = t_oam[i].oam_attr; ser.Sync("bgdata", ref oam_byte); t_oam[i].oam_attr = oam_byte;
|
||||||
|
oam_byte = t_oam[i].oam_x; ser.Sync("bgdata", ref oam_byte); t_oam[i].oam_x = oam_byte;
|
||||||
|
oam_byte = t_oam[i].patterns_0; ser.Sync("bgdata", ref oam_byte); t_oam[i].patterns_0 = oam_byte;
|
||||||
|
oam_byte = t_oam[i].patterns_1; ser.Sync("bgdata", ref oam_byte); t_oam[i].patterns_1 = oam_byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
|
@ -264,93 +309,91 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
ppu_open_bus_decay_timer = new int[8];
|
ppu_open_bus_decay_timer = new int[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
void runppu(int x)
|
void runppu()
|
||||||
{
|
{
|
||||||
//run one ppu cycle at a time so we can interact with the ppu and clockPPU at high granularity
|
//run one ppu cycle at a time so we can interact with the ppu and clockPPU at high granularity
|
||||||
for (int i = 0; i < x; i++)
|
|
||||||
|
race_2006 = false;
|
||||||
|
if (install_2006>0)
|
||||||
{
|
{
|
||||||
race_2006 = false;
|
install_2006--;
|
||||||
if (install_2006>0)
|
if (install_2006==0)
|
||||||
{
|
{
|
||||||
install_2006--;
|
ppur.install_latches();
|
||||||
if (install_2006==0)
|
|
||||||
{
|
|
||||||
ppur.install_latches();
|
|
||||||
|
|
||||||
//nes.LogLine("addr wrote vt = {0}, ht = {1}", ppur._vt, ppur._ht);
|
//nes.LogLine("addr wrote vt = {0}, ht = {1}", ppur._vt, ppur._ht);
|
||||||
//normally the address isnt observed by the board till it gets clocked by a read or write.
|
//normally the address isnt observed by the board till it gets clocked by a read or write.
|
||||||
//but maybe thats just because a ppu read/write shoves it on the address bus
|
//but maybe thats just because a ppu read/write shoves it on the address bus
|
||||||
//apparently this shoves it on the address bus, too, or else blargg's mmc3 tests dont pass
|
//apparently this shoves it on the address bus, too, or else blargg's mmc3 tests dont pass
|
||||||
//ONLY if the ppu is not rendering
|
//ONLY if the ppu is not rendering
|
||||||
if (ppur.status.sl == 241 || !PPUON)
|
if (ppur.status.sl == 241 || !PPUON)
|
||||||
nes.Board.AddressPPU(ppur.get_2007access());
|
nes.Board.AddressPPU(ppur.get_2007access());
|
||||||
|
|
||||||
race_2006 = true;
|
race_2006 = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (install_2001 > 0)
|
|
||||||
{
|
|
||||||
install_2001--;
|
|
||||||
if (install_2001 == 0)
|
|
||||||
{
|
|
||||||
show_bg_new = reg_2001.show_bg;
|
|
||||||
show_obj_new = reg_2001.show_obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ppur.status.cycle++;
|
|
||||||
is_even_cycle = !is_even_cycle;
|
|
||||||
|
|
||||||
if (PPUON && ppur.status.cycle >= 257 && ppur.status.cycle <= 320 && 0 <= ppur.status.sl && ppur.status.sl <= 240)
|
|
||||||
{
|
|
||||||
reg_2003 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here we execute a CPU instruction if enough PPU cycles have passed
|
|
||||||
// also do other things that happen at instruction level granularity
|
|
||||||
cpu_stepcounter++;
|
|
||||||
if (cpu_stepcounter == nes.cpu_sequence[cpu_step])
|
|
||||||
{
|
|
||||||
cpu_step++;
|
|
||||||
if (cpu_step == 5) cpu_step = 0;
|
|
||||||
cpu_stepcounter = 0;
|
|
||||||
|
|
||||||
// this is where the CPU instruction is called
|
|
||||||
nes.RunCpuOne();
|
|
||||||
|
|
||||||
// decay the ppu bus, approximating real behaviour
|
|
||||||
PpuOpenBusDecay(DecayType.None);
|
|
||||||
|
|
||||||
// Check for NMIs
|
|
||||||
if (NMI_PendingInstructions > 0)
|
|
||||||
{
|
|
||||||
NMI_PendingInstructions--;
|
|
||||||
if (NMI_PendingInstructions <= 0)
|
|
||||||
{
|
|
||||||
nes.cpu.NMI = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Reg2002_vblank_active_pending)
|
|
||||||
{
|
|
||||||
Reg2002_vblank_active = 1;
|
|
||||||
Reg2002_vblank_active_pending = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Reg2002_vblank_clear_pending)
|
|
||||||
{
|
|
||||||
Reg2002_vblank_active = 0;
|
|
||||||
Reg2002_vblank_clear_pending = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasClockPPU)
|
|
||||||
{
|
|
||||||
nes.Board.ClockPPU();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_totalCycles += x;
|
|
||||||
}
|
if (install_2001 > 0)
|
||||||
|
{
|
||||||
|
install_2001--;
|
||||||
|
if (install_2001 == 0)
|
||||||
|
{
|
||||||
|
show_bg_new = reg_2001.show_bg;
|
||||||
|
show_obj_new = reg_2001.show_obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ppur.status.cycle++;
|
||||||
|
is_even_cycle = !is_even_cycle;
|
||||||
|
|
||||||
|
if (PPUON && ppur.status.cycle >= 257 && ppur.status.cycle <= 320 && 0 <= ppur.status.sl && ppur.status.sl <= 240)
|
||||||
|
{
|
||||||
|
reg_2003 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we execute a CPU instruction if enough PPU cycles have passed
|
||||||
|
// also do other things that happen at instruction level granularity
|
||||||
|
cpu_stepcounter++;
|
||||||
|
if (cpu_stepcounter == nes.cpu_sequence[cpu_step])
|
||||||
|
{
|
||||||
|
cpu_step++;
|
||||||
|
if (cpu_step == 5) cpu_step = 0;
|
||||||
|
cpu_stepcounter = 0;
|
||||||
|
|
||||||
|
// this is where the CPU instruction is called
|
||||||
|
nes.RunCpuOne();
|
||||||
|
|
||||||
|
// decay the ppu bus, approximating real behaviour
|
||||||
|
PpuOpenBusDecay(DecayType.None);
|
||||||
|
|
||||||
|
// Check for NMIs
|
||||||
|
if (NMI_PendingInstructions > 0)
|
||||||
|
{
|
||||||
|
NMI_PendingInstructions--;
|
||||||
|
if (NMI_PendingInstructions <= 0)
|
||||||
|
{
|
||||||
|
nes.cpu.NMI = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reg2002_vblank_active_pending)
|
||||||
|
{
|
||||||
|
Reg2002_vblank_active = 1;
|
||||||
|
Reg2002_vblank_active_pending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reg2002_vblank_clear_pending)
|
||||||
|
{
|
||||||
|
Reg2002_vblank_active = 0;
|
||||||
|
Reg2002_vblank_clear_pending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasClockPPU)
|
||||||
|
{
|
||||||
|
nes.Board.ClockPPU();
|
||||||
|
}
|
||||||
|
_totalCycles += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue