[NES] make pattern view run at a reasonable speed

This commit is contained in:
zeromus 2011-03-13 01:09:35 +00:00
parent e015be999a
commit 44619d747c
1 changed files with 147 additions and 143 deletions

View File

@ -12,167 +12,171 @@ using System.Diagnostics;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public partial class NESPPU : Form public partial class NESPPU : Form
{ {
//TODO: //TODO:
//Pattern viewer - //Pattern viewer -
// Row interleaving // Row interleaving
// Proper color reading // Proper color reading
// 2nd table // 2nd table
// option for 2x view (and 4x?) // option for 2x view (and 4x?)
// Mouse over events // Mouse over events
// user option to select different palettes // user option to select different palettes
//Sprite viewer //Sprite viewer
//Nametable viewer //Nametable viewer
int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired
int defaultHeight; int defaultHeight;
NES Nes; NES Nes;
public NESPPU() public NESPPU()
{ {
InitializeComponent(); InitializeComponent();
Closing += (o, e) => SaveConfigSettings(); Closing += (o, e) => SaveConfigSettings();
} }
private void SaveConfigSettings() private void SaveConfigSettings()
{ {
Global.Config.NESPPUWndx = this.Location.X; Global.Config.NESPPUWndx = this.Location.X;
Global.Config.NESPPUWndy = this.Location.Y; Global.Config.NESPPUWndy = this.Location.Y;
} }
public void Restart() public void Restart()
{ {
if (!(Global.Emulator is NES)) this.Close(); if (!(Global.Emulator is NES)) this.Close();
Nes = Global.Emulator as NES; Nes = Global.Emulator as NES;
} }
private void LoadConfigSettings() private void LoadConfigSettings()
{ {
defaultWidth = Size.Width; //Save these first so that the user can restore to its original size defaultWidth = Size.Width; //Save these first so that the user can restore to its original size
defaultHeight = Size.Height; defaultHeight = Size.Height;
if (Global.Config.NESPPUWndx >= 0 && Global.Config.NESPPUWndy >= 0) if (Global.Config.NESPPUWndx >= 0 && Global.Config.NESPPUWndy >= 0)
Location = new Point(Global.Config.NESPPUWndx, Global.Config.NESPPUWndy); Location = new Point(Global.Config.NESPPUWndx, Global.Config.NESPPUWndy);
} }
private byte GetBit(int address, int bit) private byte GetBit(int address, int bit)
{ {
byte value = Nes.ppu.ppubus_read(address); byte value = Nes.ppu.ppubus_read(address);
return (byte)(((value >> (7 - bit)) & 1)); return (byte)(((value >> (7 - bit)) & 1));
} }
public void UpdateValues() public unsafe void UpdateValues()
{ {
if (!(Global.Emulator is NES)) return; if (!(Global.Emulator is NES)) return;
if (!this.IsHandleCreated || this.IsDisposed) return; if (!this.IsHandleCreated || this.IsDisposed) return;
//Pattern Viewer //Pattern Viewer
for (int x = 0; x < 16; x++) for (int x = 0; x < 16; x++)
{ {
PaletteView.bgPalettes[x].SetValue(Nes.ConvertColor(Nes.ppu.PALRAM[PaletteView.bgPalettes[x].address])); PaletteView.bgPalettes[x].SetValue(Nes.ConvertColor(Nes.ppu.PALRAM[PaletteView.bgPalettes[x].address]));
PaletteView.spritePalettes[x].SetValue(Nes.ppu.PALRAM[PaletteView.spritePalettes[x].address]); PaletteView.spritePalettes[x].SetValue(Nes.ppu.PALRAM[PaletteView.spritePalettes[x].address]);
} }
PaletteView.Refresh(); PaletteView.Refresh();
//Pattern Viewer //Pattern Viewer
for (int i = 0; i < 16; i++) System.Drawing.Imaging.BitmapData bmpdata = PatternView.pattern.LockBits(new Rectangle(new Point(0, 0), PatternView.pattern.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
{ int* framebuf = (int*)bmpdata.Scan0.ToPointer();
for (int j = 0; j < 16; j++) for (int i = 0; i < 16; i++)
{ {
for (int x = 0; x < 8; x++) for (int j = 0; j < 16; j++)
{ {
for (int y = 0; y < 8; y++) for (int x = 0; x < 8; x++)
{ {
Bit b0 = new Bit(); for (int y = 0; y < 8; y++)
Bit b1 = new Bit(); {
Bit b0 = new Bit();
Bit b1 = new Bit();
Bit b2 = new Bit(); Bit b2 = new Bit();
Bit b3 = new Bit(); //2nd page of patterns Bit b3 = new Bit(); //2nd page of patterns
b0 = GetBit((i * 256) + (j * 16) + y + b0 * 8, x); b0 = GetBit((i * 256) + (j * 16) + y + b0 * 8, x);
b1 = GetBit((i * 256) + (j * 16) + y + b1 * 8, x); b1 = GetBit((i * 256) + (j * 16) + y + b1 * 8, x);
b2 = GetBit(0x1000 + (i * 256) + (j * 16) + y + b2 * 8, x); b2 = GetBit(0x1000 + (i * 256) + (j * 16) + y + b2 * 8, x);
b3 = GetBit(0x1000 + (i * 256) + (j * 16) + y + b3 * 8, x); b3 = GetBit(0x1000 + (i * 256) + (j * 16) + y + b3 * 8, x);
byte value = (byte)(b0 + (b1 * 2)); byte value = (byte)(b0 + (b1 * 2));
byte value2 = (byte)(b2 + (b3 * 2)); byte value2 = (byte)(b2 + (b3 * 2));
value += Nes.ppu.PALRAM[value + (0*4)]; //TODO: 0 = user selection 0-7 value += Nes.ppu.PALRAM[value + (0 * 4)]; //TODO: 0 = user selection 0-7
value2 += Nes.ppu.PALRAM[value2 + (0*4)]; //TODO: 0 = user selection 0-7 value2 += Nes.ppu.PALRAM[value2 + (0 * 4)]; //TODO: 0 = user selection 0-7
int cvalue = Nes.ConvertColor(value); int cvalue = Nes.ConvertColor(value);
int cvalue2 = Nes.ConvertColor(value2); int cvalue2 = Nes.ConvertColor(value2);
unchecked unchecked
{ {
cvalue = cvalue | (int)0xFF000000; cvalue = cvalue | (int)0xFF000000;
cvalue2 = cvalue2 | (int)0xFF000000; cvalue2 = cvalue2 | (int)0xFF000000;
} }
Color color = Color.FromArgb(cvalue); Color color = Color.FromArgb(cvalue);
Color color2 = Color.FromArgb(cvalue2); Color color2 = Color.FromArgb(cvalue2);
PatternView.pattern.SetPixel(x + (j*8), y + (i*8), color); int adr = (x + (j * 8)) + (y + (i * 8)) * (bmpdata.Stride / 4);
PatternView.pattern.SetPixel(128 + x + (j * 8), y + (i * 8), color2); framebuf[adr] = color.ToArgb();
} framebuf[adr + 128] = color2.ToArgb();
} }
} }
} }
PatternView.Refresh(); }
} PatternView.pattern.UnlockBits(bmpdata);
PatternView.Refresh();
}
private void NESPPU_Load(object sender, EventArgs e) private void NESPPU_Load(object sender, EventArgs e)
{ {
LoadConfigSettings(); LoadConfigSettings();
Nes = Global.Emulator as NES; Nes = Global.Emulator as NES;
ClearDetails(); ClearDetails();
} }
private void ClearDetails() private void ClearDetails()
{ {
SectionLabel.Text = ""; SectionLabel.Text = "";
AddressLabel.Text = ""; AddressLabel.Text = "";
ValueLabel.Text = ""; ValueLabel.Text = "";
//TODO: more info labels //TODO: more info labels
} }
private void PaletteView_MouseLeave(object sender, EventArgs e) private void PaletteView_MouseLeave(object sender, EventArgs e)
{ {
ClearDetails(); ClearDetails();
} }
private void PaletteView_MouseEnter(object sender, EventArgs e) private void PaletteView_MouseEnter(object sender, EventArgs e)
{ {
SectionLabel.Text = "Section: Palette"; SectionLabel.Text = "Section: Palette";
} }
private void PaletteView_MouseMove(object sender, MouseEventArgs e) private void PaletteView_MouseMove(object sender, MouseEventArgs e)
{ {
int baseAddr = 0x3F00; int baseAddr = 0x3F00;
if (e.Y > 16) if (e.Y > 16)
baseAddr += 16; baseAddr += 16;
int column = (e.X - PaletteView.Location.X) / 16; int column = (e.X - PaletteView.Location.X) / 16;
int addr = column + baseAddr; int addr = column + baseAddr;
AddressLabel.Text = "Address: 0x" + String.Format("{0:X4}", addr, NumberStyles.HexNumber); AddressLabel.Text = "Address: 0x" + String.Format("{0:X4}", addr, NumberStyles.HexNumber);
int val; int val;
if (baseAddr == 0x3F00) if (baseAddr == 0x3F00)
val = PaletteView.bgPalettes[column].GetValue(); val = PaletteView.bgPalettes[column].GetValue();
else else
val = PaletteView.spritePalettes[column].GetValue(); val = PaletteView.spritePalettes[column].GetValue();
ValueLabel.Text = "Color: 0x" + String.Format("{0:X2}", val, NumberStyles.HexNumber); ValueLabel.Text = "Color: 0x" + String.Format("{0:X2}", val, NumberStyles.HexNumber);
} }
private void autoloadToolStripMenuItem_Click(object sender, EventArgs e) private void autoloadToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Global.Config.AutoLoadNESPPU ^= true; Global.Config.AutoLoadNESPPU ^= true;
} }
private void saveWindowPositionToolStripMenuItem_Click(object sender, EventArgs e) private void saveWindowPositionToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Global.Config.NESPPUSaveWindowPosition ^= true; Global.Config.NESPPUSaveWindowPosition ^= true;
} }
private void toolStripDropDownButton1_DropDownOpened(object sender, EventArgs e) private void toolStripDropDownButton1_DropDownOpened(object sender, EventArgs e)
{ {
autoloadToolStripMenuItem.Checked = Global.Config.AutoLoadNESPPU; autoloadToolStripMenuItem.Checked = Global.Config.AutoLoadNESPPU;
saveWindowPositionToolStripMenuItem.Checked = Global.Config.NESPPUSaveWindowPosition; saveWindowPositionToolStripMenuItem.Checked = Global.Config.NESPPUSaveWindowPosition;
} }
} }
} }