NESHawk: Clean up and minor refactor
Simplify the code base a bit and gets a performance boost as well.
This commit is contained in:
parent
000d30025a
commit
7814a9ed30
|
@ -385,10 +385,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
//at least it should be, but something is off with that (start up time?) so it is 3,3,3,4,3 for now
|
//at least it should be, but something is off with that (start up time?) so it is 3,3,3,4,3 for now
|
||||||
//NTSC:
|
//NTSC:
|
||||||
//sequence of ppu clocks per cpu clock: 3
|
//sequence of ppu clocks per cpu clock: 3
|
||||||
ByteBuffer cpu_sequence;
|
public ByteBuffer cpu_sequence;
|
||||||
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[] { 3, 3, 3, 3, 3 });
|
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[] { 3, 3, 3, 3, 3 });
|
||||||
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[] { 3, 3, 3, 4, 3 });
|
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[] { 3, 3, 3, 4, 3 });
|
||||||
public int cpu_step, cpu_stepcounter, cpu_deadcounter;
|
public int cpu_deadcounter;
|
||||||
|
|
||||||
public int oam_dma_index;
|
public int oam_dma_index;
|
||||||
public bool oam_dma_exec = false;
|
public bool oam_dma_exec = false;
|
||||||
|
@ -401,140 +401,122 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
public bool do_the_reread;
|
public bool do_the_reread;
|
||||||
public byte DB; //old data bus values from previous reads
|
public byte DB; //old data bus values from previous reads
|
||||||
|
|
||||||
|
|
||||||
#if VS2012
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#endif
|
|
||||||
internal void RunCpuOne()
|
internal void RunCpuOne()
|
||||||
{
|
{
|
||||||
cpu_stepcounter++;
|
///////////////////////////
|
||||||
if (cpu_stepcounter == cpu_sequence[cpu_step])
|
// OAM DMA start
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
|
if (sprdma_countdown > 0)
|
||||||
{
|
{
|
||||||
cpu_step++;
|
sprdma_countdown--;
|
||||||
if (cpu_step == 5) cpu_step = 0;
|
if (sprdma_countdown == 0)
|
||||||
cpu_stepcounter = 0;
|
|
||||||
|
|
||||||
///////////////////////////
|
|
||||||
// OAM DMA start
|
|
||||||
///////////////////////////
|
|
||||||
|
|
||||||
if (sprdma_countdown > 0)
|
|
||||||
{
|
{
|
||||||
sprdma_countdown--;
|
if (cpu.TotalExecutedCycles % 2 == 0)
|
||||||
if (sprdma_countdown == 0)
|
|
||||||
{
|
{
|
||||||
if (cpu.TotalExecutedCycles % 2 == 0)
|
cpu_deadcounter = 2;
|
||||||
{
|
|
||||||
cpu_deadcounter = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cpu_deadcounter = 1;
|
|
||||||
}
|
|
||||||
oam_dma_exec = true;
|
|
||||||
cpu.RDY = false;
|
|
||||||
oam_dma_index = 0;
|
|
||||||
special_case_delay = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign)
|
|
||||||
{
|
|
||||||
if (cpu_deadcounter == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (oam_dma_index % 2 == 0)
|
|
||||||
{
|
|
||||||
oam_dma_byte = ReadMemory(oam_dma_addr);
|
|
||||||
oam_dma_addr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteMemory(0x2004, oam_dma_byte);
|
|
||||||
}
|
|
||||||
oam_dma_index++;
|
|
||||||
if (oam_dma_index == 512) oam_dma_exec = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cpu_deadcounter--;
|
cpu_deadcounter = 1;
|
||||||
}
|
}
|
||||||
}
|
oam_dma_exec = true;
|
||||||
else if (apu.dmc_dma_countdown == 1)
|
|
||||||
{
|
|
||||||
dmc_realign = true;
|
|
||||||
}
|
|
||||||
else if (dmc_realign)
|
|
||||||
{
|
|
||||||
dmc_realign = false;
|
|
||||||
}
|
|
||||||
/////////////////////////////
|
|
||||||
// OAM DMA end
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
// dmc dma start
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
if (apu.dmc_dma_countdown > 0)
|
|
||||||
{
|
|
||||||
cpu.RDY = false;
|
cpu.RDY = false;
|
||||||
dmc_dma_exec = true;
|
oam_dma_index = 0;
|
||||||
apu.dmc_dma_countdown--;
|
special_case_delay = true;
|
||||||
if (apu.dmc_dma_countdown == 0)
|
|
||||||
{
|
|
||||||
apu.RunDMCFetch();
|
|
||||||
dmc_dma_exec = false;
|
|
||||||
apu.dmc_dma_countdown = -1;
|
|
||||||
do_the_reread = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
// dmc dma end
|
|
||||||
/////////////////////////////
|
|
||||||
apu.RunOne(true);
|
|
||||||
|
|
||||||
if (cpu.RDY && !IRQ_delay)
|
|
||||||
{
|
|
||||||
cpu.IRQ = _irq_apu || Board.IRQSignal;
|
|
||||||
}
|
|
||||||
else if (special_case_delay || apu.dmc_dma_countdown == 3)
|
|
||||||
{
|
|
||||||
cpu.IRQ = _irq_apu || Board.IRQSignal;
|
|
||||||
special_case_delay = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu.ExecuteOne();
|
|
||||||
apu.RunOne(false);
|
|
||||||
|
|
||||||
if (ppu.double_2007_read > 0)
|
|
||||||
ppu.double_2007_read--;
|
|
||||||
|
|
||||||
if (do_the_reread && cpu.RDY)
|
|
||||||
do_the_reread = false;
|
|
||||||
|
|
||||||
if (IRQ_delay)
|
|
||||||
IRQ_delay = false;
|
|
||||||
|
|
||||||
if (!dmc_dma_exec && !oam_dma_exec && !cpu.RDY)
|
|
||||||
{
|
|
||||||
cpu.RDY = true;
|
|
||||||
IRQ_delay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu.ppu_open_bus_decay(0);
|
|
||||||
|
|
||||||
Board.ClockCPU();
|
|
||||||
ppu.PostCpuInstructionOne();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oam_dma_exec && apu.dmc_dma_countdown != 1 && !dmc_realign)
|
||||||
|
{
|
||||||
|
if (cpu_deadcounter == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (oam_dma_index % 2 == 0)
|
||||||
|
{
|
||||||
|
oam_dma_byte = ReadMemory(oam_dma_addr);
|
||||||
|
oam_dma_addr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteMemory(0x2004, oam_dma_byte);
|
||||||
|
}
|
||||||
|
oam_dma_index++;
|
||||||
|
if (oam_dma_index == 512) oam_dma_exec = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpu_deadcounter--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (apu.dmc_dma_countdown == 1)
|
||||||
|
{
|
||||||
|
dmc_realign = true;
|
||||||
|
}
|
||||||
|
else if (dmc_realign)
|
||||||
|
{
|
||||||
|
dmc_realign = false;
|
||||||
|
}
|
||||||
|
/////////////////////////////
|
||||||
|
// OAM DMA end
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////
|
||||||
|
// dmc dma start
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
if (apu.dmc_dma_countdown > 0)
|
||||||
|
{
|
||||||
|
cpu.RDY = false;
|
||||||
|
dmc_dma_exec = true;
|
||||||
|
apu.dmc_dma_countdown--;
|
||||||
|
if (apu.dmc_dma_countdown == 0)
|
||||||
|
{
|
||||||
|
apu.RunDMCFetch();
|
||||||
|
dmc_dma_exec = false;
|
||||||
|
apu.dmc_dma_countdown = -1;
|
||||||
|
do_the_reread = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////
|
||||||
|
// dmc dma end
|
||||||
|
/////////////////////////////
|
||||||
|
apu.RunOne(true);
|
||||||
|
|
||||||
|
if (cpu.RDY && !IRQ_delay)
|
||||||
|
{
|
||||||
|
cpu.IRQ = _irq_apu || Board.IRQSignal;
|
||||||
|
}
|
||||||
|
else if (special_case_delay || apu.dmc_dma_countdown == 3)
|
||||||
|
{
|
||||||
|
cpu.IRQ = _irq_apu || Board.IRQSignal;
|
||||||
|
special_case_delay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.ExecuteOne();
|
||||||
|
apu.RunOne(false);
|
||||||
|
|
||||||
|
if (ppu.double_2007_read > 0)
|
||||||
|
ppu.double_2007_read--;
|
||||||
|
|
||||||
|
if (do_the_reread && cpu.RDY)
|
||||||
|
do_the_reread = false;
|
||||||
|
|
||||||
|
if (IRQ_delay)
|
||||||
|
IRQ_delay = false;
|
||||||
|
|
||||||
|
if (!dmc_dma_exec && !oam_dma_exec && !cpu.RDY)
|
||||||
|
{
|
||||||
|
cpu.RDY = true;
|
||||||
|
IRQ_delay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Board.ClockCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VS2012
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#endif
|
|
||||||
public byte ReadReg(int addr)
|
public byte ReadReg(int addr)
|
||||||
{
|
{
|
||||||
byte ret_spec;
|
byte ret_spec;
|
||||||
|
@ -681,7 +663,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
case 0x4013:
|
case 0x4013:
|
||||||
apu.WriteReg(addr, val);
|
apu.WriteReg(addr, val);
|
||||||
break;
|
break;
|
||||||
case 0x4014: Exec_OAMDma(val); break;
|
case 0x4014:
|
||||||
|
//schedule a sprite dma event for beginning 1 cycle in the future.
|
||||||
|
//this receives 2 because thats just the way it works out.
|
||||||
|
oam_dma_addr = (ushort)(val << 8);
|
||||||
|
sprdma_countdown = 1;
|
||||||
|
break;
|
||||||
case 0x4015: apu.WriteReg(addr, val); break;
|
case 0x4015: apu.WriteReg(addr, val); break;
|
||||||
case 0x4016:
|
case 0x4016:
|
||||||
if (_isVS)
|
if (_isVS)
|
||||||
|
@ -740,15 +727,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Exec_OAMDma(byte val)
|
|
||||||
{
|
|
||||||
//schedule a sprite dma event for beginning 1 cycle in the future.
|
|
||||||
//this receives 2 because thats just the way it works out.
|
|
||||||
oam_dma_addr = (ushort)(val << 8);
|
|
||||||
|
|
||||||
sprdma_countdown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the provided palette as current.
|
/// Sets the provided palette as current.
|
||||||
/// Applies the current deemph settings if needed to expand a 64-entry palette to 512
|
/// Applies the current deemph settings if needed to expand a 64-entry palette to 512
|
||||||
|
|
|
@ -60,8 +60,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
ser.Sync("cpu_accumulate", ref cpu_accumulate);
|
ser.Sync("cpu_accumulate", ref cpu_accumulate);
|
||||||
ser.Sync("_irq_apu", ref _irq_apu);
|
ser.Sync("_irq_apu", ref _irq_apu);
|
||||||
ser.Sync("sprdma_countdown", ref sprdma_countdown);
|
ser.Sync("sprdma_countdown", ref sprdma_countdown);
|
||||||
ser.Sync("cpu_step", ref cpu_step);
|
|
||||||
ser.Sync("cpu_stepcounter", ref cpu_stepcounter);
|
|
||||||
ser.Sync("cpu_deadcounter", ref cpu_deadcounter);
|
ser.Sync("cpu_deadcounter", ref cpu_deadcounter);
|
||||||
|
|
||||||
//oam related
|
//oam related
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb
|
using System;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
|
@ -8,6 +6,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
{
|
{
|
||||||
public sealed partial class PPU
|
public sealed partial class PPU
|
||||||
{
|
{
|
||||||
|
public int cpu_step, cpu_stepcounter;
|
||||||
|
|
||||||
// this only handles region differences within the PPU
|
// this only handles region differences within the PPU
|
||||||
int preNMIlines;
|
int preNMIlines;
|
||||||
int postNMIlines;
|
int postNMIlines;
|
||||||
|
@ -203,6 +203,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
|
ser.Sync("cpu_step", ref cpu_step);
|
||||||
|
ser.Sync("cpu_stepcounter", ref cpu_stepcounter);
|
||||||
ser.Sync("ppudead", ref ppudead);
|
ser.Sync("ppudead", ref ppudead);
|
||||||
ser.Sync("idleSynch", ref idleSynch);
|
ser.Sync("idleSynch", ref idleSynch);
|
||||||
ser.Sync("NMI_PendingInstructions", ref NMI_PendingInstructions);
|
ser.Sync("NMI_PendingInstructions", ref NMI_PendingInstructions);
|
||||||
|
@ -255,32 +257,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
ppu_open_bus_decay_timer = new int[8];
|
ppu_open_bus_decay_timer = new int[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VS2012
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#endif
|
|
||||||
void TriggerNMI()
|
|
||||||
{
|
|
||||||
nes.cpu.NMI = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//this gets called once after each cpu instruction executes.
|
|
||||||
//anything that needs to happen at instruction granularity can get checked here
|
|
||||||
//to save having to check it at ppu cycle granularity
|
|
||||||
public void PostCpuInstructionOne()
|
|
||||||
{
|
|
||||||
if (NMI_PendingInstructions > 0)
|
|
||||||
{
|
|
||||||
NMI_PendingInstructions--;
|
|
||||||
if (NMI_PendingInstructions <= 0)
|
|
||||||
{
|
|
||||||
TriggerNMI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if VS2012
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
#endif
|
|
||||||
void runppu(int x)
|
void runppu(int x)
|
||||||
{
|
{
|
||||||
//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
|
||||||
|
@ -318,13 +294,36 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
ppur.status.cycle++;
|
ppur.status.cycle++;
|
||||||
is_even_cycle = !is_even_cycle;
|
is_even_cycle = !is_even_cycle;
|
||||||
//might not actually run a cpu cycle if there are none to be run right now
|
|
||||||
nes.RunCpuOne();
|
// 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
|
||||||
|
ppu_open_bus_decay(0);
|
||||||
|
|
||||||
|
// Check for NMIs
|
||||||
|
if (NMI_PendingInstructions > 0)
|
||||||
|
{
|
||||||
|
NMI_PendingInstructions--;
|
||||||
|
if (NMI_PendingInstructions <= 0)
|
||||||
|
{
|
||||||
|
nes.cpu.NMI = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Reg2002_vblank_active_pending)
|
if (Reg2002_vblank_active_pending)
|
||||||
{
|
{
|
||||||
//if (Reg2002_vblank_active_pending)
|
Reg2002_vblank_active = 1;
|
||||||
Reg2002_vblank_active = 1;
|
|
||||||
Reg2002_vblank_active_pending = false;
|
Reg2002_vblank_active_pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,10 +336,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
nes.Board.ClockPPU();
|
nes.Board.ClockPPU();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hack
|
|
||||||
//public bool PAL = false;
|
|
||||||
//bool SPRITELIMIT = true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,6 +309,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
public Reg_2000 reg_2000;
|
public Reg_2000 reg_2000;
|
||||||
public Reg_2001 reg_2001;
|
public Reg_2001 reg_2001;
|
||||||
byte reg_2003;
|
byte reg_2003;
|
||||||
|
|
||||||
void regs_reset()
|
void regs_reset()
|
||||||
{
|
{
|
||||||
//TODO - would like to reconstitute the entire PPU instead of all this..
|
//TODO - would like to reconstitute the entire PPU instead of all this..
|
||||||
|
@ -396,12 +397,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
return (byte)((Reg2002_vblank_active << 7) | (Reg2002_objhit << 6) | (Reg2002_objoverflow << 5) | (ppu_open_bus & 0x1F));
|
return (byte)((Reg2002_vblank_active << 7) | (Reg2002_objhit << 6) | (Reg2002_objoverflow << 5) | (ppu_open_bus & 0x1F));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_2002()
|
|
||||||
{
|
|
||||||
Reg2002_objhit = Reg2002_objoverflow = 0;
|
|
||||||
Reg2002_vblank_clear_pending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//OAM ADDRESS (write)
|
//OAM ADDRESS (write)
|
||||||
void write_2003(int addr, byte value)
|
void write_2003(int addr, byte value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb
|
//TODO - correctly emulate PPU OFF state
|
||||||
|
|
||||||
//TODO - correctly emulate PPU OFF state
|
|
||||||
|
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
using System;
|
using System;
|
||||||
|
@ -10,6 +8,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
sealed partial class PPU
|
sealed partial class PPU
|
||||||
{
|
{
|
||||||
const int kFetchTime = 2;
|
const int kFetchTime = 2;
|
||||||
|
const int kLineTime = 341;
|
||||||
|
|
||||||
struct BGDataRecord
|
struct BGDataRecord
|
||||||
{
|
{
|
||||||
|
@ -78,7 +77,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
if (reg_2001.color_disable)
|
if (reg_2001.color_disable)
|
||||||
pixelcolor_latch_2 &= 0x30;
|
pixelcolor_latch_2 &= 0x30;
|
||||||
|
|
||||||
xbuf[(target - 2)] = PaletteAdjustPixel(pixelcolor_latch_2);
|
//TODO - check flashing sirens in werewolf
|
||||||
|
//tack on the deemph bits. THESE MAY BE ORDERED WRONG. PLEASE CHECK IN THE PALETTE CODE
|
||||||
|
xbuf[(target - 2)] = (short)(pixelcolor_latch_2 | reg_2001.intensity_lsl_6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row_check >= 1)
|
if (row_check >= 1)
|
||||||
|
@ -158,14 +159,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
} //switch(cycle)
|
} //switch(cycle)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO - check flashing sirens in werewolf
|
|
||||||
short PaletteAdjustPixel(int pixel)
|
|
||||||
{
|
|
||||||
//tack on the deemph bits. THESE MAY BE ORDERED WRONG. PLEASE CHECK IN THE PALETTE CODE
|
|
||||||
return (short)(pixel | reg_2001.intensity_lsl_6);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int kLineTime = 341;
|
|
||||||
public unsafe void FrameAdvance()
|
public unsafe void FrameAdvance()
|
||||||
{
|
{
|
||||||
BGDataRecord* bgdata = stackalloc BGDataRecord[34]; //one at the end is junk, it can never be rendered
|
BGDataRecord* bgdata = stackalloc BGDataRecord[34]; //one at the end is junk, it can never be rendered
|
||||||
|
@ -191,12 +184,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
runppu(3);
|
runppu(3);
|
||||||
bool nmi_destiny = reg_2000.vblank_nmi_gen && Reg2002_vblank_active;
|
bool nmi_destiny = reg_2000.vblank_nmi_gen && Reg2002_vblank_active;
|
||||||
runppu(3);
|
runppu(3);
|
||||||
if (nmi_destiny) TriggerNMI();
|
if (nmi_destiny) nes.cpu.NMI = true;
|
||||||
nes.Board.AtVsyncNMI();
|
nes.Board.AtVsyncNMI();
|
||||||
runppu(postNMIlines * kLineTime - delay);
|
runppu(postNMIlines * kLineTime - delay);
|
||||||
|
|
||||||
//this seems to run just before the dummy scanline begins
|
//this seems to happen just before the dummy scanline begins
|
||||||
clear_2002();
|
Reg2002_objhit = Reg2002_objoverflow = 0;
|
||||||
|
Reg2002_vblank_clear_pending = true;
|
||||||
|
|
||||||
idleSynch ^= true;
|
idleSynch ^= true;
|
||||||
|
|
||||||
|
@ -224,8 +218,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
yp = sl - 1;
|
yp = sl - 1;
|
||||||
ppuphase = PPUPHASE.BG;
|
ppuphase = PPUPHASE.BG;
|
||||||
|
|
||||||
// "If PPUADDR is not less then 8 when rendering starts, the first 8 fights in OAM and written to from
|
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM and written to from
|
||||||
// the current location off PPUADDR"
|
// the current location off PPUADDR"
|
||||||
if (sl == 0 && PPUON && reg_2003 >= 8 && region==Region.NTSC)
|
if (sl == 0 && PPUON && reg_2003 >= 8 && region==Region.NTSC)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
|
@ -233,7 +227,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
OAM[i] = OAM[reg_2003 & 0xF8 + i];
|
OAM[i] = OAM[reg_2003 & 0xF8 + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NTViewCallback != null && yp == NTViewCallback.Scanline) NTViewCallback.Callback();
|
if (NTViewCallback != null && yp == NTViewCallback.Scanline) NTViewCallback.Callback();
|
||||||
if (PPUViewCallback != null && yp == PPUViewCallback.Scanline) PPUViewCallback.Callback();
|
if (PPUViewCallback != null && yp == PPUViewCallback.Scanline) PPUViewCallback.Callback();
|
||||||
|
|
||||||
|
@ -255,7 +249,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
|
|
||||||
//check all the conditions that can cause things to render in these 8px
|
//check all the conditions that can cause things to render in these 8px
|
||||||
bool renderspritenow = show_obj_new && (xt > 0 || reg_2001.show_obj_leftmost);
|
bool renderspritenow = show_obj_new && (xt > 0 || reg_2001.show_obj_leftmost);
|
||||||
bool renderbgnow;
|
bool renderbgnow;
|
||||||
|
bool hit_pending = false;
|
||||||
|
|
||||||
for (int xp = 0; xp < 8; xp++, rasterpos++)
|
for (int xp = 0; xp < 8; xp++, rasterpos++)
|
||||||
{
|
{
|
||||||
|
@ -350,7 +345,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
{
|
{
|
||||||
if (yp >= read_value && yp < read_value + spriteHeight && PPUON)
|
if (yp >= read_value && yp < read_value + spriteHeight && PPUON)
|
||||||
{
|
{
|
||||||
Reg2002_objoverflow = true;
|
hit_pending = true;
|
||||||
|
//Reg2002_objoverflow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0)
|
if (yp >= read_value && yp < read_value + spriteHeight && spr_true_count == 0)
|
||||||
|
@ -400,6 +396,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||||
else
|
else
|
||||||
runppu(1);
|
runppu(1);
|
||||||
|
|
||||||
|
if (hit_pending)
|
||||||
|
{
|
||||||
|
hit_pending = false;
|
||||||
|
Reg2002_objoverflow = true;
|
||||||
|
}
|
||||||
|
|
||||||
renderbgnow = show_bg_new && (xt > 0 || reg_2001.show_bg_leftmost);
|
renderbgnow = show_bg_new && (xt > 0 || reg_2001.show_bg_leftmost);
|
||||||
//bg pos is different from raster pos due to its offsetability.
|
//bg pos is different from raster pos due to its offsetability.
|
||||||
//so adjust for that here
|
//so adjust for that here
|
||||||
|
|
Loading…
Reference in New Issue