[NES] ntview: add ability to view individual nametables zoomed in

This commit is contained in:
zeromus 2011-06-10 08:10:16 +00:00
parent 51367f58c7
commit 4bf905c055
5 changed files with 262 additions and 137 deletions

View File

@ -15,10 +15,11 @@ namespace BizHawk
public void* ptr; public void* ptr;
public byte* byteptr; public byte* byteptr;
public int len; public int len;
public int itemsize;
public static CBuffer<T> malloc(int amt) public static CBuffer<T> malloc(int amt, int itemsize)
{ {
return new CBuffer<T>(amt); return new CBuffer<T>(amt, itemsize);
} }
public void Write08(uint addr, byte val) { byteptr[addr] = val; } public void Write08(uint addr, byte val) { byteptr[addr] = val; }
@ -38,21 +39,25 @@ namespace BizHawk
public uint Read32(int addr) { return *(uint*)(byteptr + addr); } public uint Read32(int addr) { return *(uint*)(byteptr + addr); }
public ulong Read64(int addr) { return *(ulong*)(byteptr + addr); } public ulong Read64(int addr) { return *(ulong*)(byteptr + addr); }
public CBuffer(T[] arr) public CBuffer(T[] arr, int itemsize)
{ {
this.itemsize = itemsize;
len = arr.Length; len = arr.Length;
this.arr = arr; this.arr = arr;
hnd = GCHandle.Alloc(arr, GCHandleType.Pinned); hnd = GCHandle.Alloc(arr, GCHandleType.Pinned);
ptr = hnd.AddrOfPinnedObject().ToPointer(); ptr = hnd.AddrOfPinnedObject().ToPointer();
byteptr = (byte*)ptr; byteptr = (byte*)ptr;
Util.memset(byteptr, 0, len*itemsize);
} }
public CBuffer(int amt) public CBuffer(int amt, int itemsize)
{ {
this.itemsize = itemsize;
len = amt; len = amt;
arr = new T[amt]; arr = new T[amt];
hnd = GCHandle.Alloc(arr, GCHandleType.Pinned); hnd = GCHandle.Alloc(arr, GCHandleType.Pinned);
ptr = hnd.AddrOfPinnedObject().ToPointer(); ptr = hnd.AddrOfPinnedObject().ToPointer();
byteptr = (byte*)ptr; byteptr = (byte*)ptr;
Util.memset(byteptr, 0, len * itemsize);
} }
public void Dispose() public void Dispose()
@ -67,8 +72,8 @@ namespace BizHawk
public class ByteBuffer : CBuffer<byte> public class ByteBuffer : CBuffer<byte>
{ {
public ByteBuffer(int amt) : base(amt) { } public ByteBuffer(int amt) : base(amt,1) { }
public ByteBuffer(byte[] arr) : base(arr) { } public ByteBuffer(byte[] arr) : base(arr,1) { }
public byte this[int index] public byte this[int index]
{ {
#if DEBUG #if DEBUG
@ -83,16 +88,16 @@ namespace BizHawk
public class IntBuffer : CBuffer<int> public class IntBuffer : CBuffer<int>
{ {
public IntBuffer(int amt) : base(amt) { } public IntBuffer(int amt) : base(amt, 4) { }
public IntBuffer(int[] arr) : base(arr) { } public IntBuffer(int[] arr) : base(arr,4) { }
public int this[int index] public int this[int index]
{ {
#if DEBUG #if DEBUG
get { return arr[index]; } get { return arr[index]; }
set { arr[index] = value; } set { arr[index] = value; }
#else #else
set { Write32(index, (uint) value); } set { Write32(index<<2, (uint) value); }
get { return (int)Read32(index);} get { return (int)Read32(index<<2);}
#endif #endif
} }
} }

View File

@ -156,14 +156,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
else else
bank_1k = b_banks_1k[bank_1k]; bank_1k = b_banks_1k[bank_1k];
//bank_1k = NES.Frame;
//something like this..? //something like this..?
//bool special_sel = NES.ppu.reg_2000.obj_size_16 && NES.ppu.ppuphase == NES.PPU.PPUPHASE.OBJ; //bool special_sel = NES.ppu.reg_2000.obj_size_16 && NES.ppu.ppuphase == NES.PPU.PPUPHASE.OBJ;
//bool a_sel = special_sel || (!a_sel && ab_mode == 0); //bool a_sel = special_sel || (!a_sel && ab_mode == 0);
bank_1k &= chr_bank_mask_1k; bank_1k &= chr_bank_mask_1k;
addr = (bank_1k<<10)|ofs; addr = (bank_1k<<10)|ofs;
return addr; return addr;

View File

@ -1,34 +1,35 @@
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
partial class NESNameTableViewer partial class NESNameTableViewer
{ {
/// <summary> /// <summary>
/// Required designer variable. /// Required designer variable.
/// </summary> /// </summary>
private System.ComponentModel.IContainer components = null; private System.ComponentModel.IContainer components = null;
/// <summary> /// <summary>
/// Clean up any resources being used. /// Clean up any resources being used.
/// </summary> /// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (disposing && (components != null)) if (disposing && (components != null))
{ {
components.Dispose(); components.Dispose();
} }
base.Dispose(disposing); base.Dispose(disposing);
} }
#region Windows Form Designer generated code #region Windows Form Designer generated code
/// <summary> /// <summary>
/// Required method for Designer support - do not modify /// Required method for Designer support - do not modify
/// the contents of this method with the code editor. /// the contents of this method with the code editor.
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
this.NameTableView = new BizHawk.MultiClient.NameTableViewer();
this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.autoloadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.autoloadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -37,7 +38,13 @@
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.txtScanline = new System.Windows.Forms.TextBox(); this.txtScanline = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.NameTableView = new BizHawk.MultiClient.NameTableViewer(); this.rbNametableNW = new System.Windows.Forms.RadioButton();
this.rbNametableNE = new System.Windows.Forms.RadioButton();
this.rbNametableSW = new System.Windows.Forms.RadioButton();
this.rbNametableSE = new System.Windows.Forms.RadioButton();
this.label2 = new System.Windows.Forms.Label();
this.rbNametableAll = new System.Windows.Forms.RadioButton();
this.label3 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout(); this.groupBox1.SuspendLayout();
this.menuStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
@ -51,6 +58,14 @@
this.groupBox1.TabIndex = 0; this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false; this.groupBox1.TabStop = false;
// //
// NameTableView
//
this.NameTableView.BackColor = System.Drawing.Color.White;
this.NameTableView.Location = new System.Drawing.Point(17, 19);
this.NameTableView.Name = "NameTableView";
this.NameTableView.Size = new System.Drawing.Size(512, 480);
this.NameTableView.TabIndex = 0;
//
// menuStrip1 // menuStrip1
// //
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -102,7 +117,7 @@
// //
// txtScanline // txtScanline
// //
this.txtScanline.Location = new System.Drawing.Point(563, 64); this.txtScanline.Location = new System.Drawing.Point(578, 64);
this.txtScanline.Name = "txtScanline"; this.txtScanline.Name = "txtScanline";
this.txtScanline.Size = new System.Drawing.Size(60, 20); this.txtScanline.Size = new System.Drawing.Size(60, 20);
this.txtScanline.TabIndex = 2; this.txtScanline.TabIndex = 2;
@ -112,25 +127,94 @@
// label1 // label1
// //
this.label1.AutoSize = true; this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(564, 45); this.label1.Location = new System.Drawing.Point(579, 45);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(48, 13); this.label1.Size = new System.Drawing.Size(48, 13);
this.label1.TabIndex = 3; this.label1.TabIndex = 3;
this.label1.Text = "Scanline"; this.label1.Text = "Scanline";
// //
// NameTableView // rbNametableNW
// //
this.NameTableView.BackColor = System.Drawing.Color.White; this.rbNametableNW.AutoSize = true;
this.NameTableView.Location = new System.Drawing.Point(17, 19); this.rbNametableNW.Location = new System.Drawing.Point(592, 115);
this.NameTableView.Name = "NameTableView"; this.rbNametableNW.Name = "rbNametableNW";
this.NameTableView.Size = new System.Drawing.Size(512, 480); this.rbNametableNW.Size = new System.Drawing.Size(14, 13);
this.NameTableView.TabIndex = 0; this.rbNametableNW.TabIndex = 4;
this.rbNametableNW.UseVisualStyleBackColor = true;
this.rbNametableNW.CheckedChanged += new System.EventHandler(this.rbNametable_CheckedChanged);
//
// rbNametableNE
//
this.rbNametableNE.AutoSize = true;
this.rbNametableNE.Location = new System.Drawing.Point(612, 115);
this.rbNametableNE.Name = "rbNametableNE";
this.rbNametableNE.Size = new System.Drawing.Size(14, 13);
this.rbNametableNE.TabIndex = 5;
this.rbNametableNE.UseVisualStyleBackColor = true;
this.rbNametableNE.CheckedChanged += new System.EventHandler(this.rbNametable_CheckedChanged);
//
// rbNametableSW
//
this.rbNametableSW.AutoSize = true;
this.rbNametableSW.Location = new System.Drawing.Point(592, 134);
this.rbNametableSW.Name = "rbNametableSW";
this.rbNametableSW.Size = new System.Drawing.Size(14, 13);
this.rbNametableSW.TabIndex = 6;
this.rbNametableSW.UseVisualStyleBackColor = true;
this.rbNametableSW.CheckedChanged += new System.EventHandler(this.rbNametable_CheckedChanged);
//
// rbNametableSE
//
this.rbNametableSE.AutoSize = true;
this.rbNametableSE.Location = new System.Drawing.Point(612, 134);
this.rbNametableSE.Name = "rbNametableSE";
this.rbNametableSE.Size = new System.Drawing.Size(14, 13);
this.rbNametableSE.TabIndex = 7;
this.rbNametableSE.UseVisualStyleBackColor = true;
this.rbNametableSE.CheckedChanged += new System.EventHandler(this.rbNametable_CheckedChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(579, 99);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(58, 13);
this.label2.TabIndex = 8;
this.label2.Text = "Nametable";
//
// rbNametableAll
//
this.rbNametableAll.AutoSize = true;
this.rbNametableAll.Checked = true;
this.rbNametableAll.Location = new System.Drawing.Point(582, 153);
this.rbNametableAll.Name = "rbNametableAll";
this.rbNametableAll.Size = new System.Drawing.Size(14, 13);
this.rbNametableAll.TabIndex = 9;
this.rbNametableAll.TabStop = true;
this.rbNametableAll.UseVisualStyleBackColor = true;
this.rbNametableAll.CheckedChanged += new System.EventHandler(this.rbNametable_CheckedChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(602, 153);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(30, 13);
this.label3.TabIndex = 10;
this.label3.Text = "<- All";
// //
// NESNameTableViewer // NESNameTableViewer
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(668, 561); this.ClientSize = new System.Drawing.Size(668, 561);
this.Controls.Add(this.label3);
this.Controls.Add(this.rbNametableAll);
this.Controls.Add(this.label2);
this.Controls.Add(this.rbNametableSE);
this.Controls.Add(this.rbNametableSW);
this.Controls.Add(this.rbNametableNE);
this.Controls.Add(this.rbNametableNW);
this.Controls.Add(this.label1); this.Controls.Add(this.label1);
this.Controls.Add(this.txtScanline); this.Controls.Add(this.txtScanline);
this.Controls.Add(this.groupBox1); this.Controls.Add(this.groupBox1);
@ -146,19 +230,26 @@
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
} }
#endregion #endregion
private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.GroupBox groupBox1;
private NameTableViewer NameTableView; private NameTableViewer NameTableView;
private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem autoloadToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem autoloadToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem saveWindowPositionToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveWindowPositionToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.TextBox txtScanline; private System.Windows.Forms.TextBox txtScanline;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
} private System.Windows.Forms.RadioButton rbNametableNW;
private System.Windows.Forms.RadioButton rbNametableNE;
private System.Windows.Forms.RadioButton rbNametableSW;
private System.Windows.Forms.RadioButton rbNametableSE;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.RadioButton rbNametableAll;
private System.Windows.Forms.Label label3;
}
} }

View File

@ -11,27 +11,27 @@ using BizHawk.Emulation.Consoles.Nintendo;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public partial class NESNameTableViewer : Form public partial class NESNameTableViewer : Form
{ {
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;
NES.PPU.DebugCallback Callback = new NES.PPU.DebugCallback(); NES.PPU.DebugCallback Callback = new NES.PPU.DebugCallback();
public NESNameTableViewer() public NESNameTableViewer()
{ {
InitializeComponent(); InitializeComponent();
Closing += (o, e) => SaveConfigSettings(); Closing += (o, e) => SaveConfigSettings();
Callback.Callback = () => Generate(); Callback.Callback = () => Generate();
} }
private void SaveConfigSettings() private void SaveConfigSettings()
{ {
Global.Config.NESNameTableWndx = this.Location.X; Global.Config.NESNameTableWndx = this.Location.X;
Global.Config.NESNameTableWndy = this.Location.Y; Global.Config.NESNameTableWndy = this.Location.Y;
} }
unsafe void Generate() unsafe void Generate()
{ {
@ -98,54 +98,54 @@ namespace BizHawk.MultiClient
NameTableView.Refresh(); NameTableView.Refresh();
} }
public void UpdateValues() public void UpdateValues()
{ {
if (!(Global.Emulator is NES)) return; if (!(Global.Emulator is NES)) return;
NES.PPU ppu = (Global.Emulator as NES).ppu; NES.PPU ppu = (Global.Emulator as NES).ppu;
ppu.NTViewCallback = Callback; ppu.NTViewCallback = Callback;
} }
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 NESNameTableViewer_Load(object sender, EventArgs e) private void NESNameTableViewer_Load(object sender, EventArgs e)
{ {
defaultWidth = this.Size.Width; //Save these first so that the user can restore to its original size defaultWidth = this.Size.Width; //Save these first so that the user can restore to its original size
defaultHeight = this.Size.Height; defaultHeight = this.Size.Height;
if (Global.Config.NESNameTableSaveWindowPosition && Global.Config.NESNameTableWndx >= 0 && Global.Config.NESNameTableWndy >= 0) if (Global.Config.NESNameTableSaveWindowPosition && Global.Config.NESNameTableWndx >= 0 && Global.Config.NESNameTableWndy >= 0)
this.Location = new Point(Global.Config.NESNameTableWndx, Global.Config.NESNameTableWndy); this.Location = new Point(Global.Config.NESNameTableWndx, Global.Config.NESNameTableWndy);
Nes = Global.Emulator as NES; Nes = Global.Emulator as NES;
} }
private void exitToolStripMenuItem_Click(object sender, EventArgs e) private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ {
this.Close(); this.Close();
} }
private void autoloadToolStripMenuItem_Click(object sender, EventArgs e) private void autoloadToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Global.Config.AutoLoadNESNameTable ^= true; Global.Config.AutoLoadNESNameTable ^= true;
} }
private void saveWindowPositionToolStripMenuItem_Click(object sender, EventArgs e) private void saveWindowPositionToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Global.Config.NESNameTableSaveWindowPosition ^= true; Global.Config.NESNameTableSaveWindowPosition ^= true;
} }
private void optionsToolStripMenuItem_DropDownOpened(object sender, EventArgs e) private void optionsToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
{ {
autoloadToolStripMenuItem.Checked = Global.Config.AutoLoadNESNameTable; autoloadToolStripMenuItem.Checked = Global.Config.AutoLoadNESNameTable;
saveWindowPositionToolStripMenuItem.Checked = Global.Config.NESNameTableSaveWindowPosition; saveWindowPositionToolStripMenuItem.Checked = Global.Config.NESNameTableSaveWindowPosition;
} }
private void txtScanline_TextChanged(object sender, EventArgs e) private void txtScanline_TextChanged(object sender, EventArgs e)
{ {
int temp=0; int temp = 0;
if (int.TryParse(txtScanline.Text, out temp)) if (int.TryParse(txtScanline.Text, out temp))
{ {
Callback.Scanline = temp; Callback.Scanline = temp;
@ -158,5 +158,15 @@ namespace BizHawk.MultiClient
if (Nes.ppu.NTViewCallback == Callback) if (Nes.ppu.NTViewCallback == Callback)
Nes.ppu.NTViewCallback = null; Nes.ppu.NTViewCallback = null;
} }
}
private void rbNametable_CheckedChanged(object sender, EventArgs e)
{
if (rbNametableNW.Checked) NameTableView.Which = NameTableViewer.WhichNametable.NT_2000;
if (rbNametableNE.Checked) NameTableView.Which = NameTableViewer.WhichNametable.NT_2400;
if (rbNametableSW.Checked) NameTableView.Which = NameTableViewer.WhichNametable.NT_2800;
if (rbNametableSE.Checked) NameTableView.Which = NameTableViewer.WhichNametable.NT_2C00;
if (rbNametableAll.Checked) NameTableView.Which = NameTableViewer.WhichNametable.NT_ALL;
}
}
} }

View File

@ -8,34 +8,57 @@ using System.Globalization;
namespace BizHawk.MultiClient namespace BizHawk.MultiClient
{ {
public class NameTableViewer : Control public class NameTableViewer : Control
{ {
Size pSize; Size pSize;
public Bitmap nametables; public Bitmap nametables;
public NameTableViewer() public NameTableViewer()
{ {
pSize = new Size(512, 480); pSize = new Size(512, 480);
nametables = new Bitmap(pSize.Width, pSize.Height); nametables = new Bitmap(pSize.Width, pSize.Height);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true); SetStyle(ControlStyles.DoubleBuffer, true);
this.Size = new Size(256, 224); this.Size = new Size(256, 224);
this.BackColor = Color.White; this.BackColor = Color.White;
this.Paint += new System.Windows.Forms.PaintEventHandler(this.NameTableViewer_Paint); this.Paint += new System.Windows.Forms.PaintEventHandler(this.NameTableViewer_Paint);
} }
private void Display(Graphics g) public enum WhichNametable
{ {
unchecked NT_2000, NT_2400, NT_2800, NT_2C00, NT_ALL
{ }
g.DrawImage(nametables, 1, 1);
}
}
private void NameTableViewer_Paint(object sender, PaintEventArgs e) public WhichNametable Which = WhichNametable.NT_ALL;
{
Display(e.Graphics); private void Display(Graphics g)
} {
} g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
switch (Which)
{
case WhichNametable.NT_ALL:
g.DrawImageUnscaled(nametables, 1, 1);
break;
case WhichNametable.NT_2000:
g.DrawImage(nametables, new Rectangle(0, 0, 512, 480), 0, 0, 256, 240, GraphicsUnit.Pixel);
break;
case WhichNametable.NT_2400:
g.DrawImage(nametables, new Rectangle(0, 0, 512, 480), 256, 0, 256, 240, GraphicsUnit.Pixel);
break;
case WhichNametable.NT_2800:
g.DrawImage(nametables, new Rectangle(0, 0, 512, 480), 0, 240, 256, 240, GraphicsUnit.Pixel);
break;
case WhichNametable.NT_2C00:
g.DrawImage(nametables, new Rectangle(0, 0, 512, 480), 256, 240, 256, 240, GraphicsUnit.Pixel);
break;
}
}
private void NameTableViewer_Paint(object sender, PaintEventArgs e)
{
Display(e.Graphics);
}
}
} }