[NES] general ppu timing, mmc3, and nt view fixups.
This commit is contained in:
parent
d0ea2f7106
commit
d05b81238e
|
@ -3,13 +3,13 @@ look for tests here: http://wiki.nesdev.com/w/index.php/Emulator_tests
|
||||||
==blargg's tests==
|
==blargg's tests==
|
||||||
|
|
||||||
MMC3:
|
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.
|
FAIL for 6. neither nintendulator or fceux pass this. we should be able to pass it once mmc3 variant support is finalized.
|
||||||
|
|
||||||
ppu tests:
|
ppu tests:
|
||||||
PASS for all but power_up_palette.nes which is lame
|
PASS for all but power_up_palette.nes which is lame
|
||||||
|
|
||||||
ppu_vbl_nmi:
|
ppu_vbl_nmi:
|
||||||
FAIL for 9. But hardly anyone passes this.....
|
FAIL for 10. But hardly anyone passes this.....
|
||||||
|
|
||||||
sprite hit tests:
|
sprite hit tests:
|
||||||
FAIL for 9 and 10. fceux passes 10 (oldppu) and nintendulator passes both.
|
FAIL for 9 and 10. fceux passes 10 (oldppu) and nintendulator passes both.
|
||||||
|
@ -21,9 +21,6 @@ cpu_timing_test.nes
|
||||||
official_only.nes
|
official_only.nes
|
||||||
PASS
|
PASS
|
||||||
|
|
||||||
all_instrs.nes
|
|
||||||
FAIL (freezes emu??). I think this requires undocumented instructions.
|
|
||||||
|
|
||||||
instr_timing.nes
|
instr_timing.nes
|
||||||
PASS
|
PASS
|
||||||
|
|
||||||
|
@ -33,6 +30,9 @@ cpu_interrupts.nes
|
||||||
instr_misc.nes
|
instr_misc.nes
|
||||||
PASS
|
PASS
|
||||||
|
|
||||||
|
all_instrs.nes
|
||||||
|
FAIL (undocumented opcodes)
|
||||||
|
|
||||||
=============
|
=============
|
||||||
|
|
||||||
nestest.nes
|
nestest.nes
|
||||||
|
|
|
@ -13,6 +13,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
void Create(NES nes);
|
void Create(NES nes);
|
||||||
bool Configure(NES.EDetectionOrigin origin);
|
bool Configure(NES.EDetectionOrigin origin);
|
||||||
|
|
||||||
|
//gets called once per PPU clock, for boards with complex behaviour which must be monitoring clock (i.e. mmc3 irq counter)
|
||||||
|
void ClockPPU();
|
||||||
|
|
||||||
byte ReadPRG(int addr);
|
byte ReadPRG(int addr);
|
||||||
byte ReadPPU(int addr); byte PeekPPU(int addr);
|
byte ReadPPU(int addr); byte PeekPPU(int addr);
|
||||||
void AddressPPU(int addr);
|
void AddressPPU(int addr);
|
||||||
|
@ -49,6 +53,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
this.NES = nes;
|
this.NES = nes;
|
||||||
}
|
}
|
||||||
public abstract bool Configure(NES.EDetectionOrigin origin);
|
public abstract bool Configure(NES.EDetectionOrigin origin);
|
||||||
|
public virtual void ClockPPU() { }
|
||||||
|
|
||||||
public CartInfo Cart { get { return NES.cart; } }
|
public CartInfo Cart { get { return NES.cart; } }
|
||||||
public NES NES { get; set; }
|
public NES NES { get; set; }
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
//state
|
//state
|
||||||
public NES.NESBoardBase.EMirrorType mirror;
|
public NES.NESBoardBase.EMirrorType mirror;
|
||||||
int ppubus_state, ppubus_statecounter;
|
int a12_old;
|
||||||
byte irq_reload, irq_counter;
|
byte irq_reload, irq_counter;
|
||||||
bool irq_pending, irq_enable;
|
bool irq_pending, irq_enable;
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
SyncIRQ();
|
SyncIRQ();
|
||||||
break;
|
break;
|
||||||
case 0x6001: //$E001 - IRQ Enable
|
case 0x6001: //$E001 - IRQ Enable
|
||||||
|
//board.NES.LogLine("irq en");
|
||||||
irq_enable = true;
|
irq_enable = true;
|
||||||
SyncIRQ();
|
SyncIRQ();
|
||||||
break;
|
break;
|
||||||
|
@ -156,7 +157,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
void IRQ_EQ_Pass()
|
void IRQ_EQ_Pass()
|
||||||
{
|
{
|
||||||
if (irq_enable)
|
if (irq_enable)
|
||||||
|
{
|
||||||
|
//board.NES.LogLine("mmc3 IRQ");
|
||||||
irq_pending = true;
|
irq_pending = true;
|
||||||
|
}
|
||||||
SyncIRQ();
|
SyncIRQ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +178,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
irq_counter--;
|
irq_counter--;
|
||||||
//Console.WriteLine(irq_counter);
|
|
||||||
if (irq_counter == 0)
|
if (irq_counter == 0)
|
||||||
{
|
{
|
||||||
IRQ_EQ_Pass();
|
IRQ_EQ_Pass();
|
||||||
|
@ -182,22 +185,50 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO - this should be determined from NES timestamps to correctly emulate ppu writes interfering
|
//it really seems like these should be the same but i cant seem to unify them.
|
||||||
public void Tick_PPU(int addr)
|
//theres no sense in delaying the IRQ, so its logic must be tied to the separator.
|
||||||
|
//the hint, of course, is that the countdown value is the same.
|
||||||
|
//will someone else try to unify them?
|
||||||
|
int separator_counter;
|
||||||
|
int irq_countdown;
|
||||||
|
|
||||||
|
public void ClockPPU()
|
||||||
{
|
{
|
||||||
ppubus_statecounter++;
|
if (separator_counter > 0)
|
||||||
int state = (addr >> 12) & 1;
|
separator_counter--;
|
||||||
if (ppubus_state == 0 && ppubus_statecounter > 1 && state == 1)
|
|
||||||
|
if (irq_countdown > 0)
|
||||||
{
|
{
|
||||||
ppubus_statecounter = 0;
|
irq_countdown--;
|
||||||
|
if (irq_countdown == 0)
|
||||||
|
{
|
||||||
|
//board.NES.LogLine("ClockIRQ");
|
||||||
ClockIRQ();
|
ClockIRQ();
|
||||||
}
|
}
|
||||||
if (ppubus_state != state)
|
|
||||||
{
|
|
||||||
ppubus_state = state;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddressPPU(int addr)
|
||||||
|
{
|
||||||
|
int a12 = (addr >> 12) & 1;
|
||||||
|
bool rising_edge = (a12 == 1 && a12_old == 0);
|
||||||
|
if (rising_edge)
|
||||||
|
{
|
||||||
|
if (separator_counter > 0)
|
||||||
|
{
|
||||||
|
separator_counter = 15;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
separator_counter = 15;
|
||||||
|
irq_countdown = 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a12_old = a12;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class MMC3_Family_Board_Base : NES.NESBoardBase
|
public abstract class MMC3_Family_Board_Base : NES.NESBoardBase
|
||||||
|
@ -276,7 +307,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public override void AddressPPU(int addr)
|
public override void AddressPPU(int addr)
|
||||||
{
|
{
|
||||||
mmc3.Tick_PPU(addr);
|
mmc3.AddressPPU(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClockPPU()
|
||||||
|
{
|
||||||
|
mmc3.ClockPPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void BaseSetup()
|
protected override void BaseSetup()
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
int use_ram = (bank_1k >> 6) & 1;
|
int use_ram = (bank_1k >> 6) & 1;
|
||||||
if (use_ram == 1)
|
if (use_ram == 1)
|
||||||
{
|
{
|
||||||
mmc3.Tick_PPU(addr);
|
|
||||||
addr = ((bank_1k&0x3f) << 10) | (addr & 0x3FF);
|
addr = ((bank_1k&0x3f) << 10) | (addr & 0x3FF);
|
||||||
addr &= 0x1FFF;
|
addr &= 0x1FFF;
|
||||||
return VRAM[addr];
|
return VRAM[addr];
|
||||||
|
@ -52,7 +51,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
int use_ram = (bank_1k >> 6) & 1;
|
int use_ram = (bank_1k >> 6) & 1;
|
||||||
if (use_ram == 1)
|
if (use_ram == 1)
|
||||||
{
|
{
|
||||||
mmc3.Tick_PPU(addr);
|
|
||||||
addr = ((bank_1k & 0x3f) << 10) | (addr & 0x3FF);
|
addr = ((bank_1k & 0x3f) << 10) | (addr & 0x3FF);
|
||||||
addr &= 0x1FFF;
|
addr &= 0x1FFF;
|
||||||
VRAM[addr] = value;
|
VRAM[addr] = value;
|
||||||
|
|
|
@ -30,7 +30,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public override byte ReadPPU(int addr)
|
public override byte ReadPPU(int addr)
|
||||||
{
|
{
|
||||||
mmc3.Tick_PPU(addr);
|
|
||||||
if (addr < 0x2000)
|
if (addr < 0x2000)
|
||||||
{
|
{
|
||||||
//read patterns from mapper controlled area
|
//read patterns from mapper controlled area
|
||||||
|
@ -44,7 +43,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public override void WritePPU(int addr, byte value)
|
public override void WritePPU(int addr, byte value)
|
||||||
{
|
{
|
||||||
mmc3.Tick_PPU(addr);
|
|
||||||
if (addr < 0x2000)
|
if (addr < 0x2000)
|
||||||
{
|
{
|
||||||
//nothing wired here
|
//nothing wired here
|
||||||
|
|
|
@ -90,6 +90,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
protected void RunCpu(int ppu_cycles)
|
protected void RunCpu(int ppu_cycles)
|
||||||
{
|
{
|
||||||
|
//not being used right now. maybe needed later.
|
||||||
|
//Timestamp += ppu_cycles;
|
||||||
|
|
||||||
int cycles = ppu_cycles;
|
int cycles = ppu_cycles;
|
||||||
if (ppu.PAL)
|
if (ppu.PAL)
|
||||||
cycles *= 15;
|
cycles *= 15;
|
||||||
|
@ -111,7 +114,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
cpu_accumulate -= 48*todo;
|
cpu_accumulate -= 48*todo;
|
||||||
cpu.Execute(todo);
|
cpu.Execute(todo);
|
||||||
apu.Run(todo);
|
apu.Run(todo);
|
||||||
ppu.TickCpu();
|
ppu.PostCpuInstruction(todo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
bool lagged = true;
|
bool lagged = true;
|
||||||
bool islag = false;
|
bool islag = false;
|
||||||
public int Frame { get { return _frame; } set { _frame = value; } }
|
public int Frame { get { return _frame; } set { _frame = value; } }
|
||||||
|
public long Timestamp { get; private set; }
|
||||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||||
public bool IsLagFrame { get { return islag; } }
|
public bool IsLagFrame { get { return islag; } }
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
}
|
}
|
||||||
|
|
||||||
//when the ppu issues a read it goes through here and into the game board
|
//when the ppu issues a read it goes through here and into the game board
|
||||||
public byte ppubus_read(int addr)
|
public byte ppubus_read(int addr, bool ppu)
|
||||||
{
|
{
|
||||||
|
//speculative -- hardware doesnt touch the bus when the PPU is disabled
|
||||||
|
//(without this, smb3 title screen creates garbage when skipped)
|
||||||
|
if (!reg_2001.PPUON && ppu)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
nes.board.AddressPPU(addr);
|
nes.board.AddressPPU(addr);
|
||||||
//apply freeze
|
//apply freeze
|
||||||
if (ppubus_freeze[addr].IsFrozen)
|
if (ppubus_freeze[addr].IsFrozen)
|
||||||
|
@ -91,12 +96,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
nes.cpu.NMI = true;
|
nes.cpu.NMI = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TickCpu()
|
//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 PostCpuInstruction(int todo)
|
||||||
{
|
{
|
||||||
if (NMI_PendingCycles > 0)
|
if (NMI_PendingInstructions > 0)
|
||||||
{
|
{
|
||||||
NMI_PendingCycles--;
|
NMI_PendingInstructions--;
|
||||||
if (NMI_PendingCycles == 0)
|
if (NMI_PendingInstructions <= 0)
|
||||||
{
|
{
|
||||||
TriggerNMI();
|
TriggerNMI();
|
||||||
}
|
}
|
||||||
|
@ -105,17 +113,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
void runppu(int x)
|
void runppu(int x)
|
||||||
{
|
{
|
||||||
//pputime+=x;
|
|
||||||
|
|
||||||
//DON'T LIKE THIS....
|
|
||||||
ppur.status.cycle += x;
|
ppur.status.cycle += x;
|
||||||
while(ppur.status.cycle >= ppur.status.end_cycle)
|
while(ppur.status.cycle >= ppur.status.end_cycle)
|
||||||
ppur.status.cycle -= ppur.status.end_cycle;
|
ppur.status.cycle -= ppur.status.end_cycle;
|
||||||
|
|
||||||
if(x == 0) return;
|
//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++)
|
||||||
|
{
|
||||||
|
//might not actually run a cpu cycle if there are none to be run right now
|
||||||
nes.RunCpu(1);
|
nes.RunCpu(1);
|
||||||
x--;
|
|
||||||
|
|
||||||
if (Reg2002_vblank_active_pending)
|
if (Reg2002_vblank_active_pending)
|
||||||
{
|
{
|
||||||
|
@ -130,9 +136,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
Reg2002_vblank_clear_pending = false;
|
Reg2002_vblank_clear_pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nes.board.ClockPPU();
|
||||||
if (x == 0) return;
|
}
|
||||||
nes.RunCpu(x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//hack
|
//hack
|
||||||
|
|
|
@ -296,7 +296,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
Bit Reg2002_vblank_active; //Vertical blank start (0: has not started; 1: has started)
|
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_active_pending; //set of Reg2002_vblank_active is pending
|
||||||
bool Reg2002_vblank_clear_pending; //ppu's clear of vblank flag is pending
|
bool Reg2002_vblank_clear_pending; //ppu's clear of vblank flag is pending
|
||||||
int NMI_PendingCycles;
|
int NMI_PendingInstructions;
|
||||||
byte PPUGenLatch;
|
byte PPUGenLatch;
|
||||||
public PPUREGS ppur;
|
public PPUREGS ppur;
|
||||||
public Reg_2000 reg_2000;
|
public Reg_2000 reg_2000;
|
||||||
|
@ -330,7 +330,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
if (!reg_2000.vblank_nmi_gen & ((value & 0x80) != 0) && (Reg2002_vblank_active) && !Reg2002_vblank_clear_pending)
|
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
|
//if we just unleashed the vblank interrupt then activate it now
|
||||||
NMI_PendingCycles = 2;
|
NMI_PendingInstructions = 2;
|
||||||
}
|
}
|
||||||
reg_2000.Value = value;
|
reg_2000.Value = value;
|
||||||
}
|
}
|
||||||
|
@ -465,7 +465,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
byte ret = VRAMBuffer;
|
byte ret = VRAMBuffer;
|
||||||
|
|
||||||
//in any case, we read from the ppu bus
|
//in any case, we read from the ppu bus
|
||||||
VRAMBuffer = ppubus_read(addr);
|
VRAMBuffer = ppubus_read(addr,false);
|
||||||
|
|
||||||
//but reads from the palette are implemented in the PPU and return immediately
|
//but reads from the palette are implemented in the PPU and return immediately
|
||||||
if ((addr & 0x3F00) == 0x3F00)
|
if ((addr & 0x3F00) == 0x3F00)
|
||||||
|
|
|
@ -27,11 +27,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
void Read_bgdata(ref BGDataRecord bgdata) {
|
void Read_bgdata(ref BGDataRecord bgdata) {
|
||||||
int addr = ppur.get_ntread();
|
int addr = ppur.get_ntread();
|
||||||
bgdata.nt = ppubus_read(addr);
|
bgdata.nt = ppubus_read(addr, true);
|
||||||
runppu(kFetchTime);
|
runppu(kFetchTime);
|
||||||
|
|
||||||
addr = ppur.get_atread();
|
addr = ppur.get_atread();
|
||||||
byte at = ppubus_read(addr);
|
byte at = ppubus_read(addr, true);
|
||||||
|
|
||||||
//modify at to get appropriate palette shift
|
//modify at to get appropriate palette shift
|
||||||
if((ppur.vt&2)!=0) at >>= 4;
|
if((ppur.vt&2)!=0) at >>= 4;
|
||||||
|
@ -53,10 +53,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
runppu(1);
|
runppu(1);
|
||||||
|
|
||||||
addr = ppur.get_ptread(bgdata.nt);
|
addr = ppur.get_ptread(bgdata.nt);
|
||||||
bgdata.pt_0 = ppubus_read(addr);
|
bgdata.pt_0 = ppubus_read(addr, true);
|
||||||
runppu(kFetchTime);
|
runppu(kFetchTime);
|
||||||
addr |= 8;
|
addr |= 8;
|
||||||
bgdata.pt_1 = ppubus_read(addr);
|
bgdata.pt_1 = ppubus_read(addr, true);
|
||||||
runppu(kFetchTime);
|
runppu(kFetchTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,11 +380,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
//pattern table fetches
|
//pattern table fetches
|
||||||
int addr = patternAddress;
|
int addr = patternAddress;
|
||||||
oam->patterns[0] = ppubus_read(addr);
|
oam->patterns[0] = ppubus_read(addr, true);
|
||||||
if (realSprite) runppu(kFetchTime);
|
if (realSprite) runppu(kFetchTime);
|
||||||
|
|
||||||
addr += 8;
|
addr += 8;
|
||||||
oam->patterns[1] = ppubus_read(addr);
|
oam->patterns[1] = ppubus_read(addr, true);
|
||||||
if (realSprite) runppu(kFetchTime);
|
if (realSprite) runppu(kFetchTime);
|
||||||
|
|
||||||
//hflip
|
//hflip
|
||||||
|
@ -405,7 +405,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
//screen (or basically, the first nametable address that will be accessed when
|
//screen (or basically, the first nametable address that will be accessed when
|
||||||
//the PPU is fetching background data on the next scanline).
|
//the PPU is fetching background data on the next scanline).
|
||||||
//(not implemented yet)
|
//(not implemented yet)
|
||||||
runppu(kFetchTime * 2);
|
|
||||||
if (sl == 0)
|
if (sl == 0)
|
||||||
{
|
{
|
||||||
if (idleSynch && reg_2001.show_bg && !PAL)
|
if (idleSynch && reg_2001.show_bg && !PAL)
|
||||||
|
@ -421,6 +420,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
for (int xt = 0; xt < 2; xt++)
|
for (int xt = 0; xt < 2; xt++)
|
||||||
Read_bgdata(ref bgdata[xt]);
|
Read_bgdata(ref bgdata[xt]);
|
||||||
|
|
||||||
|
runppu(kFetchTime * 2);
|
||||||
|
|
||||||
//After memory access 170, the PPU simply rests for 4 cycles (or the
|
//After memory access 170, the PPU simply rests for 4 cycles (or the
|
||||||
//equivelant of half a memory access cycle) before repeating the whole
|
//equivelant of half a memory access cycle) before repeating the whole
|
||||||
//pixel/scanline rendering process. If the scanline being rendered is the very
|
//pixel/scanline rendering process. If the scanline being rendered is the very
|
||||||
|
|
|
@ -63,8 +63,8 @@ namespace BizHawk.MultiClient
|
||||||
int nt = ppu.ppubus_peek(ntbyte_ptr + 0x2000);
|
int nt = ppu.ppubus_peek(ntbyte_ptr + 0x2000);
|
||||||
|
|
||||||
int at = ppu.ppubus_peek(atbyte_ptr + 0x2000);
|
int at = ppu.ppubus_peek(atbyte_ptr + 0x2000);
|
||||||
if((ty&1)!=0) at >>= 4;
|
if((ty&2)!=0) at >>= 4;
|
||||||
if((tx&1)!=0) at >>= 2;
|
if((tx&2)!=0) at >>= 2;
|
||||||
at &= 0x03;
|
at &= 0x03;
|
||||||
at <<= 2;
|
at <<= 2;
|
||||||
|
|
||||||
|
@ -74,6 +74,10 @@ namespace BizHawk.MultiClient
|
||||||
int pt_0 = ppu.ppubus_peek(pt_addr);
|
int pt_0 = ppu.ppubus_peek(pt_addr);
|
||||||
int pt_1 = ppu.ppubus_peek(pt_addr + 8);
|
int pt_1 = ppu.ppubus_peek(pt_addr + 8);
|
||||||
int pixel = ((pt_0 >> (7 - bgpx)) & 1) | (((pt_1 >> (7 - bgpx)) & 1) << 1);
|
int pixel = ((pt_0 >> (7 - bgpx)) & 1) | (((pt_1 >> (7 - bgpx)) & 1) << 1);
|
||||||
|
|
||||||
|
//if the pixel is transparent, draw the backdrop color
|
||||||
|
//TODO - consider making this optional? nintendulator does it and fceux doesnt need to do it due to buggy palette logic which creates the same effect
|
||||||
|
if(pixel!=0)
|
||||||
pixel |= at;
|
pixel |= at;
|
||||||
|
|
||||||
pixel = ppu.PALRAM[pixel];
|
pixel = ppu.PALRAM[pixel];
|
||||||
|
|
|
@ -115,15 +115,6 @@ namespace BizHawk.MultiClient
|
||||||
}
|
}
|
||||||
PatternView.pattern.UnlockBits(bmpdata);
|
PatternView.pattern.UnlockBits(bmpdata);
|
||||||
PatternView.Refresh();
|
PatternView.Refresh();
|
||||||
|
|
||||||
//Nametable viewer
|
|
||||||
for (int i = 0; i < 30; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < 32; j++)
|
|
||||||
{
|
|
||||||
int v = Nes.ppu.ppubus_read(0x2000 + i + j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NESPPU_Load(object sender, EventArgs e)
|
private void NESPPU_Load(object sender, EventArgs e)
|
||||||
|
|
Loading…
Reference in New Issue