diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index bc2ee55db0..0581efb55b 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -224,6 +224,7 @@
+
diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
index 9c95daa3ff..674bb028fc 100644
--- a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
+++ b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
@@ -17,16 +17,27 @@ namespace BizHawk.Emulation.CPUs.M6502
PendingCycles += cycles;
while (PendingCycles > 0)
{
- if (NMI)
- {
- TriggerException(ExceptionType.NMI);
- NMI = false;
- }
- if (IRQ && !FlagI)
- {
- TriggerException(ExceptionType.IRQ);
- }
-
+ if (NMI)
+ {
+ TriggerException(ExceptionType.NMI);
+ NMI = false;
+ }
+ if (IRQ && !FlagI)
+ {
+ if (SEI_Pending)
+ FlagI = true;
+ TriggerException(ExceptionType.IRQ);
+ }
+ if (CLI_Pending)
+ {
+ FlagI = false;
+ CLI_Pending = false;
+ }
+ if (SEI_Pending)
+ {
+ FlagI = true;
+ SEI_Pending = false;
+ }
if(debug) Console.WriteLine(State());
ushort this_pc = PC;
@@ -209,7 +220,15 @@ TriggerException(ExceptionType.BRK);
PendingCycles -= 5; TotalExecutedCycles += 5;
break;
case 0x28: // PLP
- P = ReadMemory((ushort)(++S + 0x100));
+ //handle I flag differently. sort of a sloppy way to do the job, but it does finish it off.
+ value8 = ReadMemory((ushort)(++S + 0x100));
+ if ((value8 & 0x04) != 0 && !FlagI)
+ SEI_Pending = true;
+ if ((value8 & 0x04) == 0 && FlagI)
+ CLI_Pending = true;
+ value8 &= unchecked((byte)~0x04);
+ P &= 0x04;
+ P |= value8;
FlagT = true;//this seems wrong
PendingCycles -= 4; TotalExecutedCycles += 4;
break;
@@ -431,7 +450,8 @@ FlagT = true;// this seems wrong
PendingCycles -= 6; TotalExecutedCycles += 6;
break;
case 0x58: // CLI
- FlagI = false;
+ //FlagI = false;
+ CLI_Pending = true;
PendingCycles -= 2; TotalExecutedCycles += 2;
break;
case 0x59: // EOR addr,Y
@@ -594,7 +614,8 @@ FlagT = true;// this seems wrong
PendingCycles -= 6; TotalExecutedCycles += 6;
break;
case 0x78: // SEI
- FlagI = true;
+ //FlagI = true;
+ SEI_Pending = true;
PendingCycles -= 2; TotalExecutedCycles += 2;
break;
case 0x79: // ADC addr,Y
diff --git a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
index 635209db00..2bd0e9a016 100644
--- a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
+++ b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
@@ -103,6 +103,9 @@ namespace BizHawk.Emulation.CPUs.M6502
public bool IRQ;
public bool NMI;
+ public bool CLI_Pending;
+ public bool SEI_Pending;
+ public bool EscapeRequest;
public void SyncState(Serializer ser)
{
diff --git a/BizHawk.Emulation/Consoles/Nintendo/Docs/test_status.txt b/BizHawk.Emulation/Consoles/Nintendo/Docs/test_status.txt
new file mode 100644
index 0000000000..e7651b4146
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Nintendo/Docs/test_status.txt
@@ -0,0 +1,32 @@
+look for tests here: http://wiki.nesdev.com/w/index.php/Emulator_tests
+
+blargg's MMC3:
+ FAIL for 4 and 6. i think 4 might not fail until some invisible PPU operations are correct. neither nintendulator or fceux pass these.
+
+blargg's ppu tests:
+ PASS for all but power_up_palette.nes which is lame
+
+blargg's ppu_vbl_nmi:
+ FAIL for 9. But hardly anyone passes this.....
+
+blargg's sprite hit tests:
+ FAIL for 9 and 10. fceux passes 10 (oldppu) and nintendulator passes both.
+ boath are not going to work any time soon due to sprite pattern decoding being separate from BG pattern fetching instead of interleaved.
+
+all_instrs.nes
+ FAIL (freezes emu??). I think this requires undocumented instructions.
+
+cpu_interrupts.nes
+ PASS
+
+instr_misc.nes
+ PASS
+
+instr_timing.nes
+ PASS
+
+nestest.nes
+ PASS
+
+official_only.nes
+ PASS
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
index 22a47268ad..e8ed2a9fce 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
@@ -15,6 +15,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
bool Configure(NES.EDetectionOrigin origin);
byte ReadPRG(int addr);
byte ReadPPU(int addr); byte PeekPPU(int addr);
+ void AddressPPU(int addr);
byte ReadWRAM(int addr);
byte ReadEXP(int addr);
void WritePRG(int addr, byte value);
@@ -140,6 +141,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
}
+ public virtual void AddressPPU(int addr) { }
public virtual byte PeekPPU(int addr) { return ReadPPU(addr); }
public virtual byte ReadPPU(int addr)
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
index f98ce9efe3..12e2653c98 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
@@ -63,7 +63,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public override void WritePRG(int addr, byte value)
{
if (ROM != null && bus_conflict) value = HandleNormalPRGConflict(addr,value);
- prg = (value*2) & prg_mask;
+ int prg_bank = value & 7;
+ prg = (prg_bank * 2) & prg_mask;
if ((value & 0x10) == 0)
SetMirrorType(NES.NESBoardBase.EMirrorType.OneScreenA);
else
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs
index 76aaaec427..dc1eedf90c 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs
@@ -22,6 +22,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
bank_regs[8] = (byte)(num_prg_banks - 1);
bank_regs[9] = (byte)(num_prg_banks - 2);
+ bank_regs[0] = 0;
+ bank_regs[1] = 1;
+ bank_regs[2] = 2;
+ bank_regs[3] = 3;
+ bank_regs[4] = 4;
+ bank_regs[5] = 5;
+ sync_2k_chr();
}
public void Dispose()
@@ -34,10 +41,28 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public int chr_mode, prg_mode, reg_addr;
//this contains the 8 programmable regs and 2 more at the end to represent PRG banks -2 and -1; and 4 more at the end to break down chr regs 0 and 1
+ //in other words:
+ //0: chr reg 0 (not used directly)
+ //1: chr reg 1 (not used directly)
+ //2,3,4,5: chr reg 2,3,4,5
+ //6,7: prg reg 6,7
+ //8,9: prg reg -2,-1
+ //10: chr reg 0A
+ //11: chr reg 0B
+ //12: chr reg 1A
+ //13: chr reg 1B
ByteBuffer bank_regs = new ByteBuffer(14);
ByteBuffer prg_lookup = new ByteBuffer(new byte[] { 6, 7, 9, 8, 9, 7, 6, 8 });
ByteBuffer chr_lookup = new ByteBuffer(new byte[] { 10, 11, 12, 13, 2, 3, 4, 5 });
+ void sync_2k_chr()
+ {
+ bank_regs[10] = (byte)((bank_regs[0] & ~1) + 0);
+ bank_regs[11] = (byte)((bank_regs[0] & ~1) + 1);
+ bank_regs[12] = (byte)((bank_regs[1] & ~1) + 0);
+ bank_regs[13] = (byte)((bank_regs[1] & ~1) + 1);
+ }
+
public virtual void WritePRG(int addr, byte value)
{
switch (addr & 0x6001)
@@ -49,11 +74,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
break;
case 0x0001: //$8001
bank_regs[reg_addr] = value;
- //setup the 2K chr regs
- bank_regs[10] = (byte)((bank_regs[0] & ~1) + 0);
- bank_regs[11] = (byte)((bank_regs[0] & ~1) + 1);
- bank_regs[12] = (byte)((bank_regs[1] & ~1) + 0);
- bank_regs[13] = (byte)((bank_regs[1] & ~1) + 1);
+ sync_2k_chr();
break;
}
}
@@ -114,37 +135,49 @@ namespace BizHawk.Emulation.Consoles.Nintendo
case 0x2001: //$A001
//wram enable/protect
break;
- case 0x4000: //$C000
+ case 0x4000: //$C000 - IRQ Reload value
irq_reload = value;
break;
- case 0x4001: //$C001
+ case 0x4001: //$C001 - IRQ Clear
irq_counter = 0;
break;
- case 0x6000: //$E000
+ case 0x6000: //$E000 - IRQ Acknowledge / Disable
irq_enable = false;
irq_pending = false;
SyncIRQ();
break;
- case 0x6001: //$E001
+ case 0x6001: //$E001 - IRQ Enable
irq_enable = true;
SyncIRQ();
break;
}
}
+ void IRQ_EQ_Pass()
+ {
+ if (irq_enable)
+ irq_pending = true;
+ SyncIRQ();
+ }
+
void ClockIRQ()
{
if (irq_counter == 0)
+ {
irq_counter = irq_reload;
+
+ //TODO - MMC3 variant behaviour??? not sure
+ //was needed to pass 2-details.nes
+ if (irq_counter == 0)
+ IRQ_EQ_Pass();
+ }
else
{
irq_counter--;
//Console.WriteLine(irq_counter);
if (irq_counter == 0)
{
- if (irq_enable)
- irq_pending = true;
- SyncIRQ();
+ IRQ_EQ_Pass();
}
}
}
@@ -240,24 +273,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//state
protected MMC3 mmc3;
+
+ public override void AddressPPU(int addr)
+ {
+ mmc3.Tick_PPU(addr);
+ }
- public override byte ReadPPU(int addr)
- {
- mmc3.Tick_PPU(addr);
- return base.ReadPPU(addr);
- }
-
- public override void WritePPU(int addr, byte value)
- {
- mmc3.Tick_PPU(addr);
- base.WritePPU(addr, value);
- }
-
- public override void WritePRG(int addr, byte value)
- {
- base.WritePRG(addr, value);
- }
-
protected override void BaseSetup()
{
wram_mask = (Cart.wram_size * 1024) - 1;
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs
index be3ada4fd6..cb907ade04 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs
@@ -50,6 +50,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//analyze board type
switch (Cart.board_type)
{
+ case "TXROM-HOMEBREW":
+ break;
case "NES-TBROM": //tecmo world cup soccer (DE) [untested]
AssertPrg(64); AssertChr(64); AssertVram(0); AssertWram(0);
AssertBattery(false);
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
index 4e021461bb..5b2eb01a6f 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
@@ -96,13 +96,22 @@ namespace BizHawk.Emulation.Consoles.Nintendo
else
cycles <<= 4;
+
+ //tricky logic to try to run one instruction at a time
cpu_accumulate += cycles;
- if (cpu_accumulate >= 48)
+ int cpu_cycles = cpu_accumulate / 48;
+ for (; ; )
{
- int todo = cpu_accumulate / 48;
- cpu_accumulate -= todo * 48;
+ if (cpu_cycles == 0) break;
+ int need_cpu = -cpu.PendingCycles + 1;
+ if (cpu_cycles < need_cpu) break;
+ if (need_cpu == 0) need_cpu = 1;
+ int todo = need_cpu;
+ cpu_cycles -= todo;
+ cpu_accumulate -= 48*todo;
cpu.Execute(todo);
apu.Run(todo);
+ ppu.TickCpu();
}
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
index cc6182466b..5b3dfb41fd 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
@@ -18,12 +18,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//when the ppu issues a write it goes through here and into the game board
public void ppubus_write(int addr, byte value)
{
+ nes.board.AddressPPU(addr);
nes.board.WritePPU(addr, value);
}
//when the ppu issues a read it goes through here and into the game board
public byte ppubus_read(int addr)
{
+ nes.board.AddressPPU(addr);
//apply freeze
if (ppubus_freeze[addr].IsFrozen)
return ppubus_freeze[addr].value;
@@ -89,17 +91,48 @@ namespace BizHawk.Emulation.Consoles.Nintendo
nes.cpu.NMI = true;
}
+ public void TickCpu()
+ {
+ if (NMI_PendingCycles > 0)
+ {
+ NMI_PendingCycles--;
+ if (NMI_PendingCycles == 0)
+ {
+ TriggerNMI();
+ }
+ }
+ }
+
void runppu(int x)
{
//pputime+=x;
//DON'T LIKE THIS....
ppur.status.cycle += x;
- if (ppur.status.cycle > ppur.status.end_cycle)
+ while(ppur.status.cycle >= ppur.status.end_cycle)
ppur.status.cycle -= ppur.status.end_cycle;
+
+ if(x == 0) return;
+
+ nes.RunCpu(1);
+ x--;
+
+ if (Reg2002_vblank_active_pending)
+ {
+ 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 (x == 0) return;
nes.RunCpu(x);
- //pputime -= cputodo<<2;
}
//hack
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
index 9b7d6c5935..edf11799cd 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
@@ -294,6 +294,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
Bit Reg2002_objoverflow; //Sprite overflow. The PPU can handle only eight sprites on one scanline and sets this bit if it starts drawing sprites.
Bit Reg2002_objhit; //Sprite 0 overlap. Set when a nonzero pixel of sprite 0 is drawn overlapping a nonzero background pixel. Used for raster timing.
Bit Reg2002_vblank_active; //Vertical blank start (0: has not started; 1: has started)
+ bool Reg2002_vblank_active_pending; //set of Reg2002_vblank_active is pending
+ bool Reg2002_vblank_clear_pending; //ppu's clear of vblank flag is pending
+ int NMI_PendingCycles;
byte PPUGenLatch;
public PPUREGS ppur;
Reg_2000 reg_2000;
@@ -324,11 +327,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//PPU CONTROL (write)
void write_2000(byte value)
{
- if (!reg_2000.vblank_nmi_gen & ((value & 0x80) != 0) && (Reg2002_vblank_active))
+ if (!reg_2000.vblank_nmi_gen & ((value & 0x80) != 0) && (Reg2002_vblank_active) && !Reg2002_vblank_clear_pending)
{
//if we just unleashed the vblank interrupt then activate it now
- //FCEUX would use a "trigger NMI2" here in order to result in some delay effect
- TriggerNMI();
+ NMI_PendingCycles = 2;
}
reg_2000.Value = value;
}
@@ -354,12 +356,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo
int ret = (Reg2002_vblank_active << 7) | (Reg2002_objhit << 6) | (Reg2002_objoverflow << 5) | (PPUGenLatch & 0x1F);
Reg2002_vblank_active = 0;
+ Reg2002_vblank_active_pending = false;
return (byte)ret;
}
void clear_2002()
{
- Reg2002_vblank_active = Reg2002_objhit = Reg2002_objoverflow = 0;
+ Reg2002_objhit = Reg2002_objoverflow = 0;
+ Reg2002_vblank_clear_pending = true;
}
//OAM ADDRESS (write)
@@ -378,7 +382,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
OAM[reg_2003] = value;
reg_2003++;
}
- byte read_2004() { return 0xFF; /* TODO !!!!!! THIS IS UGLY. WE SHOULD PASTE IT IN OR REWRITE IT BUT WE NEED TO ASK QEED FOR TEST CASES*/ }
+ byte read_2004() {
+ return OAM[reg_2003];
+ }
//SCROLL (write)
void write_2005(byte value)
@@ -414,6 +420,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ppur._vt |= (value >> 5);
ppur._ht = value & 31;
ppur.install_latches();
+
+ nes.board.AddressPPU(ppur.get_2007access());
}
vtoggle ^= true;
}
@@ -443,6 +451,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
ppur.increment2007(reg_2000.vram_incr32 != 0);
+ int newaddr = ppur.get_2007access() & 0x3FFF;
+ nes.board.AddressPPU(newaddr);
}
byte read_2007()
{
@@ -462,6 +472,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
ppur.increment2007(reg_2000.vram_incr32 != 0);
+
+ int newaddr = ppur.get_2007access() & 0x3FFF;
+ nes.board.AddressPPU(newaddr);
return ret;
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
index d362b5bab3..f11629dc7e 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
@@ -1,5 +1,7 @@
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb
+//todo - read http://wiki.nesdev.com/w/index.php/PPU_sprite_priority
+
using System;
using System.Diagnostics;
using System.Globalization;
@@ -85,17 +87,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return;
}
- Reg2002_vblank_active = 1;
+ Reg2002_vblank_active_pending = true;
ppuphase = PPUPHASE.VBL;
- //Not sure if this is correct. According to Matt Conte and my own tests, it is.
- //Timing is probably off, though.
+ //Not sure if this is correct. According to Matt Conte and my own tests, it is. Timing is probably off, though.
//NOTE: Not having this here breaks a Super Donkey Kong game.
reg_2003 = 0;
- const int delay = 20; //fceu used 12 here but I couldnt get it to work in marble madness and pirates.
- runppu(delay); //X6502_Run(12);
- if (reg_2000.vblank_nmi_gen) TriggerNMI();
+ //fceu/fceux had 12 here, but 15 was required to pass blargg's 05-nmi_timing.nes
+ const int delay = 15;
+ runppu(3);
+ bool nmi_destiny = reg_2000.vblank_nmi_gen && Reg2002_vblank_active;
+ runppu(delay - 3);
+ if (nmi_destiny) TriggerNMI();
if (PAL)
runppu(70 * (kLineTime) - delay);
else
@@ -103,17 +107,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//this seems to run just before the dummy scanline begins
clear_2002();
- //this early out caused metroid to fail to boot. I am leaving it here as a reminder of what not to do
- //if(!PPUON) { runppu(kLineTime*242); goto finish; }
-
- //There are 2 conditions that update all 5 PPU scroll counters with the
- //contents of the latches adjacent to them. The first is after a write to
- //2006/2. The second, is at the beginning of scanline 20, when the PPU starts
- //rendering data for the first time in a frame (this update won't happen if
- //all rendering is disabled via 2001.3 and 2001.4).
-
- //if(PPUON)
- // ppur.install_latches();
TempOAM* oams = stackalloc TempOAM[128];
int* oamcounts = stackalloc int[2];
@@ -142,6 +135,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//two of those tiles were read in the last scanline.
for (int xt = 0; xt < 32; xt++)
{
+ if (sl == 31 && xt == 31)
+ {
+ int zzz = 9;
+ }
Read_bgdata(ref bgdata[xt + 2]);
//ok, we're also going to draw here.
@@ -205,11 +202,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//transparent pixel bailout
if (spixel == 0) continue;
+ //TODO - make sure we dont trigger spritehit if the edges are masked for either BG or OBJ
//spritehit:
//1. is it sprite#0?
//2. is the bg pixel nonzero?
//then, it is spritehit.
- if (oam->index == 0 && (pixel & 3) != 0 && rasterpos < 255)
+ if (oam->index == 0)
+ {
+ int zzz = 9;
+ }
+ if (oam->index == 0 && pixel != 0 && rasterpos < 255)
{
Reg2002_objhit = true;
}
@@ -397,20 +399,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ppuphase = PPUPHASE.BG;
- //fetch BG: two tiles for next line
- for (int xt = 0; xt < 2; xt++)
- Read_bgdata(ref bgdata[xt]);
-
//I'm unclear of the reason why this particular access to memory is made.
//The nametable address that is accessed 2 times in a row here, is also the
//same nametable address that points to the 3rd tile to be rendered on the
//screen (or basically, the first nametable address that will be accessed when
//the PPU is fetching background data on the next scanline).
//(not implemented yet)
- runppu(kFetchTime*2);
+ runppu(kFetchTime * 2);
if (sl == 0)
{
- if (idleSynch && reg_2001.PPUON && !PAL)
+ if (idleSynch && reg_2001.show_bg && !PAL)
ppur.status.end_cycle = 340;
else
ppur.status.end_cycle = 341;
@@ -418,7 +416,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
else
ppur.status.end_cycle = 341;
- //runppu(kFetchTime);
+
+ //fetch BG: two tiles for next line
+ for (int xt = 0; xt < 2; xt++)
+ Read_bgdata(ref bgdata[xt]);
//After memory access 170, the PPU simply rests for 4 cycles (or the
//equivelant of half a memory access cycle) before repeating the whole
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
index fd6c3e5b10..22852a6dea 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs
@@ -55,12 +55,16 @@ static string ClassifyTable = @"
1 32 32 8 0 NES-SEROM; lolo
1 128 0 8 0 NES-SNROM; zelda
1 128 128 8 0 NES-SKROM; zelda 2
-1 128 0 8 8 NES-SNROM; some of blargg's tests (apu)
-1 256 0 8 8 NES-SNROM; some of blargg's test (cpu tests)
+1 32 0 8 8 NROM-HOMEBREW; instr_timing.nes
+1 64 0 8 8 NROM-HOMEBREW; instr_misc.nes
+1 80 0 8 8 NROM-HOMEBREW; blargg's cpu_interrupts.nes
+1 128 0 8 8 NES-SNROM; some of blargg's tests (apu) [TODO recheck as NROM-HOMEBREW]
+1 256 0 8 8 NES-SNROM; some of blargg's test (cpu tests) [TODO recheck as NROM-HOMEBREW]
2 128 0 8 0 NES-UNROM; mega man
2 256 0 8 0 NES-UOROM; paperboy 2
3 32 32 8 0 NES-CNROM; adventure island
4 128 128 8 0 NES-TSROM; double dragon 2 (should be TL1ROM but maybe this will work)
+4 32 8 8 0 TXROM-HOMEBREW; blargg's mmc3 tests
7 128 0 8 0 NES-ANROM; marble madness
7 256 0 8 8 NES-AOROM; battletoads
11 32 16 8 0 Discrete_74x377
diff --git a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
index 10e8d73c6a..5363dca6bd 100644
--- a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
+++ b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
@@ -362,17 +362,27 @@ namespace M6502
w.WriteLine(" PendingCycles += cycles;");
w.WriteLine(" while (PendingCycles > 0)");
w.WriteLine(" {");
-
- w.WriteLine(" if (NMI)");
- w.WriteLine(" {");
- w.WriteLine(" TriggerException(ExceptionType.NMI);");
- w.WriteLine(" NMI = false;");
- w.WriteLine(" }");
- w.WriteLine(" if (IRQ && !FlagI)");
- w.WriteLine(" {");
- w.WriteLine(" TriggerException(ExceptionType.IRQ);");
- w.WriteLine(" }");
- w.WriteLine("");
+ w.WriteLine(" if (NMI)");
+ w.WriteLine(" {");
+ w.WriteLine(" TriggerException(ExceptionType.NMI);");
+ w.WriteLine(" NMI = false;");
+ w.WriteLine(" }");
+ w.WriteLine(" if (IRQ && !FlagI)");
+ w.WriteLine(" {");
+ w.WriteLine(" if (SEI_Pending)");
+ w.WriteLine(" FlagI = true;");
+ w.WriteLine(" TriggerException(ExceptionType.IRQ);");
+ w.WriteLine(" }");
+ w.WriteLine(" if (CLI_Pending)");
+ w.WriteLine(" {");
+ w.WriteLine(" FlagI = false;");
+ w.WriteLine(" CLI_Pending = false;");
+ w.WriteLine(" }");
+ w.WriteLine(" if (SEI_Pending)");
+ w.WriteLine(" {");
+ w.WriteLine(" FlagI = true;");
+ w.WriteLine(" SEI_Pending = false;");
+ w.WriteLine(" }");
w.WriteLine(" if(debug) Console.WriteLine(State());");
w.WriteLine("");
diff --git a/CpuCoreGenerator/MOS 6502/Instructions.cs b/CpuCoreGenerator/MOS 6502/Instructions.cs
index 07394ae457..d9b9766bb6 100644
--- a/CpuCoreGenerator/MOS 6502/Instructions.cs
+++ b/CpuCoreGenerator/MOS 6502/Instructions.cs
@@ -82,7 +82,8 @@ namespace M6502
private void CLI(OpcodeInfo op, TextWriter w)
{
- w.WriteLine(Spaces + "FlagI = false;");
+ w.WriteLine(Spaces + "//FlagI = false;");
+ w.WriteLine(Spaces + "CLI_Pending = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
@@ -244,7 +245,15 @@ namespace M6502
private void PLP(OpcodeInfo op, TextWriter w)
{
- w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x100));");
+ w.WriteLine(Spaces + "//handle I flag differently. sort of a sloppy way to do the job, but it does finish it off.");
+ w.WriteLine(Spaces + "value8 = ReadMemory((ushort)(++S + 0x100));");
+ w.WriteLine(Spaces + "if ((value8 & 0x04) != 0 && !FlagI)");
+ w.WriteLine(Spaces + "\tSEI_Pending = true;");
+ w.WriteLine(Spaces + "if ((value8 & 0x04) == 0 && FlagI)");
+ w.WriteLine(Spaces + "\tCLI_Pending = true;");
+ w.WriteLine(Spaces + "value8 &= unchecked((byte)~0x04);");
+ w.WriteLine(Spaces + "P &= 0x04;");
+ w.WriteLine(Spaces + "P |= value8;");
w.WriteLine("FlagT = true;//this seems wrong");//this seems wrong
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
@@ -333,7 +342,8 @@ w.WriteLine("FlagT = true;// this seems wrong");//this seems wrong
private void SEI(OpcodeInfo op, TextWriter w)
{
- w.WriteLine(Spaces + "FlagI = true;");
+ w.WriteLine(Spaces + "//FlagI = true;");
+ w.WriteLine(Spaces + "SEI_Pending = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}