Debugger - PPU Viewer (Nametables, chr, sprites, palette)

This commit is contained in:
Souryo 2015-08-08 22:36:39 -04:00
parent 83d91d02c0
commit 7e5707a535
28 changed files with 2683 additions and 100 deletions

View File

@ -7,6 +7,7 @@
#include "Console.h"
#include "BaseMapper.h"
#include "Disassembler.h"
#include "VideoDecoder.h"
#include "APU.h"
Debugger* Debugger::Instance = nullptr;
@ -304,4 +305,134 @@ uint32_t Debugger::GetMemoryState(DebugMemoryType type, uint8_t *buffer)
return _mapper->GetChrSize();
}
return 0;
}
void Debugger::GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData)
{
uint16_t *screenBuffer = new uint16_t[256 * 240];
uint16_t bgAddr = _ppu->GetState().ControlFlags.BackgroundPatternAddr;
uint16_t baseAddr = 0x2000 + nametableIndex * 0x400;
uint16_t baseAttributeAddr = baseAddr + 960;
for(int y = 0; y < 30; y++) {
for(int x = 0; x < 32; x++) {
uint8_t tileIndex = _mapper->ReadVRAM(baseAddr + (y << 5) + x);
uint8_t attribute = _mapper->ReadVRAM(baseAttributeAddr + ((y & 0xFC) << 1) + (x >> 2));
tileData[y * 30 + x] = tileIndex;
paletteData[y * 30 + x] = attribute;
uint8_t shift = (x & 0x02) | ((y & 0x02) << 1);
uint8_t paletteBaseAddr = ((attribute >> shift) & 0x03) << 2;
uint16_t tileAddr = bgAddr + (tileIndex << 4);
for(int i = 0; i < 8; i++) {
uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i);
uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8);
for(int j = 0; j < 8; j++) {
uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1);
screenBuffer[(y<<11)+(x<<3)+(i<<8)+j] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(paletteBaseAddr + color);
}
}
}
}
VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 256*240);
delete[] screenBuffer;
}
void Debugger::GetChrBank(int bankIndex, uint32_t* frameBuffer, uint8_t palette)
{
uint16_t *screenBuffer = new uint16_t[128 * 128];
uint16_t bgAddr = bankIndex == 0 ? 0x0000 : 0x1000;
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
uint8_t tileIndex = y * 16 + x;
uint8_t paletteBaseAddr = palette << 2;
uint16_t tileAddr = bgAddr + (tileIndex << 4);
for(int i = 0; i < 8; i++) {
uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i);
uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8);
for(int j = 0; j < 8; j++) {
uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1);
screenBuffer[(y<<10)+(x<<3)+(i<<7)+j] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(paletteBaseAddr + color);
}
}
}
}
VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 128*128);
delete[] screenBuffer;
}
void Debugger::GetSprites(uint32_t* frameBuffer)
{
uint16_t *screenBuffer = new uint16_t[64 * 128];
memset(screenBuffer, 0, 64*128*sizeof(uint16_t));
uint8_t *spriteRam = _ppu->GetSpriteRam();
uint16_t spriteAddr = _ppu->GetState().ControlFlags.SpritePatternAddr;
bool largeSprites = _ppu->GetState().ControlFlags.LargeSprites;
for(int y = 0; y < 8; y++) {
for(int x = 0; x < 8; x++) {
uint8_t ramAddr = ((y << 3) + x) << 2;
uint8_t spriteY = spriteRam[ramAddr];
uint8_t tileIndex = spriteRam[ramAddr + 1];
uint8_t attributes = spriteRam[ramAddr + 2];
uint8_t spriteX = spriteRam[ramAddr + 3];
bool verticalMirror = (attributes & 0x80) == 0x80;
bool horizontalMirror = (attributes & 0x40) == 0x40;
uint16_t tileAddr;
if(largeSprites) {
tileAddr = (tileIndex & 0x01 ? 0x1000 : 0x0000) + ((tileIndex & 0xFE) << 4);
} else {
tileAddr = spriteAddr + (tileIndex << 4);
}
uint8_t palette = 0x10 + ((attributes & 0x03) << 2);
for(int i = 0, iMax = largeSprites ? 16 : 8; i < iMax; i++) {
if(i == 8) {
//Move to next tile for 2nd tile of 8x16 sprites
tileAddr += 8;
}
uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i);
uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8);
for(int j = 0; j < 8; j++) {
uint8_t color;
if(horizontalMirror) {
color = ((lowByte >> j) & 0x01) | (((highByte >> j) & 0x01) << 1);
} else {
color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1);
}
uint16_t destAddr;
if(verticalMirror) {
destAddr = (y << 10) + (x << 3) + (((largeSprites ? 15 : 7) - i) << 6) + j;
} else {
destAddr = (y << 10) + (x << 3) + (i << 6) + j;
}
screenBuffer[destAddr] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(palette + color);
}
}
}
}
VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 64*128);
delete[] screenBuffer;
}
void Debugger::GetPalette(uint32_t* frameBuffer)
{
uint16_t *screenBuffer = new uint16_t[4*8];
for(int i = 0; i < 32; i++) {
screenBuffer[i] = _ppu->ReadPaletteRAM(i);
}
VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 4*8);
delete[] screenBuffer;
}

View File

@ -70,6 +70,10 @@ public:
vector<uint32_t> GetExecBreakpointAddresses();
uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer);
void GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData);
void GetChrBank(int bankIndex, uint32_t* frameBuffer, uint8_t palette);
void GetSprites(uint32_t* frameBuffer);
void GetPalette(uint32_t* frameBuffer);
void GetState(DebugState *state);

View File

@ -11,7 +11,8 @@ enum class ConsoleNotificationType
GameStopped = 5,
CodeBreak = 6,
CheatAdded = 7,
CheatRemoved = 8
CheatRemoved = 8,
PpuFrameDone = 9
};
class INotificationListener

View File

@ -3,7 +3,7 @@
#include "MessageManager.h"
IMessageManager* MessageManager::_messageManager = nullptr;
list<INotificationListener*> MessageManager::_notificationListeners;
vector<INotificationListener*> MessageManager::_notificationListeners;
void MessageManager::RegisterMessageManager(IMessageManager* messageManager)
{
@ -26,20 +26,32 @@ void MessageManager::DisplayToast(string title, string message, uint8_t* iconDat
void MessageManager::RegisterNotificationListener(INotificationListener* notificationListener)
{
MessageManager::_notificationListeners.push_back(notificationListener);
MessageManager::_notificationListeners.unique();
}
void MessageManager::UnregisterNotificationListener(INotificationListener* notificationListener)
{
MessageManager::_notificationListeners.remove(notificationListener);
MessageManager::_notificationListeners.erase(std::remove(MessageManager::_notificationListeners.begin(), MessageManager::_notificationListeners.end(), notificationListener), MessageManager::_notificationListeners.end());
}
void MessageManager::SendNotification(ConsoleNotificationType type)
{
list<INotificationListener*> listeners = MessageManager::_notificationListeners;
//Iterate on a copy to prevent issues if a notification causes a listener to unregister itself
for(INotificationListener* notificationListener : listeners) {
notificationListener->ProcessNotification(type);
vector<INotificationListener*> listeners = MessageManager::_notificationListeners;
vector<INotificationListener*> processedListeners;
for(size_t i = 0, len = listeners.size(); i < len; i++) {
INotificationListener* notificationListener = listeners[i];
if(std::find(processedListeners.begin(), processedListeners.end(), notificationListener) == processedListeners.end()) {
//Only send notification if it hasn't been processed already
notificationListener->ProcessNotification(type);
}
processedListeners.push_back(notificationListener);
if(len != MessageManager::_notificationListeners.size()) {
//Vector changed, start from the beginning again (can occur when sending a notification caused listeners to unregister themselves)
i = 0;
len = MessageManager::_notificationListeners.size();
listeners = MessageManager::_notificationListeners;
}
}
}

View File

@ -9,7 +9,7 @@ class MessageManager
{
private:
static IMessageManager* _messageManager;
static list<INotificationListener*> _notificationListeners;
static vector<INotificationListener*> _notificationListeners;
public:
static void RegisterMessageManager(IMessageManager* messageManager);

View File

@ -90,6 +90,8 @@ void VideoDecoder::UpdateBufferSize()
uint32_t* VideoDecoder::DecodeFrame(uint16_t* inputBuffer)
{
MessageManager::SendNotification(ConsoleNotificationType::PpuFrameDone);
_frameLock.Acquire();
UpdateBufferSize();
uint32_t* outputBuffer = _frameBuffer;
@ -100,10 +102,17 @@ uint32_t* VideoDecoder::DecodeFrame(uint16_t* inputBuffer)
}
}
_frameLock.Release();
return _frameBuffer;
}
void VideoDecoder::DebugDecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer, uint32_t length)
{
for(uint32_t i = 0; i < length; i++) {
outputBuffer[i] = PPU_PALETTE_ARGB[inputBuffer[i] & 0x3F];
}
}
void VideoDecoder::TakeScreenshot(string romFilename)
{
uint32_t bufferSize = _overscan.GetPixelCount() * 4;

View File

@ -21,4 +21,6 @@ public:
uint32_t* DecodeFrame(uint16_t* inputBuffer);
void TakeScreenshot(string romFilename);
void DebugDecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer, uint32_t length);
};

