NES: ppu view internal infrastructure
This commit is contained in:
parent
bb85875b94
commit
50704247fa
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
bool BGBaseHigh { get; }
|
||||
|
||||
/// <summary>
|
||||
/// true if sp tile indexes start at 0x1000 instead of 0x0000 (8x8 mode only)
|
||||
/// </summary>
|
||||
bool SPBaseHigh { get; }
|
||||
|
||||
/// <summary>
|
||||
/// true if sprites are 8x16
|
||||
/// </summary>
|
||||
bool SPTall { get; }
|
||||
|
||||
/// <summary>
|
||||
/// get the first 0x3000 bytes of ppu data
|
||||
/// </summary>
|
||||
|
@ -33,6 +44,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
/// <returns></returns>
|
||||
byte[] GetPalRam();
|
||||
|
||||
/// <summary>
|
||||
/// returns the object attribute memory
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
byte[] GetOam();
|
||||
|
||||
/// <summary>
|
||||
/// return one byte of PPU bus data
|
||||
/// </summary>
|
||||
|
@ -56,5 +73,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
byte[] GetExRam();
|
||||
|
||||
/// <summary>
|
||||
/// get memory domain for chr rom; return null if RAM or other N/A. for direct viewing of ROM tiles.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
MemoryDomain GetCHRROM();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue