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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_lagcount++;
|
||||
|
@ -385,6 +421,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
num_cheats = 0;
|
||||
}
|
||||
|
||||
public bool FrameGo;
|
||||
|
||||
//PAL:
|
||||
//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
|
||||
|
|
|
@ -194,7 +194,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
|
||||
//state
|
||||
int ppudead; //measured in frames
|
||||
public int ppudead; //measured in frames
|
||||
bool idleSynch;
|
||||
int NMI_PendingInstructions;
|
||||
byte PPUGenLatch;
|
||||
|
@ -253,6 +253,51 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
ser.Sync("xbuf", ref xbuf, false);
|
||||
|
||||
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()
|
||||
|
@ -264,93 +309,91 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
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
|
||||
for (int i = 0; i < x; i++)
|
||||
|
||||
race_2006 = false;
|
||||
if (install_2006>0)
|
||||
{
|
||||
race_2006 = false;
|
||||
if (install_2006>0)
|
||||
install_2006--;
|
||||
if (install_2006==0)
|
||||
{
|
||||
install_2006--;
|
||||
if (install_2006==0)
|
||||
{
|
||||
ppur.install_latches();
|
||||
ppur.install_latches();
|
||||
|
||||
//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.
|
||||
//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
|
||||
//ONLY if the ppu is not rendering
|
||||
if (ppur.status.sl == 241 || !PPUON)
|
||||
nes.Board.AddressPPU(ppur.get_2007access());
|
||||
//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.
|
||||
//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
|
||||
//ONLY if the ppu is not rendering
|
||||
if (ppur.status.sl == 241 || !PPUON)
|
||||
nes.Board.AddressPPU(ppur.get_2007access());
|
||||
|
||||
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();
|
||||
race_2006 = true;
|
||||
}
|
||||
}
|
||||
_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