View File

@ -0,0 +1,265 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlChrViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.grpTileInfo = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.txtTileAddress = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.txtTileIndex = new System.Windows.Forms.TextBox();
this.picTile = new System.Windows.Forms.PictureBox();
this.picChrBank1 = new System.Windows.Forms.PictureBox();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.lblPalette = new System.Windows.Forms.Label();
this.cboPalette = new System.Windows.Forms.ComboBox();
this.picChrBank2 = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel3.SuspendLayout();
this.grpTileInfo.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).BeginInit();
this.flowLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 3;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Controls.Add(this.grpTileInfo, 1, 1);
this.tableLayoutPanel3.Controls.Add(this.picChrBank1, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.flowLayoutPanel1, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.picChrBank2, 0, 2);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 3;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(446, 522);
this.tableLayoutPanel3.TabIndex = 3;
//
// grpTileInfo
//
this.grpTileInfo.Controls.Add(this.tableLayoutPanel4);
this.grpTileInfo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpTileInfo.Location = new System.Drawing.Point(263, 31);
this.grpTileInfo.Name = "grpTileInfo";
this.tableLayoutPanel3.SetRowSpan(this.grpTileInfo, 2);
this.grpTileInfo.Size = new System.Drawing.Size(180, 488);
this.grpTileInfo.TabIndex = 4;
this.grpTileInfo.TabStop = false;
this.grpTileInfo.Text = "Tile Info";
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.txtTileAddress, 1, 1);
this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.label2, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.label6, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.txtTileIndex, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.picTile, 1, 2);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 4;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(174, 469);
this.tableLayoutPanel4.TabIndex = 0;
//
// txtTileAddress
//
this.txtTileAddress.Location = new System.Drawing.Point(77, 29);
this.txtTileAddress.Name = "txtTileAddress";
this.txtTileAddress.ReadOnly = true;
this.txtTileAddress.Size = new System.Drawing.Size(42, 20);
this.txtTileAddress.TabIndex = 8;
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 6);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(56, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Tile Index:";
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 32);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(68, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Tile Address:";
//
// label6
//
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(3, 81);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(27, 13);
this.label6.TabIndex = 6;
this.label6.Text = "Tile:";
//
// txtTileIndex
//
this.txtTileIndex.Location = new System.Drawing.Point(77, 3);
this.txtTileIndex.Name = "txtTileIndex";
this.txtTileIndex.ReadOnly = true;
this.txtTileIndex.Size = new System.Drawing.Size(26, 20);
this.txtTileIndex.TabIndex = 7;
//
// picTile
//
this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picTile.Location = new System.Drawing.Point(77, 55);
this.picTile.Name = "picTile";
this.picTile.Size = new System.Drawing.Size(66, 66);
this.picTile.TabIndex = 12;
this.picTile.TabStop = false;
//
// picChrBank1
//
this.picChrBank1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picChrBank1.Location = new System.Drawing.Point(1, 1);
this.picChrBank1.Margin = new System.Windows.Forms.Padding(1);
this.picChrBank1.Name = "picChrBank1";
this.tableLayoutPanel3.SetRowSpan(this.picChrBank1, 2);
this.picChrBank1.Size = new System.Drawing.Size(258, 258);
this.picChrBank1.TabIndex = 0;
this.picChrBank1.TabStop = false;
this.picChrBank1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picChrBank_MouseMove);
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.Controls.Add(this.lblPalette);
this.flowLayoutPanel1.Controls.Add(this.cboPalette);
this.flowLayoutPanel1.Location = new System.Drawing.Point(260, 0);
this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(166, 28);
this.flowLayoutPanel1.TabIndex = 5;
//
// lblPalette
//
this.lblPalette.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPalette.AutoSize = true;
this.lblPalette.Location = new System.Drawing.Point(3, 7);
this.lblPalette.Name = "lblPalette";
this.lblPalette.Size = new System.Drawing.Size(43, 13);
this.lblPalette.TabIndex = 0;
this.lblPalette.Text = "Palette:";
//
// cboPalette
//
this.cboPalette.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboPalette.FormattingEnabled = true;
this.cboPalette.Items.AddRange(new object[] {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7"});
this.cboPalette.Location = new System.Drawing.Point(52, 3);
this.cboPalette.Name = "cboPalette";
this.cboPalette.Size = new System.Drawing.Size(45, 21);
this.cboPalette.TabIndex = 1;
this.cboPalette.SelectedIndexChanged += new System.EventHandler(this.cboPalette_SelectedIndexChanged);
//
// picChrBank2
//
this.picChrBank2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picChrBank2.Location = new System.Drawing.Point(1, 261);
this.picChrBank2.Margin = new System.Windows.Forms.Padding(1);
this.picChrBank2.Name = "picChrBank2";
this.picChrBank2.Size = new System.Drawing.Size(258, 258);
this.picChrBank2.TabIndex = 1;
this.picChrBank2.TabStop = false;
this.picChrBank2.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picChrBank_MouseMove);
//
// ctrlChrViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel3);
this.Name = "ctrlChrViewer";
this.Size = new System.Drawing.Size(446, 522);
this.tableLayoutPanel3.ResumeLayout(false);
this.grpTileInfo.ResumeLayout(false);
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).EndInit();
this.flowLayoutPanel1.ResumeLayout(false);
this.flowLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.PictureBox picChrBank2;
private System.Windows.Forms.PictureBox picChrBank1;
private System.Windows.Forms.GroupBox grpTileInfo;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.TextBox txtTileAddress;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txtTileIndex;
private System.Windows.Forms.PictureBox picTile;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Label lblPalette;
private System.Windows.Forms.ComboBox cboPalette;
}
}

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlChrViewer : UserControl
{
public ctrlChrViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!this.DesignMode) {
this.cboPalette.SelectedIndex = 0;
}
}
public void RefreshViewer()
{
PictureBox[] chrBanks = new PictureBox[] { this.picChrBank1, this.picChrBank2 };
for(int i = 0; i < 2; i++) {
byte[] pixelData = InteropEmu.DebugGetChrBank(i, this.cboPalette.SelectedIndex);
GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
try {
Bitmap source = new Bitmap(128, 128, 4*128, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
Bitmap target = new Bitmap(256, 256);
using(Graphics g = Graphics.FromImage(target)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(source, new Rectangle(0, 0, 256, 256), new Rectangle(0, 0, 128, 128), GraphicsUnit.Pixel);
}
chrBanks[i].Image = target;
} finally {
handle.Free();
}
}
}
private void cboPalette_SelectedIndexChanged(object sender, EventArgs e)
{
this.RefreshViewer();
}
private void picChrBank_MouseMove(object sender, MouseEventArgs e)
{
List<PictureBox> chrBanks = new List<PictureBox>() { this.picChrBank1, this.picChrBank2 };
int bankIndex = chrBanks.IndexOf((PictureBox)sender);
int baseAddress = bankIndex == 0 ? 0x0000 : 0x1000;
int tileX = Math.Min(e.X / 16, 15);
int tileY = Math.Min(e.Y / 16, 15);
int tileIndex = tileY * 16 + tileX;
this.txtTileIndex.Text = tileIndex.ToString("X2");
this.txtTileAddress.Text = (baseAddress + tileIndex * 16).ToString("X4");
Bitmap tile = new Bitmap(64, 64);
using(Graphics g = Graphics.FromImage(tile)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*16, tileY*16, 16, 16), GraphicsUnit.Pixel);
}
this.picTile.Image = tile;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,318 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlNametableViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.grpTileInfo = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.txtPaletteAddress = new System.Windows.Forms.TextBox();
this.txtAttributeAddress = new System.Windows.Forms.TextBox();
this.txtAttributeData = new System.Windows.Forms.TextBox();
this.txtTileAddress = new System.Windows.Forms.TextBox();
this.lblTileIndex = new System.Windows.Forms.Label();
this.lblTileAddress = new System.Windows.Forms.Label();
this.lblAttributeData = new System.Windows.Forms.Label();
this.lblAttributeAddress = new System.Windows.Forms.Label();
this.lblPaletteAddress = new System.Windows.Forms.Label();
this.lblTile = new System.Windows.Forms.Label();
this.txtTileIndex = new System.Windows.Forms.TextBox();
this.picNametable4 = new System.Windows.Forms.PictureBox();
this.picNametable3 = new System.Windows.Forms.PictureBox();
this.picNametable2 = new System.Windows.Forms.PictureBox();
this.picNametable1 = new System.Windows.Forms.PictureBox();
this.picTile = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel1.SuspendLayout();
this.grpTileInfo.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picNametable4)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 3;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.picNametable4, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.picNametable3, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.picNametable2, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.picNametable1, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.grpTileInfo, 2, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(697, 488);
this.tableLayoutPanel1.TabIndex = 2;
//
// grpTileInfo
//
this.grpTileInfo.Controls.Add(this.tableLayoutPanel2);
this.grpTileInfo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpTileInfo.Location = new System.Drawing.Point(523, 3);
this.grpTileInfo.Name = "grpTileInfo";
this.tableLayoutPanel1.SetRowSpan(this.grpTileInfo, 2);
this.grpTileInfo.Size = new System.Drawing.Size(171, 482);
this.grpTileInfo.TabIndex = 4;
this.grpTileInfo.TabStop = false;
this.grpTileInfo.Text = "Tile Info";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Controls.Add(this.txtPaletteAddress, 1, 4);
this.tableLayoutPanel2.Controls.Add(this.txtAttributeAddress, 1, 3);
this.tableLayoutPanel2.Controls.Add(this.txtAttributeData, 1, 2);
this.tableLayoutPanel2.Controls.Add(this.txtTileAddress, 1, 1);
this.tableLayoutPanel2.Controls.Add(this.lblTileIndex, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.lblTileAddress, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.lblAttributeData, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.lblAttributeAddress, 0, 3);
this.tableLayoutPanel2.Controls.Add(this.lblPaletteAddress, 0, 4);
this.tableLayoutPanel2.Controls.Add(this.lblTile, 0, 5);
this.tableLayoutPanel2.Controls.Add(this.txtTileIndex, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.picTile, 1, 5);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 7;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(165, 463);
this.tableLayoutPanel2.TabIndex = 0;
//
// txtPaletteAddress
//
this.txtPaletteAddress.Location = new System.Drawing.Point(99, 107);
this.txtPaletteAddress.Name = "txtPaletteAddress";
this.txtPaletteAddress.ReadOnly = true;
this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20);
this.txtPaletteAddress.TabIndex = 11;
//
// txtAttributeAddress
//
this.txtAttributeAddress.Location = new System.Drawing.Point(99, 81);
this.txtAttributeAddress.Name = "txtAttributeAddress";
this.txtAttributeAddress.ReadOnly = true;
this.txtAttributeAddress.Size = new System.Drawing.Size(42, 20);
this.txtAttributeAddress.TabIndex = 10;
//
// txtAttributeData
//
this.txtAttributeData.Location = new System.Drawing.Point(99, 55);
this.txtAttributeData.Name = "txtAttributeData";
this.txtAttributeData.ReadOnly = true;
this.txtAttributeData.Size = new System.Drawing.Size(26, 20);
this.txtAttributeData.TabIndex = 9;
//
// txtTileAddress
//
this.txtTileAddress.Location = new System.Drawing.Point(99, 29);
this.txtTileAddress.Name = "txtTileAddress";
this.txtTileAddress.ReadOnly = true;
this.txtTileAddress.Size = new System.Drawing.Size(42, 20);
this.txtTileAddress.TabIndex = 8;
//
// lblTileIndex
//
this.lblTileIndex.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTileIndex.AutoSize = true;
this.lblTileIndex.Location = new System.Drawing.Point(3, 6);
this.lblTileIndex.Name = "lblTileIndex";
this.lblTileIndex.Size = new System.Drawing.Size(56, 13);
this.lblTileIndex.TabIndex = 0;
this.lblTileIndex.Text = "Tile Index:";
//
// lblTileAddress
//
this.lblTileAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTileAddress.AutoSize = true;
this.lblTileAddress.Location = new System.Drawing.Point(3, 32);
this.lblTileAddress.Name = "lblTileAddress";
this.lblTileAddress.Size = new System.Drawing.Size(68, 13);
this.lblTileAddress.TabIndex = 1;
this.lblTileAddress.Text = "Tile Address:";
//
// lblAttributeData
//
this.lblAttributeData.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblAttributeData.AutoSize = true;
this.lblAttributeData.Location = new System.Drawing.Point(3, 58);
this.lblAttributeData.Name = "lblAttributeData";
this.lblAttributeData.Size = new System.Drawing.Size(75, 13);
this.lblAttributeData.TabIndex = 2;
this.lblAttributeData.Text = "Attribute Data:";
//
// lblAttributeAddress
//
this.lblAttributeAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblAttributeAddress.AutoSize = true;
this.lblAttributeAddress.Location = new System.Drawing.Point(3, 84);
this.lblAttributeAddress.Name = "lblAttributeAddress";
this.lblAttributeAddress.Size = new System.Drawing.Size(90, 13);
this.lblAttributeAddress.TabIndex = 3;
this.lblAttributeAddress.Text = "Attribute Address:";
//
// lblPaletteAddress
//
this.lblPaletteAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPaletteAddress.AutoSize = true;
this.lblPaletteAddress.Location = new System.Drawing.Point(3, 110);
this.lblPaletteAddress.Name = "lblPaletteAddress";
this.lblPaletteAddress.Size = new System.Drawing.Size(84, 13);
this.lblPaletteAddress.TabIndex = 4;
this.lblPaletteAddress.Text = "Palette Address:";
//
// lblTile
//
this.lblTile.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTile.AutoSize = true;
this.lblTile.Location = new System.Drawing.Point(3, 159);
this.lblTile.Name = "lblTile";
this.lblTile.Size = new System.Drawing.Size(27, 13);
this.lblTile.TabIndex = 6;
this.lblTile.Text = "Tile:";
//
// txtTileIndex
//
this.txtTileIndex.Location = new System.Drawing.Point(99, 3);
this.txtTileIndex.Name = "txtTileIndex";
this.txtTileIndex.ReadOnly = true;
this.txtTileIndex.Size = new System.Drawing.Size(26, 20);
this.txtTileIndex.TabIndex = 7;
//
// picNametable4
//
this.picNametable4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picNametable4.Location = new System.Drawing.Point(261, 245);
this.picNametable4.Margin = new System.Windows.Forms.Padding(1);
this.picNametable4.Name = "picNametable4";
this.picNametable4.Size = new System.Drawing.Size(258, 242);
this.picNametable4.TabIndex = 3;
this.picNametable4.TabStop = false;
this.picNametable4.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove);
//
// picNametable3
//
this.picNametable3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picNametable3.Location = new System.Drawing.Point(1, 245);
this.picNametable3.Margin = new System.Windows.Forms.Padding(1);
this.picNametable3.Name = "picNametable3";
this.picNametable3.Size = new System.Drawing.Size(258, 242);
this.picNametable3.TabIndex = 2;
this.picNametable3.TabStop = false;
this.picNametable3.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove);
//
// picNametable2
//
this.picNametable2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picNametable2.Location = new System.Drawing.Point(261, 1);
this.picNametable2.Margin = new System.Windows.Forms.Padding(1);
this.picNametable2.Name = "picNametable2";
this.picNametable2.Size = new System.Drawing.Size(258, 242);
this.picNametable2.TabIndex = 1;
this.picNametable2.TabStop = false;
this.picNametable2.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove);
//
// picNametable1
//
this.picNametable1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picNametable1.Location = new System.Drawing.Point(1, 1);
this.picNametable1.Margin = new System.Windows.Forms.Padding(1);
this.picNametable1.Name = "picNametable1";
this.picNametable1.Size = new System.Drawing.Size(258, 242);
this.picNametable1.TabIndex = 0;
this.picNametable1.TabStop = false;
this.picNametable1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove);
//
// picTile
//
this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picTile.Location = new System.Drawing.Point(99, 133);
this.picTile.Name = "picTile";
this.picTile.Size = new System.Drawing.Size(63, 66);
this.picTile.TabIndex = 12;
this.picTile.TabStop = false;
//
// ctrlNametableViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "ctrlNametableViewer";
this.Size = new System.Drawing.Size(697, 488);
this.tableLayoutPanel1.ResumeLayout(false);
this.grpTileInfo.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picNametable4)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picNametable1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.PictureBox picNametable4;
private System.Windows.Forms.PictureBox picNametable3;
private System.Windows.Forms.PictureBox picNametable2;
private System.Windows.Forms.PictureBox picNametable1;
private System.Windows.Forms.GroupBox grpTileInfo;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TextBox txtPaletteAddress;
private System.Windows.Forms.TextBox txtAttributeAddress;
private System.Windows.Forms.TextBox txtAttributeData;
private System.Windows.Forms.TextBox txtTileAddress;
private System.Windows.Forms.Label lblTileIndex;
private System.Windows.Forms.Label lblTileAddress;
private System.Windows.Forms.Label lblAttributeData;
private System.Windows.Forms.Label lblAttributeAddress;
private System.Windows.Forms.Label lblPaletteAddress;
private System.Windows.Forms.Label lblTile;
private System.Windows.Forms.TextBox txtTileIndex;
private System.Windows.Forms.PictureBox picTile;
}
}

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlNametableViewer : UserControl
{
private List<byte[]> _tileData = new List<byte[]>() { null, null, null, null };
private List<byte[]> _attributeData = new List<byte[]>() { null, null, null, null };
public ctrlNametableViewer()
{
InitializeComponent();
}
public void RefreshViewer()
{
PictureBox[] nametables = new PictureBox[] { this.picNametable1, this.picNametable2, this.picNametable3, this.picNametable4 };
for(int i = 0; i < 4; i++) {
byte[] nametablePixelData, tileData, attributeData;
InteropEmu.DebugGetNametable(i, out nametablePixelData, out tileData, out attributeData);
_tileData[i] = tileData;
_attributeData[i] = attributeData;
GCHandle handle = GCHandle.Alloc(nametablePixelData, GCHandleType.Pinned);
try {
Bitmap source = new Bitmap(256, 240, 4*256, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
Bitmap target = new Bitmap(256, 240);
using(Graphics g = Graphics.FromImage(target)) {
g.DrawImage(source, new Rectangle(0, 0, 256, 240), new Rectangle(0, 0, 256, 240), GraphicsUnit.Pixel);
}
nametables[i].Image = target;
} finally {
handle.Free();
}
}
}
private void picNametable_MouseMove(object sender, MouseEventArgs e)
{
List<PictureBox> nametables = new List<PictureBox>() { this.picNametable1, this.picNametable2, this.picNametable3, this.picNametable4 };
int nametableIndex = nametables.IndexOf((PictureBox)sender);
int baseAddress = 0x2000 + nametableIndex * 0x400;
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
int bgAddr = state.PPU.ControlFlags.BackgroundPatternAddr;
int tileX = Math.Min(e.X / 8, 31);
int tileY = Math.Min(e.Y / 8, 29);
int shift = (tileX & 0x02) | ((tileY & 0x02) << 1);
int tileIndex = _tileData[nametableIndex][tileY*32+tileX];
int attributeData = _attributeData[nametableIndex][tileY*32+tileX];
int attributeAddr = baseAddress + 960 + ((tileY & 0xFC) << 1) + (tileX >> 2);
int paletteBaseAddr = ((attributeData >> shift) & 0x03) << 2;
this.txtTileIndex.Text = tileIndex.ToString("X2");
this.txtTileAddress.Text = (bgAddr + tileIndex * 16).ToString("X4");
this.txtAttributeData.Text = attributeData.ToString("X2");
this.txtAttributeAddress.Text = attributeAddr.ToString("X4");
this.txtPaletteAddress.Text = (0x3F00 + paletteBaseAddr).ToString("X4");
Bitmap tile = new Bitmap(64, 64);
using(Graphics g = Graphics.FromImage(tile)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*8, tileY*8, 8, 8), GraphicsUnit.Pixel);
}
this.picTile.Image = tile;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,198 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlPaletteViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.grpColorInfo = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.txtPaletteAddress = new System.Windows.Forms.TextBox();
this.lblColor = new System.Windows.Forms.Label();
this.lblPaletteAddress = new System.Windows.Forms.Label();
this.lblColorTile = new System.Windows.Forms.Label();
this.txtColor = new System.Windows.Forms.TextBox();
this.picColor = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.picPalette = new System.Windows.Forms.PictureBox();
this.grpColorInfo.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picColor)).BeginInit();
this.tableLayoutPanel3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picPalette)).BeginInit();
this.SuspendLayout();
//
// grpColorInfo
//
this.grpColorInfo.Controls.Add(this.tableLayoutPanel4);
this.grpColorInfo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpColorInfo.Location = new System.Drawing.Point(135, 3);
this.grpColorInfo.Name = "grpColorInfo";
this.grpColorInfo.Size = new System.Drawing.Size(544, 254);
this.grpColorInfo.TabIndex = 4;
this.grpColorInfo.TabStop = false;
this.grpColorInfo.Text = "Color Info";
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.txtPaletteAddress, 1, 1);
this.tableLayoutPanel4.Controls.Add(this.lblColor, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.lblPaletteAddress, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.lblColorTile, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.txtColor, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.picColor, 1, 2);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 4;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(538, 235);
this.tableLayoutPanel4.TabIndex = 0;
//
// txtPaletteAddress
//
this.txtPaletteAddress.Location = new System.Drawing.Point(93, 29);
this.txtPaletteAddress.Name = "txtPaletteAddress";
this.txtPaletteAddress.ReadOnly = true;
this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20);
this.txtPaletteAddress.TabIndex = 8;
//
// lblColor
//
this.lblColor.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblColor.AutoSize = true;
this.lblColor.Location = new System.Drawing.Point(3, 6);
this.lblColor.Name = "lblColor";
this.lblColor.Size = new System.Drawing.Size(34, 13);
this.lblColor.TabIndex = 0;
this.lblColor.Text = "Color:";
//
// lblPaletteAddress
//
this.lblPaletteAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPaletteAddress.AutoSize = true;
this.lblPaletteAddress.Location = new System.Drawing.Point(3, 32);
this.lblPaletteAddress.Name = "lblPaletteAddress";
this.lblPaletteAddress.Size = new System.Drawing.Size(84, 13);
this.lblPaletteAddress.TabIndex = 1;
this.lblPaletteAddress.Text = "Palette Address:";
//
// lblColorTile
//
this.lblColorTile.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblColorTile.AutoSize = true;
this.lblColorTile.Location = new System.Drawing.Point(3, 81);
this.lblColorTile.Name = "lblColorTile";
this.lblColorTile.Size = new System.Drawing.Size(48, 13);
this.lblColorTile.TabIndex = 6;
this.lblColorTile.Text = "Preview:";
//
// txtColor
//
this.txtColor.Location = new System.Drawing.Point(93, 3);
this.txtColor.Name = "txtColor";
this.txtColor.ReadOnly = true;
this.txtColor.Size = new System.Drawing.Size(26, 20);
this.txtColor.TabIndex = 7;
//
// picColor
//
this.picColor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picColor.Location = new System.Drawing.Point(93, 55);
this.picColor.Name = "picColor";
this.picColor.Size = new System.Drawing.Size(66, 66);
this.picColor.TabIndex = 12;
this.picColor.TabStop = false;
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 3;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Controls.Add(this.grpColorInfo, 2, 1);
this.tableLayoutPanel3.Controls.Add(this.picPalette, 0, 1);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 2;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(682, 260);
this.tableLayoutPanel3.TabIndex = 3;
//
// picPalette
//
this.picPalette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picPalette.Location = new System.Drawing.Point(1, 1);
this.picPalette.Margin = new System.Windows.Forms.Padding(1);
this.picPalette.Name = "picPalette";
this.picPalette.Size = new System.Drawing.Size(130, 258);
this.picPalette.TabIndex = 0;
this.picPalette.TabStop = false;
this.picPalette.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picPalette_MouseMove);
//
// ctrlPaletteViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel3);
this.Name = "ctrlPaletteViewer";
this.Size = new System.Drawing.Size(682, 260);
this.grpColorInfo.ResumeLayout(false);
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picColor)).EndInit();
this.tableLayoutPanel3.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picPalette)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox picPalette;
private System.Windows.Forms.GroupBox grpColorInfo;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.TextBox txtPaletteAddress;
private System.Windows.Forms.Label lblColor;
private System.Windows.Forms.Label lblPaletteAddress;
private System.Windows.Forms.Label lblColorTile;
private System.Windows.Forms.TextBox txtColor;
private System.Windows.Forms.PictureBox picColor;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlPaletteViewer : UserControl
{
private byte[] _paletteRam;
public ctrlPaletteViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public void RefreshViewer()
{
this._paletteRam = InteropEmu.DebugGetMemoryState(DebugMemoryType.PaletteMemory);
byte[] pixelData = InteropEmu.DebugGetPalette();
GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
try {
Bitmap source = new Bitmap(4, 8, 4*4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
Bitmap target = new Bitmap(128, 256);
using(Graphics g = Graphics.FromImage(target)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(source, new Rectangle(0, 0, 128, 256), new Rectangle(0, 0, 4, 8), GraphicsUnit.Pixel);
}
this.picPalette.Image = target;
} finally {
handle.Free();
}
}
private void picPalette_MouseMove(object sender, MouseEventArgs e)
{
int tileX = Math.Min(e.X / 32, 31);
int tileY = Math.Min(e.Y / 32, 31);
int tileIndex = tileY * 4 + tileX;
this.txtColor.Text = _paletteRam[tileIndex].ToString("X2");
this.txtPaletteAddress.Text = (0x3F00 + tileIndex).ToString("X4");
Bitmap tile = new Bitmap(64, 64);
using(Graphics g = Graphics.FromImage(tile)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(picPalette.Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*32, tileY*32, 32, 32), GraphicsUnit.Pixel);
}
this.picColor.Image = tile;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,273 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlSpriteViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.grpSpriteInfo = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.txtPosition = new System.Windows.Forms.TextBox();
this.txtPaletteAddress = new System.Windows.Forms.TextBox();
this.txtTileAddress = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.lblTile = new System.Windows.Forms.Label();
this.txtTileIndex = new System.Windows.Forms.TextBox();
this.chkVerticalMirroring = new System.Windows.Forms.CheckBox();
this.chkHorizontalMirroring = new System.Windows.Forms.CheckBox();
this.lblPaletteAddr = new System.Windows.Forms.Label();
this.lblPosition = new System.Windows.Forms.Label();
this.picTile = new System.Windows.Forms.PictureBox();
this.picSprites = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel3.SuspendLayout();
this.grpSpriteInfo.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picSprites)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 2;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Controls.Add(this.grpSpriteInfo, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.picSprites, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 1;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.Size = new System.Drawing.Size(682, 516);
this.tableLayoutPanel3.TabIndex = 3;
//
// grpSpriteInfo
//
this.grpSpriteInfo.Controls.Add(this.tableLayoutPanel4);
this.grpSpriteInfo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpSpriteInfo.Location = new System.Drawing.Point(263, 3);
this.grpSpriteInfo.Name = "grpSpriteInfo";
this.grpSpriteInfo.Size = new System.Drawing.Size(416, 510);
this.grpSpriteInfo.TabIndex = 4;
this.grpSpriteInfo.TabStop = false;
this.grpSpriteInfo.Text = "Sprite Info";
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.txtPosition, 1, 3);
this.tableLayoutPanel4.Controls.Add(this.txtPaletteAddress, 1, 2);
this.tableLayoutPanel4.Controls.Add(this.txtTileAddress, 1, 1);
this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.label2, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.lblTile, 0, 6);
this.tableLayoutPanel4.Controls.Add(this.txtTileIndex, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.picTile, 1, 6);
this.tableLayoutPanel4.Controls.Add(this.chkVerticalMirroring, 0, 5);
this.tableLayoutPanel4.Controls.Add(this.chkHorizontalMirroring, 0, 4);
this.tableLayoutPanel4.Controls.Add(this.lblPaletteAddr, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.lblPosition, 0, 3);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 8;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(410, 491);
this.tableLayoutPanel4.TabIndex = 0;
//
// txtPosition
//
this.txtPosition.Location = new System.Drawing.Point(93, 81);
this.txtPosition.Name = "txtPosition";
this.txtPosition.ReadOnly = true;
this.txtPosition.Size = new System.Drawing.Size(42, 20);
this.txtPosition.TabIndex = 18;
//
// txtPaletteAddress
//
this.txtPaletteAddress.Location = new System.Drawing.Point(93, 55);
this.txtPaletteAddress.Name = "txtPaletteAddress";
this.txtPaletteAddress.ReadOnly = true;
this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20);
this.txtPaletteAddress.TabIndex = 17;
//
// txtTileAddress
//
this.txtTileAddress.Location = new System.Drawing.Point(93, 29);
this.txtTileAddress.Name = "txtTileAddress";
this.txtTileAddress.ReadOnly = true;
this.txtTileAddress.Size = new System.Drawing.Size(42, 20);
this.txtTileAddress.TabIndex = 8;
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 6);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(56, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Tile Index:";
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 32);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(68, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Tile Address:";
//
// lblTile
//
this.lblTile.AutoSize = true;
this.lblTile.Location = new System.Drawing.Point(3, 155);
this.lblTile.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.lblTile.Name = "lblTile";
this.lblTile.Size = new System.Drawing.Size(27, 13);
this.lblTile.TabIndex = 6;
this.lblTile.Text = "Tile:";
//
// txtTileIndex
//
this.txtTileIndex.Location = new System.Drawing.Point(93, 3);
this.txtTileIndex.Name = "txtTileIndex";
this.txtTileIndex.ReadOnly = true;
this.txtTileIndex.Size = new System.Drawing.Size(26, 20);
this.txtTileIndex.TabIndex = 7;
//
// chkVerticalMirroring
//
this.chkVerticalMirroring.AutoSize = true;
this.tableLayoutPanel4.SetColumnSpan(this.chkVerticalMirroring, 2);
this.chkVerticalMirroring.Location = new System.Drawing.Point(3, 130);
this.chkVerticalMirroring.Name = "chkVerticalMirroring";
this.chkVerticalMirroring.Size = new System.Drawing.Size(77, 17);
this.chkVerticalMirroring.TabIndex = 14;
this.chkVerticalMirroring.Text = "Vertical flip";
this.chkVerticalMirroring.UseVisualStyleBackColor = true;
//
// chkHorizontalMirroring
//
this.chkHorizontalMirroring.AutoSize = true;
this.tableLayoutPanel4.SetColumnSpan(this.chkHorizontalMirroring, 2);
this.chkHorizontalMirroring.Location = new System.Drawing.Point(3, 107);
this.chkHorizontalMirroring.Name = "chkHorizontalMirroring";
this.chkHorizontalMirroring.Size = new System.Drawing.Size(89, 17);
this.chkHorizontalMirroring.TabIndex = 13;
this.chkHorizontalMirroring.Text = "Horizontal flip";
this.chkHorizontalMirroring.UseVisualStyleBackColor = true;
//
// lblPaletteAddr
//
this.lblPaletteAddr.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPaletteAddr.AutoSize = true;
this.lblPaletteAddr.Location = new System.Drawing.Point(3, 58);
this.lblPaletteAddr.Name = "lblPaletteAddr";
this.lblPaletteAddr.Size = new System.Drawing.Size(84, 13);
this.lblPaletteAddr.TabIndex = 15;
this.lblPaletteAddr.Text = "Palette Address:";
//
// lblPosition
//
this.lblPosition.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPosition.AutoSize = true;
this.lblPosition.Location = new System.Drawing.Point(3, 84);
this.lblPosition.Name = "lblPosition";
this.lblPosition.Size = new System.Drawing.Size(70, 13);
this.lblPosition.TabIndex = 16;
this.lblPosition.Text = "Position (X,Y)";
//
// picTile
//
this.picTile.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picTile.Location = new System.Drawing.Point(93, 153);
this.picTile.Name = "picTile";
this.picTile.Size = new System.Drawing.Size(66, 130);
this.picTile.TabIndex = 12;
this.picTile.TabStop = false;
//
// picSprites
//
this.picSprites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picSprites.Location = new System.Drawing.Point(1, 1);
this.picSprites.Margin = new System.Windows.Forms.Padding(1);
this.picSprites.Name = "picSprites";
this.picSprites.Size = new System.Drawing.Size(258, 514);
this.picSprites.TabIndex = 0;
this.picSprites.TabStop = false;
this.picSprites.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picSprites_MouseMove);
//
// ctrlSpriteViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel3);
this.Name = "ctrlSpriteViewer";
this.Size = new System.Drawing.Size(682, 516);
this.tableLayoutPanel3.ResumeLayout(false);
this.grpSpriteInfo.ResumeLayout(false);
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picSprites)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.PictureBox picSprites;
private System.Windows.Forms.GroupBox grpSpriteInfo;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.TextBox txtTileAddress;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label lblTile;
private System.Windows.Forms.TextBox txtTileIndex;
private System.Windows.Forms.PictureBox picTile;
private System.Windows.Forms.TextBox txtPosition;
private System.Windows.Forms.TextBox txtPaletteAddress;
private System.Windows.Forms.CheckBox chkVerticalMirroring;
private System.Windows.Forms.CheckBox chkHorizontalMirroring;
private System.Windows.Forms.Label lblPaletteAddr;
private System.Windows.Forms.Label lblPosition;
}
}

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlSpriteViewer : UserControl
{
private byte[] _spriteRam;
public ctrlSpriteViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public void RefreshViewer()
{
_spriteRam = InteropEmu.DebugGetMemoryState(DebugMemoryType.SpriteMemory);
byte[] pixelData = InteropEmu.DebugGetSprites();
GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
try {
Bitmap source = new Bitmap(64, 128, 4*64, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
Bitmap target = new Bitmap(256, 512);
using(Graphics g = Graphics.FromImage(target)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(source, new Rectangle(0, 0, 256, 512), new Rectangle(0, 0, 64, 128), GraphicsUnit.Pixel);
}
picSprites.Image = target;
} finally {
handle.Free();
}
}
private void picSprites_MouseMove(object sender, MouseEventArgs e)
{
int tileX = Math.Min(e.X / 32, 31);
int tileY = Math.Min(e.Y / 64, 63);
int ramAddr = ((tileY << 3) + tileX) << 2;
int spriteY = _spriteRam[ramAddr];
int tileIndex = _spriteRam[ramAddr + 1];
int attributes = _spriteRam[ramAddr + 2];
int spriteX = _spriteRam[ramAddr + 3];
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
int tileAddr;
if(state.PPU.ControlFlags.LargeSprites != 0) {
tileAddr = ((tileIndex & 0x01) == 0x01 ? 0x1000 : 0x0000) + ((tileIndex & 0xFE) << 4);
} else {
tileAddr = state.PPU.ControlFlags.SpritePatternAddr + (tileIndex << 4);
}
int paletteAddr = 0x3F10 + ((attributes & 0x03) << 2);
bool verticalMirror = (attributes & 0x80) == 0x80;
bool horizontalMirror = (attributes & 0x40) == 0x40;
this.txtTileIndex.Text = tileIndex.ToString("X2");
this.txtTileAddress.Text = tileAddr.ToString("X4");
this.txtPosition.Text = spriteX.ToString() + ", " + spriteY.ToString();
this.txtPaletteAddress.Text = paletteAddr.ToString("X4");
this.chkVerticalMirroring.Checked = verticalMirror;
this.chkHorizontalMirroring.Checked = horizontalMirror;
Bitmap tile = new Bitmap(64, 128);
using(Graphics g = Graphics.FromImage(tile)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 128), new Rectangle(tileX*32, tileY*64, 32, 64), GraphicsUnit.Pixel);
}
this.picTile.Image = tile;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -34,12 +34,17 @@
this.components = new System.ComponentModel.Container();
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.tlpTop = new System.Windows.Forms.TableLayoutPanel();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.contextMenuCode = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.tableLayoutPanel10 = new System.Windows.Forms.TableLayoutPanel();
this.grpBreakpoints = new System.Windows.Forms.GroupBox();
this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints();
this.grpWatch = new System.Windows.Forms.GroupBox();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuClose = new System.Windows.Forms.ToolStripMenuItem();
@ -65,15 +70,8 @@
this.mnuFindPrev = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGoTo = new System.Windows.Forms.ToolStripMenuItem();
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.nametableViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.cHRViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
@ -124,6 +122,18 @@
this.tlpTop.Size = new System.Drawing.Size(984, 422);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 416);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// contextMenuCode
//
this.contextMenuCode.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -148,6 +158,27 @@
this.mnuSetNextStatement.Size = new System.Drawing.Size(258, 22);
this.mnuSetNextStatement.Text = "Set Next Statement";
//
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362);
this.ctrlConsoleStatus.TabIndex = 3;
//
// ctrlDebuggerCodeSplit
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 416);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
//
// tableLayoutPanel10
//
this.tableLayoutPanel10.ColumnCount = 2;
@ -178,6 +209,15 @@
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
//
// ctrlBreakpoints
//
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(480, 137);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged);
//
// grpWatch
//
this.grpWatch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -191,6 +231,14 @@
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
//
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(480, 137);
this.ctrlWatch.TabIndex = 0;
//
// menuStrip
//
this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -216,7 +264,7 @@
// mnuClose
//
this.mnuClose.Name = "mnuClose";
this.mnuClose.Size = new System.Drawing.Size(152, 22);
this.mnuClose.Size = new System.Drawing.Size(103, 22);
this.mnuClose.Text = "Close";
this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click);
//
@ -404,88 +452,26 @@
// toolsToolStripMenuItem
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.nametableViewerToolStripMenuItem,
this.cHRViewerToolStripMenuItem,
this.toolStripMenuItem3,
this.mnuPpuViewer,
this.mnuMemoryViewer});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
this.toolsToolStripMenuItem.Text = "Tools";
//
// nametableViewerToolStripMenuItem
// mnuPpuViewer
//
this.nametableViewerToolStripMenuItem.Name = "nametableViewerToolStripMenuItem";
this.nametableViewerToolStripMenuItem.Size = new System.Drawing.Size(170, 22);
this.nametableViewerToolStripMenuItem.Text = "Nametable Viewer";
//
// cHRViewerToolStripMenuItem
//
this.cHRViewerToolStripMenuItem.Name = "cHRViewerToolStripMenuItem";
this.cHRViewerToolStripMenuItem.Size = new System.Drawing.Size(170, 22);
this.cHRViewerToolStripMenuItem.Text = "CHR Viewer";
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(167, 6);
this.mnuPpuViewer.Name = "mnuPpuViewer";
this.mnuPpuViewer.Size = new System.Drawing.Size(157, 22);
this.mnuPpuViewer.Text = "PPU Viewer";
this.mnuPpuViewer.Click += new System.EventHandler(this.mnuNametableViewer_Click);
//
// mnuMemoryViewer
//
this.mnuMemoryViewer.Name = "mnuMemoryViewer";
this.mnuMemoryViewer.Size = new System.Drawing.Size(170, 22);
this.mnuMemoryViewer.Size = new System.Drawing.Size(157, 22);
this.mnuMemoryViewer.Text = "Memory Viewer";
this.mnuMemoryViewer.Click += new System.EventHandler(this.mnuMemoryViewer_Click);
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 416);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362);
this.ctrlConsoleStatus.TabIndex = 3;
//
// ctrlDebuggerCodeSplit
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 416);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
//
// ctrlBreakpoints
//
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(480, 137);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged);
//
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(480, 137);
this.ctrlWatch.TabIndex = 0;
//
// frmDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -548,9 +534,7 @@
private System.Windows.Forms.ToolStripMenuItem mnuView;
private System.Windows.Forms.ToolStripMenuItem mnuSplitView;
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem nametableViewerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem cHRViewerToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
private System.Windows.Forms.ToolStripMenuItem mnuPpuViewer;
private System.Windows.Forms.ToolStripMenuItem mnuMemoryViewer;
private Controls.ctrlBreakpoints ctrlBreakpoints;
private System.Windows.Forms.ToolStripMenuItem mnuGoTo;

View File

@ -14,7 +14,7 @@ namespace Mesen.GUI.Debugger
{
public partial class frmDebugger : Form
{
private List<frmMemoryViewer> _memoryViewers = new List<frmMemoryViewer>();
private List<Form> _childForms = new List<Form>();
private InteropEmu.NotificationListener _notifListener;
private ctrlDebuggerCode _lastCodeWindow;
@ -42,10 +42,13 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugStep(100000);
}
void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
{
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {
this.BeginInvoke((MethodInvoker)(() => UpdateDebugger()));
} else if(e.NotificationType == InteropEmu.ConsoleNotificationType.GameLoaded) {
InteropEmu.DebugRelease();
InteropEmu.DebugInitialize();
}
}
@ -107,6 +110,15 @@ namespace Mesen.GUI.Debugger
ctrlDebuggerCode.HighlightBreakpoints(ctrlBreakpoints.GetBreakpoints());
}
private void OpenChildForm(Form frm)
{
this._childForms.Add(frm);
frm.FormClosed += (obj, args) => {
this._childForms.Remove((Form)obj);
};
frm.Show();
}
private void mnuContinue_Click(object sender, EventArgs e)
{
ClearActiveStatement();
@ -175,12 +187,7 @@ namespace Mesen.GUI.Debugger
private void mnuMemoryViewer_Click(object sender, EventArgs e)
{
frmMemoryViewer frm = new frmMemoryViewer();
this._memoryViewers.Add(frm);
frm.FormClosed += (obj, args) => {
this._memoryViewers.Remove((frmMemoryViewer)obj);
};
frm.Show();
OpenChildForm(new frmMemoryViewer());
}
private void ctrlBreakpoints_BreakpointChanged(object sender, EventArgs e)
@ -225,10 +232,15 @@ namespace Mesen.GUI.Debugger
protected override void OnFormClosed(FormClosedEventArgs e)
{
foreach(frmMemoryViewer frm in this._memoryViewers.ToArray()) {
foreach(Form frm in this._childForms.ToArray()) {
frm.Close();
}
base.OnFormClosed(e);
}
private void mnuNametableViewer_Click(object sender, EventArgs e)
{
OpenChildForm(new frmPpuViewer());
}
}
}

245
GUI.NET/Debugger/frmPpuViewer.Designer.cs generated Normal file
View File

@ -0,0 +1,245 @@
namespace Mesen.GUI.Debugger
{
partial class frmPpuViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
if(this._notifListener != null) {
this._notifListener.Dispose();
this._notifListener = null;
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuClose = new System.Windows.Forms.ToolStripMenuItem();
this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.tabMain = new System.Windows.Forms.TabControl();
this.tpgNametableViewer = new System.Windows.Forms.TabPage();
this.ctrlNametableViewer = new Mesen.GUI.Debugger.Controls.ctrlNametableViewer();
this.tpgChrViewer = new System.Windows.Forms.TabPage();
this.ctrlChrViewer = new Mesen.GUI.Debugger.Controls.ctrlChrViewer();
this.tpgSpriteViewer = new System.Windows.Forms.TabPage();
this.ctrlSpriteViewer = new Mesen.GUI.Debugger.Controls.ctrlSpriteViewer();
this.tpgPaletteViewer = new System.Windows.Forms.TabPage();
this.ctrlPaletteViewer = new Mesen.GUI.Debugger.Controls.ctrlPaletteViewer();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.menuStrip1.SuspendLayout();
this.tabMain.SuspendLayout();
this.tpgNametableViewer.SuspendLayout();
this.tpgChrViewer.SuspendLayout();
this.tpgSpriteViewer.SuspendLayout();
this.tpgPaletteViewer.SuspendLayout();
this.SuspendLayout();
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.viewToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(709, 24);
this.menuStrip1.TabIndex = 2;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuClose});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "File";
//
// mnuClose
//
this.mnuClose.Name = "mnuClose";
this.mnuClose.Size = new System.Drawing.Size(103, 22);
this.mnuClose.Text = "Close";
this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click);
//
// viewToolStripMenuItem
//
this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuRefresh,
this.toolStripMenuItem1,
this.mnuAutoRefresh});
this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.viewToolStripMenuItem.Text = "View";
//
// mnuRefresh
//
this.mnuRefresh.Name = "mnuRefresh";
this.mnuRefresh.ShortcutKeys = System.Windows.Forms.Keys.F5;
this.mnuRefresh.Size = new System.Drawing.Size(152, 22);
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// mnuAutoRefresh
//
this.mnuAutoRefresh.Checked = true;
this.mnuAutoRefresh.CheckOnClick = true;
this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked;
this.mnuAutoRefresh.Name = "mnuAutoRefresh";
this.mnuAutoRefresh.Size = new System.Drawing.Size(152, 22);
this.mnuAutoRefresh.Text = "Auto-refresh";
//
// tabMain
//
this.tabMain.Controls.Add(this.tpgNametableViewer);
this.tabMain.Controls.Add(this.tpgChrViewer);
this.tabMain.Controls.Add(this.tpgSpriteViewer);
this.tabMain.Controls.Add(this.tpgPaletteViewer);
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabMain.Location = new System.Drawing.Point(0, 24);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
this.tabMain.Size = new System.Drawing.Size(709, 545);
this.tabMain.TabIndex = 3;
//
// tpgNametableViewer
//
this.tpgNametableViewer.Controls.Add(this.ctrlNametableViewer);
this.tpgNametableViewer.Location = new System.Drawing.Point(4, 22);
this.tpgNametableViewer.Name = "tpgNametableViewer";
this.tpgNametableViewer.Padding = new System.Windows.Forms.Padding(3);
this.tpgNametableViewer.Size = new System.Drawing.Size(701, 519);
this.tpgNametableViewer.TabIndex = 0;
this.tpgNametableViewer.Text = "Nametable Viewer";
this.tpgNametableViewer.UseVisualStyleBackColor = true;
//
// ctrlNametableViewer
//
this.ctrlNametableViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlNametableViewer.Location = new System.Drawing.Point(3, 3);
this.ctrlNametableViewer.Name = "ctrlNametableViewer";
this.ctrlNametableViewer.Size = new System.Drawing.Size(695, 513);
this.ctrlNametableViewer.TabIndex = 0;
//
// tpgChrViewer
//
this.tpgChrViewer.Controls.Add(this.ctrlChrViewer);
this.tpgChrViewer.Location = new System.Drawing.Point(4, 22);
this.tpgChrViewer.Name = "tpgChrViewer";
this.tpgChrViewer.Padding = new System.Windows.Forms.Padding(3);
this.tpgChrViewer.Size = new System.Drawing.Size(701, 519);
this.tpgChrViewer.TabIndex = 1;
this.tpgChrViewer.Text = "CHR Viewer";
this.tpgChrViewer.UseVisualStyleBackColor = true;
//
// ctrlChrViewer
//
this.ctrlChrViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlChrViewer.Location = new System.Drawing.Point(3, 3);
this.ctrlChrViewer.Name = "ctrlChrViewer";
this.ctrlChrViewer.Size = new System.Drawing.Size(695, 513);
this.ctrlChrViewer.TabIndex = 2;
//
// tpgSpriteViewer
//
this.tpgSpriteViewer.Controls.Add(this.ctrlSpriteViewer);
this.tpgSpriteViewer.Location = new System.Drawing.Point(4, 22);
this.tpgSpriteViewer.Name = "tpgSpriteViewer";
this.tpgSpriteViewer.Size = new System.Drawing.Size(701, 519);
this.tpgSpriteViewer.TabIndex = 2;
this.tpgSpriteViewer.Text = "Sprite Viewer";
this.tpgSpriteViewer.UseVisualStyleBackColor = true;
//
// ctrlSpriteViewer
//
this.ctrlSpriteViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlSpriteViewer.Location = new System.Drawing.Point(0, 0);
this.ctrlSpriteViewer.Name = "ctrlSpriteViewer";
this.ctrlSpriteViewer.Size = new System.Drawing.Size(701, 519);
this.ctrlSpriteViewer.TabIndex = 0;
//
// tpgPaletteViewer
//
this.tpgPaletteViewer.Controls.Add(this.ctrlPaletteViewer);
this.tpgPaletteViewer.Location = new System.Drawing.Point(4, 22);
this.tpgPaletteViewer.Name = "tpgPaletteViewer";
this.tpgPaletteViewer.Size = new System.Drawing.Size(701, 519);
this.tpgPaletteViewer.TabIndex = 3;
this.tpgPaletteViewer.Text = "Palette Viewer";
this.tpgPaletteViewer.UseVisualStyleBackColor = true;
//
// ctrlPaletteViewer
//
this.ctrlPaletteViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPaletteViewer.Location = new System.Drawing.Point(0, 0);
this.ctrlPaletteViewer.Name = "ctrlPaletteViewer";
this.ctrlPaletteViewer.Size = new System.Drawing.Size(701, 519);
this.ctrlPaletteViewer.TabIndex = 0;
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6);
//
// frmPpuViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(709, 569);
this.Controls.Add(this.tabMain);
this.Controls.Add(this.menuStrip1);
this.MainMenuStrip = this.menuStrip1;
this.MinimumSize = new System.Drawing.Size(725, 607);
this.Name = "frmPpuViewer";
this.Text = "PPU Viewer";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.tabMain.ResumeLayout(false);
this.tpgNametableViewer.ResumeLayout(false);
this.tpgChrViewer.ResumeLayout(false);
this.tpgSpriteViewer.ResumeLayout(false);
this.tpgPaletteViewer.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem mnuClose;
private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem mnuRefresh;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh;
private System.Windows.Forms.TabControl tabMain;
private System.Windows.Forms.TabPage tpgNametableViewer;
private System.Windows.Forms.TabPage tpgChrViewer;
private System.Windows.Forms.TabPage tpgSpriteViewer;
private Controls.ctrlNametableViewer ctrlNametableViewer;
private Controls.ctrlChrViewer ctrlChrViewer;
private Controls.ctrlSpriteViewer ctrlSpriteViewer;
private System.Windows.Forms.TabPage tpgPaletteViewer;
private Controls.ctrlPaletteViewer ctrlPaletteViewer;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmPpuViewer : BaseForm
{
private InteropEmu.NotificationListener _notifListener;
public frmPpuViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!this.DesignMode) {
this._notifListener = new InteropEmu.NotificationListener();
this._notifListener.OnNotification += this._notifListener_OnNotification;
this.ctrlNametableViewer.RefreshViewer();
this.ctrlChrViewer.RefreshViewer();
this.ctrlSpriteViewer.RefreshViewer();
this.ctrlPaletteViewer.RefreshViewer();
}
}
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
{
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {
this.BeginInvoke((MethodInvoker)(() => this.RefreshViewers()));
} else if(e.NotificationType == InteropEmu.ConsoleNotificationType.PpuFrameDone) {
this.BeginInvoke((MethodInvoker)(() => this.AutoRefresh()));
}
}
private void RefreshViewers()
{
if(this.tabMain.SelectedTab == this.tpgNametableViewer) {
this.ctrlNametableViewer.RefreshViewer();
} else if(this.tabMain.SelectedTab == this.tpgChrViewer) {
this.ctrlChrViewer.RefreshViewer();
} else if(this.tabMain.SelectedTab == this.tpgSpriteViewer) {
this.ctrlSpriteViewer.RefreshViewer();
} else if(this.tabMain.SelectedTab == this.tpgPaletteViewer) {
this.ctrlPaletteViewer.RefreshViewer();
}
}
private void AutoRefresh()
{
if(mnuAutoRefresh.Checked) {
this.RefreshViewers();
}
}
private void mnuRefresh_Click(object sender, EventArgs e)
{
this.RefreshViewers();
}
private void mnuClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -20,6 +20,9 @@
_notifListener.Dispose();
_notifListener = null;
}
if(_debugger != null) {
_debugger.Close();
}
StopEmu();
InteropEmu.Release();
base.Dispose(disposing);

