[nes] timing and accuracy work.

This commit is contained in:
zeromus 2011-06-06 10:27:42 +00:00
parent 89ff0c8927
commit e6afb2359b
15 changed files with 257 additions and 94 deletions

View File

@ -224,6 +224,7 @@
<Compile Include="Sound\Utilities\Waves.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Consoles\Nintendo\Docs\test_status.txt" />
<Content Include="Consoles\PC Engine\Compat.txt" />
<Content Include="Consoles\Sega\SMS\Compat.txt" />
<Content Include="Notes.txt" />

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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("");

View File

@ -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);
}