diff --git a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs
index 85f2863b81..cdc82c0893 100644
--- a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs
+++ b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs
@@ -30,6 +30,8 @@ namespace BizHawk.Client.EmuHawk
private NES _nes { get; set; }
[RequiredService]
private INESPPUViewable xxx { get; set; }
+ [RequiredService]
+ private IEmulator _emu { get; set; }
public NesPPU()
{
@@ -89,10 +91,10 @@ namespace BizHawk.Client.EmuHawk
{
return (byte)((_ppuBus[address] >> (7 - bit)) & 1);
}
-
+
private bool CheckChange()
{
- var changed = false;
+ bool changed = false;
for (var i = 0; i < 0x20; i++)
{
_palRamPrev[i] = _palRam[i];
@@ -121,7 +123,7 @@ namespace BizHawk.Client.EmuHawk
return changed;
}
- private unsafe void DrawPatternView(PatternViewer dest, byte[] src)
+ private unsafe void DrawPatternView(PatternViewer dest, byte[] src, int[] FinalPalette, byte[] PALRAM)
{
int b0;
int b1;
@@ -133,7 +135,7 @@ namespace BizHawk.Client.EmuHawk
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb);
- var framebuf = (int*)bmpdata.Scan0.ToPointer();
+ int* framebuf = (int*)bmpdata.Scan0;
for (int z = 0; z < 2; z++)
{
int pal;
@@ -152,7 +154,7 @@ namespace BizHawk.Client.EmuHawk
b1 = (byte)((src[address + 8] >> (7 - x)) & 1);
value = (byte)(b0 + (b1 << 1));
- cvalue = _nes.LookupColor(_nes.ppu.PALRAM[value + (pal << 2)]);
+ cvalue = FinalPalette[PALRAM[value + (pal << 2)]];
int adr = (x + (j << 3)) + (y + (i << 3)) * (bmpdata.Stride >> 2);
framebuf[adr + (z << 7)] = cvalue;
}
@@ -172,105 +174,109 @@ namespace BizHawk.Client.EmuHawk
return;
}
- if (_nes.Frame % RefreshRate.Value == 0 || now)
+ if (_emu.Frame % RefreshRate.Value != 0 && !now)
+ return;
+
+ byte[] PALRAM = xxx.GetPalRam();
+ int[] FinalPalette = xxx.GetPalette();
+ byte[] OAM = xxx.GetOam();
+
+ int b0;
+ int b1;
+ byte value;
+ int cvalue;
+
+ if (CheckChange())
{
- int b0;
- int b1;
- byte value;
- int cvalue;
+ _forceChange = false;
- if (CheckChange())
+ // Pattern Viewer
+ for (var i = 0; i < 16; i++)
{
- _forceChange = false;
-
- // Pattern Viewer
- for (var i = 0; i < 16; i++)
- {
- PaletteView.BgPalettesPrev[i].Value = PaletteView.BgPalettes[i].Value;
- PaletteView.SpritePalettesPrev[i].Value = PaletteView.SpritePalettes[i].Value;
- PaletteView.BgPalettes[i].Value = _nes.LookupColor(_nes.ppu.PALRAM[PaletteView.BgPalettes[i].Address]);
- PaletteView.SpritePalettes[i].Value = _nes.LookupColor(_nes.ppu.PALRAM[PaletteView.SpritePalettes[i].Address]);
- }
-
- if (PaletteView.HasChanged())
- {
- PaletteView.Refresh();
- }
-
- DrawPatternView(PatternView, _ppuBus);
+ PaletteView.BgPalettesPrev[i].Value = PaletteView.BgPalettes[i].Value;
+ PaletteView.SpritePalettesPrev[i].Value = PaletteView.SpritePalettes[i].Value;
+ PaletteView.BgPalettes[i].Value = FinalPalette[PALRAM[PaletteView.BgPalettes[i].Address]];
+ PaletteView.SpritePalettes[i].Value = FinalPalette[PALRAM[PaletteView.SpritePalettes[i].Address]];
}
- var bmpdata2 = SpriteView.sprites.LockBits(new Rectangle(new Point(0, 0), SpriteView.sprites.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
- var framebuf2 = (int*)bmpdata2.Scan0.ToPointer();
-
- int pt_add = _nes.ppu.reg_2000.obj_pattern_hi ? 0x1000 : 0;
- bool is8x16 = _nes.ppu.reg_2000.obj_size_16;
-
-
- // Sprite Viewer
- for (int n = 0; n < 4; n++)
+ if (PaletteView.HasChanged())
{
- for (int r = 0; r < 16; r++)
+ PaletteView.Refresh();
+ }
+
+ DrawPatternView(PatternView, _ppuBus, FinalPalette, PALRAM);
+ }
+
+ var bmpdata2 = SpriteView.sprites.LockBits(new Rectangle(new Point(0, 0), SpriteView.sprites.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+ var framebuf2 = (int*)bmpdata2.Scan0.ToPointer();
+
+ int pt_add = xxx.SPBaseHigh ? 0x1000 : 0;
+ bool is8x16 = xxx.SPTall;
+
+
+ // Sprite Viewer
+ for (int n = 0; n < 4; n++)
+ {
+ for (int r = 0; r < 16; r++)
+ {
+ int BaseAddr = (r << 2) + (n << 6);
+ int TileNum = OAM[BaseAddr + 1];
+ int patternAddr;
+
+ if (is8x16)
{
- int BaseAddr = (r << 2) + (n << 6);
- int TileNum = _nes.ppu.OAM[BaseAddr + 1];
- int patternAddr;
+ patternAddr = (TileNum >> 1) * 0x20;
+ patternAddr += 0x1000 * (TileNum & 1);
+ }
+ else
+ {
+ patternAddr = TileNum * 0x10;
+ patternAddr += pt_add;
+ }
+
+ int Attributes = OAM[BaseAddr + 2];
+ int Palette = Attributes & 0x03;
+
+ for (int x = 0; x < 8; x++)
+ {
+ for (int y = 0; y < 8; y++)
+ {
+ int address = patternAddr + y;
+ b0 = (byte)((_ppuBus[address] >> (7 - x)) & 1);
+ b1 = (byte)((_ppuBus[address + 8] >> (7 - x)) & 1);
+ value = (byte)(b0 + (b1 << 1));
+ cvalue = FinalPalette[PALRAM[16 + value + (Palette << 2)]];
+
+ int adr = (x + (r * 16)) + (y + (n * 24)) * (bmpdata2.Stride >> 2);
+ framebuf2[adr] = cvalue;
+ }
if (is8x16)
{
- patternAddr = (TileNum >> 1) * 0x20;
- patternAddr += 0x1000 * (TileNum & 1);
- }
- else
- {
- patternAddr = TileNum * 0x10;
- patternAddr += pt_add;
- }
-
- int Attributes = _nes.ppu.OAM[BaseAddr + 2];
- int Palette = Attributes & 0x03;
-
- for (int x = 0; x < 8; x++)
- {
+ patternAddr += 0x10;
for (int y = 0; y < 8; y++)
{
int address = patternAddr + y;
b0 = (byte)((_ppuBus[address] >> (7 - x)) & 1);
b1 = (byte)((_ppuBus[address + 8] >> (7 - x)) & 1);
value = (byte)(b0 + (b1 << 1));
- cvalue = _nes.LookupColor(_nes.ppu.PALRAM[16 + value + (Palette << 2)]);
+ cvalue = FinalPalette[PALRAM[16 + value + (Palette << 2)]];
- int adr = (x + (r * 16)) + (y + (n * 24)) * (bmpdata2.Stride >> 2);
+ int adr = (x + (r << 4)) + ((y + 8) + (n * 24)) * (bmpdata2.Stride >> 2);
framebuf2[adr] = cvalue;
}
- if (is8x16)
- {
- patternAddr += 0x10;
- for (int y = 0; y < 8; y++)
- {
- int address = patternAddr + y;
- b0 = (byte)((_ppuBus[address] >> (7 - x)) & 1);
- b1 = (byte)((_ppuBus[address + 8] >> (7 - x)) & 1);
- value = (byte)(b0 + (b1 << 1));
- cvalue = _nes.LookupColor(_nes.ppu.PALRAM[16 + value + (Palette << 2)]);
-
- int adr = (x + (r << 4)) + ((y+8) + (n * 24)) * (bmpdata2.Stride >> 2);
- framebuf2[adr] = cvalue;
- }
-
- patternAddr -= 0x10;
- }
+ patternAddr -= 0x10;
}
}
}
-
- SpriteView.sprites.UnlockBits(bmpdata2);
- SpriteView.Refresh();
-
- HandleSpriteViewMouseMove(SpriteView.PointToClient(MousePosition));
- HandlePaletteViewMouseMove(PaletteView.PointToClient(MousePosition));
}
+
+ SpriteView.sprites.UnlockBits(bmpdata2);
+ SpriteView.Refresh();
+
+ HandleSpriteViewMouseMove(SpriteView.PointToClient(MousePosition));
+ HandlePaletteViewMouseMove(PaletteView.PointToClient(MousePosition));
}
private void ClearDetails()
@@ -609,12 +615,14 @@ namespace BizHawk.Client.EmuHawk
if (e.X >= SpriteView.ClientRectangle.Right) return;
if (e.Y >= SpriteView.ClientRectangle.Bottom) return;
- bool is8x16 = _nes.ppu.reg_2000.obj_size_16;
+ byte[] OAM = xxx.GetOam();
+
+ bool is8x16 = xxx.SPTall;
var spriteNumber = ((e.Y / 24) * 16) + (e.X / 16);
- int x = _nes.ppu.OAM[(spriteNumber * 4) + 3];
- int y = _nes.ppu.OAM[spriteNumber * 4];
- var color = _nes.ppu.OAM[(spriteNumber * 4) + 2] & 0x03;
- var attributes = _nes.ppu.OAM[(spriteNumber * 4) + 2];
+ int x = OAM[(spriteNumber * 4) + 3];
+ int y = OAM[spriteNumber * 4];
+ var color = OAM[(spriteNumber * 4) + 2] & 0x03;
+ var attributes = OAM[(spriteNumber * 4) + 2];
var flags = "Flags: ";
int h = GetBit(attributes, 6);
@@ -639,7 +647,7 @@ namespace BizHawk.Client.EmuHawk
flags += "Front";
}
- int tile = _nes.ppu.OAM[spriteNumber * 4 + 1];
+ int tile = OAM[spriteNumber * 4 + 1];
if (is8x16)
{
if ((tile & 1) != 0)
@@ -702,15 +710,17 @@ namespace BizHawk.Client.EmuHawk
var bmp = new Bitmap(64, 64);
var g = Graphics.FromImage(bmp);
+ byte[] PALRAM = xxx.GetPalRam();
+
if (baseAddr == 0x3F00)
{
- val = _nes.ppu.PALRAM[PaletteView.BgPalettes[column].Address];
+ val = PALRAM[PaletteView.BgPalettes[column].Address];
ValueLabel.Text = "ID: BG" + (column / 4);
g.FillRectangle(new SolidBrush(PaletteView.BgPalettes[column].Color), 0, 0, 64, 64);
}
else
{
- val = _nes.ppu.PALRAM[PaletteView.SpritePalettes[column].Address];
+ val = PALRAM[PaletteView.SpritePalettes[column].Address];
ValueLabel.Text = "ID: SPR" + (column / 4);
g.FillRectangle(new SolidBrush(PaletteView.SpritePalettes[column].Color), 0, 0, 64, 64);
}
@@ -784,16 +794,16 @@ namespace BizHawk.Client.EmuHawk
tile += (e.Y / 8) * 16;
var usage = "Usage: ";
- if ((_nes.ppu.reg_2000.Value & 0x10) << 4 == ((address >> 4) & 0x100))
+ if (xxx.BGBaseHigh == address >= 0x1000) // bghigh
{
usage = "BG";
}
- else if (((_nes.ppu.reg_2000.Value & 0x08) << 5) == ((address >> 4) & 0x100))
+ else if (xxx.SPBaseHigh == address >= 0x1000) // sphigh
{
usage = "SPR";
}
- if ((_nes.ppu.reg_2000.Value & 0x20) > 0)
+ if (xxx.SPTall) // spbig
{
usage += " (SPR16)";
}
@@ -841,7 +851,7 @@ namespace BizHawk.Client.EmuHawk
private void CHRROMViewReload()
{
- CHRROM = _nes.MemoryDomains["CHR VROM"];
+ CHRROM = xxx.GetCHRROM();
if (CHRROM == null)
{
numericUpDownCHRROMBank.Enabled = false;
@@ -865,7 +875,7 @@ namespace BizHawk.Client.EmuHawk
for (int i = 0; i < 8192; i++)
chrromcache[i] = CHRROM.PeekByte(offs + i);
- DrawPatternView(CHRROMView, chrromcache);
+ DrawPatternView(CHRROMView, chrromcache, xxx.GetPalette(), xxx.GetPalRam());
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs
index ce0feadb49..3b815c0217 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
@@ -21,6 +22,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
///
bool BGBaseHigh { get; }
+ ///
+ /// true if sp tile indexes start at 0x1000 instead of 0x0000 (8x8 mode only)
+ ///
+ bool SPBaseHigh { get; }
+
+ ///
+ /// true if sprites are 8x16
+ ///
+ bool SPTall { get; }
+
///
/// get the first 0x3000 bytes of ppu data
///
@@ -33,6 +44,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
///
byte[] GetPalRam();
+ ///
+ /// returns the object attribute memory
+ ///
+ ///
+ byte[] GetOam();
+
///
/// return one byte of PPU bus data
///
@@ -56,5 +73,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
///
///
byte[] GetExRam();
+
+ ///
+ /// get memory domain for chr rom; return null if RAM or other N/A. for direct viewing of ROM tiles.
+ ///
+ ///
+ MemoryDomain GetCHRROM();
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs
index 691993979e..5bb897f034 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
@@ -17,6 +18,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
get { return ppu.reg_2000.bg_pattern_hi; }
}
+ public bool SPBaseHigh
+ {
+ get { return ppu.reg_2000.obj_pattern_hi; }
+ }
+
+ public bool SPTall
+ {
+ get { return ppu.reg_2000.obj_size_16; }
+ }
+
public byte[] GetPPUBus()
{
byte[] ret = new byte[0x3000];
@@ -32,6 +43,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
return ppu.PALRAM;
}
+ public byte[] GetOam()
+ {
+ return ppu.OAM;
+ }
+
public byte PeekPPU(int addr)
{
return board.PeekPPU(addr);
@@ -65,5 +81,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
throw new InvalidOperationException();
}
}
+
+ public MemoryDomain GetCHRROM()
+ {
+ return MemoryDomains["CHR VROM"];
+ }
}
}