View File

@ -109,6 +109,24 @@
<Compile Include="Debugger\Controls\ctrlBreakpoints.Designer.cs">
<DependentUpon>ctrlBreakpoints.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlPaletteViewer.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlPaletteViewer.Designer.cs">
<DependentUpon>ctrlPaletteViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlSpriteViewer.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlSpriteViewer.Designer.cs">
<DependentUpon>ctrlSpriteViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlChrViewer.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlChrViewer.Designer.cs">
<DependentUpon>ctrlChrViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlConsoleStatus.cs">
<SubType>UserControl</SubType>
</Compile>
@ -127,6 +145,12 @@
<Compile Include="Debugger\Controls\ctrlHexViewer.Designer.cs">
<DependentUpon>ctrlHexViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlNametableViewer.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlNametableViewer.Designer.cs">
<DependentUpon>ctrlNametableViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlScrollableTextbox.cs">
<SubType>UserControl</SubType>
</Compile>
@ -169,6 +193,12 @@
<Compile Include="Debugger\frmMemoryViewer.Designer.cs">
<DependentUpon>frmMemoryViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\frmPpuViewer.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\frmPpuViewer.Designer.cs">
<DependentUpon>frmPpuViewer.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BaseConfigForm.Designer.cs">
<DependentUpon>BaseConfigForm.cs</DependentUpon>
</Compile>
@ -259,6 +289,15 @@
<EmbeddedResource Include="Debugger\Controls\ctrlBreakpoints.resx">
<DependentUpon>ctrlBreakpoints.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlPaletteViewer.resx">
<DependentUpon>ctrlPaletteViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlSpriteViewer.resx">
<DependentUpon>ctrlSpriteViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlChrViewer.resx">
<DependentUpon>ctrlChrViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlConsoleStatus.resx">
<DependentUpon>ctrlConsoleStatus.cs</DependentUpon>
</EmbeddedResource>
@ -268,6 +307,9 @@
<EmbeddedResource Include="Debugger\Controls\ctrlHexViewer.resx">
<DependentUpon>ctrlHexViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlNametableViewer.resx">
<DependentUpon>ctrlNametableViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlScrollableTextbox.resx">
<DependentUpon>ctrlScrollableTextbox.cs</DependentUpon>
</EmbeddedResource>
@ -286,6 +328,9 @@
<EmbeddedResource Include="Debugger\frmMemoryViewer.resx">
<DependentUpon>frmMemoryViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\frmPpuViewer.resx">
<DependentUpon>frmPpuViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BaseConfigForm.resx">
<DependentUpon>BaseConfigForm.cs</DependentUpon>
</EmbeddedResource>

View File

@ -83,6 +83,10 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern UInt32 DebugGetRelativeAddress(UInt32 addr);
[DllImport(DLLPath, EntryPoint="DebugGetMemoryState")] private static extern UInt32 DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer);
[DllImport(DLLPath, EntryPoint="DebugGetNametable")] private static extern void DebugGetNametableWrapper(UInt32 nametableIndex, IntPtr frameBuffer, IntPtr tileData, IntPtr attributeData);
[DllImport(DLLPath, EntryPoint="DebugGetChrBank")] private static extern void DebugGetChrBankWrapper(UInt32 bankIndex, IntPtr frameBuffer, Byte palette);
[DllImport(DLLPath, EntryPoint="DebugGetSprites")] private static extern void DebugGetSpritesWrapper(IntPtr frameBuffer);
[DllImport(DLLPath, EntryPoint="DebugGetPalette")] private static extern void DebugGetPaletteWrapper(IntPtr frameBuffer);
public static byte[] DebugGetMemoryState(DebugMemoryType type)
{
@ -97,6 +101,66 @@ namespace Mesen.GUI
return buffer;
}
public static void DebugGetNametable(int nametableIndex, out byte[] frameData, out byte[] tileData, out byte[] attributeData)
{
frameData = new byte[256*240*4];
tileData = new byte[32*30];
attributeData = new byte[32*30];
GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
GCHandle hTileData = GCHandle.Alloc(tileData, GCHandleType.Pinned);
GCHandle hAttributeData = GCHandle.Alloc(attributeData, GCHandleType.Pinned);
try {
InteropEmu.DebugGetNametableWrapper((UInt32)nametableIndex, hFrameData.AddrOfPinnedObject(), hTileData.AddrOfPinnedObject(), hAttributeData.AddrOfPinnedObject());
} finally {
hFrameData.Free();
hTileData.Free();
hAttributeData.Free();
}
}
public static byte[] DebugGetChrBank(int bankIndex, int palette)
{
byte[] frameData = new byte[128*128*4];
GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
try {
InteropEmu.DebugGetChrBankWrapper((UInt32)bankIndex, hFrameData.AddrOfPinnedObject(), (Byte)palette);
} finally {
hFrameData.Free();
}
return frameData;
}
public static byte[] DebugGetSprites()
{
byte[] frameData = new byte[64*128*4];
GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
try {
InteropEmu.DebugGetSpritesWrapper(hFrameData.AddrOfPinnedObject());
} finally {
hFrameData.Free();
}
return frameData;
}
public static byte[] DebugGetPalette()
{
byte[] frameData = new byte[4*8*4];
GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
try {
InteropEmu.DebugGetPaletteWrapper(hFrameData.AddrOfPinnedObject());
} finally {
hFrameData.Free();
}
return frameData;
}
public static string GetROMPath() { return PtrToStringUtf8(InteropEmu.GetROMPathWrapper()); }
public static string GetKeyName(UInt32 key) { return PtrToStringUtf8(InteropEmu.GetKeyNameWrapper(key)); }
@ -129,6 +193,9 @@ namespace Mesen.GUI
GameResumed = 4,
GameStopped = 5,
CodeBreak = 6,
CheatAdded = 7,
CheatRemoved = 8,
PpuFrameDone = 9,
}
public struct KeyMapping

View File

@ -34,6 +34,10 @@ extern "C"
DllExport const char* __stdcall DebugGetCode() { return _debugger->GetCode()->c_str(); }
DllExport uint32_t __stdcall DebugGetMemoryState(uint32_t type, uint8_t *buffer) { return _debugger->GetMemoryState((DebugMemoryType)type, buffer); }
DllExport void __stdcall DebugGetNametable(uint32_t nametableIndex, uint32_t *frameBuffer, uint8_t *tileData, uint8_t *attributeData) { _debugger->GetNametable(nametableIndex, frameBuffer, tileData, attributeData); }
DllExport void __stdcall DebugGetChrBank(uint32_t bankIndex, uint32_t *frameBuffer, uint8_t palette) { _debugger->GetChrBank(bankIndex, frameBuffer, palette); }
DllExport void __stdcall DebugGetSprites(uint32_t *frameBuffer) { _debugger->GetSprites(frameBuffer); }
DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { _debugger->GetPalette(frameBuffer); }
DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return _debugger->GetMemoryValue(addr); }
DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return _debugger->GetRelativeAddress(addr); }